PackageManagerService扫描安装apk详解

作者: Yink_Liu | 来源:发表于2017-09-28 17:39 被阅读0次

    PMS系列:
    1、PackageManagerService服务框架详解
    2、PackageManagerService启动分析
    3、PackageManagerService之app数据类(Settings)分析
    4、本文PackageManagerService扫描安装apk详解
    5、PackageManagerService根据权限等级管理权限(默认赋予apk权限)

    本文主要分析Android的PMS如何安装一个apk,代码基于android N

    一、安装方式

    apk的安装有如下四种方式:
    1、apk随着PMS的启动而安装(本文)
    2、adb install安装
    3、ODM内置商店静默安装
    4、拷贝apk到手机,界面安装
    这四种方式在代码里的实现其实就是如下两种:
    1、PMS调用scanDirLI扫描安装
    2、直接或间接调用installPackageAsUser安装

    二、安装流程

    在PMS启动的时候就会去扫描安装系统各个目录下的apk,比如system/app data/app vendor/app等调用的就是scanDirLI方法

    private void scanDirLI(File dir, final int parseFlags, int scanFlags, long currentTime) {
            final File[] files = dir.listFiles();
            for (File file : files) {
                final boolean isPackage = (isApkFile(file) || file.isDirectory())
                        && !PackageInstallerService.isStageName(file.getName());
                if (!isPackage) {
                    // Ignore entries which are not packages
                    continue;
                }
    
                try {
            //扫描安装
                    scanPackageTracedLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK,
                            scanFlags, currentTime, null);
                } catch (PackageManagerException e) {
                    Slog.w(TAG, "Failed to parse " + file + ": " + e.getMessage());
    
                    //删除无效应用的用户数据
                    if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
                            e.error == PackageManager.INSTALL_FAILED_INVALID_APK) {
                        logCriticalInfo(Log.WARN, "Deleting invalid package at " + file);
                        removeCodePathLI(file);
                    }
                }
            }
    
        }
    

    scanPackageTracedLI里就是一个简单的调用,调用到了scanPackageLI

    2.1、解析AndroidManifest.xml

    private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
                long currentTime, UserHandle user) throws PackageManagerException {
            if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
            PackageParser pp = new PackageParser();
            pp.setSeparateProcesses(mSeparateProcesses);
            pp.setOnlyCoreApps(mOnlyCore);
            pp.setDisplayMetrics(mMetrics);
    
            if ((scanFlags & SCAN_TRUSTED_OVERLAY) != 0) {
                parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY;
            }
    
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
            final PackageParser.Package pkg;
            try {
            //解析AndroidMainifest.xml
                pkg = pp.parsePackage(scanFile, parseFlags);
            } catch (PackageParserException e) {
                throw PackageManagerException.from(e);
            } finally {
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
        //继续解析
            return scanPackageLI(pkg, scanFile, parseFlags, scanFlags, currentTime, user);
        }
    

    解析AndroidMainifest.xml大致调用过程如下:
    parsePackage -> parseClusterPackage/parseMonolithicPackage -> parseBaseApk

    private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,
                String[] outError) throws XmlPullParserException, IOException {
            ...
        //读出pkgName
            final Package pkg = new Package(pkgName);
        //从资源里获得AndroidManifest的数组 
            TypedArray sa = res.obtainAttributes(parser,
                    com.android.internal.R.styleable.AndroidManifest);
        //根据上面的sa读出版本号等
            pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
            pkg.baseRevisionCode = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
            pkg.mVersionName = sa.getNonConfigurationString(
                    com.android.internal.R.styleable.AndroidManifest_versionName, 0);
            if (pkg.mVersionName != null) {
                pkg.mVersionName = pkg.mVersionName.intern();
            }
        //是否为核心app
            pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
        //回收
            sa.recycle();
        //开始共有属性解析
            return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
        }
    
    private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
                XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
                IOException {
        //每次解析先清空
        mParseInstrumentationArgs = null;
            mParseActivityArgs = null;
            mParseServiceArgs = null;
            mParseProviderArgs = null;
    
            int type;
            boolean foundApp = false;
        //读出AndroidManifest
            TypedArray sa = res.obtainAttributes(parser,
                    com.android.internal.R.styleable.AndroidManifest);
        //从sa中读出uid等
            String str = sa.getNonConfigurationString(
                    com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
            if (str != null && str.length() > 0) {
                String nameError = validateName(str, true, false);
                if (nameError != null && !"android".equals(pkg.packageName)) {
                    outError[0] = "<manifest> specifies bad sharedUserId name \""
                        + str + "\": " + nameError;
                    mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
                    return null;
                }
                pkg.mSharedUserId = str.intern();
                pkg.mSharedUserLabel = sa.getResourceId(
                        com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
            }
    
            pkg.installLocation = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifest_installLocation,
                    PARSE_DEFAULT_INSTALL_LOCATION);
            pkg.applicationInfo.installLocation = pkg.installLocation;
        ...
            int supportsSmallScreens = 1;
            int supportsNormalScreens = 1;
            int supportsLargeScreens = 1;
            int supportsXLargeScreens = 1;
            int resizeable = 1;
            int anyDensity = 1;
        //共有属性解析从这里开始
            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 (acceptedTags != null && !acceptedTags.contains(tagName)) {
                    Slog.w(TAG, "Skipping unsupported element under <manifest>: "
                            + tagName + " at " + mArchiveSourcePath + " "
                            + parser.getPositionDescription());
                    XmlUtils.skipCurrentTag(parser);
                    continue;
                }
            //TAG:application
                if (tagName.equals(TAG_APPLICATION)) {
                    if (foundApp) {
                        if (RIGID_PARSER) {
                            outError[0] = "<manifest> has more than one <application>";
                            mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                            return null;
                        } else {
                            Slog.w(TAG, "<manifest> has more than one <application>");
                            XmlUtils.skipCurrentTag(parser);
                            continue;
                        }
                    }
    
                    foundApp = true;
                    if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
                        return null;
                    }
                } else if (tagName.equals(TAG_OVERLAY)) {   //TAG:overlay
                    sa = res.obtainAttributes(parser,
                            com.android.internal.R.styleable.AndroidManifestResourceOverlay);
                    pkg.mOverlayTarget = sa.getString(
                            com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
                    pkg.mOverlayPriority = sa.getInt(
                            com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
                            -1);
                    sa.recycle();
    
                    if (pkg.mOverlayTarget == null) {
                        outError[0] = "<overlay> does not specify a target package";
                        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                        return null;
                    }
                    if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
                        outError[0] = "<overlay> priority must be between 0 and 9999";
                        mParseError =
                            PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                        return null;
                    }
                    XmlUtils.skipCurrentTag(parser);
    
                } else if (tagName.equals(TAG_KEY_SETS)) {   //key-sets
                    if (!parseKeySets(pkg, res, parser, outError)) {
                        return null;
                    }
                } 
        ...permission、uses-sdk等等都在这儿解析
        return pkg;
    }
    

    2.2 判断是否更新、覆盖安装apk等

    继续跟踪代码,调用scanPackageLI:

    private PackageParser.Package scanPackageLI(PackageParser.Package pkg, File scanFile,
                final int policyFlags, int scanFlags, long currentTime, UserHandle user)
                throws PackageManagerException {
            ...
        //scanPackageInternalLI方法是把扫描到的androidmainifest数据和之前在手机内扫描得到的数据做对比,然后进行对应操作。
            PackageParser.Package scannedPkg = scanPackageInternalLI(pkg, scanFile, policyFlags,
                    scanFlags, currentTime, user);
    
            // Scan the children
            final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
            for (int i = 0; i < childCount; i++) {
                PackageParser.Package childPackage = pkg.childPackages.get(i);
                scanPackageInternalLI(childPackage, scanFile, policyFlags, scanFlags,
                        currentTime, user);
            }
        ...
            return scannedPkg;
        }
    
    private PackageParser.Package scanPackageInternalLI(PackageParser.Package pkg, File scanFile,
                int policyFlags, int scanFlags, long currentTime, UserHandle user)
                throws PackageManagerException {
            ...
            synchronized (mPackages) {
                //看是否是已知的包、并对其操作
                String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
                if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
                    ps = mSettings.peekPackageLPr(oldName);
                }
                // If there was no original package, see one for the real package name.
                if (ps == null) {
                    ps = mSettings.peekPackageLPr(pkg.packageName);
                }
                
                updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName);
                if (DEBUG_INSTALL && updatedPkg != null) Slog.d(TAG, "updatedPkg = " + updatedPkg);
    
                ///非第一次启动 如果是一个已卸载的系统应用或者vendor app(厂商应用)则直接返回null
                if (!isFirstBoot() && (isVendorApp(pkg) || isSystemApp(pkg))
                     && ((updatedPkg != null)
                          || (ps.getInstallStatus() == PackageSettingBase.PKG_INSTALL_INCOMPLETE))) {
                     Slog.d(TAG, "Skip scanning " + scanFile.toString() + ", pacakge " + updatedPkg +
                                ", install status:  " + ps.getInstallStatus());
                     return null;
                } else if (ps == null && updatedPkg != null) {
                    Slog.d(TAG, "Skip scanning uninstalled package: " + pkg.packageName);
                    return null;
                }
        ...
    
            boolean updatedPkgBetter = false;
            // 首先检查是否是包含更新的系统包,包括vendor文件下
            if (updatedPkg != null &&
                    (((policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0) ||
                            ((policyFlags & PackageParser.PARSE_IS_OPERATOR) != 0))) {
            //如果新的包不在priv-app下,应该下调Flag
                if (locationIsPrivileged(scanFile)) {
                    updatedPkg.pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
                } else {
                    updatedPkg.pkgPrivateFlags &= ~ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
                }
    
                if (ps != null && !ps.codePath.equals(scanFile)) {
                    //如果扫描到的包路径发生了变化,根据已经存储的内容来判断该如何操作此app
                    /** M: [Operator] Allow vendor package downgrade. @{ */
                    /// Always install the updated one on data partition
                    if (pkg.mVersionCode < ps.versionCode
                           || ((policyFlags & PackageParser.PARSE_IS_OPERATOR) != 0)) {
                    ...
                        if (!updatedPkg.codePath.equals(scanFile)) {
                            updatedPkg.codePath = scanFile;
                            updatedPkg.codePathString = scanFile.toString();
                            updatedPkg.resourcePath = scanFile;
                            updatedPkg.resourcePathString = scanFile.toString();
                        }
                        updatedPkg.pkg = pkg;
                        updatedPkg.versionCode = pkg.mVersionCode;
    
                        // Update the disabled system child packages to point to the package too.
                        final int childCount = updatedPkg.childPackageNames != null
                                ? updatedPkg.childPackageNames.size() : 0;
                        for (int i = 0; i < childCount; i++) {
                            String childPackageName = updatedPkg.childPackageNames.get(i);
                            PackageSetting updatedChildPkg = mSettings.getDisabledSystemPkgLPr(
                                    childPackageName);
                            if (updatedChildPkg != null) {
                                updatedChildPkg.pkg = pkg;
                                updatedChildPkg.versionCode = pkg.mVersionCode;
                            }
                        }
                    } else {
                        //system下的app优先于我们安装跟新到data下的app
                        synchronized (mPackages) {
                            // Just remove the loaded entries from package lists.
                            mPackages.remove(ps.name);
                        }
                        InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
                                ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));
                        synchronized (mInstallLock) {
                            args.cleanUpResourcesLI();
                        }
                        synchronized (mPackages) {
                            mSettings.enableSystemPackageLPw(ps.name);
                        }
                        updatedPkgBetter = true;
                    }
                }
            }
    
        //标记更新
            if (updatedPkg != null) {
            //给system app加上flag:PARSE_IS_SYSTEM
                if (isSystemApp(updatedPkg)) {
                    policyFlags |= PackageParser.PARSE_IS_SYSTEM;
                }
            //给vendor下的app更跟新flags
                if ((isVendorApp(updatedPkg) || locationIsOperator(updatedPkg.codePath))
                        && locationIsOperator(ps.codePath)) {
                    policyFlags |= PackageParser.PARSE_IS_OPERATOR;
                }
    
                if ((updatedPkg.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
                    policyFlags |= PackageParser.PARSE_IS_PRIVILEGED;
                }
    
            }
            //扫描验证证书
            collectCertificatesLI(ps, pkg, scanFile, policyFlags);
    
            //一个新的system app,但有一个已安装的同名非系统app
            boolean shouldHideSystemApp = false;
            if (updatedPkg == null && ps != null
                    && (policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) {
                //如果签名不同,擦除已安装应用和数据
                if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
                        != PackageManager.SIGNATURE_MATCH) {
                    logCriticalInfo(Log.WARN, "Package " + ps.name + " appeared on system, but"
                            + " signatures don't match existing userdata copy; removing");
                    try (PackageFreezer freezer = freezePackage(pkg.packageName,
                            "scanPackageInternalLI")) {
                        deletePackageLIF(pkg.packageName, null, true, null, 0, null, false, null);
                    }
                    ps = null;
                } else {
                    //新添加app更旧,则隐藏此app,后续会重新添加
                    if (pkg.mVersionCode <= ps.versionCode) {
                        shouldHideSystemApp = true;
                        logCriticalInfo(Log.INFO, "Package " + ps.name + " appeared at " + scanFile
                                + " but new version " + pkg.mVersionCode + " better than installed "
                                + ps.versionCode + "; hiding system");
                    } else {
                        //如果比已安装的app新,则保留app数据直接安装更新此system app
                        InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
                                ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));
                        synchronized (mInstallLock) {
                            args.cleanUpResourcesLI();
                        }
                    }
                }
            }
    
            //如果app中制定的资源在别的路径,则从PackageSettings中抓取
            if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
                if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
                    policyFlags |= PackageParser.PARSE_FORWARD_LOCK;
                }
            }
    
            // TODO: extend to support forward-locked splits
            String resourcePath = null;
            String baseResourcePath = null;
            if ((policyFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
                if (ps != null && ps.resourcePathString != null) {
                    resourcePath = ps.resourcePathString;
                    baseResourcePath = ps.resourcePathString;
                } else {
                    // Should not happen at all. Just log an error.
                    Slog.e(TAG, "Resource path not set for package " + pkg.packageName);
                }
            } else {
                resourcePath = pkg.codePath;
                baseResourcePath = pkg.baseCodePath;
            }
    
            //设置app路径
            pkg.setApplicationVolumeUuid(pkg.volumeUuid);
            pkg.setApplicationInfoCodePath(pkg.codePath);
            pkg.setApplicationInfoBaseCodePath(pkg.baseCodePath);
            pkg.setApplicationInfoSplitCodePaths(pkg.splitCodePaths);
            pkg.setApplicationInfoResourcePath(resourcePath);
            pkg.setApplicationInfoBaseResourcePath(baseResourcePath);
            pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths);
    
            // Note that we invoke the following method only if we are about to unpack an application
            PackageParser.Package scannedPkg = scanPackageLI(pkg, policyFlags, scanFlags
                    | SCAN_UPDATE_SIGNATURE, currentTime, user);
    
            if (shouldHideSystemApp) {
                synchronized (mPackages) {
                    mSettings.disableSystemPackageLPw(pkg.packageName, true);
                }
            }
    
            return scannedPkg;
        }
    
    private PackageParser.Package scanPackageLI(PackageParser.Package pkg, final int policyFlags,
                int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
            boolean success = false;
            try {
                final PackageParser.Package res = scanPackageDirtyLI(pkg, policyFlags, scanFlags,
                        currentTime, user);
                success = true;
                return res;
            } finally {
                if (!success && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
                    // DELETE_DATA_ON_FAILURES is only used by frozen paths
                    destroyAppDataLIF(pkg, UserHandle.USER_ALL,
                            StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
                    destroyAppProfilesLIF(pkg, UserHandle.USER_ALL);
                }
            }
        }
    

    2.3 安装核心函数scanPackageDirtyLI

    不论是开机扫描安装APK,还是通过adb命令安装APK,最终都会调用scanPackageDirtyLI函数进行APK安装。
    代码过多,代码片段如下:

    private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg,
                final int policyFlags, final int scanFlags, long currentTime, UserHandle user)
                throws PackageManagerException {
        //1.先对framework-res.apk单独处理
            if (pkg.packageName.equals("android")) {
                synchronized (mPackages) {
                    if ((scanFlags & SCAN_CHECK_ONLY) == 0) {
                        // Set up information for our fall-back user intent resolution activity.
                        mPlatformPackage = pkg;
                        pkg.mVersionCode = mSdkVersion;
                        mAndroidApplication = pkg.applicationInfo;
    
                        if (!mResolverReplaced) {
                            mResolveActivity.applicationInfo = mAndroidApplication;
                            mResolveActivity.name = ResolverActivity.class.getName();
                            mResolveActivity.packageName = mAndroidApplication.packageName;
                            mResolveActivity.processName = "system:ui";
                            mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
                            mResolveActivity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NEVER;
                            mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
                            mResolveActivity.theme = R.style.Theme_Material_Dialog_Alert;
                            mResolveActivity.exported = true;
                            mResolveActivity.enabled = true;
                            mResolveActivity.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
                            mResolveActivity.configChanges = ActivityInfo.CONFIG_SCREEN_SIZE
                                    | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE
                                    | ActivityInfo.CONFIG_SCREEN_LAYOUT
                                    | ActivityInfo.CONFIG_ORIENTATION
                                    | ActivityInfo.CONFIG_KEYBOARD
                                    | ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
                            mResolveInfo.activityInfo = mResolveActivity;
                            mResolveInfo.priority = 0;
                            mResolveInfo.preferredOrder = 0;
                            mResolveInfo.match = 0;
                            mResolveComponentName = new ComponentName(
                                    mAndroidApplication.packageName, mResolveActivity.name);
                        }
                    }
                }
            }
        
        //检测新的安装包
            synchronized (mPackages) {
                if (mPackages.containsKey(pkg.packageName)
                        || mSharedLibraries.containsKey(pkg.packageName)) {
                    throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
                            "Application package " + pkg.packageName
                                    + " already installed.  Skipping duplicate.");
                }
                if ((scanFlags & SCAN_REQUIRE_KNOWN) != 0) {
                    if (mExpectingBetter.containsKey(pkg.packageName)) {
                        logCriticalInfo(Log.WARN,
                                "Relax SCAN_REQUIRE_KNOWN requirement for package " + pkg.packageName);
                    } else {
                        PackageSetting known = mSettings.peekPackageLPr(pkg.packageName);
                        ...
                }
            }
    
            //2.初始化代码路径和资源路径
            File destCodeFile = new File(pkg.applicationInfo.getCodePath());
            File destResourceFile = new File(pkg.applicationInfo.getResourcePath());
    
    
            // 新的包会进行如下操作操作
            synchronized (mPackages) {
                if (pkg.mSharedUserId != null) {
                    suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, 0, true);
            ...
                }
                PackageSetting origPackage = null;
                String realName = null;
                if (pkg.mOriginalPackages != null) {
                    //重命名do this
                    final String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
                    if (pkg.mOriginalPackages.contains(renamed)) {
                        realName = pkg.mRealPackage;
                        if (!pkg.packageName.equals(renamed)) {
                            pkg.setPackageName(renamed);
                        }
    
                    } else {
                        for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
                            if ((origPackage = mSettings.peekPackageLPr(
                                    pkg.mOriginalPackages.get(i))) != null) {
                                if (!verifyPackageUpdateLPr(origPackage, pkg)) {
                                    origPackage = null;
                                    continue;
                                } else if (origPackage.sharedUser != null) {
                                    // Make sure uid is compatible between packages.
                                    if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
                                        origPackage = null;
                                        continue;
                                    }
                                    // TODO: Add case when shared user id is added [b/28144775]
                                } else {
                                    if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
                                            + pkg.packageName + " to old name " + origPackage.name);
                                }
                                break;
                            }
                        }
                    }
                }
    
                // 创建PackageSetting并设置
                pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
                        destResourceFile, pkg.applicationInfo.nativeLibraryRootDir,
                        pkg.applicationInfo.primaryCpuAbi,
                        pkg.applicationInfo.secondaryCpuAbi,
                        pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags,
                        pkg.applicationInfo.flagsEx,
                        user, false);
                if (pkgSetting == null) {
                    throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
                            "Creating application package " + pkg.packageName + " failed");
                }
    
                if (pkgSetting.origPackage != null) {
                    pkg.setPackageName(origPackage.name);
    
                    String msg = "New package " + pkgSetting.realName
                            + " renamed to replace old package " + pkgSetting.name;
                    reportSettingsProblem(Log.WARN, msg);
    
                    // Make a note of it.
                    if ((scanFlags & SCAN_CHECK_ONLY) == 0) {
                        mTransferedPackages.add(origPackage.name);
                    }
    
                    // No longer need to retain this.
                    pkgSetting.origPackage = null;
                }
    
                if ((scanFlags & SCAN_CHECK_ONLY) == 0 && realName != null) {
                    // Make a note of it.
                    mTransferedPackages.add(pkg.packageName);
                }
    
            // 3.创建共享库
                if ((policyFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
                    updateSharedLibrariesLPw(pkg, null);
                }
            // 4.验证签名信息的合法性
                pkg.applicationInfo.uid = pkgSetting.appId;
                pkg.mExtras = pkgSetting;
                if (shouldCheckUpgradeKeySetLP(pkgSetting, scanFlags)) {
                    if (checkUpgradeKeySetLP(pkgSetting, pkg)) {
                        pkgSetting.signatures.mSignatures = pkg.mSignatures;
                    } else {
                ....
                    }
                } else {
                    try {
                        verifySignaturesLP(pkgSetting, pkg);
                        pkgSetting.signatures.mSignatures = pkg.mSignatures;
                    } catch (PackageManagerException e) {
                        if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0
                              || (policyFlags & PackageParser.PARSE_IS_OPERATOR) == 0) {
                            throw e;
                        }
                        pkgSetting.signatures.mSignatures = pkg.mSignatures;
                        if (pkgSetting.sharedUser != null) {
                            if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
                                                  pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
                                throw new PackageManagerException(
                                        INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
                                                "Signature mismatch for shared user: "
                                                + pkgSetting.sharedUser);
                            }
                        }
                        String msg = "System package " + pkg.packageName
                            + " signature changed; retaining data.";
                        reportSettingsProblem(Log.WARN, msg);
                    }
                }
                //5.验证新的包的Provider不会与现有包冲突
                if ((scanFlags & SCAN_NEW_INSTALL) != 0) {
                    final int N = pkg.providers.size();
                    int i;
                    for (i=0; i<N; i++) {
                        PackageParser.Provider p = pkg.providers.get(i);
                        if (p.info.authority != null) {
                            String names[] = p.info.authority.split(";");
                            for (int j = 0; j < names.length; j++) {
                                if (mProvidersByAuthority.containsKey(names[j])) {
                                    PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
                                    final String otherPackageName =
                                            ((other != null && other.getComponentName() != null) ?
                                                    other.getComponentName().getPackageName() : "?");
                                    throw new PackageManagerException(
                                            INSTALL_FAILED_CONFLICTING_PROVIDER,
                                                    "Can't install because provider name " + names[j]
                                                    + " (in package " + pkg.applicationInfo.packageName
                                                    + ") is already used by " + otherPackageName);
                                }
                            }
                        }
                    }
                }
            //6.是否需要获得其他包的权限
            if ((scanFlags & SCAN_CHECK_ONLY) == 0 && pkg.mAdoptPermissions != null) {
                    // This package wants to adopt ownership of permissions from
                    // another package.
                    for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) {
                        final String origName = pkg.mAdoptPermissions.get(i);
                        final PackageSetting orig = mSettings.peekPackageLPr(origName);
                        if (orig != null) {
                            if (verifyPackageUpdateLPr(orig, pkg)) {
                                Slog.i(TAG, "Adopting permissions from " + origName + " to "
                                        + pkg.packageName);
                                mSettings.transferPermissionsLPw(origName, pkg.packageName);
                            }
                        }
                    }
            }
    
            final String pkgName = pkg.packageName;
    
        //7.确定进程名称
            final long scanFileTime = scanFile.lastModified();
            final boolean forceDex = (scanFlags & SCAN_FORCE_DEX) != 0;
            pkg.applicationInfo.processName = fixProcessName(
                    pkg.applicationInfo.packageName,
                    pkg.applicationInfo.processName,
                    pkg.applicationInfo.uid);
    
            if (pkg != mPlatformPackage) {
                // Get all of our default paths setup
                pkg.applicationInfo.initForUser(UserHandle.USER_SYSTEM);
            }
    
            final String path = scanFile.getPath();
            final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);
    
        //Lib库路径
            if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
                derivePackageAbi(pkg, scanFile, cpuAbiOverride, true /* extract libs */);
                if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp() &&
                        pkg.applicationInfo.primaryCpuAbi == null) {
                    setBundledAppAbisAndRoots(pkg, pkgSetting);
                    setNativeLibraryPaths(pkg);
                }
    
            } else {
                if ((scanFlags & SCAN_MOVE) != 0) {
                    pkg.applicationInfo.primaryCpuAbi = pkgSetting.primaryCpuAbiString;
                    pkg.applicationInfo.secondaryCpuAbi = pkgSetting.secondaryCpuAbiString;
                }
                setNativeLibraryPaths(pkg);
            }
        //cpu描述
            pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi;
            pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi;
            pkgSetting.cpuAbiOverrideString = cpuAbiOverride;
    
            pkg.cpuAbiOverride = cpuAbiOverride;
    
            //保存lib路径、方便卸载时清理
            pkgSetting.legacyNativeLibraryPathString = pkg.applicationInfo.nativeLibraryRootDir;
    
    
            ArrayList<PackageParser.Package> clientLibPkgs = null;
    
            if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
                if (nonMutatedPs != null) {
                    synchronized (mPackages) {
                        mSettings.mPackages.put(nonMutatedPs.name, nonMutatedPs);
                    }
                }
                return pkg;
            }
    
    
            //8. Lib库的更新设置操作等
            synchronized (mPackages) {
                if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
                    // Only system apps can add new shared libraries.
                    if (pkg.libraryNames != null) {
                        for (int i=0; i<pkg.libraryNames.size(); i++) {
                            String name = pkg.libraryNames.get(i);
                            boolean allowed = false;
                            if (pkg.isUpdatedSystemApp()) {
                                final PackageSetting sysPs = mSettings
                                        .getDisabledSystemPkgLPr(pkg.packageName);
                                if (sysPs.pkg != null && sysPs.pkg.libraryNames != null) {
                                    for (int j=0; j<sysPs.pkg.libraryNames.size(); j++) {
                                        if (name.equals(sysPs.pkg.libraryNames.get(j))) {
                                            allowed = true;
                                            break;
                                        }
                                    }
                                }
                            } else {
                                allowed = true;
                            }
                            if (allowed) {
                                if (!mSharedLibraries.containsKey(name)) {
                                    mSharedLibraries.put(name, new SharedLibraryEntry(null, pkg.packageName));
                                } else if (!name.equals(pkg.packageName)) {
                                    ...
                                }
                            } else {
                               ...
                            }
                        }
                        if ((scanFlags & SCAN_BOOTING) == 0) {
                            clientLibPkgs = updateAllSharedLibrariesLPw(pkg);
                        }
                    }
                }
            }
            // 更新lib时杀死依赖此lib的进程
            if (clientLibPkgs != null) {
                for (int i=0; i<clientLibPkgs.size(); i++) {
                    PackageParser.Package clientPkg = clientLibPkgs.get(i);
                    killApplication(clientPkg.applicationInfo.packageName,
                            clientPkg.applicationInfo.uid, "update lib");
                }
            }
    
        //9.跟新Settings参数
            boolean createIdmapFailed = false;
            synchronized (mPackages) {
                // We don't expect installation to fail beyond this point
    
                if (pkgSetting.pkg != null) {
                    // Note that |user| might be null during the initial boot scan. If a codePath
                    // for an app has changed during a boot scan, it's due to an app update that's
                    // part of the system partition and marker changes must be applied to all users.
                    maybeRenameForeignDexMarkers(pkgSetting.pkg, pkg,
                        (user != null) ? user : UserHandle.ALL);
                }
    
                // Add the new setting to mSettings
                mSettings.insertPackageSettingLPw(pkgSetting, pkg);
                // Add the new setting to mPackages
                mPackages.put(pkg.applicationInfo.packageName, pkg);
                // Make sure we don't accidentally delete its data.
                final Iterator<PackageCleanItem> iter = mSettings.mPackagesToBeCleaned.iterator();
                while (iter.hasNext()) {
                    PackageCleanItem item = iter.next();
                    if (pkgName.equals(item.packageName)) {
                        iter.remove();
                    }
                }
    
                //10. 更新安装的时间
                if (currentTime != 0) {
                    if (pkgSetting.firstInstallTime == 0) {
                        pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
                    } else if ((scanFlags&SCAN_UPDATE_TIME) != 0) {
                        pkgSetting.lastUpdateTime = currentTime;
                    }
                } else if (pkgSetting.firstInstallTime == 0) {
                    // We need *something*.  Take time time stamp of the file.
                    pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
                } else if ((policyFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
                    if (scanFileTime != pkgSetting.timeStamp) {
                        // A package on the system image has changed; consider this
                        // to be an update.
                        pkgSetting.lastUpdateTime = scanFileTime;
                    }
                }
            //11.下面的操作就是各类组建权限等的安装操作
            //跟新设置apk的provider并更新到数据中
                int N = pkg.providers.size();
                StringBuilder r = null;
                int i;
                for (i=0; i<N; i++) {
                    PackageParser.Provider p = pkg.providers.get(i);
                    p.info.processName = fixProcessName(pkg.applicationInfo.processName,
                            p.info.processName, pkg.applicationInfo.uid);
                    mProviders.addProvider(p);
                    p.syncable = p.info.isSyncable;
                    if (p.info.authority != null) {
                        String names[] = p.info.authority.split(";");
                        p.info.authority = null;
                        for (int j = 0; j < names.length; j++) {
                            if (j == 1 && p.syncable) {
                                p = new PackageParser.Provider(p);
                                p.syncable = false;
                            }
                            if (!mProvidersByAuthority.containsKey(names[j])) {
                                mProvidersByAuthority.put(names[j], p);
                                if (p.info.authority == null) {
                                    p.info.authority = names[j];
                                } else {
                                    p.info.authority = p.info.authority + ";" + names[j];
                                }
                            } else {
                                PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
                            }
                        }
                    }
                    if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                        if (r == null) {
                            r = new StringBuilder(256);
                        } else {
                            r.append(' ');
                        }
                        r.append(p.info.name);
                    }
                }
                if (r != null) {
                    if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Providers: " + r);
                }
            //services信息
                N = pkg.services.size();
                r = null;
                for (i=0; i<N; i++) {
                    PackageParser.Service s = pkg.services.get(i);
                    s.info.processName = fixProcessName(pkg.applicationInfo.processName,
                            s.info.processName, pkg.applicationInfo.uid);
                    mServices.addService(s);
                    if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                        if (r == null) {
                            r = new StringBuilder(256);
                        } else {
                            r.append(' ');
                        }
                        r.append(s.info.name);
                    }
                }
                if (r != null) {
                    if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Services: " + r);
                }
                //广播信息
                N = pkg.receivers.size();
                r = null;
                for (i=0; i<N; i++) {
                    PackageParser.Activity a = pkg.receivers.get(i);
                    a.info.processName = fixProcessName(pkg.applicationInfo.processName,
                            a.info.processName, pkg.applicationInfo.uid);
                    mReceivers.addActivity(a, "receiver");
                    if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                        if (r == null) {
                            r = new StringBuilder(256);
                        } else {
                            r.append(' ');
                        }
                        r.append(a.info.name);
                    }
                }
                if (r != null) {
                    if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Receivers: " + r);
                }
            //activity信息
                N = pkg.activities.size();
                r = null;
                for (i=0; i<N; i++) {
                    PackageParser.Activity a = pkg.activities.get(i);
                    a.info.processName = fixProcessName(pkg.applicationInfo.processName,
                            a.info.processName, pkg.applicationInfo.uid);
                    mActivities.addActivity(a, "activity");
                    if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                        if (r == null) {
                            r = new StringBuilder(256);
                        } else {
                            r.append(' ');
                        }
                        r.append(a.info.name);
                    }
                }
                if (r != null) {
                    if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Activities: " + r);
                }
            //权限信息
                N = pkg.permissionGroups.size();
                r = null;
                for (i=0; i<N; i++) {
                    PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
                    PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
                    if (cur == null) {
                        mPermissionGroups.put(pg.info.name, pg);
                        if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                            if (r == null) {
                                r = new StringBuilder(256);
                            } else {
                                r.append(' ');
                            }
                            r.append(pg.info.name);
                        }
                    } else {
                        if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                            if (r == null) {
                                r = new StringBuilder(256);
                            } else {
                                r.append(' ');
                            }
                            r.append("DUP:");
                            r.append(pg.info.name);
                        }
                    }
                }
                if (r != null) {
                    if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Permission Groups: " + r);
                }
    
                N = pkg.permissions.size();
                r = null;
                for (i=0; i<N; i++) {
                    PackageParser.Permission p = pkg.permissions.get(i);
    
                    // Assume by default that we did not install this permission into the system.
                    p.info.flags &= ~PermissionInfo.FLAG_INSTALLED;
                    if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
                        p.group = mPermissionGroups.get(p.info.group);
                        // Warn for a permission in an unknown group.
                        if (p.info.group != null && p.group == null) {
                            Slog.w(TAG, "Permission " + p.info.name + " from package "
                                    + p.info.packageName + " in an unknown group " + p.info.group);
                        }
                    }
    
                    ArrayMap<String, BasePermission> permissionMap =
                            p.tree ? mSettings.mPermissionTrees
                                    : mSettings.mPermissions;
                    BasePermission bp = permissionMap.get(p.info.name);
    
                    // Allow system apps to redefine non-system permissions
                    if (bp != null && !Objects.equals(bp.sourcePackage, p.info.packageName)) {
                        final boolean currentOwnerIsSystem = (bp.perm != null
                                && isSystemApp(bp.perm.owner));
                        if (isSystemApp(p.owner)) {
                            if (bp.type == BasePermission.TYPE_BUILTIN && bp.perm == null) {
                                // It's a built-in permission and no owner, take ownership now
                                bp.packageSetting = pkgSetting;
                                bp.perm = p;
                                bp.uid = pkg.applicationInfo.uid;
                                bp.sourcePackage = p.info.packageName;
                                p.info.flags |= PermissionInfo.FLAG_INSTALLED;
                            } else if (!currentOwnerIsSystem) {
                                String msg = "New decl " + p.owner + " of permission  "
                                        + p.info.name + " is system; overriding " + bp.sourcePackage;
                                reportSettingsProblem(Log.WARN, msg);
                                bp = null;
                            }
                        }
                    }
    
                    if (bp == null) {
                        bp = new BasePermission(p.info.name, p.info.packageName,
                                BasePermission.TYPE_NORMAL);
                        permissionMap.put(p.info.name, bp);
                    }
    
                    if (bp.perm == null) {
                        if (bp.sourcePackage == null
                                || bp.sourcePackage.equals(p.info.packageName)) {
                            BasePermission tree = findPermissionTreeLP(p.info.name);
                            if (tree == null
                                    || tree.sourcePackage.equals(p.info.packageName)) {
                                bp.packageSetting = pkgSetting;
                                bp.perm = p;
                                bp.uid = pkg.applicationInfo.uid;
                                bp.sourcePackage = p.info.packageName;
                                p.info.flags |= PermissionInfo.FLAG_INSTALLED;
                                if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                                    if (r == null) {
                                        r = new StringBuilder(256);
                                    } else {
                                        r.append(' ');
                                    }
                                    r.append(p.info.name);
                                }
                            } else {
                                Slog.w(TAG, "Permission " + p.info.name + " from package "
                                        + p.info.packageName + " ignored: base tree "
                                        + tree.name + " is from package "
                                        + tree.sourcePackage);
                            }
                        } else {
                            Slog.w(TAG, "Permission " + p.info.name + " from package "
                                    + p.info.packageName + " ignored: original from "
                                    + bp.sourcePackage);
                        }
                    } else if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                        if (r == null) {
                            r = new StringBuilder(256);
                        } else {
                            r.append(' ');
                        }
                        r.append("DUP:");
                        r.append(p.info.name);
                    }
                    if (bp.perm == p) {
                        bp.protectionLevel = p.info.protectionLevel;
                    }
                }
    
                if (r != null) {
                    if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Permissions: " + r);
                }
            //Instrumentation信息(Instrumentation用来跟踪本应用内的application及activity生命周期)
                N = pkg.instrumentation.size();
                r = null;
                for (i=0; i<N; i++) {
                    PackageParser.Instrumentation a = pkg.instrumentation.get(i);
                    a.info.packageName = pkg.applicationInfo.packageName;
                    a.info.sourceDir = pkg.applicationInfo.sourceDir;
                    a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
                    a.info.splitSourceDirs = pkg.applicationInfo.splitSourceDirs;
                    a.info.splitPublicSourceDirs = pkg.applicationInfo.splitPublicSourceDirs;
                    a.info.dataDir = pkg.applicationInfo.dataDir;
                    a.info.deviceProtectedDataDir = pkg.applicationInfo.deviceProtectedDataDir;
                    a.info.credentialProtectedDataDir = pkg.applicationInfo.credentialProtectedDataDir;
    
                    a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
                    a.info.secondaryNativeLibraryDir = pkg.applicationInfo.secondaryNativeLibraryDir;
                    mInstrumentation.put(a.getComponentName(), a);
                    if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                        if (r == null) {
                            r = new StringBuilder(256);
                        } else {
                            r.append(' ');
                        }
                        r.append(a.info.name);
                    }
                }
                if (r != null) {
                    if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Instrumentation: " + r);
                }
    
                if (pkg.protectedBroadcasts != null) {
                    N = pkg.protectedBroadcasts.size();
                    for (i=0; i<N; i++) {
                        mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
                    }
                }
    
                pkgSetting.setTimeStamp(scanFileTime);
    
                // Create idmap files for pairs of (packages, overlay packages).
                // Note: "android", ie framework-res.apk, is handled by native layers.
                if (pkg.mOverlayTarget != null) {
                    // This is an overlay package.
                    if (pkg.mOverlayTarget != null && !pkg.mOverlayTarget.equals("android") &&
                            /// M: ALPS02521810, support mediatek-res runtime overlay
                            !pkg.mOverlayTarget.equals("com.mediatek")) {
                        if (!mOverlays.containsKey(pkg.mOverlayTarget)) {
                            mOverlays.put(pkg.mOverlayTarget,
                                    new ArrayMap<String, PackageParser.Package>());
                        }
                        ArrayMap<String, PackageParser.Package> map = mOverlays.get(pkg.mOverlayTarget);
                        map.put(pkg.packageName, pkg);
                        PackageParser.Package orig = mPackages.get(pkg.mOverlayTarget);
                        if (orig != null && !createIdmapForPackagePairLI(orig, pkg)) {
                            createIdmapFailed = true;
                        }
                    }
                } else if (mOverlays.containsKey(pkg.packageName) &&
                        !pkg.packageName.equals("android") &&
                        /// M: ALPS02521810, support mediatek-res runtime overlay
                        !pkg.packageName.equals("com.mediatek")) {
                    // This is a regular package, with one or more known overlay packages.
                    createIdmapsForPackageLI(pkg);
                }
            }
    
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    
            if (createIdmapFailed) {
                throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
                        "scanPackageLI failed to createIdmap");
            }
            return pkg;
        }
    

    scanPackageDirtyLI流程总结如下:
    1.先对framework-res.apk单独处理
    2.初始化代码路径和资源路径
    3.创建共享库
    4.验证签名信息的合法性
    5.验证新的包的Provider不会与现有包冲突
    6.是否需要获得其他包的权限
    7.确定进程名称
    8.Lib库的更新设置操作等
    9.跟新Settings参数
    10.更新安装的时间
    11.四大组件、权限、Instrumentation、把解析的这些信息注册到PMS

    小结

    到此PMS扫描安装系统apk的流程就分析完了。先解析Androidmainifest读出apk信息,然后判断安装方式,最后调用scanPackageDirtyLI解析。

    相关文章

      网友评论

        本文标题:PackageManagerService扫描安装apk详解

        本文链接:https://www.haomeiwen.com/subject/fmdvextx.html