PackageManagerService installPackage 流程

来看一下install package的流程,由于没有App的源码包,所以只有从PackageManagerService 中 installpackage开始读起了。

installPackageAsUser()所有的install 都会走到这里。

 public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer,
            int installFlags, String installerPackageName, VerificationParams verificationParams,
            String packageAbiOverride, int userId) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);

//这里会开始校验 caller的 UID 和permission
//还是依旧去保证,在没有root权限下,安装App的安全性。
        final int callingUid = Binder.getCallingUid();
        enforceCrossUserPermission(callingUid, userId, true, true, "installPackageAsUser");

//继续校验这个user 是不是受到限制的。
        if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
            try {
                if (observer != null) {
                    observer.onPackageInstalled("", INSTALL_FAILED_USER_RESTRICTED, null, null);
                }
            } catch (RemoteException re) {
            }
            return;
        }
//如果这个uid 是core进程,打上flags
        if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) {
            installFlags |= PackageManager.INSTALL_FROM_ADB;

        } 
//普通的进程uid 走常规安装模式。
else {
            // Caller holds INSTALL_PACKAGES permission, so we're less strict
            // about installerPackageName.

            installFlags &= ~PackageManager.INSTALL_FROM_ADB;
            installFlags &= ~PackageManager.INSTALL_ALL_USERS;
        }

        UserHandle user;
        if ((installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
            user = UserHandle.ALL;
        } else {
            user = new UserHandle(userId);
        }

        verificationParams.setInstallerUid(callingUid);

        final File originFile = new File(originPath);
        final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile);


//往PackageHandler 构建准备 安装的 msg,开始准备走按准流程。
//所有的APP install 都是走handler,来保证,安装流程是串行,而不是并行的。
        final Message msg = mHandler.obtainMessage(INIT_COPY);
        msg.obj = new InstallParams(origin, observer, installFlags,
                installerPackageName, verificationParams, user, packageAbiOverride);
        mHandler.sendMessage(msg);
    }

在PackageHandler中

    case INIT_COPY: {
                    HandlerParams params = (HandlerParams) msg.obj;
                    int idx = mPendingInstalls.size();
                    if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
                    // If a bind was already initiated we dont really
                    // need to do anything. The pending install
                    // will be processed later on.
                    if (!mBound) {
                        // If this is the only one pending we might
                        // have to bind to the service again.
                        if (!connectToService()) {
                            Slog.e(TAG, "Failed to bind to media container service");
                            params.serviceError();
                            return;
                        } else {
                            // Once we bind to the service, the first
                            // pending request will be processed.
                            mPendingInstalls.add(idx, params);
                        }
                    } else {
                        mPendingInstalls.add(idx, params);
                        // Already bound to the service. Just make
                        // sure we trigger off processing the first request.
                        if (idx == 0) {
                            mHandler.sendEmptyMessage(MCS_BOUND);
                        }
                    }
                    break;
                }

系统会将service的安装线程的优先级调高准备做安装操作,并把安装的信息放在mPendingInstalls 队列中。如果,mPendingInstalls中的size从0变为1,则会跑出一个MCS_BOUND,执行轮训操作,一直到队列中的size变为0。

                case MCS_BOUND: {
                    if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
                    if (msg.obj != null) {
                        mContainerService = (IMediaContainerService) msg.obj;
                    }
                    if (mContainerService == null) {
                        // Something seriously wrong. Bail out
                        Slog.e(TAG, "Cannot bind to media container service");
                        for (HandlerParams params : mPendingInstalls) {
                            // Indicate service bind error
                            params.serviceError();
                        }
                        mPendingInstalls.clear();
                    } else if (mPendingInstalls.size() > 0) {
                        HandlerParams params = mPendingInstalls.get(0);
                        if (params != null) {
                            if (params.startCopy()) {
                                // We are done... look for more work or to
                                // go idle.
                                if (DEBUG_SD_INSTALL) Log.i(TAG,
                                        "Checking for more work or unbind...");
                                // Delete pending install
                                if (mPendingInstalls.size() > 0) {
                                    mPendingInstalls.remove(0);
                                }
                                if (mPendingInstalls.size() == 0) {
                                    if (mBound) {
                                        if (DEBUG_SD_INSTALL) Log.i(TAG,
                                                "Posting delayed MCS_UNBIND");
                                        removeMessages(MCS_UNBIND);
                                        Message ubmsg = obtainMessage(MCS_UNBIND);
                                        // Unbind after a little delay, to avoid
                                        // continual thrashing.
                                        sendMessageDelayed(ubmsg, 10000);
                                    }
                                } else {
                                    // There are more pending requests in queue.
                                    // Just post MCS_BOUND message to trigger processing
                                    // of next pending install.
                                    if (DEBUG_SD_INSTALL) Log.i(TAG,
                                            "Posting MCS_BOUND for next work");
                                    mHandler.sendEmptyMessage(MCS_BOUND);
                                }
                            }
                        }
                    } else {
                        // Should never happen ideally.
                        Slog.w(TAG, "Empty queue");
                    }
                    break;
                }

