installPackage 安装流程最终会调用 PackageManagerService 对应方法,当然是使用 binder 机制得以实现跨进程通信。

先来看看 installPackage 流程具体和各种进程如何关联调用,有个整体印象以后我们再来分析其流程。
Android 源码 installPackage 流程分析-编程知识网
起点是 ApplicationPackageManager 类 installPackage 方法。

frameworks/base/core/java/android/app/ApplicationPackageManager.java

/*package*/
final class ApplicationPackageManager extends PackageManager {......@Overridepublic void installPackage(Uri packageURI, PackageInstallObserver observer,int flags, String installerPackageName) {final VerificationParams verificationParams = new VerificationParams(null, null,null, VerificationParams.NO_UID, null);installCommon(packageURI, observer, flags, installerPackageName, verificationParams, null);}......
}
  1. 参数检查
  2. 调用 android.content.pm.IPackageManager.Stub.Proxy 类 installPackage 方法

frameworks/base/core/java/android/app/ApplicationPackageManager.java

/*package*/
final class ApplicationPackageManager extends PackageManager {......private void installCommon(Uri packageURI,PackageInstallObserver observer, int flags, String installerPackageName,VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {if (!"file".equals(packageURI.getScheme())) {throw new UnsupportedOperationException("Only file:// URIs are supported");}if (encryptionParams != null) {throw new UnsupportedOperationException("ContainerEncryptionParams not supported");}final String originPath = packageURI.getPath();try {mPM.installPackage(originPath, observer.getBinder(), flags, installerPackageName,verificationParams, null);} catch (RemoteException ignored) {}}......
}

IPackageManager.Stub.Proxy 代理类是在 ActivityThread 类方法 getPackageManager() 中获取的。

  1. 从 ServiceManager 服务关键处获取包管理 IBinder
  2. 调用 IPackageManager.Stub.asInterface() 方法返回代理对象 IPackageManager.Stub.Proxy

frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread {......public static IPackageManager getPackageManager() {if (sPackageManager != null) {//Slog.v("PackageManager", "returning cur default = " + sPackageManager);return sPackageManager;}IBinder b = ServiceManager.getService("package");//Slog.v("PackageManager", "default service binder = " + b);sPackageManager = IPackageManager.Stub.asInterface(b);//Slog.v("PackageManager", "default service = " + sPackageManager);return sPackageManager;}......
}

下面是编译 aidl 生成的 IPackageManager Java 文件,其中揭示了如何返回 IPackageManager.Stub.Proxy 代理类的逻辑。

public interface IPackageManager extends android.os.IInterface {/*** Local-side IPC implementation stub class.*/public static abstract class Stub extends android.os.Binder implements android.content.pm.IPackageManager {private static final java.lang.String DESCRIPTOR = "android.content.pm.IPackageManager";/*** Construct the stub at attach it to the interface.*/public Stub() {this.attachInterface(this, DESCRIPTOR);}/*** Cast an IBinder object into an android.content.pm.IPackageManager interface,* generating a proxy if needed.*/public static android.content.pm.IPackageManager asInterface(android.os.IBinder obj) {if ((obj == null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin != null) && (iin instanceof android.content.pm.IPackageManager))) {return ((android.content.pm.IPackageManager) iin);}return new android.content.pm.IPackageManager.Stub.Proxy(obj);}@Overridepublic android.os.IBinder asBinder() {return this;}......private static class Proxy implements android.content.pm.IPackageManager {private android.os.IBinder mRemote;Proxy(android.os.IBinder remote) {mRemote = remote;}@Overridepublic android.os.IBinder asBinder() {return mRemote;}public java.lang.String getInterfaceDescriptor() {return DESCRIPTOR;}......}......}......
}

下面来追一下 mPM,赋值是在 ApplicationPackageManager 构造函数内。

frameworks/base/core/java/android/app/ApplicationPackageManager.java

final class ApplicationPackageManager extends PackageManager {......ApplicationPackageManager(ContextImpl context,IPackageManager pm) {mContext = context;mPM = pm;}......
}

ApplicationPackageManager 对象创建又是在 ContextImpl(上下文实现类) 类 getPackageManager() 方法中。

frameworks/base/core/java/android/app/ContextImpl.java

class ContextImpl extends Context {......@Overridepublic PackageManager getPackageManager() 方法中。 {if (mPackageManager != null) {return mPackageManager;}IPackageManager pm = ActivityThread.getPackageManager();if (pm != null) {// Doesn't matter if we make more than one instance.return (mPackageManager = new ApplicationPackageManager(this, pm));}return null;}......
}

现在继续回到 ApplicationPackageManager 类 installCommon 方法,最后会调用远程 PackageManagerService 类 installPackage 方法。

  1. 权限检查,系统级或 root 用户才能安装
  2. 发送消息,消息的 obj 赋值为 InstallParams 对象(包含了安装包的必要信息)

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub {......@Overridepublic void installPackage(String originPath, IPackageInstallObserver2 observer,int installFlags, String installerPackageName, VerificationParams verificationParams,String packageAbiOverride) {installPackageAsUser(originPath, observer, installFlags, installerPackageName,verificationParams, packageAbiOverride, UserHandle.getCallingUserId());}@Overridepublic void installPackageAsUser(String originPath, IPackageInstallObserver2 observer,int installFlags, String installerPackageName, VerificationParams verificationParams,String packageAbiOverride, int userId) {mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);final int callingUid = Binder.getCallingUid();enforceCrossUserPermission(callingUid, userId, true, true, "installPackageAsUser");if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {try {if (observer != null) {observer.onPackageInstalled("", INSTALL_FAILED_USER_RESTRICTED, null, null);}} catch (RemoteException re) {}return;}if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) {installFlags |= PackageManager.INSTALL_FROM_ADB;} else {// 调用方拥有 INSTALL_PACKAGES 权限,因此我们对 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);}// 在安装时,只有系统组件可以绕过运行时权限。if ((installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0&& mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS) == PackageManager.PERMISSION_DENIED) {throw new SecurityException("You need the "+ "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission "+ "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");}verificationParams.setInstallerUid(callingUid);final File originFile = new File(originPath);final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile);final Message msg = mHandler.obtainMessage(INIT_COPY);msg.obj = new InstallParams(origin, null, observer, installFlags, installerPackageName,null, verificationParams, user, packageAbiOverride, null);mHandler.sendMessage(msg);}......
}

Handler 收到消息之后在 doHandleMessage 函数中进行处理。

  1. 如果已经绑定到了 DefaultContainerService,只需将 HandlerParams 添加到 mPendingInstalls 待处理的安装列表,并且 idx = 0,马上发送消息 MCS_BOUND 进一步处理
  2. 如果没有绑定到 DefaultContainerService,首先调用 connectToService() 进行绑定,绑定成功以后 mBound 置为 true,connectToService() 函数返回 true,然后将 HandlerParams 添加到 mPendingInstalls 列表

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub {......class PackageHandler extends Handler {private boolean mBound = false;final ArrayList<HandlerParams> mPendingInstalls =new ArrayList<HandlerParams>();private boolean connectToService() {if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +" DefaultContainerService");Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);if (mContext.bindServiceAsUser(service, mDefContainerConn,Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);mBound = true;return true;}Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);return false;}private void disconnectService() {mContainerService = null;mBound = false;Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);mContext.unbindService(mDefContainerConn);Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);}PackageHandler(Looper looper) {super(looper);}public void handleMessage(Message msg) {try {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);// 如果一个 bind 已经启动,我们实际上不需要做任何事情。稍后将处理待决的安装。if (!mBound) {// 如果只有这一个待决的安装,我们可能不得不再次绑定服务。if (!connectToService()) {Slog.e(TAG, "Failed to bind to media container service");params.serviceError();return;} else {// 一旦我们绑定到服务,第一个待决的安装请求将被处理。mPendingInstalls.add(idx, params);}} else {mPendingInstalls.add(idx, params);// 已经绑定到服务。只要确保我们启动了处理第一个请求。if (idx == 0) {mHandler.sendEmptyMessage(MCS_BOUND);}}break;}......}}}......
}

DefaultContainerService 提供检查和复制可能驻留在可移动存储器上的文件的服务。这是为了防止系统进程持有打开的文件,这些文件会导致内核在删除底层设备时杀死它。

connectToService() 进行 DefaultContainerService 服务绑定,当服务绑定成功会回调 DefaultContainerConnection 类 onServiceConnected 方法。

