android源码分析目录

一 概述

之前咱们介绍了 PMS 的作业原理。首要包含 PMS 的发动流程,和 PMS 发动时扫描装置使用,并获取四大组件信息的流程

今日咱们再来说说 PMS 的别的一个作业流程,那便是 PMS 装置 apk 的流程

首要,Android 的装置会经过一个 InstallStart 进行跳转,到达一个 PackageInstallerActivity

二 PackageInstallerActivity

2.1 onCreate

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);
	}
	// 获取 PackageManager
	mPm = getPackageManager();
	// 获取 IPackageManager
	mIpm = AppGlobals.getPackageManager();
	// 获取权限办理 AppOpsManager
	mAppOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
	// 经过 PackageManager 取得 PackageInstaller
	mInstaller = mPm.getPackageInstaller();
	// 获取 多用户体系办理用户的类 UserManager
	mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
	final Intent intent = getIntent();
	...
	// 装置包的 Uri
	final Uri packageUri;
	if (PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction())) {
		final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1);
		// 经过 mInstaller 获取一个 PackageInstaller.SessionInfo
		final PackageInstaller.SessionInfo info = mInstaller.getSessionInfo(sessionId);
		mSessionId = sessionId;
		packageUri = Uri.fromFile(new File(info.resolvedBaseCodePath));
		mOriginatingURI = null;
		mReferrerURI = null;
	}
	...
}

PackageInstallerActivity 的逻辑首要在onCreateonResume中,在 onCreate 中,首要是获取一个PackageInstaller.SessionInfo,并构造一个 Uri

2.2 onResume

protected void onResume() {
	super.onResume();
	if (mAppSnippet != null) {
		//  在咱们覆盖这个布局之前,加载假布局并禁用OK按钮
		bindUi();
		// 查看是否答应装置该软件包,假如答应就发动装置。假如不答应
	    // 则显现相应的对话框。
		checkIfAllowedAndInitiateInstall();
	}
	...
}

在 onResume 中,则进行了 UI 绑定,会展现咱们想要装置的 apk 的一些基本信息。

2.3 bindUi

bindUi 便是将咱们要装置的使用展现出来,并给用户弹窗挑选

private void bindUi() {
	// 展现要装置apk的根底信息
	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 {
						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);
	...
}

在装置界面展现使用的一些简介信息 mAppSnippet,假如用户挑选赞同,就开端装置 startInstall,否则就关闭页面。

2.4 startInstall

startInstall 的逻辑便是发动一个子 Activity 来实践装置使用程序,它便是 InstallInstalling

    private void startInstall() {
        Intent newIntent = new Intent();
        newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
                mPkgInfo.applicationInfo);
        newIntent.setData(mPackageURI);
        // 设置目标 Activity
        newIntent.setClass(this, InstallInstalling.class);
        String installerPackageName = getIntent().getStringExtra(
                Intent.EXTRA_INSTALLER_PACKAGE_NAME);
		... // 传参
        newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
        startActivity(newIntent);
        finish();
    }

三 InstallInstalling

InstallInstalling 装置使用有两个阶段

  1. 发送装置包给 PackageManager 并处理来自 PackageManager 的成果
  2. 处理成果回调,InstallSuccess 或 InstallFailed

3.1 onCreate

相同咱们从 onCreate 开端,

protected void onCreate(@Nullable Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	ApplicationInfo appInfo = getIntent()
			.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
	mPackageURI = getIntent().getData();
	// 经过 scheme 来判别当时的第一阶段仍是第二阶段
	if ("package".equals(mPackageURI.getScheme())) {
		try {
			// 假如是第二阶段,就跳转到处理成果的函数,成功或者失利
			getPackageManager().installExistingPackage(appInfo.packageName);
			launchSuccess();
		} catch (PackageManager.NameNotFoundException e) {
			launchFailure(PackageInstaller.STATUS_FAILURE,
					PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
		}
	} else {
		// 假如是第一阶段,就将装置包信息发送给 PackageManager
		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),
				...
				}, null);
		setupAlert();
		requireViewById(R.id.installing).setVisibility(View.VISIBLE);
		if (savedInstanceState != null) {
			mSessionId = savedInstanceState.getInt(SESSION_ID);
			mInstallId = savedInstanceState.getInt(INSTALL_ID);
			// 为成果注册观察者;假如成果被交付,或许会当即回调,同时
			// 活动被破坏
			try {
				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);
			final Uri referrerUri = getIntent().getParcelableExtra(Intent.EXTRA_REFERRER);
			... // 填充参数
			File file = new File(mPackageURI.getPath());
			...
			try {
				// 获取 PackageManager 的 PackageInstaller,拿到 PackageInstallerService
				// 发送装置参数
				mSessionId = getPackageManager().getPackageInstaller().createSession(params);
			} catch (IOException e) {
				launchFailure(PackageInstaller.STATUS_FAILURE,
						PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
			}
		}
		mCancelButton = mAlert.getButton(DialogInterface.BUTTON_NEGATIVE);
	}
}