1。很明显可以看到先去做一些service的校验,是否存活。
2。开始拷贝params.startCopy(),通过InstallParams中的handleStartCopy()进行文件的拷贝。



 int ret = PackageManager.INSTALL_SUCCEEDED; if (origin.staged) { if (origin.file != null) { installFlags |= PackageManager.INSTALL_INTERNAL; installFlags &= ~PackageManager.INSTALL_EXTERNAL; } else if (origin.cid != null) { installFlags |= PackageManager.INSTALL_EXTERNAL; installFlags &= ~PackageManager.INSTALL_INTERNAL; } else { throw new IllegalStateException("Invalid stage location"); } } final boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0; final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0; PackageInfoLite pkgLite = null; if (onInt && onSd) { // Check if both bits are set. Slog.w(TAG, "Conflicting flags specified for installing on both internal and external"); ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; } else { pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags, packageAbiOverride); /* * If we have too little free space, try to free cache * before giving up. */ if (!origin.staged && pkgLite.recommendedInstallLocation == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) { // TODO: focus freeing disk space on the target device final StorageManager storage = StorageManager.from(mContext); final long lowThreshold = storage.getStorageLowBytes( Environment.getDataDirectory()); final long sizeBytes = mContainerService.calculateInstalledSize( origin.resolvedPath, isForwardLocked(), packageAbiOverride); if (mInstaller.freeCache(sizeBytes + lowThreshold) >= 0) { pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags, packageAbiOverride); } /* * The cache free must have deleted the file we * downloaded to install. * * TODO: fix the "freeCache" call to not delete * the file we care about. */ if (pkgLite.recommendedInstallLocation == PackageHelper.RECOMMEND_FAILED_INVALID_URI) { pkgLite.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE; } } } if (ret == PackageManager.INSTALL_SUCCEEDED) { int loc = pkgLite.recommendedInstallLocation; if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) { ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) { ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS; } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) { ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) { ret = PackageManager.INSTALL_FAILED_INVALID_APK; } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) { ret = PackageManager.INSTALL_FAILED_INVALID_URI; } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) { ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE; } else { // Override with defaults if needed. loc = installLocationPolicy(pkgLite); if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) { ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE; } else if (!onSd && !onInt) { // Override install location with flags if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) { // Set the flag to install on external media. installFlags |= PackageManager.INSTALL_EXTERNAL; installFlags &= ~PackageManager.INSTALL_INTERNAL; } else { // Make sure the flag for installing on external // media is unset installFlags |= PackageManager.INSTALL_INTERNAL; installFlags &= ~PackageManager.INSTALL_EXTERNAL; } } } } final InstallArgs args = createInstallArgs(this); mArgs = args; if (ret == PackageManager.INSTALL_SUCCEEDED) { /* * ADB installs appear as UserHandle.USER_ALL, and can only be performed by * UserHandle.USER_OWNER, so use the package verifier for UserHandle.USER_OWNER. */ int userIdentifier = getUser().getIdentifier(); if (userIdentifier == UserHandle.USER_ALL && ((installFlags & PackageManager.INSTALL_FROM_ADB) != 0)) { userIdentifier = UserHandle.USER_OWNER; } /* * Determine if we have any installed package verifiers. If we * do, then we'll defer to them to verify the packages. */ final int requiredUid = mRequiredVerifierPackage == null ? -1 : getPackageUid(mRequiredVerifierPackage, userIdentifier); if (!origin.existing && requiredUid != -1 && isVerificationEnabled(userIdentifier, installFlags)) { final Intent verification = new Intent( Intent.ACTION_PACKAGE_NEEDS_VERIFICATION); verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); verification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)), PACKAGE_MIME_TYPE); verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE, PackageManager.GET_DISABLED_COMPONENTS, 0 /* TODO: Which userId? */); if (DEBUG_VERIFY) { Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent " + verification.toString() + " with " + pkgLite.verifiers.length + " optional verifiers"); } final int verificationId = mPendingVerificationToken++; verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId); verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE, installerPackageName); verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, installFlags); verification.putExtra(PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME, pkgLite.packageName); verification.putExtra(PackageManager.EXTRA_VERIFICATION_VERSION_CODE, pkgLite.versionCode); if (verificationParams != null) { if (verificationParams.getVerificationURI() != null) { verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI, verificationParams.getVerificationURI()); } if (verificationParams.getOriginatingURI() != null) { verification.putExtra(Intent.EXTRA_ORIGINATING_URI, verificationParams.getOriginatingURI()); } if (verificationParams.getReferrer() != null) { verification.putExtra(Intent.EXTRA_REFERRER, verificationParams.getReferrer()); } if (verificationParams.getOriginatingUid() >= 0) { verification.putExtra(Intent.EXTRA_ORIGINATING_UID, verificationParams.getOriginatingUid()); } if (verificationParams.getInstallerUid() >= 0) { verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID, verificationParams.getInstallerUid()); } } final PackageVerificationState verificationState = new PackageVerificationState( requiredUid, args); mPendingVerification.append(verificationId, verificationState); final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite, receivers, verificationState); /* * If any sufficient verifiers were listed in the package * manifest, attempt to ask them. */ if (sufficientVerifiers != null) { final int N = sufficientVerifiers.size(); if (N == 0) { Slog.i(TAG, "Additional verifiers required, but none installed."); ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE; } else { for (int i = 0; i < N; i++) { final ComponentName verifierComponent = sufficientVerifiers.get(i); final Intent sufficientIntent = new Intent(verification); sufficientIntent.setComponent(verifierComponent); mContext.sendBroadcastAsUser(sufficientIntent, getUser()); } } } final ComponentName requiredVerifierComponent = matchComponentForVerifier( mRequiredVerifierPackage, receivers); if (ret == PackageManager.INSTALL_SUCCEEDED && mRequiredVerifierPackage != null) { /* * Send the intent to the required verification agent, * but only start the verification timeout after the * target BroadcastReceivers have run. */ verification.setComponent(requiredVerifierComponent); mContext.sendOrderedBroadcastAsUser(verification, getUser(), android.Manifest.permission.PACKAGE_VERIFICATION_AGENT, new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final Message msg = mHandler .obtainMessage(CHECK_PENDING_VERIFICATION); msg.arg1 = verificationId; mHandler.sendMessageDelayed(msg, getVerificationTimeout()); } }, null, 0, null, null); /* * We don't want the copy to proceed until verification * succeeds, so null out this field. */ mArgs = null; } } else { /* * No package verification is enabled, so immediately start * the remote call to initiate copy using temporary file. */ ret = args.copyApk(mContainerService, true); } } mRet = ret; 

1。判断安装的位置是否在 rom里面还是sd卡里面
2。如果cache过多,系统会清理掉部分cache腾出rom空间,来给copy.
3.向系统发出一个PACKAGE_VERIFICATION_AGENT 来代理校验。看看是否经过用户同意。
4,收到校验通过之后又会向 PackageHandler 发送一个
CHECK_PENDING_VERIFICATION


          case CHECK_PENDING_VERIFICATION: {
                    final int verificationId = msg.arg1;
                    final PackageVerificationState state = mPendingVerification.get(verificationId);

                    if ((state != null) && !state.timeoutExtended()) {
                        final InstallArgs args = state.getInstallArgs();
                        final Uri originUri = Uri.fromFile(args.origin.resolvedFile);

                        Slog.i(TAG, "Verification timed out for " + originUri);
                        mPendingVerification.remove(verificationId);

                        int ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;

                        if (getDefaultVerificationResponse() == PackageManager.VERIFICATION_ALLOW) {
                            Slog.i(TAG, "Continuing with installation of " + originUri);
                            state.setVerifierResponse(Binder.getCallingUid(),
                                    PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
                            broadcastPackageVerified(verificationId, originUri,
                                    PackageManager.VERIFICATION_ALLOW,
                                    state.getInstallArgs().getUser());
                            try {
                                ret = args.copyApk(mContainerService, true);
                            } catch (RemoteException e) {
                                Slog.e(TAG, "Could not contact the ContainerService");
                            }
                        } else {
                            broadcastPackageVerified(verificationId, originUri,
                                    PackageManager.VERIFICATION_REJECT,
                                    state.getInstallArgs().getUser());
                        }

                        processPendingInstall(args, ret);
                        mHandler.sendEmptyMessage(MCS_UNBIND);
                    }
                    break;
                }

1。检查 if (getDefaultVerificationResponse() == PackageManager.VERIFICATION_ALLOW) {
是否呗allow的,如果通过,则广播 allow的操作,并更改state的状态。
2。 ret = args.copyApk(mContainerService, true);
准备开始copyApk,先将Package copy到指定目录,
ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);

再将native copy到系统的目录, ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
abiOverride);

很重要一点是,貌似所有的 so文件都是统一放在一起的,所以so文件 根本就不能有重名的。

在进行 processPendingInstall(args, ret);


          PackageInstalledInfo res = new PackageInstalledInfo();
                res.returnCode = currentStatus;
                res.uid = -1;
                res.pkg = null;
                res.removedInfo = new PackageRemovedInfo();
                if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                    args.doPreInstall(res.returnCode);
                    synchronized (mInstallLock) {
                        installPackageLI(args, res);
                    }
                    args.doPostInstall(res.returnCode, res.uid);
                }

                // A restore should be performed at this point if (a) the install
                // succeeded, (b) the operation is not an update, and (c) the new
                // package has not opted out of backup participation.
                final boolean update = res.removedInfo.removedPackage != null;
                final int flags = (res.pkg == null) ? 0 : res.pkg.applicationInfo.flags;
                boolean doRestore = !update
                        && ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0);

                // Set up the post-install work request bookkeeping. This will be used
                // and cleaned up by the post-install event handling regardless of whether
                // there's a restore pass performed. Token values are >= 1.
                int token;
                if (mNextInstallToken < 0) mNextInstallToken = 1;
                token = mNextInstallToken++;

                PostInstallData data = new PostInstallData(args, res);
                mRunningInstalls.put(token, data);
                if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);

                if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
                    // Pass responsibility to the Backup Manager. It will perform a
                    // restore if appropriate, then pass responsibility back to the
                    // Package Manager to run the post-install observer callbacks
                    // and broadcasts.
                    IBackupManager bm = IBackupManager.Stub.asInterface(
                            ServiceManager.getService(Context.BACKUP_SERVICE));
                    if (bm != null) {
                        if (DEBUG_INSTALL) Log.v(TAG, "token " + token
                                + " to BM for possible restore");
                        try {
                            if (bm.isBackupServiceActive(UserHandle.USER_OWNER)) {
                                bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
                            } else {
                                doRestore = false;
                            }
                        } catch (RemoteException e) {
                            // can't happen; the backup manager is local
                        } catch (Exception e) {
                            Slog.e(TAG, "Exception trying to enqueue restore", e);
                            doRestore = false;
                        }
                    } else {
                        Slog.e(TAG, "Backup Manager not found!");
                        doRestore = false;
                    }
                }

                if (!doRestore) {
                    // No restore possible, or the Backup Manager was mysteriously not
                    // available -- just fire the post-install work request directly.
                    if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
                    Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
                    mHandler.sendMessage(msg);
                }

