代码不是连续的。
开始。
adb install *.apk.
1,commandline.c
int adb_commandline(int argc, char **argv){
...
if(!strcmp(argv[0],"install")){
return install_app(ttpye,serial,argc,argv);
}
...
}
int install_app(transport_type transport,char * serial,int argc,char ** argv){
static const char *const DATA_DEST = "/data/local/tmp/%s"
static const char *const SD_DEST = "/sdcard/tmp/%s"
...
apk_file = argv[file_arg];//获取apk全路径:/../*.apk
//将apk传送到手机的目标路径
err = do_sync_push(apk_file,apk_dest,1/*verify APK */);
//执行脚本pm,安装apk
pm_command(transport,serial,argc,argv);
//delete that apk
delete_file(transport,serial,apk_dest);
}
static int pm_command(...){
//执行pm.java的main()
send_shellcommand(transport,serial,buf);
}
2,pm.java
public static void main(String[] args){
new Pm().run(args);
}
public void run(String[] args){
//获取PKMS的binder客户端
mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
...
runInstall();//安装
...
}
private void runInstall(){
...
//监视安装情况
PackageInstallObserver obs = new PackageInstallObserver()
try{//安装
mPm.installPackageWithVerification(apkURI,obs,installFlags,installerPackageName,verificationURI,null);
...
}
}
}
3,PackageManagerService.java
public void installPackageWithVerification(...){
...
//mHandler之前提过,构造函数的时候开启的,用于apk的安装卸载
final Message msg = mHandler.obtainMessage(INIT_COPY);
msg.obj = new InstallParams(packageURI,observer,filteredFlags,installerPackageName,verificationURI,manifestDigest):
mHandler.sendMessage(msg);
}
public void handleMessage(Message msg){
try{
doHandleMessage(msg);
}
}
void doHandleMessage(Message msg){
...
case INIT_COPY:
//先处理等待安装的包
int idx = mPendingInstalls.size()
//连接到DefaultContainerService服务,主要作用是为apk选择最好的安装位置。
if(!connectToSerivice())
//存在等待安装的包就把这个apk加到等待队里
mPendingInstalls.add(idx,params);
//没有等待的包就安装
mHandler.sendEmptyMessage(MCS_BOUND);
case MCS_BOUND:
...
if(params.startCopy())//安装
...
}
final boolean startCopy(){
...
handleStartCopy();
...
handleReturnCode();
//处理安装完毕
case POST_INSTALL:
//会判断是否是update,在extras里区分
//发送PACKAGE_ADDED广播
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,res.pkg.applicationInfo.packageName,extras,null,null);
...
//清理资源
res.removedInfo.args.doPostDeleteLI(true);
...
//通知pm安装结果
args.observer.packageInstalled(res.name,res.returnCode);
}
public void handleStartCopy(){//InstallParams.handleStartCopy
//一系列检查判断,安装位置SD卡or Interanl存储
//存储空间剩余量
...
//得到PackageInfoLite对象。这个对象继承自Parcelable,用于描述apk的结构
pkgLite = mContainerService.getMinimalPackageInfo(packageURI,flags,lowThreshold);
//获得apk的建议路径
int loc = pkgLite.recommendedInstallLocation;
...
//创建InstallArgs对象,Internal存储为FileInstallArgs ,SD卡存储为SdInstallArgs.
final InstallArgs args = createInstallArgs(this);
...
ret = args.copyApk(mContainerService,true);//安装
}
void handleReturnCode(){//InstallParams.HandleParams
...
processPendingInstall(mArgs,mRet);
}
private void processPendingInstall(...){
mHandler.post(new Runnable(){
public void run(){
...
args.doPreInstall(res.returnCode);//上面的mArgs
synchronized(mInstallLock){
installPackageLI(args,true,res);//安装
}
args.doPostInstall(res.returnCode);
...
//安装完毕发消息
Message msg = mHandler.obtainMessage(POST_INSTALL,token,0);
mHandler.sendMessage(msg);
}
});
}
private void installPackageLI(...){
//做了两个主要操作
//1,调用doRename对临时文件进行改名。
if(!args.doRename(res.returnCode,pkgName,oldCodePath))
//2,安装:replace or install new
//无论是哪个最终会调用上一节学习PKMS构造函数时调用的核心函数scanPackageLI(),完成自己apk信息上报,公有化。apk安装完毕。
if(replace){
replacePackageLI(...);
}esle{
installNewPackageLI(...)
}
}
4,DefaultContainerService.java
3中涉及的几个函数。
public PackageInfoLite getMinimalPackageInfo(...){ PackageInfoLite ret = new PackageInfoLite(); ... //archiveFilePath由传进来的fileUri即packURI获得,fileUri指向/data/local/tmp/*.apk String archiveFilePath = fileUri.getPath(); PackageParser.PackageLite pkg = PackageParser.parsePackageLite(archiveFilePath,0); ret.recommandedInstallLocation = recommendAppInstallLocation(pkg.installLocation,archiveFilePath,flags,threshold); private int recommandAppInstallLocation(...){ int prefer;//最好的位置 //在 //pkg.installLocation check_inner:{ ... } //和Settings数据库中设置的安装位置 int installPreference = Settings.System.getInt(); } //中选择 ... //最后判断是否有足够空间 ... }
最后上个萌图