Android框架层PackageManagerService构造方法中的两个synchronized

在此之前的一些操作基本上都是比较简单的,也没有做什么核心的事情。主要是在这两个synchronized中,开始时,启动一个名为PackageManager的消息线程,该线程是PackageManagerService的工作线程,mHandlerThread线程是一个带消息循环的工作线程,在定义该线程对象的时候就已经创建。

mHandlerThread.start();// 启动消息处理线程

对于对象mHandlerThreadfinal老早就创建好了

final HandlerThread mHandlerThread = new HandlerThread(“PackageManager”,
            Process.THREAD_PRIORITY_BACKGROUND);

同时为该消息线程创建了一个消息分发器PackageHandler对象,通过该handler对象可以往PackageManager线程发送消息,PackageManager线程通过消息循环处理发送进来的消息,消息处理过程如下:

class PackageHandler extends Handler {。。。。}

在这里这些消息并非是在PackageHandler中处理的,而是通过连接服务MCS,通过MCS服务间接的完成消息处理的。(见PackageHandler代码,其中有启动连接服务的方法connectToService,disconnectService。

======================================================================================

之后就是,,

                // 获取路径
                File dataDir = Environment.getDataDirectory();// // dataDir
                                                                // =/data/
                mAppDataDir = new File(dataDir, “data”);// 创建目录 mAppDataDir =
                                                        // /data/data
                mUserAppDataDir = new File(dataDir, “user”);// mUserAppDataDir =
                                                            // /data/user
                mDrmAppPrivateInstallDir = new File(dataDir, “app-private”);// mDrmAppPrivateInstallDir=

// UserManager类似与动态数据库
                mUserManager = new UserManager(mInstaller, mUserAppDataDir);

创建/data/目录,上面mUserManager = new UserManager(mInstaller, mUserAppDataDir);是初始化user信息,也即是构造UserManager。

    UserManager(File dataDir, File baseUserPath) {
        mUsersDir = new File(dataDir, USER_INFO_DIR);
        mUsersDir.mkdirs();
        mBaseUserPath = baseUserPath;
        FileUtils.setPermissions(mUsersDir.toString(),
                FileUtils.S_IRWXU|FileUtils.S_IRWXG
                |FileUtils.S_IROTH|FileUtils.S_IXOTH,
                -1, -1);
        mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
        readUserList();
    }

    public UserManager(Installer installer, File baseUserPath) {
        this(Environment.getDataDirectory(), baseUserPath);
        mInstaller = installer;
    }

下面的构造调用了上面的,

    private void readUserList() {
        mUsers = new SparseArray<UserInfo>();
        if (!mUserListFile.exists()) {
            fallbackToSingleUser();
            return;
        }
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(mUserListFile);
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(fis, null);
            int type;
            while ((type = parser.next()) != XmlPullParser.START_TAG
                    && type != XmlPullParser.END_DOCUMENT) {
                ;
            }

            if (type != XmlPullParser.START_TAG) {
                Slog.e(LOG_TAG, “Unable to read user list”);
                fallbackToSingleUser();
                return;
            }

            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
                if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_USER)) {
                    String id = parser.getAttributeValue(null, ATTR_ID);
                    UserInfo user = readUser(Integer.parseInt(id));
                    if (user != null) {
                        mUsers.put(user.id, user);
                    }
                }
            }
            updateUserIds();
        } catch (IOException ioe) {
            fallbackToSingleUser();
        } catch (XmlPullParserException pe) {
            fallbackToSingleUser();
        }
    }
UserInfo user = readUser(Integer.parseInt(id));

if (user != null) {
                        mUsers.put(user.id, user);
                    }

这里都是解析xml文件,获取用户信息。。将获取到的UserInfo保存到UserManager中的mUsers中。

====================================================================

