PackageManagerService启动及初始化流程

PackageManagerService也是有ServerThread启动的,运行在system_process进程。

我们先来看下PackageManagerService是怎么启动的:

PackageManagerService启动及初始化流程_第1张图片

PackageManagerService的启动需要四个参数,context上下文环境信息由ActivityManagerService获取,installer是一个安装器,是对install程序的一个封装,在new一个Installer之后会调用ping命令测试是否能连接的上install的服务端。

再来看一下PackageManagerService的初始化流程:

PackageManagerService启动及初始化流程_第2张图片

相关代码:

public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
                SystemClock.uptimeMillis());

        if (mSdkVersion <= 0) {
            Slog.w(TAG, "**** ro.build.version.sdk not set!");
        }

        mContext = context;
        mFactoryTest = factoryTest;
        mOnlyCore = onlyCore;
        mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
        mMetrics = new DisplayMetrics();
        mSettings = new Settings(context);//新建一个Settings结构
        mSettings.addSharedUserLPw("android.uid.system", //添加一些用户id
                Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
        mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, ApplicationInfo.FLAG_SYSTEM);
        mSettings.addSharedUserLPw("android.uid.log", LOG_UID, ApplicationInfo.FLAG_SYSTEM);
        mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID, ApplicationInfo.FLAG_SYSTEM);
        mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID, ApplicationInfo.FLAG_SYSTEM);

        String separateProcesses = SystemProperties.get("debug.separate_processes");
        if (separateProcesses != null && separateProcesses.length() > 0) {
            if ("*".equals(separateProcesses)) {
                mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
                mSeparateProcesses = null;
                Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
            } else {
                mDefParseFlags = 0;
                mSeparateProcesses = separateProcesses.split(",");
                Slog.w(TAG, "Running with debug.separate_processes: "
                        + separateProcesses);
            }
        } else {
            mDefParseFlags = 0;
            mSeparateProcesses = null;
        }

        mInstaller = installer;//在ServerThread中创建,调用了其中的ping测试是否连上

        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);//获取WINDOW_SERVICE
        Display d = wm.getDefaultDisplay();//获取显示参数
        d.getMetrics(mMetrics);

        synchronized (mInstallLock) {
        // writer
        synchronized (mPackages) {
            mHandlerThread.start();//启动消息处理循环
            mHandler = new PackageHandler(mHandlerThread.getLooper());//PackageHandler封装了对消息的处理

            File dataDir = Environment.getDataDirectory();///data
            mAppDataDir = new File(dataDir, "data");//待检测目录/data/data
            mAppInstallDir = new File(dataDir, "app");///data/app
            mAppLibInstallDir = new File(dataDir, "app-lib");///data/app-lib
            mAsecInternalPath = new File(dataDir, "app-asec").getPath();///data/app-asec
            mUserAppDataDir = new File(dataDir, "user");///data/user
            mDrmAppPrivateInstallDir = new File(dataDir, "app-private");///data/app-private

            sUserManager = new UserManagerService(context, this,
                    mInstallLock, mPackages);//创建一个UserManagerService

            readPermissions();//读取权限配置文件中的信息,保存到全局变量

            mRestoredSettings = mSettings.readLPw(sUserManager.getUsers(false));
            long startTime = SystemClock.uptimeMillis();

            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
                    startTime);

            // Set flag to monitor and not change apk file paths when
            // scanning install directories.
            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 libFiles = new HashSet();

            mFrameworkDir = new File(Environment.getRootDirectory(), "framework");///system/framework
            mDalvikCacheDir = new File(dataDir, "dalvik-cache");///data/dalvik-cache

            boolean didDexOpt = false;

            /**
             * Out of paranoia, ensure that everything in the boot class
             * path has been dexed.
             */
            String bootClassPath = System.getProperty("java.boot.class.path");//所有在bootClassPath目录的类已经优化了
            if (bootClassPath != null) {//确保 boot路径的class都被优化了
                String[] paths = splitString(bootClassPath, ':');
                for (int i=0; i 0) {//确保 外部库也被 优化
                Iterator libs = mSharedLibraries.values().iterator();
                while (libs.hasNext()) {
                    String lib = libs.next();
                    try {
                        if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
                            libFiles.add(lib);
                            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());
                    }
                }
            }

            // Gross hack for now: we know this file doesn't contain any
            // code, so don't dexopt it to avoid the resulting log spew.
            libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");//framework-res.apk没有包含代码,不需要优化

            /**
             * And there are a number of commands implemented in Java, which
             * we currently need to do the dexopt on so that they can be
             * run from a non-root shell.
             */
            String[] frameworkFiles = mFrameworkDir.list();
            if (frameworkFiles != null) {
                for (int i=0; i possiblyDeletedUpdatedSystemApps = new ArrayList();
            if (!mOnlyCore) {
                Iterator psit = mSettings.mPackages.values().iterator();
                while (psit.hasNext()) {
                    PackageSetting ps = psit.next();

                    /*
                     * If this is not a system app, it can't be a
                     * disable system app.
                     */
                    if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {//系统app
                        continue;
                    }

                    /*
                     * If the package is scanned, it's not erased.
                     */
                    final PackageParser.Package scannedPkg = mPackages.get(ps.name);
                    if (scannedPkg != null) {
                        /*
                         * If the system app is both scanned and in the
                         * disabled packages list, then it must have been
                         * added via OTA. Remove it from the currently
                         * scanned package so the previously user-installed
                         * application can be scanned.
                         *///如果系统app刚被扫描并且在disabled列表,则它肯定是通过ota添加的,从当前扫描的package中移除它,所以以前用户安装的可以被扫描到
                        if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
                            Slog.i(TAG, "Expecting better updatd system app for " + ps.name
                                    + "; removing system app");
                            removePackageLI(ps, 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);
                        removeDataDirsLI(ps.name);
                    } else {
                        final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
                        if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
                            possiblyDeletedUpdatedSystemApps.add(ps.name);
                        }
                    }
                }
            }

            //look for any incomplete package installations未安装完全的package
            ArrayList deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
            //clean up list
            for(int i = 0; i < deletePkgsList.size(); i++) {
                //clean up here
                cleanupInstallFailedPackage(deletePkgsList.get(i));//移除安装失败的package
            }
            //delete tmp files
            deleteTempPackageFiles();//移除临时文件

            if (!mOnlyCore) {
                EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                        SystemClock.uptimeMillis());
                mAppInstallObserver = new AppDirObserver(
                    mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
                mAppInstallObserver.startWatching();//监控/data/app目录
                scanDirLI(mAppInstallDir, 0, scanMode, 0);//扫描该目录下的package
    
                mDrmAppInstallObserver = new AppDirObserver( //DRM,英文全称Digital Rights Management, 可以翻译为:内容数字版权加密保护技术
                    mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
                mDrmAppInstallObserver.startWatching();//监控/data/app-private目录
                scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,//扫描该目录下的package
                        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";
                        removeDataDirsLI(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 {
                mAppInstallObserver = null;
                mDrmAppInstallObserver = null;
            }

            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
                    SystemClock.uptimeMillis());
            Slog.i(TAG, "Time to scan packages: "
                    + ((SystemClock.uptimeMillis()-startTime)/1000f)
                    + " seconds");

            // If the platform SDK has changed since the last time we booted,
            // we need to re-grant app permission to catch any new ones that
            // appear.  This is really a hack, and means that apps can in some
            // cases get permissions that the user didn't initially explicitly
            // allow...  it would be nice to have some better way to handle
            // this situation.
            final boolean regrantPermissions = mSettings.mInternalSdkPlatform
                    != mSdkVersion;
            if (regrantPermissions) Slog.i(TAG, "Platform changed from "
                    + mSettings.mInternalSdkPlatform + " to " + mSdkVersion
                    + "; regranting permissions for internal storage");
            mSettings.mInternalSdkPlatform = mSdkVersion;
            
            updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL //赋予package相应请求的权限
                    | (regrantPermissions
                            ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
                            : 0));

            // can downgrade to reader
            mSettings.writeLPr();//写/data/system/packages.xml

            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                    SystemClock.uptimeMillis());

            // Now after opening every single application zip, make sure they
            // are all flushed.  Not really needed, but keeps things nice and
            // tidy.
            Runtime.getRuntime().gc();

            mRequiredVerifierPackage = getRequiredVerifierLPr();
        } // synchronized (mPackages)
        } // synchronized (mInstallLock)
    }

