• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

app 安装方式

武飞扬头像
菜鸟xiaowang
帮助1

APK的安装方式主要有以下几种:

  • 通过adb命令安装:adb 命令包括adb push/install
  • 用户下载的Apk,通过系统安装器PackageInstaller安装该Apk。PackageInstaller是系统内置的应用程序,用于安装和卸载应用程序。
  • 系统开机时安装系统应用。 persistent属性
  • 应用商店下载后自动安装。

PackageInstaller的位置

frameworks\base\packages\PackageInstaller\路径下

其中InstallStart为PackageInstaller入口
  1.  
    <activity android:name=".InstallStart"
  2.  
    android:theme="@android:style/Theme.Translucent.NoTitleBar"
  3.  
    android:exported="true"
  4.  
    android:excludeFromRecents="true">
  5.  
    <intent-filter android:priority="1">
  6.  
    <action android:name="android.intent.action.VIEW" />
  7.  
    <action android:name="android.intent.action.INSTALL_PACKAGE" />
  8.  
    <category android:name="android.intent.category.DEFAULT" />
  9.  
    <data android:scheme="content" />
  10.  
    <data android:mimeType="application/vnd.android.package-archive" />
  11.  
    </intent-filter>
  12.  
    <intent-filter android:priority="1">
  13.  
    <action android:name="android.intent.action.INSTALL_PACKAGE" />
  14.  
    <category android:name="android.intent.category.DEFAULT" />
  15.  
    <data android:scheme="package" />
  16.  
    <data android:scheme="content" />
  17.  
    </intent-filter>
  18.  
    <intent-filter android:priority="1">
  19.  
    <action android:name="android.content.pm.action.CONFIRM_INSTALL" />
  20.  
    <category android:name="android.intent.category.DEFAULT" />
  21.  
    </intent-filter>
  22.  
    </activity>
学新通

安装apk的代码主要是调用InstallStart

  1.  
    Intent intent = new Intent(Intent.ACTION_VIEW);
  2.  
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  3.  
    intent.setDataAndType(Uri.parse("file://" path),"application/vnd.android.package-archive");
  4.  
    context.startActivity(intent);

PackageInstaller是系统内置的应用程序,用于安装和卸载应用。当我们调用PackageInstaller来安装应用时会跳转到InstallStart,并调用它的onCreate方法:

  1.  
    String callingPackage = getCallingPackage();
  2.  
     
  3.  
    final boolean isSessionInstall =
  4.  
    PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction());
  5.  
     
  6.  
     
  7.  
     
  8.  
    if (isSessionInstall) {
  9.  
    nextActivity.setClass(this, PackageInstallerActivity.class);
  10.  
    } else {
  11.  
    Uri packageUri = intent.getData();
  12.  
     
  13.  
    if (packageUri != null && packageUri.getScheme().equals(
  14.  
    ContentResolver.SCHEME_CONTENT)) {
  15.  
    // [IMPORTANT] This path is deprecated, but should still work. Only necessary
  16.  
    // features should be added.
  17.  
     
  18.  
    // Copy file to prevent it from being changed underneath this process
  19.  
    //调用这里,启动InstallStaging
  20.  
    nextActivity.setClass(this, InstallStaging.class);
  21.  
    } else if (packageUri != null && packageUri.getScheme().equals(
  22.  
    PackageInstallerActivity.SCHEME_PACKAGE)) {
  23.  
     
  24.  
    nextActivity.setClass(this, PackageInstallerActivity.class);
  25.  
    } else {
  26.  
    Intent result = new Intent();
  27.  
    result.putExtra(Intent.EXTRA_INSTALL_RESULT,
  28.  
    PackageManager.INSTALL_FAILED_INVALID_URI);
  29.  
    setResult(RESULT_FIRST_USER, result);
  30.  
     
  31.  
    nextActivity = null;
  32.  
    }
  33.  
    }
  34.  
     
  35.  
    if (nextActivity != null) {
  36.  
    startActivity(nextActivity);
  37.  
    }
  38.  
    finish();
学新通

frameworks\base\packages\PackageInstaller\src\com\android\packageinstaller\InstallStaging.java   InstallStaging的onResume方法

  1.  
    @Override
  2.  
    protected void onResume() {
  3.  
    super.onResume();
  4.  
     
  5.  
    // This is the first onResume in a single life of the activity
  6.  
    if (mStagingTask == null) {
  7.  
    // File does not exist, or became invalid
  8.  
    if (mStagedFile == null) {
  9.  
    // Create file delayed to be able to show error
  10.  
    try {
  11.  
    如果File类型的mStagedFile 为null,则创建mStagedFile ,mStagedFile用于存储临时数据
  12.  
    mStagedFile = TemporaryFileManager.getStagedFile(this);
  13.  
    } catch (IOException e) {
  14.  
    showError();
  15.  
    return;
  16.  
    }
  17.  
    }
  18.  
    启动StagingAsyncTask
  19.  
    mStagingTask = new StagingAsyncTask();
  20.  
    mStagingTask.execute(getIntent().getData());
  21.  
    }
  22.  
    }
学新通

 StagingAsyncTask是InstallStaging的内部类,

  1.  
    private final class StagingAsyncTask extends AsyncTask<Uri, Void, Boolean> {
  2.  
    @Override
  3.  
    protected Boolean doInBackground(Uri... params) {
  4.  
    if (params == null || params.length <= 0) {
  5.  
    return false;
  6.  
    }
  7.  
    Uri packageUri = params[0];
  8.  
    try (InputStream in = getContentResolver().openInputStream(packageUri)) {
  9.  
    // Despite the comments in ContentResolver#openInputStream the returned stream can
  10.  
    // be null.
  11.  
    if (in == null) {
  12.  
    return false;
  13.  
    }
  14.  
     
  15.  
    try (OutputStream out = new FileOutputStream(mStagedFile)) {
  16.  
    byte[] buffer = new byte[1024 * 1024];
  17.  
    int bytesRead;
  18.  
    while ((bytesRead = in.read(buffer)) >= 0) {
  19.  
    // Be nice and respond to a cancellation
  20.  
    if (isCancelled()) {
  21.  
    return false;
  22.  
    }
  23.  
    out.write(buffer, 0, bytesRead);
  24.  
    }
  25.  
    }
  26.  
    } catch (IOException | SecurityException | IllegalStateException e) {
  27.  
    Log.w(LOG_TAG, "Error staging apk from content URI", e);
  28.  
    return false;
  29.  
    }
  30.  
    return true;
  31.  
    }
  32.  
     
  33.  
    @Override
  34.  
    protected void onPostExecute(Boolean success) {
  35.  
    if (success) {
  36.  
    // Now start the installation again from a file
  37.  
    Intent installIntent = new Intent(getIntent());
  38.  
    installIntent.setClass(InstallStaging.this, DeleteStagedFileOnResult.class);
  39.  
    installIntent.setData(Uri.fromFile(mStagedFile));
  40.  
     
  41.  
    if (installIntent.getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
  42.  
    installIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
  43.  
    }
  44.  
     
  45.  
    installIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
  46.  
    startActivity(installIntent);
  47.  
     
  48.  
    InstallStaging.this.finish();
  49.  
    } else {
  50.  
    showError();
  51.  
    }
  52.  
    }
  53.  
    }
学新通

doInBackground方法中将packageUri(content协议的Uri)的内容写入到mStagedFile中,如果写入成功,onPostExecute方法中会跳转到DeleteStagedFileOnResult中,

frameworks\base\packages\PackageInstaller\src\com\android\packageinstaller\DeleteStagedFileOnResult.java

DeleteStagedFileOnResult启动PackageInstallerActivity实现apk的安装

  1.  
    public class DeleteStagedFileOnResult extends Activity {
  2.  
    @Override
  3.  
    protected void onCreate(@Nullable Bundle savedInstanceState) {
  4.  
    super.onCreate(savedInstanceState);
  5.  
     
  6.  
    if (savedInstanceState == null) {
  7.  
    Intent installIntent = new Intent(getIntent());
  8.  
    installIntent.setClass(this, PackageInstallerActivity.class);
  9.  
     
  10.  
    installIntent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
  11.  
    startActivityForResult(installIntent, 0);
  12.  
    }
  13.  
    }
  14.  
     
  15.  
    @Override
  16.  
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  17.  
    File sourceFile = new File(getIntent().getData().getPath());
  18.  
    sourceFile.delete();
  19.  
     
  20.  
    setResult(resultCode, data);
  21.  
    finish();
  22.  
    }
  23.  
    }