解析系统permission信息

  1. void readPermissions() {  
  2.     // Read permissions from …/etc/permission directory.  
  3.     File libraryDir = new File(Environment.getRootDirectory(), “etc/permissions”);  
  4.     if (!libraryDir.exists() || !libraryDir.isDirectory()) {  
  5.         Slog.w(TAG, “No directory “ + libraryDir + “, skipping”);  
  6.         return;  
  7.     }  
  8.     if (!libraryDir.canRead()) {  
  9.         Slog.w(TAG, “Directory “ + libraryDir + ” cannot be read”);  
  10.         return;  
  11.     }  
  12.     // 循环读取etc/permissions目录下的XML文件  
  13.     for (File f : libraryDir.listFiles()) {  
  14.         // 跳过platform.xml文件,最后读取该文件  
  15.         if (f.getPath().endsWith(“etc/permissions/platform.xml”)) {  
  16.             continue;  
  17.         }  
  18.         if (!f.getPath().endsWith(“.xml”)) {  
  19.             Slog.i(TAG, “Non-xml file “ + f + ” in “ + libraryDir + ” directory, ignoring”);  
  20.             continue;  
  21.         }  
  22.         if (!f.canRead()) {  
  23.             Slog.w(TAG, “Permissions library file “ + f + ” cannot be read”);  
  24.             continue;  
  25.         }  
  26.         readPermissionsFromXml(f);  
  27.     }  
  28.     // Read permissions from …/etc/permissions/platform.xml last so it will take precedence  
  29.     final File permFile = new File(Environment.getRootDirectory(),“etc/permissions/platform.xml”);  
  30.     readPermissionsFromXml(permFile);  
  31. }  

函数readPermissionsFromXml使用PULL方式解析这些XML文件,下面分别介绍各个标签的解析过程。

feature标签用来描述设备应该支持的硬件特性。解析过程如下:

[java]
view plain
copy
print
?

  1. else if (“feature”.equals(name)) {  
  2.     //读取熟悉name的值  
  3.     String fname = parser.getAttributeValue(null“name”);  
  4.     if (fname == null) {  
  5.         Slog.w(TAG, “<feature> without name at “+ parser.getPositionDescription());  
  6.     } else {  
  7.         //创建一个FeatureInfo对象  
  8.         FeatureInfo fi = new FeatureInfo();  
  9.         fi.name = fname;  
  10.         //mAvailableFeatures是PackageManagerService的成员变量,以HashMap的方式保存硬件支持的特性  
  11.         mAvailableFeatures.put(fname, fi);  
  12.     }  
  13.     XmlUtils.skipCurrentTag(parser);  
  14.     continue;  
  15. }  

 

library用于指定系统库,当应用程序运行时,系统会为进程加载一些必要库。该标签的解析过程如下:

[java]
view plain
copy
print
?

  1. else if (“library”.equals(name)) {  
  2.     //读取属性name的值  
  3.     String lname = parser.getAttributeValue(null“name”);  
  4.     //读取属性file的值  
  5.     String lfile = parser.getAttributeValue(null“file”);  
  6.     if (lname == null) {  
  7.         Slog.w(TAG, “<library> without name at “+ parser.getPositionDescription());  
  8.     } else if (lfile == null) {  
  9.         Slog.w(TAG, “<library> without file at “+ parser.getPositionDescription());  
  10.     } else {  
  11.         //mSharedLibraries是PackageManagerService的成员变量,以HashMap的形式保存进程运行库  
  12.         mSharedLibraries.put(lname, lfile);  
  13.     }  
  14.     XmlUtils.skipCurrentTag(parser);  
  15.     continue;  
  16. }  

 

其他的见代码。。。。

===============================================================================

读取package信息

/data/system/packages.xml文件用于记录系统中所安装的Package信息;/data/system/packages-backup.xml文件是/data/packages.xml文件的备份。在PackageManagerService扫描完目标文件夹后会创建该文件,当系统进行程序安装卸载时会更新该文件。
/data/system/packages-stopped.xml文件用于记录系统中强制停止运行的Package信息。/data/system/packages-stopped-backup.xml是/data/packages-stopped.xml文件的备份。在强制停止某个应用时,会将应用相关信息记录到该文件中。
/data/system/packages.list保存系统中存在的所有非系统自带的APK信息。

当系统第一次开机时,这些文件并不存在,而在以后的开机中,扫描到的这些XML文件是上一次运行过程中创建的。