1。args.doPreInstall(res.returnCode);
在清除文件,老的 dex文件,resourceFile文件
2。installPackageLI(args, res);
中 pkg = pp.parsePackage(tmpPackageFile, parseFlags);
这里会将Apk的地址,注册到AssetManager中去,应该就是写到一个管理apk的配置文件中,每次启动的时候,系统回去读这个配置文件,看看有哪些apk安装过的。
final Package pkg = parseBaseApk(baseApk, assets, flags);
中会根据apk的manifest构建一个Resources,设置一些基本的元素,例如asset的位置 mMetrics,手机硬件的配置。
final Package pkg = parseBaseApk(res, parser, flags, outError);
通过manifest里面的文件得到packagename等,构造出package对象。
3。 pp.collectCertificates(pkg, parseFlags);
获取签名等校验
4。 PackageSetting ps = mSettings.mPackages.get(pkgName);
从原来的setting里面获取已经安装过的包,
如果有,则会和现在的这个包,进行
verifySignaturesLP(ps, pkg);
签名上面的校验,看看签名是否一致。
5。 deriveNonSystemPackageAbi(pkg, new File(pkg.codePath), args.abiOverride,
true /* extract libs */);
系统会根据自己cpu的型号,寻找到合适的so文件copy。

6。 int result = mPackageDexOptimizer
.performDexOpt(pkg, null /* instruction sets /, true / forceDex */,
false /* defer /, false / inclDependencies */);
对dex文件进行指令上面的优化。
7。 if (replace) {
replacePackageLI(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
installerPackageName, res);
} else {
installNewPackageLI(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
args.user, installerPackageName, res);
}
如果是覆盖安装的话,就会走上面的流程,先将未来的包删除deletePackageLI(),只会留下 data的文件夹。
删除 deleteCodeCacheDirsLI(pkgName);原来的指令优化的文件,dex加载的时候,会有指令优化的cache。
在 updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res);
往系统里面写入新的权限,更新新的status 例如版本号之类的。
如果一旦上面有哪个地方出错,系统则会吊用 从新走一次deletePackageLI()尝试覆盖安装