学新通

DeleteStagedFileOnResult将mStagedFile传入PackageInstallerActivity,InstallStaging主要将content协议的Uri转换为File协议,然后跳转到PackageInstallerActivity,这样就可以像此前版本(Android7.0之前)一样启动安装流程了。

frameworks\base\packages\PackageInstaller\src\com\android\packageinstaller\PackageInstallerActivity.java

  1.  
    @Override
  2.  
    protected void onCreate(Bundle icicle) {
  3.  
    getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
  4.  
     
  5.  
    super.onCreate(null);
  6.  
     
  7.  
    if (icicle != null) {
  8.  
    mAllowUnknownSources = icicle.getBoolean(ALLOW_UNKNOWN_SOURCES_KEY);
  9.  
    }
  10.  
    //初始话安装所需要的各种对象
  11.  
    mPm = getPackageManager();
  12.  
    mIpm = AppGlobals.getPackageManager();
  13.  
    mAppOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
  14.  
    mInstaller = mPm.getPackageInstaller();
  15.  
    mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
  16.  
     
  17.  
    final Intent intent = getIntent();
  18.  
     
  19.  
    mCallingPackage = intent.getStringExtra(EXTRA_CALLING_PACKAGE);
  20.  
    mSourceInfo = intent.getParcelableExtra(EXTRA_ORIGINAL_SOURCE_INFO);
  21.  
    mOriginatingUid = intent.getIntExtra(Intent.EXTRA_ORIGINATING_UID,
  22.  
    PackageInstaller.SessionParams.UID_UNKNOWN);
  23.  
    mOriginatingPackage = (mOriginatingUid != PackageInstaller.SessionParams.UID_UNKNOWN)
  24.  
    ? getPackageNameForUid(mOriginatingUid) : null;
  25.  
     
  26.  
     
  27.  
    final Uri packageUri;
  28.  
     
  29.  
    if (PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction())) {
  30.  
    final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1);
  31.  
    final PackageInstaller.SessionInfo info = mInstaller.getSessionInfo(sessionId);
  32.  
    if (info == null || !info.sealed || info.resolvedBaseCodePath == null) {
  33.  
    Log.w(TAG, "Session " mSessionId " in funky state; ignoring");
  34.  
    finish();
  35.  
    return;
  36.  
    }
  37.  
     
  38.  
    mSessionId = sessionId;
  39.  
    packageUri = Uri.fromFile(new File(info.resolvedBaseCodePath));
  40.  
    mOriginatingURI = null;
  41.  
    mReferrerURI = null;
  42.  
    } else {
  43.  
    mSessionId = -1;
  44.  
    packageUri = intent.getData();
  45.  
    mOriginatingURI = intent.getParcelableExtra(Intent.EXTRA_ORIGINATING_URI);
  46.  
    mReferrerURI = intent.getParcelableExtra(Intent.EXTRA_REFERRER);
  47.  
    }
  48.  
     
  49.  
    // if there's nothing to do, quietly slip into the ether
  50.  
    if (packageUri == null) {
  51.  
    Log.w(TAG, "Unspecified source");
  52.  
    setPmResult(PackageManager.INSTALL_FAILED_INVALID_URI);
  53.  
    finish();
  54.  
    return;
  55.  
    }
  56.  
     
  57.  
    if (DeviceUtils.isWear(this)) {
  58.  
    showDialogInner(DLG_NOT_SUPPORTED_ON_WEAR);
  59.  
    return;
  60.  
    }
  61.  
     
  62.  
    boolean wasSetUp = processPackageUri(packageUri);
  63.  
    if (!wasSetUp) {
  64.  
    return;
  65.  
    }
  66.  
     
  67.  
    // load dummy layout with OK button disabled until we override this layout in
  68.  
    // startInstallConfirm
  69.  
    bindUi();
  70.  
    //判断是否是未知来源的应用,如果开启允许安装未知来源选项则直接初始化安装
  71.  
    checkIfAllowedAndInitiateInstall();
  72.  
    }
学新通
类名 描述
PackageManager 用于向应用程序进程提供一些功能,最终的功能是由PMS来实现的
IPackageManager 一个AIDL的接口,用于和PMS进行进程间通信
AppOpsManager 用于权限动态检测,在Android4.3中被引入
PackageInstaller 提供安装、升级和删除应用程序功能
UserManager 用于多用户管理


        bindUi();

  1.  
    /**
  2.  
    * Check if it is allowed to install the package and initiate install if allowed. If not allowed
  3.  
    * show the appropriate dialog.
  4.  
    */
  5.  
    private void checkIfAllowedAndInitiateInstall() {
  6.  
    // Check for install apps user restriction first.
  7.  
    final int installAppsRestrictionSource = mUserManager.getUserRestrictionSource(
  8.  
    UserManager.DISALLOW_INSTALL_APPS, Process.myUserHandle());
  9.  
    if ((installAppsRestrictionSource & UserManager.RESTRICTION_SOURCE_SYSTEM) != 0) {
  10.  
    showDialogInner(DLG_INSTALL_APPS_RESTRICTED_FOR_USER);
  11.  
    return;
  12.  
    } else if (installAppsRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
  13.  
    startActivity(new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS));
  14.  
    finish();
  15.  
    return;
  16.  
    }
  17.  
    //判断如果允许安装未知来源或者根据Intent判断得出该APK不是未知来源
  18.  
    if (mAllowUnknownSources || !isInstallRequestFromUnknownSource(getIntent())) {
  19.  
    initiateInstall();
  20.  
    } else {
  21.  
    // 如果管理员限制来自未知源的安装, 就弹出提示Dialog或者跳转到设置界面
  22.  
    // Check for unknown sources restrictions.
  23.  
    final int unknownSourcesRestrictionSource = mUserManager.getUserRestrictionSource(
  24.  
    UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, Process.myUserHandle());
  25.  
    final int unknownSourcesGlobalRestrictionSource = mUserManager.getUserRestrictionSource(
  26.  
    UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, Process.myUserHandle());
  27.  
    final int systemRestriction = UserManager.RESTRICTION_SOURCE_SYSTEM
  28.  
    & (unknownSourcesRestrictionSource | unknownSourcesGlobalRestrictionSource);
  29.  
    if (systemRestriction != 0) {
  30.  
    showDialogInner(DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER);
  31.  
    } else if (unknownSourcesRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
  32.  
    startAdminSupportDetailsActivity(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
  33.  
    } else if (unknownSourcesGlobalRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
  34.  
    startAdminSupportDetailsActivity(
  35.  
    UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY);
  36.  
    } else {
  37.  
    handleUnknownSources();
  38.  
    }
  39.  
    }
  40.  
    }
学新通

bindUi()方法主要完成对安装界面的加载

  1.  
    private void bindUi() {
  2.  
    mAlert.setIcon(mAppSnippet.icon);
  3.  
    mAlert.setTitle(mAppSnippet.label);
  4.  
    mAlert.setView(R.layout.install_content_view);
  5.  
    mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install),
  6.  
    (ignored, ignored2) -> {
  7.  
    if (mOk.isEnabled()) {
  8.  
    if (mSessionId != -1) {
  9.  
    mInstaller.setPermissionsResult(mSessionId, true);
  10.  
    finish();
  11.  
    } else {
  12.  
    完成app的安装
  13.  
    startInstall();
  14.  
    }
  15.  
    }
  16.  
    }, null);
  17.  
    mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
  18.  
    (ignored, ignored2) -> {
  19.  
    // Cancel and finish
  20.  
    setResult(RESULT_CANCELED);
  21.  
    if (mSessionId != -1) {
  22.  
    mInstaller.setPermissionsResult(mSessionId, false);
  23.  
    }
  24.  
    finish();
  25.  
    }, null);
  26.  
    setupAlert();
  27.  
     
  28.  
    mOk = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
  29.  
    mOk.setEnabled(false);
  30.  
     
  31.  
    if (!mOk.isInTouchMode()) {
  32.  
    mAlert.getButton(DialogInterface.BUTTON_NEGATIVE).requestFocus();
  33.  
    }
  34.  
    }
