PackageManagerService启动及初始化流程

2023-11-12

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


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PackageManagerService启动及初始化流程 的相关文章

  • matlab如何读取一个文件夹下所有文件,Matlab获取一个文件夹下所有文件名

    Matlab获取一个文件夹下所有文件名 fileFolder fullfile D MATLAB bin trc dirOutput dir fullfile fileFolder trc fileNames dirOutput name
  • 解决IDEA中ctrl+shift+f快捷键搜索没反应的问题

    文章目录 0写在前面 1 问题解决 1 1 直接切换英文输入法 1 2 win10 输入法 1 3 搜狗输入法 1 4 其他 2 写在末尾 0写在前面 今天想使用 在文件中查询 功能 使用ctrl shift f进行搜索的时候 疯狂的按组合
  • keil CMSIS_DAP.DLL missing

    由于keil版本支持问题 可以下载以下版本的CMSIS DAP DLL进行替换 CMSIS DAP DLL官方下载地址 百度云下载 提取码 g8ia keil安装目录如 D Keil v5 ARM BIN 先删除原来的CMSIS DAP D
  • MySQL存储过程遍历游标用loop嵌套循环的例子

    CREATE DEFINER root PROCEDURE procInitData IN sId1 INT IN sId2 INT IN sId3 INT IN sId4 INT IN sId5 INT IN sId6 INT IN sI
  • 函数调用约定cdecl、stdcall、fastcall

    我们在编写代码的时候都会调用函数 有点函数有多个参数 例如 int test int a char b char c 上面的函数调用方式是test 10 c tinus 那么这个函数编译器是怎么知道有多少个参数 参数类型是什么了 因为函数调
  • 基于FPGA的LCD1602驱动(含代码)

    目录 LCD1602显示原理 LCD1602接口 LCD1602操作时序 1 读操作时序 2 写操作时序 LCD1602初始化 LCD1602读写数据 LCD1602显示原理 将LCD显示屏与FPGA连接之后 需要做的第一件事就是进行LCD
  • Redis底层封装细节

    日常我们程序员在使用redis做缓存的时候 很少会直接使用到RedisTemplate直接操作k v键值对 而是通过对RedisTemplate原生代码的封装 来构建我们日常便于使用习惯的代码来操作数据 这里我分享一下日常基本的对Redis
  • 【华为OD机试】矩阵元素的边界值【2023 B卷

    华为OD机试 真题 点这里 华为OD机试 真题考点分类 点这里 题目描述 给定一个N M矩阵 请先找出M个该矩阵中每列元素的最大值 然后输出这M个值中的最小值 输入描述 无 输出描述 无 备注 N和M的取值范围均为 0 100 用例1 输入
  • umi+dva+antd后台管理系统(3)---完整登录逻辑

    源码在这儿MyGithub 觉得不错留颗小星星哦 界面准备好啦 开始写登录 1 回顾一下redux是什么 redux 是一个应用数据流框架 主要解决了组件间状态共享的问题 原理是集中式管理 可以让数据更可控 react 中所有数据处理都在
  • JS加减乘除位移方法封装

    常用加减乘除等方法汇总 直接上代码 逻辑简单 代码如下 div 加减乘除位移方法汇总 div
  • 轨迹预处理(轨迹压缩)

    轨迹压缩分为在线压缩和离线压缩两类 在介绍两类压缩算法之前 本文先介绍两种 距离度量 方法 第一种距离度量方法是 垂直的欧几里得距离 如图b所示 p1 p7 p12作为压缩后的点 垂直度量 则为做垂线计算 第二种距离度量方法是 时间同步的欧
  • Dynamics CRM2011 导入解决方案报根组件插入错误的解决方法

    今天在还原一个老版本的解决方案 在导入时报根组件插入问题 Cannot add a Root Component 38974590 9322 e311 b365 00155d810a00 of type 31 because it is n
  • android: ERROR: unknown virtual device nam

    环境变量 ANDROID SDK HOME your path 设置好就没有问题了
  • 刷脸支付服务商为各行各业提供完美体验

    随着刷脸支付技术迭代更新的速度加快 其商业化应用的步伐也越来越快了 4月17日 支付宝推出第二代基于线下消费场景的刷脸支付机具 蜻蜓2 0 定价1499元 同时 新一代蜻蜓还实现了刷脸注册会员卡的功能 切中了苦于获客高成本的线下零售门店的需
  • pve 使用noVNC num lock 不同步的问题

    问题描述 在使用 pve 的noVNC 控制台 访问 WINDOWS 虚拟机时 VM 会出现num lock 状态不同步的情况 主要是由于WINDOWS 笔者这里是 SERVER2022 启动后默认关闭了 num lock 而 pve的虚拟