在 onCreate 中有两个分支,进行装置仍是装置成功,

  • 假如是装置成功,就会发动 InstallSuccess (一个对应的 Activity)。
  • 进行装置就会进行参数填充

最终经过 getPackageManager().getPackageInstaller().createSession(params) 创立了一个 Session。

3.2 onResume

protected void onResume() {
	super.onResume();
	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);
		}
	}
}
  • InstallingAsyncTask
  • PackageInstallerService

四 InstallingAsyncTask

InstallingAsyncTask 承继自 AsyncTask,首要是将文件西悉尼写到 session,然后提交到 session。代码很长,咱们主重视主流程的提交即可。

private final class InstallingAsyncTask extends AsyncTask<Void, Void,
		PackageInstaller.Session> {
	volatile boolean isDone;
	@Override
	protected PackageInstaller.Session doInBackground(Void... params) {
		PackageInstaller.Session session;
		try {
			// 1. 经过 mSessionId 获取对应的 session
			session = getPackageManager().getPackageInstaller().openSession(mSessionId);
		} ...
		session.setStagingProgress(0);
		try {
			// 将文件信息写入 session
			...
			return session;
		}  ...
	}
	@Override
	protected void onPostExecute(PackageInstaller.Session session) {
		if (session != null) {
			// 提交 session
			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 | PendingIntent.FLAG_MUTABLE);
			// IPackageInstallerSession 其实便是 PackageInstallerService
			session.commit(pendingIntent.getIntentSender());
			mCancelButton.setEnabled(false);
			setFinishOnTouchOutside(false);
		} else {
			...
		}
	}
}

五 PackageInstallerService

5.1 createSession

[frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java]
public int createSession(SessionParams params, String installerPackageName,
		String callingAttributionTag, int userId) {
	try {
		return createSessionInternal(params, installerPackageName, callingAttributionTag,
				userId);
	} catch (IOException e) {
		throw ExceptionUtils.wrap(e);
	}
}

createSession 是创立一个体系仅有的 session,这个 session 表明一次装置过程,这样哪怕后续装置中断了,都可用凭仗这个 session 进行康复装置。

接下来咱们看看提交的逻辑。

六 PackageInstallerSession

6.1 commit

session 提交之后会经过大量的 Handler 转发,所以咱们找到它终究调用的 handleInstall

public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
	...
	dispatchSessionSealed();
}

6.2 dispatchSessionSealed

private void dispatchSessionSealed() {
	mHandler.obtainMessage(MSG_ON_SESSION_SEALED).sendToTarget();
}

6.3 handleSessionSealed

private void handleSessionSealed() {
	...
	dispatchStreamValidateAndCommit();
}

6.4 handleStreamValidateAndCommit

private void handleStreamValidateAndCommit() {
	try {
		// 发送消息 MSG_INSTALL
		if (allSessionsReady && streamValidateAndCommit()) {
			mHandler.obtainMessage(MSG_INSTALL).sendToTarget();
		}
	} catch (PackageManagerException e) {
		destroy();
		String msg = ExceptionUtils.getCompleteMessage(e);
		dispatchSessionFinished(e.error, msg, null);
		maybeFinishChildSessions(e.error, msg);
	}
}

6.5 handleInstall

private void handleInstall() {
	/**
	 * 假如一个Session 需求用户操作,则中止整个Session集的装置
	 */
	if (sendPendingUserActionIntentIfNeeded()) {
		return;
	}
	// isStaged 为 true 的时分表明下次体系发动的时分才真实装置
	// 一般用于(体系的)apex装置
	if (params.isStaged) {
		mStagedSession.verifySession();
	} else {
		verify();
	}
}

isStaged 为 true 表明现在不装置,下次发动发动的时分装置,一般用于装置体系的 apex 包。和咱们使用装置无关。

在 handleInstall 中,会调用 verify,之后都是一些装置的校验,包含且不限于包名,签名,Hash 值等等,这儿就不详细探讨了。关于装置包的校验,这儿就不多扩展了,咱们看一下调用流程即可。

6.6 verifySession

public void verifySession() {
	verify();
}

6.7 verify

private void verify() {
	try {
		...
		verifyNonStaged();
	} catch (PackageManagerException e) {
		...
	}
}

6.8 verifyNonStaged

private void verifyNonStaged()
		throws PackageManagerException {
	mSessionProvider.getSessionVerifier().verify(this, (error, msg) -> {
		mHandler.post(() -> {
			...
			// 调用完结而且成功,调用 onVerificationComplete
			if (error == INSTALL_SUCCEEDED) {
				onVerificationComplete();
			} else {
				// 校验不经过
				onSessionVerificationFailure(error, msg);
			}
		});
	});
}

6.9 onVerificationComplete

private void onVerificationComplete() {
	// 校验完结,开端装置。
	install();
}

当校验完结之后,就会调用 install 开端装置