学新通
  1.  
    private void initiateInstall() {
  2.  
    String pkgName = mPkgInfo.packageName;
  3.  
    // Check if there is already a package on the device with this name
  4.  
    // but it has been renamed to something else.
  5.  
    String[] oldName = mPm.canonicalToCurrentPackageNames(new String[] { pkgName });
  6.  
    if (oldName != null && oldName.length > 0 && oldName[0] != null) {
  7.  
    pkgName = oldName[0];
  8.  
    mPkgInfo.packageName = pkgName;
  9.  
    mPkgInfo.applicationInfo.packageName = pkgName;
  10.  
    }
  11.  
    // Check if package is already installed. display confirmation dialog if replacing pkg
  12.  
    try {
  13.  
    // This is a little convoluted because we want to get all uninstalled
  14.  
    // apps, but this may include apps with just data, and if it is just
  15.  
    // data we still want to count it as "installed".
  16.  
    mAppInfo = mPm.getApplicationInfo(pkgName,
  17.  
    PackageManager.MATCH_UNINSTALLED_PACKAGES);
  18.  
    if ((mAppInfo.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
  19.  
    mAppInfo = null;
  20.  
    }
  21.  
    } catch (NameNotFoundException e) {
  22.  
    mAppInfo = null;
  23.  
    }
  24.  
     
  25.  
    startInstallConfirm();
  26.  
    }
学新通
  1.  
    private void startInstallConfirm() {
  2.  
    View viewToEnable;
  3.  
     
  4.  
    if (mAppInfo != null) {
  5.  
    viewToEnable = (mAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
  6.  
    ? requireViewById(R.id.install_confirm_question_update_system)
  7.  
    : requireViewById(R.id.install_confirm_question_update);
  8.  
    } else {
  9.  
    // This is a new application with no permissions.
  10.  
    viewToEnable = requireViewById(R.id.install_confirm_question);
  11.  
    }
  12.  
     
  13.  
    viewToEnable.setVisibility(View.VISIBLE);
  14.  
     
  15.  
    mEnableOk = true;
  16.  
    mOk.setEnabled(true);
  17.  
    mOk.setFilterTouchesWhenObscured(true);
  18.  
    }
学新通

 具体加载的布局文件再frameworks\base\packages\PackageInstaller\res\layout\下

学新通

现在来总结下PackageInstaller初始化的过程:

  1. 根据Uri的Scheme协议不同,跳转到不同的界面,content协议跳转到InstallStart,其他的跳转到PackageInstallerActivity。
  2. InstallStart将content协议的Uri转换为File协议,然后跳转到PackageInstallerActivity。
  3. PackageInstallerActivity会分别对package协议和file协议的Uri进行处理,如果是file协议会解析APK文件得到包信息PackageInfo。
  4. PackageInstallerActivity中会对未知来源进行处理,如果允许安装未知来源或者根据Intent判断得出该APK不是未知来源,就会初始化安装确认界面,如果管理员限制来自未知源的安装, 就弹出提示Dialog或者跳转到设置界面。

 startInstall();方法调用 InstallInstalling 来安装apk

startInstall方法用于跳转到InstallInstalling这个Activity,并关闭掉当前的PackageInstallerActivity。InstallInstalling主要用于向包管理器发送包的信息并处理包管理的回调。

  1.  
    private void startInstall() {
  2.  
    // Start subactivity to actually install the application
  3.  
    Intent newIntent = new Intent();
  4.  
    newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
  5.  
    mPkgInfo.applicationInfo);
  6.  
    newIntent.setData(mPackageURI);
  7.  
    newIntent.setClass(this, InstallInstalling.class);
  8.  
    String installerPackageName = getIntent().getStringExtra(
  9.  
    Intent.EXTRA_INSTALLER_PACKAGE_NAME);
  10.  
    if (mOriginatingURI != null) {
  11.  
    newIntent.putExtra(Intent.EXTRA_ORIGINATING_URI, mOriginatingURI);
  12.  
    }
  13.  
    if (mReferrerURI != null) {
  14.  
    newIntent.putExtra(Intent.EXTRA_REFERRER, mReferrerURI);
  15.  
    }
  16.  
    if (mOriginatingUid != PackageInstaller.SessionParams.UID_UNKNOWN) {
  17.  
    newIntent.putExtra(Intent.EXTRA_ORIGINATING_UID, mOriginatingUid);
  18.  
    }
  19.  
    if (installerPackageName != null) {
  20.  
    newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME,
  21.  
    installerPackageName);
  22.  
    }
  23.  
    if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
  24.  
    newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
  25.  
    }
  26.  
    newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
  27.  
    if(localLOGV) Log.i(TAG, "downloaded app uri=" mPackageURI);
  28.  
    startActivity(newIntent);
  29.  
    finish();
  30.  
    }
学新通

frameworks\base\packages\PackageInstaller\src\com\android\packageinstaller\InstallInstalling.java

  1.  
    @Override
  2.  
    protected void onCreate(@Nullable Bundle savedInstanceState) {
  3.  
    super.onCreate(savedInstanceState);
  4.  
     
  5.  
    ApplicationInfo appInfo = getIntent()
  6.  
    .getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
  7.  
    mPackageURI = getIntent().getData();
  8.  
     
  9.  
    if ("package".equals(mPackageURI.getScheme())) {
  10.  
    try {
  11.  
    getPackageManager().installExistingPackage(appInfo.packageName);
  12.  
    launchSuccess();
  13.  
    } catch (PackageManager.NameNotFoundException e) {
  14.  
    launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
  15.  
    }
  16.  
    } else {
  17.  
    //根据mPackageURI创建一个对应的File
  18.  
    final File sourceFile = new File(mPackageURI.getPath());
  19.  
    PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
  20.  
     
  21.  
    mAlert.setIcon(as.icon);
  22.  
    mAlert.setTitle(as.label);
  23.  
    mAlert.setView(R.layout.install_content_view);
  24.  
    mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
  25.  
    (ignored, ignored2) -> {
  26.  
    if (mInstallingTask != null) {
  27.  
    mInstallingTask.cancel(true);
  28.  
    }
  29.  
     
  30.  
    if (mSessionId > 0) {
  31.  
    getPackageManager().getPackageInstaller().abandonSession(mSessionId);
  32.  
    mSessionId = 0;
  33.  
    }
  34.  
     
  35.  
    setResult(RESULT_CANCELED);
  36.  
    finish();
  37.  
    }, null);
  38.  
    setupAlert();
  39.  
    requireViewById(R.id.installing).setVisibility(View.VISIBLE);
  40.  
    //如果savedInstanceState不为null,获取此前保存的mSessionId和mInstallId
  41.  
    if (savedInstanceState != null) {
  42.  
    mSessionId = savedInstanceState.getInt(SESSION_ID);
  43.  
    mInstallId = savedInstanceState.getInt(INSTALL_ID);
  44.  
     
  45.  
    // Reregister for result; might instantly call back if result was delivered while
  46.  
    // activity was destroyed
  47.  
    try {
  48.  
    //向InstallEventReceiver注册一个观察者
  49.  
    InstallEventReceiver.addObserver(this, mInstallId,
  50.  
    this::launchFinishBasedOnResult);
  51.  
    } catch (EventResultPersister.OutOfIdsException e) {
  52.  
    // Does not happen
  53.  
    }
  54.  
    } else {
  55.  
    PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
  56.  
    PackageInstaller.SessionParams.MODE_FULL_INSTALL);
  57.  
    params.setInstallAsInstantApp(false);
  58.  
    params.setReferrerUri(getIntent().getParcelableExtra(Intent.EXTRA_REFERRER));
  59.  
    params.setOriginatingUri(getIntent()
  60.  
    .getParcelableExtra(Intent.EXTRA_ORIGINATING_URI));
  61.  
    params.setOriginatingUid(getIntent().getIntExtra(Intent.EXTRA_ORIGINATING_UID,
  62.  
    UID_UNKNOWN));
  63.  
    params.setInstallerPackageName(getIntent().getStringExtra(
  64.  
    Intent.EXTRA_INSTALLER_PACKAGE_NAME));
  65.  
    params.setInstallReason(PackageManager.INSTALL_REASON_USER);
  66.  
     
  67.  
    File file = new File(mPackageURI.getPath());
  68.  
    try {
  69.  
    PackageParser.PackageLite pkg = PackageParser.parsePackageLite(file, 0);
  70.  
    params.setAppPackageName(pkg.packageName);
  71.  
    params.setInstallLocation(pkg.installLocation);
  72.  
    params.setSize(
  73.  
    PackageHelper.calculateInstalledSize(pkg, false, params.abiOverride));
  74.  
    } catch (PackageParser.PackageParserException e) {
  75.  
    Log.e(LOG_TAG, "Cannot parse package " file ". Assuming defaults.");
  76.  
    Log.e(LOG_TAG,
  77.  
    "Cannot calculate installed size " file ". Try only apk size.");
  78.  
    params.setSize(file.length());
  79.  
    } catch (IOException e) {
  80.  
    Log.e(LOG_TAG,
  81.  
    "Cannot calculate installed size " file ". Try only apk size.");
  82.  
    params.setSize(file.length());
  83.  
    }
  84.  
     
  85.  
    try {
  86.  
    mInstallId = InstallEventReceiver
  87.  
    .addObserver(this, EventResultPersister.GENERATE_NEW_ID,
  88.  
    this::launchFinishBasedOnResult);
  89.  
    } catch (EventResultPersister.OutOfIdsException e) {
  90.  
    launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
  91.  
    }
  92.  
     
  93.  
    try {
  94.  
    mSessionId = getPackageManager().getPackageInstaller().createSession(params);
  95.  
    } catch (IOException e) {
  96.  
    launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
  97.  
    }
  98.  
    }
  99.  
     
  100.  
    mCancelButton = mAlert.getButton(DialogInterface.BUTTON_NEGATIVE);
  101.  
     
  102.  
    mSessionCallback = new InstallSessionCallback();
  103.  
    }
  104.  
    }