[java]
view plain
copy
print
?

  1. boolean readLPw(List<UserInfo> users) {  
  2.     FileInputStream str = null;  
  3.     //如果/data/system/packages-backup.xml文件存在  
  4.     if (mBackupSettingsFilename.exists()) {  
  5.         try {  
  6.             //读取/data/system/packages-backup.xml文件  
  7.             str = new FileInputStream(mBackupSettingsFilename);  
  8.             mReadMessages.append(“Reading from backup settings file\n”);  
  9.             PackageManagerService.reportSettingsProblem(Log.INFO,“Need to read from backup settings file”);  
  10.             //当/data/system/packages.xml文件的备份文件存在时,删除packages.xml文件  
  11.             if (mSettingsFilename.exists()) {  
  12.                 Slog.w(PackageManagerService.TAG, “Cleaning up settings file “+ mSettingsFilename);  
  13.                 mSettingsFilename.delete();  
  14.             }  
  15.         } catch (java.io.IOException e) {  
  16.             // We’ll try for the normal settings file.  
  17.         }  
  18.     }  
  19.     mPendingPackages.clear();  
  20.     mPastSignatures.clear();  
  21.     try {  
  22.         //如果/data/system/packages-backup.xml文件为空  
  23.         if (str == null) {  
  24.             //同时/data/system/packages.xml文件不存在  
  25.             if (!mSettingsFilename.exists()) {  
  26.                 mReadMessages.append(“No settings file found\n”);  
  27.                 PackageManagerService.reportSettingsProblem(Log.INFO,  
  28.                         “No settings file; creating initial state”);  
  29.                 //读取/etc/preferred-apps目录下的xml文件  
  30.                 readDefaultPreferredAppsLPw();  
  31.                 return false;  
  32.             }  
  33.             //如果packages.xml的备份文件为空,读取packages.xml文件内容  
  34.             str = new FileInputStream(mSettingsFilename);  
  35.         }  
  36.         //解析文件内容  
  37.         XmlPullParser parser = Xml.newPullParser();  
  38.         parser.setInput(str, null);  
  39.         int type;  
  40.         while ((type = parser.next()) != XmlPullParser.START_TAG  
  41.                 && type != XmlPullParser.END_DOCUMENT) {  
  42.             ;  
  43.         }  
  44.         …  
  45. }  

 

接下来检测并优化BOOTCLASSPATH环境变量指定的Java运行库及platform.xml中配置的Java库,同时优化/system/framework目录下的Jar包和apk文件,最后删除/data/dalvik-cache目录下的一些缓存文件。在init.rc中配置的BOOTCLASSPATH如下:

  1. long startTime = SystemClock.uptimeMillis();  
  2. EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,startTime);  
  3. // 设置扫描模式  
  4. int scanMode = SCAN_MONITOR | SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING;  
  5. if (mNoDexOpt) {  
  6.     Slog.w(TAG, “Running ENG build: no pre-dexopt!”);  
  7.     scanMode |= SCAN_NO_DEX;  
  8. }  
  9. //保存库文件路径  
  10. final HashSet<String> libFiles = new HashSet<String>();  
  11. //mFrameworkDir = /framework/  
  12. mFrameworkDir = new File(Environment.getRootDirectory(), “framework”);  
  13. //mDalvikCacheDir = /data/dalvik-cache/  
  14. mDalvikCacheDir = new File(dataDir, “dalvik-cache”);  
  15. boolean didDexOpt = false;  
  16. //通过属性的方式得到启动Java启动类库的路径,在init.rc中通过BOOTCLASSPATH环境变量的方式设置  
  17. String bootClassPath = System.getProperty(“java.boot.class.path”);  
  18. if (bootClassPath != null) {  
  19.     String[] paths = splitString(bootClassPath, ‘:’);  
  20.     for (int i=0; i<paths.length; i++) {  
  21.         try {  
  22.             //判断Jar包是否需要dex优化  
  23.             if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {  
  24.                 //如果需要则添加到libFiles表中  
  25.                 libFiles.add(paths[i]);  
  26.                 //通过安装器请求installd服务进程执行dex优化  
  27.                 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);  
  28.                 didDexOpt = true;  
  29.             }  
  30.         } catch (FileNotFoundException e) {  
  31.             Slog.w(TAG, “Boot class path not found: “ + paths[i]);  
  32.         } catch (IOException e) {  
  33.             Slog.w(TAG, “Cannot dexopt “ + paths[i] + “; is it an APK or JAR? “  
  34.                     + e.getMessage());  
  35.         }  
  36.     }  
  37. else {  
  38.     Slog.w(TAG, “No BOOTCLASSPATH found!”);  
  39. }  
  40. //在前面解析platfor.xml时,将一些额外的类库路径保存到了mSharedLibraries变量中  
  41. if (mSharedLibraries.size() > 0) {  
  42.     //循环变量mSharedLibraries变量  
  43.     Iterator<String> libs = mSharedLibraries.values().iterator();  
  44.     while (libs.hasNext()) {  
  45.         String lib = libs.next();  
  46.         try {  
  47.             //判断Jar包是否需要dex优化  
  48.             if (dalvik.system.DexFile.isDexOptNeeded(lib)) {  
  49.                 //如果需要则添加到libFiles表中  
  50.                 libFiles.add(lib);  
  51.                 //通过安装器进行dex优化  
  52.                 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);  
  53.                 didDexOpt = true;  
  54.             }  
  55.         } catch (FileNotFoundException e) {  
  56.             Slog.w(TAG, “Library not found: “ + lib);  
  57.         } catch (IOException e) {  
  58.             Slog.w(TAG, “Cannot dexopt “ + lib + “; is it an APK or JAR? “  
  59.                     + e.getMessage());  
  60.         }  
  61.     }  
  62. }  
  63. //将/system/frameworks/framework-res.apk添加到libFiles中  
  64. libFiles.add(mFrameworkDir.getPath() + “/framework-res.apk”);  
  65. //列出/system/frameworks目录下的文件  
  66. String[] frameworkFiles = mFrameworkDir.list();  
  67. if (frameworkFiles != null) {  
  68.     //遍历/system/frameworks目录下的文件  
  69.     for (int i=0; i<frameworkFiles.length; i++) {  
  70.         File libPath = new File(mFrameworkDir, frameworkFiles[i]);  
  71.         String path = libPath.getPath();  
  72.         //判断libFiles中是否已经包含该文件,如果包含则跳过  
  73.         if (libFiles.contains(path)) {  
  74.             continue;  
  75.         }  
  76.         //跳过不是apk或jar文件  
  77.         if (!path.endsWith(“.apk”) && !path.endsWith(“.jar”)) {  
  78.             continue;  
  79.         }  
  80.         try {  
  81.             //判断Jar包或apk是否需要dex优化  
  82.             if (dalvik.system.DexFile.isDexOptNeeded(path)) {  
  83.                 //通过安装器进行dex优化  
  84.                 mInstaller.dexopt(path, Process.SYSTEM_UID, true);  
  85.                 didDexOpt = true;  
  86.             }  
  87.         } catch (FileNotFoundException e) {  
  88.             Slog.w(TAG, “Jar not found: “ + path);  
  89.         } catch (IOException e) {  
  90.             Slog.w(TAG, “Exception reading jar: “ + path, e);  
  91.         }  
  92.     }  
  93. }  
  94. //如果前面对某个文件做过优化,只要优化了,didDexOpt就被设置为true  
  95. if (didDexOpt) {  
  96.     //遍历/data/dalvik-cache目录下的文件  
  97.     String[] files = mDalvikCacheDir.list();  
  98.     if (files != null) {  
  99.         for (int i=0; i<files.length; i++) {  
  100.             String fn = files[i];  
  101.             //删除文件名以”data@app@”和”data@app-private@”开头的文件  
  102.             if (fn.startsWith(“data@app@”)  
  103.                     || fn.startsWith(“data@app-private@”)) {  
  104.                 Slog.i(TAG, “Pruning dalvik file: “ + fn);  
  105.                 (new File(mDalvikCacheDir, fn)).delete();  
  106.             }  
  107.         }  
  108.     }  
  109. }  
