分析通过 APK 文件安装应用的过程
PackageManagerService
应用安装过程
- 涉及文件
packages\apps\PackageInstaller\
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.javai
PackageInstaller
调用安装程序:
|
|
Intent
匹配
|
|
InstallStart.onCreate()
|
|
InstallStaging.onResume()
|
|
PackageInstallerActivity.class
onCreate()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
protected void onCreate(Bundle icicle) { super.onCreate(null); if (icicle != null) { mAllowUnknownSources = icicle.getBoolean(ALLOW_UNKNOWN_SOURCES_KEY); } // 获取 PackageManager,PackageManagerService 的代理类,它持有下面的 mIpm, // 其实就是 new ApplicationPackageManager(this, mIpm);通过 mIpm 和 PackageManagerService 通讯 mPm = getPackageManager(); // 获取 IPackageManager,这是 PackageManagerService 的 Binder 代理类 mIpm = AppGlobals.getPackageManager(); // 获取 AppOpsManager,这是 AppOpsServiec 的代理类;应用操作相关 mAppOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE); // 获取 PackageInstallerService,应用安装服务 mInstaller = mPm.getPackageInstaller(); // 获取 UserManager,这是 UserManagerService 的代理类,用于用户管理 mUserManager = (UserManager) getSystemService(Context.USER_SERVICE); final Intent intent = getIntent(); final Uri packageUri; if (PackageInstaller.ACTION_CONFIRM_PERMISSIONS.equals(intent.getAction())) { // ...... } else { mSessionId = -1; packageUri = intent.getData(); mOriginatingURI = intent.getParcelableExtra(Intent.EXTRA_ORIGINATING_URI); mReferrerURI = intent.getParcelableExtra(Intent.EXTRA_REFERRER); } // 穿戴设备 if (DeviceUtils.isWear(this)) { showDialogInner(DLG_NOT_SUPPORTED_ON_WEAR); return; } // 解析 Uri 并设置此程序包的安装程序 boolean wasSetUp = processPackageUri(packageUri); if (!wasSetUp) { return; } // load dummy layout with OK button disabled until we override this layout in // startInstallConfirm bindUi(R.layout.install_confirm, false); // 检查是否允许安装软件包并在允许的情况下启动安装。 如果不允许显示相应的对话框。 // 允许安装则调用 initiateInstall(); checkIfAllowedAndInitiateInstall(); }
获取安装包信息
processPackageUri()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
private boolean processPackageUri(final Uri packageUri) { mPackageURI = packageUri; final String scheme = packageUri.getScheme(); switch (scheme) { case SCHEME_PACKAGE: { // ...... } break; case ContentResolver.SCHEME_FILE: { File sourceFile = new File(packageUri.getPath()); PackageParser.Package parsed = PackageUtil.getPackageInfo(this, sourceFile); // ...... mPkgInfo = PackageParser.generatePackageInfo(parsed, null, PackageManager.GET_PERMISSIONS, 0, 0, null, new PackageUserState()); mAppSnippet = PackageUtil.getAppSnippet(this, mPkgInfo.applicationInfo, sourceFile); } break; } return true; } public static PackageParser.Package getPackageInfo(Context context, File sourceFile) { final PackageParser parser = new PackageParser(); parser.setCallback(new PackageParser.CallbackImpl(context.getPackageManager())); try { return parser.parsePackage(sourceFile, 0); } catch (PackageParserException e) { return null; } }
PackageParser.parsePackage()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
public Package parsePackage(File packageFile, int flags) throws PackageParserException { return parsePackage(packageFile, flags, false /* useCaches */); } public Package parsePackage(File packageFile, int flags, boolean useCaches) throws PackageParserException { // ...... long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0; if (packageFile.isDirectory()) { // parseClusterPackage() 我们在上一篇(二)中分析过 parsed = parseClusterPackage(packageFile, flags); } else { parsed = parseMonolithicPackage(packageFile, flags); } // ...... return parsed; }
initiateInstall()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
private void initiateInstall() { String pkgName = mPkgInfo.packageName; // Check if there is already a package on the device with this name // but it has been renamed to something else. // 如果设备上已有该应用包,并且曾经有更改过包名,则使用旧包名 String[] oldName = mPm.canonicalToCurrentPackageNames(new String[] { pkgName }); if (oldName != null && oldName.length > 0 && oldName[0] != null) { pkgName = oldName[0]; mPkgInfo.packageName = pkgName; mPkgInfo.applicationInfo.packageName = pkgName; } // Check if package is already installed. display confirmation dialog if replacing pkg // 如果该应用包已被安装,则显示该应用被替换 try { // This is a little convoluted because we want to get all uninstalled // apps, but this may include apps with just data, and if it is just // data we still want to count it as "installed". mAppInfo = mPm.getApplicationInfo(pkgName, PackageManager.MATCH_UNINSTALLED_PACKAGES); if ((mAppInfo.flags&ApplicationInfo.FLAG_INSTALLED) == 0) { mAppInfo = null; } } catch (NameNotFoundException e) { mAppInfo = null; } // 主要显示应用需要的权限,最终调用 startInstall() 方法通过 InstallInstalling.class 类进行安装 startInstallConfirm(); }
InstallInstalling.class
onCreate()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.install_installing); ApplicationInfo appInfo = getIntent() .getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO); mPackageURI = getIntent().getData(); if ("package".equals(mPackageURI.getScheme())) { // ...... } else { final File sourceFile = new File(mPackageURI.getPath()); // 获取安装包基本信息:应用名称和应用图标 PackageUtil.initSnippetForNewApp(this, PackageUtil.getAppSnippet(this, appInfo, sourceFile), R.id.app_snippet); if (savedInstanceState != null) { // ...... } else { // 安装应用会话参数 PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( PackageInstaller.SessionParams.MODE_FULL_INSTALL); params.installFlags = PackageManager.INSTALL_FULL_APP; params.referrerUri = getIntent().getParcelableExtra(Intent.EXTRA_REFERRER); params.originatingUri = getIntent() .getParcelableExtra(Intent.EXTRA_ORIGINATING_URI); params.originatingUid = getIntent().getIntExtra(Intent.EXTRA_ORIGINATING_UID, UID_UNKNOWN); params.installerPackageName = getIntent().getStringExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME); File file = new File(mPackageURI.getPath()); try { // 应用包基本信息 PackageParser.PackageLite pkg = PackageParser.parsePackageLite(file, 0); // 应用包名 params.setAppPackageName(pkg.packageName); // 安装位置 params.setInstallLocation(pkg.installLocation); // 安装后占用空间 params.setSize( PackageHelper.calculateInstalledSize(pkg, false, params.abiOverride)); } catch (PackageParser.PackageParserException e) { params.setSize(file.length()); } catch (IOException e) { params.setSize(file.length()); } try { // 接收安装事件并保存到 EventResultPersister;返回等待安装事件的 ID // 这里将结果传入到 launchFinishBasedOnResult() 方法进行处理 mInstallId = InstallEventReceiver .addObserver(this, EventResultPersister.GENERATE_NEW_ID, this::launchFinishBasedOnResult); } catch (EventResultPersister.OutOfIdsException e) { launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null); } try { // 创建安装会话并返回会话 Id mSessionId = getPackageManager().getPackageInstaller().createSession(params); } catch (IOException e) { launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null); } } // 显示安装进度 mSessionCallback = new InstallSessionCallback(); } } protected void onStart() { super.onStart(); // 安装会话回调,这里只显示安装进度 getPackageManager().getPackageInstaller().registerSessionCallback(mSessionCallback); } protected void onResume() { super.onResume(); // This is the first onResume in a single life of the activity if (mInstallingTask == null) { // 获取安装会话信息 PackageInstaller installer = getPackageManager().getPackageInstaller(); PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId); if (sessionInfo != null && !sessionInfo.isActive()) { // 通过 AsyncTask 异步执行 mInstallingTask = new InstallingAsyncTask(); mInstallingTask.execute(); } else { // we will receive a broadcast when the install is finished mCancelButton.setEnabled(false); setFinishOnTouchOutside(false); } } }
InstallingAsyncTask.class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
private final class InstallingAsyncTask extends AsyncTask<Void, Void, PackageInstaller.Session> { volatile boolean isDone; @Override protected PackageInstaller.Session doInBackground(Void... params) { PackageInstaller.Session session; try { // 开启安装会话 session = getPackageManager().getPackageInstaller().openSession(mSessionId); } catch (IOException e) { return null; } // 初始化安装进度 session.setStagingProgress(0); try { File file = new File(mPackageURI.getPath()); try (InputStream in = new FileInputStream(file)) { long sizeBytes = file.length(); try (OutputStream out = session .openWrite("PackageInstaller", 0, sizeBytes)) { byte[] buffer = new byte[1024 * 1024]; while (true) { int numRead = in.read(buffer); if (numRead == -1) { // 确保写入硬盘 session.fsync(out); break; } if (isCancelled()) { session.close(); break; } out.write(buffer, 0, numRead); if (sizeBytes > 0) { float fraction = ((float) numRead / (float) sizeBytes); session.addProgress(fraction); } } } } return session; } catch (IOException | SecurityException e) { Log.e(LOG_TAG, "Could not write package", e); session.close(); return null; } finally { synchronized (this) { isDone = true; notifyAll(); } } } @Override protected void onPostExecute(PackageInstaller.Session session) { if (session != null) { Intent broadcastIntent = new Intent(BROADCAST_ACTION); broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); broadcastIntent.setPackage( getPackageManager().getPermissionControllerPackageName()); broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId); PendingIntent pendingIntent = PendingIntent.getBroadcast( InstallInstalling.this, mInstallId, broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT); // 传入 IntentSender;把它看作可以传递给其它应用的 Intent 就好 session.commit(pendingIntent.getIntentSender()); mCancelButton.setEnabled(false); setFinishOnTouchOutside(false); } else { getPackageManager().getPackageInstaller().abandonSession(mSessionId); if (!isCancelled()) { launchFailure(PackageManager.INSTALL_FAILED_INVALID_APK, null); } } } }
PackageInstaller.class
createSession()
|
|
PackageInstallerService.createSession()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
public int createSession(SessionParams params, String installerPackageName, int userId) { try { return createSessionInternal(params, installerPackageName, userId); } catch (IOException e) { throw ExceptionUtils.wrap(e); } } private int createSessionInternal(SessionParams params, String installerPackageName, int userId) throws IOException { // 权限检查 final int callingUid = Binder.getCallingUid(); mPermissionManager.enforceCrossUserPermission( callingUid, userId, true, true, "createSession"); if (mPm.isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) { throw new SecurityException("User restriction prevents installing"); } // 根据调用者的 UID 修正 SessionParams.installFlags if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) { params.installFlags |= PackageManager.INSTALL_FROM_ADB; } else { // Only apps with INSTALL_PACKAGES are allowed to set an installer that is not the // caller. if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES) != PackageManager.PERMISSION_GRANTED) { mAppOps.checkPackage(callingUid, installerPackageName); } params.installFlags &= ~PackageManager.INSTALL_FROM_ADB; params.installFlags &= ~PackageManager.INSTALL_ALL_USERS; params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; if ((params.installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0 && !mPm.isCallerVerifier(callingUid)) { params.installFlags &= ~PackageManager.INSTALL_VIRTUAL_PRELOAD; } } // Only system components can circumvent runtime permissions when installing. if ((params.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"); } // 不支持的 flags;已经不允许安装在外置存储 if ((params.installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0 || (params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) { throw new IllegalArgumentException( "New installs into ASEC containers no longer supported"); } // Defensively resize giant app icons // 调整图标大小 if (params.appIcon != null) { final ActivityManager am = (ActivityManager) mContext.getSystemService( Context.ACTIVITY_SERVICE); final int iconSize = am.getLauncherLargeIconSize(); if ((params.appIcon.getWidth() > iconSize * 2) || (params.appIcon.getHeight() > iconSize * 2)) { params.appIcon = Bitmap.createScaledBitmap(params.appIcon, iconSize, iconSize, true); } } switch (params.mode) { case SessionParams.MODE_FULL_INSTALL: case SessionParams.MODE_INHERIT_EXISTING: break; default: throw new IllegalArgumentException("Invalid install mode: " + params.mode); } // If caller requested explicit location, sanity check it, otherwise // resolve the best internal or adopted location. // 根据 installFlags 确定安装位置 if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) { if (!PackageHelper.fitsOnInternal(mContext, params)) { throw new IOException("No suitable internal storage available"); } } else if ((params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) { if (!PackageHelper.fitsOnExternal(mContext, params)) { throw new IOException("No suitable external storage available"); } } else if ((params.installFlags & PackageManager.INSTALL_FORCE_VOLUME_UUID) != 0) { // For now, installs to adopted media are treated as internal from // an install flag point-of-view. params.setInstallFlagsInternal(); } else { // 默认不指定安装位置 // For now, installs to adopted media are treated as internal from // an install flag point-of-view. params.setInstallFlagsInternal(); // Resolve best location for install, based on combination of // requested install flags, delta size, and manifest settings. final long ident = Binder.clearCallingIdentity(); try { params.volumeUuid = PackageHelper.resolveInstallVolume(mContext, params); } finally { Binder.restoreCallingIdentity(ident); } } final int sessionId; final PackageInstallerSession session; synchronized (mSessions) { // Sanity check that installer isn't going crazy // 确保调用者没有提交过多的会话 final int activeCount = getSessionCount(mSessions, callingUid); if (activeCount >= MAX_ACTIVE_SESSIONS) { throw new IllegalStateException( "Too many active sessions for UID " + callingUid); } final int historicalCount = mHistoricalSessionsByInstaller.get(callingUid); if (historicalCount >= MAX_HISTORICAL_SESSIONS) { throw new IllegalStateException( "Too many historical sessions for UID " + callingUid); } // 生成当前新建会话的 Id sessionId = allocateSessionIdLocked(); } final long createdMillis = System.currentTimeMillis(); // We're staging to exactly one location File stageDir = null; String stageCid = null; if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) { // 默认安装到内置存储 final boolean isInstant = (params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0; // /data 下面的临时目录,用于存放 apk 文件 stageDir = buildStageDir(params.volumeUuid, sessionId, isInstant); } else { stageCid = buildExternalStageCid(sessionId); } // 新建会话对象 session = new PackageInstallerSession(mInternalCallback, mContext, mPm, mInstallThread.getLooper(), sessionId, userId, installerPackageName, callingUid, params, createdMillis, stageDir, stageCid, false, false); synchronized (mSessions) { mSessions.put(sessionId, session); } // 回调,通知会话创建 mCallbacks.notifySessionCreated(session.sessionId, session.userId); // 异步写入到 SessionFile 进行记录 writeSessionsAsync(); return sessionId; }
openSession()
|
|
PackageInstallerService.openSession()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
public IPackageInstallerSession openSession(int sessionId) { try { return openSessionInternal(sessionId); } catch (IOException e) { throw ExceptionUtils.wrap(e); } } private IPackageInstallerSession openSessionInternal(int sessionId) throws IOException { synchronized (mSessions) { final PackageInstallerSession session = mSessions.get(sessionId); if (session == null || !isCallingUidOwner(session)) { throw new SecurityException("Caller has no access to session " + sessionId); } session.open(); // 返回的是 IPackageInstallerSession;其实就是该会话的代理 return session; } }
PackageInstallerSession.open()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
public void open() throws IOException { // 激活当前会话 if (mActiveCount.getAndIncrement() == 0) { mCallback.onSessionActiveChanged(this, true); } boolean wasPrepared; synchronized (mLock) { wasPrepared = mPrepared; if (!mPrepared) { if (stageDir != null) { // 准备临时目录 prepareStageDir(stageDir); } else { throw new IllegalArgumentException("stageDir must be set"); } mPrepared = true; } } if (!wasPrepared) { // 回调,通知会话准备完毕 mCallback.onSessionPrepared(this); } }
Session.commit()
|
|
PackageInstallerSession.commit()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) { Preconditions.checkNotNull(statusReceiver); final boolean wasSealed; synchronized (mLock) { // 检查调用者是否是该会话的所有者 assertCallerIsOwnerOrRootLocked(); // 检查会话是否准备好或被销毁 assertPreparedAndNotDestroyedLocked("commit"); final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter( mContext, statusReceiver, sessionId, isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId); mRemoteObserver = adapter.getBinder(); // forTransfer=false if (forTransfer) { mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, null); if (mInstallerUid == mOriginalInstallerUid) { throw new IllegalArgumentException("Session has not been transferred"); } } else { // 检查安装用户是否改变 if (mInstallerUid != mOriginalInstallerUid) { throw new IllegalArgumentException("Session has been transferred"); } } // mSealed=false wasSealed = mSealed; if (!mSealed) { try { // 锁定会话以防止修改并验证其内容。 sealAndValidateLocked(); } catch (IOException e) { throw new IllegalArgumentException(e); } catch (PackageManagerException e) { // Do now throw an exception here to stay compatible with O and older destroyInternal(); dispatchSessionFinished(e.error, ExceptionUtils.getCompleteMessage(e), null); return; } } // Client staging is fully done at this point // 客户端部分已全部完成 mClientProgress = 1f; computeProgressLocked(true); // This ongoing commit should keep session active, even though client // will probably close their end. // 活动会话计数器增加 mActiveCount.incrementAndGet(); mCommitted = true; // 调用 commitLocked() 方法 mHandler.obtainMessage(MSG_COMMIT).sendToTarget(); } if (!wasSealed) { // Persist the fact that we've sealed ourselves to prevent // mutations of any hard links we create. We do this without holding // the session lock, since otherwise it's a lock inversion. mCallback.onSessionSealedBlocking(this); } }
PackageInstallerSession.commitLocked()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
private void commitLocked() throws PackageManagerException { // ...... 一些检查工作 // Inherit any packages and native libraries from existing install that // haven't been overridden. if (params.mode == SessionParams.MODE_INHERIT_EXISTING) { // ...... 安装包继承已经安装的应用,进行一些库文件拷贝 } // TODO: surface more granular state from dexopt mInternalProgress = 0.5f; computeProgressLocked(true); // Unpack native libraries // 解压本地库文件 extractNativeLibraries(mResolvedStageDir, params.abiOverride, mayInheritNativeLibs()); // We've reached point of no return; call into PMS to install the stage. // Regardless of success or failure we always destroy session. // 观察者,监听安装结果 final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() { @Override public void onUserActionRequired(Intent intent) { throw new IllegalStateException(); } @Override public void onPackageInstalled(String basePackageName, int returnCode, String msg, Bundle extras) { destroyInternal(); dispatchSessionFinished(returnCode, msg, extras); } }; final UserHandle user; if ((params.installFlags & PackageManager.INSTALL_ALL_USERS) != 0) { user = UserHandle.ALL; } else { user = new UserHandle(userId); } mRelinquished = true; // 提交给 PackageManagerService 进行下一步安装工作 mPm.installStage(mPackageName, stageDir, localObserver, params, mInstallerPackageName, mInstallerUid, user, mSigningDetails); }
PackageManagerService.class
installStage()
|
|
PackageHandler.handleMessage()
|
|
HandlerParams.startCopy()
|
|
handleStartCopy()
获取安装包信息和安装位置,根据默认策略改变安装位置并生成安装参数
|
|
IMediaContainerService.getMinimalPackageInfo()
远程调用
DefaultContainerService.mBinder.getMinimalPackageInfo()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
public PackageInfoLite getMinimalPackageInfo(String packagePath, int flags, String abiOverride) { final Context context = DefaultContainerService.this; PackageInfoLite ret = new PackageInfoLite(); if (packagePath == null) { ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK; return ret; } final File packageFile = new File(packagePath); final PackageParser.PackageLite pkg; final long sizeBytes; try { // 解析得到 PackageInfoLite pkg = PackageParser.parsePackageLite(packageFile, 0); // 计算安装所需空间 sizeBytes = PackageHelper.calculateInstalledSize(pkg, abiOverride); } catch (PackageParserException | IOException e) { if (!packageFile.exists()) { ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_URI; } else { ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK; } return ret; } final int recommendedInstallLocation; final long token = Binder.clearCallingIdentity(); try { // 确定建议安装位置 recommendedInstallLocation = PackageHelper.resolveInstallLocation(context, pkg.packageName, pkg.installLocation, sizeBytes, flags); } finally { Binder.restoreCallingIdentity(token); } ret.packageName = pkg.packageName; ret.splitNames = pkg.splitNames; ret.versionCode = pkg.versionCode; ret.versionCodeMajor = pkg.versionCodeMajor; ret.baseRevisionCode = pkg.baseRevisionCode; ret.splitRevisionCodes = pkg.splitRevisionCodes; ret.installLocation = pkg.installLocation; ret.verifiers = pkg.verifiers; ret.recommendedInstallLocation = recommendedInstallLocation; ret.multiArch = pkg.multiArch; return ret; }
PackageHelper.resolveInstallLocation()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
public static int resolveInstallLocation(Context context, String packageName, int installLocation, long sizeBytes, int installFlags) { final SessionParams params = new SessionParams(SessionParams.MODE_INVALID); params.appPackageName = packageName; params.installLocation = installLocation; params.sizeBytes = sizeBytes; params.installFlags = installFlags; try { return resolveInstallLocation(context, params); } catch (IOException e) { throw new IllegalStateException(e); } } public static int resolveInstallLocation(Context context, SessionParams params) throws IOException { ApplicationInfo existingInfo = null; try { // 根据包名获取应用信息;如果以前有安装过该应用否则为空 existingInfo = context.getPackageManager().getApplicationInfo(params.appPackageName, PackageManager.MATCH_ANY_USER); } catch (NameNotFoundException ignored) { } final int prefer; final boolean checkBoth; boolean ephemeral = false; if ((params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) { // 及时应用 prefer = RECOMMEND_INSTALL_INTERNAL; ephemeral = true; checkBoth = false; } else if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) { // 要求安装在内置存储 prefer = RECOMMEND_INSTALL_INTERNAL; checkBoth = false; } else if ((params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) { // 要求安装在内置存储 prefer = RECOMMEND_INSTALL_EXTERNAL; checkBoth = false; } else if (params.installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) { // 要求只能安装在内置存储 prefer = RECOMMEND_INSTALL_INTERNAL; checkBoth = false; } else if (params.installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) { // 要求优先安装在外置存储 prefer = RECOMMEND_INSTALL_EXTERNAL; checkBoth = true; } else if (params.installLocation == PackageInfo.INSTALL_LOCATION_AUTO) { // 没有指定具体位置,由系统自己决定 // When app is already installed, prefer same medium // 如果安装过该应用,用上次安装的位置 if (existingInfo != null) { // TODO: distinguish if this is external ASEC if ((existingInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) { prefer = RECOMMEND_INSTALL_EXTERNAL; } else { prefer = RECOMMEND_INSTALL_INTERNAL; } } else { // 默认安装到内置存储 prefer = RECOMMEND_INSTALL_INTERNAL; } checkBoth = true; } else { // 默认安装到内置存储 prefer = RECOMMEND_INSTALL_INTERNAL; checkBoth = false; } // 判断是否优先安装到内置存储,没有唯一指定安装位置则:checkBoth=true boolean fitsOnInternal = false; if (checkBoth || prefer == RECOMMEND_INSTALL_INTERNAL) { fitsOnInternal = fitsOnInternal(context, params); } // 判断是否优先安装到位置存储 boolean fitsOnExternal = false; if (checkBoth || prefer == RECOMMEND_INSTALL_EXTERNAL) { fitsOnExternal = fitsOnExternal(context, params); } if (prefer == RECOMMEND_INSTALL_INTERNAL) { // The ephemeral case will either fit and return EPHEMERAL, or will not fit // and will fall through to return INSUFFICIENT_STORAGE if (fitsOnInternal) { // 决定安装到内置存储 return (ephemeral) ? PackageHelper.RECOMMEND_INSTALL_EPHEMERAL : PackageHelper.RECOMMEND_INSTALL_INTERNAL; } } else if (prefer == RECOMMEND_INSTALL_EXTERNAL) { if (fitsOnExternal) { // 决定安装到外置存储 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL; } } if (checkBoth) { if (fitsOnInternal) { return PackageHelper.RECOMMEND_INSTALL_INTERNAL; } else if (fitsOnExternal) { return PackageHelper.RECOMMEND_INSTALL_EXTERNAL; } } // 找不到适合安装的位置 return PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE; }
installLocationPolicy()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
private int installLocationPolicy(PackageInfoLite pkgLite) { String packageName = pkgLite.packageName; int installLocation = pkgLite.installLocation; boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0; // reader synchronized (mPackages) { // Currently installed package which the new package is attempting to replace or // null if no such package is installed. // 根据包名获取应用信息,如果之前没有安装过为空 PackageParser.Package installedPkg = mPackages.get(packageName); // Package which currently owns the data which the new package will own if installed. // If an app is unstalled while keeping data (e.g., adb uninstall -k), installedPkg // will be null whereas dataOwnerPkg will contain information about the package // which was uninstalled while keeping its data. PackageParser.Package dataOwnerPkg = installedPkg; if (dataOwnerPkg == null) { PackageSetting ps = mSettings.mPackages.get(packageName); if (ps != null) { // 之前有安装过但是已经卸载却保留了数据 dataOwnerPkg = ps.pkg; } } if (dataOwnerPkg != null) { // If installed, the package will get access to data left on the device by its // predecessor. As a security measure, this is permited only if this is not a // version downgrade or if the predecessor package is marked as debuggable and // a downgrade is explicitly requested. // // On debuggable platform builds, downgrades are permitted even for // non-debuggable packages to make testing easier. Debuggable platform builds do // not offer security guarantees and thus it's OK to disable some security // mechanisms to make debugging/testing easier on those builds. However, even on // debuggable builds downgrades of packages are permitted only if requested via // installFlags. This is because we aim to keep the behavior of debuggable // platform builds as close as possible to the behavior of non-debuggable // platform builds. // 是否是降级安装,安装比已有版本低的版本 final boolean downgradeRequested = (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0; // 当前是否是调试模式 final boolean packageDebuggable = (dataOwnerPkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; // 判断是否允许降级安装 final boolean downgradePermitted = (downgradeRequested) && ((Build.IS_DEBUGGABLE) || (packageDebuggable)); if (!downgradePermitted) { try { // 检查是否是降级安装 checkDowngrade(dataOwnerPkg, pkgLite); } catch (PackageManagerException e) { Slog.w(TAG, "Downgrade detected: " + e.getMessage()); return PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE; } } } if (installedPkg != null) { // 应用已经安装过 if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { // Check for updated system application. if ((installedPkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { // 升级系统应用 if (onSd) { // 允许安装在外置存储 return PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION; } return PackageHelper.RECOMMEND_INSTALL_INTERNAL; } else { if (onSd) { // Install flag overrides everything. // 要求安装到外置存储 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL; } // If current upgrade specifies particular preference if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) { // 要求只能安装在内置存储 // Application explicitly specified internal. return PackageHelper.RECOMMEND_INSTALL_INTERNAL; } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) { // 优先安装到外置存储 // App explictly prefers external. Let policy decide } else { // 未指定安装位置 // Prefer previous location if (isExternal(installedPkg)) { // 使用上次应用安装的位置 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL; } // 默认安装到内置存储 return PackageHelper.RECOMMEND_INSTALL_INTERNAL; } } } else { // Invalid install. Return error code return PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS; } } } // All the special cases have been taken care of. // Return result based on recommended install location. if (onSd) { return PackageHelper.RECOMMEND_INSTALL_EXTERNAL; } return pkgLite.recommendedInstallLocation; }
createInstallArgs()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
private InstallArgs createInstallArgs(InstallParams params) { if (params.move != null) { // 移动应用 return new MoveInstallArgs(params); } else { // 正常安装 return new FileInstallArgs(params); } } int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException { try { return doCopyApk(imcs, temp); } finally { } } private int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException { // 在我们当前分析的安装流程中 staged=true 因为在 PackageInstallerSession 中已经进行了拷贝 if (origin.staged) { codeFile = origin.file; resourceFile = origin.file; return PackageManager.INSTALL_SUCCEEDED; } // ...... 其它方式安装的拷贝动作 }
handleReturnCode()
|
|
installPackageTracedLI()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
private void installPackageTracedLI(InstallArgs args, PackageInstalledInfo res) { try { installPackageLI(args, res); } finally { } } private void installPackageLI(InstallArgs args, PackageInstalledInfo res) { // ...... 变量初始化 // Result object to be returned // 要返回的结果对象 res.setReturnCode(PackageManager.INSTALL_SUCCEEDED); res.installerPackageName = installerPackageName; // Sanity check // 完整性检查,及时应用只能安装在内置存储 if (instantApp && (forwardLocked || onExternal)) { res.setReturnCode(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID); return; } // Retrieve PackageSettings and parse package @ParseFlags final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY | PackageParser.PARSE_ENFORCE_CODE | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0) | (forceSdk ? PackageParser.PARSE_FORCE_SDK : 0); PackageParser pp = new PackageParser(); pp.setSeparateProcesses(mSeparateProcesses); pp.setDisplayMetrics(mMetrics); pp.setCallback(mPackageParserCallback); final PackageParser.Package pkg; try { // 解析 apk 文件得到 PackageParser.Package 对象 pkg = pp.parsePackage(tmpPackageFile, parseFlags); DexMetadataHelper.validatePackageDexMetadata(pkg); } catch (PackageParserException e) { res.setError("Failed parse during installPackageLI", e); return; } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } // Instant apps have several additional install-time checks. // 检查是否支持及时应用 if (instantApp) { if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.O) { res.setError(INSTALL_FAILED_INSTANT_APP_INVALID, "Instant app package must target at least O"); return; } if (pkg.applicationInfo.targetSandboxVersion != 2) { res.setError(INSTALL_FAILED_INSTANT_APP_INVALID, "Instant app package must use targetSandboxVersion 2"); return; } if (pkg.mSharedUserId != null) { res.setError(INSTALL_FAILED_INSTANT_APP_INVALID, "Instant app package may not declare a sharedUserId"); return; } } if (pkg.applicationInfo.isStaticSharedLibrary()) { // Static shared libraries have synthetic package names renameStaticSharedLibraryPackage(pkg); // No static shared libs on external storage if (onExternal) { // 共享库不允许安装在外置存储 res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION, "Packages declaring static-shared libs cannot be updated"); return; } } // If we are installing a clustered package add results for the children if (pkg.childPackages != null) { // 处理子包 synchronized (mPackages) { final int childCount = pkg.childPackages.size(); for (int i = 0; i < childCount; i++) { PackageParser.Package childPkg = pkg.childPackages.get(i); PackageInstalledInfo childRes = new PackageInstalledInfo(); childRes.setReturnCode(PackageManager.INSTALL_SUCCEEDED); childRes.pkg = childPkg; childRes.name = childPkg.packageName; PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName); if (childPs != null) { childRes.origUsers = childPs.queryInstalledUsers( sUserManager.getUserIds(), true); } if ((mPackages.containsKey(childPkg.packageName))) { childRes.removedInfo = new PackageRemovedInfo(this); childRes.removedInfo.removedPackage = childPkg.packageName; childRes.removedInfo.installerPackageName = childPs.installerPackageName; } if (res.addedChildPackages == null) { res.addedChildPackages = new ArrayMap<>(); } res.addedChildPackages.put(childPkg.packageName, childRes); } } } // If package doesn't declare API override, mark that we have an install // time CPU ABI override. if (TextUtils.isEmpty(pkg.cpuAbiOverride)) { 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 { // either use what we've been given or parse directly from the APK if (args.signingDetails != PackageParser.SigningDetails.UNKNOWN) { pkg.setSigningDetails(args.signingDetails); } else { PackageParser.collectCertificates(pkg, false /* skipVerify */); } } catch (PackageParserException e) { res.setError("Failed collect during installPackageLI", e); return; } // 检查签名版本 if (instantApp && pkg.mSigningDetails.signatureSchemeVersion < SignatureSchemeVersion.SIGNING_BLOCK_V2) { res.setError(INSTALL_FAILED_INSTANT_APP_INVALID, "Instant app package must be signed with APK Signature Scheme v2 or greater"); return; } // Get rid of all references to package scan path via parser. // ...... 检查是否要替换现有包 pp = null; String oldCodePath = null; boolean systemApp = false; synchronized (mPackages) { // Check if installing already existing package } if (args.move != null) { // We did an in-place move, so dex is ready to roll // 移动应用 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); } // We moved the entire application as-is, so bring over the // previously derived ABI information. pkg.applicationInfo.primaryCpuAbi = ps.primaryCpuAbiString; pkg.applicationInfo.secondaryCpuAbi = ps.secondaryCpuAbiString; } } else if (!forwardLocked && !pkg.applicationInfo.isExternalAsec()) { // Enable SCAN_NO_DEX flag to skip dexopt at a later stage scanFlags |= SCAN_NO_DEX; try { String abiOverride = (TextUtils.isEmpty(pkg.cpuAbiOverride) ? args.abiOverride : pkg.cpuAbiOverride); final boolean extractNativeLibs = !pkg.isLibrary(); derivePackageAbi(pkg, abiOverride, extractNativeLibs); } catch (PackageManagerException pme) { res.setError(INSTALL_FAILED_INTERNAL_ERROR, "Error deriving application ABI"); return; } // Shared libraries for the package need to be updated. synchronized (mPackages) { try { updateSharedLibrariesLPr(pkg, null); } catch (PackageManagerException e) { } } } // 重命名安装包路径名,使用拷贝后的 if (!args.doRename(res.returnCode, pkg, oldCodePath)) { res.setError(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename"); return; } if (PackageManagerServiceUtils.isApkVerityEnabled()) { // 安装验证相关 } if (!instantApp) { startIntentFilterVerifications(args.user.getIdentifier(), replace, pkg); } else { } try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags, "installPackageLI")) { if (replace) { if (pkg.applicationInfo.isStaticSharedLibrary()) { // Static libs have a synthetic package name containing the version // and cannot be updated as an update would get a new package name, // unless this is the exact same version code which is useful for // development. PackageParser.Package existingPkg = mPackages.get(pkg.packageName); if (existingPkg != null && existingPkg.getLongVersionCode() != pkg.getLongVersionCode()) { res.setError(INSTALL_FAILED_DUPLICATE_PACKAGE, "Packages declaring " + "static-shared libs cannot be updated"); return; } } // 用新的应用信息替换旧的 replacePackageLIF(pkg, parseFlags, scanFlags, args.user, installerPackageName, res, args.installReason); } else { // 将新应用信息加入到 PackageManagerService installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES, args.user, installerPackageName, volumeUuid, res, args.installReason); } } // Prepare the application profiles for the new code paths. // This needs to be done before invoking dexopt so that any install-time profile // can be used for optimizations. // 为新代码路径准备应用程序配置文件。 这需要在调用 dexopt 之前完成,以便任何安装时配置文件都可以用于优化。 mArtManagerService.prepareAppProfiles(pkg, resolveUserIds(args.user.getIdentifier())); // ...... dexopt 相关操作 BackgroundDexOptService.notifyPackageChanged(pkg.packageName); synchronized (mPackages) { final PackageSetting ps = mSettings.mPackages.get(pkgName); if (ps != null) { res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true); ps.setUpdateAvailable(false /*updateAvailable*/); } final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; for (int i = 0; i < childCount; i++) { PackageParser.Package childPkg = pkg.childPackages.get(i); PackageInstalledInfo childRes = res.addedChildPackages.get(childPkg.packageName); PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName); if (childPs != null) { childRes.newUsers = childPs.queryInstalledUsers( sUserManager.getUserIds(), true); } } if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { updateSequenceNumberLP(ps, res.newUsers); updateInstantAppInstallerLocked(pkgName); } } }