6.10 install

private void install() {
	try {
		installNonStaged();
	} catch (PackageManagerException e) {
		final String completeMsg = ExceptionUtils.getCompleteMessage(e);
		onSessionInstallationFailure(e.error, completeMsg);
	}
}

6.11 installNonStaged

private void installNonStaged()
		throws PackageManagerException {
	final PackageManagerService.InstallParams installingSession = makeInstallParams();
	if (installingSession == null) {
		throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
				"Session should contain at least one apk session for installation");
	}
	if (isMultiPackage()) {
		...
		mPm.installStage(installingSession, installingChildSessions);
	} else {
		mPm.installStage(installingSession);
	}
}

在装置函数 installNonStaged 中,不论是批量装置的 isMultiPackage,仍是单个装置,终究都会执行到 PMS 的 installStage

七 PMS

7.1 installStage

   void installStage(InstallParams params) {
        final Message msg = mHandler.obtainMessage(INIT_COPY);
        params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
        msg.obj = params;
        mHandler.sendMessage(msg);
    }

PMS 的 installStage 中,首要就会经过 Handler 发送一条消息 INIT_COPY,开端复制装置包

7.2 doHandleMessage

void doHandleMessage(Message msg) {
	switch (msg.what) {
		case INIT_COPY: {
			HandlerParams params = (HandlerParams) msg.obj;
			if (params != null) {
				params.startCopy();
			}
			break;
		}

在 doHandleMessage 中,会调用 startCopy 复制装置包,这个 params,便是之前传入的

八 HandlerParams

private abstract class HandlerParams {
	 final void startCopy() {
		handleStartCopy();
		handleReturnCode();
	}
}

这个 HandlerParams 是一个抽象类,它的 startCopy 调用了两个函数 handleStartCopyhandleReturnCode,这两个都是抽象办法,由子类完结。

而这个子类在之前传入的参数的[7.1]中咱们现已看到了,它便是 InstallParams。

九 PMS.InstallParams

9.1 handleStartCopy

    public void handleStartCopy() {
        if ((mInstallFlags & PackageManager.INSTALL_APEX) != 0) {
            mRet = INSTALL_SUCCEEDED;
            return;
        }
        // 获取一个包信息
        PackageInfoLite pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mPm.mContext,
                mPackageLite, mOriginInfo.mResolvedPath, mInstallFlags, mPackageAbiOverride);
        // 验证和装置之间有一个推迟。设备的状况或许在这个推迟内发生变化
        // 所以咱们需求从头验证。
        boolean isStaged = (mInstallFlags & INSTALL_STAGED) != 0;
        if (isStaged) {
            Pair<Integer, String> ret = mInstallPackageHelper.verifyReplacingVersionCode(
                    pkgLite, mRequiredInstalledVersionCode, mInstallFlags);
            mRet = ret.first;
            if (mRet != INSTALL_SUCCEEDED) {
                return;
            }
        }
        final boolean ephemeral = (mInstallFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
        if (!mOriginInfo.mStaged && pkgLite.recommendedInstallLocation
                == InstallLocationUtils.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
            // 假如 staged 为 false,但是可用空间太小,就释放缓存再测验一次
            pkgLite.recommendedInstallLocation = mPm.freeCacheForInstallation(
                    pkgLite.recommendedInstallLocation, mPackageLite,
                    mOriginInfo.mResolvedPath, mPackageAbiOverride, mInstallFlags);
        }
        // 覆盖装置
        mRet = overrideInstallLocation(pkgLite.packageName, pkgLite.recommendedInstallLocation,
                pkgLite.installLocation);
    }

handleStartCopy 准确来说是为复制做的一些预备,真实的复制是由 handleReturnCode 完结的。

9.2 handleReturnCode

void handleReturnCode() {
	processPendingInstall();
}

9.3 processPendingInstall

private void processPendingInstall() {
	// 创立装置参数
	InstallArgs args = createInstallArgs(this);
	if (mRet == PackageManager.INSTALL_SUCCEEDED) {
		// 复制 apk
		mRet = args.copyApk();
	}
	...
	// 下面两个函数,最终都会调用到 processInstallRequestsAsync
	if (mParentInstallParams != null) {
		mParentInstallParams.tryProcessInstallRequest(args, mRet);
	} else {
		PackageInstalledInfo res = new PackageInstalledInfo(mRet);
		processInstallRequestsAsync(
				res.mReturnCode == PackageManager.INSTALL_SUCCEEDED,
				Collections.singletonList(new InstallRequest(args, res)));
	}
}
  • 这儿的 args 是一个 InstallArgs,这是一个抽象类,咱们直接看它的完结 FileInstallArgs。PMS 便是经过它完结的 apk 的复制。
  • 然后经过 InstallParams 的 processInstallRequestsAsync 处理复制后的流程。

十 FileInstallArgs

10.1 copyApk

[frameworks/base/services/core/java/com/android/server/pm/FileInstallArgs.java]
int copyApk() {
		return doCopyApk();
}

10.2 doCopyApk

private int doCopyApk() {
	try {
		final boolean isEphemeral = (mInstallFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
		// 分配权限,创立目录 /data/app
		final File tempDir =
				mPm.mInstallerService.allocateStageDirLegacy(mVolumeUuid, isEphemeral);
		mCodeFile = tempDir;
	} catch (IOException e) {
		...
	}
	// 复制apk
	int ret = PackageManagerServiceUtils.copyPackage(
			mOriginInfo.mFile.getAbsolutePath(), mCodeFile);
	if (ret != PackageManager.INSTALL_SUCCEEDED) {
		Slog.e(TAG, "Failed to copy package");
		return ret;
	}
	final boolean isIncremental = isIncrementalPath(mCodeFile.getAbsolutePath());
	final File libraryRoot = new File(mCodeFile, LIB_DIR_NAME);
	NativeLibraryHelper.Handle handle = null;
	try {
		// 复制 so 库
		handle = NativeLibraryHelper.Handle.create(mCodeFile);
		ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
				mAbiOverride, isIncremental);
	} catch (IOException e) {
		Slog.e(TAG, "Copying native libraries failed", e);
		ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
	} finally {
		IoUtils.closeQuietly(handle);
	}
	return ret;
}

十一 PackageManagerServiceUtils

11.1 copyPackage

    [frameworks/base/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java]
    public static int copyPackage(String packagePath, File targetDir) {
        try {
            final File packageFile = new File(packagePath);
           ...
            // 调用 copyFile 函数开端复制
            copyFile(pkg.getBaseApkPath(), targetDir, "base.apk");
            if (!ArrayUtils.isEmpty(pkg.getSplitNames())) {
                for (int i = 0; i < pkg.getSplitNames().length; i++) {
                    copyFile(pkg.getSplitApkPaths()[i], targetDir,
                            "split_" + pkg.getSplitNames()[i] + ".apk");
                }
            }
            return PackageManager.INSTALL_SUCCEEDED;
        }
    }

11.2 copyFile

private static void copyFile(String sourcePath, File targetDir, String targetName)
		throws ErrnoException, IOException {
	final File targetFile = new File(targetDir, targetName);
	final FileDescriptor targetFd = Os.open(targetFile.getAbsolutePath(),
			O_RDWR | O_CREAT, 0644);
	Os.chmod(targetFile.getAbsolutePath(), 0644);
	FileInputStream source = null;
	try {
		source = new FileInputStream(sourcePath);
		FileUtils.copy(source.getFD(), targetFd);
	} finally {
		IoUtils.closeQuietly(source);
	}
}

最终在 copyFile 函数进行了复制,权限为 0644,即用户具有读写权限,组用户和其它用户具有只读权限。

接下来咱们回到 [9.2] 继续看后面的流程 processInstallRequestsAsync

十二 PMS

12.1 processInstallRequestsAsync

[frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]
// 排队进行异步操作,因为软件包的装置或许需求一点时间
private void processInstallRequestsAsync(boolean success,
		List<InstallRequest> installRequests) {
	...
	if (success) {
		for (InstallRequest request : apkInstallRequests) {
			request.args.doPreInstall(request.installResult.returnCode);
		}
		synchronized (mInstallLock) {
			installPackagesTracedLI(apkInstallRequests);
		}
		for (InstallRequest request : apkInstallRequests) {
			request.args.doPostInstall(
					request.installResult.returnCode, request.installResult.uid);
		}
	}
	for (InstallRequest request : apkInstallRequests) {
		restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult,
				new PostInstallData(request.args, request.installResult, null));
	}
}

十三 InstallPackageHelper

13.1 processInstallRequests

[frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java]
public void processInstallRequests(boolean success, List<InstallRequest> installRequests) {
	List<InstallRequest> apexInstallRequests = new ArrayList<>();
	List<InstallRequest> apkInstallRequests = new ArrayList<>();
	for (InstallRequest request : installRequests) {
		if ((request.mArgs.mInstallFlags & PackageManager.INSTALL_APEX) != 0) {
			apexInstallRequests.add(request);
		} else {
			apkInstallRequests.add(request);
		}
	}
	// 支撑APEXs和APKs的多包装置或许需求一些考虑以确保装置的原子性。
	if (!apexInstallRequests.isEmpty()) {
		if (success) {
			// 因为 installApexPackages 需求与外部服务(apexd)对话,
			// 所以咱们 安排以异步方式运行它。一旦完结,它将康复装置。
			Thread t = new Thread(() -> installApexPackagesTraced(apexInstallRequests),
					"installApexPackages");
			t.start();
		} else {
			// 非阶段性APEX装置在之前的某个当地失利了
			// processInstallRequestAsync。在这种情况下,只需求告诉观察者失利
			InstallRequest request = apexInstallRequests.get(0);
			mPm.notifyInstallObserver(request.mInstallResult,
					request.mArgs.mObserver);
		}
		return;
	}
	if (success) {
		// 预装置,做一些查看,假如存在异常情况,就清楚复制的 apk 文件
		for (InstallRequest request : apkInstallRequests) {
			request.mArgs.doPreInstall(request.mInstallResult.mReturnCode);
		}
		// 真实的装置
		synchronized (mPm.mInstallLock) {
			installPackagesTracedLI(apkInstallRequests);
		}
		// 装置后的操作
		for (InstallRequest request : apkInstallRequests) {
			request.mArgs.doPostInstall(
					request.mInstallResult.mReturnCode, request.mInstallResult.mUid);
		}
	}
	for (InstallRequest request : apkInstallRequests) {
		restoreAndPostInstall(request.mArgs.mUser.getIdentifier(),
				request.mInstallResult,
				new PostInstallData(request.mArgs,
						request.mInstallResult, null));
	}
}

processInstallRequests 便是真实装置的流程。它分为 4 个过程

  1. doPreInstall 装置预处理,判别校验的成果,假如不经过就清楚 apk 文件。
  2. installPackagesTracedLI 真实的装置逻辑。
  3. doPostInstall 装置后的处理操作。

十四 PMS

14.1 doPreInstall

[frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]
int doPreInstall(int status) {
	if (status != PackageManager.INSTALL_SUCCEEDED) {
		cleanUp();
	}
	return status;
}

假如校验状况不经过,就经过 cleanUp 清除装置文件。

14.2 installPackagesTracedLI

[frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]
private void installPackagesTracedLI(List<InstallRequest> requests) {
	...
	installPackagesLI(requests);
}

14.3 installPackagesLI

[frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]
private void installPackagesLI(List<InstallRequest> requests) {
	...
		for (InstallRequest request : requests) {
			// 获取一切的恳求,并扫描、校对或提交
			final PrepareResult prepareResult;
			try {
				// 先预处理
				prepareResult =
						preparePackageLI(request.mArgs, request.mInstallResult);
			} ...
			...
			try {
				// 扫描
				final ScanResult result = scanPackageTracedLI(
						prepareResult.mPackageToScan, prepareResult.mParseFlags,
						prepareResult.mScanFlags, System.currentTimeMillis(),
						request.mArgs.mUser, request.mArgs.mAbiOverride);
				...
		}
		...
			try {
				// 调停装置包
				reconciledPackages = ReconcilePackageUtils.reconcilePackages(
						reconcileRequest, mSharedLibraries,
						mPm.mSettings.getKeySetManagerService(), mPm.mSettings);
			} ...
			try {
				// 提交装置包
				commitRequest = new CommitRequest(reconciledPackages,
						mPm.mUserManager.getUserIds());
				commitPackagesLocked(commitRequest);
				success = true;
			} ...
		}
		// 提交
		executePostCommitSteps(commitRequest);
	} finally {
		if (success) {
			for (InstallRequest request : requests) {
				final InstallArgs args = request.mArgs;
				if (args.mDataLoaderType != DataLoaderType.INCREMENTAL) {
					continue;
				}
				if (args.mSigningDetails.getSignatureSchemeVersion() != SIGNING_BLOCK_V4) {
					continue;
				}
				// 假如是增量装置,咱们在装置前绕过验证器。
				// 在验证了软件包是有效的后,向验证器发送一个告诉,
				// 其中包含 base.apk的根哈希值
				...
				VerificationUtils.broadcastPackageVerified(verificationId, originUri,
						PackageManager.VERIFICATION_ALLOW, rootHashString,
						args.mDataLoaderType, args.getUser(), mContext);
			}
		} else {
			for (ScanResult result : preparedScans.values()) {
				if (createdAppId.getOrDefault(result.mRequest.mParsedPackage.getPackageName(),
						false)) {
					cleanUpAppIdCreation(result);
				}
			}
			// 创立一个装置失利的描述性的原因。
			for (InstallRequest request : requests) {
				if (request.mInstallResult.mFreezer != null) {
					request.mInstallResult.mFreezer.close();
				}
				if (request.mInstallResult.mReturnCode == PackageManager.INSTALL_SUCCEEDED) {
					request.mInstallResult.mReturnCode = PackageManager.INSTALL_UNKNOWN;
				}
			}
		}
	}
}

