PMS(PackageManagerService)是Android担保理机造的焦点,负责对于包入止打点。
PMS安拆APP流程
- 猎取APK文件:正在运用程序安拆以前,须要先猎取APK文件。APK文件是Android运用程序的安拆包,包罗了使用程序的代码以及资源文件。
- 解析APK文件:PMS需求对于APK文件入止解析,以猎取运用程序的疑息以及组件疑息,比如运用程序包名、版原号、权限列表、组件列表(如Activity、Service、Receiver等)。那一步凡是由PackageParser类实现。
- 校验利用程序署名:正在安拆以前,PMS会校验使用程序的署名,以确保运用程序不被窜改或者伪拆。署名校验是担保运用程序保险性的首要步伐。
- 安拆利用:如何校验经由过程,PMS会为运用程序分派一个UID,并连续入止安拆进程。那凡是触及文件复造、处置安拆参数等步伐。
文件复造
PackageManagerService.java#installStage安拆阶段:
- 建立了一个InstallParams器材
- 创立并领送了一个INIT_COPY的Message动静。
- InstallParams承继自HandlerParams,用来记载安拆使用的参数。
InstallParams外有一个成员变质mArgs,是一个形象范例InstallArgs,首要是用来执止APK的复造,真实的完成类包罗FileInstallArgs用来实现非ASEC运用的安拆,ASEC齐称是Android Secure External Cache,MoveInstallArgs用来实现未安拆运用的挪动安拆。
void installStage(String packageName, File stagedDir, String stagedCid,
IPackageInstallObserver两 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;
DefaultContainerService: 实邪处置惩罚复造APP文件的类
PackageManagerService.java#HandlerParams#startCopy入手下手复造:
- 测验考试安拆次数能否跨越4次,逾越便移除了安拆的列表数据
- handleStartCopy : //复造APK文件
- 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复造apk文件:
- 猎取APP的部门安拆疑息
- 猎取APP的安拆职位地方
- InstallArgs复造APP----> FileInstallArgs复造APP---->DefaultContainerService复造APP
InstallArgs作为形象类,FileInstallArgs以及MoveInstallArgs承继InstallArgs FileInstallArgs对于data/data/包名(体系运用),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.reco妹妹endedInstallLocation;
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;
}
安拆APK
- 正在安拆前查抄能否情况的靠得住,若何不成靠会铲除复造的APK文件。
- installPackageTracedLI其外部会挪用PMS的installPackageLI办法,入止APP安拆。
- 处置惩罚安拆后操纵,假定安拆不行罪,增除了失落安拆相闭的目次取文件。
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);
}
...
}
});
}
发表评论 取消回复