pms包管理服务分析-PackageManagerService构造函数和包扫描过程

上一章pms初步理解中提到SystemServer启动pms只创建了一个pms实例,那么重点在pms的实例化过程究竟做了什么事情,下面来研究下pms的构造方法。

PackageManagerService构造方法 ①:

[/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]

public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START, SystemClock.uptimeMillis());
        mContext = context;
        mFactoryTest = factoryTest;
        mOnlyCore = onlyCore;
        mLazyDexOpt = "eng".equals(SystemProperties.get("ro.build.type")); 
        mMetrics = new DisplayMetrics();
        mSettings = new Settings(mPackages);
        mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);

构造方法内部首先获得一个系统级上下文mContext,并在实例化mSettings后,添加system, radio, log, nfc, bluetooth, shell  6SharedUserSettingsmSettings

  Settings

Settings这个类包含所有安装后的apk信息,里面保存了一个mPackages映射表,根据apk包名映射对应的apk包信息,比如permissions权限信息 ,name, codePath, mSharedLibraries, restrictions, userid, version等等,这些信息将保存到一个名为 packagesXML文件中,pms服务启动时,如果packages.xml文件存在,那么会先读里面的内容初始化Settings实例,随后packages.xml文件里面的内容会随着apk安装信息的更新而更新。

Settings类结构如图(2)所示


                                                                                                                                             (图2


Settings的构造方法

Settings类的构造方法如下,主要创建data/system目录下的多个配置文件,例如packages.xml

[/frameworks/base/services/core/java/com/android/server/pm/Settings.java]

Settings(Context context) {
       this(context, Environment.getDataDirectory());
  }

    Settings(Context context, File dataDir) {
        mSystemDir = new File(dataDir, "system"); 
        mSystemDir.mkdirs();
        FileUtils.setPermissions(mSystemDir.toString(),
                FileUtils.S_IRWXU|FileUtils.S_IRWXG
                |FileUtils.S_IROTH|FileUtils.S_IXOTH,
                -1, -1);
        mSettingsFilename = new File(mSystemDir, "packages.xml"); 
        mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml"); 
        mPackageListFilename = new File(mSystemDir, "packages.list"); 
        FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);

        // Deprecated: Needed for migration
        mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml"); 
        mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml"); 
  }
	

//创建data/system目录

//创建data/system/packages.xml文件

//创建data/system/pacakges-backup.xml文件

//创建data/system/packages.list文件

//创建data/system/packages-stopped.xml文件

//创建data/system/packages-stopped-backup.xml文件


创建并添加SharedUserSetting

 Settings实例化后,调用SettingsaddSharedUserLPw方法添加6个系统的sharedUser,保存在SettingsmSharedUsers数组中。下图是SharedUserSettings的类结构,其中SettingBaseSharedUserSetting的基类,基类中包含pkgFlags/pkgPrivateFlags/PermissionsState,另外SettingBase也是PackageSetting的基类。


实例化SystemConfig并获得gids, systempermissions, features

PackageManagerService的构造方法体 ②:

[/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]

 mInstaller = installer; 
 getDefaultDisplayMetrics(context, mMetrics); 
 SystemConfig systemConfig = SystemConfig.getInstance();
 mGlobalGids = systemConfig.getGlobalGids();
 mSystemPermissions = systemConfig.getSystemPermissions();
 mAvailableFeatures = systemConfig.getAvailableFeatures();

通过实例化SystemConfig获得mGlobalGids, mSystemPermissions, mAvailableFeatures 

[/frameworks/base/services/core/java/com/android/server/SystemConfig.java]

 int[] mGlobalGids; 
 final SparseArray<ArraySet<String>> mSystemPermissions = new SparseArray<>();
 final ArrayMap<String, String> mSharedLibraries  = new ArrayMap<>();
 final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>();
 final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>();
 final ArraySet<String> mAllowInPowerSave = new ArraySet<>();
 final ArraySet<String> mFixedImeApps = new ArraySet<>();
 SystemConfig() {
      readPermissions(Environment.buildPath(Environment.getRootDirectory(), "etc", "sysconfig"), false);
      readPermissions(Environment.buildPath(Environment.getRootDirectory(), "etc", "permissions"), false);
      readPermissions(Environment.buildPath(Environment.getOemDirectory(), "etc", "sysconfig"), true);
      readPermissions(Environment.buildPath(Environment.getOemDirectory(), "etc", "permissions"), true);
 }

SystemConfig解析system/etc/sysconfigpermissions目录下面的所有xml,得到下面的信息:

(1) mGlobalGids,建立底层user idsgroup ids同上层permissions之间的映射;可以指定一个权限和几个组id的对应。当一个APK被授予这个权限时,它也同时属于这几个组;

(2) mSystemPermissions,给一些底层用户分配权限,如给 shell 授予各种 permission 权限;把一个权限赋予一个UID,当进程使用这个 UID 运行时,就具备了这个权限;

(3) mSharedLibraries,系统增加的一些应用需要 link 的扩展 jar ;

(4) mAvailableFeatures,系统所有支持的个硬件,如新增硬件支持,都要添加相应的feature

 解析结果mSystemPermissions,mSharedLibraries,mSettings.mPermissions,mAvailableFeatures  等几个集合中供系统查询和权限配置使用。


开始扫描并解析apk

PackageManagerService的构造方法体 ③:

[/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]