installPackagesLI 便是装置的首要流程,它分为 4 步

  1. preparePackageLI:预处理装置包
  2. scanPackageTracedLI:扫描装置包
  3. reconcilePackages:调停装置包
  4. commitPackagesLocked:提交装置包

14.4 preparePackageLI

preparePackageLI 是装置前的预处理,它里边会对装置包做各种判别,例如版别校验,签名校验等等。

private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res)
        throws PrepareFailure {
    ...
    // PackageParser2 解析装置包,咱们在 PMS 解析装置使用中现已讲过它的原理了
    // 它可以解析装置使用的四大组件
    final ParsedPackage parsedPackage;
    try (PackageParser2 pp = mPm.mInjector.getPreparingPackageParser()) {
        parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false);
        AndroidPackageUtils.validatePackageDexMetadata(parsedPackage);
    } ...
	...
    // 假如有现成的就使用,否则从APK中解析
    if (args.mSigningDetails != SigningDetails.UNKNOWN) {
        parsedPackage.setSigningDetails(args.mSigningDetails);
    } else {
    	// 解析
        final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
        final ParseResult<SigningDetails> result = ParsingPackageUtils.getSigningDetails(
                input, parsedPackage, false /*skipVerify*/);
        parsedPackage.setSigningDetails(result.getResult());
    }
    boolean systemApp = false;
    boolean replace = false;
    synchronized (mPm.mLock) {
        // 查看是否存在相同的装置包
        if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
            String oldName = mPm.mSettings.getRenamedPackageLPr(pkgName);
            if (parsedPackage.getOriginalPackages().contains(oldName)
                    && mPm.mPackages.containsKey(oldName)) {
                ...
            } else if (mPm.mPackages.containsKey(pkgName)) {
                //存在软件包,就替换
                replace = true;
                if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing package: " + pkgName);
            }
            if (replace) {
                // 避免使用程序退出运行时权限的版别,
                // 所以新的 targetSdk 不能小于旧的
                AndroidPackage oldPackage = mPm.mPackages.get(pkgName);
                final int oldTargetSdk = oldPackage.getTargetSdkVersion();
                final int newTargetSdk = parsedPackage.getTargetSdkVersion();
                if (oldTargetSdk > Build.VERSION_CODES.LOLLIPOP_MR1
                        && newTargetSdk <= Build.VERSION_CODES.LOLLIPOP_MR1) {
                    ...
                }
                ...
            }
        }
        ...
        if (signatureCheckPs != null) {
            // 签名查看
            final KeySetManagerService ksms = mPm.mSettings.getKeySetManagerService();
            final SharedUserSetting signatureCheckSus = mPm.mSettings.getSharedUserSettingLPr(
                    signatureCheckPs);
            if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, signatureCheckSus,
                    scanFlags)) {
                if (!ksms.checkUpgradeKeySetLocked(signatureCheckPs, parsedPackage)) {
                    throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
                            + parsedPackage.getPackageName() + " upgrade keys do not match the "
                            + "previously installed version");
                }
            } else {
                ...
            }
        }
        ...
        // 将查看权限兼容性的逻辑移到PermissionManagerService中
        final int n = ArrayUtils.size(parsedPackage.getPermissions());
        for (int i = n - 1; i >= 0; i--) {
            final ParsedPermission perm = parsedPackage.getPermissions().get(i);
            final Permission bp = mPm.mPermissionManager.getPermissionTEMP(perm.getName());
            // 除了体系,不要答应任何人界说短暂的权限
            if ((perm.getProtectionLevel() & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0
                    && !systemApp) {
                ComponentMutateUtils.setProtectionLevel(perm,
                        perm.getProtectionLevel() & ~PermissionInfo.PROTECTION_FLAG_INSTANT);
            }
            ...
        }
    }
    if (systemApp) {
        if (onExternal) {
            // 体系app不能装置到sd卡
            throw new PrepareFailure(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
                    "Cannot install updates to system apps on sdcard");
        } else if (instantApp) {
            // 体系使用不能被即时使用取代
            throw new PrepareFailure(INSTALL_FAILED_SESSION_INVALID,
                    "Cannot update a system app with an instant app");
        }
    }
    if (args.mMoveInfo != null) {
        // 假如现已做过一次移动,就符号Dex现已预备好
        scanFlags |= SCAN_NO_DEX;
        scanFlags |= SCAN_MOVE;
        synchronized (mPm.mLock) {
            final PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName);
            if (ps == null) {
                res.setError(INSTALL_FAILED_INTERNAL_ERROR,
                        "Missing settings for moved package " + pkgName);
            }
            // We moved the entire application as-is, so bring over the
            // previously derived ABI information.
            parsedPackage.setPrimaryCpuAbi(ps.getPrimaryCpuAbi())
                    .setSecondaryCpuAbi(ps.getSecondaryCpuAbi());
        }
    } else {
        // 启用SCAN_NO_DEX标志,以便在以后阶段越过dexopt
        scanFlags |= SCAN_NO_DEX;
        ...
    }
    final PackageFreezer freezer =
            freezePackageForInstall(pkgName, installFlags, "installPackageLI");
    boolean shouldCloseFreezerBeforeReturn = true;
    try {
        final AndroidPackage oldPackage;
        String renamedPackage;
        boolean sysPkg = false;
        int targetScanFlags = scanFlags;
        int targetParseFlags = parseFlags;
        final PackageSetting ps;
        final PackageSetting disabledPs;
        final SharedUserSetting sharedUserSetting;
        if (replace) {
            // 假如 replace 是 true,表明存在一个旧的装置包
            // 那么就要要验证新装置包是否可用,而且还有先备份一下旧的装置包
            // 假如装置失利,旧需求回滚
            ... //
            synchronized (mPm.mLock) {
                if (DEBUG_INSTALL) {
                    Slog.d(TAG,
                            "replacePackageLI: new=" + parsedPackage + ", old=" + oldPackage);
                }
                ps = mPm.mSettings.getPackageLPr(pkgName11);
                disabledPs = mPm.mSettings.getDisabledSystemPkgLPr(ps);
                sharedUserSetting = mPm.mSettings.getSharedUserSettingLPr(ps);
                // 验证签名是否有效
                final KeySetManagerService ksms = mPm.mSettings.getKeySetManagerService();
                if (ksms.shouldCheckUpgradeKeySetLocked(ps, sharedUserSetting, scanFlags)) {
                    if (!ksms.checkUpgradeKeySetLocked(ps, parsedPackage)) {
                        throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
                                "New package not signed by keys specified by upgrade-keysets: "
                                        + pkgName11);
                    }
                } ...
                // 不答应体系晋级,除非晋级的哈希值匹配
                if (oldPackage.getRestrictUpdateHash() != null && oldPackage.isSystem()) {
                   ...
                }
                ... // 各种不答应晋级的情况判别
            }
            // 更新被删去的内容
            res.mRemovedInfo = new PackageRemovedInfo(mPm);
            res.mRemovedInfo.mUid = oldPackage.getUid();
            res.mRemovedInfo.mRemovedPackage = oldPackage.getPackageName();
            res.mRemovedInfo.mInstallerPackageName = ps.getInstallSource().installerPackageName;
            res.mRemovedInfo.mIsStaticSharedLib =
                    parsedPackage.getStaticSharedLibName() != null;
            ...
            sysPkg = oldPackage.isSystem();
            if (sysPkg) {
                // 根据需求设置体系/特权/oem/供货商/产品的标志
                final boolean privileged = oldPackage.isPrivileged();
                final boolean oem = oldPackage.isOem();
                final boolean vendor = oldPackage.isVendor();
                final boolean product = oldPackage.isProduct();
                final boolean odm = oldPackage.isOdm();
                final boolean systemExt = oldPackage.isSystemExt();
                ...
                targetParseFlags = systemParseFlags;
                targetScanFlags = systemScanFlags;
            } else { // non system replace
                replace = true;
                if (DEBUG_INSTALL) {
                    Slog.d(TAG,
                            "replaceNonSystemPackageLI: new=" + parsedPackage + ", old="
                                    + oldPackage);
                }
            }
        } else { // 新软件包的装置
            ps = null;
            disabledPs = null;
            replace = false;
            oldPackage = null;
            // Remember this for later, in case we need to rollback this install
            String pkgName1 = parsedPackage.getPackageName();
		...
		// 返回
        return new PrepareResult(replace, targetScanFlags, targetParseFlags,
                oldPackage, parsedPackage, replace /* clearCodeCache */, sysPkg,
                ps, disabledPs);
    } finally {
        res.mFreezer = freezer;
        if (shouldCloseFreezerBeforeReturn) {
            freezer.close();
        }
    }
}