long startTime = SystemClock.uptimeMillis();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,startTime);
// 设置扫描模式
int scanMode = SCAN_MONITOR | SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING;
if (mNoDexOpt) {
	Slog.w(TAG, "Running ENG build: no pre-dexopt!");
	scanMode |= SCAN_NO_DEX;
}
//保存库文件路径
final HashSet<String> libFiles = new HashSet<String>();
//mFrameworkDir = /framework/
mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
//mDalvikCacheDir = /data/dalvik-cache/
mDalvikCacheDir = new File(dataDir, "dalvik-cache");
boolean didDexOpt = false;
//通过属性的方式得到启动Java启动类库的路径,在init.rc中通过BOOTCLASSPATH环境变量的方式设置
String bootClassPath = System.getProperty("java.boot.class.path");
if (bootClassPath != null) {
	String[] paths = splitString(bootClassPath, ':');
	for (int i=0; i<paths.length; i++) {
		try {
			//判断Jar包是否需要dex优化
			if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
				//如果需要则添加到libFiles表中
				libFiles.add(paths[i]);
				//通过安装器请求installd服务进程执行dex优化
				mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
				didDexOpt = true;
			}
		} catch (FileNotFoundException e) {
			Slog.w(TAG, "Boot class path not found: " + paths[i]);
		} catch (IOException e) {
			Slog.w(TAG, "Cannot dexopt " + paths[i] + "; is it an APK or JAR? "
					+ e.getMessage());
		}
	}
} else {
	Slog.w(TAG, "No BOOTCLASSPATH found!");
}
//在前面解析platfor.xml时,将一些额外的类库路径保存到了mSharedLibraries变量中
if (mSharedLibraries.size() > 0) {
	//循环变量mSharedLibraries变量
	Iterator<String> libs = mSharedLibraries.values().iterator();
	while (libs.hasNext()) {
		String lib = libs.next();
		try {
			//判断Jar包是否需要dex优化
			if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
				//如果需要则添加到libFiles表中
				libFiles.add(lib);
				//通过安装器进行dex优化
				mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
				didDexOpt = true;
			}
		} 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());
		}
	}
}
//将/system/frameworks/framework-res.apk添加到libFiles中
libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
//列出/system/frameworks目录下的文件
String[] frameworkFiles = mFrameworkDir.list();
if (frameworkFiles != null) {
	//遍历/system/frameworks目录下的文件
	for (int i=0; i<frameworkFiles.length; i++) {
		File libPath = new File(mFrameworkDir, frameworkFiles[i]);
		String path = libPath.getPath();
		//判断libFiles中是否已经包含该文件,如果包含则跳过
		if (libFiles.contains(path)) {
			continue;
		}
		//跳过不是apk或jar文件
		if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
			continue;
		}
		try {
			//判断Jar包或apk是否需要dex优化
			if (dalvik.system.DexFile.isDexOptNeeded(path)) {
				//通过安装器进行dex优化
				mInstaller.dexopt(path, Process.SYSTEM_UID, true);
				didDexOpt = true;
			}
		} catch (FileNotFoundException e) {
			Slog.w(TAG, "Jar not found: " + path);
		} catch (IOException e) {
			Slog.w(TAG, "Exception reading jar: " + path, e);
		}
	}
}
//如果前面对某个文件做过优化,只要优化了,didDexOpt就被设置为true
if (didDexOpt) {
	//遍历/data/dalvik-cache目录下的文件
	String[] files = mDalvikCacheDir.list();
	if (files != null) {
		for (int i=0; i<files.length; i++) {
			String fn = files[i];
			//删除文件名以"data@app@"和"data@app-private@"开头的文件
			if (fn.startsWith("data@app@")
					|| fn.startsWith("data@app-private@")) {
				Slog.i(TAG, "Pruning dalvik file: " + fn);
				(new File(mDalvikCacheDir, fn)).delete();
			}
		}
	}
}