synchronized (mInstallLock) {
  // writer
   synchronized (mPackages) {
        mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
        mHandlerThread.start();
        mHandler = new PackageHandler(mHandlerThread.getLooper());
        Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
        File dataDir = Environment.getDataDirectory();
        mAppDataDir = new File(dataDir, "data");
        mAppInstallDir = new File(dataDir, "app");
        mAppLib32InstallDir = new File(dataDir, "app-lib");
        mAsecInternalPath = new File(dataDir, "app-asec").getPath();
        mUserAppDataDir = new File(dataDir, "user");
        mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
        sUserManager = new UserManagerService(context, this, mInstallLock, mPackages);

首先上mInstallLock锁,关于这个锁,前面有注释,用于在做安装操作和其他耗时操作,一般调用到“LI”标签方法都需要上这个锁。

    // Lock for state used when installing and doing other long running
    // operations.  Methods that must be called with this lock held have
    // the suffix "LI".
    final Object mInstallLock = new Object();

第二步上mPackages锁,mPackages的数据结构是包名和包对象的映射表,随着apk一个个的被解析,到最后mPackages会保存所有的已安装apk信息(重要)。同时为了线程安全,作为一个同步锁,在调用“LP”关键字结尾的方法都需要上这个锁。

    // Keys are String (package name), values are Package.  This also serves
    // as the lock for the global state.  Methods that must be called with
    // this lock held have the prefix "LP".
    final ArrayMap<String, PackageParser.Package> mPackages = new ArrayMap<String, PackageParser.Package>();

第三步,建立PackageHandler消息循环,用于处理外部的apk安装请求消息,如adb install, PackageInstaller安装apk请求。并添加到watchdog中进行状态跟踪。可以看到服务首先创建了并运行了一个HandlerThread线程后进入阻塞,并将这个线程的Looper赋予了给PackageHandler,因此所有PackageHandler发的消息都交由这个HandlerThread线程处理并分发,关于PackageHandler,后面详细分析。

           mHandlerThread = new ServiceThread(TAG,
                  Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
	   mHandlerThread.start();
           mHandler = new PackageHandler(mHandlerThread.getLooper());
           Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);

    第四步,在data目录下建立多个系统目录,如/data/app(用于保存安装的第三方apk包), /data/data(用于保存apk数据), /data/app-lib, /data/app-asec, /data/user, /data/app-private

            File dataDir = Environment.getDataDirectory();
            mAppDataDir = new File(dataDir, "data");
            mAppInstallDir = new File(dataDir, "app");
            mAppLib32InstallDir = new File(dataDir, "app-lib");
            mAsecInternalPath = new File(dataDir, "app-asec").getPath();
            mUserAppDataDir = new File(dataDir, "user");
            mDrmAppPrivateInstallDir = new File(dataDir, "app-private");

第五步,将system/etc/permissions目录解析出来的permissions信息以BasePermission形式保存到mSettingsmPermissions中。mSettingsmPermissions最终会随着所有apk的扫描解析而补全,可以认为mSettingsmPermissions保存了系统所有的权限声明。

 将system/etc/permission目录解析出来的所有sharedlibs保存到PMSmSharedLibraries,提供后面共享库的使用。

 解析并读取/data/system/packages.xml文件信息保存到mRestoredSettings实例,如果是第一次开机,读取后mRestoredSettings实例为空。

获得默认的ResolverActivity,这个可以在framework/resconfig_customResolverActivity做定制,一般为空。

PackageManagerService的构造方法体 ④:

[/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]

   // Propagate permission configuration in to package manager.
	ArrayMap<String, SystemConfig.PermissionEntry> permConfig = systemConfig.getPermissions();
	for (int i=0; i<permConfig.size(); i++) {
		SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
		BasePermission bp = mSettings.mPermissions.get(perm.name);
		if (bp == null) {
			bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);
			mSettings.mPermissions.put(perm.name, bp);
		}
		if (perm.gids != null) {
			bp.gids = appendInts(bp.gids, perm.gids);
		}
	}
	ArrayMap<String, String> libConfig = systemConfig.getSharedLibraries();
	for (int i=0; i<libConfig.size(); i++) {
		mSharedLibraries.put(libConfig.keyAt(i), new SharedLibraryEntry(libConfig.valueAt(i), null));
	}
	mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();
	mRestoredSettings = mSettings.readLPw(this, sUserManager.getUsers(false), mSdkVersion, mOnlyCore);
	String customResolverActivity = Resources.getSystem().getString(R.string.config_customResolverActivity);
	if (TextUtils.isEmpty(customResolverActivity)) {
		customResolverActivity = null;
	} else {
		mCustomResolverComponentName = ComponentName.unflattenFromString(customResolverActivity);
	}

第六步,获得服务启动时间,初始化scanFlags,随着后面的扫描,scanFlags会赋予更多的内容。读取bootClassPathsystemServerClassPath,解析所有运行环境动态jar包并添加到alreadyDexOpted列表中,表示这些动态jar已经DexOpt过。读取上面保存到mSharedLibraries并做DexOpt优化。读取system/framework目录下的所有jarapk,逐个检查是否需要odex,如不需要添加到alreadyDexOpted列表中,若需要,调用Installerdexopt,传入最优的ABI类型进行odex优化。

    long startTime = SystemClock.uptimeMillis();
	EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,startTime);
	final int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING;
	final ArraySet<String> alreadyDexOpted = new ArraySet<String>();
	final String bootClassPath = System.getenv("BOOTCLASSPATH");
	final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");            
	if (bootClassPath != null) {
		String[] bootClassPathElements = splitString(bootClassPath, ':');
		for (String element : bootClassPathElements) {
			alreadyDexOpted.add(element);
		}
	} 
	if (systemServerClassPath != null) {
		String[] systemServerClassPathElements = splitString(systemServerClassPath, ':');
		for (String element : systemServerClassPathElements) {
			alreadyDexOpted.add(element);
		}
	}
     	final List<String> allInstructionSets = getAllInstructionSets();
	final String[] dexCodeInstructionSets =
		getDexCodeInstructionSets(allInstructionSets.toArray(new String[allInstructionSets.size()]));
	if (mSharedLibraries.size() > 0) {
	for (String dexCodeInstructionSet : dexCodeInstructionSets) {
		for (SharedLibraryEntry libEntry : mSharedLibraries.values()) {
		final String lib = libEntry.path;
		try {
			byte dexoptRequired = DexFile.isDexOptNeededInternal(lib, null,
					dexCodeInstructionSet,false);
			if (dexoptRequired != DexFile.UP_TO_DATE) { 
		alreadyDexOpted.add(lib);
				if (dexoptRequired == DexFile.DEXOPT_NEEDED) {
		mInstaller.dexopt(lib, Process.SYSTEM_UID, true, dexCodeInstructionSet);
			} else {
			 mInstaller.patchoat(lib, Process.SYSTEM_UID, true, dexCodeInstructionSet);
		}
		}   
		} catch (FileNotFoundException e) {
			Slog.w(TAG, "Library not found: " + lib);
		} catch (IOException e) {
			Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "+ e.getMessage());
		}
		}
	}
	}