接下来扫描 apk 的代码十分长,这儿就不列举了,只大概说一下它的作用吧。扫描的首要作用便是为了获取 PackageParser.Package 和 PackageSetting。然后经过 reconcilePackages 对成果进行谐和。最终才是 commitPackagesLocked 的提交。

14.5 commitPackagesLocked

private void commitPackagesLocked(final CommitRequest request) {
	// 这个办法中只或许IO失利而导致失利
	for (ReconciledPackage reconciledPkg : request.mReconciledPackages.values()) {
		...
		if (reconciledPkg.mPrepareResult.mReplace) {
			AndroidPackage oldPackage = mPm.mPackages.get(packageName);
			// 设置更新和装置时间
			PackageStateInternal deletedPkgSetting = mPm.snapshotComputer()
					.getPackageStateInternal(oldPackage.getPackageName());
			reconciledPkg.mPkgSetting
					.setFirstInstallTimeFromReplaced(deletedPkgSetting, request.mAllUsers)
					.setLastUpdateTime(System.currentTimeMillis());
			res.mRemovedInfo.mBroadcastAllowList = mPm.mAppsFilter.getVisibilityAllowList(
					mPm.snapshotComputer(), reconciledPkg.mPkgSetting, request.mAllUsers,
					mPm.mSettings.getPackagesLocked());
			if (reconciledPkg.mPrepareResult.mSystem) {
				// 假如装置的是体系使用
				// 移除旧的装置包
				removePackageHelper.removePackageLI(oldPackage, true);
				if (!disableSystemPackageLPw(oldPackage)) {
					// 不需求禁用旧的软件包,直接删去即可
					res.mRemovedInfo.mArgs = new FileInstallArgs(
							oldPackage.getPath(),
							getAppDexInstructionSets(
									AndroidPackageUtils.getPrimaryCpuAbi(oldPackage,
											deletedPkgSetting),
									AndroidPackageUtils.getSecondaryCpuAbi(oldPackage,
											deletedPkgSetting)), mPm);
				} else {
					res.mRemovedInfo.mArgs = null;
				}
			} else {
				try {
					//  设置将在调用updateSettingsLI()时被写入
					deletePackageHelper.executeDeletePackageLIF(
							reconciledPkg.mDeletePackageAction, packageName,
							true, request.mAllUsers, false);
				} catch (SystemDeleteException e) {
					...
				}
				// 成功地删去了旧包;继续进行替换。
				// 更新前先将代码途径的内存复制
				PackageSetting ps1 = mPm.mSettings.getPackageLPr(
						reconciledPkg.mPrepareResult.mExistingPackage.getPackageName());
				if ((reconciledPkg.mInstallArgs.mInstallFlags & PackageManager.DONT_KILL_APP)
						== 0) {
					Set<String> oldCodePaths = ps1.getOldCodePaths();
					if (oldCodePaths == null) {
						oldCodePaths = new ArraySet<>();
					}
					Collections.addAll(oldCodePaths, oldPackage.getBaseApkPath());
					Collections.addAll(oldCodePaths, oldPackage.getSplitCodePaths());
					ps1.setOldCodePaths(oldCodePaths);
				} else {
					ps1.setOldCodePaths(null);
				}
				...
			}
		}
		// 正式提交
		AndroidPackage pkg = commitReconciledScanResultLocked(
				reconciledPkg, request.mAllUsers);
		...
	}
	ApplicationPackageManager.invalidateGetPackagesForUidCache();
}

