Android PackageManagerService(四)本地安装流程详解

本地安装参与对象包括PackageInstaller应用,PMS两部分。下面我们就来分析下PackageInstaller是如何调用到PMS中的。函数调用时序图示。

点击文件管理器里面app文件会启动 PackageInstaller的InstallStart这个activity

protected void onCreate(@Nullable Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	
	Intent nextActivity = new Intent(intent);
	nextActivity.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);

	nextActivity.putExtra(PackageInstallerActivity.EXTRA_CALLING_PACKAGE, callingPackage);
	nextActivity.putExtra(PackageInstallerActivity.EXTRA_ORIGINAL_SOURCE_INFO, sourceInfo);
	nextActivity.putExtra(Intent.EXTRA_ORIGINATING_UID, originatingUid);

	if (isSessionInstall) {
		Uri packageUri = intent.getData();

		if (packageUri != null && (packageUri.getScheme().equals(ContentResolver.SCHEME_FILE)
				|| packageUri.getScheme().equals(ContentResolver.SCHEME_CONTENT))) {
			// Copy file to prevent it from being changed underneath this process
			nextActivity.setClass(this, InstallStaging.class);
		} 
	}

	if (nextActivity != null) {
		startActivity(nextActivity);
	}
	finish();
}

内部启动 InstallStaging这个 activity,然后在内部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 {
				mStagedFile = TemporaryFileManager.getStagedFile(this);
			} catch (IOException e) {
				showError();
				return;
			}
		}

		mStagingTask = new StagingAsyncTask();
		mStagingTask.execute(getIntent().getData());
	}
}

然后在任务的onPostExecute方法启动PackageInstallerActivity这个activity 

@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, PackageInstallerActivity.class);
		installIntent.setData(Uri.fromFile(mStagedFile));
		installIntent
				.setFlags(installIntent.getFlags() & ~Intent.FLAG_ACTIVITY_FORWARD_RESULT);
		installIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
		startActivityForResult(installIntent, 0);
	} else {
		showError();
	}
}

然后点击安装按钮调用startInstall

 public void onClick(View v) {
        if (v == mOk) {
            if (mOk.isEnabled()) {
                if (mOkCanInstall || mScrollView == null) {
                    if (mSessionId != -1) {
                        mInstaller.setPermissionsResult(mSessionId, true);
                        finish();
                    } else {
                        startInstall();
                    }
                } else {
                    mScrollView.pageScroll(View.FOCUS_DOWN);
                }
            }
        } else if (v == mCancel) {
            // Cancel and finish
            setResult(RESULT_CANCELED);
            if (mSessionId != -1) {
                mInstaller.setPermissionsResult(mSessionId, false);
            }
            finish();
        }
    }

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();
    }

之后启动InstallInstalling,因为Activity中的默认成员方法的执行顺序是onCreate->onStart->onResume...其中onCreate的方法中主要过程包括:

  • 1 获取待安装应用信息
  • 2 根据应用安装与否决定如何调用方法
  • 3 如果已存在,则直接调用PackageManager.installExistingPackage
  • 4 如果不存在则构造session
  • 5 之后则为安装事件广播添加一个监测
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.install_installing);
    // 获取待安装应用信息
    ApplicationInfo appInfo = getIntent()
            .getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
    mPackageURI = getIntent().getData();
    // 如果应用已存在,则使用这条路径安装
    if ("package".equals(mPackageURI.getScheme())) {
        try {
            getPackageManager().installExistingPackage(appInfo.packageName);
            launchSuccess();
        } catch (PackageManager.NameNotFoundException e) {
            launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
        }
    } else { //否则使用session提交安装应用
        final File sourceFile = new File(mPackageURI.getPath());
        PackageUtil.initSnippetForNewApp(this, PackageUtil.getAppSnippet(this, appInfo,
                sourceFile), R.id.app_snippet);
        // 如果session已存在,则获取sessionId等数据
        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.addObserver(this, mInstallId,
                        this::launchFinishBasedOnResult);
            } catch (EventResultPersister.OutOfIdsException e) {
                // Does not happen
            }
        } else { // 否则创建session
            PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                    PackageInstaller.SessionParams.MODE_FULL_INSTALL);
            // ......
            try {
                mInstallId = InstallEventReceiver
                        .addObserver(this, EventResultPersister.GENERATE_NEW_ID,
                                this::launchFinishBasedOnResult);
            } catch (EventResultPersister.OutOfIdsException e) {
                launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
            }
            //创建session
            try {
                mSessionId = getPackageManager().getPackageInstaller().createSession(params);
            } catch (IOException e) {
                launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
            }
        }
        //......
        mSessionCallback = new InstallSessionCallback();

在这个activity里面启动一个任务,然后调用 session.commit(pendingIntent.getIntentSender());

protected void onPostExecute(PackageInstaller.Session session) {
            if (session != null) {
                Intent broadcastIntent = new Intent(BROADCAST_ACTION);
                broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                broadcastIntent.setPackage(
                        getPackageManager().getPermissionControllerPackageName());
                broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId);

                PendingIntent pendingIntent = PendingIntent.getBroadcast(
                        InstallInstalling.this,
                        mInstallId,
                        broadcastIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT);
                //提交session
                session.commit(pendingIntent.getIntentSender());
                mCancelButton.setEnabled(false);
                setFinishOnTouchOutside(false);
            } else {
                getPackageManager().getPackageInstaller().abandonSession(mSessionId);

                if (!isCancelled()) {
                    launchFailure(PackageManager.INSTALL_FAILED_INVALID_APK, null);
                }
            }
        }

 session对象传输顺序为:

  •  PackageInstaller.Session.commit
  •  IPackageInstallerSession.commit
  •  PackageInstallerSession.commit
  • 4Handler.Callback.handleMessage
  •  PackageInstallerSession.commitLock
  •  PMS.installStage

这里是不是似曾相识,这一步跟Adb安装提交session完全一样,之后就调用installStage方法完成安装。

具体参考Android PackageManagerService(三)adb安装流程详解

总结:其实安装的本质就是解析应用,主要是解析Android应用的清单文件,保存到PMS的内部数据结构供系统使用,保存重要信息到package.xml和package.list的配置文件。调用Installd守护进程创建应用数据目录,配置文件,转移dex文件到/data/dalvik-cache下面供虚拟机使用的工程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BFP_BSP

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值