adb install 发生了什么-PMS篇
在上一篇中,最后通过binder调用了shellCommand。
//frameworks/native/libs/binder/Binder.cpp
status_t IBinder::shellCommand(const sp<IBinder>& target, int in, int out, int err,
Vector<String16>& args, const sp<IShellCallback>& callback,
const sp<IResultReceiver>& resultReceiver)
{
Parcel send;
Parcel reply;
send.writeFileDescriptor(in);
send.writeFileDescriptor(out);
send.writeFileDescriptor(err);
const size_t numArgs = args.size();
send.writeInt32(numArgs);
for (size_t i = 0; i < numArgs; i++) {
send.writeString16(args[i]);
}
send.writeStrongBinder(callback != nullptr ? IInterface::asBinder(callback) : nullptr);
send.writeStrongBinder(resultReceiver != nullptr ? IInterface::asBinder(resultReceiver) : nullptr);
return target->transact(SHELL_COMMAND_TRANSACTION, send, &reply);
}
通过transact将消息发送到了service中,code为SHELL_COMMAND_TRANSACTION。
//frameworks/base/core/java/android/os/Binder.java
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply,
int flags) throws RemoteException {
...
if (code == SHELL_COMMAND_TRANSACTION) {//code等于SHELL_COMMAND_TRANSACTION
ParcelFileDescriptor in = data.readFileDescriptor();
ParcelFileDescriptor out = data.readFileDescriptor();
ParcelFileDescriptor err = data.readFileDescriptor();
String[] args = data.readStringArray();
ShellCallback shellCallback = ShellCallback.CREATOR.createFromParcel(data);
ResultReceiver resultReceiver = ResultReceiver.CREATOR.createFromParcel(data);
try {
if (out != null) {
shellCommand(in != null ? in.getFileDescriptor() : null,
out.getFileDescriptor(),
err != null ? err.getFileDescriptor() : out.getFileDescriptor(),
args, shellCallback, resultReceiver);
}
}
...
}
当code为SHELL_COMMAND_TRANSACTION时,会调用shellCommand。
//frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out,
FileDescriptor err, String[] args, ShellCallback callback,
ResultReceiver resultReceiver) {
(new PackageManagerShellCommand(this, mContext,
mDomainVerificationManager.getShell()))
.exec(this, in, out, err, args, callback, resultReceiver);
}
创建了一个PackageManagerShellCommand对象,然后调用了exec.这是父类中的方法。
//frameworks/libs/modules-utils/java/com/android/modules/utils/BasicShellCommandHandler.java
public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args) {
int res = -1;
try {
res = onCommand(mCmd);
if (DEBUG) Log.d(TAG, "Executed command " + mCmd + " on " + mTarget);
}
...
return res;
}
执行部分调用onCommand方法。
//frameworks/base/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@Override
public int onCommand(String cmd) {
final PrintWriter pw = getOutPrintWriter();
try {
switch (cmd) {
...
case "install":
return runInstall();
....
return -1;
}
private int runInstall() throws RemoteException {
return doRunInstall(makeInstallParams(UNSUPPORTED_INSTALL_CMD_OPTS));
}
install指令最后调用到doRunInstall。
private int doRunInstall(final InstallParams params) throws RemoteException {
final PrintWriter pw = getOutPrintWriter();
ArrayList<String> args = getRemainingArgs();
...
final int sessionId = doCreateSession(params.sessionParams,
params.installerPackageName, params.userId);//创建Session
boolean abandonSession = true;
try {
if (isStreaming) {
if (doAddFiles(sessionId, args, params.sessionParams.sizeBytes, isApex)
!= PackageInstaller.STATUS_SUCCESS) {
return 1;
}
} else {
if (doWriteSplits(sessionId, args, params.sessionParams.sizeBytes, isApex)
!= PackageInstaller.STATUS_SUCCESS) {//写入数据
return 1;
}
}
if (doCommitSession(sessionId, false /*logSuccess*/)
!= PackageInstaller.STATUS_SUCCESS) {//执行操作
return 1;
}
abandonSession = false;
if (params.sessionParams.isStaged && params.stagedReadyTimeoutMs > 0) {
return doWaitForStagedSessionReady(sessionId, params.stagedReadyTimeoutMs, pw);
}
pw.println("Success");
return 0;
}
}
很直接的分为三步:
- doCreateSession
- doWriteSplits
- doCommitSession
先看看doCreateSession
//frameworks/base/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
private int doCreateSession(SessionParams params, String installerPackageName, int userId)
throws RemoteException {
if (userId == UserHandle.USER_ALL) {
params.installFlags |= PackageManager.INSTALL_ALL_USERS;
}
final int translatedUserId =
translateUserId(userId, UserHandle.USER_SYSTEM, "doCreateSession");//获取一个userid
final int sessionId = mInterface.getPackageInstaller()
.createSession(params, installerPackageName, null /*installerAttributionTag*/,
translatedUserId);
return sessionId;
}
通过一个IPC调用创建了一个Session。mInterface是一个IPackageManager,在 PackageManagerShellCommand创建的时候传入的
//frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
public class IPackageManagerImpl extends IPackageManagerBase {
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out,
FileDescriptor err, String[] args, ShellCallback callback,
ResultReceiver resultReceiver) {
(new PackageManagerShellCommand(this, mContext,
mDomainVerificationManager.getShell()))
.exec(this, in, out, err, args, callback, resultReceiver);
}
}
//frameworks/base/services/core/java/com/android/server/pm/IPackageManagerBase.java
public final IPackageInstaller getPackageInstaller() {
// Return installer service for internal calls.
if (PackageManagerServiceUtils.isSystemOrRoot()) {
return mInstallerService;
}
}
getPackageInstaller返回的就是PackageInstallerService,接着看PackageInstallerService的createSession。
//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java
@Override
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);
}
}
private int createSessionInternal(SessionParams params, String installerPackageName,
String installerAttributionTag, int userId)
throws IOException {
final int callingUid = Binder.getCallingUid();
final Computer snapshot = mPm.snapshotComputer();
。。。。
final int sessionId;
final PackageInstallerSession session;
synchronized (mSessions) {
// Check that the installer does not have too many active sessions.
final int activeCount = getSessionCount(mSessions, callingUid);
final int historicalCount = mHistoricalSessionsByInstaller.get(callingUid);
sessionId = allocateSessionIdLocked();
}
File stageDir = null;
String stageCid = null;
if (!params.isMultiPackage) {//根据sessionId创建安装时的临时目录
if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
stageDir = buildSessionDir(sessionId, params);
} else {
stageCid = buildExternalStageCid(sessionId);
}
}
InstallSource installSource = InstallSource.create(installerPackageName,
originatingPackageName, requestedInstallerPackageName,
installerAttributionTag, params.packageSource);
session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this,
mSilentUpdatePolicy, mInstallThread.getLooper(), mStagingManager, sessionId,
userId, callingUid, installSource, params, createdMillis, 0L, stageDir, stageCid,
null, null, false, false, false, false, null, SessionInfo.INVALID_ID,
false, false, false, PackageManager.INSTALL_UNKNOWN, "");//创建了一个PackageInstallerSession
synchronized (mSessions) {
mSessions.put(sessionId, session);
}
mPm.addInstallerPackageName(session.getInstallSource());
return sessionId;
}
重要部分就是创建了一个PackageInstallerSession,然后和sessionId绑定起来,把sessionId返回给调用方。
下面看doWriteSplits
//frameworks/base/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
boolean logSuccess) throws RemoteException {
PackageInstaller.Session session = null;
try {
session = new PackageInstaller.Session(
mInterface.getPackageInstaller().openSession(sessionId));//根据sessionid创建本地的session
final PrintWriter pw = getOutPrintWriter();
final ParcelFileDescriptor fd;
if (STDIN_PATH.equals(inPath)) {
fd = ParcelFileDescriptor.dup(getInFileDescriptor());
} else if (inPath != null) {
fd = openFileForSystem(inPath, "r");
if (fd == null) {
return -1;
}
sizeBytes = fd.getStatSize();
if (sizeBytes < 0) {
getErrPrintWriter().println("Unable to get size of: " + inPath);
return -1;
}
} else {
fd = ParcelFileDescriptor.dup(getInFileDescriptor());
}
session.write(splitName, 0, sizeBytes, fd);//拿到fd将文件fd写入session
if (logSuccess) {
pw.println("Success: streamed " + sizeBytes + " bytes");
}
return 0;
} catch (IOException e) {
getErrPrintWriter().println("Error: failed to write; " + e.getMessage());
return 1;
} finally {
IoUtils.closeQuietly(session);
}
}
这部分很简单,就是获取文件fd,然后写入session中。
//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
@Override
public void write(String name, long offsetBytes, long lengthBytes,
ParcelFileDescriptor fd) {
assertCanWrite(fd != null);
try {
doWriteInternal(name, offsetBytes, lengthBytes, fd);
} catch (IOException e) {
throw ExceptionUtils.wrap(e);
}
}
private ParcelFileDescriptor doWriteInternal(String name, long offsetBytes, long lengthBytes,
ParcelFileDescriptor incomingFd) throws IOException {
final RevocableFileDescriptor fd;
final FileBridge bridge;
try {
// Use installer provided name for now; we always rename later
final File target;
final long identity = Binder.clearCallingIdentity();
try {
target = new File(stageDir, name);//创建暂存文件
} finally {
Binder.restoreCallingIdentity(identity);
}
ParcelFileDescriptor targetPfd = openTargetInternal(target.getAbsolutePath(),
O_CREAT | O_WRONLY, 0644);
Os.chmod(target.getAbsolutePath(), 0644);
.....
if (incomingFd != null) {
try {//将数据写入暂存文件
final Int64Ref last = new Int64Ref(0);
FileUtils.copy(incomingFd.getFileDescriptor(), targetPfd.getFileDescriptor(),
lengthBytes, null, Runnable::run,
(long progress) -> {
if (params.sizeBytes > 0) {
final long delta = progress - last.value;
last.value = progress;
synchronized (mProgressLock) {
setClientProgressLocked(mClientProgress
+ (float) delta / (float) params.sizeBytes);
}
}
});
}
}
通过fd将文件复制到了暂存目录下。
最后就是通过doCommitSession安装
//frameworks/base/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
private int doCommitSession(int sessionId, boolean logSuccess)
throws RemoteException {
final PrintWriter pw = getOutPrintWriter();
PackageInstaller.Session session = null;
try {//也是根据sessionId创建session
session = new PackageInstaller.Session(
mInterface.getPackageInstaller().openSession(sessionId));
...
final LocalIntentReceiver receiver = new LocalIntentReceiver();//注册Receiver接受结果
session.commit(receiver.getIntentSender());//调用commit
if (!session.isStaged()) {
final Intent result = receiver.getResult();
final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
PackageInstaller.STATUS_FAILURE);
if (status == PackageInstaller.STATUS_SUCCESS) {
if (logSuccess) {
pw.println("Success");
}
} else {
pw.println("Failure ["
+ result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
}
return status;
}
}
也看下PackageInstallerSession中的commit。
//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
....
dispatchSessionSealed();
}
private void dispatchSessionSealed() {
mHandler.obtainMessage(MSG_ON_SESSION_SEALED).sendToTarget();//发送MSG_ON_SESSION_SEALED执行handleSessionSealed
}
private void handleSessionSealed() {
assertSealed("dispatchSessionSealed");
// Persist the fact that we've sealed ourselves to prevent
// mutations of any hard links we create.
mCallback.onSessionSealedBlocking(this);
dispatchStreamValidateAndCommit();
}
private void dispatchStreamValidateAndCommit() {
mHandler.obtainMessage(MSG_STREAM_VALIDATE_AND_COMMIT).sendToTarget();//发送MSG_STREAM_VALIDATE_AND_COMMIT
}
.....
private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_ON_SESSION_SEALED:
handleSessionSealed();
break;
case MSG_STREAM_VALIDATE_AND_COMMIT:
handleStreamValidateAndCommit();//在这里回做初步的apk解析获得PackageLite
break;
case MSG_INSTALL:
handleInstall();
break;
case MSG_ON_PACKAGE_INSTALLED:
final SomeArgs args = (SomeArgs) msg.obj;
final String packageName = (String) args.arg1;
final String message = (String) args.arg2;
final Bundle extras = (Bundle) args.arg3;
final IntentSender statusReceiver = (IntentSender) args.arg4;
final int returnCode = args.argi1;
args.recycle();
sendOnPackageInstalled(mContext, statusReceiver, sessionId,
isInstallerDeviceOwnerOrAffiliatedProfileOwner(), userId,
packageName, returnCode, message, extras);
break;
case MSG_SESSION_VALIDATION_FAILURE:
final int error = msg.arg1;
final String detailMessage = (String) msg.obj;
onSessionValidationFailure(error, detailMessage);
break;
}
return true;
}
};
handle作为状态机通过发送消息最后到handleInstall执行安装。
//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
@WorkerThread
private void handleInstall() {
...
if (sendPendingUserActionIntentIfNeeded()) {//如果一个Session 需要用户操作,则停止整个Session集的安装
return;
}
if (params.isStaged) {
mStagedSession.verifySession();
} else {
verify();//进行一些签名包名等判断
}
}
private void verify() {
....
verifyNonStaged();
}
private void verifyNonStaged()
throws PackageManagerException {
mSessionProvider.getSessionVerifier().verify(this, (error, msg) -> {
//verify之后的回调
mHandler.post(() -> {
if (error == INSTALL_SUCCEEDED) {
onVerificationComplete();
} else {
onSessionVerificationFailure(error, msg);
}
});
});
}
private void onVerificationComplete() {
....
install();
}
最后都会进入verify中进行安装前的判断,经过一系列的判断通过install安装
private CompletableFuture<Void> install() {
List<CompletableFuture<InstallResult>> futures = installNonStaged();
....
}
private List<CompletableFuture<InstallResult>> installNonStaged() {
List<CompletableFuture<InstallResult>> futures = new ArrayList<>();
CompletableFuture<InstallResult> future = new CompletableFuture<>();
futures.add(future);
final InstallParams installingSession = makeInstallParams(future);
installingSession.installStage();
......
return futures;
}
最后通过installingSession.installStage();来执行安装。
//frameworks/base/services/core/java/com/android/server/pm/InstallParams.java
public void installStage() {
final Message msg = mPm.mHandler.obtainMessage(INIT_COPY);
msg.obj = this;
mPm.mHandler.sendMessage(msg);
}
installStage通过PMS的handle发送INIT_COPY,将操作都交给了PMS。mHandler初始化在PackageManagerService的构造函数中。
//frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
mHandler = injector.getHandler();
//frameworks/base/services/core/java/com/android/server/pm/PackageManagerServiceInjector.java
public Handler getHandler() {
return mHandlerProducer.get(this, mPackageManager);
}
在上一篇中已经了解了injector就是PackageManagerServiceInjector,mHandlerProducer是在PackageManagerServiceInjector初始化的时候传入的。
(i, pm) -> {
HandlerThread thread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/);
thread.start();
return new PackageHandler(thread.getLooper(), pm);
}
mHandler就是一个PackageHandler变量,找到INIT_COPY。
INIT_COPY
//frameworks/base/services/core/java/com/android/server/pm/PackageHandler.java
void doHandleMessage(Message msg) {
switch (msg.what) {
case INIT_COPY: {
HandlerParams params = (HandlerParams) msg.obj;//InstallParams中传的是this
if (params != null) {
params.startCopy();
}
break;
}
....
}
//frameworks/base/services/core/java/com/android/server/pm/HandlerParams.java
final void startCopy() {
handleStartCopy();//调用的就是InstallParams的handleStartCopy
handleReturnCode();//InstallParams的handleReturnCode
}
回到InstallParams中看下实现
public void handleStartCopy() {
//获取基础的包信息
PackageInfoLite pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mPm.mContext,
mPackageLite, mOriginInfo.mResolvedPath, mInstallFlags, mPackageAbiOverride);
....
mRet = overrideInstallLocation(pkgLite.packageName, pkgLite.recommendedInstallLocation,
pkgLite.installLocation);//覆盖安装的话要根据原来的安装信息修改
}
handleStartCopy只是一些准备操作,实际copy在handleReturnCode
//frameworks/base/services/core/java/com/android/server/pm/InstallParams.java
@Override
void handleReturnCode() {
processPendingInstall();
}
private void processPendingInstall() {
InstallArgs args = createInstallArgs(this);//创建的是一个FileInstallArgs
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
mRet = args.copyApk();//FileInstallArgs的copy复制apk
}
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)));//安装
}
}
copyApk
//frameworks/base/services/core/java/com/android/server/pm/FileInstallArgs.java
int copyApk() {
return doCopyApk();
}
private int doCopyApk() {
.....
final boolean isEphemeral = (mInstallFlags & PackageManager.INSTALL_INSTANT_APP) != 0; //创建目录
final File tempDir =
mPm.mInstallerService.allocateStageDirLegacy(mVolumeUuid, isEphemeral);
mCodeFile = tempDir;
//复制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);//创建lib目录
NativeLibraryHelper.Handle handle = null;
handle = NativeLibraryHelper.Handle.create(mCodeFile);
ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
mAbiOverride, isIncremental);//复制so库
return ret;
}
//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);
final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
final ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite(
input.reset(), packageFile, /* flags */ 0);//获取简单解析结果和PMS启动时一样
final PackageLite pkg = result.getResult();
copyFile(pkg.getBaseApkPath(), targetDir, "base.apk");//复制apk到目标目录下,apk文件名是base.apk,所以在手机中安装之后apk都叫base.apk
return PackageManager.INSTALL_SUCCEEDED;
}
processInstallRequestsAsync
//frameworks/base/services/core/java/com/android/server/pm/InstallParams.java
private void processInstallRequestsAsync(boolean success,
List<InstallRequest> installRequests) {
mPm.mHandler.post(() -> {
mInstallPackageHelper.processInstallRequests(success, installRequests);
});
//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
public void processInstallRequests(boolean success, List<InstallRequest> installRequests) {
.....
if (success) {
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));
}
}
其中安装部分分三步
- doPreInstall 清除无用信息
- installPackagesTracedLI 执行安装
- doPostInstall
//frameworks/base/services/core/java/com/android/server/pm/FileInstallArgs.java
int doPreInstall(int status) {
if (status != PackageManager.INSTALL_SUCCEEDED) {
cleanUp();
}
return status;
}
重点是installPackagesTracedLI
//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
private void installPackagesTracedLI(List<InstallRequest> requests) {
installPackagesLI(requests);
}
private void installPackagesLI(List<InstallRequest> requests) {
boolean success = false;
try {
for (InstallRequest request : requests) {
final PrepareResult prepareResult;
prepareResult =
preparePackageLI(request.mArgs, request.mInstallResult);//预处理数据
request.mInstallResult.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
request.mInstallResult.mInstallerPackageName =
request.mArgs.mInstallSource.installerPackageName;
final String packageName = prepareResult.mPackageToScan.getPackageName();
prepareResults.put(packageName, prepareResult);
installResults.put(packageName, request.mInstallResult);
installArgs.put(packageName, request.mArgs);
try {
final ScanResult result = scanPackageTracedLI(
prepareResult.mPackageToScan, prepareResult.mParseFlags,
prepareResult.mScanFlags, System.currentTimeMillis(),
request.mArgs.mUser, request.mArgs.mAbiOverride);//scan包数据
createdAppId.put(packageName, optimisticallyRegisterAppId(result));
versionInfos.put(result.mPkgSetting.getPkg().getPackageName(),
mPm.getSettingsVersionForPackage(result.mPkgSetting.getPkg()));
} catch (PackageManagerException e) {
request.mInstallResult.setError("Scanning Failed.", e);
return;
}
}
ReconcileRequest reconcileRequest = new ReconcileRequest(preparedScans, installArgs,
installResults, prepareResults,
Collections.unmodifiableMap(mPm.mPackages), versionInfos);//调和数据
CommitRequest commitRequest = null;
synchronized (mPm.mLock) {
Map<String, ReconciledPackage> reconciledPackages;
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
reconciledPackages = ReconcilePackageUtils.reconcilePackages(
reconcileRequest, mSharedLibraries,
mPm.mSettings.getKeySetManagerService(), mPm.mSettings);
} catch (ReconcileFailure e) {
for (InstallRequest request : requests) {
request.mInstallResult.setError("Reconciliation failed...", e);
}
return;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "commitPackages");
commitRequest = new CommitRequest(reconciledPackages,
mPm.mUserManager.getUserIds());
commitPackagesLocked(commitRequest);//更新包信息
success = true;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
executePostCommitSteps(commitRequest);//完成安装
} finally {
}
}
这里又分为5步
- preparePackageLI
- scanPackageTracedLI
- ReconcileRequest
- commitPackagesLocked
- executePostCommitSteps
preparePackageLI
这个方法特别长
//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res)
throws PrepareFailure {
.....
final ParsedPackage parsedPackage;//获取PackageParser2来解析文件
try (PackageParser2 pp = mPm.mInjector.getPreparingPackageParser()) {
parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false);
AndroidPackageUtils.validatePackageDexMetadata(parsedPackage);
} catch (PackageManagerException e) {
throw new PrepareFailure("Failed parse during installPackageLI", e);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
....
if (parsedPackage.isStaticSharedLibrary()) {//静态共享库
// Static shared libraries have synthetic package names
PackageManagerService.renameStaticSharedLibraryPackage(parsedPackage);
}
boolean systemApp = false;
boolean replace = false;
synchronized (mPm.mLock) {
if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {//覆盖安装
....
if (replace) {//判断覆盖安装的各种异常
....
}
}
PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName);
PackageSetting signatureCheckPs = ps;
if (parsedPackage.isStaticSharedLibrary()) {//共享库升级
SharedLibraryInfo libraryInfo =
mSharedLibraries.getLatestStaticSharedLibraVersionLPr(parsedPackage);
if (libraryInfo != null) {
signatureCheckPs = mPm.mSettings.getPackageLPr(libraryInfo.getPackageName());
}
}
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");
}
}
}
//下面是权限相关代码,太长了就不详细看了
....
if (args.mMoveInfo != null) {
scanFlags |= SCAN_NO_DEX;
scanFlags |= SCAN_MOVE;
synchronized (mPm.mLock) {
final PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName);
//设置abi
parsedPackage.setPrimaryCpuAbi(ps.getPrimaryCpuAbi())
.setSecondaryCpuAbi(ps.getSecondaryCpuAbi());
}
} else {
// Enable SCAN_NO_DEX flag to skip dexopt at a later stage
scanFlags |= SCAN_NO_DEX;
try {
final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths>
derivedAbi = mPackageAbiHelper.derivePackageAbi(parsedPackage,
isUpdatedSystemAppFromExistingSetting || isUpdatedSystemAppInferred,
abiOverride, ScanPackageUtils.getAppLib32InstallDir());//生成安装包Abi
derivedAbi.first.applyTo(parsedPackage);
derivedAbi.second.applyTo(parsedPackage);
}
}
final PackageFreezer freezer =
freezePackageForInstall(pkgName, installFlags, "installPackageLI");
boolean shouldCloseFreezerBeforeReturn = true;
try {
if (replace) {//如果是替换安装证书之类的处理
} else { // 新包安装
}
return new PrepareResult(replace, targetScanFlags, targetParseFlags,
oldPackage, parsedPackage, replace /* clearCodeCache */, sysPkg,
ps, disabledPs);
} finally {
}
}
}
准备工作完成。接下来扫描apk
scanPackageTracedLI
private ScanResult scanPackageTracedLI(ParsedPackage parsedPackage,
final @ParsingPackageUtils.ParseFlags int parseFlags,
@PackageManagerService.ScanFlags int scanFlags, long currentTime,
@Nullable UserHandle user, String cpuAbiOverride) throws PackageManagerException {
return scanPackageNewLI(parsedPackage, parseFlags, scanFlags, currentTime, user,
cpuAbiOverride);
}
private ScanResult scanPackageNewLI(@NonNull ParsedPackage parsedPackage,
final @ParsingPackageUtils.ParseFlags int parseFlags,
@PackageManagerService.ScanFlags int scanFlags, long currentTime,
@Nullable UserHandle user, String cpuAbiOverride)
throws PackageManagerException {
....
synchronized (mPm.mLock) {
.....
return ScanPackageUtils.scanPackageOnlyLI(request, mPm.mInjector, mPm.mFactoryTest,
currentTime);
}
}
具体的扫描在scanPackageOnlyLI中
//frameworks/base/services/core/java/com/android/server/pm/ScanPackageUtils.java
public static ScanResult scanPackageOnlyLI(@NonNull ScanRequest request,
PackageManagerServiceInjector injector,
boolean isUnderFactoryTest, long currentTime)
throws PackageManagerException {
......
// Initialize package source and resource directories
final File destCodeFile = new File(parsedPackage.getPath());//初始化目标文件夹
final UUID newDomainSetId = injector.getDomainVerificationManagerInternal().generateNewId();
final boolean createNewPackage = (pkgSetting == null);
if (createNewPackage) {//如果是新的apk
final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;
final boolean virtualPreload = (scanFlags & SCAN_AS_VIRTUAL_PRELOAD) != 0;
int pkgFlags = PackageInfoUtils.appInfoFlags(parsedPackage, null);
int pkgPrivateFlags = PackageInfoUtils.appInfoPrivateFlags(parsedPackage, null);
pkgSetting = Settings.createNewSetting(parsedPackage.getPackageName(),
originalPkgSetting, disabledPkgSetting, realPkgName, sharedUserSetting,
destCodeFile, parsedPackage.getNativeLibraryRootDir(),
AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage),
AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage),
parsedPackage.getLongVersionCode(), pkgFlags, pkgPrivateFlags, user,
true /*allowInstall*/, instantApp, virtualPreload,
UserManagerService.getInstance(), usesSdkLibraries,
parsedPackage.getUsesSdkLibrariesVersionsMajor(), usesStaticLibraries,
parsedPackage.getUsesStaticLibrariesVersions(), parsedPackage.getMimeGroups(),
newDomainSetId);//创建一个新的PackageSetting,保存了包所以的配置
} else {//如果已存在就更新setting
...
}
final int userId = (user == null ? UserHandle.USER_SYSTEM : user.getIdentifier());
pkgSetting.setLegacyNativeLibraryPath(parsedPackage.getNativeLibraryRootDir());
// 更新安装时间
final long scanFileTime = getLastModifiedTime(parsedPackage);
final long existingFirstInstallTime = userId == UserHandle.USER_ALL
? PackageStateUtils.getEarliestFirstInstallTime(pkgSetting.getUserStates())
: pkgSetting.readUserState(userId).getFirstInstallTime();
if (currentTime != 0) {
if (existingFirstInstallTime == 0) {
pkgSetting.setFirstInstallTime(currentTime, userId)
.setLastUpdateTime(currentTime);
} else if ((scanFlags & SCAN_UPDATE_TIME) != 0) {
pkgSetting.setLastUpdateTime(currentTime);
}
} else if (existingFirstInstallTime == 0) {
// We need *something*. Take time stamp of the file.
pkgSetting.setFirstInstallTime(scanFileTime, userId)
.setLastUpdateTime(scanFileTime);
} else if ((parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) != 0) {
if (scanFileTime != pkgSetting.getLastModifiedTime()) {
// A package on the system image has changed; consider this
// to be an update.
pkgSetting.setLastUpdateTime(scanFileTime);
}
}
pkgSetting.setLastModifiedTime(scanFileTime);
pkgSetting.setPkg(parsedPackage)
.setPkgFlags(PackageInfoUtils.appInfoFlags(parsedPackage, pkgSetting),
PackageInfoUtils.appInfoPrivateFlags(parsedPackage, pkgSetting));
if (parsedPackage.getLongVersionCode() != pkgSetting.getVersionCode()) {
//更新VersionCode
pkgSetting.setLongVersionCode(parsedPackage.getLongVersionCode());
}
return new ScanResult(request, true, pkgSetting, changedAbiCodePath,
!createNewPackage /* existingSettingCopied */,
Process.INVALID_UID /* previousAppId */ , sdkLibraryInfo,
staticSharedLibraryInfo, dynamicSharedLibraryInfos);
}
一个apk所有的信息都已经解析出来保存了起来,利用commitPackagesLocked提交
commitPackagesLocked
private void commitPackagesLocked(final CommitRequest request) {
for (ReconciledPackage reconciledPkg : request.mReconciledPackages.values()) {
.....
// 如果有老的包就删除
deletePackageHelper.executeDeletePackageLIF(
reconciledPkg.mDeletePackageAction, packageName,
true, request.mAllUsers, false);
AndroidPackage pkg = commitReconciledScanResultLocked(
reconciledPkg, request.mAllUsers);//提交结果
updateSettingsLI(pkg, reconciledPkg, request.mAllUsers, res);//更新Settings
....
}
commitPackagesLocked主要功能就是删除老包,将解析出来的settings提交给PMS
executePostCommitSteps
private void executePostCommitSteps(CommitRequest commitRequest) {
final ArraySet<IncrementalStorage> incrementalStorages = new ArraySet<>();
for (ReconciledPackage reconciledPkg : commitRequest.mReconciledPackages.values()) {
// 创建AppData相关文件夹
mAppDataHelper.prepareAppDataPostCommitLIF(pkg, 0);
//创建AppProfile文件
mArtManagerService.prepareAppProfiles(
pkg,
mPm.resolveUserIds(reconciledPkg.mInstallArgs.mUser.getIdentifier()),
/* updateReferenceProfileContent= */ true);
//判断是否需要执行Dexopt
final int dexoptFlags = DexoptOptions.DEXOPT_BOOT_COMPLETE
| DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE
| (isBackupOrRestore ? DexoptOptions.DEXOPT_FOR_RESTORE : 0);
DexoptOptions dexoptOptions =
new DexoptOptions(packageName, compilationReason, dexoptFlags);
if (performDexopt) {/
....
mPackageDexOptimizer.performDexOpt(pkg, realPkgSetting,
null /* instructionSets */,
mPm.getOrCreateCompilerPackageStats(pkg),
mDexManager.getPackageUseInfoOrDefault(packageName),
dexoptOptions);//执行DexOpt
}
//notify包更新的消息
BackgroundDexOptService.getService().notifyPackageChanged(packageName);
notifyPackageChangeObserversOnUpdate(reconciledPkg);
}
PackageManagerServiceUtils.waitForNativeBinariesExtractionForIncremental(
incrementalStorages);
}
主要看下prepareAppDataPostCommitLIF
//frameworks/base/services/core/java/com/android/server/pm/AppDataHelper.java
public void prepareAppDataPostCommitLIF(AndroidPackage pkg, int previousAppId) {
final PackageSetting ps;
synchronized (mPm.mLock) {
ps = mPm.mSettings.getPackageLPr(pkg.getPackageName());
mPm.mSettings.writeKernelMappingLPr(ps);
}
for (UserInfo user : umInternal.getUsers(false /*excludeDying*/)) {
if (ps.getInstalled(user.id)) {//获取
//创建AppData文件夹
prepareAppData(batch, pkg, previousAppId, user.id, flags).thenRun(() -> {
//完成之后的回调
if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
int uid = UserHandle.getUid(user.id, UserHandle.getAppId(pkg.getUid()));
smInternal.prepareAppDataAfterInstall(pkg.getPackageName(), uid);
}
});
}
}
}
private @NonNull CompletableFuture<?> prepareAppData(@NonNull Installer.Batch batch,
@Nullable AndroidPackage pkg, int previousAppId, int userId,
@StorageManager.StorageFlags int flags) {
return prepareAppDataLeaf(batch, pkg, previousAppId, userId, flags);
}
private @NonNull CompletableFuture<?> prepareAppDataLeaf(@NonNull Installer.Batch batch,
@NonNull AndroidPackage pkg, int previousAppId, int userId, int flags) {
return batch.createAppData(args).whenComplete((ceDataInode, e) -> {
}
创建的是一个 CompletableFuture,看下execute
public synchronized void execute(@NonNull Installer installer) throws InstallerException {
mExecuted = true;
final CreateAppDataResult[] results = installer.createAppDataBatched(args);
}
经过层层调用到Installd服务的createAppDataBatched
//frameworks/native/cmds/installd/InstalldNativeService.cpp
binder::Status InstalldNativeService::createAppDataBatched(
const std::vector<android::os::CreateAppDataArgs>& args,
std::vector<android::os::CreateAppDataResult>* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
// Locking is performed depeer in the callstack.
std::vector<android::os::CreateAppDataResult> results;
for (const auto &arg : args) {
android::os::CreateAppDataResult result;
createAppData(arg, &result);//会根据packagename创建/data/app/<packageName>等目录
results.push_back(result);
}
*_aidl_return = results;
return ok();
}
这样经过漫长的调用一次安装就结束了。