commitPackagesLocked 便是正式提交装置的 apk 了,里边的代码虽然许多,但是做的工作其实很简略猜到。

  1. 修改装置时间
  2. 移除旧的装置包

接下来咱们回到 [14.3] 看看装置的四个过程中的最终一个,执行装置指令executePostCommitSteps

14.6 executePostCommitSteps

[frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]
private void executePostCommitSteps(CommitRequest commitRequest) {
	final ArraySet<IncrementalStorage> incrementalStorages = new ArraySet<>();
	for (ReconciledPackage reconciledPkg : commitRequest.reconciledPackages.values()) {
		...
		// 装置后预备app数据
		prepareAppDataAfterInstallLIF(pkg);
		if (reconciledPkg.prepareResult.clearCodeCache) {
			clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
					| FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
		}
		...
		// dex 优化
		if (performDexopt) {
			...
			mPackageDexOptimizer.performDexOpt(pkg, realPkgSetting,
					null /* instructionSets */,
					getOrCreateCompilerPackageStats(pkg),
					mDexManager.getPackageUseInfoOrDefault(packageName),
					dexoptOptions);
			Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
		}
		// 告诉BackgroundDexOptService该软件包现已被改变
		BackgroundDexOptService.notifyPackageChanged(packageName);
		// 告诉观察者广播
		notifyPackageChangeObserversOnUpdate(reconciledPkg);
	}
	waitForNativeBinariesExtraction(incrementalStorages);
}

