Android-Apk的安装流程分析(二)

更新时间:2023-07-17 13:50:51 阅读: 评论:0

Android-Apk的安装流程分析(⼆)
接着上节的内容来说,之前说到了PackageInstallerSession中调⽤PackageManaPgerService(简称PMS)的installStage这个⽅法来完成后续的安装流程
下⾯的流程基本的都是在PMS中进⾏的,我们来看下流程
1、PackageManaPgerService#installStage
void installStage(String packageName, File stagedDir, String stagedCid,
IPackageInstallObrver2 obrver, PackageInstaller.SessionParams ssionParams,
String installerPackageName, int installerUid, UrHandle ur,
Certificate[][] certificates) {
if (DEBUG_EPHEMERAL) {
if ((ssionParams.installFlags & PackageManager.INSTALL_EPHEMERAL) != 0) {
Slog.d(TAG, "Ephemeral install of " + packageName);
}
}
final VerificationInfo verificationInfo = new VerificationInfo(
final OriginInfo origin;
if (stagedDir != null) {
origin = OriginInfo.fromStagedFile(stagedDir);
} el {
origin = OriginInfo.fromStagedContainer(stagedCid);
}
final Message msg = mHandler.obtainMessage(INIT_COPY);
乐善好施
//实例化⼀个安装参数,⾥⾯有传进来的安装信息
final InstallParams params = new InstallParams(origin, null, obrver,
ssionParams.installFlags, installerPackageName, ssionParams.volumeUuid,
verificationInfo, ur, ssionParams.abiOverride,
params.tTraceMethod("installStage").tTraceCookie(System.identityHashCode(params));
msg.obj = params;
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStage",
System.identityHashCode(msg.obj));
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(msg.obj));
//发送⼀个INIT_COPY 的message
mHandler.ndMessage(msg);
}
这个⽅法就⼲了⼀个事情,发送了⼀个⾸次copy的消息,然后处理,看看这个handler怎么处理的
2、PackageManaPgerService#doHandleMessage
void doHandleMessage(Message msg){
switch(msg.what){
//这个就是发来的消息
ca INIT_COPY:{
HandlerParams params =(HandlerParams) msg.obj;
int idx = mPendingInstalls.size();
if(DEBUG_INSTALL) Slog.i(TAG,"init_copy idx="+ idx +": "+ params);
// If a bind was already initiated we dont really
// need to do anything. The pending install
// will be procesd later on.
//启动pms的时候 mContainerService 服务已经被绑定了
if(!mBound){
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER,"bindingMCS",
System.identityHashCode(mHandler));
// If this is the only one pending we might
// If this is the only one pending we might
/
/ have to bind to the rvice again.
// 尝试绑定服务,这⾥就是bindService
if(!connectToService()){
Slog.e(TAG,"Failed to bind to media container rvice");
params.rviceError();
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER,"bindingMCS",
System.identityHashCode(mHandler));
aceMethod != null){
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, aceMethod,                                        aceCookie);
}
return;
}el{
// Once we bind to the rvice, the first
// pending request will be procesd.
//绑定成功就添加⼀个待copy的apk 数据等待copy
//每次连接成功都会发送⼀个MCS_BOUND 消息然后处理copy任务,
mPendingInstalls.add(idx, params);
}
}el{
mPendingInstalls.add(idx, params);
// Already bound to the rvice. Just make
// sure we trigger off processing the first request.
银行不良资产if(idx ==0){
//触发下⾯的MCS_BOUND,进⾏拷贝apk,然后就是不断循环,消耗
mHandler.ndEmptyMessage(MCS_BOUND);
}
口渴的英语怎么说
}
break;
}
ca MCS_BOUND:{
if(DEBUG_INSTALL) Slog.i(TAG,"mcs_bound");
if(msg.obj != null){
mContainerService =(IMediaContainerService) msg.obj;
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER,"bindingMCS",
System.identityHashCode(mHandler));
}
将进酒ppt课件
if(mContainerService == null){
if(!mBound){
恍然大悟的反义词// Something riously wrong since we are not bound and we are not
// waiting for connection. Bail out.
Slog.e(TAG,"Cannot bind to media container rvice");
for(HandlerParams params : mPendingInstalls){
// Indicate rvice bind error
params.rviceError();
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER,"queueInstall",太极五章教学视频
System.identityHashCode(params));
aceMethod != null){
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER,
}
return;
}
mPendingInstalls.clear();
}el{
Slog.w(TAG,"Waiting to connect to media container rvice");
}
}el if(mPendingInstalls.size()>0){
HandlerParams params = (0);
if(params != null){
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER,"queueInstall",
System.identityHashCode(params));
//开始拷贝
if(params.startCopy()){
if(params.startCopy()){
// We   look for more work or to
/
/ go idle.
if(DEBUG_SD_INSTALL) Log.i(TAG,
"Checking for more work ");
// Delete pending install
if(mPendingInstalls.size()>0){
//拷贝成功了就移除拷贝任务数据
监督工作
}
if(mPendingInstalls.size()==0){
if(mBound){
if(DEBUG_SD_INSTALL) Log.i(TAG,
"Posting delayed MCS_UNBIND");
removeMessages(MCS_UNBIND);
Message ubmsg =obtainMessage(MCS_UNBIND);
// Unbind after a little delay, to avoid
// continual thrashing.
//数据没有了等待10s 就断开服务
ndMessageDelayed(ubmsg,10000);
}
}el{
// There are more pending requests in queue.
// Just post MCS_BOUND message to trigger processing
/
/ of next pending install.
if(DEBUG_SD_INSTALL) Log.i(TAG,
"Posting MCS_BOUND for next work");
//如果数据还有就继续执⾏下⼀个copy
mHandler.ndEmptyMessage(MCS_BOUND);
}
}
}
}el{
// Should never happen ideally.
Slog.w(TAG,"Empty queue");
}
break;
}
x
x
x
x
x
x
x 省略代码,,,
总结:
⽬的:把apk从PackageInstallerSession的暂存⽬录中 复制到data/app/ ⽬录下⾯ 或则sdcard的⽬录下⾯,这个根据安装参数的flag来区分,为后续⼯作做准备
过程:
1、这个复制的过程是交给DefaultContainerService 这个服务去做的,这个服务在单独的进程
2、每次需要复制的时候先连接服务
private boolean connectToService() {
if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
" DefaultContainerService");
Intent rvice = new Intent().tComponent(DEFAULT_CONTAINER_COMPONENT);
Process.tThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
//可以看到是通过bind⽅式的
if (mContext.bindServiceAsUr(rvice, mDefContainerConn,
Context.BIND_AUTO_CREATE, UrHandle.SYSTEM)) {
Process.tThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
mBound = true;
return true;
}
Process.tThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return fal;
}
3、然后启动了这个服务,在这个同时做了这个操作 mPendingInstalls.add(idx, params); 还有发送了⼀个MCS_BOUND消息给handler 执⾏拷贝,这个消息是绑定服务成功后做的事情
final private DefaultContainerConnection mDefContainerConn =
new DefaultContainerConnection();
class DefaultContainerConnection implements ServiceConnection {
public void onServiceConnected(ComponentName name, IBinder rvice) {
if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
IMediaContainerService imcs =
IMediaContainerService.Stub.asInterface(rvice);
//可以看到绑定成功发送了⼀个MCS_BOUND消息,可以完成后续的拷贝⼯作
mHandler.ndMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
}
public void onServiceDisconnected(ComponentName name) {
if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
}
}
4、MCS_BOUND 的指令下 最后调⽤了HandlerParams的startCopy⽅法,HandlerParams是⼀个抽象类,这⾥⽤的实现类是InstallParams ,这⾥多说⼀句HandlerParams的实现类有2种MeasureParams,和InstallParams ,
MeasureParams 是测量的作⽤,计算apk所占⽤的空间⼤⼩
InstallParams 是安装apk的拷贝作⽤,处理拷贝的任务
HandlerParams的startCopy⽅法最终会依次调⽤到handleStartCopy() 还有handleReturnCode() 两个⽅法
handleStartCopy处理拷贝,需要⼦类实现
handleReturnCode 处理返回结果,引发后续流程,需要⼦类实现
菲律宾黄岩岛5、InstallParams 的handleStartCopy
.
.....省略......
} el {
/*
* No package verification is enabled, so immediately start
* the remote call to initiate copy using temporary file.
*/
ret = pyApk(mContainerService, true);
}
我们看到这个arsg 其实是
final InstallArgs args = createInstallArgs(this);
createInstallArgs⽅法是
private InstallArgs createInstallArgs(InstallParams params) {
if (ve != null) {
return new MoveInstallArgs(params);
} el if (installOnExternalAc(params.installFlags) || params.isForwardLocked()) {            return new AcInstallArgs(params);
} el {
return new FileInstallArgs(params);
}
}
这⾥有三个实现类,
MoveInstallArgs :是处理已经安装了的apk的数据转移的
AcInstallArgs:这个是处理ac 就是在sdcard安装apk的拷贝类型FileInstallArgs:这个就是系统内存储的,拷贝到data/app/ 下的类型
我们就来看下FileInstallArgs类型的copyApk
最终 调⽤了doCopyApk,

本文发布于:2023-07-17 13:50:51,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1085127.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:拷贝   服务   安装   后续   处理
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图