PackageManagerService的构造方法体 ⑤:

第七步,分别按照优先级扫描解析并安装/vendor/overlay > /system/framework >/system/priv-app > /system/app > /vendor/app >oemAppDir下的所有apk文件。

[/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]

	File frameworkDir = new File(Environment.getRootDirectory(), "framework");
	alreadyDexOpted.add(frameworkDir.getPath() + "/framework-res.apk");
	alreadyDexOpted.add(frameworkDir.getPath() + "/core-libart.jar");
	String[] frameworkFiles = frameworkDir.list();
      if (frameworkFiles != null) {
		for (String dexCodeInstructionSet : dexCodeInstructionSets) {
			for (int i=0; i<frameworkFiles.length; i++) {
				File libPath = new File(frameworkDir, frameworkFiles[i]);
				String path = libPath.getPath();
				if (alreadyDexOpted.contains(path)) {
				continue;
				}
				if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
				continue;
				}
				try {
				byte dexoptRequired = DexFile.isDexOptNeededInternal(path, null, dexCodeInstructionSet, false);
				if (dexoptRequired == DexFile.DEXOPT_NEEDED) {
	mInstaller.dexopt(path, Process.SYSTEM_UID, true, dexCodeInstructionSet);
				} else if (dexoptRequired == DexFile.PATCHOAT_NEEDED) {
				mInstaller.patchoat(path, Process.SYSTEM_UID, true, dexCodeInstructionSet);
				}
				} catch (FileNotFoundException e) {
				} catch (IOException e) {
				}
			}
		}
	}
	File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
	scanDirLI(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
	scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_IS_PRIVILEGED,scanFlags | SCAN_NO_DEX, 0);
	final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
	final File systemAppDir = new File(Environment.getRootDirectory(), "app");
	scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
	File vendorAppDir = new File("/vendor/app");
	scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
	final File oemAppDir = new File(Environment.getOemDirectory(), "app");
	scanDirLI(oemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

扫描安装流程图如下:


PackageManagerService的构造方法体 ⑥:

扫描system分区的几个保存apk文件的目录,得到目录下所有文件实例,是否apk以及apk命名是否合法。如果都没问题,调用scanPackageLI方法对apk文件进一步解析。

捕获安装异常后,如果非system应用,则删除有问题的apk目录和文件。

[/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]

private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) {
	final File[] files = dir.listFiles();
	for (File file : files) {
		final boolean isPackage = (isApkFile(file) || file.isDirectory())
				&& !PackageInstallerService.isStageName(file.getName());
		if (!isPackage) {
			continue;
		}
		try {
		   scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK, scanFlags, currentTime, null);
		} catch (PackageManagerException e) {
			// Delete invalid userdata apps
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 && e.error == PackageManager.INSTALL_FAILED_INVALID_APK) {
				logCriticalInfo(Log.WARN, "Deleting invalid package at " + file);
				if (file.isDirectory()) {
					FileUtils.deleteContents(file);
				}
				file.delete();
			}
		}
	}
}

PackageManagerService的构造方法体 ⑦:

scanDirLI传入apk的文件路径后,和默认parseFlags合成扫描标记。

创建PackageParser实例,有关PackageParser(包解析器)的结构,下面会详细描述。

pp.setDisplayMetrics方法传入手机的分辨率参数,用于初始化资源管理器。最后调用PackageParserparsePackage方法返回解析的Package实例。

[/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]

private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
	parseFlags |= mDefParseFlags;
	PackageParser pp = new PackageParser();
	pp.setSeparateProcesses(mSeparateProcesses);
	pp.setOnlyCoreApps(mOnlyCore);
	pp.setDisplayMetrics(mMetrics); 
	if ((scanFlags & SCAN_TRUSTED_OVERLAY) != 0) {
		parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY;
	}
	final PackageParser.Package pkg;
	try {
		pkg = pp.parsePackage(scanFile, parseFlags);
	} catch (PackageParserException e) {
		throw PackageManagerException.from(e);
	}

PackageParser中定义多个静态内部类,如PackageParser.Package(表示一个apk安装包),这个内部类十分重要,apk解析后得到的所有信息都保存在这个类中,并添加拿到PackageManagerServicemPackages列表中。另外一个就是PackageParser.Component(表示一个应用组件),其中内部类Permission/Activity/Service/Provider都是它的子类,他们在PackageParser都是轻量级的组件表示,具体的组件表示分别是PermissionInfo/ActivityInfo/ServiceInfo/ProviderInfo。包解析类PackageParser的结构如图4


[/frameworks/base/core/java/android/content/pm/PackageParser.java]

public Package parsePackage(File packageFile, int flags) throws PackageParserException {
	if (packageFile.isDirectory()) {
		return parseClusterPackage(packageFile, flags);
	} else {
		return parseMonolithicPackage(packageFile, flags);
	}
}

private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
	final PackageLite lite = parseClusterPackageLite(packageDir, 0);
	final AssetManager assets = new AssetManager();
	try {
		loadApkIntoAssetManager(assets, lite.baseCodePath, flags);
		if (!ArrayUtils.isEmpty(lite.splitCodePaths)) {
			for (String path : lite.splitCodePaths) {
				loadApkIntoAssetManager(assets, path, flags);
			}
		}
		final File baseApk = new File(lite.baseCodePath);
		final Package pkg = parseBaseApk(baseApk, assets, flags);
		return pkg;
	} finally {
		IoUtils.closeQuietly(assets);
	}
}