接着扫描系统apk信息

[java]
view plain
copy
print
?

  1. mFlagInstall = false;  
  2. //创建文件夹监控对象,监视/system/framework目录  
  3. mFrameworkInstallObserver = new AppDirObserver(mFrameworkDir.getPath(), OBSERVER_EVENTS, true);  
  4. mFrameworkInstallObserver.startWatching();  
  5. //扫描/system/framework目录下的apk文件,扫描模式设置为非优化模式  
  6. scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM| PackageParser.PARSE_IS_SYSTEM_DIR,scanMode | SCAN_NO_DEX, 0);  
  7. //在工厂模式下,调用函数scanDirLIOnly只扫描特定的apk文件  
  8. if(engModeEnable){  
  9.     //temp null  
  10.     mVendorAppDir = null;  
  11.     mDrmAppInstallObserver = null;  
  12.     mSystemAppDir = null;  
  13.     mAppInstallObserver = null;  
  14.     mSystemInstallObserver = null;  
  15.     mPreInstallObserver = null;  
  16.     mVendorInstallObserver = null;  
  17.     mAppInstallDir = null;  
  18.     Slog.i(TAG, ” begin scan the apps !”);  
  19.     scanDirLIOnly(PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);  
  20.     Slog.i(TAG, ” end scan the apps !”);  
  21.     engModeEnable = false;  
  22. }else{//正常模式下  
  23.     //创建文件夹监控对象,监视/system/app目录  
  24.     mSystemAppDir = new File(Environment.getRootDirectory(), “app”);  
  25.     mSystemInstallObserver = new AppDirObserver(  
  26.         mSystemAppDir.getPath(), OBSERVER_EVENTS, true);  
  27.     mSystemInstallObserver.startWatching();  
  28.     //扫描/system/app目录  
  29.     scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);  
  30.     //创建文件夹监控对象,监视/vendor/app目录  
  31.     mVendorAppDir = new File(“/vendor/app”);  
  32.     mVendorInstallObserver = new AppDirObserver(  
  33.         mVendorAppDir.getPath(), OBSERVER_EVENTS, true);  
  34.     mVendorInstallObserver.startWatching();  
  35.     //扫描/vendor/app目录  
  36.     scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);  
  37.   
  38.     if (DEBUG_UPGRADE) Log.v(TAG, “Running installd update commands”);  
  39.     mInstaller.moveFiles();  
  40.     // Prune any system packages that no longer exist.  
  41.     final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();  
  42.     if (!mOnlyCore) {  
  43.         //遍历Settings的成员变量mPackages  
  44.         Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();  
  45.         while (psit.hasNext()) {  
  46.             PackageSetting ps = psit.next();  
  47.             //不是系统app  
  48.             if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {  
  49.                 continue;  
  50.             }  
  51.             //如果是系统app,同时已经被PackageManagerService扫描过了  
  52.             final PackageParser.Package scannedPkg = mPackages.get(ps.name);  
  53.             if (scannedPkg != null) {  
  54.                 //该apk包已不能使用  
  55.                 if (mSettings.isDisabledSystemPackageLPr(ps.name)) {  
  56.                     Slog.i(TAG, “Expecting better updatd system app for “ + ps.name  
  57.                             + “; removing system app”);  
  58.                     //移除该apk包信息  
  59.                     removePackageLI(scannedPkg, true);  
  60.                 }  
  61.                 continue;  
  62.             }  
  63.             if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {  
  64.                 psit.remove();  
  65.                 String msg = “System package “ + ps.name  
  66.                         + ” no longer exists; wiping its data”;  
  67.                 reportSettingsProblem(Log.WARN, msg);  
  68.                 mInstaller.remove(ps.name, 0);  
  69.                 sUserManager.removePackageForAllUsers(ps.name);  
  70.             } else {  
  71.                 final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);  
  72.                 if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {  
  73.                     possiblyDeletedUpdatedSystemApps.add(ps.name);  
  74.                 }  
  75.             }  
  76.         }  
  77.     }  
  78.     //mAppInstallDir = /data/app/  
  79.     mAppInstallDir = new File(dataDir, “app”);  
  80.     //查找未完成安装的apk包  
  81.     ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();  
  82.     //清除未完成安装包  
  83.     for(int i = 0; i < deletePkgsList.size(); i++) {  
  84.         //clean up here  
  85.         cleanupInstallFailedPackage(deletePkgsList.get(i));  
  86.     }  
  87.     //删除临时文件  
  88.     deleteTempPackageFiles();  