学新通

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。

  1.  
    @Override
  2.  
    protected void onResume() {
  3.  
    super.onResume();
  4.  
     
  5.  
    // This is the first onResume in a single life of the activity
  6.  
    if (mInstallingTask == null) {
  7.  
    PackageInstaller installer = getPackageManager().getPackageInstaller();
  8.  
    PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);
  9.  
     
  10.  
    if (sessionInfo != null && !sessionInfo.isActive()) {
  11.  
    mInstallingTask = new InstallingAsyncTask();
  12.  
    mInstallingTask.execute();
  13.  
    } else {
  14.  
    // we will receive a broadcast when the install is finished
  15.  
    mCancelButton.setEnabled(false);
  16.  
    setFinishOnTouchOutside(false);
  17.  
    }
  18.  
    }
  19.  
    }
学新通

根据mSessionId得到SessionInfo,SessionInfo代表安装会话的详细信息。如果sessionInfo不为Null并且不是活动的,就创建并执行InstallingAsyncTask。InstallingAsyncTask的doInBackground方法中会根据包(APK)的Uri,将APK的信息通过IO流的形式写入到PackageInstaller.Session中 

onResune 启动InstallingAsyncTask 

  1.  
    private final class InstallingAsyncTask extends AsyncTask<Void, Void,
  2.  
    PackageInstaller.Session> {
  3.  
    volatile boolean isDone;
  4.  
     
  5.  
    @Override
  6.  
    protected PackageInstaller.Session doInBackground(Void... params) {
  7.  
    PackageInstaller.Session session;
  8.  
    try {
  9.  
    session = getPackageManager().getPackageInstaller().openSession(mSessionId);
  10.  
    } catch (IOException e) {
  11.  
    return null;
  12.  
    }
  13.  
     
  14.  
    session.setStagingProgress(0);
  15.  
     
  16.  
    try {
  17.  
    File file = new File(mPackageURI.getPath());
  18.  
     
  19.  
    try (InputStream in = new FileInputStream(file)) {
  20.  
    long sizeBytes = file.length();
  21.  
    try (OutputStream out = session
  22.  
    .openWrite("PackageInstaller", 0, sizeBytes)) {
  23.  
    byte[] buffer = new byte[1024 * 1024];
  24.  
    while (true) {
  25.  
    int numRead = in.read(buffer);
  26.  
     
  27.  
    if (numRead == -1) {
  28.  
    session.fsync(out);
  29.  
    break;
  30.  
    }
  31.  
     
  32.  
    if (isCancelled()) {
  33.  
    session.close();
  34.  
    break;
  35.  
    }
  36.  
     
  37.  
    out.write(buffer, 0, numRead);
  38.  
    if (sizeBytes > 0) {
  39.  
    float fraction = ((float) numRead / (float) sizeBytes);
  40.  
    session.addProgress(fraction);
  41.  
    }
  42.  
    }
  43.  
    }
  44.  
    }
  45.  
     
  46.  
    return session;
  47.  
    } catch (IOException | SecurityException e) {
  48.  
    Log.e(LOG_TAG, "Could not write package", e);
  49.  
     
  50.  
    session.close();
  51.  
     
  52.  
    return null;
  53.  
    } finally {
  54.  
    synchronized (this) {
  55.  
    isDone = true;
  56.  
    notifyAll();
  57.  
    }
  58.  
    }
  59.  
    }
  60.  
     
  61.  
    @Override
  62.  
    protected void onPostExecute(PackageInstaller.Session session) {
  63.  
    if (session != null) {
  64.  
    Intent broadcastIntent = new Intent(BROADCAST_ACTION);
  65.  
    broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
  66.  
    broadcastIntent.setPackage(getPackageName());
  67.  
    broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId);
  68.  
     
  69.  
    PendingIntent pendingIntent = PendingIntent.getBroadcast(
  70.  
    InstallInstalling.this,
  71.  
    mInstallId,
  72.  
    broadcastIntent,
  73.  
    PendingIntent.FLAG_UPDATE_CURRENT);
  74.  
     
  75.  
    session.commit(pendingIntent.getIntentSender());
  76.  
    mCancelButton.setEnabled(false);
  77.  
    setFinishOnTouchOutside(false);
  78.  
    } else {
  79.  
    getPackageManager().getPackageInstaller().abandonSession(mSessionId);
  80.  
     
  81.  
    if (!isCancelled()) {
  82.  
    launchFailure(PackageManager.INSTALL_FAILED_INVALID_APK, null);
  83.  
    }
  84.  
    }
  85.  
    }
  86.  
    }
学新通

创建了一个PendingIntent,并将该PendingIntent的IntentSender通过PackageInstaller.Session的commit方法发送出去

frameworks\base\core\java\android\content\pm\PackageInstaller.java

  1.  
    protected final IPackageInstallerSession mSession;
  2.  
     
  3.  
    public void commit(@NonNull IntentSender statusReceiver) {
  4.  
    try {
  5.  
    mSession.commit(statusReceiver, false);
  6.  
    } catch (RemoteException e) {
  7.  
    throw e.rethrowFromSystemServer();
  8.  
    }
  9.  
    }

mSession的类型为IPackageInstallerSession,这说明要通过IPackageInstallerSession来进行进程间的通信,最终会调用PackageInstallerSession的commit方法

frameworks\base\services\core\java\com\android\server\pm\PackageInstallerSession.java

  1.  
    @Override
  2.  
    public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
  3.  
    if (hasParentSessionId()) {
  4.  
    throw new IllegalStateException(
  5.  
    "Session " sessionId " is a child of multi-package session "
  6.  
    mParentSessionId " and may not be committed directly.");
  7.  
    }
  8.  
     
  9.  
    if (!markAsSealed(statusReceiver, forTransfer)) {
  10.  
    return;
  11.  
    }
  12.  
    if (isMultiPackage()) {
  13.  
    final SparseIntArray remainingSessions = mChildSessionIds.clone();
  14.  
    final IntentSender childIntentSender =
  15.  
    new ChildStatusIntentReceiver(remainingSessions, statusReceiver)
  16.  
    .getIntentSender();
  17.  
    boolean sealFailed = false;
  18.  
    for (int i = mChildSessionIds.size() - 1; i >= 0; --i) {
  19.  
    final int childSessionId = mChildSessionIds.keyAt(i);
  20.  
    // seal all children, regardless if any of them fail; we'll throw/return
  21.  
    // as appropriate once all children have been processed
  22.  
    if (!mSessionProvider.getSession(childSessionId)
  23.  
    .markAsSealed(childIntentSender, forTransfer)) {
  24.  
    sealFailed = true;
  25.  
    }
  26.  
    }
  27.  
    if (sealFailed) {
  28.  
    return;
  29.  
    }
  30.  
    }
  31.  
     
  32.  
    dispatchStreamValidateAndCommit();
  33.  
    }
