1. PMSインストールAPPフローチャート
2. ファイルのコピー
PMS処理インストールHandlerParamsインストールパラメータフローチャート
PackageManagerService.java#installStage メソッドの概要
1. InstallParams オブジェクトが作成されます
2. INIT_COPY メッセージが作成され、送信されます。
3. InstallParams は HandlerParams から継承し、アプリケーションをインストールするためのパラメータを記録するために使用されます。InstallParams にはメンバー変数 mArgs があり、これは抽象型 InstallArgs であり、主に APK をコピーするために使用されます。実際の実装クラスには次のものが含まれます: FileInstallArgs:非 ASEC アプリケーション
のインストールを完了するために使用されます。ASEC の正式名は Android です
安全な外部キャッシュ
MoveInstallArgs: インストールされたアプリのモバイル インストールを完了するために使用されます
void installStage(String packageName, File stagedDir, String stagedCid,
IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
String installerPackageName, int installerUid, UserHandle user,
Certificate[][] certificates) {
...
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);
}
PackageManagerService.java#PackageHandler
connectToService(): リムーバブル ファイルのチェックとコピーに使用されるサービス
MCS_BOUND 情報を送信し、最初のインストール要求の処理をトリガーします
void doHandleMessage(Message msg) {
switch (msg.what) {
case INIT_COPY: {
HandlerParams params = (HandlerParams) msg.obj;
int idx = mPendingInstalls.size();
if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
//mBound用于标识是否绑定了服务,默认值为false
if (!mBound) {
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
System.identityHashCode(mHandler));
//connectToService里面的DefaultContainerService是用于检查和复制可移动文件的服务
if (!connectToService()) {
Slog.e(TAG, "Failed to bind to media container service");
params.serviceError();
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
System.identityHashCode(mHandler));
if (params.traceMethod != null) {
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod,
params.traceCookie);
}
//绑定服务失败则return
return;
} else {
//绑定服务成功,将请求添加到ArrayList类型的mPendingInstalls中,等待处理
mPendingInstalls.add(idx, params);
}
} else {
//已经绑定服务
mPendingInstalls.add(idx, params);
if (idx == 0) {
//5
//发送MCS_BOUND类型的消息,触发处理第一个安装请求
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
break;
}
....
}
}
}
MCS_BOUND プロセスの処理:
case MCS_BOUND: {
if (mContainerService == null) {
//判断是否已经绑定了服务
if (!mBound) {
//绑定服务的标识位,没有绑定成功
Slog.e(TAG, "Cannot bind to media container service");
for (HandlerParams params : mPendingInstalls) {
params.serviceError();
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(params));
if (params.traceMethod != null) {
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER,
params.traceMethod, params.traceCookie);
}
return;
}
//绑定失败,清空安装请求队列
mPendingInstalls.clear();
} else {
// 绑定成功
//继续等待绑定服务
Slog.w(TAG, "Waiting to connect to media container service");
}
} else if (mPendingInstalls.size() > 0) {
//安装APK的队列
HandlerParams params = mPendingInstalls.get(0); //安装队列有参数
if (params != null) {
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(params));
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
if (params.startCopy()) {
//HandlerParams开始拷贝
if (DEBUG_SD_INSTALL) Log.i(TAG,
"Checking for more work or unbind...");
//如果APK安装成功,删除本次安装请求
if (mPendingInstalls.size() > 0) {
mPendingInstalls.remove(0);
}
if (mPendingInstalls.size() == 0) {
//安装队列没有参数
if (mBound) {
//已经绑定服务,需要发送一个解绑MCS_UNBIND的message
//如果没有安装请求了,发送解绑服务的请求
if (DEBUG_SD_INSTALL) Log.i(TAG,
"Posting delayed MCS_UNBIND");
removeMessages(MCS_UNBIND);
Message ubmsg = obtainMessage(MCS_UNBIND);
sendMessageDelayed(ubmsg, 10000);
}
} else {
if (DEBUG_SD_INSTALL) Log.i(TAG,
"Posting MCS_BOUND for next work");
//如果还有其他的安装请求,接着发送MCS_BOUND消息继续处理剩余的安装请求
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}else {
Slog.w(TAG, "Empty queue");
}
break;
}
PMS が APP のコピーを処理するフローチャート
DefaultContainerService: APP ファイルのコピーを実際に処理するクラス
PackageManagerService.java#HandlerParams#startCopy
1. インストール試行回数が 4 回を超えた場合、インストール済みリスト データを削除します。
2. handleStartCopy: //APK ファイルをコピーします
。 3. handleReturnCode: //APK のインストールを開始します。
final boolean startCopy() {
boolean res;
try {
if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
//startCopy方法尝试的次数,超过了4次,就放弃这个安装请求
if (++mRetries > MAX_RETRIES) {
Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
mHandler.sendEmptyMessage(MCS_GIVE_UP); //发送放弃安装信息
handleServiceError();
return false;
} else {
handleStartCopy(); //复制APK文件
res = true;
}
} catch (RemoteException e) {
if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
mHandler.sendEmptyMessage(MCS_RECONNECT);
res = false;
}
handleReturnCode(); //处理复制APK后的安装APK逻辑
return res;
}
PackageManagerService.java#InstallParams#handleStartCopy
1. APP のインストール情報の一部を取得します。
2. APP のインストール場所を取得します
。 3. InstallArgs によって APP をコピーします ----> FileInstallArgs によって APP をコピーします ----> DefaultContainerService APP
InstallArgs を抽象としてコピーしますクラス、FileInstallArgs および MoveInstallArgs は、InstallArgs を継承します
FileInstallArgs: はい データ/データ/パッケージ名 (システム アプリケーション)
MoveInstallArgs : インストールされた APK の移動を処理するために使用されます
public void handleStartCopy() throws RemoteException {
...
//确定APK的安装位置。onSd:安装到SD卡, onInt:内部存储即Data分区,ephemeral:安装到临时存储(Instant Apps安装)
final boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;
final boolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
PackageInfoLite pkgLite = null;
if (onInt && onSd) {
// APK不能同时安装在SD卡和Data分区
Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
//安装标志冲突,Instant Apps不能安装到SD卡中
} else if (onSd && ephemeral) {
Slog.w(TAG, "Conflicting flags specified for installing ephemeral on external");
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} else {
//获取APK的少量的信息
pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
packageAbiOverride);
if (DEBUG_EPHEMERAL && ephemeral) {
Slog.v(TAG, "pkgLite for install: " + pkgLite);
}
...
if (ret == PackageManager.INSTALL_SUCCEEDED) {
//判断安装的位置
int loc = pkgLite.recommendedInstallLocation;
if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
}
...
}else{
loc = installLocationPolicy(pkgLite); //确定APP安装的位置
...
}
}
//根据InstallParams创建InstallArgs对象
final InstallArgs args = createInstallArgs(this); InstallArgs作用时:复制和重命名APK
mArgs = args;
if (ret == PackageManager.INSTALL_SUCCEEDED) {
...
if (!origin.existing && requiredUid != -1
&& isVerificationEnabled(
verifierUser.getIdentifier(), installFlags, installerUid)) {
...
} else{
ret = args.copyApk(mContainerService, true); // InstallArgs开始复制APP
}
}
mRet = ret;
}
private int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
...
try {
final boolean isEphemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
//创建临时文件存储目录
final File tempDir =
mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral);
codeFile = tempDir;
resourceFile = tempDir;
} catch (IOException e) {
Slog.w(TAG, "Failed to create copy file: " + e);
return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
}
...
int ret = PackageManager.INSTALL_SUCCEEDED;
ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);
...
return ret;
}
3.APKをインストールする
APP安装流程图
1. インストール前に環境が信頼できるかどうかを確認し、信頼できない場合はコピーした APK ファイルが消去されます。
2. installPackageTracedLI は、PMS の installPackageLI メソッドを内部的に呼び出して、APP をインストールします。
3. インストール後の操作を処理します。インストールが失敗した場合は、インストール関連のディレクトリとファイルを削除します。
final boolean startCopy() {
......
handleStartCopy(); //APP文件复制拷贝
.....
//开始安装APP
handleReturnCode();
}
void handleReturnCode() {
........
if (mArgs != null) {
processPendingInstall(mArgs, mRet);
}
}
private void processPendingInstall(final InstallArgs args, final int currentStatus) {
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
PackageInstalledInfo res = new PackageInstalledInfo();
res.setReturnCode(currentStatus);
res.uid = -1;
res.pkg = null;
res.removedInfo = null;
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
//安装前处理
args.doPreInstall(res.returnCode);
synchronized (mInstallLock) {
//开始安装
installPackageTracedLI(args, res);
}
//安装后收尾
args.doPostInstall(res.returnCode, res.uid);
}
...
}
});
}