private Package parseBaseApk(File apkFile, AssetManager assets, int flags) throws PackageParserException {
	final String apkPath = apkFile.getAbsolutePath();
	mParseError = PackageManager.INSTALL_SUCCEEDED; 
	Resources res = null;
	XmlResourceParser parser = null;
	try {
		res = new Resources(assets, mMetrics, null);
		assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Build.VERSION.RESOURCES_SDK_INT);
		parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
		final String[] outError = new String[1];
		final Package pkg = parseBaseApk(res, parser, flags, outError);
		pkg.mSignatures = null; 
		return pkg; 
	} catch (PackageParserException e) {
		throw e;
	} 
}

执行parseBaseApk方法通过XmlPullParser根据不同的深度,解析AndroidManifest.xml文件中的所有标签和元素,保存到对应的数组中。

private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags, String[] outError) 
throws XmlPullParserException, IOException { 
	AttributeSet attrs = parser;
//…//
	if (tagName.equals("key-sets")) {
		//解析keysets并保存到publicKeyNames中
		if (!parseKeySets(pkg, res, parser, attrs, outError)) { 
			return null;
		}
	} else if (tagName.equals("permission-group")) {
		//解析permission group并保存到permissionGroups中
		if (parsePermissionGroup(pkg, flags, res, parser, attrs, outError) == null) { 
			return null;
		}
	} else if (tagName.equals("permission")) {
		//解析permission并保存到permissions列表中
		if (parsePermission(pkg, res, parser, attrs, outError) == null) { 
			return null;
		}
	} else if (tagName.equals("uses-permission")) {  
		//解析uses permission并保存到requestPermissions列表中
		if (!parseUsesPermission(pkg, res, parser, attrs, outError)) {
			return null;
		}
	}
//…//

	String tagName = parser.getName();
	//判断到<application>标签,调用parseBaseApplicatin方法逐层解析下面的元素
	if (tagName.equals("application")) { 
		if (foundApp) {
			if (RIGID_PARSER) {
				mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
				return null;
			} else {
				XmlUtils.skipCurrentTag(parser);
				continue;
			}
		}
		foundApp = true;
		//开始解析application标签里的activity/receive/provider/service/intentfilter…
		if (!parseBaseApplication(pkg, res, parser, attrs, flags, outError)) { 
			return null;
		}
	}
//…//
private boolean parseBaseApplication(Package owner, Resources res, XmlPullParser parser, 
AttributeSet attrs, int flags, String[] outError) throws XmlPullParserException, IOException {
	final ApplicationInfo ai = owner.applicationInfo;
	final String pkgName = owner.applicationInfo.packageName;
//…//
	String tagName = parser.getName();
	if (tagName.equals("activity")) { 
Activity a = 
parseActivity(owner, res, parser, attrs, flags, outError, false, owner.baseHardwareAccelerated); 
		owner.activities.add(a); 
	} else if (tagName.equals("receiver")) {
	       //解析receiver并添加到PackageParser.Package.receivers中
		Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false); 
		owner.receivers.add(a); 
	} else if (tagName.equals("service")) {
	       //解析service并添加到PackageParser.Package.services中
		Service s = parseService(owner, res, parser, attrs, flags, outError);  
		owner.services.add(s); 
	} else if (tagName.equals("provider")) {
	        //解析provider并添加到PackageParser.Package.providers中
		Provider p = parseProvider(owner, res, parser, attrs, flags, outError);   
		owner.providers.add(p); 
	} 

解析的标签以及层级结构如下图。



进一步解析apk

回到PackageManagerService中,通过PackageParserparsePackage方法解析得到含apk所有基本信息的PackageParser.Package实例pkg,继续执行后续的安装操作。

PackageManagerService的构造方法体 ⑧:

PackageParser.parsePackage后得到当前扫描目录下apk文件的所有信息,并以pkg表示。接下来要更进一步的执行apk安装的操作,首先先来检查当前解析后pkg的老旧程度。这里主要针对system应用,一个首要原则是如果更新后的apkdata/app目录下)的version大于等于system/app目录下预装的同样一个apk,那这时候直接抛异常返回,不会继续往下跑,除非发现system目录下扫描的apk比之前更新的apk版本要新,那么会重新安装这个新版本的apk

一般第一次开机执行apk扫描安装操作,ps都是空,这些地方都不会跑到,只有在开机一次后生成了cache,下次开机则需要比较cache中的内容。因此保存cachepackages.xml)对于第二次开机,速度上有很大的提升。

[/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]

PackageSetting ps = null;
PackageSetting updatedPkg;
// reader
synchronized (mPackages) {
	//通过开机预加载的mSettings找到当前是否存在同样包名的旧apk
	// Look to see if we already know about this package.
	String oldName = mSettings.mRenamedPackages.get(pkg.packageName);   
	if (ps == null) {
		ps = mSettings.peekPackageLPr(pkg.packageName);
	}
	//通过开机预加载的mSettings看是否找到被disable掉的package
	updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName); 
}
boolean updatedPkgBetter = false;
if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
	if (ps != null && !ps.codePath.equals(scanFile)) {
		if (pkg.mVersionCode <= ps.versionCode) {
			//发现cache中保存的另外一个目录(data/app)的apk版本比当前扫描的apk版本要新,
//那么跳出解析,沿用cache的apk
			throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE, null);  
		} else {
			synchronized (mPackages) {
				//否则,重新激活当前扫描的apk
				mSettings.enableSystemPackageLPw(ps.name);  
			}
			updatedPkgBetter = true;
		}
	}
}

下一步搜集apk签名信息并比较,这部分会在(5)签名证书校验过程中详细分析。