学新通
  1.  
    private void dispatchStreamValidateAndCommit() {
  2.  
    mHandler.obtainMessage(MSG_STREAM_VALIDATE_AND_COMMIT).sendToTarget();
  3.  
    }
  4.  
     
  5.  
    private void handleStreamValidateAndCommit() {
  6.  
    PackageManagerException unrecoverableFailure = null;
  7.  
    // This will track whether the session and any children were validated and are ready to
  8.  
    // progress to the next phase of install
  9.  
    boolean allSessionsReady = false;
  10.  
    try {
  11.  
    allSessionsReady = streamValidateAndCommit();
  12.  
    } catch (PackageManagerException e) {
  13.  
    unrecoverableFailure = e;
  14.  
    }
  15.  
     
  16.  
    if (isMultiPackage()) {
  17.  
    int childCount = mChildSessionIds.size();
  18.  
     
  19.  
    // This will contain all child sessions that do not encounter an unrecoverable failure
  20.  
    ArrayList<PackageInstallerSession> nonFailingSessions = new ArrayList<>(childCount);
  21.  
     
  22.  
    for (int i = childCount - 1; i >= 0; --i) {
  23.  
    final int childSessionId = mChildSessionIds.keyAt(i);
  24.  
    // commit all children, regardless if any of them fail; we'll throw/return
  25.  
    // as appropriate once all children have been processed
  26.  
    try {
  27.  
    PackageInstallerSession session = mSessionProvider.getSession(childSessionId);
  28.  
    allSessionsReady &= session.streamValidateAndCommit();
  29.  
    nonFailingSessions.add(session);
  30.  
    } catch (PackageManagerException e) {
  31.  
    allSessionsReady = false;
  32.  
    if (unrecoverableFailure == null) {
  33.  
    unrecoverableFailure = e;
  34.  
    }
  35.  
    }
  36.  
    }
  37.  
    // If we encountered any unrecoverable failures, destroy all other sessions including
  38.  
    // the parent
  39.  
    if (unrecoverableFailure != null) {
  40.  
    // {@link #streamValidateAndCommit()} calls
  41.  
    // {@link #onSessionVerificationFailure(PackageManagerException)}, but we don't
  42.  
    // expect it to ever do so for parent sessions. Call that on this parent to clean
  43.  
    // it up and notify listeners of the error.
  44.  
    onSessionVerificationFailure(unrecoverableFailure);
  45.  
    // fail other child sessions that did not already fail
  46.  
    for (int i = nonFailingSessions.size() - 1; i >= 0; --i) {
  47.  
    PackageInstallerSession session = nonFailingSessions.get(i);
  48.  
    session.onSessionVerificationFailure(unrecoverableFailure);
  49.  
    }
  50.  
    }
  51.  
    }
  52.  
     
  53.  
    if (!allSessionsReady) {
  54.  
    return;
  55.  
    }
  56.  
     
  57.  
    mHandler.obtainMessage(MSG_INSTALL).sendToTarget();
  58.  
    }
学新通
  1.  
    private void handleInstall() {
  2.  
    if (isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked()) {
  3.  
    DevicePolicyEventLogger
  4.  
    .createEvent(DevicePolicyEnums.INSTALL_PACKAGE)
  5.  
    .setAdmin(mInstallSource.installerPackageName)
  6.  
    .write();
  7.  
    }
  8.  
    if (params.isStaged) {
  9.  
    mStagingManager.commitSession(this);
  10.  
    destroyInternal();
  11.  
    dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "Session staged", null);
  12.  
    return;
  13.  
    }
  14.  
     
  15.  
    if (isApexInstallation()) {
  16.  
    destroyInternal();
  17.  
    dispatchSessionFinished(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
  18.  
    "APEX packages can only be installed using staged sessions.", null);
  19.  
    return;
  20.  
    }
  21.  
     
  22.  
    // For a multiPackage session, read the child sessions
  23.  
    // outside of the lock, because reading the child
  24.  
    // sessions with the lock held could lead to deadlock
  25.  
    // (b/123391593).
  26.  
    List<PackageInstallerSession> childSessions = getChildSessionsNotLocked();
  27.  
     
  28.  
    try {
  29.  
    synchronized (mLock) {
  30.  
    installNonStagedLocked(childSessions);
  31.  
    }
  32.  
    } catch (PackageManagerException e) {
  33.  
    final String completeMsg = ExceptionUtils.getCompleteMessage(e);
  34.  
    Slog.e(TAG, "Commit of session " sessionId " failed: " completeMsg);
  35.  
    destroyInternal();
  36.  
    dispatchSessionFinished(e.error, completeMsg, null);
  37.  
    }
  38.  
    }
学新通
  1.  
    @GuardedBy("mLock")
  2.  
    private void installNonStagedLocked(List<PackageInstallerSession> childSessions)
  3.  
    throws PackageManagerException {
  4.  
    final PackageManagerService.ActiveInstallSession installingSession =
  5.  
    makeSessionActiveLocked();
  6.  
    if (installingSession == null) {
  7.  
    return;
  8.  
    }
  9.  
    if (isMultiPackage()) {
  10.  
    List<PackageManagerService.ActiveInstallSession> installingChildSessions =
  11.  
    new ArrayList<>(childSessions.size());
  12.  
    boolean success = true;
  13.  
    PackageManagerException failure = null;
  14.  
    for (int i = 0; i < childSessions.size(); i) {
  15.  
    final PackageInstallerSession session = childSessions.get(i);
  16.  
    try {
  17.  
    final PackageManagerService.ActiveInstallSession installingChildSession =
  18.  
    session.makeSessionActiveLocked();
  19.  
    if (installingChildSession != null) {
  20.  
    installingChildSessions.add(installingChildSession);
  21.  
    }
  22.  
    } catch (PackageManagerException e) {
  23.  
    failure = e;
  24.  
    success = false;
  25.  
    }
  26.  
    }
  27.  
    if (!success) {
  28.  
    sendOnPackageInstalled(mContext, mRemoteStatusReceiver, sessionId,
  29.  
    isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId, null,
  30.  
    failure.error, failure.getLocalizedMessage(), null);
  31.  
    return;
  32.  
    }
  33.  
    mPm.installStage(installingChildSessions);
  34.  
    } else {
  35.  
    mPm.installStage(installingSession);
  36.  
    }
  37.  
    }
学新通

调用 mPm的installStage方法

private final PackageManagerService mPm;

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

  1.  
    void installStage(ActiveInstallSession activeInstallSession) {
  2.  
    if (DEBUG_INSTANT) {
  3.  
    if ((activeInstallSession.getSessionParams().installFlags
  4.  
    & PackageManager.INSTALL_INSTANT_APP) != 0) {
  5.  
    Slog.d(TAG, "Ephemeral install of " activeInstallSession.getPackageName());
  6.  
    }
  7.  
    }
  8.  
    final Message msg = mHandler.obtainMessage(INIT_COPY);
  9.  
    final InstallParams params = new InstallParams(activeInstallSession);
  10.  
    params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
  11.  
    msg.obj = params;
  12.  
     
  13.  
    Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStage",
  14.  
    System.identityHashCode(msg.obj));
  15.  
    Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
  16.  
    System.identityHashCode(msg.obj));
  17.  
     
  18.  
    mHandler.sendMessage(msg);
  19.  
    }
学新通