随机推荐

  • Scala中的抽象类

    1 先看下 类的层次结构 类层次结构 也称为类分类法 是一组相关的类 它们通过继承连接起来做类似的事情 层次结构的顶部可以是一个基类 它下面的所有其他类都是从中派生出来的 或者层次结构可以有多个基类 这些基类的功能稍后会在一个或多个派生类中
  • 论文阅读-Multi-attentional Deepfake Detection

    一 论文信息 题目 Multi attentional Deepfake Detection 作者团队 会议 CVPR 2021 二 背景与创新 背景 之前大多数方法将deepfake检测模型作为一个普通的二分类问题 即首先使用骨干网络提取
  • Redis面试题

    1 基本概念 1 1 常见考点 1 Redis 为何这么快 1 基于内存 2 单线程减少上下文切换 同时保证原子性 3 IO多路复用 4 高级数据结构 如 SDS Hash以及跳表等 2 为何使用单线程 因为 Redis 是基于内存的操作
  • esp32 系列芯片分类

    模组 内置芯片 Flash PSRAM 模组尺寸 mm ESP32 WROVER PCB ESP32 D0WDQ6 4M 8M 18 00 0 10 x 31 40 0 10 x 3 30 0 10 ESP32 WROVER IPEX ES
  • 微信公众号一些错误的原因错误代码41001

    微信公众号一些错误的原因错误代码41001 错误代码41001 缺少access token 碰到这种错误 请检查自己的appid和appsecret posted on 2017 05 08 18 02 baker95935 阅读 评论
  • git如何上传所有的新文件

    目的描述 新建的git项目 项目中有许多要从本地上传到git仓库的新文件 如果用git a filename的方法一个一个的添加 太费事费力 需要有命令添加所有改动 步骤 进入项目文件夹 在其中使用git bash 1 使用git clon
  • MySQL和MongoDB那些事

    什么是 MySQL 和 MongoDB MySQL 和 MongoDB 是两个可用于存储和管理数据的数据库管理系统 MySQL 是一个关系数据库系统 以结构化表格格式存储数据 相比之下 MongoDB 以更灵活的格式将数据存储为 JSON
  • VC++ CSWDirectoryListCtrl磁盘文件列表

    效果图 头文件定义 CSWDirectoryListCtrl h pragma once include afxwin h include
  • leetcode 3. 最长不含重复的子字符串的五种解法

    leetcode链接 最长不含重复的子字符串 题目描述 给定一个字符串 s 请你找出其中不含有重复字符的 最长子串 的长度 示例 1 输入 s abcabcbb 输出 3 解释 因为无重复字符的最长子串是 abc 所以其长度为 3 示例 2
  • Android优化之启动优化和黑白屏优化

    文章目录 一 启动流程 1 开机启动流程 2 app启动流程 二 启动分类 三 黑白屏优化 1 写一个xml文件 activity welcome 2 welcomeActivity类 四 启动优化 1 获取启动时间 2 启动优化方向 一
  • Linux网络配置不生效

    关于解决Linux网络配置文件 修改不生效问题的解决方案 注意 外部问题 例如虚拟网卡 网段及网卡连通问题另行查找相关解决方案 本博客仅介绍比较生僻的Linux系统配置文件不生效有关问题 先看下产生的问题 修改为静态ip却不生效 我们按照正
  • 解决Echarts中双坐标轴分割错位问题

    1 处理函数 Description 刻度最大值 date 2023 08 30 param any isNaN maxValue 1 returns any export const getYAxisMax maxValue number
  • k8s yaml文件

    简介 YAML IPA j m l 尾音类似camel骆驼 是一个可读性高 用来表达资料序列的编程语言 YAML参考了其他多种语言 包括 XML C语言 Python Perl以及电子邮件格式RFC2822 Clark Evans在2001
  • C++基础之初始化、输入输出安全问题及常量问题

    一 C 统一初始化 初始化列表 解决方案 例1 int main int a 10 int b 10 int c 10 初始化列表 int arr 10 1 2 4 5 6 int brr 10 1 2 3 4 5 6 int crr 1
  • GAMES101回顾 -- Geometry

    Geometry Examples of geometry 隐式几何 Inplict 定义 用函数进行表示 如 f x y z 0 显式几何 Explict 定义 所有点都是直接或通过参数映射给出 所有的 u v 映射到对应的 x y z
  • 【毕业设计】爱琴海——基于HTML5的婚庆用品商城网页设计

    一 内容简介 一 背景与意义 婚俗 是指结婚的风俗 各国各族人民按照自己的习俗 举行各具特色的婚礼 具有各自浓厚的民族独特风采 婚俗元素在是中国婚俗文化的媒介 承载了中华儿女对幸福和吉祥的追求 在中国婚俗文化的发展过程中 婚庆用品设计一直在
  • 题目 2307: 蓝桥杯2019年第十届省赛真题-灵能传输

    题目 在游戏 星际争霸 II 中 高阶圣堂武士作为星灵的重要 AOE 单位 在 游戏的中后期发挥着重要的作用 其技能 灵能风暴 可以消耗大量的灵能对 一片区域内的敌军造成毁灭性的伤害 经常用于对抗人类的生化部队和虫族的 刺蛇飞龙等低血量单位
  • Android卡顿分析中常见的log

    1 看内存 bugreport 开始的时候有pss的信息 并且进行排序 之后会写一个解析和计算的 2 找system log中关键部分 一般设备hang 住的时候用户会疯狂按keycode 可以找相关log keyCode 3 down t
  • 工作与生活如何平衡?

    工作与生活如何平衡 最近忙的有些不像话了 完全没时间可以让自己慢下来思考一些事情 一方面 最近一直感觉自己身体不舒服 一方面 工作上的压力越来越大 要承担的东西也越来越多 生活 发现自己身体体质变差也有一段时间了 从一开始的小腿长时间有酸痛
  • PackageManagerService启动及初始化流程

    PackageManagerService也是有ServerThread启动的 运行在system process进程 我们先来看下PackageManagerService是怎么启动的 PackageManagerService的启动需要