// Verify certificates against what was last scanned
collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags);    
//搜集当前pkg签名信息
if (updatedPkg == null && ps != null && (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) { 
	/*
	 * Check to make sure the signatures match first. If they don't,
	 * wipe the installed application and its data.
	 */
	if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {  
//比较签名,如果不匹配,删除apk和资源
		deletePackageLI(pkg.packageName, null, true, null, null, 0, null, false);
		ps = null;
	} 
}

初始化pkg.applicationInfo中的代码和资源路径后,进一步调用scanPackageLI执行pkg安装操作。

// Set application objects path explicitly.
pkg.applicationInfo.setCodePath(pkg.codePath);
pkg.applicationInfo.setBaseCodePath(pkg.baseCodePath);
pkg.applicationInfo.setSplitCodePaths(pkg.splitCodePaths);
pkg.applicationInfo.setResourcePath(resourcePath);
pkg.applicationInfo.setBaseResourcePath(baseResourcePath);
pkg.applicationInfo.setSplitResourcePaths(pkg.splitCodePaths);
// Note that we invoke the following method only if we are about to unpack an application
//调用scanPackageLI执行进一步安装操作
PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanFlags | SCAN_UPDATE_SIGNATURE, currentTime, user);

scanPackageLI里面紧接着调用scanPackageDirtyLI,接下来详细分析scanPackageDirtyLI方法。

这个方法比较大,大概有一千两百多行,具体要分块来看。

第一步:根据parseFlags初始化pkg.applicationInfoflags,这个flagspkg类型和等级划分有很大的作用。

[/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]

private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags, 
			int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
	if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {

		//如果parseFlags含system,那么意味着这是一个system级pkg,
		//所以也给这个pkg的flags加上system标签。
		pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM  
	} 
	if ((parseFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {
		//如果parseFlags含privileged,那么意味着这是一个privileged级pkg,
		//所以也给这个pkg的flags加上privileged标签。
		pkg.applicationInfo.flags |= ApplicationInfo.FLAG_PRIVILEGED; 
	}
	if (mCustomResolverComponentName != null &&
			mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) {
		//找出默认的resolver包名
		setUpCustomResolverActivity(pkg);         
	}

第二步:如果pkg包名是”android”,表示平台应用,实际上它就是framework/framework-res.apk,将该apk信息赋值给全局变量mAndroidApplication

 判断Resolver程序是否已经有,如果没有,则用系统默认的ResolveActivity作为菜单选择应用,一般都会用源生的ResolveActivity

if (pkg.packageName.equals("android")) {
	synchronized (mPackages) {
		mPlatformPackage = pkg;
		pkg.mVersionCode = mSdkVersion;
		mAndroidApplication = pkg.applicationInfo; 
		if (!mResolverReplaced) {
			mResolveActivity.applicationInfo = mAndroidApplication;
			mResolveActivity.name = ResolverActivity.class.getName();
			mResolveActivity.packageName = mAndroidApplication.packageName;
			mResolveActivity.processName = "system:ui";
			mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
			mResolveActivity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NEVER;
			mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
			mResolveActivity.theme = R.style.Theme_Holo_Dialog_Alert;
			mResolveActivity.exported = true;
			mResolveActivity.enabled = true;
			mResolveInfo.activityInfo = mResolveActivity;
			mResolveInfo.priority = 0;
			mResolveInfo.preferredOrder = 0;
			mResolveInfo.match = 0;
			mResolveComponentName = new ComponentName(mAndroidApplication.packageName, 
							mResolveActivity.name);
		}
	}
}

第三步:

1,判断解析后的pkg是否包含shareduser,如果有则取出来赋值给suid,如:shareduserid=”android.uid.system”,那么得到的suid就是systemuid的实例。

2,获得pkg对应的PackageSetting实例pkgSetting,首次开机会new一个PackageSetting实例,随后的开机则会重用cachepackages.xml)中的pkgSettings内容。 注意:这里会对应生成apk进程的uid保存到PackageSetting实例中,以appId表示。

3,如果disabledSystemPackage包含当前pkg,则给flags标记FLAG_UPDATED_SYSTEM_APP,表示更新后的system应用。如/data/app目录下的更新apk

4,根据mSharedLibraries列表中的sharedlib来更新/data/app目录下所有apk需要用到的usesLibraryFiles

5,保存uidpkgSettingpkg实例中。

 注意:以后想要拿到对应pkgpkgSetting信息,引用其mExtras即可。

synchronized (mPackages) {
	if (pkg.mSharedUserId != null) {
		suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, true);
		if (suid == null) {
			throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE, 
			"Creating application package " + pkg.packageName + " for shared user failed");			package " + pkg.packageName + " for shared user failed");
		}
	}
	pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
			destResourceFile, pkg.applicationInfo.nativeLibraryRootDir,
			pkg.applicationInfo.primaryCpuAbi,
			pkg.applicationInfo.secondaryCpuAbi,
			pkg.applicationInfo.flags, user, false);
	if (pkgSetting == null) {
		throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
				"Creating application package " + pkg.packageName + " failed");
	}
	if (mSettings.isDisabledSystemPackageLPr(pkg.packageName)) {
		pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
	}
	if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
		updateSharedLibrariesLPw(pkg, null);
	}
	pkg.applicationInfo.uid = pkgSetting.appId;
	pkg.mExtras = pkgSetting;

第四步:检查cache中保存的签名信息和当前解析pkg的签名信息是否匹配,分4种情况:

1, cache中保存的签名信息没有标记为更新,或者包含sharedUser的情况下,需要比对签名

2, 如果签名和cache中保存的签名信息不匹配,但是system应用,直接以当前pkg签名覆盖

3, 包含sharedUser的,需要比对和其他sharedUser比对签名

4, Cache中签名信息有更新,比对后覆盖更新

注意:比对签名实际就是两个签名文件之间内容的比较。

if (!pkgSetting.keySetData.isUsingUpgradeKeySets() || pkgSetting.sharedUser != null) { 
	try {
		// 1,cache中保存的签名没有更新或者包含sharedUser,
		// 调用verifySignaturesLP比对签名
		verifySignaturesLP(pkgSetting, pkg);     
		// 1,签名匹配,更新cache信息
		pkgSetting.signatures.mSignatures = pkg.mSignatures;  
	} catch (PackageManagerException e) {
		if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
			throw e;
		}
		// 2,虽然签名和cache不一致,但是system应用的话,直接以当前pkg的签名替换覆盖
		pkgSetting.signatures.mSignatures = pkg.mSignatures;   
		if (pkgSetting.sharedUser != null) {
			// 3,包含sharedUser的话,要比对和sharedUser之间的签名
			if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures, 
				pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {  
				throw new PackageManagerException(
					INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
					"Signature mismatch for shared user : " + pkgSetting.sharedUser); 
			}
		}
	}
} else {
	// 4,cache中签名信息有更新,比对新签名
	if (!checkUpgradeKeySetLP(pkgSetting, pkg)) {  
		throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
			"Package " + pkg.packageName + " upgrade keys do not match the " + 
			"previously installed version");
	} else {
		// 4,比对一致,以当前pkg签名信息为最新
		pkgSetting.signatures.mSignatures = pkg.mSignatures; 
	}
}