PackageManagerService的初始化工作都是在它的构造函数中完成的,主要完成一下任务:

1、  添加一些用户id,如systemphone;

2、   建立并启动PackageHandler消息循环,用于处理apk安装请求如adbinstall packageinstaller安装apk时就会发送消息;

3、  解析/system/etc/permission下的xml文件,主要是platform.xml,建立permission和gid之间的关系,可以指定一个权限与几个组对应,当一个apk被授予这个权限时它也同时属于这几个组,readPermission(parser, perm);给一些底层用户分配一些权限,如shell授予各种permission,把一个权限赋予一个uid,当apk使用这个uid运行时,就具备了这个权限系统增加的一些应用需要link的扩展的jar库,系统每增加一个硬件,都要添加相应的featrue,将解析结果放入mAvailableFeatures;

4、  检查/data/system/packages.xml是否存在,里面记录了系统的ppermission,以及每个apk的name,codePath,flags,ts,version,userid等,这些信息主要是通过apk安装的时候解析AndroidManifest.xml获取到的,解析完apk后将更新信息写入这个文件并保存到flash,下次开机直接从里面读取相关信息添加到内存相关列表中,当有apk安装,升级,删除时会更新这个文件;

5、  检查BootClassPath,mSharedLibraries及/system/framework下的jar是否需要dexopt,需要则通过dexopt进行优化,这里面主要是调用mInstaller.dexopt进行相应的优化;

6、  建立 java 层的 installer  层的 installd  socket 联接,使得在上层的 install,remove,dexopt等功能最终由installd在底层实现;

7、  启动AppDirObserver线程往中监测/system/framework,/system/app,/data/app/data/app-private目录的事件,主要监听add和remove事件,对于目录监听底层通过innotify机制实现,inotify是一种文件系统的变化通知机制如文件增加、删除等事件可以立刻让用户态得知,它为用户态监视文件系统的变化提供了强大的支持,当有add event时调用scanPackageLI(File,int,int)处理,当有remove event时调用removePackageLI处理;

8、  调用scanDirLI启动apk解析,解析目录包括:/system/framework、/system/app、/vendor/app、/data/app、/data/app-private;

9、  移除临时文件;

10、 赋予package相应请求的权限;

11、 将解析出的Package的相关信息保存到相关全局变量,还有文件。

 

下面来分析前面每一步大概都做了些什么:

一、添加用户:

添加用户调用的是Settings的addSharedUserLPw

 SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags) {
        SharedUserSetting s = mSharedUsers.get(name);
        if (s != null) {
            if (s.userId == uid) {
                return s;
            }
            PackageManagerService.reportSettingsProblem(Log.ERROR,
                    "Adding duplicate shared user, keeping first: " + name);
            return null;
        }
        s = new SharedUserSetting(name, pkgFlags);//新建一个SharedUserSetting结构
        s.userId = uid;
        if (addUserIdLPw(uid, s, name)) {//保存到mUserIds或mOtherUserIds
            mSharedUsers.put(name, s);//添加到mSharedUsers
            return s;
        }
        return null;
}