创建InstallParams,它对应于包的安装数据

  1.  
    void doHandleMessage(Message msg) {
  2.  
    switch (msg.what) {
  3.  
    case INIT_COPY: {
  4.  
    HandlerParams params = (HandlerParams) msg.obj;
  5.  
    if (params != null) {
  6.  
    if (DEBUG_INSTALL) Slog.i(TAG, "init_copy: " params);
  7.  
    Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
  8.  
    System.identityHashCode(params));
  9.  
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
  10.  
    params.startCopy();
  11.  
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
  12.  
    }
  13.  
    break;
  14.  
    }

params.startCopy();

params是HandlerParams类 

  1.  
    final void startCopy() {
  2.  
    if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " mUser ": " this);
  3.  
    handleStartCopy();
  4.  
    handleReturnCode();
  5.  
    }
  1.  
    abstract void handleStartCopy();
  2.  
    abstract void handleReturnCode();

具体实现在 InstallParams里 是PackageManagerService的内部类

    class InstallParams extends HandlerParams {

  1.  
    public void handleStartCopy() {
  2.  
    int ret = PackageManager.INSTALL_SUCCEEDED;
  3.  
     
  4.  
    // If we're already staged, we've firmly committed to an install location
  5.  
    if (origin.staged) {
  6.  
    if (origin.file != null) {
  7.  
    installFlags |= PackageManager.INSTALL_INTERNAL;
  8.  
    } else {
  9.  
    throw new IllegalStateException("Invalid stage location");
  10.  
    }
  11.  
    }
  12.  
    //确定APK的安装位置。 onInt:内部存储即Data分区,ephemeral:安装到临时存储(Instant Apps安装)
  13.  
    final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;
  14.  
    final boolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
  15.  
    PackageInfoLite pkgLite = null;
  16.  
     
  17.  
    //获取APK的少量的信息
  18.  
    pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,
  19.  
    origin.resolvedPath, installFlags, packageAbiOverride);
  20.  
     
  21.  
    if (DEBUG_INSTANT && ephemeral) {
  22.  
    Slog.v(TAG, "pkgLite for install: " pkgLite);
  23.  
    }
  24.  
     
  25.  
    /*
  26.  
    * If we have too little free space, try to free cache
  27.  
    * before giving up.
  28.  
    */
  29.  
    if (!origin.staged && pkgLite.recommendedInstallLocation
  30.  
    == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
  31.  
    // TODO: focus freeing disk space on the target device
  32.  
    final StorageManager storage = StorageManager.from(mContext);
  33.  
    final long lowThreshold = storage.getStorageLowBytes(
  34.  
    Environment.getDataDirectory());
  35.  
     
  36.  
    final long sizeBytes = PackageManagerServiceUtils.calculateInstalledSize(
  37.  
    origin.resolvedPath, packageAbiOverride);
  38.  
    if (sizeBytes >= 0) {
  39.  
    try {
  40.  
    mInstaller.freeCache(null, sizeBytes lowThreshold, 0, 0);
  41.  
    pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,
  42.  
    origin.resolvedPath, installFlags, packageAbiOverride);
  43.  
    } catch (InstallerException e) {
  44.  
    Slog.w(TAG, "Failed to free cache", e);
  45.  
    }
  46.  
    }
  47.  
     
  48.  
    /*
  49.  
    * The cache free must have deleted the file we downloaded to install.
  50.  
    *
  51.  
    * TODO: fix the "freeCache" call to not delete the file we care about.
  52.  
    */
  53.  
    if (pkgLite.recommendedInstallLocation
  54.  
    == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
  55.  
    pkgLite.recommendedInstallLocation
  56.  
    = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
  57.  
    }
  58.  
    }
  59.  
     
  60.  
     
  61.  
    if (ret == PackageManager.INSTALL_SUCCEEDED) {
  62.  
    //判断安装的位置
  63.  
    int loc = pkgLite.recommendedInstallLocation;
  64.  
    if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
  65.  
    ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
  66.  
    } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
  67.  
    ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
  68.  
    } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
  69.  
    ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
  70.  
    } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
  71.  
    ret = PackageManager.INSTALL_FAILED_INVALID_APK;
  72.  
    } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
  73.  
    ret = PackageManager.INSTALL_FAILED_INVALID_URI;
  74.  
    } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
  75.  
    ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
  76.  
    } else {
  77.  
    // Override with defaults if needed.
  78.  
    loc = installLocationPolicy(pkgLite);
  79.  
    if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
  80.  
    ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
  81.  
    } else if (loc == PackageHelper.RECOMMEND_FAILED_WRONG_INSTALLED_VERSION) {
  82.  
    ret = PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION;
  83.  
    } else if (!onInt) {
  84.  
    // Override install location with flags
  85.  
    if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
  86.  
    // Set the flag to install on external media.
  87.  
    installFlags &= ~PackageManager.INSTALL_INTERNAL;
  88.  
    } else if (loc == PackageHelper.RECOMMEND_INSTALL_EPHEMERAL) {
  89.  
    if (DEBUG_INSTANT) {
  90.  
    Slog.v(TAG, "...setting INSTALL_EPHEMERAL install flag");
  91.  
    }
  92.  
    installFlags |= PackageManager.INSTALL_INSTANT_APP;
  93.  
    installFlags &= ~PackageManager.INSTALL_INTERNAL;
  94.  
    } else {
  95.  
    // Make sure the flag for installing on external
  96.  
    // media is unset
  97.  
    installFlags |= PackageManager.INSTALL_INTERNAL;
  98.  
    }
  99.  
    }
  100.  
    }
  101.  
    }
  102.  
    //根据InstallParams创建InstallArgs对象
  103.  
    final InstallArgs args = createInstallArgs(this);
  104.  
    mVerificationCompleted = true;
  105.  
    mIntegrityVerificationCompleted = true;
  106.  
    mEnableRollbackCompleted = true;
  107.  
    mArgs = args;
  108.  
     
  109.  
    if (ret == PackageManager.INSTALL_SUCCEEDED) {
  110.  
    final int verificationId = mPendingVerificationToken ;
  111.  
     
  112.  
    // Perform package verification (unless we are simply moving the package).
  113.  
    if (!origin.existing) {
  114.  
    PackageVerificationState verificationState =
  115.  
    new PackageVerificationState(this);
  116.  
    mPendingVerification.append(verificationId, verificationState);
  117.  
     
  118.  
    sendIntegrityVerificationRequest(verificationId, pkgLite, verificationState);
  119.  
    ret = sendPackageVerificationRequest(
  120.  
    verificationId, pkgLite, verificationState);
  121.  
     
  122.  
    // If both verifications are skipped, we should remove the state.
  123.  
    if (verificationState.areAllVerificationsComplete()) {
  124.  
    mPendingVerification.remove(verificationId);
  125.  
    }
  126.  
    }
  127.  
     
  128.  
     
  129.  
    if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
  130.  
    // TODO(ruhler) b/112431924: Don't do this in case of 'move'?
  131.  
    final int enableRollbackToken = mPendingEnableRollbackToken ;
  132.  
    Trace.asyncTraceBegin(
  133.  
    TRACE_TAG_PACKAGE_MANAGER, "enable_rollback", enableRollbackToken);
  134.  
    mPendingEnableRollback.append(enableRollbackToken, this);
  135.  
     
  136.  
    Intent enableRollbackIntent = new Intent(Intent.ACTION_PACKAGE_ENABLE_ROLLBACK);
  137.  
    enableRollbackIntent.putExtra(
  138.  
    PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN,
  139.  
    enableRollbackToken);
  140.  
    enableRollbackIntent.putExtra(
  141.  
    PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_SESSION_ID,
  142.  
    mSessionId);
  143.  
    enableRollbackIntent.setType(PACKAGE_MIME_TYPE);
  144.  
    enableRollbackIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
  145.  
     
  146.  
    // Allow the broadcast to be sent before boot complete.
  147.  
    // This is needed when committing the apk part of a staged
  148.  
    // session in early boot. The rollback manager registers
  149.  
    // its receiver early enough during the boot process that
  150.  
    // it will not miss the broadcast.
  151.  
    enableRollbackIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
  152.  
     
  153.  
    mContext.sendOrderedBroadcastAsUser(enableRollbackIntent, UserHandle.SYSTEM,
  154.  
    android.Manifest.permission.PACKAGE_ROLLBACK_AGENT,
  155.  
    new BroadcastReceiver() {
  156.  
    @Override
  157.  
    public void onReceive(Context context, Intent intent) {
  158.  
    // the duration to wait for rollback to be enabled, in millis
  159.  
    long rollbackTimeout = DeviceConfig.getLong(
  160.  
    DeviceConfig.NAMESPACE_ROLLBACK,
  161.  
    PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
  162.  
    DEFAULT_ENABLE_ROLLBACK_TIMEOUT_MILLIS);
  163.  
    if (rollbackTimeout < 0) {
  164.  
    rollbackTimeout = DEFAULT_ENABLE_ROLLBACK_TIMEOUT_MILLIS;
  165.  
    }
  166.  
    final Message msg = mHandler.obtainMessage(
  167.  
    ENABLE_ROLLBACK_TIMEOUT);
  168.  
    msg.arg1 = enableRollbackToken;
  169.  
    msg.arg2 = mSessionId;
  170.  
    mHandler.sendMessageDelayed(msg, rollbackTimeout);
  171.  
    }
  172.  
    }, null, 0, null, null);
  173.  
     
  174.  
    mEnableRollbackCompleted = false;
  175.  
    }
  176.  
    }
  177.  
     
  178.  
    mRet = ret;
  179.  
    }