第五步:

1,检查新安装的应用注册的provider是否和现有的provider冲突,如果冲突直接返回安装失败异常。

 2,如果有AdoptPermissions,做旧版本pkg权限向新版本pkg权限传递(发生在系统应用更新过程中)。

if ((scanFlags & SCAN_NEW_INSTALL) != 0) {
	for (int i=0; i<pkg.providers.size(); i++) {
		PackageParser.Provider p = pkg.providers.get(i);
		if (p.info.authority != null) {
			String names[] = p.info.authority.split(";");
			for (int j = 0; j < names.length; j++) {
				if (mProvidersByAuthority.containsKey(names[j])) {
					PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
					final String otherPackageName = ((other != null && other.getComponentName() 
					!= null) ? other.getComponentName().getPackageName() : "?");
					throw new PackageManagerException(INSTALL_FAILED_CONFLICTING_PROVIDER, 
					"Can't install because provider name " + names[j] + 
					" (in package " + pkg.applicationInfo.packageName
						+ ") is already used by " + otherPackageName);
				}
			}
		}
	}
}
if (pkg.mAdoptPermissions != null) {
	for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) {
		final String origName = pkg.mAdoptPermissions.get(i);
		final PackageSetting orig = mSettings.peekPackageLPr(origName);
		if (orig != null) {
			if (verifyPackageUpdateLPr(orig, pkg)) {
				mSettings.transferPermissionsLPw(origName, pkg.packageName);
			}
		}
	}
}

第六步:

1,获得扫描文件最后一次修改时间scanFileTime,这个变量后面会用到。

2,判断是否需要FORCE_DEX,后面会用到。

3,根据pkg包名获得dataPath,如果包名是”android”,dataPath/data/system,否则dataPath/data/packageName

3.1,首先判断该dataPath目录是否存在,如果存在,检查里面的有效性,如果失效或异常,重新安装

3.2,如果不存在改dataPath目录,首次安装,这时调用createDataDirsLI方法执行apk安装操作。

final String pkgName = pkg.packageName;
final long scanFileTime = scanFile.lastModified();
final boolean forceDex = (scanFlags & SCAN_FORCE_DEX) != 0;
pkg.applicationInfo.processName = fixProcessName(pkg.applicationInfo.packageName,
                pkg.applicationInfo.processName, pkg.applicationInfo.uid);
File dataPath;
if (mPlatformPackage == pkg) {
	// The system package is special.
	dataPath = new File(Environment.getDataDirectory(), "system");
	pkg.applicationInfo.dataDir = dataPath.getPath();
} else {
	dataPath = getDataPathForPackage(pkg.packageName, 0);
	boolean uidError = false;
    if (dataPath.exists()) {
		int currentUid = 0;
		pkg.applicationInfo.dataDir = dataPath.getPath();
	} else {            
		int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid, pkg.applicationInfo.seinfo);
		if (dataPath.exists()) {
			pkg.applicationInfo.dataDir = dataPath.getPath();
		} else {
			Slog.w(TAG, "Unable to create data directory: " + dataPath);
			pkg.applicationInfo.dataDir = null;
		}
    }
    pkgSetting.uidError = uidError;
}

4createDataDirsLI方法中调用mInstallerInstaller服务)中的installcreateUserData方法,通过Socket和底层installd进程通讯,创建dataPath目录。 Installd执行安装过程后面会有分析。

  private int createDataDirsLI(String packageName, int uid, String seinfo) {
        int[] users = sUserManager.getUserIds();
        int res = mInstaller.install(packageName, uid, uid, seinfo);
        if (res < 0) {
            return res;
        }
        for (int user : users) {
            if (user != 0) {
                res = mInstaller.createUserData(packageName,
                        UserHandle.getUid(user, uid), user, seinfo);
                if (res < 0) {
                    return res;
                }
            }
        }
        return res;
    }

第七步:解析system级和data级目录下apkCpuAbi信息,这里的CpuAbi表示系统以哪种形式去动态加载so库。

【应用程序二进制接口(application binary interfaceABI) 描述了应用程序和操作系统之间,一个应用和它的库之间,或者应用的组成部分之间的低接口 。ABI 不同于 API API 定义了源代码和库之间的接口,因此同样的代码可以在支持这个 API 的任何系统中编译 ,然而 ABI 允许编译好的目标代码在使用兼容 ABI 的系统中无需改动就能运行。】

pkg.cpuAbiOverride  ---> 用于应用跨进程运行,动态so的拷贝控制

pkg.applicationInfo.primaryCpuAbi  ---> 基本CpuAbi,最优先以该形式起应用进程

pkg.applicationInfo.secondaryCpuAbi   --->第二优先CpuAbi

pkg.applicationInfo.nativeLibraryRootDir     --->本地库根目录   

pkg.applicationInfo.nativeLibraryRootRequiresIsa  --- >是否添加arm/arm64   (系统应用)

pkg.applicationInfo.nativeLibraryDir   --- >本地库目录

pkg.applicationInfo.secondaryNativeLibraryDir  ---> 第二优先本地库目录

针对系统应用和第三方应用,上述CpuAbi信息的获取方式是不同的,另外系统应用的CpuAbi信息在开机扫描安装过程中就已经固定下来。

系统应用获得CpuAbi信息的过程如下。

final String path = scanFile.getPath();
final String codePath = pkg.applicationInfo.getCodePath();
 final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);
 if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
     setBundledAppAbisAndRoots(pkg, pkgSetting);
	setNativeLibraryPaths(pkg); 
}

