PackageManagerService启动及初始化流程

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

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


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

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


相关代码:

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<String> libFiles = new HashSet<String>();

            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<paths.length; i++) {
                    try {
                        if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {//需要优化?
                            libFiles.add(paths[i]);
                            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!");
            }

            /**
             * Also ensure all external libraries have had dexopt run on them.
             */
            if (mSharedLibraries.size() > 0) {//确保 外部库也被 优化
                Iterator<String> 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<frameworkFiles.length; i++) {//优化/system/framework目录下的文件
                    File libPath = new File(mFrameworkDir, frameworkFiles[i]);
                    String path = libPath.getPath();
                    // Skip the file if we alrady did it.
                    if (libFiles.contains(path)) {//已经包含过,包含过的都优化了
                        continue;
                    }
                    // Skip the file if it is not a type we want to dexopt.
                    if (!path.endsWith(".apk") && !path.endsWith(".jar")) {//跳过不符合条件的
                        continue;
                    }
                    try {
                        if (dalvik.system.DexFile.isDexOptNeeded(path)) {//需要优化
                            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);
                    }
                }
            }

            if (didDexOpt) {
                // If we had to do a dexopt of one of the previous
                // things, then something on the system has changed.
                // Consider this significant, and wipe away all other
                // existing dexopt files to ensure we don't leave any
                // dangling around.
                String[] files = mDalvikCacheDir.list();
                if (files != null) {
                    for (int i=0; i<files.length; i++) {
                        String fn = files[i];
                        if (fn.startsWith("data@app@")
                                || fn.startsWith("data@app-private@")) {
                            Slog.i(TAG, "Pruning dalvik file: " + fn);
                            (new File(mDalvikCacheDir, fn)).delete();
                        }
                    }
                }
            }

            // Find base frameworks (resource packages without code).
            mFrameworkInstallObserver = new AppDirObserver(//创建一个监察器监视/system/framework
                mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
            mFrameworkInstallObserver.startWatching();
            scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM//扫描该目录下的所有apk,进行安装
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanMode | SCAN_NO_DEX, 0);//currentTime 为 0  SCAN_NO_DEX

            // Collect all system packages.
            mSystemAppDir = new File(Environment.getRootDirectory(), "app");
            mSystemInstallObserver = new AppDirObserver(//监视/system/app
                mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
            mSystemInstallObserver.startWatching();
            scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM  //扫描该目录下的所有apk,进行安装
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);

            // Collect all vendor packages.
            mVendorAppDir = new File("/vendor/app");
            mVendorInstallObserver = new AppDirObserver(//监视/vendor/app
                mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
            mVendorInstallObserver.startWatching();
            scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM //扫描该目录下的所有apk,进行安装
                    | 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.//去除不存在的系统packages
            final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
            if (!mOnlyCore) {
                Iterator<PackageSetting> 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<PackageSetting> 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安装的时候会涉及到。


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


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

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


看一下读取的流程:


相关代码:

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, "<group> 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, "<permission> 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, "<assign-permission> without name at "
                                + parser.getPositionDescription());
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    String uidStr = parser.getAttributeValue(null, "uid");//获取用户名
                    if (uidStr == null) {
                        Slog.w(TAG, "<assign-permission> without uid at "
                                + parser.getPositionDescription());
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    int uid = Process.getUidForName(uidStr);//该用户名对应的uid
                    if (uid < 0) {
                        Slog.w(TAG, "<assign-permission> with unknown uid \""
                                + uidStr + "\" at "
                                + parser.getPositionDescription());
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    perm = perm.intern();
                    HashSet<String> perms = mSystemPermissions.get(uid);//从mSystemPermissions查找是否已为该uid分配权限
                    if (perms == null) {
                        perms = new HashSet<String>();
                        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, "<library> without name at "
                                + parser.getPositionDescription());
                    } else if (lfile == null) {
                        Slog.w(TAG, "<library> 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, "<feature> 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:

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at
  
          http://www.apache.org/licenses/LICENSE-2.0
  
     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->

<!-- This file is used to define the mappings between lower-level system
     user and group IDs and the higher-level permission names managed
     by the platform.

     Be VERY careful when editing this file!  Mistakes made here can open
     big security holes.
-->
<permissions>

    <!-- ================================================================== -->
    <!-- ================================================================== -->
    <!-- ================================================================== -->

    <!-- The following tags are associating low-level group IDs with
         permission names.  By specifying such a mapping, you are saying
         that any application process granted the given permission will
         also be running with the given group ID attached to its process,
         so it can perform any filesystem (read, write, execute) operations
         allowed for that group. -->

    <permission name="android.permission.BLUETOOTH_ADMIN" >
        <group gid="net_bt_admin" />
    </permission>

    <permission name="android.permission.BLUETOOTH" >
        <group gid="net_bt" />
    </permission>

    <permission name="android.permission.BLUETOOTH_STACK" >
        <group gid="net_bt_stack" />
    </permission>

    <permission name="android.permission.NET_TUNNELING" >
        <group gid="vpn" />
    </permission>

    <permission name="android.permission.INTERNET" >
        <group gid="inet" />
    </permission>

    <permission name="android.permission.CAMERA" >
        <group gid="camera" />
    </permission>

    <permission name="android.permission.READ_LOGS" >
        <group gid="log" />
    </permission>

    <permission name="android.permission.READ_EXTERNAL_STORAGE" >
        <group gid="sdcard_r" />
    </permission>

    <permission name="android.permission.WRITE_EXTERNAL_STORAGE" >
        <group gid="sdcard_rw" />
    </permission>

    <permission name="android.permission.WRITE_MEDIA_STORAGE" >
        <group gid="media_rw" />
    </permission>

    <permission name="android.permission.ACCESS_MTP" >
        <group gid="mtp" />
    </permission>

    <permission name="android.permission.NET_ADMIN" >
        <group gid="net_admin" />
    </permission>

    <!-- The group that /cache belongs to, linked to the permission
         set on the applications that can access /cache -->
    <permission name="android.permission.ACCESS_CACHE_FILESYSTEM" >
        <group gid="cache" />
    </permission>

    <!-- RW permissions to any system resources owned by group 'diag'.
         This is for carrier and manufacture diagnostics tools that must be
         installable from the framework. Be careful. -->
    <permission name="android.permission.DIAGNOSTIC" >
        <group gid="input" />
        <group gid="diag" />
    </permission>

    <!-- Group that can read detailed network usage statistics -->
    <permission name="android.permission.READ_NETWORK_USAGE_HISTORY">
        <group gid="net_bw_stats" />
    </permission>

    <!-- Group that can modify how network statistics are accounted -->
    <permission name="android.permission.MODIFY_NETWORK_ACCOUNTING">
        <group gid="net_bw_acct" />
    </permission>

    <!-- ================================================================== -->
    <!-- ================================================================== -->
    <!-- ================================================================== -->

    <!-- The following tags are assigning high-level permissions to specific
         user IDs.  These are used to allow specific core system users to
         perform the given operations with the higher-level framework.  For
         example, we give a wide variety of permissions to the shell user
         since that is the user the adb shell runs under and developers and
         others should have a fairly open environment in which to
         interact with the system. -->

    <!-- Standard permissions granted to the shell. -->
    <assign-permission name="android.permission.WRITE_EXTERNAL_STORAGE" uid="shell" />
    <assign-permission name="android.permission.SEND_SMS" uid="shell" />
    <assign-permission name="android.permission.CALL_PHONE" uid="shell" />
    <assign-permission name="android.permission.READ_CONTACTS" uid="shell" />
    <assign-permission name="android.permission.WRITE_CONTACTS" uid="shell" />
    <assign-permission name="android.permission.READ_CALENDAR" uid="shell" />
    <assign-permission name="android.permission.WRITE_CALENDAR" uid="shell" />
    <assign-permission name="android.permission.READ_USER_DICTIONARY" uid="shell" />
    <assign-permission name="android.permission.WRITE_USER_DICTIONARY" uid="shell" />
    <assign-permission name="android.permission.ACCESS_FINE_LOCATION" uid="shell" />
    <assign-permission name="android.permission.ACCESS_COARSE_LOCATION" uid="shell" />
    <assign-permission name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" uid="shell" />
    <assign-permission name="android.permission.ACCESS_NETWORK_STATE" uid="shell" />
    <assign-permission name="android.permission.ACCESS_WIFI_STATE" uid="shell" />
    <assign-permission name="android.permission.BLUETOOTH" uid="shell" />
    <!-- System tool permissions granted to the shell. -->
    <assign-permission name="android.permission.GET_TASKS" uid="shell" />
    <assign-permission name="android.permission.CHANGE_CONFIGURATION" uid="shell" />
    <assign-permission name="android.permission.REORDER_TASKS" uid="shell" />
    <assign-permission name="android.permission.SET_ANIMATION_SCALE" uid="shell" />
    <assign-permission name="android.permission.SET_PREFERRED_APPLICATIONS" uid="shell" />
    <assign-permission name="android.permission.WRITE_SETTINGS" uid="shell" />
    <assign-permission name="android.permission.WRITE_SECURE_SETTINGS" uid="shell" />
    <assign-permission name="android.permission.BROADCAST_STICKY" uid="shell" />
    <!-- Development tool permissions granted to the shell. -->
    <assign-permission name="android.permission.SET_DEBUG_APP" uid="shell" />
    <assign-permission name="android.permission.SET_PROCESS_LIMIT" uid="shell" />
    <assign-permission name="android.permission.SET_ALWAYS_FINISH" uid="shell" />
    <assign-permission name="android.permission.DUMP" uid="shell" />
    <assign-permission name="android.permission.SIGNAL_PERSISTENT_PROCESSES" uid="shell" />
    <assign-permission name="android.permission.KILL_BACKGROUND_PROCESSES" uid="shell" />
    <!-- Internal permissions granted to the shell. -->
    <assign-permission name="android.permission.FORCE_BACK" uid="shell" />
    <assign-permission name="android.permission.BATTERY_STATS" uid="shell" />
    <assign-permission name="android.permission.INTERNAL_SYSTEM_WINDOW" uid="shell" />
    <assign-permission name="android.permission.INJECT_EVENTS" uid="shell" />
    <assign-permission name="android.permission.RETRIEVE_WINDOW_CONTENT" uid="shell" />
    <assign-permission name="android.permission.SET_ACTIVITY_WATCHER" uid="shell" />
    <assign-permission name="android.permission.READ_INPUT_STATE" uid="shell" />
    <assign-permission name="android.permission.SET_ORIENTATION" uid="shell" />
    <assign-permission name="android.permission.INSTALL_PACKAGES" uid="shell" />
    <assign-permission name="android.permission.CLEAR_APP_USER_DATA" uid="shell" />
    <assign-permission name="android.permission.DELETE_CACHE_FILES" uid="shell" />
    <assign-permission name="android.permission.DELETE_PACKAGES" uid="shell" />
    <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="shell" />
    <assign-permission name="android.permission.READ_FRAME_BUFFER" uid="shell" />
    <assign-permission name="android.permission.DEVICE_POWER" uid="shell" />
    <assign-permission name="android.permission.INSTALL_LOCATION_PROVIDER" uid="shell" />
    <assign-permission name="android.permission.BACKUP" uid="shell" />
    <assign-permission name="android.permission.FORCE_STOP_PACKAGES" uid="shell" />
    <assign-permission name="android.permission.STOP_APP_SWITCHES" uid="shell" />
    <assign-permission name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY" uid="shell" />
    <assign-permission name="android.permission.GRANT_REVOKE_PERMISSIONS" uid="shell" />
    <assign-permission name="android.permission.SET_KEYBOARD_LAYOUT" uid="shell" />
    <assign-permission name="android.permission.GET_DETAILED_TASKS" uid="shell" />
    <assign-permission name="android.permission.SET_SCREEN_COMPATIBILITY" uid="shell" />
    <assign-permission name="android.permission.READ_EXTERNAL_STORAGE" uid="shell" />
    <assign-permission name="android.permission.WRITE_EXTERNAL_STORAGE" uid="shell" />
    <assign-permission name="android.permission.INTERACT_ACROSS_USERS" uid="shell" />
    <assign-permission name="android.permission.INTERACT_ACROSS_USERS_FULL" uid="shell" />
    <assign-permission name="android.permission.MANAGE_USERS" uid="shell" />
    <assign-permission name="android.permission.BLUETOOTH_STACK" uid="shell" />
    
    <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
    <assign-permission name="android.permission.ACCESS_DRM" uid="media" />
    <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="media" />
    <assign-permission name="android.permission.WAKE_LOCK" uid="media" />

    <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />

    <!-- This is a list of all the libraries available for application
         code to link against. -->

    <library name="android.test.runner"
            file="/system/framework/android.test.runner.jar" />
    <library name="javax.obex"
            file="/system/framework/javax.obex.jar"/>

</permissions>

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

 

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

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

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

  boolean readLPw(List<UserInfo> 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 <packages>: "
                            + 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<PackageSetting> 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,看一下模拟器的已经启动一次后的这个文件

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<packages>
<last-platform-version internal="17" external="17" />
<permission-trees />
<permissions>
<item name="android.permission.CHANGE_WIFI_MULTICAST_STATE" package="android" protection="1" />
<item name="android.permission.WRITE_CALL_LOG" package="android" protection="1" />
<item name="android.permission.CLEAR_APP_CACHE" package="android" protection="1" />
<item name="android.permission.AUTHENTICATE_ACCOUNTS" package="android" protection="1" />
<item name="android.permission.ACCESS_WIMAX_STATE" package="android" />
<item name="android.permission.ASEC_ACCESS" package="android" protection="2" />
<item name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS" package="android" protection="1" />
<item name="android.permission.INTERNAL_SYSTEM_WINDOW" package="android" protection="2" />
<item name="android.permission.ACCESS_ALL_EXTERNAL_STORAGE" package="android" protection="2" />
<item name="android.permission.ACCESS_MOCK_LOCATION" package="android" protection="1" />
<item name="android.permission.ACCESS_NETWORK_STATE" package="android" />
<item name="android.permission.CHANGE_BACKGROUND_DATA_SETTING" package="android" protection="2" />
<item name="android.permission.GET_DETAILED_TASKS" package="android" protection="2" />
<item name="android.permission.MOVE_PACKAGE" package="android" protection="18" />
<item name="android.permission.FORCE_STOP_PACKAGES" package="android" protection="2" />
<item name="com.android.launcher.permission.UNINSTALL_SHORTCUT" package="com.android.launcher" protection="1" />
<item name="android.permission.DISABLE_KEYGUARD" package="android" protection="1" />
<item name="android.permission.READ_SYNC_STATS" package="android" />
<item name="android.permission.CONTROL_WIFI_DISPLAY" package="android" protection="2" />
<item name="android.permission.GLOBAL_SEARCH_CONTROL" package="android" protection="2" />
<item name="android.permission.READ_INPUT_STATE" package="android" protection="2" />
<item name="android.permission.WRITE_DREAM_STATE" package="android" protection="2" />
<item name="android.permission.START_ANY_ACTIVITY" package="android" protection="2" />
<item name="android.permission.REBOOT" package="android" protection="18" />
<item name="android.permission.BROADCAST_WAP_PUSH" package="android" protection="2" />
<item name="android.permission.WRITE_SMS" package="android" protection="1" />
<item name="android.permission.FILTER_EVENTS" package="android" protection="2" />
<item name="android.permission.STATUS_BAR" package="android" protection="18" />
<item name="android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED" package="com.android.providers.downloads" protection="18" />
<item name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" package="android" protection="18" />
<item name="android.permission.GLOBAL_SEARCH" package="android" protection="18" />
<item name="android.permission.STOP_APP_SWITCHES" package="android" protection="18" />
<item name="android.permission.BIND_VPN_SERVICE" package="android" protection="2" />
<item name="android.permission.MANAGE_APP_TOKENS" package="android" protection="2" />
<item name="android.permission.SET_KEYBOARD_LAYOUT" package="android" protection="2" />
<item name="android.permission.RETRIEVE_WINDOW_INFO" package="android" protection="2" />
<item name="android.permission.ASEC_CREATE" package="android" protection="2" />
<item name="android.permission.RECEIVE_EMERGENCY_BROADCAST" package="android" protection="18" />
<item name="android.permission.BIND_PACKAGE_VERIFIER" package="android" protection="2" />
<item name="android.permission.BATTERY_STATS" package="android" protection="1" />
<item name="android.permission.READ_PROFILE" package="android" protection="1" />
<item name="android.permission.COPY_PROTECTED_DATA" package="android" protection="2" />
<item name="com.android.browser.permission.READ_HISTORY_BOOKMARKS" package="android" protection="1" />
<item name="android.permission.ASEC_RENAME" package="android" protection="2" />
<item name="com.android.alarm.permission.SET_ALARM" package="android" />
<item name="android.permission.MOUNT_FORMAT_FILESYSTEMS" package="android" protection="18" />
<item name="android.permission.SIGNAL_PERSISTENT_PROCESSES" package="android" protection="50" />
<item name="android.permission.MASTER_CLEAR" package="android" protection="18" />
<item name="android.permission.REMOTE_AUDIO_PLAYBACK" package="android" protection="2" />
<item name="android.permission.READ_CONTACTS" package="android" protection="1" />
<item name="android.permission.GET_ACCOUNTS" package="android" />
<item name="android.permission.RESTART_PACKAGES" package="android" />
<item name="android.permission.MANAGE_USERS" package="android" protection="18" />
<item name="android.permission.SEND_SMS_NO_CONFIRMATION" package="android" protection="18" />
<item name="android.permission.SUBSCRIBED_FEEDS_READ" package="android" />
<item name="android.permission.WAKE_LOCK" package="android" />
<item name="android.permission.RECEIVE_WAP_PUSH" package="android" protection="1" />
<item name="com.android.voicemail.permission.ADD_VOICEMAIL" package="android" protection="1" />
<item name="android.permission.INJECT_EVENTS" package="android" protection="2" />
<item name="android.permission.ACCOUNT_MANAGER" package="android" protection="2" />
<item name="android.permission.ACCESS_BLUETOOTH_SHARE" package="com.android.bluetooth" protection="2" />
<item name="android.permission.SET_ALWAYS_FINISH" package="android" protection="50" />
<item name="android.permission.WRITE_SECURE_SETTINGS" package="android" protection="50" />
<item name="android.permission.WRITE_CALENDAR" package="android" protection="1" />
<item name="android.permission.INSTALL_LOCATION_PROVIDER" package="android" protection="18" />
<item name="android.permission.WRITE_SYNC_SETTINGS" package="android" />
<item name="android.permission.MODIFY_PHONE_STATE" package="android" protection="18" />
<item name="android.permission.UPDATE_LOCK" package="android" protection="18" />
<item name="android.permission.CONFIRM_FULL_BACKUP" package="android" protection="2" />
<item name="android.permission.PACKAGE_USAGE_STATS" package="android" protection="18" />
<item name="com.android.launcher.permission.READ_SETTINGS" package="com.android.launcher" />
<item name="android.permission.ACCESS_SURFACE_FLINGER" package="android" protection="2" />
<item name="android.permission.CHANGE_NETWORK_STATE" package="android" />
<item name="android.permission.PACKAGE_VERIFICATION_AGENT" package="android" protection="18" />
<item name="android.permission.GET_TASKS" package="android" protection="1" />
<item name="com.android.launcher.permission.PRELOAD_WORKSPACE" package="com.android.launcher" protection="18" />
<item name="android.permission.PROCESS_OUTGOING_CALLS" package="android" protection="1" />
<item name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE" package="android" protection="2" />
<item name="android.permission.SET_WALLPAPER_HINTS" package="android" />
<item name="android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK" package="android" protection="18" />
<item name="android.permission.BIND_TEXT_SERVICE" package="android" protection="2" />
<item name="android.permission.BROADCAST_STICKY" package="android" />
<item name="android.permission.GRANT_REVOKE_PERMISSIONS" package="android" protection="2" />
<item name="android.permission.WRITE_USER_DICTIONARY" package="android" />
<item name="android.permission.READ_FRAME_BUFFER" package="android" protection="18" />
<item name="android.permission.GET_PACKAGE_SIZE" package="android" />
<item name="android.permission.FORCE_BACK" package="android" protection="2" />
<item name="android.permission.UPDATE_DEVICE_STATS" package="android" protection="18" />
<item name="android.permission.NFC" package="android" protection="1" />
<item name="com.android.permission.HANDOVER_STATUS" package="com.android.bluetooth" protection="2" />
<item name="android.permission.WRITE_APN_SETTINGS" package="android" protection="18" />
<item name="android.permission.SET_ANIMATION_SCALE" package="android" protection="50" />
<item name="android.permission.SET_ORIENTATION" package="android" protection="2" />
<item name="android.permission.FACTORY_TEST" package="android" protection="2" />
<item name="android.permission.REORDER_TASKS" package="android" />
<item name="android.permission.BIND_KEYGUARD_APPWIDGET" package="android" protection="18" />
<item name="android.permission.MAGNIFY_DISPLAY" package="android" protection="2" />
<item name="android.permission.ASEC_MOUNT_UNMOUNT" package="android" protection="2" />
<item name="android.permission.SET_PROCESS_LIMIT" package="android" protection="50" />
<item name="android.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS" package="android" protection="18" />
<item name="android.permission.CHANGE_WIFI_STATE" package="android" protection="1" />
<item name="android.permission.BIND_DEVICE_ADMIN" package="android" protection="2" />
<item name="android.permission.READ_CALL_LOG" package="android" protection="1" />
<item name="com.android.gallery3d.permission.GALLERY_PROVIDER" package="com.android.gallery3d" protection="18" />
<item name="android.permission.SUBSCRIBED_FEEDS_WRITE" package="android" protection="1" />
<item name="android.permission.CLEAR_APP_USER_DATA" package="android" protection="2" />
<item name="android.permission.SHUTDOWN" package="android" protection="18" />
<item name="android.permission.READ_SOCIAL_STREAM" package="android" protection="1" />
<item name="android.permission.BIND_INPUT_METHOD" package="android" protection="2" />
<item name="android.permission.READ_USER_DICTIONARY" package="android" protection="1" />
<item name="android.permission.WRITE_CONTACTS" package="android" protection="1" />
<item name="android.permission.BIND_ACCESSIBILITY_SERVICE" package="android" protection="2" />
<item name="android.permission.READ_PHONE_STATE" package="android" protection="1" />
<item name="android.permission.ACCESS_DRM" package="com.android.providers.drm" protection="2" />
<item name="android.permission.DOWNLOAD_CACHE_NON_PURGEABLE" package="com.android.providers.downloads" protection="18" />
<item name="android.permission.SET_PREFERRED_APPLICATIONS" package="android" protection="2" />
<item name="android.permission.SET_SCREEN_COMPATIBILITY" package="android" protection="2" />
<item name="android.permission.MANAGE_ACCOUNTS" package="android" protection="1" />
<item name="android.permission.PERSISTENT_ACTIVITY" package="android" />
<item name="android.permission.FLASHLIGHT" package="android" />
<item name="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS" package="com.android.providers.downloads" protection="2" />
<item name="android.permission.BIND_DIRECTORY_SEARCH" package="android" protection="18" />
<item name="android.permission.SERIAL_PORT" package="android" protection="18" />
<item name="android.permission.SEND_SMS" package="android" protection="1" />
<item name="android.permission.CONFIGURE_WIFI_DISPLAY" package="android" protection="2" />
<item name="android.permission.HARDWARE_TEST" package="android" protection="2" />
<item name="android.permission.ACCESS_CHECKIN_PROPERTIES" package="android" protection="18" />
<item name="android.permission.KILL_BACKGROUND_PROCESSES" package="android" />
<item name="android.permission.CRYPT_KEEPER" package="android" protection="18" />
<item name="android.permission.EXPAND_STATUS_BAR" package="android" />
<item name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" package="android" />
<item name="android.permission.BIND_APPWIDGET" package="android" protection="18" />
<item name="android.permission.BROADCAST_SMS" package="android" protection="2" />
<item name="android.permission.DEVICE_POWER" package="android" protection="2" />
<item name="android.permission.CHANGE_CONFIGURATION" package="android" protection="50" />
<item name="android.permission.DELETE_PACKAGES" package="android" protection="18" />
<item name="android.permission.ACCESS_WIFI_STATE" package="android" />
<item name="com.android.permission.WHITELIST_BLUETOOTH_DEVICE" package="com.android.bluetooth" protection="2" />
<item name="android.permission.ACCESS_COARSE_LOCATION" package="android" protection="1" />
<item name="android.permission.READ_SMS" package="android" protection="1" />
<item name="android.permission.ACCESS_ALL_DOWNLOADS" package="com.android.providers.downloads" protection="2" />
<item name="android.permission.CONTROL_LOCATION_UPDATES" package="android" protection="18" />
<item name="android.permission.ACCESS_DOWNLOAD_MANAGER" package="com.android.providers.downloads" protection="18" />
<item name="android.permission.MANAGE_USB" package="android" protection="18" />
<item name="android.permission.CHANGE_WIMAX_STATE" package="android" protection="1" />
<item name="android.permission.SET_WALLPAPER_COMPONENT" package="android" protection="18" />
<item name="android.permission.DELETE_CACHE_FILES" package="android" protection="18" />
<item name="android.permission.READ_PRIVILEGED_PHONE_STATE" package="android" protection="18" />
<item name="com.android.smspush.WAPPUSH_MANAGER_BIND" package="com.android.smspush" protection="18" />
<item name="android.permission.INTERACT_ACROSS_USERS" package="android" protection="50" />
<item name="android.permission.READ_SYNC_SETTINGS" package="android" />
<item name="android.permission.ASEC_DESTROY" package="android" protection="2" />
<item name="android.permission.WRITE_SOCIAL_STREAM" package="android" protection="1" />
<item name="android.permission.SET_TIME_ZONE" package="android" />
<item name="android.permission.RECEIVE_DATA_ACTIVITY_CHANGE" package="android" protection="18" />
<item name="android.permission.RETRIEVE_WINDOW_CONTENT" package="android" protection="18" />
<item name="android.permission.INSTALL_DRM" package="com.android.providers.drm" />
<item name="android.permission.SET_ACTIVITY_WATCHER" package="android" protection="2" />
<item name="android.permission.BRICK" package="android" protection="2" />
<item name="android.permission.RECEIVE_SMS" package="android" protection="1" />
<item name="android.permission.CALL_PHONE" package="android" protection="1" />
<item name="android.permission.BACKUP" package="android" protection="18" />
<item name="android.permission.READ_CALENDAR" package="android" protection="1" />
<item name="android.permission.RECEIVE_BOOT_COMPLETED" package="android" />
<item name="android.permission.SET_TIME" package="android" protection="18" />
<item name="android.permission.ACCESS_FINE_LOCATION" package="android" protection="1" />
<item name="android.permission.STATUS_BAR_SERVICE" package="android" protection="2" />
<item name="android.permission.CONNECTIVITY_INTERNAL" package="android" protection="18" />
<item name="android.permission.RECORD_AUDIO" package="android" protection="1" />
<item name="android.permission.INSTALL_PACKAGES" package="android" protection="18" />
<item name="android.permission.PERFORM_CDMA_PROVISIONING" package="android" protection="18" />
<item name="com.android.launcher.permission.INSTALL_SHORTCUT" package="com.android.launcher" protection="1" />
<item name="android.permission.USE_CREDENTIALS" package="android" protection="1" />
<item name="android.permission.SET_POINTER_SPEED" package="android" protection="2" />
<item name="com.android.browser.permission.PRELOAD" package="com.android.browser" protection="18" />
<item name="android.permission.INTERACT_ACROSS_USERS_FULL" package="android" protection="2" />
<item name="android.permission.REMOVE_TASKS" package="android" protection="2" />
<item name="android.permission.RECEIVE_MMS" package="android" protection="1" />
<item name="android.permission.MODIFY_AUDIO_SETTINGS" package="android" />
<item name="android.permission.SYSTEM_ALERT_WINDOW" package="android" protection="1" />
<item name="android.permission.WRITE_SETTINGS" package="android" />
<item name="android.permission.CALL_PRIVILEGED" package="android" protection="18" />
<item name="android.permission.READ_DREAM_STATE" package="android" protection="2" />
<item name="com.android.launcher.permission.WRITE_SETTINGS" package="com.android.launcher" />
<item name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" package="com.android.providers.downloads" />
<item name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" package="android" protection="18" />
<item name="android.permission.SET_WALLPAPER" package="android" />
<item name="android.permission.DUMP" package="android" protection="50" />
<item name="android.permission.WRITE_GSERVICES" package="android" protection="18" />
<item name="android.permission.MANAGE_NETWORK_POLICY" package="android" protection="2" />
<item name="android.permission.USE_SIP" package="android" protection="1" />
<item name="android.permission.FREEZE_SCREEN" package="android" protection="2" />
<item name="com.android.voicemail.permission.READ_WRITE_ALL_VOICEMAIL" package="com.android.providers.contacts" protection="2" />
<item name="android.permission.BIND_WALLPAPER" package="android" protection="18" />
<item name="android.permission.WRITE_PROFILE" package="android" protection="1" />
<item name="android.permission.BROADCAST_PACKAGE_REMOVED" package="android" protection="2" />
<item name="android.permission.BIND_REMOTEVIEWS" package="android" protection="18" />
<item name="android.permission.SET_DEBUG_APP" package="android" protection="50" />
<item name="android.permission.TEMPORARY_ENABLE_ACCESSIBILITY" package="android" protection="2" />
<item name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY" package="android" protection="2" />
<item name="android.permission.VIBRATE" package="android" />
<item name="android.permission.READ_CELL_BROADCASTS" package="android" protection="1" />
</permissions>
<package name="com.android.soundrecorder" codePath="/system/app/SoundRecorder.apk" nativeLibraryPath="/data/app-lib/SoundRecorder" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10030">
<sigs count="1">
<cert index="0" key="308204a830820390a003020102020900936eacbe07f201df300d06092a864886f70d0101050500308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d301e170d3038303232393031333334365a170d3335303731373031333334365a308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d30820120300d06092a864886f70d01010105000382010d00308201080282010100d6931904dec60b24b1edc762e0d9d8253e3ecd6ceb1de2ff068ca8e8bca8cd6bd3786ea70aa76ce60ebb0f993559ffd93e77a943e7e83d4b64b8e4fea2d3e656f1e267a81bbfb230b578c20443be4c7218b846f5211586f038a14e89c2be387f8ebecf8fcac3da1ee330c9ea93d0a7c3dc4af350220d50080732e0809717ee6a053359e6a694ec2cb3f284a0a466c87a94d83b31093a67372e2f6412c06e6d42f15818dffe0381cc0cd444da6cddc3b82458194801b32564134fbfde98c9287748dbf5676a540d8154c8bbca07b9e247553311c46b9af76fdeeccc8e69e7c8a2d08e782620943f99727d3c04fe72991d99df9bae38a0b2177fa31d5b6afee91f020103a381fc3081f9301d0603551d0e04160414485900563d272c46ae118605a47419ac09ca8c113081c90603551d230481c13081be8014485900563d272c46ae118605a47419ac09ca8c11a1819aa48197308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d820900936eacbe07f201df300c0603551d13040530030101ff300d06092a864886f70d010105050003820101007aaf968ceb50c441055118d0daabaf015b8a765a27a715a2c2b44f221415ffdace03095abfa42df70708726c2069e5c36eddae0400be29452c084bc27eb6a17eac9dbe182c204eb15311f455d824b656dbe4dc2240912d7586fe88951d01a8feb5ae5a4260535df83431052422468c36e22c2a5ef994d61dd7306ae4c9f6951ba3c12f1d1914ddc61f1a62da2df827f603fea5603b2c540dbd7c019c36bab29a4271c117df523cdbc5f3817a49e0efa60cbd7f74177e7a4f193d43f4220772666e4c4d83e1bd5a86087cf34f2dec21e245ca6c2bb016e683638050d2c430eea7c26a1c49d3760a58ab7f1a82cc938b4831384324bd0401fa12163a50570e684d" />
</sigs>
</package>
<package name="com.android.voicedialer" codePath="/system/app/VoiceDialer.apk" nativeLibraryPath="/data/app-lib/VoiceDialer" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10001">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="com.android.launcher" codePath="/system/app/Launcher2.apk" nativeLibraryPath="/data/app-lib/Launcher2" flags="4767301" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10004">
<sigs count="1">
<cert index="1" key="308204a830820390a003020102020900f2a73396bd38767a300d06092a864886f70d0101040500308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d301e170d3038303732333231353735395a170d3335313230393231353735395a308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d30820120300d06092a864886f70d01010105000382010d00308201080282010100c8c2dbfd094a2df45c3ff1a32ed21805ec72fc58d017971bd0f6b52c262d70819d191967e158dfd3a2c7f1b3e0e80ce545d79d2848220211eb86f0fd8312d37b420c113750cc94618ae872f4886463bdc4627caa0c0483c86493e3515571170338bfdcc4cd6addd1c0a2f35f5cf24ed3e4043a3e58e2b05e664ccde12bcb67735fd6df1249c369e62542bc0a4729e53917f5c38ffa52d17b73c9c73798ddb18ed481590875547e66bfc5daca4c25a6eb960ed96923709da302ba646cb496b325e86c5c8b2e7a3377b2bbe4c7cf33254291163f689152ac088550c83c508f4bf5adf0aed5a2dca0583f9ab0ad17650db7eea4b23fdb45885547d0feab72183889020103a381fc3081f9301d0603551d0e04160414cb4c7e2cdbb3f0ada98dab79968d172e9dbb1ed13081c90603551d230481c13081be8014cb4c7e2cdbb3f0ada98dab79968d172e9dbb1ed1a1819aa48197308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d820900f2a73396bd38767a300c0603551d13040530030101ff300d06092a864886f70d0101040500038201010040a8d096997959e917a36c44246b6bac2bae05437ecd89794118f7834720352d1c6f8a39b0869942f4da65981faa2951d33971129ec1921d795671c527d6e249f252829faf5b591310311e2de096500d568ad4114a656dc34a8c6f610453afc1ea7992dba4aa7b3f8543a6e35c0728de77fe97eeac83771fd0ec90f8e4449434ee0b6045783e70c7a2e460249260e003cf7608dc352a4c9ef706def4b26050e978ae2fffd7a3323787014915eb3cc874fcc7a9ae930877c5c8c7d1c2e2a8ee863c89180d1855cedba400e7ba43cccaa7243d397e7c0e8e8e4d7d4f92b6bbead49c0cf018069eddca2e7e2fb4668d89dbbd7950d0cd254180fa1eaafc2a556f84" />
</sigs>
</package>
<package name="com.android.defcontainer" codePath="/system/app/DefaultContainerService.apk" nativeLibraryPath="/data/app-lib/DefaultContainerService" flags="540229" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10037">
<sigs count="1">
<cert index="2" key="308204a830820390a003020102020900b3998086d056cffa300d06092a864886f70d0101040500308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d301e170d3038303431353232343035305a170d3335303930313232343035305a308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d30820120300d06092a864886f70d01010105000382010d003082010802820101009c780592ac0d5d381cdeaa65ecc8a6006e36480c6d7207b12011be50863aabe2b55d009adf7146d6f2202280c7cd4d7bdb26243b8a806c26b34b137523a49268224904dc01493e7c0acf1a05c874f69b037b60309d9074d24280e16bad2a8734361951eaf72a482d09b204b1875e12ac98c1aa773d6800b9eafde56d58bed8e8da16f9a360099c37a834a6dfedb7b6b44a049e07a269fccf2c5496f2cf36d64df90a3b8d8f34a3baab4cf53371ab27719b3ba58754ad0c53fc14e1db45d51e234fbbe93c9ba4edf9ce54261350ec535607bf69a2ff4aa07db5f7ea200d09a6c1b49e21402f89ed1190893aab5a9180f152e82f85a45753cf5fc19071c5eec827020103a381fc3081f9301d0603551d0e041604144fe4a0b3dd9cba29f71d7287c4e7c38f2086c2993081c90603551d230481c13081be80144fe4a0b3dd9cba29f71d7287c4e7c38f2086c299a1819aa48197308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d820900b3998086d056cffa300c0603551d13040530030101ff300d06092a864886f70d01010405000382010100572551b8d93a1f73de0f6d469f86dad6701400293c88a0cd7cd778b73dafcc197fab76e6212e56c1c761cfc42fd733de52c50ae08814cefc0a3b5a1a4346054d829f1d82b42b2048bf88b5d14929ef85f60edd12d72d55657e22e3e85d04c831d613d19938bb8982247fa321256ba12d1d6a8f92ea1db1c373317ba0c037f0d1aff645aef224979fba6e7a14bc025c71b98138cef3ddfc059617cf24845cf7b40d6382f7275ed738495ab6e5931b9421765c491b72fb68e080dbdb58c2029d347c8b328ce43ef6a8b15533edfbe989bd6a48dd4b202eda94c6ab8dd5b8399203daae2ed446232e4fe9bd961394c6300e5138e3cfd285e6e4e483538cb8b1b357" />
</sigs>
</package>
<package name="com.android.quicksearchbox" codePath="/system/app/QuickSearchBox.apk" nativeLibraryPath="/data/app-lib/QuickSearchBox" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10017">
<sigs count="1">
<cert index="1" />
</sigs>
</package>
<package name="com.android.contacts" codePath="/data/app/Contacts.apk" nativeLibraryPath="/data/app-lib/Contacts" flags="572996" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" sharedUserId="10022">
<sigs count="1">
<cert index="1" />
</sigs>
<perms />
</package>
<package name="com.android.inputmethod.latin" codePath="/system/app/LatinIME.apk" nativeLibraryPath="/data/app-lib/LatinIME" flags="4767301" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10033">
<sigs count="1">
<cert index="1" />
</sigs>
</package>
<package name="com.android.phone" codePath="/system/app/Phone.apk" nativeLibraryPath="/data/app-lib/Phone" flags="573005" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" sharedUserId="1001">
<sigs count="1">
<cert index="2" />
</sigs>
</package>
<package name="com.android.calculator2" codePath="/system/app/Calculator.apk" nativeLibraryPath="/data/app-lib/Calculator" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10042">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="com.android.htmlviewer" codePath="/system/app/HTMLViewer.apk" nativeLibraryPath="/data/app-lib/HTMLViewer" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10040">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="com.android.providers.calendar" codePath="/system/app/CalendarProvider.apk" nativeLibraryPath="/data/app-lib/CalendarProvider" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" sharedUserId="10018">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="com.android.bluetooth" codePath="/system/app/Bluetooth.apk" nativeLibraryPath="/data/app-lib/Bluetooth" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" sharedUserId="1002">
<sigs count="1">
<cert index="2" />
</sigs>
</package>
<package name="com.android.inputdevices" codePath="/system/app/InputDevices.apk" nativeLibraryPath="/data/app-lib/InputDevices" flags="572933" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" sharedUserId="1000">
<sigs count="1">
<cert index="2" />
</sigs>
</package>
<package name="com.android.wallpaper.holospiral" codePath="/system/app/HoloSpiralWallpaper.apk" nativeLibraryPath="/data/app-lib/HoloSpiralWallpaper" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10035">
<sigs count="1">
<cert index="1" />
</sigs>
</package>
<package name="com.android.calendar" codePath="/system/app/Calendar.apk" nativeLibraryPath="/data/app-lib/Calendar" flags="638533" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10032">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="com.android.browser" codePath="/system/app/Browser.apk" nativeLibraryPath="/data/app-lib/Browser" flags="638533" ft="141150b0de0" it="141150b0de0" ut="141150b0de0" version="17" userId="10010">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="com.android.music" codePath="/system/app/Music.apk" nativeLibraryPath="/data/app-lib/Music" flags="573029" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10023">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="com.android.providers.downloads.ui" codePath="/system/app/DownloadProviderUi.apk" nativeLibraryPath="/data/app-lib/DownloadProviderUi" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" sharedUserId="10003">
<sigs count="1">
<cert index="3" key="308204a830820390a003020102020900f2b98e6123572c4e300d06092a864886f70d0101040500308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d301e170d3038303431353233343035375a170d3335303930313233343035375a308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d30820120300d06092a864886f70d01010105000382010d00308201080282010100ae250c5a16ef97fc2869ac651b3217cc36ba0e86964168d58a049f40ce85867123a3ffb4f6d949c33cf2da3a05c23eacaa57d803889b1759bcf59e7c6f21890ae25085b7ed56aa626c0989ef9ccd36362ca0e8d1b9603fd4d8328767926ccc090c68b775ae7ff30934cc369ef2855a2667df0c667fd0c7cf5d8eba655806737303bb624726eabaedfb72f07ed7a76ab3cb9a381c4b7dcd809b140d891f00213be401f58d6a06a61eadc3a9c2f1c6567285b09ae09342a66fa421eaf93adf7573a028c331d70601ab3af7cc84033ece7c772a3a5b86b0dbe9d777c3a48aa9801edcee2781589f44d9e4113979600576a99410ba81091259dad98c6c68ff784b8f020103a381fc3081f9301d0603551d0e04160414ca293caa8bc0ed3e542eef4205a2bff2b57e4d753081c90603551d230481c13081be8014ca293caa8bc0ed3e542eef4205a2bff2b57e4d75a1819aa48197308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d820900f2b98e6123572c4e300c0603551d13040530030101ff300d06092a864886f70d0101040500038201010084de9516d5e4a87217a73da8487048f53373a5f733f390d61bdf3cc9e5251625bfcaa7c3159cae275d172a9ae1e876d5458127ac542f68290dd510c0029d8f51e0ee156b7b7b5acdb394241b8ec78b74e5c42c5cafae156caf5bd199a23a27524da072debbe378464a533630b0e4d0ffb7e08ecb701fadb6379c74467f6e00c6ed888595380792038756007872c8e3007af423a57a2cab3a282869b64c4b7bd5fc187d0a7e2415965d5aae4e07a6df751b4a75e9793c918a612b81cd0b628aee0168dc44e47b10d3593260849d6adf6d727dc24444c221d3f9ecc368cad07999f2b8105bc1f20d38d41066cc1411c257a96ea4349f5746565507e4e8020a1a81" />
</sigs>
</package>
<package name="com.android.providers.userdictionary" codePath="/system/app/UserDictionaryProvider.apk" nativeLibraryPath="/data/app-lib/UserDictionaryProvider" flags="572933" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" sharedUserId="10022">
<sigs count="1">
<cert index="1" />
</sigs>
</package>
<package name="com.android.sharedstoragebackup" codePath="/system/app/SharedStorageBackup.apk" nativeLibraryPath="/data/app-lib/SharedStorageBackup" flags="638469" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10006">
<sigs count="1">
<cert index="2" />
</sigs>
</package>
<package name="com.android.inputmethod.pinyin" codePath="/system/app/PinyinIME.apk" nativeLibraryPath="/data/app-lib/PinyinIME" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10008">
<sigs count="1">
<cert index="1" />
</sigs>
</package>
<package name="com.android.vpndialogs" codePath="/system/app/VpnDialogs.apk" nativeLibraryPath="/data/app-lib/VpnDialogs" flags="540229" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10019">
<sigs count="1">
<cert index="2" />
</sigs>
</package>
<package name="com.android.mms" codePath="/system/app/Mms.apk" nativeLibraryPath="/data/app-lib/Mms" flags="573029" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10025">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="com.android.provision" codePath="/system/app/Provision.apk" nativeLibraryPath="/data/app-lib/Provision" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10007">
<sigs count="1">
<cert index="2" />
</sigs>
</package>
<package name="com.android.providers.media" codePath="/system/app/MediaProvider.apk" nativeLibraryPath="/data/app-lib/MediaProvider" flags="4767301" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="511" sharedUserId="10003">
<sigs count="1">
<cert index="3" />
</sigs>
</package>
<package name="com.android.certinstaller" codePath="/system/app/CertInstaller.apk" nativeLibraryPath="/data/app-lib/CertInstaller" flags="540229" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10011">
<sigs count="1">
<cert index="2" />
</sigs>
</package>
<package name="com.android.galaxy4" codePath="/system/app/Galaxy4.apk" nativeLibraryPath="/data/app-lib/Galaxy4" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="1" userId="10009">
<sigs count="1">
<cert index="1" />
</sigs>
</package>
<package name="com.android.dreams.phototable" codePath="/system/app/PhotoTable.apk" nativeLibraryPath="/data/app-lib/PhotoTable" flags="1621573" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10000">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="android" codePath="/system/framework/framework-res.apk" flags="4767241" ft="14100859340" it="14100859340" ut="14100859340" version="17" sharedUserId="1000">
<sigs count="1">
<cert index="2" />
</sigs>
</package>
<package name="com.android.settings" codePath="/system/app/Settings.apk" nativeLibraryPath="/data/app-lib/Settings" flags="4767301" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" sharedUserId="1000">
<sigs count="1">
<cert index="2" />
</sigs>
</package>
<package name="com.android.providers.contacts" codePath="/system/app/ContactsProvider.apk" nativeLibraryPath="/data/app-lib/ContactsProvider" flags="540229" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" sharedUserId="10022">
<sigs count="1">
<cert index="1" />
</sigs>
</package>
<package name="com.android.videoeditor" codePath="/system/app/VideoEditor.apk" nativeLibraryPath="/data/app-lib/VideoEditor" flags="1621573" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="11" userId="10024">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="com.android.providers.applications" codePath="/system/app/ApplicationsProvider.apk" nativeLibraryPath="/data/app-lib/ApplicationsProvider" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" sharedUserId="10022">
<sigs count="1">
<cert index="1" />
</sigs>
</package>
<package name="com.android.dreams.basic" codePath="/system/app/BasicDreams.apk" nativeLibraryPath="/data/app-lib/BasicDreams" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10015">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="com.android.providers.drm" codePath="/system/app/DrmProvider.apk" nativeLibraryPath="/data/app-lib/DrmProvider" flags="540229" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" sharedUserId="10003">
<sigs count="1">
<cert index="3" />
</sigs>
</package>
<package name="com.android.gallery3d" codePath="/system/app/Gallery2.apk" nativeLibraryPath="/data/app-lib/Gallery2" flags="1621061" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="40001" userId="10043">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="com.android.exchange" codePath="/system/app/Exchange2.apk" nativeLibraryPath="/data/app-lib/Exchange2" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="500000" userId="10002">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="com.android.musicvis" codePath="/system/app/VisualizationWallpapers.apk" nativeLibraryPath="/data/app-lib/VisualizationWallpapers" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10005">
<sigs count="1">
<cert index="1" />
</sigs>
</package>
<package name="com.android.systemui" codePath="/system/app/SystemUI.apk" nativeLibraryPath="/data/app-lib/SystemUI" flags="540173" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10027">
<sigs count="1">
<cert index="2" />
</sigs>
</package>
<package name="com.android.wallpaper.livepicker" codePath="/system/app/LiveWallpapersPicker.apk" nativeLibraryPath="/data/app-lib/LiveWallpapersPicker" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10016">
<sigs count="1">
<cert index="2" />
</sigs>
</package>
<package name="com.android.keychain" codePath="/system/app/KeyChain.apk" nativeLibraryPath="/data/app-lib/KeyChain" flags="540229" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" sharedUserId="1000">
<sigs count="1">
<cert index="2" />
</sigs>
</package>
<package name="com.android.speechrecorder" codePath="/system/app/SpeechRecorder.apk" nativeLibraryPath="/data/app-lib/SpeechRecorder" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10014">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="com.android.smspush" codePath="/system/app/WAPPushManager.apk" nativeLibraryPath="/data/app-lib/WAPPushManager" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10020">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="com.android.packageinstaller" codePath="/system/app/PackageInstaller.apk" nativeLibraryPath="/data/app-lib/PackageInstaller" flags="540229" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10012">
<sigs count="1">
<cert index="2" />
</sigs>
</package>
<package name="com.android.development" codePath="/system/app/Development.apk" nativeLibraryPath="/data/app-lib/Development" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="1" userId="10038">
<sigs count="1">
<cert index="2" />
</sigs>
</package>
<package name="com.android.providers.telephony" codePath="/system/app/TelephonyProvider.apk" nativeLibraryPath="/data/app-lib/TelephonyProvider" flags="540165" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" sharedUserId="1001">
<sigs count="1">
<cert index="2" />
</sigs>
</package>
<package name="com.android.wallpaper" codePath="/system/app/LiveWallpapers.apk" nativeLibraryPath="/data/app-lib/LiveWallpapers" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10039">
<sigs count="1">
<cert index="1" />
</sigs>
</package>
<package name="com.svox.pico" codePath="/system/app/PicoTts.apk" nativeLibraryPath="/data/app-lib/PicoTts" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="1" userId="10013">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="jp.co.omronsoft.openwnn" codePath="/system/app/OpenWnn.apk" nativeLibraryPath="/data/app-lib/OpenWnn" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10041">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="com.android.noisefield" codePath="/system/app/NoiseField.apk" nativeLibraryPath="/data/app-lib/NoiseField" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="1" userId="10036">
<sigs count="1">
<cert index="1" />
</sigs>
</package>
<package name="com.android.deskclock" codePath="/system/app/DeskClock.apk" nativeLibraryPath="/data/app-lib/DeskClock" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="203" userId="10026">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="com.android.backupconfirm" codePath="/system/app/BackupRestoreConfirmation.apk" nativeLibraryPath="/data/app-lib/BackupRestoreConfirmation" flags="540165" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10021">
<sigs count="1">
<cert index="2" />
</sigs>
</package>
<package name="com.android.location.fused" codePath="/system/app/FusedLocation.apk" nativeLibraryPath="/data/app-lib/FusedLocation" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10034">
<sigs count="1">
<cert index="2" />
</sigs>
</package>
<package name="com.android.providers.settings" codePath="/system/app/SettingsProvider.apk" nativeLibraryPath="/data/app-lib/SettingsProvider" flags="572933" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" sharedUserId="1000">
<sigs count="1">
<cert index="2" />
</sigs>
</package>
<package name="com.android.magicsmoke" codePath="/system/app/MagicSmokeWallpapers.apk" nativeLibraryPath="/data/app-lib/MagicSmokeWallpapers" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" userId="10031">
<sigs count="1">
<cert index="1" />
</sigs>
</package>
<package name="com.android.providers.downloads" codePath="/system/app/DownloadProvider.apk" nativeLibraryPath="/data/app-lib/DownloadProvider" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="17" sharedUserId="10003">
<sigs count="1">
<cert index="3" />
</sigs>
</package>
<package name="com.android.musicfx" codePath="/system/app/MusicFX.apk" nativeLibraryPath="/data/app-lib/MusicFX" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="10400" userId="10029">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
<package name="com.android.phasebeam" codePath="/system/app/PhaseBeam.apk" nativeLibraryPath="/data/app-lib/PhaseBeam" flags="572997" ft="141150b09f8" it="141150b09f8" ut="141150b09f8" version="1" userId="10028">
<sigs count="1">
<cert index="1" />
</sigs>
</package>
<shared-user name="android.uid.shared" userId="10022">
<sigs count="1">
<cert index="1" />
</sigs>
<perms>
<item name="android.permission.READ_EXTERNAL_STORAGE" />
<item name="android.permission.WRITE_EXTERNAL_STORAGE" />
<item name="android.permission.WRITE_CALL_LOG" />
<item name="android.permission.READ_SOCIAL_STREAM" />
<item name="android.permission.ACCESS_COARSE_LOCATION" />
<item name="android.permission.READ_CONTACTS" />
<item name="android.permission.GET_ACCOUNTS" />
<item name="android.permission.WRITE_CONTACTS" />
<item name="android.permission.READ_PHONE_STATE" />
<item name="android.permission.RECEIVE_BOOT_COMPLETED" />
<item name="android.permission.ACCESS_FINE_LOCATION" />
<item name="android.permission.MANAGE_ACCOUNTS" />
<item name="android.permission.WAKE_LOCK" />
<item name="android.permission.NFC" />
<item name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<item name="android.permission.USE_CREDENTIALS" />
<item name="com.android.voicemail.permission.ADD_VOICEMAIL" />
<item name="android.permission.BIND_DIRECTORY_SEARCH" />
<item name="com.android.voicemail.permission.READ_WRITE_ALL_VOICEMAIL" />
<item name="android.permission.WRITE_PROFILE" />
<item name="android.permission.MODIFY_AUDIO_SETTINGS" />
<item name="android.permission.READ_PROFILE" />
<item name="android.permission.INTERNET" />
<item name="android.permission.WRITE_SETTINGS" />
<item name="android.permission.READ_SYNC_SETTINGS" />
<item name="android.permission.VIBRATE" />
<item name="android.permission.READ_CALL_LOG" />
<item name="android.permission.PACKAGE_USAGE_STATS" />
</perms>
</shared-user>
<shared-user name="android.uid.log" userId="1007">
<perms />
</shared-user>
<shared-user name="android.media" userId="10003">
<sigs count="1">
<cert index="3" />
</sigs>
<perms>
<item name="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS" />
<item name="android.permission.READ_EXTERNAL_STORAGE" />
<item name="android.permission.RECEIVE_WAP_PUSH" />
<item name="android.permission.ACCESS_CACHE_FILESYSTEM" />
<item name="android.permission.WRITE_MEDIA_STORAGE" />
<item name="android.permission.WRITE_EXTERNAL_STORAGE" />
<item name="android.permission.MODIFY_NETWORK_ACCOUNTING" />
<item name="android.permission.ACCESS_MTP" />
<item name="android.permission.RECEIVE_BOOT_COMPLETED" />
<item name="android.permission.MANAGE_USERS" />
<item name="android.permission.ACCESS_ALL_DOWNLOADS" />
<item name="android.permission.WRITE_SETTINGS" />
<item name="android.permission.INTERNET" />
<item name="android.permission.INTERACT_ACROSS_USERS" />
<item name="android.permission.ACCESS_DOWNLOAD_MANAGER" />
<item name="android.permission.CONNECTIVITY_INTERNAL" />
<item name="android.permission.WAKE_LOCK" />
<item name="android.permission.ACCESS_NETWORK_STATE" />
<item name="android.permission.UPDATE_DEVICE_STATS" />
</perms>
</shared-user>
<shared-user name="android.uid.phone" userId="1001">
<sigs count="1">
<cert index="2" />
</sigs>
<perms>
<item name="android.permission.WRITE_CALL_LOG" />
<item name="android.permission.SHUTDOWN" />
<item name="android.permission.CALL_PHONE" />
<item name="android.permission.READ_CONTACTS" />
<item name="android.permission.WRITE_CONTACTS" />
<item name="android.permission.READ_PHONE_STATE" />
<item name="android.permission.RECEIVE_BOOT_COMPLETED" />
<item name="android.permission.MANAGE_USERS" />
<item name="android.permission.SEND_SMS_NO_CONFIRMATION" />
<item name="android.permission.INTERNAL_SYSTEM_WINDOW" />
<item name="android.permission.WAKE_LOCK" />
<item name="android.permission.ACCESS_NETWORK_STATE" />
<item name="android.permission.RECORD_AUDIO" />
<item name="android.permission.PERFORM_CDMA_PROVISIONING" />
<item name="android.permission.SEND_SMS" />
<item name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<item name="android.permission.WRITE_SECURE_SETTINGS" />
<item name="android.permission.MODIFY_AUDIO_SETTINGS" />
<item name="android.permission.DISABLE_KEYGUARD" />
<item name="android.permission.SYSTEM_ALERT_WINDOW" />
<item name="android.permission.MODIFY_PHONE_STATE" />
<item name="android.permission.WRITE_SETTINGS" />
<item name="android.permission.BLUETOOTH" />
<item name="android.permission.INTERNET" />
<item name="android.permission.UPDATE_LOCK" />
<item name="android.permission.BROADCAST_SMS" />
<item name="android.permission.BLUETOOTH_ADMIN" />
<item name="android.permission.CHANGE_NETWORK_STATE" />
<item name="android.permission.CALL_PRIVILEGED" />
<item name="android.permission.DEVICE_POWER" />
<item name="android.permission.CHANGE_CONFIGURATION" />
<item name="android.permission.READ_EXTERNAL_STORAGE" />
<item name="android.permission.PROCESS_OUTGOING_CALLS" />
<item name="android.permission.WRITE_EXTERNAL_STORAGE" />
<item name="android.permission.BROADCAST_WAP_PUSH" />
<item name="android.permission.REBOOT" />
<item name="android.permission.WRITE_SMS" />
<item name="android.permission.ACCESS_WIFI_STATE" />
<item name="android.permission.STATUS_BAR" />
<item name="android.permission.ACCESS_COARSE_LOCATION" />
<item name="android.permission.READ_SMS" />
<item name="android.permission.STOP_APP_SWITCHES" />
<item name="android.permission.BROADCAST_STICKY" />
<item name="android.permission.USE_SIP" />
<item name="android.permission.WRITE_APN_SETTINGS" />
<item name="android.permission.REORDER_TASKS" />
<item name="android.permission.CHANGE_WIFI_STATE" />
<item name="com.android.smspush.WAPPUSH_MANAGER_BIND" />
<item name="android.permission.VIBRATE" />
<item name="android.permission.READ_CALL_LOG" />
<item name="android.permission.SET_TIME_ZONE" />
</perms>
</shared-user>
<shared-user name="android.uid.bluetooth" userId="1002">
<sigs count="1">
<cert index="2" />
</sigs>
<perms>
<item name="android.permission.READ_EXTERNAL_STORAGE" />
<item name="android.permission.WRITE_EXTERNAL_STORAGE" />
<item name="android.permission.READ_CONTACTS" />
<item name="android.permission.READ_PHONE_STATE" />
<item name="android.permission.RECEIVE_BOOT_COMPLETED" />
<item name="android.permission.MANAGE_USERS" />
<item name="android.permission.CONNECTIVITY_INTERNAL" />
<item name="android.permission.WAKE_LOCK" />
<item name="android.permission.ACCESS_NETWORK_STATE" />
<item name="android.permission.NET_ADMIN" />
<item name="android.permission.BLUETOOTH_STACK" />
<item name="com.android.permission.HANDOVER_STATUS" />
<item name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<item name="android.permission.ACCESS_BLUETOOTH_SHARE" />
<item name="android.permission.WRITE_SECURE_SETTINGS" />
<item name="android.permission.MODIFY_AUDIO_SETTINGS" />
<item name="android.permission.READ_PROFILE" />
<item name="android.permission.MODIFY_PHONE_STATE" />
<item name="android.permission.INTERNET" />
<item name="android.permission.BLUETOOTH" />
<item name="android.permission.WRITE_SETTINGS" />
<item name="android.permission.INTERACT_ACROSS_USERS" />
<item name="android.permission.NET_TUNNELING" />
<item name="android.permission.READ_CALL_LOG" />
<item name="com.android.gallery3d.permission.GALLERY_PROVIDER" />
<item name="android.permission.BLUETOOTH_ADMIN" />
<item name="android.permission.CHANGE_NETWORK_STATE" />
<item name="android.permission.CALL_PRIVILEGED" />
</perms>
</shared-user>
<shared-user name="android.uid.system" userId="1000">
<sigs count="1">
<cert index="2" />
</sigs>
<perms>
<item name="android.permission.MASTER_CLEAR" />
<item name="android.permission.CLEAR_APP_USER_DATA" />
<item name="android.permission.CALL_PHONE" />
<item name="android.permission.READ_CONTACTS" />
<item name="android.permission.READ_USER_DICTIONARY" />
<item name="android.permission.WRITE_CONTACTS" />
<item name="android.permission.BACKUP" />
<item name="android.permission.READ_PHONE_STATE" />
<item name="android.permission.ACCESS_WIMAX_STATE" />
<item name="android.permission.MANAGE_USERS" />
<item name="android.permission.ACCESS_NETWORK_STATE" />
<item name="android.permission.USE_CREDENTIALS" />
<item name="android.permission.SET_POINTER_SPEED" />
<item name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<item name="android.permission.MOVE_PACKAGE" />
<item name="android.permission.CONFIGURE_WIFI_DISPLAY" />
<item name="android.permission.HARDWARE_TEST" />
<item name="android.permission.WRITE_SECURE_SETTINGS" />
<item name="android.permission.ACCESS_CHECKIN_PROPERTIES" />
<item name="android.permission.MODIFY_AUDIO_SETTINGS" />
<item name="android.permission.FORCE_STOP_PACKAGES" />
<item name="android.permission.READ_SYNC_STATS" />
<item name="android.permission.WRITE_SYNC_SETTINGS" />
<item name="android.permission.MODIFY_PHONE_STATE" />
<item name="android.permission.WRITE_SETTINGS" />
<item name="android.permission.BLUETOOTH" />
<item name="android.permission.INTERNET" />
<item name="android.permission.CONFIRM_FULL_BACKUP" />
<item name="android.permission.PACKAGE_USAGE_STATS" />
<item name="com.android.launcher.permission.READ_SETTINGS" />
<item name="android.permission.BLUETOOTH_ADMIN" />
<item name="android.permission.DEVICE_POWER" />
<item name="android.permission.CHANGE_CONFIGURATION" />
<item name="com.android.launcher.permission.WRITE_SETTINGS" />
<item name="android.permission.READ_EXTERNAL_STORAGE" />
<item name="android.permission.WRITE_EXTERNAL_STORAGE" />
<item name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE" />
<item name="android.permission.ACCESS_WIFI_STATE" />
<item name="android.permission.ACCESS_COARSE_LOCATION" />
<item name="android.permission.STATUS_BAR" />
<item name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<item name="android.permission.WRITE_USER_DICTIONARY" />
<item name="android.permission.ACCESS_DOWNLOAD_MANAGER" />
<item name="android.permission.SET_KEYBOARD_LAYOUT" />
<item name="android.permission.MANAGE_USB" />
<item name="android.permission.NFC" />
<item name="android.permission.CHANGE_WIMAX_STATE" />
<item name="android.permission.WRITE_APN_SETTINGS" />
<item name="android.permission.BATTERY_STATS" />
<item name="android.permission.READ_PROFILE" />
<item name="android.permission.CHANGE_WIFI_STATE" />
<item name="android.permission.READ_SYNC_SETTINGS" />
<item name="android.permission.VIBRATE" />
<item name="android.permission.COPY_PROTECTED_DATA" />
</perms>
</shared-user>
<shared-user name="android.uid.calendar" userId="10018">
<sigs count="1">
<cert index="0" />
</sigs>
<perms>
<item name="android.permission.READ_EXTERNAL_STORAGE" />
<item name="android.permission.USE_CREDENTIALS" />
<item name="android.permission.WRITE_EXTERNAL_STORAGE" />
<item name="android.permission.GET_ACCOUNTS" />
<item name="android.permission.WRITE_CALENDAR" />
<item name="android.permission.READ_SYNC_STATS" />
<item name="android.permission.READ_CALENDAR" />
<item name="android.permission.WRITE_SYNC_SETTINGS" />
<item name="android.permission.RECEIVE_BOOT_COMPLETED" />
<item name="android.permission.INTERNET" />
<item name="android.permission.READ_SYNC_SETTINGS" />
<item name="android.permission.SUBSCRIBED_FEEDS_READ" />
<item name="android.permission.MANAGE_ACCOUNTS" />
<item name="android.permission.SUBSCRIBED_FEEDS_WRITE" />
<item name="android.permission.WAKE_LOCK" />
</perms>
</shared-user>
<shared-user name="android.uid.nfc" userId="1027">
<perms />
</shared-user>
</packages>

主要是一些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来完成的,主要是一些目录的创建等。

我们看一下相关的流程图

Install 是一个后台进程:


在启动他的时候会创建一个"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<paths.length; i++) {
                    try {
                        if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {//需要优化?
                            libFiles.add(paths[i]);
                            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!");
            }

            /**
             * Also ensure all external libraries have had dexopt run on them.
             */
            if (mSharedLibraries.size() > 0) {//确保 外部库也被 优化
                Iterator<String> 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<frameworkFiles.length; i++) {//优化/system/framework目录下的文件
                    File libPath = new File(mFrameworkDir, frameworkFiles[i]);
                    String path = libPath.getPath();
                    // Skip the file if we alrady did it.
                    if (libFiles.contains(path)) {//已经包含过,包含过的都优化了
                        continue;
                    }
                    // Skip the file if it is not a type we want to dexopt.
                    if (!path.endsWith(".apk") && !path.endsWith(".jar")) {//跳过不符合条件的
                        continue;
                    }
                    try {
                        if (dalvik.system.DexFile.isDexOptNeeded(path)) {//需要优化
                            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);
                    }
                }
            }

七、启动AppDirObserver线程往中监测

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

八、调用scanDirLI启动apk解析

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


 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<files.length; i++) {
            File file = new File(dir, files[i]);
            if (!isPackageFilename(files[i])) {//是apk
                // Ignore entries which are not apk's8
                continue;
            }
            PackageParser.Package pkg = scanPackageLI(file,
                    flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);//user 为null
            // Don't mess around with apps in system partition.
            if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
                    mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
                // Delete the apk
                Slog.w(TAG, "Cleaning up failed install of " + file);
                file.delete();//安装失败,删除文件
            }
        }
}

主要是对该目录下面的所有文件,首先判断其是否是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<BasePermission> 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<String> origPermissions = gp.grantedPermissions;
        boolean changedPermission = false;

        if (replace) {
            ps.permissionsFixed = false;
            if (gp == ps) {
                origPermissions = new HashSet<String>(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<N; i++) {
            final String name = pkg.requestedPermissions.get(i);//package请求权限名
            //final boolean required = pkg.requestedPermssionsRequired.get(i);
            final BasePermission bp = mSettings.mPermissions.get(name);//获取该 name的BasePermission
            if (DEBUG_INSTALL) {
                if (gp != ps) {
                    Log.i(TAG, "Package " + pkg.packageName + " checking " + name + ": " + bp);
                }
            }
            if (bp != null && bp.packageSetting != null) {
                final String perm = bp.name;
                boolean allowed;
                boolean allowedSig = false;
                final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;//保护级别
                if (level == PermissionInfo.PROTECTION_NORMAL
                        || level == PermissionInfo.PROTECTION_DANGEROUS) {
                    allowed = true;//允许赋予权限
                } else if (bp.packageSetting == null) {
                    // This permission is invalid; skip it.
                    allowed = false;//不允许赋予权限
                } else if (level == PermissionInfo.PROTECTION_SIGNATURE) {//更改签名来赋予权限
                    allowed = (compareSignatures(
                            bp.packageSetting.signatures.mSignatures, pkg.mSignatures)
                                    == PackageManager.SIGNATURE_MATCH)
                            || (compareSignatures(mPlatformPackage.mSignatures, pkg.mSignatures)
                                    == PackageManager.SIGNATURE_MATCH);
                    if (!allowed && (bp.protectionLevel
                            & PermissionInfo.PROTECTION_FLAG_SYSTEM) != 0) {
                        if (isSystemApp(pkg)) {
                            // For updated system applications, a system permission
                            // is granted only if it had been defined by the original application.
                            if (isUpdatedSystemApp(pkg)) {
                                final PackageSetting sysPs = mSettings
                                        .getDisabledSystemPkgLPr(pkg.packageName);
                                final GrantedPermissions origGp = sysPs.sharedUser != null
                                        ? sysPs.sharedUser : sysPs;
                                if (origGp.grantedPermissions.contains(perm)) {
                                    allowed = true;
                                } else {
                                    allowed = false;
                                }
                            } else {
                                allowed = true;
                            }
                        }
                    }
                    if (!allowed && (bp.protectionLevel
                            & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
                        // For development permissions, a development permission
                        // is granted only if it was already granted.
                        if (origPermissions.contains(perm)) {
                            allowed = true;
                        } else {
                            allowed = false;
                        }
                    }
                    if (allowed) {
                        allowedSig = true;
                    }
                } else {
                    allowed = false;
                }
                if (DEBUG_INSTALL) {
                    if (gp != ps) {
                        Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
                    }
                }
                if (allowed) {
                    if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
                            && ps.permissionsFixed) {//已经存在的非系统apk,我们不能给他添加新的权限
                        // If this is an existing, non-system package, then
                        // we can't add any new permissions to it.
                        if (!allowedSig && !gp.grantedPermissions.contains(perm)) {
                            allowed = false;
                            // Except...  if this is a permission that was added
                            // to the platform (note: need to only do this when
                            // updating the platform).
                            final int NP = PackageParser.NEW_PERMISSIONS.length;
                            for (int ip=0; ip<NP; ip++) {
                                final PackageParser.NewPermissionInfo npi
                                        = PackageParser.NEW_PERMISSIONS[ip];
                                if (npi.name.equals(perm)
                                        && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
                                    allowed = true;
                                    Log.i(TAG, "Auto-granting " + perm + " to old pkg "
                                            + pkg.packageName);
                                    break;
                                }
                            }
                        }
                    }
                    if (allowed) {//允许
                        if (!gp.grantedPermissions.contains(perm)) {
                            changedPermission = true;
                            gp.grantedPermissions.add(perm);//权限添加到该PackageSetting的grantedPermissions
                            gp.gids = appendInts(gp.gids, bp.gids);//该权限所属的组添加到gids
                        } else if (!ps.haveGids) {
                            gp.gids = appendInts(gp.gids, bp.gids);
                        }
                    } else {
                        Slog.w(TAG, "Not granting permission " + perm
                                + " to package " + pkg.packageName
                                + " because it was previously installed without");
                    }
                } else {
                    if (gp.grantedPermissions.remove(perm)) {
                        changedPermission = true;
                        gp.gids = removeInts(gp.gids, bp.gids);
                        Slog.i(TAG, "Un-granting permission " + perm
                                + " from package " + pkg.packageName
                                + " (protectionLevel=" + bp.protectionLevel
                                + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
                                + ")");
                    } else {
                        Slog.w(TAG, "Not granting permission " + perm
                                + " to package " + pkg.packageName
                                + " (protectionLevel=" + bp.protectionLevel
                                + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
                                + ")");
                    }
                }
            } else {
                Slog.w(TAG, "Unknown permission " + name
                        + " in package " + pkg.packageName);
            }
        }

        if ((changedPermission || replace) && !ps.permissionsFixed &&
                ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
                ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
            // This is the first that we have heard about this package, so the
            // permissions we have now selected are fixed until explicitly
            // changed.第一次赋予权限后将permissionsFixed设置为true
            ps.permissionsFixed = true;
        }
        ps.haveGids = true;
    }

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


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

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


相关代码:

 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<String, String> 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等的信息。


  • 0
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
Android 12 SystemServer启动流程如下: 1. 引导加载:系统启动时,先加载引导程序,进行硬件初始化、内核加载等操作。 2. Zygote 进程启动:Zygote 是 Android 系统中的一个特殊进程,负责孵化其他应用进程。Zygote 进程会预加载一些常用的类和资源,以加快应用的启动速度。 3. SystemServer 进程启动:Zygote 进程会 fork 出 SystemServer 进程,该进程是 Android 系统中的核心服务进程。SystemServer 进程负责启动和管理系统级别的服务,例如 ActivityManagerServicePackageManagerService、WindowManagerService 等。 4. SystemServer 初始化:SystemServer 进程启动后,会进行一系列的初始化操作。首先会创建 Looper 线程,用于接收消息并处理各个服务的初始化工作。然后依次创建各个系统服务,并调用它们的启动方法。 5. 启动系统服务:SystemServer 进程会按照一定顺序启动各个系统服务。每个系统服务都有自己的初始化流程,例如 PackageManagerService 会加载应用程序列表、数据目录等;ActivityManagerService初始化进程间通信机制等。 6. 启动应用进程:在系统服务启动完成后,SystemServer 进程会通过 Zygote 孵化出其他应用进程。应用进程会根据 AndroidManifest.xml 中的配置进行初始化,包括创建 Application、加载资源等。 总结来说,Android 12 SystemServer启动流程包括引导加载、Zygote 进程启动、SystemServer 进程启动、SystemServer 初始化启动系统服务和启动应用进程等步骤。这些步骤都是为了在系统启动时提供必要的服务和资源。
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值