mFlagInstall = false;
//创建文件夹监控对象,监视/system/framework目录
mFrameworkInstallObserver = new AppDirObserver(mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
mFrameworkInstallObserver.startWatching();
//扫描/system/framework目录下的apk文件,扫描模式设置为非优化模式
scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM| PackageParser.PARSE_IS_SYSTEM_DIR,scanMode | SCAN_NO_DEX, 0);
//在工厂模式下,调用函数scanDirLIOnly只扫描特定的apk文件
if(engModeEnable){
	//temp null
	mVendorAppDir = null;
	mDrmAppInstallObserver = null;
	mSystemAppDir = null;
	mAppInstallObserver = null;
	mSystemInstallObserver = null;
	mPreInstallObserver = null;
	mVendorInstallObserver = null;
	mAppInstallDir = null;
	Slog.i(TAG, " begin scan the apps !");
	scanDirLIOnly(PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
	Slog.i(TAG, " end scan the apps !");
	engModeEnable = false;
}else{//正常模式下
	//创建文件夹监控对象,监视/system/app目录
	mSystemAppDir = new File(Environment.getRootDirectory(), "app");
	mSystemInstallObserver = new AppDirObserver(
		mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
	mSystemInstallObserver.startWatching();
	//扫描/system/app目录
	scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
	//创建文件夹监控对象,监视/vendor/app目录
	mVendorAppDir = new File("/vendor/app");
	mVendorInstallObserver = new AppDirObserver(
		mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
	mVendorInstallObserver.startWatching();
	//扫描/vendor/app目录
	scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);

	if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
	mInstaller.moveFiles();
	// Prune any system packages that no longer exist.
	final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
	if (!mOnlyCore) {
		//遍历Settings的成员变量mPackages
		Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
		while (psit.hasNext()) {
			PackageSetting ps = psit.next();
			//不是系统app
			if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
				continue;
			}
			//如果是系统app,同时已经被PackageManagerService扫描过了
			final PackageParser.Package scannedPkg = mPackages.get(ps.name);
			if (scannedPkg != null) {
				//该apk包已不能使用
				if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
					Slog.i(TAG, "Expecting better updatd system app for " + ps.name
							+ "; removing system app");
					//移除该apk包信息
					removePackageLI(scannedPkg, true);
				}
				continue;
			}
			if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
				psit.remove();
				String msg = "System package " + ps.name
						+ " no longer exists; wiping its data";
				reportSettingsProblem(Log.WARN, msg);
				mInstaller.remove(ps.name, 0);
				sUserManager.removePackageForAllUsers(ps.name);
			} else {
				final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
				if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
					possiblyDeletedUpdatedSystemApps.add(ps.name);
				}
			}
		}
	}
	//mAppInstallDir = /data/app/
	mAppInstallDir = new File(dataDir, "app");
	//查找未完成安装的apk包
	ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
	//清除未完成安装包
	for(int i = 0; i < deletePkgsList.size(); i++) {
		//clean up here
		cleanupInstallFailedPackage(deletePkgsList.get(i));
	}
	//删除临时文件
	deleteTempPackageFiles();

 