首先检查mSharedUsers中是否有这个用户,没有的话则新建一个SharedUserSetting,调用addUserIdLPw保存到mUserIds或mOtherUserIds,并添加到mSharedUsers。

  private boolean addUserIdLPw(int uid, Object obj, Object name) {
        if (uid > Process.LAST_APPLICATION_UID) {//大于应用程序最大pid
            return false;
        }

        if (uid >= Process.FIRST_APPLICATION_UID) {//uid大于应用程序id的起始值
            int N = mUserIds.size();
            final int index = uid - Process.FIRST_APPLICATION_UID;
            while (index >= N) {//先添加元素,后面设置值
                mUserIds.add(null);
                N++;
            }
            if (mUserIds.get(index) != null) {
                PackageManagerService.reportSettingsProblem(Log.ERROR,
                        "Adding duplicate user id: " + uid
                        + " name=" + name);
                return false;
            }
            mUserIds.set(index, obj);//把该uid和对应的PackageSetting保存
        } else {//系统用户
            if (mOtherUserIds.get(uid) != null) {
                PackageManagerService.reportSettingsProblem(Log.ERROR,
                        "Adding duplicate shared id: " + uid
                        + " name=" + name);
                return false;
            }
            mOtherUserIds.put(uid, obj);//添加到mOtherUserIds
        }
        return true;
    }

二、建立并启动PackageHandler消息循环

PackageHandler用来处理安装apk等过程中的各种消息,后面降到apk安装的时候会涉及到。

PackageManagerService启动及初始化流程_第3张图片

这个比较简单,主要就新建一个PackageHandler,用来处理消息。


三、解析/system/etc/permission下的xml文件

主要是读取并解析/etc/permissions的xml文件,如我的平板上面:

PackageManagerService启动及初始化流程_第4张图片

看一下读取的流程:

PackageManagerService启动及初始化流程_第5张图片

相关代码:

void readPermissions() {//从/etc/permission读取权限配置信息
        // Read permissions from .../etc/permission directory.
        File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
        if (!libraryDir.exists() || !libraryDir.isDirectory()) {
            Slog.w(TAG, "No directory " + libraryDir + ", skipping");
            return;
        }
        if (!libraryDir.canRead()) {
            Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
            return;
        }

        // Iterate over the files in the directory and scan .xml files
        for (File f : libraryDir.listFiles()) {
            // We'll read platform.xml last
            if (f.getPath().endsWith("etc/permissions/platform.xml")) {
                continue;
            }

            if (!f.getPath().endsWith(".xml")) {
                Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
                continue;
            }
            if (!f.canRead()) {
                Slog.w(TAG, "Permissions library file " + f + " cannot be read");
                continue;
            }

            readPermissionsFromXml(f);
        }

        // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
        final File permFile = new File(Environment.getRootDirectory(),
                "etc/permissions/platform.xml");//最后读取
        readPermissionsFromXml(permFile);
}