学新通

 InstallArgs 是一个抽象类,定义了APK的安装逻辑,比如复制和重命名APK等,

其中FileInstallArgs用于处理安装到非ASEC的存储空间的APK,也就是内部存储空间(Data分区)

MoveInstallArgs用于处理已安装APK的移动的逻辑。

  1.  
    static abstract class InstallArgs {
  2.  
     
  3.  
     
  4.  
    class FileInstallArgs extends InstallArgs {
  5.  
    class MoveInstallArgs extends InstallArgs {
  1.  
    @Override
  2.  
    void handleReturnCode() {
  3.  
    if (mVerificationCompleted
  4.  
    && mIntegrityVerificationCompleted && mEnableRollbackCompleted) {
  5.  
    if ((installFlags & PackageManager.INSTALL_DRY_RUN) != 0) {
  6.  
    String packageName = "";
  7.  
    ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite(
  8.  
    new ParseTypeImpl(
  9.  
    (changeId, packageName1, targetSdkVersion) -> {
  10.  
    ApplicationInfo appInfo = new ApplicationInfo();
  11.  
    appInfo.packageName = packageName1;
  12.  
    appInfo.targetSdkVersion = targetSdkVersion;
  13.  
    return mPackageParserCallback.isChangeEnabled(changeId,
  14.  
    appInfo);
  15.  
    }).reset(),
  16.  
    origin.file, 0);
  17.  
    if (result.isError()) {
  18.  
    Slog.e(TAG, "Can't parse package at " origin.file.getAbsolutePath(),
  19.  
    result.getException());
  20.  
    } else {
  21.  
    packageName = result.getResult().packageName;
  22.  
    }
  23.  
    try {
  24.  
    observer.onPackageInstalled(packageName, mRet, "Dry run", new Bundle());
  25.  
    } catch (RemoteException e) {
  26.  
    Slog.i(TAG, "Observer no longer exists.");
  27.  
    }
  28.  
    return;
  29.  
    }
  30.  
    if (mRet == PackageManager.INSTALL_SUCCEEDED) {
  31.  
    mRet = mArgs.copyApk();
  32.  
    }
  33.  
    processPendingInstall(mArgs, mRet);
  34.  
    }
  35.  
    }
学新通

mArgs.copyApk();

private InstallArgs mArgs;

  1.  
    int copyApk() {
  2.  
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
  3.  
    try {
  4.  
    return doCopyApk();
  5.  
    } finally {
  6.  
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
  7.  
    }
  8.  
    }
  9.  
     
  10.  
    private int doCopyApk() {
  11.  
    if (origin.staged) {
  12.  
    if (DEBUG_INSTALL) Slog.d(TAG, origin.file " already staged; skipping copy");
  13.  
    codeFile = origin.file;
  14.  
    resourceFile = origin.file;
  15.  
    return PackageManager.INSTALL_SUCCEEDED;
  16.  
    }
  17.  
     
  18.  
    try {
  19.  
    final boolean isEphemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
  20.  
    //创建临时文件存储目录
  21.  
    final File tempDir =
  22.  
    mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral);
  23.  
    codeFile = tempDir;
  24.  
    resourceFile = tempDir;
  25.  
    } catch (IOException e) {
  26.  
    Slog.w(TAG, "Failed to create copy file: " e);
  27.  
    return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
  28.  
    }
  29.  
    将APK复制到临时存储目录
  30.  
    int ret = PackageManagerServiceUtils.copyPackage(
  31.  
    origin.file.getAbsolutePath(), codeFile);
  32.  
    if (ret != PackageManager.INSTALL_SUCCEEDED) {
  33.  
    Slog.e(TAG, "Failed to copy package");
  34.  
    return ret;
  35.  
    }
  36.  
     
  37.  
    final boolean isIncremental = isIncrementalPath(codeFile.getAbsolutePath());
  38.  
    final File libraryRoot = new File(codeFile, LIB_DIR_NAME);
  39.  
    NativeLibraryHelper.Handle handle = null;
  40.  
    try {
  41.  
    handle = NativeLibraryHelper.Handle.create(codeFile);
  42.  
    ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
  43.  
    abiOverride, isIncremental);
  44.  
    } catch (IOException e) {
  45.  
    Slog.e(TAG, "Copying native libraries failed", e);
  46.  
    ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
  47.  
    } finally {
  48.  
    IoUtils.closeQuietly(handle);
  49.  
    }
  50.  
     
  51.  
    return ret;
  52.  
    }
学新通

 processPendingInstall(mArgs, mRet);

  1.  
    private void processPendingInstall(final InstallArgs args, final int currentStatus) {
  2.  
    if (args.mMultiPackageInstallParams != null) {
  3.  
    args.mMultiPackageInstallParams.tryProcessInstallRequest(args, currentStatus);
  4.  
    } else {
  5.  
    PackageInstalledInfo res = createPackageInstalledInfo(currentStatus);
  6.  
    processInstallRequestsAsync(
  7.  
    res.returnCode == PackageManager.INSTALL_SUCCEEDED,
  8.  
    Collections.singletonList(new InstallRequest(args, res)));
  9.  
    }
  10.  
    }
  1.  
    // Queue up an async operation since the package installation may take a little while.
  2.  
    private void processInstallRequestsAsync(boolean success,
  3.  
    List<InstallRequest> installRequests) {
  4.  
    mHandler.post(() -> {
  5.  
    if (success) {
  6.  
    for (InstallRequest request : installRequests) {
  7.  
    安装前
  8.  
    request.args.doPreInstall(request.installResult.returnCode);
  9.  
    }
  10.  
    synchronized (mInstallLock) {
  11.  
    安装中
  12.  
    installPackagesTracedLI(installRequests);
  13.  
    }
  14.  
    for (InstallRequest request : installRequests) {
  15.  
    安装后
  16.  
    request.args.doPostInstall(
  17.  
    request.installResult.returnCode, request.installResult.uid);
  18.  
    }
  19.  
    }
  20.  
    for (InstallRequest request : installRequests) {
  21.  
    restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult,
  22.  
    new PostInstallData(request.args, request.installResult, null));
  23.  
    }
  24.  
    });
  25.  
    }