监控并扫描以下三个系统包安装目录:

/system/framework :该目录下的文件都是系统库

/system/app :该目录下是默认的系统应用

/vendor/app :该目录下是厂商定制的应用

最后扫描非系统apk信息

[java]
view plain
copy
print
?

  1. if (!mOnlyCore) {  
  2.     //标识数据扫描开始  EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,SystemClock.uptimeMillis());  
  3.     //创建文件夹监控对象,监视/data/app/目录  
  4.     mAppInstallObserver = new AppDirObserver(mAppInstallDir.getPath(), OBSERVER_EVENTS, false);  
  5.     mAppInstallObserver.startWatching();  
  6.     //扫描/data/app/目录下的apk文件  
  7.     scanDirLI(mAppInstallDir, 0, scanMode, 0);  
  8.     //创建文件夹监控对象,监视/system/preloadapp/目录  
  9.     mPreInstallObserver = new AppDirObserver(mPreInstallDir.getPath(), OBSERVER_EVENTS, false);  
  10.     mPreInstallObserver.startWatching();  
  11.     //扫描/system/preloadapp/目录下的apk文件  
  12.     scanDirLI(mPreInstallDir, 0, scanMode, 0);  
  13.     //创建文件夹监控对象,监视/data/app-private/目录  
  14.     mDrmAppInstallObserver = new AppDirObserver(mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);  
  15.     mDrmAppInstallObserver.startWatching();  
  16.     //扫描/data/app-private/目录下的apk文件  
  17.     scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,scanMode, 0);  
  18.     /** 
  19.      * Remove disable package settings for any updated system 
  20.      * apps that were removed via an OTA. If they’re not a 
  21.      * previously-updated app, remove them completely. 
  22.      * Otherwise, just revoke their system-level permissions. 
  23.      */  
  24.     for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {  
  25.         PackageParser.Package deletedPkg = mPackages.get(deletedAppName);  
  26.         mSettings.removeDisabledSystemPackageLPw(deletedAppName);  
  27.         String msg;  
  28.         if (deletedPkg == null) {  
  29.             msg = “Updated system package “ + deletedAppName+ ” no longer exists; wiping its data”;  
  30.             mInstaller.remove(deletedAppName, 0);  
  31.             sUserManager.removePackageForAllUsers(deletedAppName);  
  32.         } else {  
  33.             msg = “Updated system app + “ + deletedAppName+ ” no longer present; removing system privileges for “+ deletedAppName;  
  34.             deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;  
  35.             PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);  
  36.             deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;  
  37.         }  
  38.         reportSettingsProblem(Log.WARN, msg);  
  39.     }  
  40. else {  
  41.     mPreInstallObserver = null;  
  42.     mAppInstallObserver = null;  
  43.     mDrmAppInstallObserver = null;  
  44. }  