readPermissions先读取除platform.xml的其他文件,并调用readPermissionsFromXml进行解析,继续看一下readPermissionsFromXml

 private void readPermissionsFromXml(File permFile) {
        FileReader permReader = null;
        try {
            permReader = new FileReader(permFile);
        } catch (FileNotFoundException e) {
            Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
            return;
        }

        try {
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(permReader);

            XmlUtils.beginDocument(parser, "permissions");

            while (true) {
                XmlUtils.nextElement(parser);
                if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
                    break;
                }

                String name = parser.getName();
                if ("group".equals(name)) {
                    String gidStr = parser.getAttributeValue(null, "gid");
                    if (gidStr != null) {
                        int gid = Integer.parseInt(gidStr);
                        mGlobalGids = appendInt(mGlobalGids, gid);//保存到mGlobalGids
                    } else {
                        Slog.w(TAG, " without gid at "
                                + parser.getPositionDescription());
                    }

                    XmlUtils.skipCurrentTag(parser);
                    continue;
                } else if ("permission".equals(name)) {//定义了权限和组id(gid)的关系,该组拥有什么权限
                    String perm = parser.getAttributeValue(null, "name");//权限地名字
                    if (perm == null) {
                        Slog.w(TAG, " without name at "
                                + parser.getPositionDescription());
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    perm = perm.intern();
                    readPermission(parser, perm);//进一步解析,解析结果保存到 mSettings.mPermissions

                } else if ("assign-permission".equals(name)) {//那一个uid都拥有什么权限(把什么权限赋予哪个uid)
                    String perm = parser.getAttributeValue(null, "name");//获取权限名
                    if (perm == null) {
                        Slog.w(TAG, " without name at "
                                + parser.getPositionDescription());
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    String uidStr = parser.getAttributeValue(null, "uid");//获取用户名
                    if (uidStr == null) {
                        Slog.w(TAG, " without uid at "
                                + parser.getPositionDescription());
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    int uid = Process.getUidForName(uidStr);//该用户名对应的uid
                    if (uid < 0) {
                        Slog.w(TAG, " with unknown uid \""
                                + uidStr + "\" at "
                                + parser.getPositionDescription());
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    perm = perm.intern();
                    HashSet perms = mSystemPermissions.get(uid);//从mSystemPermissions查找是否已为该uid分配权限
                    if (perms == null) {
                        perms = new HashSet();
                        mSystemPermissions.put(uid, perms);//添加到mSystemPermissions
                    }
                    perms.add(perm);//添加 该权限
                    XmlUtils.skipCurrentTag(parser);

                } else if ("library".equals(name)) {//系统共享库
                    String lname = parser.getAttributeValue(null, "name");
                    String lfile = parser.getAttributeValue(null, "file");
                    if (lname == null) {
                        Slog.w(TAG, " without name at "
                                + parser.getPositionDescription());
                    } else if (lfile == null) {
                        Slog.w(TAG, " without file at "
                                + parser.getPositionDescription());
                    } else {
                        //Log.i(TAG, "Got library " + lname + " in " + lfile);
                        mSharedLibraries.put(lname, lfile);//添加到mSharedLibraries
                    }
                    XmlUtils.skipCurrentTag(parser);
                    continue;

                } else if ("feature".equals(name)) {//系统特征 (壁纸等)
                    String fname = parser.getAttributeValue(null, "name");
                    if (fname == null) {
                        Slog.w(TAG, " without name at "
                                + parser.getPositionDescription());
                    } else {
                        //Log.i(TAG, "Got feature " + fname);
                        FeatureInfo fi = new FeatureInfo();
                        fi.name = fname;
                        mAvailableFeatures.put(fname, fi);//添加到mAvailableFeatures
                    }
                    XmlUtils.skipCurrentTag(parser);
                    continue;

                } else {
                    XmlUtils.skipCurrentTag(parser);
                    continue;
                }

            }
            permReader.close();
        } catch (XmlPullParserException e) {
            Slog.w(TAG, "Got execption parsing permissions.", e);
        } catch (IOException e) {
            Slog.w(TAG, "Got execption parsing permissions.", e);
        }
    }

readPermissionsFromXml主要是:

1、读取permission name添加到mSettings.mPermissions
2、读取gid添加到mSettings.mPermissions

readPermissionsFromXml:

permission

a、读取permission name添加到mSettings.mPermissions

b、读取gid添加到mSettings.mPermissions

assign-permission

a、设置相应uid所具有的权限,保存到mSystemPermissions

 library

a、.jar包保存到mSharedLibraries

 feature

a、  硬件相关信息保存到mAvailableFeatures

 

我们来看一下platform.xml:







    
    
    

    

    
        
    

    
        
    

    
        
    

    
        
    

    
        
    

    
        
    

    
        
    

    
        
    

    
        
    

    
        
    

    
        
    

    
        
    

    
    
        
    

    
    
        
        
    

    
    
        
    

    
    
        
    

    
    
    

    

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

    

    

    
    



这个文件是模拟器上的,/etc/permissions下的其他文件还有定义该硬件的特性等。

 

四、解析系统已经安装的包

检查/data/system/packages.xml是否存在,第一次开机的时候该文件不存在,而以后每次系统如果有apk变动如新apk安装、删除、更新等,都会将相关信息记录到该文件。这个会一定程度加快系统的启动速度,但影响不大,先看一下流程图:

PackageManagerService启动及初始化流程_第6张图片

这里把有关setting相关的流程都画出来的,apk信息的读取是通过readLPw来完成的。

  boolean readLPw(List users) {//packages-backup.xml存在则从它读取,不存在在从packages.xml读取
        FileInputStream str = null;
        if (mBackupSettingsFilename.exists()) {///data/system/packages-backup.xml存在
            try {
                str = new FileInputStream(mBackupSettingsFilename);
                mReadMessages.append("Reading from backup settings file\n");
                PackageManagerService.reportSettingsProblem(Log.INFO,
                        "Need to read from backup settings file");
                if (mSettingsFilename.exists()) {///data/system/packages.xml也存在 则删除它
                    // If both the backup and setutings file exist, we
                    // ignore the settings since it might have been
                    // corrupted.
                    Slog.w(PackageManagerService.TAG, "Cleaning up settings file "
                            + mSettingsFilename);
                    mSettingsFilename.delete();
                }
            } catch (java.io.IOException e) {
                // We'll try for the normal settings file.
            }
        }

        mPendingPackages.clear();
        mPastSignatures.clear();

        try {
            if (str == null) {///data/system/packages-backup.xml不存在
                if (!mSettingsFilename.exists()) {//packages.xml不存在则返回
                    mReadMessages.append("No settings file found\n");
                    PackageManagerService.reportSettingsProblem(Log.INFO,
                            "No settings file; creating initial state");
                    readDefaultPreferredAppsLPw(0);
                    return false;
                }
                str = new FileInputStream(mSettingsFilename);//获取一个输入流/data/system/packages.xml
            }
            XmlPullParser parser = Xml.newPullParser();//新建一个xml解析器
            parser.setInput(str, null);//设置解析器的输入流

            int type;
            while ((type = parser.next()) != XmlPullParser.START_TAG
                    && type != XmlPullParser.END_DOCUMENT) {
                ;
            }

            if (type != XmlPullParser.START_TAG) {
                mReadMessages.append("No start tag found in settings file\n");
                PackageManagerService.reportSettingsProblem(Log.WARN,
                        "No start tag found in package manager settings");
                Log.wtf(PackageManagerService.TAG,
                        "No start tag found in package manager settings");
                return false;
            }

            int outerDepth = parser.getDepth();
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                    continue;
                }

                String tagName = parser.getName();
                if (tagName.equals("package")) {//解析系统中存在的package,以及该包的一些相关信息
                    readPackageLPw(parser);
                } else if (tagName.equals("permissions")) {//解析系统定义了哪些权限,由那个包定义的,构建BasePermission结构都添加到mPermissions
                    readPermissionsLPw(mPermissions, parser);
                } else if (tagName.equals("permission-trees")) {
                    readPermissionsLPw(mPermissionTrees, parser);
                } else if (tagName.equals("shared-user")) {//解析系统中可被用户共享的一些uid所拥有的权限
                    readSharedUserLPw(parser);
                } else if (tagName.equals("preferred-packages")) {
                    // no longer used.
                } else if (tagName.equals("preferred-activities")) {
                    // Upgrading from old single-user implementation;
                    // these are the preferred activities for user 0.
                    readPreferredActivitiesLPw(parser, 0);
                } else if (tagName.equals("updated-package")) {//更新的apk
                    readDisabledSysPackageLPw(parser);  
                } else if (tagName.equals("cleaning-package")) {//删除的apk
                    String name = parser.getAttributeValue(null, ATTR_NAME);
                    String userStr = parser.getAttributeValue(null, ATTR_USER);
                    String codeStr = parser.getAttributeValue(null, ATTR_CODE);
                    if (name != null) {
                        int userId = 0;
                        boolean andCode = true;
                        try {
                            if (userStr != null) {
                                userId = Integer.parseInt(userStr);
                            }
                        } catch (NumberFormatException e) {
                        }
                        if (codeStr != null) {
                            andCode = Boolean.parseBoolean(codeStr);
                        }
                        addPackageToCleanLPw(new PackageCleanItem(userId, name, andCode));
                    }
                } else if (tagName.equals("renamed-package")) {//重命名的apk
                    String nname = parser.getAttributeValue(null, "new");
                    String oname = parser.getAttributeValue(null, "old");
                    if (nname != null && oname != null) {
                        mRenamedPackages.put(nname, oname);
                    }
                } else if (tagName.equals("last-platform-version")) {
                    mInternalSdkPlatform = mExternalSdkPlatform = 0;
                    try {
                        String internal = parser.getAttributeValue(null, "internal");//内部版本号
                        if (internal != null) {
                            mInternalSdkPlatform = Integer.parseInt(internal);
                        }
                        String external = parser.getAttributeValue(null, "external");//外部版本号
                        if (external != null) {
                            mExternalSdkPlatform = Integer.parseInt(external);
                        }
                    } catch (NumberFormatException e) {
                    }
                } else if (tagName.equals("verifier")) {
                    final String deviceIdentity = parser.getAttributeValue(null, "device");
                    try {
                        mVerifierDeviceIdentity = VerifierDeviceIdentity.parse(deviceIdentity);
                    } catch (IllegalArgumentException e) {
                        Slog.w(PackageManagerService.TAG, "Discard invalid verifier device id: "
                                + e.getMessage());
                    }
                } else if (TAG_READ_EXTERNAL_STORAGE.equals(tagName)) {
                    final String enforcement = parser.getAttributeValue(null, ATTR_ENFORCEMENT);
                    mReadExternalStorageEnforced = "1".equals(enforcement);
                } else {
                    Slog.w(PackageManagerService.TAG, "Unknown element under : "
                            + parser.getName());
                    XmlUtils.skipCurrentTag(parser);
                }
            }

            str.close();

        } catch (XmlPullParserException e) {
            mReadMessages.append("Error reading: " + e.toString());
            PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
            Log.wtf(PackageManagerService.TAG, "Error reading package manager settings", e);

        } catch (java.io.IOException e) {
            mReadMessages.append("Error reading: " + e.toString());
            PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
            Log.wtf(PackageManagerService.TAG, "Error reading package manager settings", e);
        }

        final int N = mPendingPackages.size();//共享了uid的package
        for (int i = 0; i < N; i++) {
            final PendingPackage pp = mPendingPackages.get(i);//获取PendingPackage结构
            Object idObj = getUserIdLPr(pp.sharedId);//获取被共享的uid的SharedUserSetting结构
            if (idObj != null && idObj instanceof SharedUserSetting) {
                PackageSetting p = getPackageLPw(pp.name, null, pp.realName, //新建一个PackageSetting结构
                        (SharedUserSetting) idObj, pp.codePath, pp.resourcePath,
                        pp.nativeLibraryPathString, pp.versionCode, pp.pkgFlags,
                        null, true /* add */, false /* allowInstall */); //add标志为true,需要添加到mPackages
                if (p == null) {
                    PackageManagerService.reportSettingsProblem(Log.WARN,
                            "Unable to create application package for " + pp.name);
                    continue;
                }
                p.copyFrom(pp);//重新赋值该package的一些信息(在前面解析的)
            } else if (idObj != null) {
                String msg = "Bad package setting: package " + pp.name + " has shared uid "
                        + pp.sharedId + " that is not a shared uid\n";
                mReadMessages.append(msg);
                PackageManagerService.reportSettingsProblem(Log.ERROR, msg);
            } else {
                String msg = "Bad package setting: package " + pp.name + " has shared uid "
                        + pp.sharedId + " that is not defined\n";
                mReadMessages.append(msg);
                PackageManagerService.reportSettingsProblem(Log.ERROR, msg);
            }
        }
        mPendingPackages.clear();//所以的都处理完了,清空

        if (mBackupStoppedPackagesFilename.exists()///data/system/packages-stopped-backup.xml
                || mStoppedPackagesFilename.exists()) { ///data/system/packages-stopped.xml
            // Read old file
            readStoppedLPw();
            mBackupStoppedPackagesFilename.delete();
            mStoppedPackagesFilename.delete();
            // Migrate to new file format
            writePackageRestrictionsLPr(0);
        } else {
            if (users == null) {
                readPackageRestrictionsLPr(0);
            } else {
                for (UserInfo user : users) {
                    readPackageRestrictionsLPr(user.id);//读取该user的限制
                }
            }
        }

        /*
         * Make sure all the updated system packages have their shared users
         * associated with them.
         *///确保所有已更新的系统packages有他们的共享用户关联他们
        final Iterator disabledIt = mDisabledSysPackages.values().iterator();
        while (disabledIt.hasNext()) {
            final PackageSetting disabledPs = disabledIt.next();
            final Object id = getUserIdLPr(disabledPs.appId);
            if (id != null && id instanceof SharedUserSetting) {
                disabledPs.sharedUser = (SharedUserSetting) id;
            }
        }

        mReadMessages.append("Read completed successfully: " + mPackages.size() + " packages, "
                + mSharedUsers.size() + " shared uids\n");

        return true;
    }

解析/data/system/packages.xml,看一下模拟器的已经启动一次后的这个文件









































































































































































































































































































































































































































































































































































































































































































































































主要是一些permissions、package、shared-user的解析,具体的解析过程就不分析,主要是:

permissions:构造权限结构BasePermission添加到mPermissions

package:解析每个已经安装apk的name,codePath,sharedUserId,userId,version等,调用addPackageLP构建PackageSetting并添加到mPackages

shared-user:readSharedUserLP通过addSharedUserLP添加一个SharedUserSetting结构,再通过readGrantedPermissionsLP读取给这个userId赋予的权限

 

五、建立 java 层的 installer 与 c 层的 installd 的 socket 连接。

Apk的安装是通过mInstaller来完成的,主要是一些目录的创建等。

我们看一下相关的流程图

PackageManagerService启动及初始化流程_第7张图片

Install 是一个后台进程:

PackageManagerService启动及初始化流程_第8张图片

在启动他的时候会创建一个"installd"的套接字,并等待客户端的连接

而但客户端的install要执行一个命令时,以dexopt为例:

   public int dexopt(String apkPath, int uid, boolean isPublic) {
        StringBuilder builder = new StringBuilder("dexopt");
        builder.append(' ');
        builder.append(apkPath);
        builder.append(' ');
        builder.append(uid);
        builder.append(isPublic ? " 1" : " 0");
        return execute(builder.toString());
}

调用execute,execute会调用connect连接服务端,这里也不多讲了,比较简单。

六、检查相关需要优化的目录

主要是mSharedLibraries、/system/framework、外部库等

            String bootClassPath =System.getProperty("java.boot.class.path");//所有在bootClassPath目录的类已经优化了

   if (bootClassPath != null) {//确保 boot路径的class都被优化了
                String[] paths = splitString(bootClassPath, ':');
                for (int i=0; i 0) {//确保 外部库也被 优化
                Iterator libs = mSharedLibraries.values().iterator();
                while (libs.hasNext()) {
                    String lib = libs.next();
                    try {
                        if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
                            libFiles.add(lib);
                            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());
                    }
                }
            }

            // Gross hack for now: we know this file doesn't contain any
            // code, so don't dexopt it to avoid the resulting log spew.
            libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");//framework-res.apk没有包含代码,不需要优化

            /**
             * And there are a number of commands implemented in Java, which
             * we currently need to do the dexopt on so that they can be
             * run from a non-root shell.
             */
            String[] frameworkFiles = mFrameworkDir.list();
            if (frameworkFiles != null) {
                for (int i=0; i

七、启动AppDirObserver线程往中监测

这些检测的目录包括/system/framework,/system/app,/data/app/data/app-private等,这里的,相关知识参考AppDirObserver介绍

八、调用scanDirLI启动apk解析

Apk安装的流程比较复杂,后面会专门讲解,这里看一下scanDirLI的流程

PackageManagerService启动及初始化流程_第9张图片
 private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
        String[] files = dir.list();//获取该目录下的文件
        if (files == null) {
            Log.d(TAG, "No files in app dir " + dir);
            return;
        }

        if (DEBUG_PACKAGE_SCANNING) {
            Log.d(TAG, "Scanning app dir " + dir);
        }

        int i;
        for (i=0; i

主要是对该目录下面的所有文件,首先判断其是否是apk文件,是则调用scanPackageLI进行安装,安装失败的话则还要删除文件

九、移除临时文件

通过调用deleteTempPackageFiles来完成

 private void deleteTempPackageFiles() {
        final FilenameFilter filter = new FilenameFilter() {//创建一个过滤器,以vmdl开始,tmp结束的文件
            public boolean accept(File dir, String name) {
                return name.startsWith("vmdl") && name.endsWith(".tmp");
            }
        };
        deleteTempPackageFilesInDirectory(mAppInstallDir, filter);//删除/data/app满足条件的文件
        deleteTempPackageFilesInDirectory(mDrmAppPrivateInstallDir, filter);//删除/data/app-private下满足条件的文件

删除/data/app目录下以vmdl开始,tmp结束的文件

十、赋予package相应请求的权限

updatePermissionsLPw用来给apk赋权限

updatePermissionsLPw(null,null,UPDATE_PERMISSIONS_ALL                  | (regrantPermissions ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
                            : 0));
注意这里有一个UPDATE_PERMISSIONS_ALL

    private void updatePermissionsLPw(String changingPkg,
            PackageParser.Package pkgInfo, int flags) {
        // Make sure there are no dangling permission trees.
        Iterator it = mSettings.mPermissionTrees.values().iterator();
        while (it.hasNext()) {
            final BasePermission bp = it.next();
            if (bp.packageSetting == null) {
                // We may not yet have parsed the package, so just see if
                // we still know about its settings.
                bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
            }
            if (bp.packageSetting == null) {
                Slog.w(TAG, "Removing dangling permission tree: " + bp.name
                        + " from package " + bp.sourcePackage);
                it.remove();
            } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
                if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
                    Slog.i(TAG, "Removing old permission tree: " + bp.name
                            + " from package " + bp.sourcePackage);
                    flags |= UPDATE_PERMISSIONS_ALL;
                    it.remove();
                }
            }
        }

        // Make sure all dynamic permissions have been assigned to a package,
        // and make sure there are no dangling permissions.
        it = mSettings.mPermissions.values().iterator();
        while (it.hasNext()) {
            final BasePermission bp = it.next();
            if (bp.type == BasePermission.TYPE_DYNAMIC) {//动态权限
                if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
                        + bp.name + " pkg=" + bp.sourcePackage
                        + " info=" + bp.pendingInfo);
                if (bp.packageSetting == null && bp.pendingInfo != null) {
                    final BasePermission tree = findPermissionTreeLP(bp.name);
                    if (tree != null && tree.perm != null) {
                        bp.packageSetting = tree.packageSetting;
                        bp.perm = new PackageParser.Permission(tree.perm.owner,
                                new PermissionInfo(bp.pendingInfo));
                        bp.perm.info.packageName = tree.perm.info.packageName;
                        bp.perm.info.name = bp.name;
                        bp.uid = tree.uid;
                    }
                }
            }
            if (bp.packageSetting == null) {//还未解析该package
                // We may not yet have parsed the package, so just see if
                // we still know about its settings.
                bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
            }
            if (bp.packageSetting == null) {//还是为null,则移除该权限
                Slog.w(TAG, "Removing dangling permission: " + bp.name
                        + " from package " + bp.sourcePackage);
                it.remove();
            } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
                if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {//检查其他package是否使用了这个包的权限
                    Slog.i(TAG, "Removing old permission: " + bp.name//一般的权限定义都属于android这个包
                            + " from package " + bp.sourcePackage);
                    flags |= UPDATE_PERMISSIONS_ALL;
                    it.remove();
                }
            }
        }

        // Now update the permissions for all packages, in particular
        // replace the granted permissions of the system packages.
        if ((flags&UPDATE_PERMISSIONS_ALL) != 0) {//更新所有package的权限
            for (PackageParser.Package pkg : mPackages.values()) {
                if (pkg != pkgInfo) {
                    grantPermissionsLPw(pkg, (flags&UPDATE_PERMISSIONS_REPLACE_ALL) != 0);//赋予package要求的权限
                }
            }
        }
        
        if (pkgInfo != null) {
            grantPermissionsLPw(pkgInfo, (flags&UPDATE_PERMISSIONS_REPLACE_PKG) != 0);//更新某个package权限
        }
}

调用grantPermissionsLPw赋予某个apk请求的权限

private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace) {
        final PackageSetting ps = (PackageSetting) pkg.mExtras;
        if (ps == null) {
            return;
        }
        final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
        HashSet origPermissions = gp.grantedPermissions;
        boolean changedPermission = false;

        if (replace) {
            ps.permissionsFixed = false;
            if (gp == ps) {
                origPermissions = new HashSet(gp.grantedPermissions);
                gp.grantedPermissions.clear();
                gp.gids = mGlobalGids;
            }
        }

        if (gp.gids == null) {
            gp.gids = mGlobalGids;
        }

        final int N = pkg.requestedPermissions.size();//请求哪些权限
        for (int i=0; i

如果允许授予相应的权限,则添加到grantedPermissions


十一、     将解析出的Package的相关信息保存到文件

       主要是把已经安装的apk信息写回文件

PackageManagerService启动及初始化流程_第10张图片

相关代码:

 void writeLPr() {
        //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);

        // Keep the old settings around until we know the new ones have
        // been successfully written.
        if (mSettingsFilename.exists()) {///data/system/packages.xml存在
            // Presence of backup settings file indicates that we failed
            // to persist settings earlier. So preserve the older
            // backup for future reference since the current settings
            // might have been corrupted.
            if (!mBackupSettingsFilename.exists()) {///data/system/packages-backup.xml不存在
                if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {//packages.xml重命名为packages-backup.xml
                    Log.wtf(PackageManagerService.TAG, "Unable to backup package manager settings, "
                            + " current changes will be lost at reboot");
                    return;
                }
            } else {
                mSettingsFilename.delete();
                Slog.w(PackageManagerService.TAG, "Preserving older settings backup");
            }
        }

        mPastSignatures.clear();

        try {
            FileOutputStream fstr = new FileOutputStream(mSettingsFilename);
            BufferedOutputStream str = new BufferedOutputStream(fstr);

            //XmlSerializer serializer = XmlUtils.serializerInstance();
            XmlSerializer serializer = new FastXmlSerializer();
            serializer.setOutput(str, "utf-8");
            serializer.startDocument(null, true);
            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);

            serializer.startTag(null, "packages");//写packages标签

            serializer.startTag(null, "last-platform-version");//写版本信息
            serializer.attribute(null, "internal", Integer.toString(mInternalSdkPlatform));
            serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform));
            serializer.endTag(null, "last-platform-version");

            if (mVerifierDeviceIdentity != null) {
                serializer.startTag(null, "verifier");
                serializer.attribute(null, "device", mVerifierDeviceIdentity.toString());
                serializer.endTag(null, "verifier");
            }

            if (mReadExternalStorageEnforced != null) {
                serializer.startTag(null, TAG_READ_EXTERNAL_STORAGE);
                serializer.attribute(
                        null, ATTR_ENFORCEMENT, mReadExternalStorageEnforced ? "1" : "0");
                serializer.endTag(null, TAG_READ_EXTERNAL_STORAGE);
            }

            serializer.startTag(null, "permission-trees");
            for (BasePermission bp : mPermissionTrees.values()) {
                writePermissionLPr(serializer, bp);//写permissonTree
            }
            serializer.endTag(null, "permission-trees");

            serializer.startTag(null, "permissions");
            for (BasePermission bp : mPermissions.values()) {
                writePermissionLPr(serializer, bp);//写permisson
            }
            serializer.endTag(null, "permissions");

            for (final PackageSetting pkg : mPackages.values()) {
                writePackageLPr(serializer, pkg);//写Packages
            }

            for (final PackageSetting pkg : mDisabledSysPackages.values()) {
                writeDisabledSysPackageLPr(serializer, pkg);//写DisabledSysPackages
            }

            for (final SharedUserSetting usr : mSharedUsers.values()) {//写shared-user
                serializer.startTag(null, "shared-user");
                serializer.attribute(null, ATTR_NAME, usr.name);
                serializer.attribute(null, "userId",
                        Integer.toString(usr.userId));
                usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
                serializer.startTag(null, "perms");
                for (String name : usr.grantedPermissions) {
                    serializer.startTag(null, TAG_ITEM);
                    serializer.attribute(null, ATTR_NAME, name);
                    serializer.endTag(null, TAG_ITEM);
                }
                serializer.endTag(null, "perms");
                serializer.endTag(null, "shared-user");
            }

            if (mPackagesToBeCleaned.size() > 0) {//要被清除的package
                for (PackageCleanItem item : mPackagesToBeCleaned) {
                    final String userStr = Integer.toString(item.userId);
                    serializer.startTag(null, "cleaning-package");
                    serializer.attribute(null, ATTR_NAME, item.packageName);
                    serializer.attribute(null, ATTR_CODE, item.andCode ? "true" : "false");
                    serializer.attribute(null, ATTR_USER, userStr);
                    serializer.endTag(null, "cleaning-package");
                }
            }
            
            if (mRenamedPackages.size() > 0) {//重命名的package
                for (Map.Entry e : mRenamedPackages.entrySet()) {
                    serializer.startTag(null, "renamed-package");
                    serializer.attribute(null, "new", e.getKey());
                    serializer.attribute(null, "old", e.getValue());
                    serializer.endTag(null, "renamed-package");
                }
            }
            
            serializer.endTag(null, "packages");

            serializer.endDocument();

            str.flush();
            FileUtils.sync(fstr);
            str.close();

            // New settings successfully written, old ones are no longer
            // needed.
            mBackupSettingsFilename.delete();
            FileUtils.setPermissions(mSettingsFilename.toString(),
                    FileUtils.S_IRUSR|FileUtils.S_IWUSR
                    |FileUtils.S_IRGRP|FileUtils.S_IWGRP,
                    -1, -1);

            // Write package list file now, use a JournaledFile.
            //
            File tempFile = new File(mPackageListFilename.toString() + ".tmp");//写/data/system/packages.list
            JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile);

            fstr = new FileOutputStream(journal.chooseForWrite());
            str = new BufferedOutputStream(fstr);
            try {
                StringBuilder sb = new StringBuilder();
                for (final PackageSetting pkg : mPackages.values()) {//所有的package信息
                    ApplicationInfo ai = pkg.pkg.applicationInfo;
                    String dataPath = ai.dataDir;
                    boolean isDebug  = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;

                    // Avoid any application that has a space in its path
                    // or that is handled by the system.
                    if (dataPath.indexOf(" ") >= 0 || ai.uid < Process.FIRST_APPLICATION_UID)
                        continue;

                    // we store on each line the following information for now:
                    //
                    // pkgName    - package name
                    // userId     - application-specific user id
                    // debugFlag  - 0 or 1 if the package is debuggable.
                    // dataPath   - path to package's data path
                    //
                    // NOTE: We prefer not to expose all ApplicationInfo flags for now.
                    //
                    // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
                    // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
                    //   system/core/run-as/run-as.c
                    //
                    sb.setLength(0);
                    sb.append(ai.packageName);
                    sb.append(" ");
                    sb.append((int)ai.uid);
                    sb.append(isDebug ? " 1 " : " 0 ");
                    sb.append(dataPath);
                    sb.append("\n");
                    str.write(sb.toString().getBytes());
                }
                str.flush();
                FileUtils.sync(fstr);
                str.close();
                journal.commit();
            } catch (Exception e) {
                IoUtils.closeQuietly(str);
                journal.rollback();
            }

            FileUtils.setPermissions(mPackageListFilename.toString(),
                    FileUtils.S_IRUSR|FileUtils.S_IWUSR
                    |FileUtils.S_IRGRP|FileUtils.S_IWGRP,
                    -1, -1);

            writeAllUsersPackageRestrictionsLPr();//将一些限制 写回文件
            return;

        } catch(XmlPullParserException e) {
            Log.wtf(PackageManagerService.TAG, "Unable to write package manager settings, "
                    + "current changes will be lost at reboot", e);
        } catch(java.io.IOException e) {
            Log.wtf(PackageManagerService.TAG, "Unable to write package manager settings, "
                    + "current changes will be lost at reboot", e);
        }
        // Clean up partially written files
        if (mSettingsFilename.exists()) {
            if (!mSettingsFilename.delete()) {
                Log.wtf(PackageManagerService.TAG, "Failed to clean up mangled file: "
                        + mSettingsFilename);
            }
        }
        //Debug.stopMethodTracing();
}

这个函数也比较简单,主要是把前面解析出来的信息重新保存到文件,因为这时的信息可能跟开始packages.xml不一样了。

 

到这里,PackageManagerService就已经初始化完成了,以后有Package的变动都会在PackageManagerService中反应出来,我们也可以查询Activity、Service、Provider等的信息。


你可能感兴趣的:(android框架)