private static void setBundledAppAbi(PackageParser.Package pkg, String apkRoot, String apkName) {
	final File codeFile = new File(pkg.codePath);
	final boolean has64BitLibs;
	final boolean has32BitLibs;
	if (isApkFile(codeFile)) {
		// Monolithic install 单独apk文件形式
		has64BitLibs = (new File(apkRoot, new File(LIB64_DIR_NAME, apkName).getPath())).exists();
		has32BitLibs = (new File(apkRoot, new File(LIB_DIR_NAME, apkName).getPath())).exists();
	} else {
		// Cluster install 以文件夹形式安装方式
		final File rootDir = new File(codeFile, LIB_DIR_NAME);
		if (!ArrayUtils.isEmpty(Build.SUPPORTED_64_BIT_ABIS)
				&& !TextUtils.isEmpty(Build.SUPPORTED_64_BIT_ABIS[0])) {
			final String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_64_BIT_ABIS[0]);
			has64BitLibs = (new File(rootDir, isa)).exists();
		}
		if (!ArrayUtils.isEmpty(Build.SUPPORTED_32_BIT_ABIS)
				&& !TextUtils.isEmpty(Build.SUPPORTED_32_BIT_ABIS[0])) {
			final String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_32_BIT_ABIS[0]);
			has32BitLibs = (new File(rootDir, isa)).exists();
		}
	}
	if (has64BitLibs && !has32BitLibs) {
		// 只含64位so,系统支持64位,则primaryCpuAbi是arm64 
		pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0];
		pkg.applicationInfo.secondaryCpuAbi = null;
	} else if (has32BitLibs && !has64BitLibs) {
		//只含32位so,系统支持32位,则primaryCpuAbi是armabi
		pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0];
		pkg.applicationInfo.secondaryCpuAbi = null;
	} else if (has32BitLibs && has64BitLibs) {
		//两个so都含,检查是否支持multiArch,否则抛异常
		// primaryCpuAbi以列表顺序最高 secondaryCpuAbi为第二
		if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) == 0) {
			Slog.e(TAG, "Package: " + pkg + " has multiple bundled libs, but is not multiarch.");
		}
		if (VMRuntime.is64BitInstructionSet(getPreferredInstructionSet())) {
			pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0];
			pkg.applicationInfo.secondaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0];
		} else {
			pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0];
			pkg.applicationInfo.secondaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0];
		}
	} else {
		//不包含so,则为空
		pkg.applicationInfo.primaryCpuAbi = null;
		pkg.applicationInfo.secondaryCpuAbi = null;
	}
}


获得primaryCpuAbisecondaryCpuAbi信息后,将这两个信息保存到pkgSettings中。然后执行setNativeLibraryPaths方法获得跟多nativeLibrary信息,如nativeLibraryRootDir, nativeLibraryDir

      非系统应用获得primaryCpuAbisceondaryCpuAbi信息就显得复杂很多,通过计算得到安装应用的primaryCpuAbi后,需要创建Linkso关联起来(注意:只为32so创建link)。代码如下: 

	if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path);
	final int[] userIds = sUserManager.getUserIds();
	synchronized (mInstallLock) {
		// Create a native library symlink only if we have native libraries
		// and if the native libraries are 32 bit libraries. We do not provide
		// this symlink for 64 bit libraries.
		if (pkg.applicationInfo.primaryCpuAbi != null &&
				!VMRuntime.is64BitAbi(pkg.applicationInfo.primaryCpuAbi)) {
			final String nativeLibPath = pkg.applicationInfo.nativeLibraryDir;
			for (int userId : userIds) {
				if (mInstaller.linkNativeLibraryDirectory(pkg.packageName, 
					nativeLibPath, userId) < 0) {
					throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
							"Failed linking native library dir (user=" + userId + ")");
				}
			}
		}
	}

针对frameworks-res.apkprimaryCpuAbi有特殊的处理,根据VMRuntime是否允许64位来优先判断。

	// This is a special case for the "system" package, where the ABI is
	// dictated by the zygote configuration (and init.rc). We should keep track
	// of this ABI so that we can deal with "normal" applications that run under
	// the same UID correctly.
	if (mPlatformPackage == pkg) {
		pkg.applicationInfo.primaryCpuAbi = VMRuntime.getRuntime().is64Bit() ?
				Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0];
	}

第八步:primaryCpuAbi处理完成后,继续scanPackageDirtyLI方法收尾部分代码。

	if ((scanFlags&SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) {
		// 此处做shareduser的CpuAbi适配动作,意思是shareduser的应用CpuAbi信息应该统一
		// 这里判断如果是开机扫描过程,不用做这步,放在PMS构造方法最后去做
		adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages,
				pkg, forceDex, (scanFlags & SCAN_DEFER_DEX) != 0);
	}

// 声明了FACTORY_TEST权限的应用,对应的applicationInfo中要记录一个标志位标识
	if (mFactoryTest && pkg.requestedPermissions.contains(
			android.Manifest.permission.FACTORY_TEST)) {
		pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
	}