到现在,咱们装置的 apk 现现已历了如下过程

  1. 复制到 /data/app
  2. 各种校验
  3. 预处理的扫描和解析装置文件
  4. 移除了旧的装置包

在接下来的 executePostCommitSteps 中,体系则首要做了三件事

  1. 预备装置后的 App 数据 AppData
  2. 对装置包做 dex 优化
  3. 装置完结,告诉观察者,并把装置包显现到桌面中。

14.7 doPostInstall

[frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]
int doPostInstall(int status, int uid) {
	if (status == PackageManager.INSTALL_SUCCEEDED) {
		cleanUp(move.fromUuid);
	} else {
		cleanUp(move.toUuid);
	}
	return status;
}

十五 总结

到这儿,PMS 装置使用的流程咱们就整理完毕了,最终再来做一个简略的概括总结。

PMS 作为 Android 中的包办理服务,装置使用的流程如下。

  1. 首要发动一个装置使用的界面 Activity。用户可用在这个界面挑选是否装置,而且这个界面还有此刻装置的使用的信息(图标,姓名,权限等等)。
  2. 假如用户挑选赞同,就会经过 PMS 创立一个 session,这个 session 的 id 是体系仅有的。
  3. PMS 会经过 Handler 的消息机制,最终调用到 handleInstall 这个函数,它便是使用装置的开端。
  4. 使用的装置会分为两种,一种是 Stage 为 true,这种会在下次发动发动时装置,一种则是普通使用的装置。
  5. 装置的流程大致分为以下几步
    1. 校验装置包
    2. 复制 apk
    3. 扫描 apk 解析装置文件
    4. 对装置包做 dex 优化
    5. 告诉观察者。

最终用一张全体的UML图结束吧。

PMS源码解析——apk的安装流程(Android12)