赞
踩
APK的安装方式主要有以下几种:
frameworks\base\packages\PackageInstaller\路径下
其中InstallStart为PackageInstaller入口
- <activity android:name=".InstallStart"
- android:theme="@android:style/Theme.Translucent.NoTitleBar"
- android:exported="true"
- android:excludeFromRecents="true">
- <intent-filter android:priority="1">
- <action android:name="android.intent.action.VIEW" />
- <action android:name="android.intent.action.INSTALL_PACKAGE" />
- <category android:name="android.intent.category.DEFAULT" />
- <data android:scheme="content" />
- <data android:mimeType="application/vnd.android.package-archive" />
- </intent-filter>
- <intent-filter android:priority="1">
- <action android:name="android.intent.action.INSTALL_PACKAGE" />
- <category android:name="android.intent.category.DEFAULT" />
- <data android:scheme="package" />
- <data android:scheme="content" />
- </intent-filter>
- <intent-filter android:priority="1">
- <action android:name="android.content.pm.action.CONFIRM_INSTALL" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
安装apk的代码主要是调用InstallStart
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.setDataAndType(Uri.parse("file://" + path),"application/vnd.android.package-archive");
- context.startActivity(intent);
PackageInstaller是系统内置的应用程序,用于安装和卸载应用。当我们调用PackageInstaller来安装应用时会跳转到InstallStart,并调用它的onCreate方法:
- String callingPackage = getCallingPackage();
-
- final boolean isSessionInstall =
- PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction());
-
-
-
- if (isSessionInstall) {
- nextActivity.setClass(this, PackageInstallerActivity.class);
- } else {
- Uri packageUri = intent.getData();
-
- if (packageUri != null && packageUri.getScheme().equals(
- ContentResolver.SCHEME_CONTENT)) {
- // [IMPORTANT] This path is deprecated, but should still work. Only necessary
- // features should be added.
-
- // Copy file to prevent it from being changed underneath this process
- //调用这里,启动InstallStaging
- nextActivity.setClass(this, InstallStaging.class);
- } else if (packageUri != null && packageUri.getScheme().equals(
- PackageInstallerActivity.SCHEME_PACKAGE)) {
-
- nextActivity.setClass(this, PackageInstallerActivity.class);
- } else {
- Intent result = new Intent();
- result.putExtra(Intent.EXTRA_INSTALL_RESULT,
- PackageManager.INSTALL_FAILED_INVALID_URI);
- setResult(RESULT_FIRST_USER, result);
-
- nextActivity = null;
- }
- }
-
- if (nextActivity != null) {
- startActivity(nextActivity);
- }
- finish();
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
frameworks\base\packages\PackageInstaller\src\com\android\packageinstaller\InstallStaging.java InstallStaging的onResume方法
- @Override
- protected void onResume() {
- super.onResume();
-
- // This is the first onResume in a single life of the activity
- if (mStagingTask == null) {
- // File does not exist, or became invalid
- if (mStagedFile == null) {
- // Create file delayed to be able to show error
- try {
- 如果File类型的mStagedFile 为null,则创建mStagedFile ,mStagedFile用于存储临时数据
- mStagedFile = TemporaryFileManager.getStagedFile(this);
- } catch (IOException e) {
- showError();
- return;
- }
- }
- 启动StagingAsyncTask
- mStagingTask = new StagingAsyncTask();
- mStagingTask.execute(getIntent().getData());
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
StagingAsyncTask是InstallStaging的内部类,
- private final class StagingAsyncTask extends AsyncTask<Uri, Void, Boolean> {
- @Override
- protected Boolean doInBackground(Uri... params) {
- if (params == null || params.length <= 0) {
- return false;
- }
- Uri packageUri = params[0];
- try (InputStream in = getContentResolver().openInputStream(packageUri)) {
- // Despite the comments in ContentResolver#openInputStream the returned stream can
- // be null.
- if (in == null) {
- return false;
- }
-
- try (OutputStream out = new FileOutputStream(mStagedFile)) {
- byte[] buffer = new byte[1024 * 1024];
- int bytesRead;
- while ((bytesRead = in.read(buffer)) >= 0) {
- // Be nice and respond to a cancellation
- if (isCancelled()) {
- return false;
- }
- out.write(buffer, 0, bytesRead);
- }
- }
- } catch (IOException | SecurityException | IllegalStateException e) {
- Log.w(LOG_TAG, "Error staging apk from content URI", e);
- return false;
- }
- return true;
- }
-
- @Override
- protected void onPostExecute(Boolean success) {
- if (success) {
- // Now start the installation again from a file
- Intent installIntent = new Intent(getIntent());
- installIntent.setClass(InstallStaging.this, DeleteStagedFileOnResult.class);
- installIntent.setData(Uri.fromFile(mStagedFile));
-
- if (installIntent.getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
- installIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
- }
-
- installIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
- startActivity(installIntent);
-
- InstallStaging.this.finish();
- } else {
- showError();
- }
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
doInBackground方法中将packageUri(content协议的Uri)的内容写入到mStagedFile中,如果写入成功,onPostExecute方法中会跳转到DeleteStagedFileOnResult中,
frameworks\base\packages\PackageInstaller\src\com\android\packageinstaller\DeleteStagedFileOnResult.java
DeleteStagedFileOnResult启动PackageInstallerActivity实现apk的安装
- public class DeleteStagedFileOnResult extends Activity {
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- if (savedInstanceState == null) {
- Intent installIntent = new Intent(getIntent());
- installIntent.setClass(this, PackageInstallerActivity.class);
-
- installIntent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
- startActivityForResult(installIntent, 0);
- }
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- File sourceFile = new File(getIntent().getData().getPath());
- sourceFile.delete();
-
- setResult(resultCode, data);
- finish();
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
DeleteStagedFileOnResult将mStagedFile传入PackageInstallerActivity,InstallStaging主要将content协议的Uri转换为File协议,然后跳转到PackageInstallerActivity,这样就可以像此前版本(Android7.0之前)一样启动安装流程了。
frameworks\base\packages\PackageInstaller\src\com\android\packageinstaller\PackageInstallerActivity.java
- @Override
- protected void onCreate(Bundle icicle) {
- getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
-
- super.onCreate(null);
-
- if (icicle != null) {
- mAllowUnknownSources = icicle.getBoolean(ALLOW_UNKNOWN_SOURCES_KEY);
- }
- //初始话安装所需要的各种对象
- mPm = getPackageManager();
- mIpm = AppGlobals.getPackageManager();
- mAppOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
- mInstaller = mPm.getPackageInstaller();
- mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
-
- final Intent intent = getIntent();
-
- mCallingPackage = intent.getStringExtra(EXTRA_CALLING_PACKAGE);
- mSourceInfo = intent.getParcelableExtra(EXTRA_ORIGINAL_SOURCE_INFO);
- mOriginatingUid = intent.getIntExtra(Intent.EXTRA_ORIGINATING_UID,
- PackageInstaller.SessionParams.UID_UNKNOWN);
- mOriginatingPackage = (mOriginatingUid != PackageInstaller.SessionParams.UID_UNKNOWN)
- ? getPackageNameForUid(mOriginatingUid) : null;
-
-
- final Uri packageUri;
-
- if (PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction())) {
- final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1);
- final PackageInstaller.SessionInfo info = mInstaller.getSessionInfo(sessionId);
- if (info == null || !info.sealed || info.resolvedBaseCodePath == null) {
- Log.w(TAG, "Session " + mSessionId + " in funky state; ignoring");
- finish();
- return;
- }
-
- mSessionId = sessionId;
- packageUri = Uri.fromFile(new File(info.resolvedBaseCodePath));
- mOriginatingURI = null;
- mReferrerURI = null;
- } else {
- mSessionId = -1;
- packageUri = intent.getData();
- mOriginatingURI = intent.getParcelableExtra(Intent.EXTRA_ORIGINATING_URI);
- mReferrerURI = intent.getParcelableExtra(Intent.EXTRA_REFERRER);
- }
-
- // if there's nothing to do, quietly slip into the ether
- if (packageUri == null) {
- Log.w(TAG, "Unspecified source");
- setPmResult(PackageManager.INSTALL_FAILED_INVALID_URI);
- finish();
- return;
- }
- if (DeviceUtils.isWear(this)) {
- showDialogInner(DLG_NOT_SUPPORTED_ON_WEAR);
- return;
- }
- boolean wasSetUp = processPackageUri(packageUri);
- if (!wasSetUp) {
- return;
- }
- // load dummy layout with OK button disabled until we override this layout in
- // startInstallConfirm
- bindUi();
- //判断是否是未知来源的应用,如果开启允许安装未知来源选项则直接初始化安装
- checkIfAllowedAndInitiateInstall();
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
类名 | 描述 |
---|---|
PackageManager | 用于向应用程序进程提供一些功能,最终的功能是由PMS来实现的 |
IPackageManager | 一个AIDL的接口,用于和PMS进行进程间通信 |
AppOpsManager | 用于权限动态检测,在Android4.3中被引入 |
PackageInstaller | 提供安装、升级和删除应用程序功能 |
UserManager | 用于多用户管理 |
bindUi();
- /**
- * Check if it is allowed to install the package and initiate install if allowed. If not allowed
- * show the appropriate dialog.
- */
- private void checkIfAllowedAndInitiateInstall() {
- // Check for install apps user restriction first.
- final int installAppsRestrictionSource = mUserManager.getUserRestrictionSource(
- UserManager.DISALLOW_INSTALL_APPS, Process.myUserHandle());
- if ((installAppsRestrictionSource & UserManager.RESTRICTION_SOURCE_SYSTEM) != 0) {
- showDialogInner(DLG_INSTALL_APPS_RESTRICTED_FOR_USER);
- return;
- } else if (installAppsRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
- startActivity(new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS));
- finish();
- return;
- }
- //判断如果允许安装未知来源或者根据Intent判断得出该APK不是未知来源
- if (mAllowUnknownSources || !isInstallRequestFromUnknownSource(getIntent())) {
- initiateInstall();
- } else {
- // 如果管理员限制来自未知源的安装, 就弹出提示Dialog或者跳转到设置界面
- // Check for unknown sources restrictions.
- final int unknownSourcesRestrictionSource = mUserManager.getUserRestrictionSource(
- UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, Process.myUserHandle());
- final int unknownSourcesGlobalRestrictionSource = mUserManager.getUserRestrictionSource(
- UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, Process.myUserHandle());
- final int systemRestriction = UserManager.RESTRICTION_SOURCE_SYSTEM
- & (unknownSourcesRestrictionSource | unknownSourcesGlobalRestrictionSource);
- if (systemRestriction != 0) {
- showDialogInner(DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER);
- } else if (unknownSourcesRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
- startAdminSupportDetailsActivity(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
- } else if (unknownSourcesGlobalRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
- startAdminSupportDetailsActivity(
- UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY);
- } else {
- handleUnknownSources();
- }
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
bindUi()方法主要完成对安装界面的加载
- private void bindUi() {
- mAlert.setIcon(mAppSnippet.icon);
- mAlert.setTitle(mAppSnippet.label);
- mAlert.setView(R.layout.install_content_view);
- mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install),
- (ignored, ignored2) -> {
- if (mOk.isEnabled()) {
- if (mSessionId != -1) {
- mInstaller.setPermissionsResult(mSessionId, true);
- finish();
- } else {
- 完成app的安装
- startInstall();
- }
- }
- }, null);
- mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
- (ignored, ignored2) -> {
- // Cancel and finish
- setResult(RESULT_CANCELED);
- if (mSessionId != -1) {
- mInstaller.setPermissionsResult(mSessionId, false);
- }
- finish();
- }, null);
- setupAlert();
-
- mOk = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
- mOk.setEnabled(false);
-
- if (!mOk.isInTouchMode()) {
- mAlert.getButton(DialogInterface.BUTTON_NEGATIVE).requestFocus();
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- 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;
- }
-
- startInstallConfirm();
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- private void startInstallConfirm() {
- View viewToEnable;
-
- if (mAppInfo != null) {
- viewToEnable = (mAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
- ? requireViewById(R.id.install_confirm_question_update_system)
- : requireViewById(R.id.install_confirm_question_update);
- } else {
- // This is a new application with no permissions.
- viewToEnable = requireViewById(R.id.install_confirm_question);
- }
-
- viewToEnable.setVisibility(View.VISIBLE);
-
- mEnableOk = true;
- mOk.setEnabled(true);
- mOk.setFilterTouchesWhenObscured(true);
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
具体加载的布局文件再frameworks\base\packages\PackageInstaller\res\layout\下
现在来总结下PackageInstaller初始化的过程:
startInstall();方法调用 InstallInstalling 来安装apk
startInstall方法用于跳转到InstallInstalling这个Activity,并关闭掉当前的PackageInstallerActivity。InstallInstalling主要用于向包管理器发送包的信息并处理包管理的回调。
- private void startInstall() {
- // Start subactivity to actually install the application
- Intent newIntent = new Intent();
- newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
- mPkgInfo.applicationInfo);
- newIntent.setData(mPackageURI);
- newIntent.setClass(this, InstallInstalling.class);
- String installerPackageName = getIntent().getStringExtra(
- Intent.EXTRA_INSTALLER_PACKAGE_NAME);
- if (mOriginatingURI != null) {
- newIntent.putExtra(Intent.EXTRA_ORIGINATING_URI, mOriginatingURI);
- }
- if (mReferrerURI != null) {
- newIntent.putExtra(Intent.EXTRA_REFERRER, mReferrerURI);
- }
- if (mOriginatingUid != PackageInstaller.SessionParams.UID_UNKNOWN) {
- newIntent.putExtra(Intent.EXTRA_ORIGINATING_UID, mOriginatingUid);
- }
- if (installerPackageName != null) {
- newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME,
- installerPackageName);
- }
- if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
- newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
- }
- newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
- if(localLOGV) Log.i(TAG, "downloaded app uri="+mPackageURI);
- startActivity(newIntent);
- finish();
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
frameworks\base\packages\PackageInstaller\src\com\android\packageinstaller\InstallInstalling.java
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- ApplicationInfo appInfo = getIntent()
- .getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
- mPackageURI = getIntent().getData();
-
- if ("package".equals(mPackageURI.getScheme())) {
- try {
- getPackageManager().installExistingPackage(appInfo.packageName);
- launchSuccess();
- } catch (PackageManager.NameNotFoundException e) {
- launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
- }
- } else {
- //根据mPackageURI创建一个对应的File
- final File sourceFile = new File(mPackageURI.getPath());
- PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
-
- mAlert.setIcon(as.icon);
- mAlert.setTitle(as.label);
- mAlert.setView(R.layout.install_content_view);
- mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
- (ignored, ignored2) -> {
- if (mInstallingTask != null) {
- mInstallingTask.cancel(true);
- }
-
- if (mSessionId > 0) {
- getPackageManager().getPackageInstaller().abandonSession(mSessionId);
- mSessionId = 0;
- }
-
- setResult(RESULT_CANCELED);
- finish();
- }, null);
- setupAlert();
- requireViewById(R.id.installing).setVisibility(View.VISIBLE);
- //如果savedInstanceState不为null,获取此前保存的mSessionId和mInstallId
- if (savedInstanceState != null) {
- mSessionId = savedInstanceState.getInt(SESSION_ID);
- mInstallId = savedInstanceState.getInt(INSTALL_ID);
-
- // Reregister for result; might instantly call back if result was delivered while
- // activity was destroyed
- try {
- //向InstallEventReceiver注册一个观察者
- InstallEventReceiver.addObserver(this, mInstallId,
- this::launchFinishBasedOnResult);
- } catch (EventResultPersister.OutOfIdsException e) {
- // Does not happen
- }
- } else {
- PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
- PackageInstaller.SessionParams.MODE_FULL_INSTALL);
- params.setInstallAsInstantApp(false);
- params.setReferrerUri(getIntent().getParcelableExtra(Intent.EXTRA_REFERRER));
- params.setOriginatingUri(getIntent()
- .getParcelableExtra(Intent.EXTRA_ORIGINATING_URI));
- params.setOriginatingUid(getIntent().getIntExtra(Intent.EXTRA_ORIGINATING_UID,
- UID_UNKNOWN));
- params.setInstallerPackageName(getIntent().getStringExtra(
- Intent.EXTRA_INSTALLER_PACKAGE_NAME));
- params.setInstallReason(PackageManager.INSTALL_REASON_USER);
-
- 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) {
- Log.e(LOG_TAG, "Cannot parse package " + file + ". Assuming defaults.");
- Log.e(LOG_TAG,
- "Cannot calculate installed size " + file + ". Try only apk size.");
- params.setSize(file.length());
- } catch (IOException e) {
- Log.e(LOG_TAG,
- "Cannot calculate installed size " + file + ". Try only apk size.");
- params.setSize(file.length());
- }
-
- try {
- mInstallId = InstallEventReceiver
- .addObserver(this, EventResultPersister.GENERATE_NEW_ID,
- this::launchFinishBasedOnResult);
- } catch (EventResultPersister.OutOfIdsException e) {
- launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
- }
-
- try {
- mSessionId = getPackageManager().getPackageInstaller().createSession(params);
- } catch (IOException e) {
- launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
- }
- }
-
- mCancelButton = mAlert.getButton(DialogInterface.BUTTON_NEGATIVE);
-
- mSessionCallback = new InstallSessionCallback();
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
onCreate方法中会分别对package和content协议的Uri进行处理,我们来看content协议的Uri处理部分。注释1处如果savedInstanceState不为null,获取此前保存的mSessionId和mInstallId,其中mSessionId是安装包的会话id,mInstallId是等待的安装事件id。注释2处根据mInstallId向InstallEventReceiver注册一个观察者,launchFinishBasedOnResult会接收到安装事件的回调,无论安装成功或者失败都会关闭当前的Activity(InstallInstalling)。如果savedInstanceState为null,代码的逻辑也是类似的,注释3处创建SessionParams,它用来代表安装会话的参数,注释4、5处根据mPackageUri对包(APK)进行轻量级的解析,并将解析的参数赋值给SessionParams。注释6处和注释2处类似向InstallEventReceiver注册一个观察者返回一个新的mInstallId,其中InstallEventReceiver继承自BroadcastReceiver,用于接收安装事件并回调给EventResultPersister。 注释7处PackageInstaller的createSession方法内部会通过IPackageInstaller与PackageInstallerService进行进程间通信,最终调用的是PackageInstallerService的createSession方法来创建并返回mSessionId。
- @Override
- 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()) {
- mInstallingTask = new InstallingAsyncTask();
- mInstallingTask.execute();
- } else {
- // we will receive a broadcast when the install is finished
- mCancelButton.setEnabled(false);
- setFinishOnTouchOutside(false);
- }
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
根据mSessionId得到SessionInfo,SessionInfo代表安装会话的详细信息。如果sessionInfo不为Null并且不是活动的,就创建并执行InstallingAsyncTask。InstallingAsyncTask的doInBackground方法中会根据包(APK)的Uri,将APK的信息通过IO流的形式写入到PackageInstaller.Session中
onResune 启动InstallingAsyncTask
- 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(getPackageName());
- broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId);
-
- PendingIntent pendingIntent = PendingIntent.getBroadcast(
- InstallInstalling.this,
- mInstallId,
- broadcastIntent,
- PendingIntent.FLAG_UPDATE_CURRENT);
-
- session.commit(pendingIntent.getIntentSender());
- mCancelButton.setEnabled(false);
- setFinishOnTouchOutside(false);
- } else {
- getPackageManager().getPackageInstaller().abandonSession(mSessionId);
-
- if (!isCancelled()) {
- launchFailure(PackageManager.INSTALL_FAILED_INVALID_APK, null);
- }
- }
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
创建了一个PendingIntent,并将该PendingIntent的IntentSender通过PackageInstaller.Session的commit方法发送出去
frameworks\base\core\java\android\content\pm\PackageInstaller.java
- protected final IPackageInstallerSession mSession;
-
- public void commit(@NonNull IntentSender statusReceiver) {
- try {
- mSession.commit(statusReceiver, false);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
mSession的类型为IPackageInstallerSession,这说明要通过IPackageInstallerSession来进行进程间的通信,最终会调用PackageInstallerSession的commit方法
frameworks\base\services\core\java\com\android\server\pm\PackageInstallerSession.java
- @Override
- public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
- if (hasParentSessionId()) {
- throw new IllegalStateException(
- "Session " + sessionId + " is a child of multi-package session "
- + mParentSessionId + " and may not be committed directly.");
- }
-
- if (!markAsSealed(statusReceiver, forTransfer)) {
- return;
- }
- if (isMultiPackage()) {
- final SparseIntArray remainingSessions = mChildSessionIds.clone();
- final IntentSender childIntentSender =
- new ChildStatusIntentReceiver(remainingSessions, statusReceiver)
- .getIntentSender();
- boolean sealFailed = false;
- for (int i = mChildSessionIds.size() - 1; i >= 0; --i) {
- final int childSessionId = mChildSessionIds.keyAt(i);
- // seal all children, regardless if any of them fail; we'll throw/return
- // as appropriate once all children have been processed
- if (!mSessionProvider.getSession(childSessionId)
- .markAsSealed(childIntentSender, forTransfer)) {
- sealFailed = true;
- }
- }
- if (sealFailed) {
- return;
- }
- }
- dispatchStreamValidateAndCommit();
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- private void dispatchStreamValidateAndCommit() {
- mHandler.obtainMessage(MSG_STREAM_VALIDATE_AND_COMMIT).sendToTarget();
- }
-
- private void handleStreamValidateAndCommit() {
- PackageManagerException unrecoverableFailure = null;
- // This will track whether the session and any children were validated and are ready to
- // progress to the next phase of install
- boolean allSessionsReady = false;
- try {
- allSessionsReady = streamValidateAndCommit();
- } catch (PackageManagerException e) {
- unrecoverableFailure = e;
- }
-
- if (isMultiPackage()) {
- int childCount = mChildSessionIds.size();
-
- // This will contain all child sessions that do not encounter an unrecoverable failure
- ArrayList<PackageInstallerSession> nonFailingSessions = new ArrayList<>(childCount);
-
- for (int i = childCount - 1; i >= 0; --i) {
- final int childSessionId = mChildSessionIds.keyAt(i);
- // commit all children, regardless if any of them fail; we'll throw/return
- // as appropriate once all children have been processed
- try {
- PackageInstallerSession session = mSessionProvider.getSession(childSessionId);
- allSessionsReady &= session.streamValidateAndCommit();
- nonFailingSessions.add(session);
- } catch (PackageManagerException e) {
- allSessionsReady = false;
- if (unrecoverableFailure == null) {
- unrecoverableFailure = e;
- }
- }
- }
- // If we encountered any unrecoverable failures, destroy all other sessions including
- // the parent
- if (unrecoverableFailure != null) {
- // {@link #streamValidateAndCommit()} calls
- // {@link #onSessionVerificationFailure(PackageManagerException)}, but we don't
- // expect it to ever do so for parent sessions. Call that on this parent to clean
- // it up and notify listeners of the error.
- onSessionVerificationFailure(unrecoverableFailure);
- // fail other child sessions that did not already fail
- for (int i = nonFailingSessions.size() - 1; i >= 0; --i) {
- PackageInstallerSession session = nonFailingSessions.get(i);
- session.onSessionVerificationFailure(unrecoverableFailure);
- }
- }
- }
-
- if (!allSessionsReady) {
- return;
- }
-
- mHandler.obtainMessage(MSG_INSTALL).sendToTarget();
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- private void handleInstall() {
- if (isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked()) {
- DevicePolicyEventLogger
- .createEvent(DevicePolicyEnums.INSTALL_PACKAGE)
- .setAdmin(mInstallSource.installerPackageName)
- .write();
- }
- if (params.isStaged) {
- mStagingManager.commitSession(this);
- destroyInternal();
- dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "Session staged", null);
- return;
- }
-
- if (isApexInstallation()) {
- destroyInternal();
- dispatchSessionFinished(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
- "APEX packages can only be installed using staged sessions.", null);
- return;
- }
-
- // For a multiPackage session, read the child sessions
- // outside of the lock, because reading the child
- // sessions with the lock held could lead to deadlock
- // (b/123391593).
- List<PackageInstallerSession> childSessions = getChildSessionsNotLocked();
-
- try {
- synchronized (mLock) {
- installNonStagedLocked(childSessions);
- }
- } catch (PackageManagerException e) {
- final String completeMsg = ExceptionUtils.getCompleteMessage(e);
- Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
- destroyInternal();
- dispatchSessionFinished(e.error, completeMsg, null);
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- @GuardedBy("mLock")
- private void installNonStagedLocked(List<PackageInstallerSession> childSessions)
- throws PackageManagerException {
- final PackageManagerService.ActiveInstallSession installingSession =
- makeSessionActiveLocked();
- if (installingSession == null) {
- return;
- }
- if (isMultiPackage()) {
- List<PackageManagerService.ActiveInstallSession> installingChildSessions =
- new ArrayList<>(childSessions.size());
- boolean success = true;
- PackageManagerException failure = null;
- for (int i = 0; i < childSessions.size(); ++i) {
- final PackageInstallerSession session = childSessions.get(i);
- try {
- final PackageManagerService.ActiveInstallSession installingChildSession =
- session.makeSessionActiveLocked();
- if (installingChildSession != null) {
- installingChildSessions.add(installingChildSession);
- }
- } catch (PackageManagerException e) {
- failure = e;
- success = false;
- }
- }
- if (!success) {
- sendOnPackageInstalled(mContext, mRemoteStatusReceiver, sessionId,
- isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId, null,
- failure.error, failure.getLocalizedMessage(), null);
- return;
- }
- mPm.installStage(installingChildSessions);
- } else {
- mPm.installStage(installingSession);
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
调用 mPm的installStage方法
private final PackageManagerService mPm;
frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java
- void installStage(ActiveInstallSession activeInstallSession) {
- if (DEBUG_INSTANT) {
- if ((activeInstallSession.getSessionParams().installFlags
- & PackageManager.INSTALL_INSTANT_APP) != 0) {
- Slog.d(TAG, "Ephemeral install of " + activeInstallSession.getPackageName());
- }
- }
- final Message msg = mHandler.obtainMessage(INIT_COPY);
- final InstallParams params = new InstallParams(activeInstallSession);
- params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
- msg.obj = params;
-
- Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStage",
- System.identityHashCode(msg.obj));
- Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
- System.identityHashCode(msg.obj));
-
- mHandler.sendMessage(msg);
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
创建InstallParams,它对应于包的安装数据
- void doHandleMessage(Message msg) {
- switch (msg.what) {
- case INIT_COPY: {
- HandlerParams params = (HandlerParams) msg.obj;
- if (params != null) {
- if (DEBUG_INSTALL) Slog.i(TAG, "init_copy: " + params);
- Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
- System.identityHashCode(params));
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
- params.startCopy();
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
- break;
- }
params.startCopy();
params是HandlerParams类
- final void startCopy() {
- if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
- handleStartCopy();
- handleReturnCode();
- }
- abstract void handleStartCopy();
- abstract void handleReturnCode();
具体实现在 InstallParams里 是PackageManagerService的内部类
class InstallParams extends HandlerParams {
- public void handleStartCopy() {
- int ret = PackageManager.INSTALL_SUCCEEDED;
-
- // If we're already staged, we've firmly committed to an install location
- if (origin.staged) {
- if (origin.file != null) {
- installFlags |= PackageManager.INSTALL_INTERNAL;
- } else {
- throw new IllegalStateException("Invalid stage location");
- }
- }
- //确定APK的安装位置。 onInt:内部存储即Data分区,ephemeral:安装到临时存储(Instant Apps安装)
- final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;
- final boolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
- PackageInfoLite pkgLite = null;
-
- //获取APK的少量的信息
- pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,
- origin.resolvedPath, installFlags, packageAbiOverride);
-
- if (DEBUG_INSTANT && ephemeral) {
- Slog.v(TAG, "pkgLite for install: " + pkgLite);
- }
-
- /*
- * If we have too little free space, try to free cache
- * before giving up.
- */
- if (!origin.staged && pkgLite.recommendedInstallLocation
- == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
- // TODO: focus freeing disk space on the target device
- final StorageManager storage = StorageManager.from(mContext);
- final long lowThreshold = storage.getStorageLowBytes(
- Environment.getDataDirectory());
-
- final long sizeBytes = PackageManagerServiceUtils.calculateInstalledSize(
- origin.resolvedPath, packageAbiOverride);
- if (sizeBytes >= 0) {
- try {
- mInstaller.freeCache(null, sizeBytes + lowThreshold, 0, 0);
- pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,
- origin.resolvedPath, installFlags, packageAbiOverride);
- } catch (InstallerException e) {
- Slog.w(TAG, "Failed to free cache", e);
- }
- }
-
- /*
- * The cache free must have deleted the file we downloaded to install.
- *
- * TODO: fix the "freeCache" call to not delete the file we care about.
- */
- if (pkgLite.recommendedInstallLocation
- == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
- pkgLite.recommendedInstallLocation
- = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
- }
- }
-
-
- if (ret == PackageManager.INSTALL_SUCCEEDED) {
- //判断安装的位置
- int loc = pkgLite.recommendedInstallLocation;
- if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
- ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
- } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
- ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
- } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
- ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
- ret = PackageManager.INSTALL_FAILED_INVALID_APK;
- } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
- ret = PackageManager.INSTALL_FAILED_INVALID_URI;
- } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
- ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
- } else {
- // Override with defaults if needed.
- loc = installLocationPolicy(pkgLite);
- if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
- ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
- } else if (loc == PackageHelper.RECOMMEND_FAILED_WRONG_INSTALLED_VERSION) {
- ret = PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION;
- } else if (!onInt) {
- // Override install location with flags
- if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
- // Set the flag to install on external media.
- installFlags &= ~PackageManager.INSTALL_INTERNAL;
- } else if (loc == PackageHelper.RECOMMEND_INSTALL_EPHEMERAL) {
- if (DEBUG_INSTANT) {
- Slog.v(TAG, "...setting INSTALL_EPHEMERAL install flag");
- }
- installFlags |= PackageManager.INSTALL_INSTANT_APP;
- installFlags &= ~PackageManager.INSTALL_INTERNAL;
- } else {
- // Make sure the flag for installing on external
- // media is unset
- installFlags |= PackageManager.INSTALL_INTERNAL;
- }
- }
- }
- }
- //根据InstallParams创建InstallArgs对象
- final InstallArgs args = createInstallArgs(this);
- mVerificationCompleted = true;
- mIntegrityVerificationCompleted = true;
- mEnableRollbackCompleted = true;
- mArgs = args;
-
- if (ret == PackageManager.INSTALL_SUCCEEDED) {
- final int verificationId = mPendingVerificationToken++;
-
- // Perform package verification (unless we are simply moving the package).
- if (!origin.existing) {
- PackageVerificationState verificationState =
- new PackageVerificationState(this);
- mPendingVerification.append(verificationId, verificationState);
-
- sendIntegrityVerificationRequest(verificationId, pkgLite, verificationState);
- ret = sendPackageVerificationRequest(
- verificationId, pkgLite, verificationState);
-
- // If both verifications are skipped, we should remove the state.
- if (verificationState.areAllVerificationsComplete()) {
- mPendingVerification.remove(verificationId);
- }
- }
-
-
- if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
- // TODO(ruhler) b/112431924: Don't do this in case of 'move'?
- final int enableRollbackToken = mPendingEnableRollbackToken++;
- Trace.asyncTraceBegin(
- TRACE_TAG_PACKAGE_MANAGER, "enable_rollback", enableRollbackToken);
- mPendingEnableRollback.append(enableRollbackToken, this);
- Intent enableRollbackIntent = new Intent(Intent.ACTION_PACKAGE_ENABLE_ROLLBACK);
- enableRollbackIntent.putExtra(
- PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN,
- enableRollbackToken);
- enableRollbackIntent.putExtra(
- PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_SESSION_ID,
- mSessionId);
- enableRollbackIntent.setType(PACKAGE_MIME_TYPE);
- enableRollbackIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- // Allow the broadcast to be sent before boot complete.
- // This is needed when committing the apk part of a staged
- // session in early boot. The rollback manager registers
- // its receiver early enough during the boot process that
- // it will not miss the broadcast.
- enableRollbackIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendOrderedBroadcastAsUser(enableRollbackIntent, UserHandle.SYSTEM,
- android.Manifest.permission.PACKAGE_ROLLBACK_AGENT,
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- // the duration to wait for rollback to be enabled, in millis
- long rollbackTimeout = DeviceConfig.getLong(
- DeviceConfig.NAMESPACE_ROLLBACK,
- PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
- DEFAULT_ENABLE_ROLLBACK_TIMEOUT_MILLIS);
- if (rollbackTimeout < 0) {
- rollbackTimeout = DEFAULT_ENABLE_ROLLBACK_TIMEOUT_MILLIS;
- }
- final Message msg = mHandler.obtainMessage(
- ENABLE_ROLLBACK_TIMEOUT);
- msg.arg1 = enableRollbackToken;
- msg.arg2 = mSessionId;
- mHandler.sendMessageDelayed(msg, rollbackTimeout);
- }
- }, null, 0, null, null);
- mEnableRollbackCompleted = false;
- }
- }
- mRet = ret;
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
InstallArgs 是一个抽象类,定义了APK的安装逻辑,比如复制和重命名APK等,
其中FileInstallArgs用于处理安装到非ASEC的存储空间的APK,也就是内部存储空间(Data分区)
MoveInstallArgs用于处理已安装APK的移动的逻辑。
- static abstract class InstallArgs {
-
-
- class FileInstallArgs extends InstallArgs {
- class MoveInstallArgs extends InstallArgs {
- @Override
- void handleReturnCode() {
- if (mVerificationCompleted
- && mIntegrityVerificationCompleted && mEnableRollbackCompleted) {
- if ((installFlags & PackageManager.INSTALL_DRY_RUN) != 0) {
- String packageName = "";
- ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite(
- new ParseTypeImpl(
- (changeId, packageName1, targetSdkVersion) -> {
- ApplicationInfo appInfo = new ApplicationInfo();
- appInfo.packageName = packageName1;
- appInfo.targetSdkVersion = targetSdkVersion;
- return mPackageParserCallback.isChangeEnabled(changeId,
- appInfo);
- }).reset(),
- origin.file, 0);
- if (result.isError()) {
- Slog.e(TAG, "Can't parse package at " + origin.file.getAbsolutePath(),
- result.getException());
- } else {
- packageName = result.getResult().packageName;
- }
- try {
- observer.onPackageInstalled(packageName, mRet, "Dry run", new Bundle());
- } catch (RemoteException e) {
- Slog.i(TAG, "Observer no longer exists.");
- }
- return;
- }
- if (mRet == PackageManager.INSTALL_SUCCEEDED) {
- mRet = mArgs.copyApk();
- }
- processPendingInstall(mArgs, mRet);
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
mArgs.copyApk();
private InstallArgs mArgs;
- int copyApk() {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
- try {
- return doCopyApk();
- } finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
- }
-
- private int doCopyApk() {
- if (origin.staged) {
- if (DEBUG_INSTALL) Slog.d(TAG, origin.file + " already staged; skipping copy");
- codeFile = origin.file;
- resourceFile = origin.file;
- return PackageManager.INSTALL_SUCCEEDED;
- }
-
- try {
- final boolean isEphemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
- //创建临时文件存储目录
- final File tempDir =
- mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral);
- codeFile = tempDir;
- resourceFile = tempDir;
- } catch (IOException e) {
- Slog.w(TAG, "Failed to create copy file: " + e);
- return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- }
- 将APK复制到临时存储目录
- int ret = PackageManagerServiceUtils.copyPackage(
- origin.file.getAbsolutePath(), codeFile);
- if (ret != PackageManager.INSTALL_SUCCEEDED) {
- Slog.e(TAG, "Failed to copy package");
- return ret;
- }
-
- final boolean isIncremental = isIncrementalPath(codeFile.getAbsolutePath());
- final File libraryRoot = new File(codeFile, LIB_DIR_NAME);
- NativeLibraryHelper.Handle handle = null;
- try {
- handle = NativeLibraryHelper.Handle.create(codeFile);
- ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
- abiOverride, isIncremental);
- } catch (IOException e) {
- Slog.e(TAG, "Copying native libraries failed", e);
- ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
- } finally {
- IoUtils.closeQuietly(handle);
- }
-
- return ret;
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
processPendingInstall(mArgs, mRet);
- private void processPendingInstall(final InstallArgs args, final int currentStatus) {
- if (args.mMultiPackageInstallParams != null) {
- args.mMultiPackageInstallParams.tryProcessInstallRequest(args, currentStatus);
- } else {
- PackageInstalledInfo res = createPackageInstalledInfo(currentStatus);
- processInstallRequestsAsync(
- res.returnCode == PackageManager.INSTALL_SUCCEEDED,
- Collections.singletonList(new InstallRequest(args, res)));
- }
- }
- // Queue up an async operation since the package installation may take a little while.
- private void processInstallRequestsAsync(boolean success,
- List<InstallRequest> installRequests) {
- mHandler.post(() -> {
- if (success) {
- for (InstallRequest request : installRequests) {
- 安装前
- request.args.doPreInstall(request.installResult.returnCode);
- }
- synchronized (mInstallLock) {
- 安装中
- installPackagesTracedLI(installRequests);
- }
- for (InstallRequest request : installRequests) {
- 安装后
- request.args.doPostInstall(
- request.installResult.returnCode, request.installResult.uid);
- }
- }
- for (InstallRequest request : installRequests) {
- restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult,
- new PostInstallData(request.args, request.installResult, null));
- }
- });
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- private PackageInstalledInfo createPackageInstalledInfo(
- int currentStatus) {
- PackageInstalledInfo res = new PackageInstalledInfo();
- res.setReturnCode(currentStatus);
- res.uid = -1;
- res.pkg = null;
- res.removedInfo = null;
- return res;
- }
- @GuardedBy({"mInstallLock", "mLock"})
- private void installPackagesTracedLI(List<InstallRequest> requests) {
- try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
- installPackagesLI(requests);
- } finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
- }
- private void installPackagesLI(List<InstallRequest> requests) {
- final Map<String, ScanResult> preparedScans = new ArrayMap<>(requests.size());
- final Map<String, InstallArgs> installArgs = new ArrayMap<>(requests.size());
- final Map<String, PackageInstalledInfo> installResults = new ArrayMap<>(requests.size());
- final Map<String, PrepareResult> prepareResults = new ArrayMap<>(requests.size());
- final Map<String, VersionInfo> versionInfos = new ArrayMap<>(requests.size());
- final Map<String, PackageSetting> lastStaticSharedLibSettings =
- new ArrayMap<>(requests.size());
- final Map<String, Boolean> createdAppId = new ArrayMap<>(requests.size());
- boolean success = false;
- try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI");
- for (InstallRequest request : requests) {
- // TODO(b/109941548): remove this once we've pulled everything from it and into
- // scan, reconcile or commit.
- final PrepareResult prepareResult;
- try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage");
- prepareResult =
- preparePackageLI(request.args, request.installResult);
- } catch (PrepareFailure prepareFailure) {
- request.installResult.setError(prepareFailure.error,
- prepareFailure.getMessage());
- request.installResult.origPackage = prepareFailure.conflictingPackage;
- request.installResult.origPermission = prepareFailure.conflictingPermission;
- return;
- } finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
- request.installResult.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
- request.installResult.installerPackageName =
- request.args.installSource.installerPackageName;
-
- final String packageName = prepareResult.packageToScan.getPackageName();
- prepareResults.put(packageName, prepareResult);
- installResults.put(packageName, request.installResult);
- installArgs.put(packageName, request.args);
- try {
- final ScanResult result = scanPackageTracedLI(
- prepareResult.packageToScan, prepareResult.parseFlags,
- prepareResult.scanFlags, System.currentTimeMillis(),
- request.args.user, request.args.abiOverride);
- if (null != preparedScans.put(result.pkgSetting.pkg.getPackageName(), result)) {
- request.installResult.setError(
- PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE,
- "Duplicate package " + result.pkgSetting.pkg.getPackageName()
- + " in multi-package install request.");
- return;
- }
- createdAppId.put(packageName, optimisticallyRegisterAppId(result));
- versionInfos.put(result.pkgSetting.pkg.getPackageName(),
- getSettingsVersionForPackage(result.pkgSetting.pkg));
- if (result.staticSharedLibraryInfo != null) {
- final PackageSetting sharedLibLatestVersionSetting =
- getSharedLibLatestVersionSetting(result);
- if (sharedLibLatestVersionSetting != null) {
- lastStaticSharedLibSettings.put(result.pkgSetting.pkg.getPackageName(),
- sharedLibLatestVersionSetting);
- }
- }
- } catch (PackageManagerException e) {
- request.installResult.setError("Scanning Failed.", e);
- return;
- }
- }
- ReconcileRequest reconcileRequest = new ReconcileRequest(preparedScans, installArgs,
- installResults,
- prepareResults,
- mSharedLibraries,
- Collections.unmodifiableMap(mPackages), versionInfos,
- lastStaticSharedLibSettings);
- CommitRequest commitRequest = null;
- synchronized (mLock) {
- Map<String, ReconciledPackage> reconciledPackages;
- try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
- reconciledPackages = reconcilePackagesLocked(
- reconcileRequest, mSettings.mKeySetManagerService);
- } catch (ReconcileFailure e) {
- for (InstallRequest request : requests) {
- request.installResult.setError("Reconciliation failed...", e);
- }
- return;
- } finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
- try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "commitPackages");
- commitRequest = new CommitRequest(reconciledPackages,
- mUserManager.getUserIds());
- commitPackagesLocked(commitRequest);
- success = true;
- } finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
- }
- executePostCommitSteps(commitRequest);
- } finally {
- if (success) {
- for (InstallRequest request : requests) {
- final InstallArgs args = request.args;
- if (args.mDataLoaderType != DataLoaderType.INCREMENTAL) {
- continue;
- }
- if (args.signingDetails.signatureSchemeVersion != SIGNING_BLOCK_V4) {
- continue;
- }
- // For incremental installs, we bypass the verifier prior to install. Now
- // that we know the package is valid, send a notice to the verifier with
- // the root hash of the base.apk.
- final String baseCodePath = request.installResult.pkg.getBaseCodePath();
- final String[] splitCodePaths = request.installResult.pkg.getSplitCodePaths();
- final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
- final int verificationId = mPendingVerificationToken++;
- final String rootHashString = PackageManagerServiceUtils
- .buildVerificationRootHashString(baseCodePath, splitCodePaths);
- broadcastPackageVerified(verificationId, originUri,
- PackageManager.VERIFICATION_ALLOW, rootHashString,
- args.mDataLoaderType, args.getUser());
- }
- } else {
- for (ScanResult result : preparedScans.values()) {
- if (createdAppId.getOrDefault(result.request.parsedPackage.getPackageName(),
- false)) {
- cleanUpAppIdCreation(result);
- }
- }
- // TODO(patb): create a more descriptive reason than unknown in future release
- // mark all non-failure installs as UNKNOWN so we do not treat them as success
- for (InstallRequest request : requests) {
- if (request.installResult.freezer != null) {
- request.installResult.freezer.close();
- }
- if (request.installResult.returnCode == PackageManager.INSTALL_SUCCEEDED) {
- request.installResult.returnCode = PackageManager.INSTALL_UNKNOWN;
- }
- }
- }
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
executePostCommitSteps执行安装
installPackageLI方法的代码有将近500行,这里截取主要的部分,主要做了几件事:
installNewPackageLIF主要做了以下3件事:
安装APK的过程就讲到这里,就不再往下分析下去,有兴趣的同学可以接着深挖。
本文主要讲解了PMS是如何处理APK安装的,主要有几个步骤:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。