  1. 调用 IMediaContainerService.Stub.asInterface 获取 IMediaContainerService.Stub.Proxy 代理类
  2. 将代理类封装到 MCS_BOUND 消息发送

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub {......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");IMediaContainerService imcs =IMediaContainerService.Stub.asInterface(service);mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));}public void onServiceDisconnected(ComponentName name) {if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");}}......
}
  1. 从消息中获取 IMediaContainerService.Stub.Proxy 代理对象
  2. 从 mPendingInstalls 待决安装队列中逐个取出 HandlerParams 对象,调用其 startCopy() 方法完成拷贝
  3. mPendingInstalls 待决安装队列清空之后发送 MCS_UNBIND 消息对 DefaultContainerService 进行解绑定

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub {......class PackageHandler extends Handler {......void doHandleMessage(Message msg) {switch (msg.what) {......case MCS_BOUND: {if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");if (msg.obj != null) {mContainerService = (IMediaContainerService) msg.obj;}if (mContainerService == null) {......} else if (mPendingInstalls.size() > 0) {HandlerParams params = mPendingInstalls.get(0);if (params != null) {if (params.startCopy()) {// 我们完成了...寻找更多工作或开始 idleif (DEBUG_SD_INSTALL) Log.i(TAG,"Checking for more work or unbind...");// 从列表中删除待决安装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);// 稍微延迟后解除绑定,以避免不断地颠簸。sendMessageDelayed(ubmsg, 10000);}} else {// 队列中有更多的待决安装请求。// 只需发布 MCS_BOUND 消息来触发对下一个待决安装的处理。if (DEBUG_SD_INSTALL) Log.i(TAG,"Posting MCS_BOUND for next work");mHandler.sendEmptyMessage(MCS_BOUND);}}}} else {......}break;}......}}}......
}

startCopy() 完成的工作:

  1. 超出最大重试次数,发送 MCS_GIVE_UP 消息放弃
  2. 实际调用 handleStartCopy() 开始处理拷贝
  3. 远程调用抛出异常,发出 MCS_RECONNECT 消息重连
  4. 最后调用 handleReturnCode() 处理返回值

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub {......private abstract class HandlerParams {private static final int MAX_RETRIES = 4;/*** 尝试 startCopy() 并发生非致命错误的次数。*/private int mRetries = 0;/** 用户请求信息或安装的用户句柄。 */private final UserHandle mUser;HandlerParams(UserHandle user) {mUser = user;}UserHandle getUser() {return mUser;}final boolean startCopy() {boolean res;try {if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);// 超出最大次数,发送 MCS_GIVE_UP 放弃消息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");// 远程调用抛出异常,发出 MCS_RECONNECT 重连消息mHandler.sendEmptyMessage(MCS_RECONNECT);res = false;}handleReturnCode();return res;}final void serviceError() {if (DEBUG_INSTALL) Slog.i(TAG, "serviceError");handleServiceError();handleReturnCode();}abstract void handleStartCopy() throws RemoteException;abstract void handleServiceError();abstract void handleReturnCode();}......
}

HandlerParams 实际为 InstallParams 类型,因此会调用其 handleStartCopy() 真正开始处理拷贝。

调用远程方法以获取软件包信息并处理安装位置。如果需要,根据默认策略覆盖安装位置,然后根据安装位置创建安装参数。接下来做一些相关的包验证工作。

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub {......class InstallParams extends HandlerParams {......public void handleStartCopy() throws RemoteException {int ret = PackageManager.INSTALL_SUCCEEDED;// 设置 installFlags 安装位置对应位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) {// 无效的安装位置Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;} else {// 解析给定的包并返回最小的细节,// 这是通过 binder 机制调用远程 IMediaContainerService.Stub 类 getMinimalPackageInfo 方法完成的pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,packageAbiOverride);/** 如果我们的可用空间太少,请在放弃之前尝试释放缓存。*/if (!origin.staged && pkgLite.recommendedInstallLocation== PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {// TODO: focus freeing disk space on the target devicefinal StorageManager storage = StorageManager.from(mContext);final long lowThreshold = storage.getStorageLowBytes(Environment.getDataDirectory());final long sizeBytes = mContainerService.calculateInstalledSize(origin.resolvedPath, isForwardLocked(), packageAbiOverride);if (mInstaller.freeCache(null, 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 {// 获取建议安装位置loc = installLocationPolicy(pkgLite);if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;} else if (!onSd && !onInt) {// Override install location with flagsif (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {// 将标志设置为安装在外部媒体上installFlags |= PackageManager.INSTALL_EXTERNAL;installFlags &= ~PackageManager.INSTALL_INTERNAL;} else {// 确保在外部媒体上安装的标志未设置installFlags |= PackageManager.INSTALL_INTERNAL;installFlags &= ~PackageManager.INSTALL_EXTERNAL;}}}}// 创建安装参数final InstallArgs args = createInstallArgs(this);mArgs = args;if (ret == PackageManager.INSTALL_SUCCEEDED) {/** ADB 安装呈现为 UserHandle.USER_ALL,* 并且只能由 UserHandle.USER_OWNER 执行,* 因此请使用 UserHandle.USER_OWNER 的包验证程序。*/int userIdentifier = getUser().getIdentifier();if (userIdentifier == UserHandle.USER_ALL&& ((installFlags & PackageManager.INSTALL_FROM_ADB) != 0)) {userIdentifier = UserHandle.USER_OWNER;}/** 确定我们是否已安装任何包验证程序。使用它们对包进行验证。*/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);// 为“所有”用户安装的应用程序使用设备所有者来验证应用程序UserHandle verifierUser = getUser();if (verifierUser == UserHandle.ALL) {verifierUser = UserHandle.OWNER;}/** 如果软件包清单中列出了足够的验证者,请尝试询问它们。*/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, verifierUser);}}}final ComponentName requiredVerifierComponent = matchComponentForVerifier(mRequiredVerifierPackage, receivers);if (ret == PackageManager.INSTALL_SUCCEEDED&& mRequiredVerifierPackage != null) {/** 将意图发送到所需的验证代理,* 但仅在目标 BroadcastReceivers 运行之后才开始验证超时。*/verification.setComponent(requiredVerifierComponent);mContext.sendOrderedBroadcastAsUser(verification, verifierUser,android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,new BroadcastReceiver() {@Overridepublic 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);/** 在验证成功之前,我们不希望继续进行复制,因此将该字段设为空。*/mArgs = null;}} else {/** 没有启用包验证,因此立即启动远程调用以使用临时文件启动复制。*/ret = args.copyApk(mContainerService, true);}}mRet = ret;}......}......
}

再继续分析之前需要把 Log 搬出来。(新安装 com.cgollner.systemmonitor 这个包)

06-04 15:09:26.796   473   497 D PackageManager: args=com.android.server.pm.PackageManagerService$FileInstallArgs@d438816
06-04 15:09:26.796   473   497 D PackageManager: -----copyApk----
06-04 15:09:26.797   473   497 D PackageManager: tempDir path=/data/app/vmdl1872124892.tmp
06-04 15:09:26.843  1303  1317 D DefContainer: Copying /storage/emulated/0/TestUpdate.apk to base.apk
06-04 15:09:26.850   473   497 D PackageManager: IParcelFileDescriptorFactory file=/data/app/vmdl1872124892.tmp/base.apk
06-04 15:09:27.043   473   497 D PackageManager: libraryRoot=/data/app/vmdl1872124892.tmp/lib
06-04 15:09:28.758   473   497 I PackageManager.DexOptimizer: Running dexopt (dex2oat) on: /data/app/vmdl1872124892.tmp/base.apk pkg=com.cgollner.systemmonitor isa=arm vmSafeMode=false debuggable=false oatDir = /data/app/vmdl1872124892.tmp/oat bootComplete=true
06-04 15:09:28.811  1526  1526 I dex2oat : Starting dex2oat.
  1. mArgs 指向了 PackageManagerService 类内部类 FileInstallArgs
  2. 没走到包验证分支,直接走到了 FileInstallArgs 类 copyApk 方法,对 Apk 进行了拷贝动作
  3. 最后的 Log 表明 apk 还进行了 dex2oat 转化(dex 转为 oat)

现在可以继续分析 copyApk 方法了。

tempDir 文件夹路径为 /data/app/vmdl1872124892.tmp

apk 拷贝路径从 /storage/emulated/0/xxx.apk (TestUpdate.apk)到 /data/app/vmdl1872124892.tmp/base.apk

libraryRoot 文件夹路径为 /data/app/vmdl1872124892.tmp/lib

  1. 创建临时 temp 路径 /data/app/vmdl1872124892.tmp -> /data/app/com.cgollner.systemmonitor-1
  2. 拷贝 apk
  3. 拷贝 native lib

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub {......class FileInstallArgs extends InstallArgs {......// Example topology:// /data/app/com.example/base.apk// /data/app/com.example/split_foo.apk// /data/app/com.example/lib/arm/libfoo.so// /data/app/com.example/lib/arm64/libfoo.so// /data/app/com.example/dalvik/arm/base.apk@classes.dex......int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {......try {// 创建临时 temp 路径 final File tempDir = mInstallerService.allocateStageDirLegacy(volumeUuid);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() {@Overridepublic 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());}}};int ret = PackageManager.INSTALL_SUCCEEDED;// apk 拷贝ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);if (ret != PackageManager.INSTALL_SUCCEEDED) {Slog.e(TAG, "Failed to copy package");return ret;}final File libraryRoot = new File(codeFile, LIB_DIR_NAME);NativeLibraryHelper.Handle handle = null;try {handle = NativeLibraryHelper.Handle.create(codeFile);// native lib 拷贝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;}......}......
}

拷贝 apk 是通过调用(binder远程调用) IMediaContainerService.Stub 类 copyPackage 方法实现的,传入两个参数,第一个为 apk 的原始路径,第二个参数是一个 IParcelFileDescriptorFactory.Stub 对象,传输到 IMediaContainerService.Stub 类它会拿到对应的代理类。

调用链如下:

copyPackage -> copyPackageInner -> copyFile

frameworks/base/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java

public class DefaultContainerService extends IntentService {private static final String TAG = "DefContainer";private IMediaContainerService.Stub mBinder = new IMediaContainerService.Stub() {......@Overridepublic int copyPackage(String packagePath, IParcelFileDescriptorFactory target) {if (packagePath == null || target == null) {return PackageManager.INSTALL_FAILED_INVALID_URI;}PackageLite pkg = null;try {final File packageFile = new File(packagePath);// 解析安装包获取包信息 PackageLitepkg = PackageParser.parsePackageLite(packageFile, 0);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 {copyFile(pkg.baseCodePath, target, "base.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 {in = new FileInputStream(sourcePath);// 这里调用了 IParcelFileDescriptorFactory.Stub 类 open 方法out = new ParcelFileDescriptor.AutoCloseOutputStream(target.open(targetName, ParcelFileDescriptor.MODE_READ_WRITE));// 发生实际拷贝动作Streams.copy(in, out);} finally {IoUtils.closeQuietly(out);IoUtils.closeQuietly(in);}}    ......
}

startCopy() 最后调用了 InstallParams 类 handleReturnCode() 方法,它又实际调用了 processPendingInstall。此时 mRet = PackageManager.INSTALL_SUCCEEDED。

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub {......class InstallParams extends HandlerParams {......@Overridevoid handleReturnCode() {if (mArgs != null) {processPendingInstall(mArgs, mRet);}}......}......
}

分析前继续看一段后续 Log:

06-04 13:52:41.691  1588  1588 W dex2oat : Before Android 4.1, method int android.support.v7.internal.widget.ListViewCompat.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView
06-04 13:52:47.537  1588  1588 I dex2oat : dex2oat took 6.235s (threads: 2) arena alloc=1471KB java alloc=3MB native alloc=11MB free=2MB
06-04 13:52:47.636   446   471 W PackageManager: Unknown permission android.permission.ACCESS_SUPERUSER in package com.cgollner.systemmonitor
06-04 13:52:47.636   446   471 W PackageManager: Unknown permission com.android.vending.CHECK_LICENSE in package com.cgollner.systemmonitor
06-04 13:52:47.712   446   471 V BackupManagerService: restoreAtInstall pkg=com.cgollner.systemmonitor token=5 restoreSet=0
06-04 13:52:47.712   446   471 V BackupManagerService: Finishing install immediately
  1. 调用 FileInstallArgs 类 doPreInstall 方法执行安装前动作
  2. 调用 installPackageLI 执行实际的安装动作
  3. 调用 FileInstallArgs 类 doPostInstall 方法执行安装后动作
  4. 如果 (a) 安装成功,(b) 操作不是更新,以及 © 新包没有选择不参与备份,此时应该执行 restore。Log 指明 BackupManagerService 执行了 restore 动作。

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub {......private void processPendingInstall(final InstallArgs args, final int currentStatus) {// 异步操作排队,因为包的安装可能需要一段时间。mHandler.post(new Runnable() {public void run() {mHandler.removeCallbacks(this);// 要返回的结果对象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)安装成功,(b)操作不是更新,以及(c)新包没有选择不参与备份,// 此时应该执行 restore 。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);// 设置安装后工作请求簿记。安装后事件处理将使用并清理此事件,// 而不管是否执行了 restore 过程。令牌值 >= 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) {// 将责任移交给备份管理器。 // 它将在适当时执行 restore,// 然后将责任传递回包管理器以运行安装后的观察者回调和广播。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) {// 无法 restore,或者备份管理器不可用———直接发出安装后工作请求即可。if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);mHandler.sendMessage(msg);}}});}......
}

doPreInstall() 安装前动作很简单,如果 status != PackageManager.INSTALL_SUCCEEDED,说明前面拷贝安装包出现了问题,直接调用 cleanUp() 删除临时创建的文件夹。doPostInstall() 在安装包之后进行善后工作,和 doPreInstall() 实现一致,删除临时创建的文件夹。

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub {......class FileInstallArgs extends InstallArgs {......int doPreInstall(int status) {if (status != PackageManager.INSTALL_SUCCEEDED) {cleanUp();}return status;}......int doPostInstall(int status, int uid) {if (status != PackageManager.INSTALL_SUCCEEDED) {cleanUp();}return status;}......private boolean cleanUp() {if (codeFile == null || !codeFile.exists()) {return false;}if (codeFile.isDirectory()) {mInstaller.rmPackageDir(codeFile.getAbsolutePath());} else {codeFile.delete();}if (resourceFile != null && !FileUtils.contains(codeFile, resourceFile)) {resourceFile.delete();}return true;}        ......}......
}

installPackageLI 函数非常复杂,涉及解析安装包、验证签名、检查权限、dex2oat、重命名、应用替换(含升级)和新应用安装几个方面。

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub {......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());final boolean forwardLocked = ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);final boolean onExternal = (((installFlags & PackageManager.INSTALL_EXTERNAL) != 0)|| (args.volumeUuid != null));boolean replace = false;int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;if (args.move != null) {// 移动完整的应用程序;在新的安装位置执行初始扫描scanFlags |= SCAN_INITIAL;}// 要返回的结果对象res.returnCode = PackageManager.INSTALL_SUCCEEDED;if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile);// 检索 PackageSettings 和解析包final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY| (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)| (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0);PackageParser pp = new PackageParser();pp.setSeparateProcesses(mSeparateProcesses);pp.setDisplayMetrics(mMetrics);final PackageParser.Package pkg;try {// 解析安装包pkg = pp.parsePackage(tmpPackageFile, parseFlags);} catch (PackageParserException e) {res.setError("Failed parse during installPackageLI", e);return;}// 标记我们有一个安装时 CPU ABI 覆盖。pkg.cpuAbiOverride = args.abiOverride;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 {pp.collectCertificates(pkg, parseFlags);pp.collectManifestDigest(pkg);} catch (PackageParserException e) {res.setError("Failed collect during installPackageLI", e);return;}/* 签名验证相关:如果安装程序传递了清单摘要,请立即进行比较。 */if (args.manifestDigest != null) {if (DEBUG_INSTALL) {final String parsedManifest = pkg.manifestDigest == null ? "null": pkg.manifestDigest.toString();Slog.d(TAG, "Comparing manifests: " + args.manifestDigest.toString() + " vs. "+ parsedManifest);}if (!args.manifestDigest.equals(pkg.manifestDigest)) {res.setError(INSTALL_FAILED_PACKAGE_CHANGED, "Manifest digest changed");return;}} else if (DEBUG_INSTALL) {final String parsedManifest = pkg.manifestDigest == null? "null" : pkg.manifestDigest.toString();Slog.d(TAG, "manifestDigest was not present, but parser got: " + parsedManifest);}// Get rid of all references to package scan path via parser.pp = null;String oldCodePath = null;boolean systemApp = false;synchronized (mPackages) {// 检查是否安装已经存在的包if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {String oldName = mSettings.mRenamedPackages.get(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);}// 阻止应用选择运行时权限if (replace) {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;}}}PackageSetting ps = mSettings.mPackages.get(pkgName);if (ps != null) {if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);// 快速检查是否更新时签名正确;// 稍后我们将在扫描时再次检查这一点,// 但我们希望在切换到重新定义的权限之前尽早退出。if (shouldCheckUpgradeKeySetLP(ps, scanFlags)) {if (!checkUpgradeKeySetLP(ps, pkg)) {res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "+ pkg.packageName + " upgrade keys do not match the "+ "previously installed version");return;}} else {try {verifySignaturesLP(ps, pkg);} catch (PackageManagerException e) {res.setError(e.error, e.getMessage());return;}}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);}// 检查新扫描的包是否要定义一个已经定义的权限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);if (bp != null) {// 如果定义包使用匹配的证书进行了签名,则没有问题。// 当然,这也包括“更新相同的包”的情况。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 (!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 (!"android".equals(pkg.packageName)) {// 阻止应用程序将保护级别从任何其他类型更改为危险,因为这将允许特权升级,// 其中一个应用程序在其他应用程序的组中添加普通/签名权限,// 然后将其重新定义为危险级别,从而导致该组自动授予权限。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 && onExternal) {// 禁用SD卡上系统应用程序的更新res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,"Cannot install updates to system apps on sdcard");return;}if (args.move != null) {// 我们做了原地移动,因此dex准备就绪scanFlags |= SCAN_NO_DEX;scanFlags |= SCAN_MOVE;synchronized (mPackages) {final PackageSetting ps = mSettings.mPackages.get(pkgName);if (ps == null) {res.setError(INSTALL_FAILED_INTERNAL_ERROR,"Missing settings for moved package " + pkgName);}// 我们按原样移动了整个应用程序,因此引入了以前派生的 ABI 信息。pkg.applicationInfo.primaryCpuAbi = ps.primaryCpuAbiString;pkg.applicationInfo.secondaryCpuAbi = ps.secondaryCpuAbiString;}} else if (!forwardLocked && !pkg.applicationInfo.isExternalAsec()) {// 启用 SCAN_NO_DEX 标志以在以后跳过 dexoptscanFlags |= SCAN_NO_DEX;try {derivePackageAbi(pkg, new File(pkg.codePath), args.abiOverride,true /* extract libs */);} catch (PackageManagerException pme) {Slog.e(TAG, "Error deriving application ABI", pme);res.setError(INSTALL_FAILED_INTERNAL_ERROR, "Error deriving application ABI");return;}// 在删除旧软件包之前运行dexopt,以最大程度地减少应用程序不可用时的时间int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instruction sets */, false /* forceDex */,false /* defer */, false /* inclDependencies */,true /* boot complete */);if (result == PackageDexOptimizer.DEX_OPT_FAILED) {res.setError(INSTALL_FAILED_DEXOPT, "Dexopt failed for " + pkg.codePath);return;}}// 重命名(将临时路径命名为最终路径)if (!args.doRename(res.returnCode, pkg, oldCodePath)) {res.setError(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename");return;}startIntentFilterVerifications(args.user.getIdentifier(), replace, pkg);if (replace) {// 替换应用replacePackageLI(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,installerPackageName, volumeUuid, res);} else {// 安装新应用installNewPackageLI(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,args.user, installerPackageName, volumeUuid, res);}synchronized (mPackages) {final PackageSetting ps = mSettings.mPackages.get(pkgName);if (ps != null) {res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);}}}......
}

重命名非常简单,把临时路径命名为了最终路径:/data/app/vmdl1872124892.tmp -> /data/app/com.cgollner.systemmonitor-1

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub {......class FileInstallArgs extends InstallArgs {......boolean doRename(int status, PackageParser.Package pkg, String oldCodePath) {if (status != PackageManager.INSTALL_SUCCEEDED) {cleanUp();return false;}final File targetDir = codeFile.getParentFile();final File beforeCodeFile = codeFile;final File afterCodeFile = getNextCodePath(targetDir, pkg.packageName);if (DEBUG_INSTALL) Slog.d(TAG, "Renaming " + beforeCodeFile + " to " + afterCodeFile);try {Os.rename(beforeCodeFile.getAbsolutePath(), afterCodeFile.getAbsolutePath());} catch (ErrnoException e) {Slog.w(TAG, "Failed to rename", e);return false;}if (!SELinux.restoreconRecursive(afterCodeFile)) {Slog.w(TAG, "Failed to restorecon");return false;}// 在内部反映重命名codeFile = afterCodeFile;resourceFile = afterCodeFile;// 在扫描的细节中反映重命名pkg.codePath = afterCodeFile.getAbsolutePath();pkg.baseCodePath = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile,pkg.baseCodePath);pkg.splitCodePaths = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile,pkg.splitCodePaths);// 在应用信息中反映重命名pkg.applicationInfo.volumeUuid = pkg.volumeUuid;pkg.applicationInfo.setCodePath(pkg.codePath);pkg.applicationInfo.setBaseCodePath(pkg.baseCodePath);pkg.applicationInfo.setSplitCodePaths(pkg.splitCodePaths);pkg.applicationInfo.setResourcePath(pkg.codePath);pkg.applicationInfo.setBaseResourcePath(pkg.baseCodePath);pkg.applicationInfo.setSplitResourcePaths(pkg.splitCodePaths);return true;}        ......}......
}

再来分析 installNewPackageLI。

  1. 处理系统中已经安装同名包的情况
  2. 调用 scanPackageLI 扫描安装包
  3. 更新 Settings(包含有关动态设置的信息)
  4. 删除部分安装的应用程序。如果数据目录已经存在,则必须将其还原

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub {......private void installNewPackageLI(PackageParser.Package pkg, int parseFlags, int scanFlags,UserHandle user, String installerPackageName, String volumeUuid,PackageInstalledInfo res) {// 记住这一点,以防我们需要回滚此安装String pkgName = pkg.packageName;if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);final boolean dataDirExists = Environment.getDataUserPackageDirectory(volumeUuid, UserHandle.USER_OWNER, pkgName).exists();synchronized(mPackages) {if (mSettings.mRenamedPackages.containsKey(pkgName)) {// 已经安装了同名的包,尽管它已被重命名为较旧的名称。// 我们试图安装的软件包应该作为现有软件包的更新来安装,但没有被要求res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName+ " without first uninstalling package running as "+ mSettings.mRenamedPackages.get(pkgName));return;}if (mPackages.containsKey(pkgName)) {// 不允许通过相同名称的现有软件包进行安装。res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName+ " without first uninstalling.");return;}}try {// 扫描安装包PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanFlags,System.currentTimeMillis(), user);// 更新 Settings(包含有关动态设置的信息)updateSettingsLI(newPackage, installerPackageName, volumeUuid, null, null, res, user);// 删除部分安装的应用程序。如果数据目录已经存在,则必须将其还原if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {// 从内部结构中移除包。// 请注意,我们希望 deletePackageX 删除在 scanPackageLocked 中创建的程序包数据和缓存目录,// 除非这些目录在我们尝试安装之前就已经存在。deletePackageLI(pkgName, UserHandle.ALL, false, null, null,dataDirExists ? PackageManager.DELETE_KEEP_DATA : 0,res.removedInfo, true);}} catch (PackageManagerException e) {res.setError("Package couldn't be installed in " + pkg.codePath, e);}}......
}

扫描安装包是调用 scanPackageLI 实现的。scanPackageLI 主要工作是调用 scanPackageDirtyLI 方法完成的。

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub {......private PackageParser.Package scanPackageLI(PackageParser.Package pkg, int parseFlags,int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {boolean success = false;try {final PackageParser.Package res = scanPackageDirtyLI(pkg, parseFlags, scanFlags,currentTime, user);success = true;return res;} finally {......}}......
}

scanPackageDirtyLI 这个方法的代码太长了,不得不吐槽一下 google 开发这个函数的工程师,这个函数为何不能细分一下呢?委屈脸~这个函数完成了一系列艰难的任务,涵盖初始化包源目录和资源目录、验证签名、创建数据目录、设置 native 库路径等等。

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub {......private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags,int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {final File scanFile = new File(pkg.codePath);if (pkg.applicationInfo.getCodePath() == null ||pkg.applicationInfo.getResourcePath() == null) {// 抛出异常,资源和代码路径还没有设置。throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,"Code and resource paths haven't been set correctly");}// 设置 FLAG_SYSTEM,表示系统应用if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;} else {// 只允许系统应用被标记为核心应用。pkg.coreApp = false;}// 设置 PRIVATE_FLAG_PRIVILEGED,表示特权系统应用if ((parseFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;}if (mCustomResolverComponentName != null &&mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) {setUpCustomResolverActivity(pkg);}if (pkg.packageName.equals("android")) {synchronized (mPackages) {if (mAndroidApplication != null) {Slog.w(TAG, "*************************************************");Slog.w(TAG, "Core android package being redefined.  Skipping.");Slog.w(TAG, " file=" + scanFile);Slog.w(TAG, "*************************************************");throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,"Core android package being redefined.  Skipping.");}// 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_Holo_Dialog_Alert;mResolveActivity.exported = true;mResolveActivity.enabled = true;mResolveInfo.activityInfo = mResolveActivity;mResolveInfo.priority = 0;mResolveInfo.preferredOrder = 0;mResolveInfo.match = 0;mResolveComponentName = new ComponentName(mAndroidApplication.packageName, mResolveActivity.name);}}}if (DEBUG_PACKAGE_SCANNING) {if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)Log.d(TAG, "Scanning package " + pkg.packageName);}// 应用程序软件包已安装,跳过重复项。if (mPackages.containsKey(pkg.packageName)|| mSharedLibraries.containsKey(pkg.packageName)) {throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,"Application package " + pkg.packageName+ " already installed.  Skipping duplicate.");}// 如果只安装预存在的包,则要求扫描的APK是已知的,// 并且位于先前为其建立的路径上。我们通常会选择以前不知道的包,// 但是如果我们对这个包的安装状态有一个先验的预期,就强制执行它。// 对于新系统包,只有一个例外。当OTA包含一个新的系统包时,// 我们允许代码路径从系统位置更改为用户安装的位置。如果我们不允许此更改,// 则应用程序的任何更新的、用户安装的版本将被忽略。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);if (known != null) {if (DEBUG_PACKAGE_SCANNING) {Log.d(TAG, "Examining " + pkg.codePath+ " and requiring known paths " + known.codePathString+ " & " + known.resourcePathString);}if (!pkg.applicationInfo.getCodePath().equals(known.codePathString)|| !pkg.applicationInfo.getResourcePath().equals(known.resourcePathString)) {throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED,"Application package " + pkg.packageName+ " found at " + pkg.applicationInfo.getCodePath()+ " but expected at " + known.codePathString + "; ignoring.");}}}}// 初始化包源目录和资源目录File destCodeFile = new File(pkg.applicationInfo.getCodePath());File destResourceFile = new File(pkg.applicationInfo.getResourcePath());SharedUserSetting suid = null;PackageSetting pkgSetting = null;if (!isSystemApp(pkg)) {// 只有系统应用程序才能使用这些功能。pkg.mOriginalPackages = null;pkg.mRealPackage = null;pkg.mAdoptPermissions = null;}// writersynchronized (mPackages) {if (pkg.mSharedUserId != null) {suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, 0, true);if (suid == null) {throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,"Creating application package " + pkg.packageName+ " for shared user failed");}if (DEBUG_PACKAGE_SCANNING) {if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid=" + suid.userId+ "): packages=" + suid.packages);}}// 检查是否从原来的包名重命名。PackageSetting origPackage = null;String realName = null;if (pkg.mOriginalPackages != null) {// 这个包可能需要重命名为以前安装的名称。让我们检查一下……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) {// 确保uid在包之间是兼容的。if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {Slog.w(TAG, "Unable to migrate data from " + origPackage.name+ " to " + pkg.packageName + ": old uid "+ origPackage.sharedUser.name+ " differs from " + pkg.mSharedUserId);origPackage = null;continue;}} else {if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "+ pkg.packageName + " to old name " + origPackage.name);}break;}}}}if (mTransferedPackages.contains(pkg.packageName)) {Slog.w(TAG, "Package " + pkg.packageName+ " was transferred to another, but its .apk remains");}// 只需创建设置,不添加即可。对于已经存在的软件包,PkgSetting 已经存在,因此不必创建。pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,destResourceFile, pkg.applicationInfo.nativeLibraryRootDir,pkg.applicationInfo.primaryCpuAbi,pkg.applicationInfo.secondaryCpuAbi,pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags,user, false);if (pkgSetting == null) {throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,"Creating application package " + pkg.packageName + " failed");}if (pkgSetting.origPackage != null) {// 如果我们是第一次从原始程序包过渡,请立即确定新程序包的名称。// 我们需要在使用新名称查找软件包之后执行此操作,// 因此 getPackageLP 可以正确处理问题。pkg.setPackageName(origPackage.name);// 提交关于此的报告。String msg = "New package " + pkgSetting.realName+ " renamed to replace old package " + pkgSetting.name;reportSettingsProblem(Log.WARN, msg);// 把它记下来。mTransferedPackages.add(origPackage.name);// 不再需要保留这些。pkgSetting.origPackage = null;}if (realName != null) {// 把它记下来mTransferedPackages.add(pkg.packageName);}if (mSettings.isDisabledSystemPackageLPr(pkg.packageName)) {pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;}if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {// 检查所有共享库并映射到它们的实际文件路径。// 我们在这里只对不在系统目录上的应用程序执行此操作,// 因为它们是唯一会因此导致安装失败的应用程序。// 扫描完成后,我们将更新系统应用程序的所有库路径。updateSharedLibrariesLPw(pkg, null);}if (mFoundPolicyFile) {SELinuxMMAC.assignSeinfoValue(pkg);}pkg.applicationInfo.uid = pkgSetting.appId;pkg.mExtras = pkgSetting;if (shouldCheckUpgradeKeySetLP(pkgSetting, scanFlags)) {if (checkUpgradeKeySetLP(pkgSetting, pkg)) {// 我们刚刚确定了应用程序的签名是正确的,提交最新解析的证书。pkgSetting.signatures.mSignatures = pkg.mSignatures;} else {if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,"Package " + pkg.packageName + " upgrade keys do not match the "+ "previously installed version");} else {pkgSetting.signatures.mSignatures = pkg.mSignatures;String msg = "System package " + pkg.packageName+ " signature changed; retaining data.";reportSettingsProblem(Log.WARN, msg);}}} else {try {verifySignaturesLP(pkgSetting, pkg);// 我们刚刚确定了应用程序的签名是正确的,提交最新解析的证书。pkgSetting.signatures.mSignatures = pkg.mSignatures;} catch (PackageManagerException e) {if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 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);}}// 确认此新程序包没有与现有程序包冲突的任何内容提供程序。// 仅在尚未安装软件包的情况下才这样做,因为我们不想破坏已安装的东西。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);}}}}}if (pkg.mAdoptPermissions != null) {// 该软件包希望采用另一个软件包的权限所有权。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;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);File dataPath;if (mPlatformPackage == pkg) {// 系统软件包是特殊的。dataPath = new File(Environment.getDataDirectory(), "system");pkg.applicationInfo.dataDir = dataPath.getPath();} else {// 这是一个普通的程序包,需要创建数据目录。dataPath = Environment.getDataUserPackageDirectory(pkg.volumeUuid,UserHandle.USER_OWNER, pkg.packageName);boolean uidError = false;if (dataPath.exists()) {int currentUid = 0;try {StructStat stat = Os.stat(dataPath.getPath());currentUid = stat.st_uid;} catch (ErrnoException e) {Slog.e(TAG, "Couldn't stat path " + dataPath.getPath(), e);}// 如果数据路径的所有者不匹配,就会出现问题。if (currentUid != pkg.applicationInfo.uid) {boolean recovered = false;if (currentUid == 0) {// 目录以某种方式归根用户所有。// 请求 installd 来解决这个问题。int ret = mInstaller.fixUid(pkg.volumeUuid, pkgName,pkg.applicationInfo.uid, pkg.applicationInfo.uid);if (ret >= 0) {recovered = true;String msg = "Package " + pkg.packageName+ " unexpectedly changed to uid 0; recovered to " ++ pkg.applicationInfo.uid;reportSettingsProblem(Log.WARN, msg);}}if (!recovered && ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0|| (scanFlags&SCAN_BOOTING) != 0)) {// 如果这是系统应用程序,我们至少可以删除其当前数据,以便该应用程序仍然可以运行。int ret = removeDataDirsLI(pkg.volumeUuid, pkgName);if (ret >= 0) {// TODO: Kill the processes first// Old data gone!String prefix = (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0? "System package " : "Third party package ";String msg = prefix + pkg.packageName+ " has changed from uid: "+ currentUid + " to "+ pkg.applicationInfo.uid + "; old data erased";reportSettingsProblem(Log.WARN, msg);recovered = true;// 现在重新安装应用程序。ret = createDataDirsLI(pkg.volumeUuid, pkgName, pkg.applicationInfo.uid,pkg.applicationInfo.seinfo);if (ret == -1) {// Ack should not happen!msg = prefix + pkg.packageName+ " could not have data directory re-created after delete.";reportSettingsProblem(Log.WARN, msg);throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE, msg);}}if (!recovered) {mHasSystemUidErrors = true;}} else if (!recovered) {// If we allow this install to proceed, we will be broken.// Abort, abort!throw new PackageManagerException(INSTALL_FAILED_UID_CHANGED,"scanPackageLI");}if (!recovered) {pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"+ pkg.applicationInfo.uid + "/fs_"+ currentUid;pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;pkg.applicationInfo.nativeLibraryRootDir = pkg.applicationInfo.dataDir;String msg = "Package " + pkg.packageName+ " has mismatched uid: "+ currentUid + " on disk, "+ pkg.applicationInfo.uid + " in settings";// writersynchronized (mPackages) {mSettings.mReadMessages.append(msg);mSettings.mReadMessages.append('\n');uidError = true;if (!pkgSetting.uidError) {reportSettingsProblem(Log.ERROR, msg);}}}}pkg.applicationInfo.dataDir = dataPath.getPath();if (mShouldRestoreconData) {Slog.i(TAG, "SELinux relabeling of " + pkg.packageName + " issued.");mInstaller.restoreconData(pkg.volumeUuid, pkg.packageName,pkg.applicationInfo.seinfo, pkg.applicationInfo.uid);}} else {if (DEBUG_PACKAGE_SCANNING) {if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)Log.v(TAG, "Want this data dir: " + dataPath);}// 调用安装程序来执行实际安装int ret = createDataDirsLI(pkg.volumeUuid, pkgName, pkg.applicationInfo.uid,pkg.applicationInfo.seinfo);if (ret < 0) {// Error from installerthrow new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,"Unable to create data dirs [errorCode=" + ret + "]");}if (dataPath.exists()) {pkg.applicationInfo.dataDir = dataPath.getPath();} else {Slog.w(TAG, "Unable to create data directory: " + dataPath);pkg.applicationInfo.dataDir = null;}}pkgSetting.uidError = uidError;}final String path = scanFile.getPath();final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);if ((scanFlags & SCAN_NEW_INSTALL) == 0) {derivePackageAbi(pkg, scanFile, cpuAbiOverride, true /* extract libs */);// 一些系统应用程序仍对本地库使用目录结构,// 在这种情况下,我们可能最终无法仅基于apk结构来检测abi。 // 尝试根据目录结构检测abi。if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp() &&pkg.applicationInfo.primaryCpuAbi == null) {setBundledAppAbisAndRoots(pkg, pkgSetting);setNativeLibraryPaths(pkg);}} else {if ((scanFlags & SCAN_MOVE) != 0) {// 我们没有为此操作运行dex-opt(因为我们也移动了编译后的输出),// 但是我们已经在 PackageSetting 中包含了该软件包的软件包信息。 // 我们只使用它并基于新的代码路径派生 native 库路径。pkg.applicationInfo.primaryCpuAbi = pkgSetting.primaryCpuAbiString;pkg.applicationInfo.secondaryCpuAbi = pkgSetting.secondaryCpuAbiString;}// 再次设置 native 库路径。对于移动,路径将根据我们上面确定的ABI进行更新。// 对于非移动,路径将根据我们在编译期间确定的ABI进行更新,但该路径将取决于最终的包路径。setNativeLibraryPaths(pkg);}if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path);final int[] userIds = sUserManager.getUserIds();synchronized (mInstallLock) {// 确保所有用户数据目录已准备就绪if (!TextUtils.isEmpty(pkg.volumeUuid)) {for (int userId : userIds) {if (userId != 0) {mInstaller.createUserData(pkg.volumeUuid, pkg.packageName,UserHandle.getUid(userId, pkg.applicationInfo.uid), userId,pkg.applicationInfo.seinfo);}}}// 仅当我们有 native 库并且 native 库是32位库时,才创建本机库符号链接。// 我们不为64位库提供此符号链接。if (pkg.applicationInfo.primaryCpuAbi != null &&!VMRuntime.is64BitAbi(pkg.applicationInfo.primaryCpuAbi)) {final String nativeLibPath = pkg.applicationInfo.nativeLibraryDir;for (int userId : userIds) {if (mInstaller.linkNativeLibraryDirectory(pkg.volumeUuid, pkg.packageName,nativeLibPath, userId) < 0) {throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,"Failed linking native library dir (user=" + userId + ")");}}}}// 这是“system”程序包的特例,其中的ABI由zygote配置(和init.rc)决定。// 我们应该跟踪此ABI,以便我们可以处理在相同UID下正确运行的“正常”应用程序。if (mPlatformPackage == pkg) {pkg.applicationInfo.primaryCpuAbi = VMRuntime.getRuntime().is64Bit() ?Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0];}// 如果软件包设置中的abi-override与为安装指定的abiOverride之间不匹配。// 对此发出警告,因为我们已经在不考虑软件包设置的情况下编译了该应用程序。if ((scanFlags & SCAN_NO_DEX) == 0 && (scanFlags & SCAN_NEW_INSTALL) != 0) {if (cpuAbiOverride == null && pkgSetting.cpuAbiOverrideString != null) {Slog.w(TAG, "Ignoring persisted ABI override " + cpuAbiOverride +" for package: " + pkg.packageName);}}pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi;pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi;pkgSetting.cpuAbiOverrideString = cpuAbiOverride;// 将派生的覆盖复制回已解析的包,以便我们可以相应地更新包设置。pkg.cpuAbiOverride = cpuAbiOverride;if (DEBUG_ABI_SELECTION) {Slog.d(TAG, "Resolved nativeLibraryRoot for " + pkg.applicationInfo.packageName+ " to root=" + pkg.applicationInfo.nativeLibraryRootDir + ", isa="+ pkg.applicationInfo.nativeLibraryRootRequiresIsa);}// 将派生路径写入 PackageSettings,以便我们知道在卸载时清理什么。pkgSetting.legacyNativeLibraryPathString = pkg.applicationInfo.nativeLibraryRootDir;if (DEBUG_ABI_SELECTION) {Log.d(TAG, "Abis for package[" + pkg.packageName + "] are" +" primary=" + pkg.applicationInfo.primaryCpuAbi +" secondary=" + pkg.applicationInfo.secondaryCpuAbi);}if ((scanFlags&SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) {// We don't do this here during boot because we can do it all// at once after scanning all existing packages.//// We also do this *before* we perform dexopt on this package, so that// we can avoid redundant dexopts, and also to make sure we've got the// code and package path correct.adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages,pkg, forceDex, (scanFlags & SCAN_DEFER_DEX) != 0, true /* boot complete */);}if ((scanFlags & SCAN_NO_DEX) == 0) {int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instruction sets */,forceDex, (scanFlags & SCAN_DEFER_DEX) != 0, false /* inclDependencies */,(scanFlags & SCAN_BOOTING) == 0);if (result == PackageDexOptimizer.DEX_OPT_FAILED) {throw new PackageManagerException(INSTALL_FAILED_DEXOPT, "scanPackageLI");}}if (mFactoryTest && pkg.requestedPermissions.contains(android.Manifest.permission.FACTORY_TEST)) {pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;}ArrayList<PackageParser.Package> clientLibPkgs = null;// writersynchronized (mPackages) {if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {// 只有系统应用程序可以添加新的共享库。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;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)) {Slog.w(TAG, "Package " + pkg.packageName + " library "+ name + " already exists; skipping");}} else {Slog.w(TAG, "Package " + pkg.packageName + " declares lib "+ name + " that is not declared on system image; skipping");}}if ((scanFlags&SCAN_BOOTING) == 0) {// 需要更新作为共享库客户端的所有应用程序。clientLibPkgs = updateAllSharedLibrariesLPw(pkg);}}}}// 我们还需要 dexopt 任何依赖于这个库的应用程序。// 注意,如果这些失败,我们应该中止安装,因为安装库将导致一些应用程序被破坏。if (clientLibPkgs != null) {if ((scanFlags & SCAN_NO_DEX) == 0) {for (int i = 0; i < clientLibPkgs.size(); i++) {PackageParser.Package clientPkg = clientLibPkgs.get(i);int result = mPackageDexOptimizer.performDexOpt(clientPkg,null /* instruction sets */, forceDex,(scanFlags & SCAN_DEFER_DEX) != 0, false,(scanFlags & SCAN_BOOTING) == 0);if (result == PackageDexOptimizer.DEX_OPT_FAILED) {throw new PackageManagerException(INSTALL_FAILED_DEXOPT,"scanPackageLI failed to dexopt clientLibPkgs");}}}}// 请求 ActivityManager 终止进程(仅适用于现有软件包)if ((scanFlags & SCAN_REPLACING) != 0) {killApplication(pkg.applicationInfo.packageName,pkg.applicationInfo.uid, "replace pkg");}// 还需要杀死所有依赖该库的应用程序。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");}}// 确保我们没有添加任何虚假的键集信息KeySetManagerService ksms = mSettings.mKeySetManagerService;ksms.assertScannedPackageValid(pkg);// writersynchronized (mPackages) {// 将新设置添加到 mSettingsmSettings.insertPackageSettingLPw(pkgSetting, pkg);// 将新设置添加到 mPackagesmPackages.put(pkg.applicationInfo.packageName, pkg);// 确保我们不会意外删除其数据。final Iterator<PackageCleanItem> iter = mSettings.mPackagesToBeCleaned.iterator();while (iter.hasNext()) {PackageCleanItem item = iter.next();if (pkgName.equals(item.packageName)) {iter.remove();}}// 请注意首次安装/最后更新时间。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) {// 使用文件的时间戳。pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;} else if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {if (scanFileTime != pkgSetting.timeStamp) {// 系统映像上的包已更改;可以将此看作是一次更新。pkgSetting.lastUpdateTime = scanFileTime;}}// 将程序包的 KeySets 添加到全局 KeySetManagerServiceksms.addScannedPackageLPw(pkg);// 处理内容提供者 Providerint 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) {// We only want the first authority for a provider to possibly be// syncable, so if we already added this provider using a different// authority clear the syncable flag. We copy the provider before// changing it because the mProviders object contains a reference// to a provider that we don't want to change.// Only do this for the second authority since the resulting provider// object can be the same for all future authorities for this provider.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];}if (DEBUG_PACKAGE_SCANNING) {if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)Log.d(TAG, "Registered content provider: " + names[j]+ ", className = " + p.info.name + ", isSyncable = "+ p.info.isSyncable);}} else {PackageParser.Provider other = mProvidersByAuthority.get(names[j]);Slog.w(TAG, "Skipping provider name " + names[j] +" (in package " + pkg.applicationInfo.packageName +"): name already used by "+ ((other != null && other.getComponentName() != null)? other.getComponentName().getPackageName() : "?"));}}}if ((parseFlags&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);}// 处理 ServiceN = 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 ((parseFlags&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 ((parseFlags&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);}// 处理 ActivityN = 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 ((parseFlags&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);}// 处理 PermissionGroupN = 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 ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {if (r == null) {r = new StringBuilder(256);} else {r.append(' ');}r.append(pg.info.name);}} else {Slog.w(TAG, "Permission group " + pg.info.name + " from package "+ pg.info.packageName + " ignored: original from "+ cur.info.packageName);if ((parseFlags&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);}// 处理 PermissionN = 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;// Now that permission groups have a special meaning, we ignore permission// groups for legacy apps to prevent unexpected behavior. In particular,// permissions for one app being granted to someone just becuase they happen// to be in a group defined by another app (before this had no implications).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 permissionsif (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 nowbp.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 ((parseFlags&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 ((parseFlags&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);}// 处理 InstrumentationN = 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;// TODO: Update instrumentation.nativeLibraryDir as well ? Does it// need other information about the application, like the ABI and what not ?a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;mInstrumentation.put(a.getComponentName(), a);if ((parseFlags&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")) {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)) {throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,"scanPackageLI failed to createIdmap");}}} else if (mOverlays.containsKey(pkg.packageName) &&!pkg.packageName.equals("android")) {// This is a regular package, with one or more known overlay packages.createIdmapsForPackageLI(pkg);}}return pkg;}......
}

安装成功以后在系统中的路径如下图:

/data/app/xxx-x
Android 源码 installPackage 流程分析-编程知识网

回到 PackageManagerService 类 processPendingInstall 方法,最后会调用 BackupManagerService 类 restoreAtInstall 方法。此方法的作用:为正在安装的应用程序将需要一个恢复通道,然后需要在恢复完成时通知包管理器。

BackupManagerService 是负责备份和恢复服务功能的。

frameworks/base/services/backup/java/com/android/server/backup/BackupManagerService.java

    public void restoreAtInstall(String packageName, int token) {......boolean skip = false;long restoreSet = getAvailableRestoreToken(packageName);if (DEBUG) Slog.v(TAG, "restoreAtInstall pkg=" + packageName+ " token=" + Integer.toHexString(token)+ " restoreSet=" + Long.toHexString(restoreSet));if (restoreSet == 0) {if (MORE_DEBUG) Slog.i(TAG, "No restore set");skip = true;}// Do we have a transport to fetch data for us?IBackupTransport transport = getTransport(mCurrentTransport);if (transport == null) {if (DEBUG) Slog.w(TAG, "No transport");skip = true;}if (!mAutoRestore) {if (DEBUG) {Slog.w(TAG, "Non-restorable state: auto=" + mAutoRestore);}skip = true;}if (!skip) {......}if (skip) {// Auto-restore disabled or no way to attempt a restore; just tell the Package// Manager to proceed with the post-install handling for this package.if (DEBUG) Slog.v(TAG, "Finishing install immediately");try {mPackageManagerBinder.finishPackageInstall(token);} catch (RemoteException e) { /* can't happen */ }}}

重点关注发送 POST_INSTALL 消息。

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub {......@Overridepublic void finishPackageInstall(int token) {enforceSystemOrRoot("Only the system is allowed to finish installs");if (DEBUG_INSTALL) {Slog.v(TAG, "BM finishing package install for " + token);}final Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);mHandler.sendMessage(msg);}......
}

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub {......class PackageHandler extends Handler {......void doHandleMessage(Message msg) {switch (msg.what) {......case POST_INSTALL: {if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);PostInstallData data = mRunningInstalls.get(msg.arg1);mRunningInstalls.delete(msg.arg1);boolean deleteOld = false;if (data != null) {InstallArgs args = data.args;PackageInstalledInfo res = data.res;if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {final String packageName = res.pkg.applicationInfo.packageName;res.removedInfo.sendBroadcast(false, true, false);Bundle extras = new Bundle(1);extras.putInt(Intent.EXTRA_UID, res.uid);// 既然我们已经成功安装了包,那么在发布安装之前,如果需要,就授予运行时权限。if ((args.installFlags& PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0) {grantRequestedRuntimePermissions(res.pkg, args.user.getIdentifier(),args.installGrantPermissions);}// 确定第一次添加此包的用户和看到更新的用户。int[] firstUsers;int[] updateUsers = new int[0];if (res.origUsers == null || res.origUsers.length == 0) {firstUsers = res.newUsers;} else {firstUsers = new int[0];for (int i=0; i<res.newUsers.length; i++) {int user = res.newUsers[i];boolean isNew = true;for (int j=0; j<res.origUsers.length; j++) {if (res.origUsers[j] == user) {isNew = false;break;}}if (isNew) {int[] newFirst = new int[firstUsers.length+1];System.arraycopy(firstUsers, 0, newFirst, 0,firstUsers.length);newFirst[firstUsers.length] = user;firstUsers = newFirst;} else {int[] newUpdate = new int[updateUsers.length+1];System.arraycopy(updateUsers, 0, newUpdate, 0,updateUsers.length);newUpdate[updateUsers.length] = user;updateUsers = newUpdate;}}}// 发送包安装成功广播,感兴趣的接受者可以接收,比如 Launcher 应用sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,packageName, extras, null, null, firstUsers);final boolean update = res.removedInfo.removedPackage != null;if (update) {extras.putBoolean(Intent.EXTRA_REPLACING, true);}sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,packageName, extras, null, null, updateUsers);if (update) {// 发送包替换成功广播sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,packageName, extras, null, null, updateUsers);sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,null, null, packageName, null, updateUsers);// 在升级时,将 asec 承载的包视为可移动媒体if (res.pkg.isForwardLocked() || isExternal(res.pkg)) {if (DEBUG_INSTALL) {Slog.i(TAG, "upgrading pkg " + res.pkg+ " is ASEC-hosted -> AVAILABLE");}int[] uidArray = new int[] { res.pkg.applicationInfo.uid };ArrayList<String> pkgList = new ArrayList<String>(1);pkgList.add(packageName);sendResourcesChangedBroadcast(true, true,pkgList,uidArray, null);}}if (res.removedInfo.args != null) {// 现在安全地删除被替换包的旧资源deleteOld = true;}// 如果这个应用程序是浏览器,并且是新安装的,清除这些用户的默认浏览器状态if (firstUsers.length > 0) {// 该应用程序的性质并不取决于用户,因此我们可以在任何用户中检查其浏览器性质并进行概括。if (packageIsBrowser(packageName, firstUsers[0])) {synchronized (mPackages) {for (int userId : firstUsers) {mSettings.setDefaultBrowserPackageNameLPw(null, userId);}}}}// Log current value of "unknown sources" settingEventLog.writeEvent(EventLogTags.UNKNOWN_SOURCES_ENABLED,getUnknownSourcesSettings());}// 强制 gc 清理Runtime.getRuntime().gc();// 我们在一次gc后删除sdcard上的应用程序。if (deleteOld) {synchronized (mInstallLock) {res.removedInfo.args.doPostDeleteLI(true);}}if (args.observer != null) {try {Bundle extras = extrasForInstallResult(res);// 安装成功回调。// 这会调用到 installPackage 方法中传入的参数 PackageInstallObserver 对象args.observer.onPackageInstalled(res.name, res.returnCode,res.returnMsg, extras);} catch (RemoteException e) {Slog.i(TAG, "Observer no longer exists.");}}} else {Slog.e(TAG, "Bogus post-install token " + msg.arg1);}} break;......}}}......
}