// 筛选出应用中满足条件的shareLibrary并添加到mSharedLibraries总表中。
     ArrayList<PackageParser.Package> clientLibPkgs = null;
	// writer
	synchronized (mPackages) {
		if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
			// Only system apps can add new shared libraries.
			for (int i=0; i<pkg.libraryNames.size(); i++) {
				String name = pkg.libraryNames.get(i);
				if (!mSharedLibraries.containsKey(name)) {
				    mSharedLibraries.put(name, new SharedLibraryEntry(null, pkg.packageName));
				} else if (!name.equals(pkg.packageName)) {
					Slog.w(TAG, "Package " + pkg.packageName + " library "
								+ name + " already exists; skipping");
				}
			}
		}
	}

	//如果扫描flag带SCAN_REPLACING标志,意味着应用替换,请求AMS先杀死当前运行中的旧应用进程
	if ((scanFlags & SCAN_REPLACING) != 0) {
		killApplication(pkg.applicationInfo.packageName,
					pkg.applicationInfo.uid, "update pkg");
	}


	// writer
	synchronized (mPackages) {
		// 当前pkgSettings添加到mSettings总表中
		mSettings.insertPackageSettingLPw(pkgSetting, pkg);
		// 当前pkg添加到mPackages总表中
		mPackages.put(pkg.applicationInfo.packageName, pkg);
		// 更新第一次安装和最后一次更新时间
            if (currentTime != 0) {
                if (pkgSetting.firstInstallTime == 0) {
                    pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
                } else if ((scanFlags&SCAN_UPDATE_TIME) != 0) {
                    pkgSetting.lastUpdateTime = currentTime;
                }
            } else if (pkgSetting.firstInstallTime == 0) {
                pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
            } else if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
                if (scanFileTime != pkgSetting.timeStamp) {
                    pkgSetting.lastUpdateTime = scanFileTime;
                }
            }
		// 添加安装应用签名key到KSMS中
            KeySetManagerService ksms = mSettings.mKeySetManagerService;
            ksms.removeAppKeySetDataLPw(pkg.packageName);
            ksms.addSigningKeySetToPackageLPw(pkg.packageName, pkg.mSigningKeys);
            
		// 将应用声明的providers添加到mProviders总表中
		int N = pkg.providers.size();
            StringBuilder r = null;
            int i;
            for (i=0; i<N; i++) {
                PackageParser.Provider p = pkg.providers.get(i);
                p.info.processName = fixProcessName(pkg.applicationInfo.processName,
                        p.info.processName, pkg.applicationInfo.uid);
                mProviders.addProvider(p);
            if (r != null) {
                if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Providers: " + r);
            }

   		// 将应用声明的service添加到mServices总表中
N = pkg.services.size();
            r = null;
            for (i=0; i<N; i++) {
                PackageParser.Service s = pkg.services.get(i);
                s.info.processName = fixProcessName(pkg.applicationInfo.processName,
                        s.info.processName, pkg.applicationInfo.uid);
                mServices.addService(s);
            }
            if (r != null) {
                if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Services: " + r);
            }

// 将应用声明的recievers添加到mReceivers总表中
            N = pkg.receivers.size();
            r = null;
            for (i=0; i<N; i++) {
                PackageParser.Activity a = pkg.receivers.get(i);
                a.info.processName = fixProcessName(pkg.applicationInfo.processName,
                        a.info.processName, pkg.applicationInfo.uid);
                mReceivers.addActivity(a, "receiver");     
            }
            if (r != null) {
                if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Receivers: " + r);
            }
// 将应用声明的activity添加到mActivities总表中
            N = pkg.activities.size();
            r = null;
            for (i=0; i<N; i++) {
                PackageParser.Activity a = pkg.activities.get(i);
                a.info.processName = fixProcessName(pkg.applicationInfo.processName,
                        a.info.processName, pkg.applicationInfo.uid);
                mActivities.addActivity(a, "activity");
		}
            if (r != null) {
                if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Activities: " + r);
            }

// 将应用声明的permissionGroup添加到mPermissionGroups总表中
mPermissionGroups.put(pg.info.name, pg);
// 将应用声明的instrumentation添加到mInstrumentation总表中
N = pkg.instrumentation.size();
            r = null;
            for (i=0; i<N; i++) {
                PackageParser.Instrumentation a = pkg.instrumentation.get(i);
                a.info.packageName = pkg.applicationInfo.packageName;
                a.info.sourceDir = pkg.applicationInfo.sourceDir;
                a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
                a.info.splitSourceDirs = pkg.applicationInfo.splitSourceDirs;
                a.info.splitPublicSourceDirs = pkg.applicationInfo.splitPublicSourceDirs;
                a.info.dataDir = pkg.applicationInfo.dataDir;
                a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
                mInstrumentation.put(a.getComponentName(), a);
            }
            if (r != null) {
                if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Instrumentation: " + r);
            }
}
// scanPackageDirty方法执行完毕,返回安装后的pkg
return pkg;

至此,scanPackageDirty方法执行完毕,apk解析安装过程初步完成并返回解析出来的pkg实例。

要重点注意到pkgmExtras引用指向了包含apk权限等各种信息的实例pkgSettings,同时pkg实例添加到了mPackages列表中,以后就可以通过mPackages列表找到这个pkg

扫描安装过程如下图所示



pms构造方法结尾部分

分别扫描所有apk目录并安装解析所有apk后,回到pms构造方法中,主要完成两个事情,一个是清理多余或者无效的apk信息,另外一个是更新所有应用的sharedLibrary和权限信息

清理多余或者无效的apk信息:

	// Prune any system packages that no longer exist.
	final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
	final ArrayMap<String, File> expectingBetter = new ArrayMap<>();
	//look for any incomplete package installations
	ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
	//delete tmp files
	deleteTempPackageFiles();
	// Remove any shared userIDs that have no associated packages
	mSettings.pruneSharedUsersLPw();

更新所有应用的sharedLibrary和权限信息:

	// Now that we know all of the shared libraries, update all clients to have
	// the correct library paths.
	updateAllSharedLibrariesLPw();
	for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
		// NOTE: We ignore potential failures here during a system scan (like
		// the rest of the commands above) because there's precious little we
		// can do about it. A settings error is reported, though.
		adjustCpuAbisForSharedUserLPw(setting.packages, null /* scanned package */,
				false /* force dexopt */, false /* defer dexopt */);
	}

	updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL | (regrantPermissions
					? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
					: 0));

关于updatePermissionsLPw这个方法十分重要,系统权限管理的分级以及分配规则就在这个方法里面。后面在系统权限管理中详细分析。

至此,pms的构造方法就分析完毕。

理解:构造方法中做了很多初始化的内容,以及扫描所有应用目录下的apk文件进行解析安装,最终都会添加到mPackages列表中,并在最后遍历mPackages列表中的所有应用,完成权限分配,共享库更新等功能。后续所有包管理任务都按照得到的mPackages来完成。



猜你喜欢

转载自blog.csdn.net/lgglkk/article/details/54839662