赞
踩
installPackage 安装流程最终会调用 PackageManagerService 对应方法,当然是使用 binder 机制得以实现跨进程通信。
先来看看 installPackage 流程具体和各种进程如何关联调用,有个整体印象以后我们再来分析其流程。
起点是 ApplicationPackageManager 类 installPackage 方法。
frameworks/base/core/java/android/app/ApplicationPackageManager.java
/*package*/
final class ApplicationPackageManager extends PackageManager {
......
@Override
public 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);
}
......
}
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() 中获取的。
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); } @Override public 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; } @Override public 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 { ...... @Override public 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 方法。
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
public class PackageManagerService extends IPackageManager.Stub { ...... @Override public void installPackage(String originPath, IPackageInstallObserver2 observer, int installFlags, String installerPackageName, VerificationParams verificationParams, String packageAbiOverride) { installPackageAsUser(originPath, observer, installFlags, installerPackageName, verificationParams, packageAbiOverride, UserHandle.getCallingUserId()); } @Override public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer, int installFlags, String installerPackageName, VerificationParams verificationParams, String packageAbiOverride, int userId) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null); 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 函数中进行处理。
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 方法。
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"); } } ...... }
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()) { // 我们完成了...寻找更多工作或开始 idle if (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() 完成的工作:
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 device final StorageManager storage = StorageManager.from(mContext); final long lowThreshold = storage.getStorageLowBytes( Environment.getDataDirectory()); final long sizeBytes = mContainerService.calculateInstalledSize( origin.resolvedPath, isForwardLocked(), packageAbiOverride); if (mInstaller.freeCache(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 flags if (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() { @Override public void onReceive(Context context, Intent intent) { final Message msg = mHandler .obtainMessage(CHECK_PENDING_VERIFICATION); msg.arg1 = verificationId; mHandler.sendMessageDelayed(msg, getVerificationTimeout()); } }, null, 0, null, null); /* * 在验证成功之前,我们不希望继续进行复制,因此将该字段设为空。 */ 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.
现在可以继续分析 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
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() { @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()); } } }; 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() { ...... @Override public 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); // 解析安装包获取包信息 PackageLite pkg = 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 {
......
@Override
void 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
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 标志以在以后跳过 dexopt scanFlags |= 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。
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; } // writer synchronized (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"; // writer synchronized (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 installer throw 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; // writer synchronized (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); // writer synchronized (mPackages) { // 将新设置添加到 mSettings mSettings.insertPackageSettingLPw(pkgSetting, pkg); // 将新设置添加到 mPackages mPackages.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 添加到全局 KeySetManagerService ksms.addScannedPackageLPw(pkg); // 处理内容提供者 Provider int N = pkg.providers.size(); StringBuilder r = null; int i; for (i=0; i<N; i++) { PackageParser.Provider p = pkg.providers.get(i); p.info.processName = fixProcessName(pkg.applicationInfo.processName, p.info.processName, pkg.applicationInfo.uid); mProviders.addProvider(p); p.syncable = p.info.isSyncable; if (p.info.authority != null) { String names[] = p.info.authority.split(";"); p.info.authority = null; for (int j = 0; j < names.length; j++) { if (j == 1 && p.syncable) { // 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); } // 处理 Service N = pkg.services.size(); r = null; for (i=0; i<N; i++) { PackageParser.Service s = pkg.services.get(i); s.info.processName = fixProcessName(pkg.applicationInfo.processName, s.info.processName, pkg.applicationInfo.uid); mServices.addService(s); if ((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); } // 处理 Activity N = pkg.activities.size(); r = null; for (i=0; i<N; i++) { PackageParser.Activity a = pkg.activities.get(i); a.info.processName = fixProcessName(pkg.applicationInfo.processName, a.info.processName, pkg.applicationInfo.uid); mActivities.addActivity(a, "activity"); if ((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); } // 处理 PermissionGroup N = pkg.permissionGroups.size(); r = null; for (i=0; i<N; i++) { PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i); PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name); if (cur == null) { mPermissionGroups.put(pg.info.name, pg); if ((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); } // 处理 Permission N = pkg.permissions.size(); r = null; for (i=0; i<N; i++) { PackageParser.Permission p = pkg.permissions.get(i); // Assume by default that we did not install this permission into the system. p.info.flags &= ~PermissionInfo.FLAG_INSTALLED; // 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 permissions if (bp != null && !Objects.equals(bp.sourcePackage, p.info.packageName)) { final boolean currentOwnerIsSystem = (bp.perm != null && isSystemApp(bp.perm.owner)); if (isSystemApp(p.owner)) { if (bp.type == BasePermission.TYPE_BUILTIN && bp.perm == null) { // It's a built-in permission and no owner, take ownership now bp.packageSetting = pkgSetting; bp.perm = p; bp.uid = pkg.applicationInfo.uid; bp.sourcePackage = p.info.packageName; p.info.flags |= PermissionInfo.FLAG_INSTALLED; } else if (!currentOwnerIsSystem) { String msg = "New decl " + p.owner + " of permission " + p.info.name + " is system; overriding " + bp.sourcePackage; reportSettingsProblem(Log.WARN, msg); bp = null; } } } if (bp == null) { bp = new BasePermission(p.info.name, p.info.packageName, BasePermission.TYPE_NORMAL); permissionMap.put(p.info.name, bp); } if (bp.perm == null) { if (bp.sourcePackage == null || bp.sourcePackage.equals(p.info.packageName)) { BasePermission tree = findPermissionTreeLP(p.info.name); if (tree == null || tree.sourcePackage.equals(p.info.packageName)) { bp.packageSetting = pkgSetting; bp.perm = p; bp.uid = pkg.applicationInfo.uid; bp.sourcePackage = p.info.packageName; p.info.flags |= PermissionInfo.FLAG_INSTALLED; if ((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); } // 处理 Instrumentation N = pkg.instrumentation.size(); r = null; for (i=0; i<N; i++) { PackageParser.Instrumentation a = pkg.instrumentation.get(i); a.info.packageName = pkg.applicationInfo.packageName; a.info.sourceDir = pkg.applicationInfo.sourceDir; a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir; a.info.splitSourceDirs = pkg.applicationInfo.splitSourceDirs; a.info.splitPublicSourceDirs = pkg.applicationInfo.splitPublicSourceDirs; a.info.dataDir = pkg.applicationInfo.dataDir; // 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
回到 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 {
......
@Override
public 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" setting EventLog.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; ...... } } } ...... }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。