上一篇我们讲到在PackageInstallerSession的commitLocked方法中,我们最后调用了PackageManagerService的installStage方法。这里我们直接从
PackageManagerService.java
installStage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
void installStage(String packageName, File stagedDir, String stagedCid, IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams, String installerPackageName, int installerUid, UserHandle user, Certificate[][] certificates) { if (DEBUG_EPHEMERAL) { if ((sessionParams.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) { Slog.d(TAG, "Ephemeral install of " + packageName); } } // VerificationInfo中主要是用来存储权限验证需要的信息 final VerificationInfo verificationInfo = new VerificationInfo( sessionParams.originatingUri, sessionParams.referrerUri, sessionParams.originatingUid, installerUid); final OriginInfo origin; if (stagedDir != null) { origin = OriginInfo.fromStagedFile(stagedDir); } else { origin = OriginInfo.fromStagedContainer(stagedCid); } final Message msg = mHandler.obtainMessage(INIT_COPY); final int installReason = fixUpInstallReason(installerPackageName, installerUid, sessionParams.installReason); // 创建InstallParams对象,准备安装包所需要的安装数据 final InstallParams params = new InstallParams(origin, null, observer, sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid, verificationInfo, user, sessionParams.abiOverride, sessionParams.grantedRuntimePermissions, certificates, installReason); params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params)); // 将安装包的安装数据放到消息中,准备发送出去 msg.obj = params; Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStage", System.identityHashCode(msg.obj)); Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall", System.identityHashCode(msg.obj)); // 向mHandler发送数据 mHandler.sendMessage(msg); } |
上面的代码中,在最后我们向mHandler发送了INIT_COPY,接下来我们分析mHandler是如何处理INIT_COPY的。
mHandler处理INIT_COPY
首先在PackageManagerService初始化的时候有初始化mHandler:mHandler = new PackageHandler(mHandlerThread.getLooper());
,所以这里直接查看PackageHandler相关代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
public void handleMessage(Message msg) { try { // 调用doHandleMessage进行实际处理 doHandleMessage(msg); } finally { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); } } void doHandleMessage(Message msg) { switch (msg.what) { case INIT_COPY: { // 获取安装包的安装数据信息 HandlerParams params = (HandlerParams) msg.obj; // 获取当前等待安装的数量 int idx = mPendingInstalls.size(); if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params); // mBound用于标识是否已经绑定到服务,初始值为false if (!mBound) { Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS", System.identityHashCode(mHandler)); // 如果还没有绑定,那调用connectToService绑定到实际的服务 if (!connectToService()) { Slog.e(TAG, "Failed to bind to media container service"); params.serviceError(); Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS", System.identityHashCode(mHandler)); if (params.traceMethod != null) { Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod, params.traceCookie); } // 如果绑定失败直接返回 return; } else { // 如果绑定成功,将请求添加到mPendingInstalls中,mPendingInstalls是一个ArrayList对象 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; } ........................ |
mBound是用来标记是否已经绑定到DefaultContainerService服务,mBound的默认值是false,表示默认没有绑定到DefaultContainerService。
connectToService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
private boolean connectToService() { if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" + " DefaultContainerService"); // Component的包名为com.android.defcontainer,类名为com.android.defcontainer.DefaultContainerService Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT); Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); // 绑定DefaultContainerService,绑定成功后会调用service的onServiceConnected if (mContext.bindServiceAsUser(service, mDefContainerConn, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) { // 设置继承优先级 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); mBound = true; return true; } Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); return false; } |
这里bindServiceAsUser和应用层调用bindService是一样的,当传递BIND_AUTO_CREATE后会立刻调用mDefContainerConn的onServiceConnected方法。
DefaultContainerConnection
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
final private DefaultContainerConnection mDefContainerConn = new DefaultContainerConnection(); class DefaultContainerConnection implements ServiceConnection { public void onServiceConnected(ComponentName name, IBinder service) { if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected"); final IMediaContainerService imcs = IMediaContainerService.Stub .asInterface(Binder.allowBlocking(service)); // 发送MCS_BOUND信息,并且携带imcs mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs)); } public void onServiceDisconnected(ComponentName name) { if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected"); } } |
在onServiceConnected中,首先获取到IMediaContainerService的服务对象,然后再将该imcs服务对象附加到MCS_BOUND类型的Message中,最后再发送出去。这里再一次通过mHandler来处理数据,接下来我们分析mHandler是如何处理MCS_BOUND类型的消息的。
mHandler处理MCS_BOUND消息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
.................. case MCS_BOUND: { if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound"); // 获取msg中的IMediaContainerService服务对象 if (msg.obj != null) { mContainerService = (IMediaContainerService) msg.obj; Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS", System.identityHashCode(mHandler)); } // mContainerService不为null if (mContainerService == null) { .......... // 如果mPendingInstalls中存在未处理的安装请求 } else if (mPendingInstalls.size() > 0) { // 获取第一个安装请求 HandlerParams params = mPendingInstalls.get(0); if (params != null) { Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall", System.identityHashCode(params)); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy"); // 调用startCopy开始处理APK的安装,下面再分析其处理过程 if (params.startCopy()) { if (DEBUG_SD_INSTALL) Log.i(TAG, "Checking for more work or unbind..."); // 处理完成,移除安装请求 if (mPendingInstalls.size() > 0) { mPendingInstalls.remove(0); } if (mPendingInstalls.size() == 0) { // 如果没有已经没有安装请求了,而且DefaultContainerService还处于绑定中 if (mBound) { if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting delayed MCS_UNBIND"); // 发送消息,解除DefaultContainerService绑定 removeMessages(MCS_UNBIND); Message ubmsg = obtainMessage(MCS_UNBIND); sendMessageDelayed(ubmsg, 10000); } } else { // mPendingInstalls中还有未处理的安装请求,继续发送MCS_BOUND消息处理 if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting MCS_BOUND for next work"); mHandler.sendEmptyMessage(MCS_BOUND); } } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } else { // Should never happen ideally. Slog.w(TAG, "Empty queue"); } break; } case MCS_RECONNECT: { .............. |
上面的代码都比较容易理解,我们接着分析关键部分startCopy的代码。
startCopy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
final boolean startCopy() { boolean res; try { if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this); // MAX_RETRIES=4,代表有4次尝试安装的机会,如果超过四次就放弃这个安装请求 if (++mRetries > MAX_RETRIES) { Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up"); // 发送放弃安装请求消息 mHandler.sendEmptyMessage(MCS_GIVE_UP); handleServiceError(); return false; } else { // 处理安装请求 handleStartCopy(); res = true; } } catch (RemoteException e) { if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT"); mHandler.sendEmptyMessage(MCS_RECONNECT); res = false; } // 处理返回值 handleReturnCode(); return res; } |
这里主要有handleStartCopy和handleReturnCode来完成所有的工作。
handleStartCopy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
public void handleStartCopy() throws RemoteException { 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"); } } // 安装到SD卡 final boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0; // 安装到内部存储 final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0; // 安装临时存储,Instant APP Google版小程序 final boolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0; PackageInfoLite pkgLite = null; // 不能同时安装在内部存储以及SD卡中 if (onInt && onSd) { Slog.w(TAG, "Conflicting flags specified for installing on both internal and external"); ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; // Instant APP不能安装到SD卡中 } else if (onSd && ephemeral) { Slog.w(TAG, "Conflicting flags specified for installing ephemeral on external"); ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; } else { // 通过mContainerService获取最小APK安装信息 pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags, packageAbiOverride); if (DEBUG_EPHEMERAL && ephemeral) { Slog.v(TAG, "pkgLite for install: " + pkgLite); } // 如果空间不住,尝试释放cache 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()); // 计算安装container的大小 final long sizeBytes = mContainerService.calculateInstalledSize( origin.resolvedPath, isForwardLocked(), packageAbiOverride); try { // 释放cache mInstaller.freeCache(null, sizeBytes + lowThreshold, 0, 0); pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags, packageAbiOverride); } catch (InstallerException e) { Slog.w(TAG, "Failed to free cache", e); } // 空间依旧不够 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 { // 调用installLocationPolicy判断最终的安装路径 // installLocationPolicy主要判断终端上是否有已经安装过该APK,同一个APK一般只能用新版的替换旧版 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 if (loc == PackageHelper.RECOMMEND_INSTALL_EPHEMERAL) { if (DEBUG_EPHEMERAL) { Slog.v(TAG, "...setting INSTALL_EPHEMERAL install flag"); } installFlags |= PackageManager.INSTALL_INSTANT_APP; installFlags &= ~(PackageManager.INSTALL_EXTERNAL |PackageManager.INSTALL_INTERNAL); } else { // Make sure the flag for installing on external // media is unset installFlags |= PackageManager.INSTALL_INTERNAL; installFlags &= ~PackageManager.INSTALL_EXTERNAL; } } } } // 在上面确认完安装路径后,调用createInstallArgs来创建一个安装参数对象 final InstallArgs args = createInstallArgs(this); mArgs = args; if (ret == PackageManager.INSTALL_SUCCEEDED) { // 如果是为所有用户安装,就调用设备拥有者来校验安装此应用 UserHandle verifierUser = getUser(); if (verifierUser == UserHandle.ALL) { verifierUser = UserHandle.SYSTEM; } /* * 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, MATCH_DEBUG_TRIAGED_MISSING, verifierUser.getIdentifier()); final int optionalUid = mOptionalVerifierPackage == null ? -1 : getPackageUid(mOptionalVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING, verifierUser.getIdentifier()); final int installerUid = verificationInfo == null ? -1 : verificationInfo.installerUid; // 检查是否需要执行验证,正常情况下通过adb安装应用以及是首先用户执行应用安装才需要执行验证 if (!origin.existing && (requiredUid != -1 || optionalUid != -1) && isVerificationEnabled( verifierUser.getIdentifier(), installFlags, installerUid)) { ................................ } else { // 调用安装参数对象的copyApk方法执行安装。 ret = args.copyApk(mContainerService, true); } } mRet = ret; } |
这上面的代码内容很多,这里尽量对其中一些函数做分析。
1. handleStartCopy -> getMinimalPackageInfo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
public PackageInfoLite getMinimalPackageInfo(String packagePath, int flags, String abiOverride) { // 获取DefaultContainerService服务对象 final Context context = DefaultContainerService.this; final boolean isForwardLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0; // 创建应用包信息对象 PackageInfoLite ret = new PackageInfoLite(); if (packagePath == null) { Slog.i(TAG, "Invalid package file " + packagePath); ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK; return ret; } final File packageFile = new File(packagePath); final PackageParser.PackageLite pkg; final long sizeBytes; try { // 创建PackageLite pkg = PackageParser.parsePackageLite(packageFile, 0); // 计算安装APK所需存储空间大小 sizeBytes = PackageHelper.calculateInstalledSize(pkg, isForwardLocked, abiOverride); } catch (PackageParserException | IOException e) { Slog.w(TAG, "Failed to parse package at " + packagePath + ": " + e); if (!packageFile.exists()) { ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_URI; } else { ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK; } return ret; } final int recommendedInstallLocation; final long token = Binder.clearCallingIdentity(); try { // 调用resolveInstallLocation确定应用安装位置 recommendedInstallLocation = PackageHelper.resolveInstallLocation(context, pkg.packageName, pkg.installLocation, sizeBytes, flags); } finally { Binder.restoreCallingIdentity(token); } ret.packageName = pkg.packageName; ret.splitNames = pkg.splitNames; ret.versionCode = pkg.versionCode; ret.baseRevisionCode = pkg.baseRevisionCode; ret.splitRevisionCodes = pkg.splitRevisionCodes; ret.installLocation = pkg.installLocation; ret.verifiers = pkg.verifiers; ret.recommendedInstallLocation = recommendedInstallLocation; ret.multiArch = pkg.multiArch; return ret; } |
这里对最终的安装路径感兴趣,所以继续最终下去,接着看resolveInstallLocation的代码
1.1 getMinimalPackageInfo -> resolveInstallLocation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
public static int resolveInstallLocation(Context context, String packageName, int installLocation, long sizeBytes, int installFlags) { // 创建SessionParams,并填充其中的参数 final SessionParams params = new SessionParams(SessionParams.MODE_INVALID); params.appPackageName = packageName; params.installLocation = installLocation; params.sizeBytes = sizeBytes; params.installFlags = installFlags; try { // 调用同名重载方法 return resolveInstallLocation(context, params); } catch (IOException e) { throw new IllegalStateException(e); } } public static int resolveInstallLocation(Context context, SessionParams params) throws IOException { ApplicationInfo existingInfo = null; try { // 通过PackageManager查看是否已安装同名的应用 existingInfo = context.getPackageManager().getApplicationInfo(params.appPackageName, PackageManager.MATCH_ANY_USER); } catch (NameNotFoundException ignored) { } final int prefer; final boolean checkBoth; boolean ephemeral = false; // Instant APP安装到内部存储,checkBoth表示不需要再次确认 if ((params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) { prefer = RECOMMEND_INSTALL_INTERNAL; ephemeral = true; checkBoth = false; } else if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) { prefer = RECOMMEND_INSTALL_INTERNAL; checkBoth = false; } else if ((params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) { prefer = RECOMMEND_INSTALL_EXTERNAL; checkBoth = false; } else if (params.installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) { prefer = RECOMMEND_INSTALL_INTERNAL; checkBoth = false; } else if (params.installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) { prefer = RECOMMEND_INSTALL_EXTERNAL; checkBoth = true; // 大部分情况下,AndroidManifest中定义的为AUTO } else if (params.installLocation == PackageInfo.INSTALL_LOCATION_AUTO) { // 如果APP已经安装过,那么倾向于和原安装路径保持一致 if (existingInfo != null) { if ((existingInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) { prefer = RECOMMEND_INSTALL_EXTERNAL; } else { prefer = RECOMMEND_INSTALL_INTERNAL; } } else { // 否则新安装应用安装到内部存储 prefer = RECOMMEND_INSTALL_INTERNAL; } checkBoth = true; } else { prefer = RECOMMEND_INSTALL_INTERNAL; checkBoth = false; } boolean fitsOnInternal = false; // fitsOnInternal和fitsOnExternal用来确认prefer指定的安装路径是否有足够存储空间进行安装 if (checkBoth || prefer == RECOMMEND_INSTALL_INTERNAL) { fitsOnInternal = fitsOnInternal(context, params); } boolean fitsOnExternal = false; if (checkBoth || prefer == RECOMMEND_INSTALL_EXTERNAL) { fitsOnExternal = fitsOnExternal(context, params); } if (prefer == RECOMMEND_INSTALL_INTERNAL) { // The ephemeral case will either fit and return EPHEMERAL, or will not fit // and will fall through to return INSUFFICIENT_STORAGE if (fitsOnInternal) { return (ephemeral) ? PackageHelper.RECOMMEND_INSTALL_EPHEMERAL : PackageHelper.RECOMMEND_INSTALL_INTERNAL; } } else if (prefer == RECOMMEND_INSTALL_EXTERNAL) { if (fitsOnExternal) { return PackageHelper.RECOMMEND_INSTALL_EXTERNAL; } } if (checkBoth) { if (fitsOnInternal) { return PackageHelper.RECOMMEND_INSTALL_INTERNAL; } else if (fitsOnExternal) { return PackageHelper.RECOMMEND_INSTALL_EXTERNAL; } } // 如果上面都没有返回,则表示存储空间不足 return PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE; } |
上面显示了安装路径的确认过程。现在我们再次返回handleStartCopy方法中,接着我们分析handleStartCopy方法中的createInstallArgs方法。这个方法会根据安装路径来创建不同的参数对象,源码如下
2. handleStartCopy -> createInstallArgs
1 2 3 4 5 6 7 8 9 10 11 12 |
private InstallArgs createInstallArgs(InstallParams params) { // move表示安装路径在内置存储和外置存储间迁移 if (params.move != null) { return new MoveInstallArgs(params); // AESC表示安装路径为SD卡 } else if (installOnExternalAsec(params.installFlags) || params.isForwardLocked()) { return new AsecInstallArgs(params); // File表示安装到内置存储空间 } else { return new FileInstallArgs(params); } } |
InstallArgs是一个抽象类,定义了应用的安装逻辑。MoveInstallArgs、AsecInstallArgs和FileInstallArgs三个类都是InstallArgs的子类。这里确认使用FileInstallArgs,所以我们接着回到handleStartCopy方法中,分析args.copyApk方法。args表示的就是一个FileInstallArgs对象,所以这里调用的是FileInstallArgs的copyApk方法。
FileInstallArgs.copyApk
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk"); try { // 直接调用doCopyApk完成所需操作 return doCopyApk(imcs, temp); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } private int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException { if (origin.staged) { if (DEBUG_INSTALL) Slog.d(TAG, origin.file + " already staged; skipping copy"); codeFile = origin.file; resourceFile = origin.file; return PackageManager.INSTALL_SUCCEEDED; } try { // 非Instate APP final boolean isEphemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0; // 创建要给临时路径 // 临时路径一般为/data/app/xxxxxxxxxx.tmp final File tempDir = mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral); codeFile = tempDir; resourceFile = tempDir; } catch (IOException e) { Slog.w(TAG, "Failed to create copy file: " + e); return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; } // 定义回调接口 final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() { @Override public ParcelFileDescriptor open(String name, int mode) throws RemoteException { if (!FileUtils.isValidExtFilename(name)) { throw new IllegalArgumentException("Invalid filename: " + name); } try { // 当接口被回调时,需要创建并打开接口,同时赋予相应权限 final File file = new File(codeFile, name); final FileDescriptor fd = Os.open(file.getAbsolutePath(), O_RDWR | O_CREAT, 0644); Os.chmod(file.getAbsolutePath(), 0644); return new ParcelFileDescriptor(fd); } catch (ErrnoException e) { throw new RemoteException("Failed to open: " + e.getMessage()); } } }; // 调用DefaultContainerService的copyPackage方法进行package复制操作,同时将回调接口传入 int ret = PackageManager.INSTALL_SUCCEEDED; ret = imcs.copyPackage(origin.file.getAbsolutePath(), target); if (ret != PackageManager.INSTALL_SUCCEEDED) { Slog.e(TAG, "Failed to copy package"); return ret; } // 复制APK里面的native库文件 final File libraryRoot = new File(codeFile, LIB_DIR_NAME); NativeLibraryHelper.Handle handle = null; try { handle = NativeLibraryHelper.Handle.create(codeFile); ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot, abiOverride); } catch (IOException e) { Slog.e(TAG, "Copying native libraries failed", e); ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; } finally { IoUtils.closeQuietly(handle); } return ret; } |
上面调用DefaultContainerService的copyPackage方法进行Package的复制操作,所以我们看看copyPackage完成什么操作。
doCopyApk -> copyPackage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
public int copyPackage(String packagePath, IParcelFileDescriptorFactory target) { // 如果源文件或者目标文件为null,返回安装出错标志 if (packagePath == null || target == null) { return PackageManager.INSTALL_FAILED_INVALID_URI; } PackageLite pkg = null; try { final File packageFile = new File(packagePath); // 老方法了,获取安装包信息 pkg = PackageParser.parsePackageLite(packageFile, 0); // 调用copyPackageInner方法进行实际复制操作 return copyPackageInner(pkg, target); } catch (PackageParserException | IOException | RemoteException e) { Slog.w(TAG, "Failed to copy package at " + packagePath + ": " + e); return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; } } private int copyPackageInner(PackageLite pkg, IParcelFileDescriptorFactory target) throws IOException, RemoteException { // 将package的baseCodePath复制到目标地址并命名为base.apk copyFile(pkg.baseCodePath, target, "base.apk"); // 如果使用了APK拆分技术,就执行下面这一段 if (!ArrayUtils.isEmpty(pkg.splitNames)) { for (int i = 0; i < pkg.splitNames.length; i++) { copyFile(pkg.splitCodePaths[i], target, "split_" + pkg.splitNames[i] + ".apk"); } } return PackageManager.INSTALL_SUCCEEDED; } private void copyFile(String sourcePath, IParcelFileDescriptorFactory target, String targetName) throws IOException, RemoteException { Slog.d(TAG, "Copying " + sourcePath + " to " + targetName); InputStream in = null; OutputStream out = null; try { //目的文件作为输出,这里进行了多层封装 //回调接口target调用open函数后,将创建并打开目的端文件,然后赋予相应的写权限 //ParcelFileDescriptor.AutoCloseOutputStream利用文件描述符构造出一个可自动关闭的输出流 in = new FileInputStream(sourcePath); out = new ParcelFileDescriptor.AutoCloseOutputStream( target.open(targetName, ParcelFileDescriptor.MODE_READ_WRITE)); // 进行实际复制操作 Streams.copy(in, out); } finally { IoUtils.closeQuietly(out); IoUtils.closeQuietly(in); } } |
handleStartCopy的所有流程到这里就结束了,接着我们返回到最前面的startCopy函数处,还有一个方法调用没有解析,那就是handleReturnCode方法了,接下来让我们继续go on
handleReturnCode
1 2 3 4 5 |
void handleReturnCode() { if (mArgs != null) { processPendingInstall(mArgs, mRet); } } |
这上面的mArgs是一个FileInstallArgs对象,代表一个安装参数对象。
processPendingInstall
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
private void processPendingInstall(final InstallArgs args, final int currentStatus) { // 因为引用安装消耗时间可能较长,所以这里创建一个异步操作 mHandler.post(new Runnable() { public void run() { mHandler.removeCallbacks(this); // 安装结果信息对象 PackageInstalledInfo res = new PackageInstalledInfo(); res.setReturnCode(currentStatus); res.uid = -1; res.pkg = null; res.removedInfo = null; if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { // 安装前处理 args.doPreInstall(res.returnCode); synchronized (mInstallLock) { // 实际安装操作 installPackageTracedLI(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 != null && 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) { // 调用backup接口进行恢复 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"); Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "restore", token); try { // TODO: http://b/22388012 if (bm.isBackupServiceActive(UserHandle.USER_SYSTEM)) { 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) { if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token); Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall", token); // 发出一个POST_INSTALL消息,触发后续的操作 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0); mHandler.sendMessage(msg); } } }); } |
安装前处理doPreInstall
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
int doPreInstall(int status) { if (status != PackageManager.INSTALL_SUCCEEDED) { cleanUp(); } return status; } private boolean cleanUp() { if (codeFile == null || !codeFile.exists()) { return false; } removeCodePathLI(codeFile); if (resourceFile != null && !FileUtils.contains(codeFile, resourceFile)) { resourceFile.delete(); } return true; } void removeCodePathLI(File codePath) { if (codePath.isDirectory()) { try { mInstaller.rmPackageDir(codePath.getAbsolutePath()); } catch (InstallerException e) { Slog.w(TAG, "Failed to remove code path", e); } } else { codePath.delete(); } } |
这里有个疑问就是,在执行doPreInstall前就已经判断过status是否为PackageManager.INSTALL_SUCCEEDED,只有status等于PackageManager.INSTALL_SUCCEEDED才会执行doPreInstall操作。为什么在doPreInstall里面还要多此一举呢?这里估计res.returnCode这个返回值是可以在多处被修改的,所以可能在整个安装过程中这个值被修改了,例如在此之前可能还在执行正常的安装,但是到执行doPreInstall的时候,用户突然点击了Cancel按钮。
安装实际操作 installPackageTracedLI
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 |
private void installPackageTracedLI(InstallArgs args, PackageInstalledInfo res) { try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackage"); installPackageLI(args, res); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } private void installPackageLI(InstallArgs args, PackageInstalledInfo res) { // 获取安装标志位 final int installFlags = args.installFlags; final String installerPackageName = args.installerPackageName; final String volumeUuid = args.volumeUuid; final File tmpPackageFile = new File(args.getCodePath()); // 根据安装标志位定义一些Boolean变量 final boolean forwardLocked = ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0); final boolean onExternal = (((installFlags & PackageManager.INSTALL_EXTERNAL) != 0) || (args.volumeUuid != null)); final boolean instantApp = ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0); final boolean fullApp = ((installFlags & PackageManager.INSTALL_FULL_APP) != 0); final boolean forceSdk = ((installFlags & PackageManager.INSTALL_FORCE_SDK) != 0); final boolean virtualPreload = ((installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0); boolean replace = false; int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE; if (args.move != null) { // moving a complete application; perform an initial scan on the new install location scanFlags |= SCAN_INITIAL; } if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) { scanFlags |= SCAN_DONT_KILL_APP; } if (instantApp) { scanFlags |= SCAN_AS_INSTANT_APP; } if (fullApp) { scanFlags |= SCAN_AS_FULL_APP; } if (virtualPreload) { scanFlags |= SCAN_AS_VIRTUAL_PRELOAD; } // 设置默认安装返回值为INSTALL_SUCCEEDED res.setReturnCode(PackageManager.INSTALL_SUCCEEDED); // 安装包包名 res.installerPackageName = installerPackageName; if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile); // 完整性检查 if (instantApp && (forwardLocked || onExternal)) { Slog.i(TAG, "Incompatible ephemeral install; fwdLocked=" + forwardLocked + " external=" + onExternal); res.setReturnCode(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID); return; } // Retrieve PackageSettings and parse package final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY | PackageParser.PARSE_ENFORCE_CODE | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0) | (instantApp ? PackageParser.PARSE_IS_EPHEMERAL : 0) | (forceSdk ? PackageParser.PARSE_FORCE_SDK : 0); // 创建PackagePaser PackageParser pp = new PackageParser(); pp.setSeparateProcesses(mSeparateProcesses); pp.setDisplayMetrics(mMetrics); pp.setCallback(mPackageParserCallback); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage"); final PackageParser.Package pkg; try { // 解析APK文件,获取Package信息 pkg = pp.parsePackage(tmpPackageFile, parseFlags); } catch (PackageParserException e) { res.setError("Failed parse during installPackageLI", e); return; } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } // 检查系统是否符合安装Instant APP的要求 if (instantApp && pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) { Slog.w(TAG, "Instant app package " + pkg.packageName + " does not target O"); res.setError(INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE, "Instant app package must target O"); return; } if (instantApp && pkg.applicationInfo.targetSandboxVersion != 2) { Slog.w(TAG, "Instant app package " + pkg.packageName + " does not target targetSandboxVersion 2"); res.setError(INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE, "Instant app package must use targetSanboxVersion 2"); return; } // 安装静态共享库 if (pkg.applicationInfo.isStaticSharedLibrary()) { // Static shared libraries have synthetic package names renameStaticSharedLibraryPackage(pkg); // No static shared libs on external storage if (onExternal) { Slog.i(TAG, "Static shared libs can only be installed on internal storage."); res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION, "Packages declaring static-shared libs cannot be updated"); return; } } // 安装一簇安装包的时候,需要记录child package的安装情况 if (pkg.childPackages != null) { synchronized (mPackages) { final int childCount = pkg.childPackages.size(); for (int i = 0; i < childCount; i++) { PackageParser.Package childPkg = pkg.childPackages.get(i); PackageInstalledInfo childRes = new PackageInstalledInfo(); childRes.setReturnCode(PackageManager.INSTALL_SUCCEEDED); childRes.pkg = childPkg; childRes.name = childPkg.packageName; PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName); if (childPs != null) { childRes.origUsers = childPs.queryInstalledUsers( sUserManager.getUserIds(), true); } if ((mPackages.containsKey(childPkg.packageName))) { childRes.removedInfo = new PackageRemovedInfo(this); childRes.removedInfo.removedPackage = childPkg.packageName; childRes.removedInfo.installerPackageName = childPs.installerPackageName; } if (res.addedChildPackages == null) { res.addedChildPackages = new ArrayMap<>(); } res.addedChildPackages.put(childPkg.packageName, childRes); } } } // CPU ABI处理 if (TextUtils.isEmpty(pkg.cpuAbiOverride)) { pkg.cpuAbiOverride = args.abiOverride; } // APK标记为仅用于测试时的执行逻辑 String pkgName = res.name = pkg.packageName; if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) { if ((installFlags & PackageManager.INSTALL_ALLOW_TEST) == 0) { res.setError(INSTALL_FAILED_TEST_ONLY, "installPackageLI"); return; } } try { // 如果还没解析到APK的安装签名证书 if (args.certificates != null) { try { // 获取APK的签名帧数 PackageParser.populateCertificates(pkg, args.certificates); } catch (PackageParserException e) { // there was something wrong with the certificates we were given; // try to pull them from the APK PackageParser.collectCertificates(pkg, parseFlags); } } else { PackageParser.collectCertificates(pkg, parseFlags); } } catch (PackageParserException e) { res.setError("Failed collect during installPackageLI", e); return; } pp = null; String oldCodePath = null; boolean systemApp = false; synchronized (mPackages) { // 检查是否已经安装过该安装包 if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { String oldName = mSettings.getRenamedPackageLPr(pkgName); if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName) && mPackages.containsKey(oldName)) { // 该安装包是来自一个原始包的,而且设备已经从原始包升级而来 // 这里需要继续使用原始包的包名 pkg.setPackageName(oldName); pkgName = pkg.packageName; replace = true; if (DEBUG_INSTALL) Slog.d(TAG, "Replacing existing renamed package: oldName=" + oldName + " pkgName=" + pkgName); } else if (mPackages.containsKey(pkgName)) { // 设置为替换 replace = true; if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName); } // Child packages are installed through the parent package if (pkg.parentPackage != null) { res.setError(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME, "Package " + pkg.packageName + " is child of package " + pkg.parentPackage.parentPackage + ". Child packages " + "can be updated only through the parent package."); return; } // 如果需要替换 if (replace) { // 阻止安装包的TargetSdk降级,以逃避运行时权限检查 PackageParser.Package oldPackage = mPackages.get(pkgName); final int oldTargetSdk = oldPackage.applicationInfo.targetSdkVersion; final int newTargetSdk = pkg.applicationInfo.targetSdkVersion; if (oldTargetSdk > Build.VERSION_CODES.LOLLIPOP_MR1 && newTargetSdk <= Build.VERSION_CODES.LOLLIPOP_MR1) { res.setError(PackageManager.INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE, "Package " + pkg.packageName + " new target SDK " + newTargetSdk + " doesn't support runtime permissions but the old" + " target SDK " + oldTargetSdk + " does."); return; } // 防止应用降低SandBox的版本 final int oldTargetSandbox = oldPackage.applicationInfo.targetSandboxVersion; final int newTargetSandbox = pkg.applicationInfo.targetSandboxVersion; if (oldTargetSandbox == 2 && newTargetSandbox != 2) { res.setError(PackageManager.INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE, "Package " + pkg.packageName + " new target sandbox " + newTargetSandbox + " is incompatible with the previous value of" + oldTargetSandbox + "."); return; } // 防止直接安装子程序 if (oldPackage.parentPackage != null) { res.setError(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME, "Package " + pkg.packageName + " is child of package " + oldPackage.parentPackage + ". Child packages " + "can be updated only through the parent package."); return; } } } PackageSetting ps = mSettings.mPackages.get(pkgName); // 查看Setting中是否存在要安装的APK的信息,如果有就获取安装包对应的信息 if (ps != null) { if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps); // 可以存在多个静态共享库,在安装时需要检查其签名是否正确 PackageSetting signatureCheckPs = ps; if (pkg.applicationInfo.isStaticSharedLibrary()) { SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg); if (libraryEntry != null) { signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk); } } // 检查应用签名是否正确 if (shouldCheckUpgradeKeySetLP(signatureCheckPs, scanFlags)) { if (!checkUpgradeKeySetLP(signatureCheckPs, pkg)) { res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package " + pkg.packageName + " upgrade keys do not match the " + "previously installed version"); return; } } else { try { verifySignaturesLP(signatureCheckPs, pkg); } catch (PackageManagerException e) { res.setError(e.error, e.getMessage()); return; } } // 检查该应用是否是systemApp oldCodePath = mSettings.mPackages.get(pkgName).codePathString; if (ps.pkg != null && ps.pkg.applicationInfo != null) { systemApp = (ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } res.origUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true); } // 获取APK中的申明使用的权限 int N = pkg.permissions.size(); for (int i = N-1; i >= 0; i--) { PackageParser.Permission perm = pkg.permissions.get(i); BasePermission bp = mSettings.mPermissions.get(perm.info.name); // 仅允许systemApp定义ephemeral权限 if ((perm.info.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0 && !systemApp) { Slog.w(TAG, "Non-System package " + pkg.packageName + " attempting to delcare ephemeral permission " + perm.info.name + "; Removing ephemeral."); perm.info.protectionLevel &= ~PermissionInfo.PROTECTION_FLAG_INSTANT; } // 检查新安装的应用是否定义了已经定义过的权限 if (bp != null) { // If the defining package is signed with our cert, it's okay. This // also includes the "updating the same package" case, of course. // "updating same package" could also involve key-rotation. final boolean sigsOk; if (bp.sourcePackage.equals(pkg.packageName) && (bp.packageSetting instanceof PackageSetting) && (shouldCheckUpgradeKeySetLP((PackageSetting) bp.packageSetting, scanFlags))) { sigsOk = checkUpgradeKeySetLP((PackageSetting) bp.packageSetting, pkg); } else { sigsOk = compareSignatures(bp.packageSetting.signatures.mSignatures, pkg.mSignatures) == PackageManager.SIGNATURE_MATCH; } if (!sigsOk) { // If the owning package is the system itself, we log but allow // install to proceed; we fail the install on all other permission // redefinitions. if (!bp.sourcePackage.equals("android")) { res.setError(INSTALL_FAILED_DUPLICATE_PERMISSION, "Package " + pkg.packageName + " attempting to redeclare permission " + perm.info.name + " already owned by " + bp.sourcePackage); res.origPermission = perm.info.name; res.origPackage = bp.sourcePackage; return; } else { Slog.w(TAG, "Package " + pkg.packageName + " attempting to redeclare system permission " + perm.info.name + "; ignoring new declaration"); pkg.permissions.remove(i); } } else if (!PLATFORM_PACKAGE_NAME.equals(pkg.packageName)) { // 防止将protection级别的权限改为dangerous级别的权限 if ((perm.info.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) == PermissionInfo.PROTECTION_DANGEROUS) { if (bp != null && !bp.isRuntime()) { Slog.w(TAG, "Package " + pkg.packageName + " trying to change a " + "non-runtime permission " + perm.info.name + " to runtime; keeping old protection level"); perm.info.protectionLevel = bp.protectionLevel; } } } } } } if (systemApp) { if (onExternal) { // 系统APP不能升级安装到SD卡中 res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION, "Cannot install updates to system apps on sdcard"); return; } else if (instantApp) { // 系统APP不能升级替换为Instant APP res.setError(INSTALL_FAILED_INSTANT_APP_INVALID, "Cannot update a system app with an instant app"); return; } } // 迁移应用,这里不是先略过 if (args.move != null) { ................ } // 重命名应用 // 重命名应用会从原来的临时目录/data/app/xxxxxxxxxx.tmp修改为/data/app/包名-1/base.apk // 其中-1代码安装的版本好,如果在此基础上进行了一次update升级安装的话,这个-1会变成-2 if (!args.doRename(res.returnCode, pkg, oldCodePath)) { res.setError(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename"); return; } // 检查是否要进行dex优化 // 优化的条件是1、没有添加前向索 2、不是安装在外置存储 3、不是Instant APP或者稍后会进行DEX优化 final boolean performDexopt = !forwardLocked && !pkg.applicationInfo.isExternalAsec() && (!instantApp || Global.getInt(mContext.getContentResolver(), Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0); if (performDexopt) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt"); DexoptOptions dexoptOptions = new DexoptOptions(pkg.packageName, REASON_INSTALL, DexoptOptions.DEXOPT_BOOT_COMPLETE); mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles, null /* instructionSets */, getOrCreateCompilerPackageStats(pkg), mDexManager.getPackageUseInfoOrDefault(pkg.packageName), dexoptOptions); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } BackgroundDexOptService.notifyPackageChanged(pkg.packageName); startIntentFilterVerifications(args.user.getIdentifier(), replace, pkg); try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags, "installPackageLI")) { // 替换安装 if (replace) { if (pkg.applicationInfo.isStaticSharedLibrary()) { PackageParser.Package existingPkg = mPackages.get(pkg.packageName); if (existingPkg != null && existingPkg.mVersionCode != pkg.mVersionCode) { res.setError(INSTALL_FAILED_DUPLICATE_PACKAGE, "Packages declaring " + "static-shared libs cannot be updated"); return; } } // 用新的Package替换旧的Package replacePackageLIF(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user, installerPackageName, res, args.installReason); } else { // 将新的Package信息添加到PKMS中 installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES, args.user, installerPackageName, volumeUuid, res, args.installReason); } } synchronized (mPackages) { // 下面更新应用程序所属的用户 final PackageSetting ps = mSettings.mPackages.get(pkgName); if (ps != null) { res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true); ps.setUpdateAvailable(false /*updateAvailable*/); } final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; for (int i = 0; i < childCount; i++) { PackageParser.Package childPkg = pkg.childPackages.get(i); PackageInstalledInfo childRes = res.addedChildPackages.get(childPkg.packageName); PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName); if (childPs != null) { childRes.newUsers = childPs.queryInstalledUsers( sUserManager.getUserIds(), true); } } if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { updateSequenceNumberLP(ps, res.newUsers); updateInstantAppInstallerLocked(pkgName); } } } |
这一段代码比较长,博主能看懂能解释的都尽量解释了。因为我们这里假设的是安装过程,所以我们接下来看安装应用调用的方法installNewPackageLIF。
installPackageLI -> installNewPackageLIF
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags, int scanFlags, UserHandle user, String installerPackageName, String volumeUuid, PackageInstalledInfo res, int installReason) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installNewPackage"); // 获取包名 String pkgName = pkg.packageName; if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg); synchronized(mPackages) { final String renamedPackage = mSettings.getRenamedPackageLPr(pkgName); if (renamedPackage != null) { // 如果之前有安装过相同包名,但是已将包名改为其他包名的应用我们将其视为re-install res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName + " without first uninstalling package running as " + renamedPackage); return; } if (mPackages.containsKey(pkgName)) { // 重安装应用 res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName + " without first uninstalling."); return; } } try { // 扫描解析APK PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags, System.currentTimeMillis(), user); // 更新Setting信息 updateSettingsLI(newPackage, installerPackageName, null, res, user, installReason); if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { // 为新应用准备数据 prepareAppDataAfterInstallLIF(newPackage); } else { // 如果安装失败了则清除安装数据。 deletePackageLIF(pkgName, UserHandle.ALL, false, null, PackageManager.DELETE_KEEP_DATA, res.removedInfo, true, null); } } catch (PackageManagerException e) { res.setError("Package couldn't be installed in " + pkg.codePath, e); } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } |
最后我们还有一个POST_INSTALL消息还没处理,接下来我们查看POST_INSTALL消息是如何处理的
POST_INSTALL消息处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
case POST_INSTALL: { if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1); PostInstallData data = mRunningInstalls.get(msg.arg1); final boolean didRestore = (msg.arg2 != 0); mRunningInstalls.delete(msg.arg1); if (data != null) { InstallArgs args = data.args; PackageInstalledInfo parentRes = data.res; final boolean grantPermissions = (args.installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0; final boolean killApp = (args.installFlags & PackageManager.INSTALL_DONT_KILL_APP) == 0; final boolean virtualPreload = ((args.installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0); final String[] grantedPermissions = args.installGrantPermissions; // 调用handlePackagePostInstall处理父安装包 handlePackagePostInstall(parentRes, grantPermissions, killApp, virtualPreload, grantedPermissions, didRestore, args.installerPackageName, args.observer); // 同样调用handlePackagePostInstall处理自安装包 final int childCount = (parentRes.addedChildPackages != null) ? parentRes.addedChildPackages.size() : 0; for (int i = 0; i < childCount; i++) { PackageInstalledInfo childRes = parentRes.addedChildPackages.valueAt(i); handlePackagePostInstall(childRes, grantPermissions, killApp, virtualPreload, grantedPermissions, false /*didRestore*/, args.installerPackageName, args.observer); } // Log tracing if needed if (args.traceMethod != null) { Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, args.traceMethod, args.traceCookie); } } else { Slog.e(TAG, "Bogus post-install token " + msg.arg1); } Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "postInstall", msg.arg1); } break; |
handlePackagePostInstall是我们需要分析的最后一个函数了,再坚持一下把它看完吧。
handlePackagePostInstall
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
private void handlePackagePostInstall(PackageInstalledInfo res, boolean grantPermissions, boolean killApp, boolean virtualPreload, String[] grantedPermissions, boolean launchedForRestore, String installerPackage, IPackageInstallObserver2 installObserver) { if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { // 如果是移除应用,发送应用移除广播 if (res.removedInfo != null) { res.removedInfo.sendPackageRemovedBroadcasts(killApp); } // 获取运行时权限 if (grantPermissions) { grantRequestedRuntimePermissions(res.pkg, res.newUsers, grantedPermissions); } final boolean update = res.removedInfo != null && res.removedInfo.removedPackage != null; final String installerPackageName = res.installerPackageName != null ? res.installerPackageName : res.removedInfo != null ? res.removedInfo.installerPackageName : null; if (res.pkg.parentPackage != null) { synchronized (mPackages) { grantRuntimePermissionsGrantedToDisabledPrivSysPackageParentLPw(res.pkg); } } ......................... // 如果不是一个静态共享库的话发送安装成功的广播 if (res.pkg.staticSharedLibName == null) { mProcessLoggingHandler.invalidateProcessLoggingBaseApkHash(res.pkg.baseCodePath); int appId = UserHandle.getAppId(res.uid); boolean isSystem = res.pkg.applicationInfo.isSystemApp(); sendPackageAddedForNewUsers(packageName, isSystem || virtualPreload, virtualPreload /*startReceiver*/, appId, firstUsers); Bundle extras = new Bundle(1); extras.putInt(Intent.EXTRA_UID, res.uid); if (update) { extras.putBoolean(Intent.EXTRA_REPLACING, true); } // 发送ACTION_PACKAGE_ADDED广播 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras, 0 /*flags*/, null /*targetPackage*/, null /*finishedReceiver*/, updateUsers); if (installerPackageName != null) { sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras, 0 /*flags*/, installerPackageName, null /*finishedReceiver*/, updateUsers); } // 如果时升级应用,升级成功的话发送ACTION_PACKAGE_REPLACED广播 if (update) { sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras, 0 /*flags*/, null /*targetPackage*/, null /*finishedReceiver*/, updateUsers); if (installerPackageName != null) { sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras, 0 /*flags*/, installerPackageName, null /*finishedReceiver*/, updateUsers); } sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null /*package*/, null /*extras*/, 0 /*flags*/, packageName /*targetPackage*/, null /*finishedReceiver*/, updateUsers); } else if (launchedForRestore && !isSystemApp(res.pkg)) { if (DEBUG_BACKUP) { Slog.i(TAG, "Post-restore of " + packageName + " sending FIRST_LAUNCH in " + Arrays.toString(firstUsers)); } sendFirstLaunchBroadcast(packageName, installerPackage, firstUsers); } if (res.pkg.isForwardLocked() || isExternal(res.pkg)) { if (DEBUG_INSTALL) { Slog.i(TAG, "upgrading pkg " + res.pkg + " is ASEC-hosted -> AVAILABLE"); } final int[] uidArray = new int[]{res.pkg.applicationInfo.uid}; ArrayList<String> pkgList = new ArrayList<>(1); pkgList.add(packageName); sendResourcesChangedBroadcast(true, true, pkgList, uidArray, null); } } ........................ // 将安装结果放回给pm.java中的观察者 if (installObserver != null) { try { Bundle extras = extrasForInstallResult(res); installObserver.onPackageInstalled(res.name, res.returnCode, res.returnMsg, extras); } catch (RemoteException e) { Slog.i(TAG, "Observer no longer exists."); } } } |