if (!mOnlyCore) {
	//标识数据扫描开始	EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,SystemClock.uptimeMillis());
	//创建文件夹监控对象,监视/data/app/目录
	mAppInstallObserver = new AppDirObserver(mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
	mAppInstallObserver.startWatching();
	//扫描/data/app/目录下的apk文件
	scanDirLI(mAppInstallDir, 0, scanMode, 0);
	//创建文件夹监控对象,监视/system/preloadapp/目录
	mPreInstallObserver = new AppDirObserver(mPreInstallDir.getPath(), OBSERVER_EVENTS, false);
	mPreInstallObserver.startWatching();
	//扫描/system/preloadapp/目录下的apk文件
	scanDirLI(mPreInstallDir, 0, scanMode, 0);
	//创建文件夹监控对象,监视/data/app-private/目录
	mDrmAppInstallObserver = new AppDirObserver(mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
	mDrmAppInstallObserver.startWatching();
	//扫描/data/app-private/目录下的apk文件
	scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,scanMode, 0);
	/**
	 * Remove disable package settings for any updated system
	 * apps that were removed via an OTA. If they're not a
	 * previously-updated app, remove them completely.
	 * Otherwise, just revoke their system-level permissions.
	 */
	for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
		PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
		mSettings.removeDisabledSystemPackageLPw(deletedAppName);
		String msg;
		if (deletedPkg == null) {
			msg = "Updated system package " + deletedAppName+ " no longer exists; wiping its data";
			mInstaller.remove(deletedAppName, 0);
			sUserManager.removePackageForAllUsers(deletedAppName);
		} else {
			msg = "Updated system app + " + deletedAppName+ " no longer present; removing system privileges for "+ deletedAppName;
			deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
			PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
			deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
		}
		reportSettingsProblem(Log.WARN, msg);
	}
} else {
	mPreInstallObserver = null;
	mAppInstallObserver = null;
	mDrmAppInstallObserver = null;
}

 

监控并扫描以下三个数据目录:

/data/app/

/system/preloadapp/

/data/app-private/

最后进入结尾阶段,将扫描到的信息保存到文件中。

[java]
view plain
copy
print
?

  1. mFlagInstall = true;  
  2. EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,SystemClock.uptimeMillis());  
  3. final boolean regrantPermissions = mSettings.mInternalSdkPlatform != mSdkVersion;  
  4. mSettings.mInternalSdkPlatform = mSdkVersion;  
  5. updatePermissionsLPw(nullnull, UPDATE_PERMISSIONS_ALL | (regrantPermissions  
  6.                 ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL): 0));  
  7. ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();  
  8. for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) {  
  9.     if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {  
  10.         removed.add(pa);  
  11.     }  
  12. }  
  13. for (int i=0; i<removed.size(); i++) {  
  14.     PreferredActivity pa = removed.get(i);  
  15.     Slog.w(TAG, “Removing dangling preferred activity: “  
  16.             + pa.mPref.mComponent);  
  17.     mSettings.mPreferredActivities.removeFilter(pa);  
  18. }  
  19. // can downgrade to reader  
  20. mSettings.writeLPr();  
  21.   
  22. EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,SystemClock.uptimeMillis());  
  23. Runtime.getRuntime().gc();  
  24. mRequiredVerifierPackage = getRequiredVerifierLPr();  
mFlagInstall = true;
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,SystemClock.uptimeMillis());
final boolean regrantPermissions = mSettings.mInternalSdkPlatform != mSdkVersion;
mSettings.mInternalSdkPlatform = mSdkVersion;
updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL | (regrantPermissions
				? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL): 0));
ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) {
	if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
		removed.add(pa);
	}
}
for (int i=0; i<removed.size(); i++) {
	PreferredActivity pa = removed.get(i);
	Slog.w(TAG, "Removing dangling preferred activity: "
			+ pa.mPref.mComponent);
	mSettings.mPreferredActivities.removeFilter(pa);
}
// can downgrade to reader
mSettings.writeLPr();

EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,SystemClock.uptimeMillis());
Runtime.getRuntime().gc();
mRequiredVerifierPackage = getRequiredVerifierLPr();

至此,PackageManagerService就构造完成了,构造过程认为繁重,Apk文件扫描解析耗费比较长的时间,这是导致开机速度慢的原因。

    原文作者:Fate_I_C
    原文地址: https://blog.csdn.net/kagoy/article/details/16355507
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