学新通
  1.  
    private PackageInstalledInfo createPackageInstalledInfo(
  2.  
    int currentStatus) {
  3.  
    PackageInstalledInfo res = new PackageInstalledInfo();
  4.  
    res.setReturnCode(currentStatus);
  5.  
    res.uid = -1;
  6.  
    res.pkg = null;
  7.  
    res.removedInfo = null;
  8.  
    return res;
  9.  
    }
  1.  
        @GuardedBy({"mInstallLock", "mLock"})
  2.  
        private void installPackagesTracedLI(List<InstallRequest> requests) {
  3.  
            try {
  4.  
                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
  5.  
                installPackagesLI(requests);
  6.  
            } finally {
  7.  
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
  8.  
            }
  9.  
        }
  1.  
    private void installPackagesLI(List<InstallRequest> requests) {
  2.  
    final Map<String, ScanResult> preparedScans = new ArrayMap<>(requests.size());
  3.  
    final Map<String, InstallArgs> installArgs = new ArrayMap<>(requests.size());
  4.  
    final Map<String, PackageInstalledInfo> installResults = new ArrayMap<>(requests.size());
  5.  
    final Map<String, PrepareResult> prepareResults = new ArrayMap<>(requests.size());
  6.  
    final Map<String, VersionInfo> versionInfos = new ArrayMap<>(requests.size());
  7.  
    final Map<String, PackageSetting> lastStaticSharedLibSettings =
  8.  
    new ArrayMap<>(requests.size());
  9.  
    final Map<String, Boolean> createdAppId = new ArrayMap<>(requests.size());
  10.  
    boolean success = false;
  11.  
    try {
  12.  
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI");
  13.  
    for (InstallRequest request : requests) {
  14.  
    // TODO(b/109941548): remove this once we've pulled everything from it and into
  15.  
    // scan, reconcile or commit.
  16.  
    final PrepareResult prepareResult;
  17.  
    try {
  18.  
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage");
  19.  
    prepareResult =
  20.  
    preparePackageLI(request.args, request.installResult);
  21.  
    } catch (PrepareFailure prepareFailure) {
  22.  
    request.installResult.setError(prepareFailure.error,
  23.  
    prepareFailure.getMessage());
  24.  
    request.installResult.origPackage = prepareFailure.conflictingPackage;
  25.  
    request.installResult.origPermission = prepareFailure.conflictingPermission;
  26.  
    return;
  27.  
    } finally {
  28.  
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
  29.  
    }
  30.  
    request.installResult.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
  31.  
    request.installResult.installerPackageName =
  32.  
    request.args.installSource.installerPackageName;
  33.  
     
  34.  
    final String packageName = prepareResult.packageToScan.getPackageName();
  35.  
    prepareResults.put(packageName, prepareResult);
  36.  
    installResults.put(packageName, request.installResult);
  37.  
    installArgs.put(packageName, request.args);
  38.  
    try {
  39.  
    final ScanResult result = scanPackageTracedLI(
  40.  
    prepareResult.packageToScan, prepareResult.parseFlags,
  41.  
    prepareResult.scanFlags, System.currentTimeMillis(),
  42.  
    request.args.user, request.args.abiOverride);
  43.  
    if (null != preparedScans.put(result.pkgSetting.pkg.getPackageName(), result)) {
  44.  
    request.installResult.setError(
  45.  
    PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE,
  46.  
    "Duplicate package " result.pkgSetting.pkg.getPackageName()
  47.  
    " in multi-package install request.");
  48.  
    return;
  49.  
    }
  50.  
    createdAppId.put(packageName, optimisticallyRegisterAppId(result));
  51.  
    versionInfos.put(result.pkgSetting.pkg.getPackageName(),
  52.  
    getSettingsVersionForPackage(result.pkgSetting.pkg));
  53.  
    if (result.staticSharedLibraryInfo != null) {
  54.  
    final PackageSetting sharedLibLatestVersionSetting =
  55.  
    getSharedLibLatestVersionSetting(result);
  56.  
    if (sharedLibLatestVersionSetting != null) {
  57.  
    lastStaticSharedLibSettings.put(result.pkgSetting.pkg.getPackageName(),
  58.  
    sharedLibLatestVersionSetting);
  59.  
    }
  60.  
    }
  61.  
    } catch (PackageManagerException e) {
  62.  
    request.installResult.setError("Scanning Failed.", e);
  63.  
    return;
  64.  
    }
  65.  
    }
  66.  
    ReconcileRequest reconcileRequest = new ReconcileRequest(preparedScans, installArgs,
  67.  
    installResults,
  68.  
    prepareResults,
  69.  
    mSharedLibraries,
  70.  
    Collections.unmodifiableMap(mPackages), versionInfos,
  71.  
    lastStaticSharedLibSettings);
  72.  
    CommitRequest commitRequest = null;
  73.  
    synchronized (mLock) {
  74.  
    Map<String, ReconciledPackage> reconciledPackages;
  75.  
    try {
  76.  
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
  77.  
    reconciledPackages = reconcilePackagesLocked(
  78.  
    reconcileRequest, mSettings.mKeySetManagerService);
  79.  
    } catch (ReconcileFailure e) {
  80.  
    for (InstallRequest request : requests) {
  81.  
    request.installResult.setError("Reconciliation failed...", e);
  82.  
    }
  83.  
    return;
  84.  
    } finally {
  85.  
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
  86.  
    }
  87.  
    try {
  88.  
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "commitPackages");
  89.  
    commitRequest = new CommitRequest(reconciledPackages,
  90.  
    mUserManager.getUserIds());
  91.  
    commitPackagesLocked(commitRequest);
  92.  
    success = true;
  93.  
    } finally {
  94.  
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
  95.  
    }
  96.  
    }
  97.  
    executePostCommitSteps(commitRequest);
  98.  
    } finally {
  99.  
    if (success) {
  100.  
    for (InstallRequest request : requests) {
  101.  
    final InstallArgs args = request.args;
  102.  
    if (args.mDataLoaderType != DataLoaderType.INCREMENTAL) {
  103.  
    continue;
  104.  
    }
  105.  
    if (args.signingDetails.signatureSchemeVersion != SIGNING_BLOCK_V4) {
  106.  
    continue;
  107.  
    }
  108.  
    // For incremental installs, we bypass the verifier prior to install. Now
  109.  
    // that we know the package is valid, send a notice to the verifier with
  110.  
    // the root hash of the base.apk.
  111.  
    final String baseCodePath = request.installResult.pkg.getBaseCodePath();
  112.  
    final String[] splitCodePaths = request.installResult.pkg.getSplitCodePaths();
  113.  
    final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
  114.  
    final int verificationId = mPendingVerificationToken ;
  115.  
    final String rootHashString = PackageManagerServiceUtils
  116.  
    .buildVerificationRootHashString(baseCodePath, splitCodePaths);
  117.  
    broadcastPackageVerified(verificationId, originUri,
  118.  
    PackageManager.VERIFICATION_ALLOW, rootHashString,
  119.  
    args.mDataLoaderType, args.getUser());
  120.  
    }
  121.  
    } else {
  122.  
    for (ScanResult result : preparedScans.values()) {
  123.  
    if (createdAppId.getOrDefault(result.request.parsedPackage.getPackageName(),
  124.  
    false)) {
  125.  
    cleanUpAppIdCreation(result);
  126.  
    }
  127.  
    }
  128.  
    // TODO(patb): create a more descriptive reason than unknown in future release
  129.  
    // mark all non-failure installs as UNKNOWN so we do not treat them as success
  130.  
    for (InstallRequest request : requests) {
  131.  
    if (request.installResult.freezer != null) {
  132.  
    request.installResult.freezer.close();
  133.  
    }
  134.  
    if (request.installResult.returnCode == PackageManager.INSTALL_SUCCEEDED) {
  135.  
    request.installResult.returnCode = PackageManager.INSTALL_UNKNOWN;
  136.  
    }
  137.  
    }
  138.  
    }
  139.  
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
  140.  
    }
  141.  
    }
学新通

executePostCommitSteps执行安装

installPackageLI方法的代码有将近500行,这里截取主要的部分,主要做了几件事:

  1. 创建PackageParser解析APK。
  2. 检查APK是否存在,如果存在就获取此前没被改名前的包名并在注释1处赋值给PackageParser.Package类型的pkg,在注释3处将标志位replace置为true表示是替换安装。
  3. 注释3处,如果Settings中保存有要安装的APK的信息,说明此前安装过该APK,则需要校验APK的签名信息,确保安全的进行替换。
  4. 在注释4处将临时文件重新命名,比如前面提到的/data/app/vmdl18300388.tmp/base.apk,重命名为/data/app/包名-1/base.apk。这个新命名的包名会带上一个数字后缀1,每次升级一个已有的App,这个数字会不断的累加。
  5. 系统APP的更新安装会有两个限制,一个是系统APP不能在SD卡上替换安装,另一个是系统APP不能被Instant App替换。
  6. 注释5处根据replace来做区分,如果是替换安装就会调用replacePackageLIF方法,其方法内部还会对系统APP和非系统APP进行区分处理,如果是新安装APK会调用installNewPackageLIF方法。

installNewPackageLIF主要做了以下3件事:

  1. 扫描APK,将APK的信息存储在PackageParser.Package类型的newPackage中,一个Package的信息包含了1个base APK以及0个或者多个split APK。
  2. 更新该APK对应的Settings信息,Settings用于保存所有包的动态设置。
  3. 如果安装成功就为新安装的应用程序准备数据,安装失败就删除APK。

安装APK的过程就讲到这里,就不再往下分析下去,有兴趣的同学可以接着深挖。

**4.总结 **

本文主要讲解了PMS是如何处理APK安装的,主要有几个步骤:

  1. PackageInstaller安装APK时会将APK的信息交由PMS处理,PMS通过向PackageHandler发送消息来驱动APK的复制和安装工作。
  2. PMS发送INIT_COPY和MCS_BOUND类型的消息,控制PackageHandler来绑定DefaultContainerService,完成复制APK等工作。
  3. 复制APK完成后,会开始进行安装APK的流程,包括安装前的检查、安装APK和安装后的收尾工作。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgejcef
系列文章
更多 icon
同类精品
更多 icon
继续加载