installNewPackageLI(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
args.user, installerPackageName, res);
安装全新的 App

    boolean dataDirExists = getDataPathForPackage(pkg.packageName, 0).exists();

检测data目录是否存在。

检测 if (mSettings.mRenamedPackages.containsKey(pkgName)) {

妈蛋,以前就遇到过这样子的情况,某些时候安装全新App的时候,系统的setting里面,居然会残留 以前没有卸载干净的东西,只能 root过后进入到系统配置文件中强行删除 那行配置,重启手机。

然后其它流程没啥特别的,就是向系统注册权限啊,向setting里面写入。

6。 restoreAtInstall(rpackageName, token)

7。最后会发送一个MCS_UNBIND msg出去

会去查看一下这玩意是否backup过,如果有的话,就能从远端恢复数据。

          case MCS_UNBIND: {
                    // If there is no actual work left, then time to unbind.
                    if (DEBUG_INSTALL) Slog.i(TAG, "mcs_unbind");

                    if (mPendingInstalls.size() == 0 && mPendingVerification.size() == 0) {
                        if (mBound) {
                            if (DEBUG_INSTALL) Slog.i(TAG, "calling disconnectService()");

                            disconnectService();
                        }
                    } else if (mPendingInstalls.size() > 0) {
                        // There are more pending requests in queue.
                        // Just post MCS_BOUND message to trigger processing
                        // of next pending install.
                        mHandler.sendEmptyMessage(MCS_BOUND);
                    }

                    break;
                }

基本上就是和远端的service解绑,并轮询 mPendingInstalls中的任务。

基本上整个安装流程结束

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