Android PackageManagerService(三)pm命令安装流程详解

关于pm命令安装,其copy过程与下载安装不同,但安装过程却与下载过程是相同的,这里不做重复分析。

拷贝过程流程图

 pm的入口在com.android.commands.pm.Pm类,那么这是如何调用到这个类的呢,这是adb命令通过adbd守护进程调用到/system/bin/pm这个脚本,其脚本源码如下:

base=/system
export CLASSPATh-$base/framework/pm.jar
exec app_process $base/bin.com.android.commands.pm.Pm "$@"

Pm类通过脚本启动,执行顺序是main->run->runInstall,然后提交session。

public static void main(String[] args) {
        int exitCode = 1;
        try {
            exitCode = new Pm().run(args);
        } catch (Exception e) {
            Log.e(TAG, "Error", e);
            System.err.println("Error: " + e);
            if (e instanceof RemoteException) {
                System.err.println(PM_NOT_RUNNING_ERR);
            }
        }
        System.exit(exitCode);
}
 public int run(String[] args) throws RemoteException {
	boolean validCommand = false;
	if (args.length < 1) {
		return showUsage();
	}
	mAm = IAccountManager.Stub.asInterface(ServiceManager.getService(Context.ACCOUNT_SERVICE));
	mUm = IUserManager.Stub.asInterface(ServiceManager.getService(Context.USER_SERVICE));
	mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));

	if (mPm == null) {
		System.err.println(PM_NOT_RUNNING_ERR);
		return 1;
	}
	mInstaller = mPm.getPackageInstaller();

	mArgs = args;
	String op = args[0];
	mNextArg = 1;

	//......
	//安装
	if ("install".equals(op)) {
		return runInstall();
	}

	if ("uninstall".equals(op)) {
		return runUninstall();
	}
	//.....
}

Pm.runInstall中首先是创建session,然后提交session,代码如下。

 private int runInstall() throws RemoteException {
	long startedTime = SystemClock.elapsedRealtime();
	//创建安装参数
	final InstallParams params = makeInstallParams();
	//app路径
	final String inPath = nextArg();

	if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) {
		File file = new File(inPath);
		if (file.isFile()) {
			try {
				//轻量级解析
				ApkLite baseApk = PackageParser.parseApkLite(file, 0);
				PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null,
						null, null);
						
				params.sessionParams.setSize(
						PackageHelper.calculateInstalledSize(pkgLite, false,
						params.sessionParams.abiOverride));
			} catch (PackageParserException | IOException e) {
				System.err.println("Error: Failed to parse APK file: " + e);
				return 1;
			}
		} else {
			System.err.println("Error: Can't open non-file: " + inPath);
			return 1;
		}
	}
	//创建一个session id
	final int sessionId = doCreateSession(params.sessionParams,
			params.installerPackageName, params.userId);

	try {
		//copy文件
		if (doWriteSession(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
				false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
			return 1;
		}
		//提交session
		Pair<String, Integer> status = doCommitSession(sessionId, false /*logSuccess*/);
		if (status.second != PackageInstaller.STATUS_SUCCESS) {
			return 1;
		}
		return 0;
	} finally {
		try {
			mInstaller.abandonSession(sessionId);
		} catch (Exception ignore) {
		}
	}
}

接下来看doCommitSession,根据id创建PackageInstallerSession的客户端调用commit

//PM.commit
private Pair<String, Integer> doCommitSession(int sessionId, boolean logSuccess)
		throws RemoteException {
	PackageInstaller.Session session = null;
	try {
        //根据session id  创建session
		session = new PackageInstaller.Session(
				mInstaller.openSession(sessionId));

		final LocalIntentReceiver receiver = new LocalIntentReceiver();
        //跨进程提交会调用PackageInstallerSession.commit
		session.commit(receiver.getIntentSender());

		final Intent result = receiver.getResult();
		final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
				PackageInstaller.STATUS_FAILURE);
        
		return new Pair<>(result.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME), status);
	} finally {
		IoUtils.closeQuietly(session);
	}
}

 commit 内部发一个消息,然后调用commitLocked

//PackageInstallerSession.commit
@Override
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
	Preconditions.checkNotNull(statusReceiver);

	final boolean wasSealed;
	synchronized (mLock) {
		//.....

		mCommitted = true;
		mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
	}

}

private final Handler.Callback mHandlerCallback = new Handler.Callback() {
	@Override
	public boolean handleMessage(Message msg) {
		switch (msg.what) {
			case MSG_COMMIT:
				synchronized (mLock) {
					try {
						//内部调用commitLocked
						commitLocked();
					} catch (PackageManagerException e) {
						final String completeMsg = ExceptionUtils.getCompleteMessage(e);
						destroyInternal();
						dispatchSessionFinished(e.error, completeMsg, null);
					}
				}

				break;
		}

		return true;
	}

//PackageInstallerSession.commitLocked
private void commitLocked()
		throws PackageManagerException {


	// Unpack native libraries
	extractNativeLibraries(mResolvedStageDir, params.abiOverride);

	// Container is ready to go, let's seal it up!
	if (stageCid != null) {
		finalizeAndFixContainer(stageCid);
	}
	//.......
	mRelinquished = true;
	//调用PMS的installStage
	mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params,
			mInstallerPackageName, mInstallerUid, user, mCertificates);
}

回到了PMS.installStage

void installStage(String packageName, File stagedDir, String stagedCid,
		IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
		String installerPackageName, int installerUid, UserHandle user,
		Certificate[][] certificates) {
	
	final VerificationInfo verificationInfo = new VerificationInfo(
			sessionParams.originatingUri, sessionParams.referrerUri,
			sessionParams.originatingUid, installerUid);

	final OriginInfo origin;
	if (stagedDir != null) {
		origin = OriginInfo.fromStagedFile(stagedDir);
	} else {
		origin = OriginInfo.fromStagedContainer(stagedCid);
	}

	final Message msg = mHandler.obtainMessage(INIT_COPY);
	final int installReason = fixUpInstallReason(installerPackageName, installerUid,
			sessionParams.installReason);
	final InstallParams params = new InstallParams(origin, null, observer,
			sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
			verificationInfo, user, sessionParams.abiOverride,
			sessionParams.grantedRuntimePermissions, certificates, installReason);
	params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
	msg.obj = params;

	//发送INIT_COPY
	mHandler.sendMessage(msg);
}

发送完Handler消息后就与下载安装过程相同了。请参考:Android PackageManagerService(二)下载安装详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

BFP_BSP

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

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

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

打赏作者

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

抵扣说明:

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

余额充值