PacakgeManagerService学习笔记七-APK installation
来源:互联网 发布:ocr文字识别软件mac版 编辑:程序博客网 时间:2024/04/30 06:45
1. adb install: adb intall有多个参数,只做简单学习,adb install xxx.apk, adb是一个命令,install是其参数。
/*--commandline.c--> adb_commandline*/
int adb_commandline(int argc, char **argv){/*-----------省略------------*/ if(!strcmp(argv[0], "install")) { if (argc < 2) return usage(); return install_app(ttype, serial, argc, argv); }/*-----------省略------------*/}int install_app(transport_type transport, char* serial, int argc, char** argv){/*将要安装的APK从host主机上,copy到手机中,需要先设置copy目录,如果要安装在内存中对应的目录为/data/local/tmp;如果要安装在sd卡中对应的目录为/sdcard/temp*/ static const char *const DATA_DEST = "/data/local/tmp/%s"; static const char *const SD_DEST = "/sdcard/tmp/%s"; const char* where = DATA_DEST; char apk_dest[PATH_MAX]; char verification_dest[PATH_MAX]; char* apk_file; char* verification_file = NULL; int file_arg = -1; int err; int i; int verify_apk = 1; for (i = 1; i < argc; i++) { if (*argv[i] != '-') { file_arg = i; break; } else if (!strcmp(argv[i], "-i")) { // Skip the installer package name. i++; } else if (!strcmp(argv[i], "-s")) { where = SD_DEST; } else if (!strcmp(argv[i], "--algo")) { verify_apk = 0; i++; } else if (!strcmp(argv[i], "--iv")) { verify_apk = 0; i++; } else if (!strcmp(argv[i], "--key")) { verify_apk = 0; i++; } } if (file_arg < 0) { fprintf(stderr, "can't find filename in arguments\n"); return 1; } else if (file_arg + 2 < argc) { fprintf(stderr, "too many files specified; only takes APK file and verifier file\n"); return 1; } apk_file = argv[file_arg]; if (file_arg != argc - 1) { verification_file = argv[file_arg + 1]; } if (check_file(apk_file) || check_file(verification_file)) { return 1; } snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file)); if (verification_file != NULL) { snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file)); if (!strcmp(apk_dest, verification_dest)) { fprintf(stderr, "APK and verification file can't have the same name\n"); return 1; } }/*如果有verification.apk,先做检查*/ err = do_sync_push(apk_file, apk_dest, verify_apk); if (err) { goto cleanup_apk; } else { argv[file_arg] = apk_dest; /* destination name, not source location */ } if (verification_file != NULL) { err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */); if (err) { goto cleanup_apk; } else { argv[file_arg + 1] = verification_dest; /* destination name, not source location */ } }/*执行pm脚本进行安装*/ pm_command(transport, serial, argc, argv);cleanup_apk: if (verification_file != NULL) { delete_file(transport, serial, verification_dest); } delete_file(transport, serial, apk_dest); return err;}
以上代码中的3个关键点:
1> android4.0新增了APK安装过程中的Verfication的功能。该功能就是在安装的过程中将相关信息发送给指定的Verfication程序(另外一个apk),由它对要安装的APK进行检查2> 调用pm_command进行安装
3> 安装完后,执行删除复制的临时文件
2. pm
static int pm_command(transport_type transport, char* serial, int argc, char** argv){ char buf[4096]; snprintf(buf, sizeof(buf), "shell:pm"); while(argc-- > 0) { char *quoted; quoted = dupAndQuote(*argv++); strncat(buf, " ", sizeof(buf)-1); strncat(buf, quoted, sizeof(buf)-1); free(quoted); }/*发送“shell:pm install 参数”到手持式终端*/ send_shellcommand(transport, serial, buf); return 0;}pm脚本:
/*pm脚本*//*#Script to start "pm" on the device, which has a very rudimentary(基本的)#shell#base=/systemexport CLASSPATH=$base/frameworks/pm.jar exec app_process $base/bin com.android.commands.pm.Pm “$@”*/该脚本通过app_process进程指向pm,jar中的main方法。
/*---------pm.java------------*/ public static void main(String[] args) { new Pm().run(args); } public void run(String[] args) { boolean validCommand = false; if (args.length < 1) { showUsage(); return; }/*获得binder客户端*/ mUm = IUserManager.Stub.asInterface(ServiceManager.getService("user")); mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); if (mPm == null) { System.err.println(PM_NOT_RUNNING_ERR); return; } mArgs = args; String op = args[0]; mNextArg = 1;......... if ("install".equals(op)) { runInstall(); return; }.........}
run方法中调用runInstall方法
1. 解析安装参数
2. 调用installPackageWithVerificationAndEncrytion完成后续的安装工作
private void runInstall() { int installFlags = PackageManager.INSTALL_ALL_USERS; String installerPackageName = null; String opt; String algo = null; byte[] iv = null; byte[] key = null; String macAlgo = null; byte[] macKey = null; byte[] tag = null; String originatingUriString = null; String referrer = null;/*省略部分该部分对安装参数进行解析*/ /*省略*/ final Uri apkURI; final Uri verificationURI; final Uri originatingURI; final Uri referrerURI; if (originatingUriString != null) { originatingURI = Uri.parse(originatingUriString); } else { originatingURI = null; } if (referrer != null) { referrerURI = Uri.parse(referrer); } else { referrerURI = null; } // Populate apkURI, must be present final String apkFilePath = nextArg(); System.err.println("\tpkg: " + apkFilePath); if (apkFilePath != null) { apkURI = Uri.fromFile(new File(apkFilePath)); } else { System.err.println("Error: no package specified"); return; } // Populate verificationURI, optionally present final String verificationFilePath = nextArg(); if (verificationFilePath != null) { System.err.println("\tver: " + verificationFilePath); verificationURI = Uri.fromFile(new File(verificationFilePath)); } else { verificationURI = null; }/*inofify机制,接收安装结果*/ PackageInstallObserver obs = new PackageInstallObserver(); try { VerificationParams verificationParams = new VerificationParams(verificationURI, originatingURI, referrerURI, VerificationParams.NO_UID, null);/*调用installPackageWithVerificationAndEncryption完成安装*/ mPm.installPackageWithVerificationAndEncryption(apkURI, obs, installFlags, installerPackageName, verificationParams, encryptionParams); synchronized (obs) { while (!obs.finished) { try { obs.wait(); } catch (InterruptedException e) { } } if (obs.result == PackageManager.INSTALL_SUCCEEDED) { System.out.println("Success"); } else { System.err.println("Failure [" + installFailureToString(obs.result) + "]"); } } } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); } }
installPackageWithVerfication:
/*PackageManagerService.java*/ public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer, int flags, String installerPackageName, Uri verificationURI, ManifestDigest manifestDigest) {/*检查客户端进程是否具有安装Package权限。*/ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null); final int uid = Binder.getCallingUid(); final int filteredFlags; if (uid == Process.SHELL_UID || uid == 0) { if (DEBUG_INSTALL) { Slog.v(TAG, "Install from ADB"); } filteredFlags = flags | PackageManager.INSTALL_FROM_ADB; } else { filteredFlags = flags & ~PackageManager.INSTALL_FROM_ADB; }/*创建一个Message对象,code = INIT_COPY,将该消息发送给PackageManagerService中的mHandler
创建一个InstallParams对象*/ final Message msg = mHandler.obtainMessage(INIT_COPY); msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName, verificationURI, manifestDigest); mHandler.sendMessage(msg); }
mHandler中的handleMessage中调用doHandleMessage方法:
1. INIT_COPY
void doHandleMessage(Message msg) { switch (msg.what) { case INIT_COPY: { if (DEBUG_INSTALL) Slog.i(TAG, "init_copy"); HandlerParams params = (HandlerParams) msg.obj; int idx = mPendingInstalls.size(); if (DEBUG_INSTALL) Slog.i(TAG, "idx=" + idx); // If a bind was already initiated we dont really // need to do anything. The pending install // will be processed later on. if (!mBound) { // If this is the only one pending we might // have to bind to the service again./*启动DefaultContainerService服务,通过bindService来启动*/ if (!connectToService()) { Slog.e(TAG, "Failed to bind to media container service"); params.serviceError(); return; } else { // Once we bind to the service, the first // pending request will be processed. mPendingInstalls.add(idx, params); } } else { mPendingInstalls.add(idx, params); // Already bound to the service. Just make // sure we trigger off processing the first request. if (idx == 0) { mHandler.sendEmptyMessage(MCS_BOUND); } } break; }/*---------省略---------*/}
connectToService方法:
private boolean connectToService() { if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" + " DefaultContainerService"); Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT); Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);/*mDefContainerConn:*/ if (mContext.bindService(service, mDefContainerConn, Context.BIND_AUTO_CREATE)) { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); mBound = true; return true; } Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); return false; }mDefContainerConn: DefaultContainerConnection,如果链接成功内部发送MCS_BOUND
final private DefaultContainerConnection mDefContainerConn = new DefaultContainerConnection(); class DefaultContainerConnection implements ServiceConnection { public void onServiceConnected(ComponentName name, IBinder service) { if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected"); IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(service);/*连接成功后,发送MCS_BOUND给mHandler*/ mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs)); } public void onServiceDisconnected(ComponentName name) { if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected"); } };
/*省略*/ case MCS_BOUND: { if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound"); if (msg.obj != null) { mContainerService = (IMediaContainerService) msg.obj; } if (mContainerService == null) {//服务没启动,不能安装 // Something seriously wrong. Bail out Slog.e(TAG, "Cannot bind to media container service"); for (HandlerParams params : mPendingInstalls) { mPendingInstalls.remove(0); // Indicate service bind error params.serviceError(); } mPendingInstalls.clear(); } else if (mPendingInstalls.size() > 0) { HandlerParams params = mPendingInstalls.get(0); if (params != null) { if (params.startCopy()) { // We are done... look for more work or to // go idle. if (DEBUG_SD_INSTALL) Log.i(TAG, "Checking for more work or unbind..."); // Delete pending install if (mPendingInstalls.size() > 0) {/*移除队头*/ mPendingInstalls.remove(0); } if (mPendingInstalls.size() == 0) { if (mBound) { if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting delayed MCS_UNBIND");/*安装完成,与服务断开,通过发送MCS_UNBIND断开与Service*/ removeMessages(MCS_UNBIND); Message ubmsg = obtainMessage(MCS_UNBIND); // Unbind after a little delay, to avoid // continual thrashing. sendMessageDelayed(ubmsg, 10000); } } else { // 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 woek"); mHandler.sendEmptyMessage(MCS_BOUND); } } } } else { // Should never happen ideally. Slog.w(TAG, "Empty queue"); } break; }/*省略*/1> 抽象类HandlerParams,及其子类:
InstallParams: 处理APK的安装;
MoveParams:处理APK用于处理某个已经安装的APK"搬家";
MeasureParams:用于查询某个已安装的APK占存储空间的大小;
2> 抽象类InstallArgs及其子类:
FileInstallArgs: 针对的是安装在内部存储的APK
SdInstallArgs: 针对的是安装在sd卡的APK
final boolean startCopy() { boolean res; try { if (DEBUG_INSTALL) Slog.i(TAG, "startCopy"); 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(); res = true; } } catch (RemoteException e) { if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT"); mHandler.sendEmptyMessage(MCS_RECONNECT); res = false; } handleReturnCode(); return res; } public void handleStartCopy() throws RemoteException { int ret = PackageManager.INSTALL_SUCCEEDED;/*根据adb install 的参数,判断安装位置*/ final boolean fwdLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0; final boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0; final boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0; PackageInfoLite pkgLite = null; if (onInt && onSd) { // Check if both bits are set./*不能同时安装在内部存储和SD卡*/ Slog.w(TAG, "Conflicting flags specified for installing on both internal and external"); ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; } else if (fwdLocked && onSd) { // Check for forward locked apps Slog.w(TAG, "Cannot install fwd locked apps on sdcard"); ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; } else { final long lowThreshold;/*获取DeviceStorageMonitorService的binder客户端*/ final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager .getService(DeviceStorageMonitorService.SERVICE); if (dsm == null) { Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed"); lowThreshold = 0L; } else {/*查询最小余量*/ lowThreshold = dsm.getMemoryLowThreshold(); } // Remote call to find out default install location try {/*给DefaultContainerService URI读权限*/ mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);/*获取轻量级的PackageInfoLite对象*/ pkgLite = mContainerService.getMinimalPackageInfo(packageURI, flags, lowThreshold); } finally {/*收回权限*/ mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION); }/*推荐安装路径*/ 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 if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) { ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) { ret = PackageManager.INSTALL_FAILED_INVALID_APK; } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) { ret = PackageManager.INSTALL_FAILED_INVALID_URI; } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) { ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE; } else { // Override with defaults if needed./*apk检查*/ loc = installLocationPolicy(pkgLite, flags); if (!onSd && !onInt) { // Override install location with flags if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) { // Set the flag to install on external media. flags |= PackageManager.INSTALL_EXTERNAL; flags &= ~PackageManager.INSTALL_INTERNAL; } else { // Make sure the flag for installing on external // media is unset flags |= PackageManager.INSTALL_INTERNAL; flags &= ~PackageManager.INSTALL_EXTERNAL; } } } }/*创建一个安装参数对象,内部安装该对象实际为FileInstallArgs*/ final InstallArgs args = createInstallArgs(this); mArgs = args; if (ret == PackageManager.INSTALL_SUCCEEDED) { /* * Determine if we have any installed package verifiers. If we * do, then we'll defer to them to verify the packages. */ final int requiredUid = mRequiredVerifierPackage == null ? -1 : getPackageUid(mRequiredVerifierPackage);/*verification处理*/ if (requiredUid != -1 && isVerificationEnabled()) { final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION); verification.setDataAndType(packageURI, PACKAGE_MIME_TYPE); verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); final List<ResolveInfo> receivers = queryIntentReceivers(verification, null, PackageManager.GET_DISABLED_COMPONENTS); if (DEBUG_VERIFY) { Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent " + verification.toString() + " with " + pkgLite.verifiers.length + " optional verifiers"); } final int verificationId = mPendingVerificationToken++; verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId); verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE, installerPackageName); verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, flags); if (verificationURI != null) { verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI, verificationURI); } final PackageVerificationState verificationState = new PackageVerificationState( requiredUid, args); mPendingVerification.append(verificationId, verificationState); final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite, receivers, verificationState); /* * If any sufficient verifiers were listed in the package * manifest, attempt to ask them. */ if (sufficientVerifiers != null) { final int N = sufficientVerifiers.size(); if (N == 0) { Slog.i(TAG, "Additional verifiers required, but none installed."); ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE; } else { for (int i = 0; i < N; i++) { final ComponentName verifierComponent = sufficientVerifiers.get(i); final Intent sufficientIntent = new Intent(verification); sufficientIntent.setComponent(verifierComponent); mContext.sendBroadcast(sufficientIntent); } } } final ComponentName requiredVerifierComponent = matchComponentForVerifier( mRequiredVerifierPackage, receivers); if (ret == PackageManager.INSTALL_SUCCEEDED && mRequiredVerifierPackage != null) { /* * Send the intent to the required verification agent, * but only start the verification timeout after the * target BroadcastReceivers have run. */ verification.setComponent(requiredVerifierComponent); mContext.sendOrderedBroadcast(verification, android.Manifest.permission.PACKAGE_VERIFICATION_AGENT, new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final Message msg = mHandler .obtainMessage(CHECK_PENDING_VERIFICATION); msg.arg1 = verificationId; mHandler.sendMessageDelayed(msg, getVerificationTimeout()); } }, null, 0, null, null); /* * We don't want the copy to proceed until verification * succeeds, so null out this field. */ mArgs = null; } } else { /* * No package verification is enabled, so immediately start * the remote call to initiate copy using temporary file. *//*调用FileInstallArgs的copyApk方法*/ ret = args.copyApk(mContainerService, true); } } mRet = ret; }
以上代码知识点:
1> 调用DefaultContainerService的getMinimalPackageInfo函数,得到一个PackageInfoLite对象,该对象是一个轻量级的用于描述APK的机构,这个不同于PackageLite,这两个中的成员非常相似,只是PackageInfoLite实现了Parcelable接口,因此,该类可通过binder在进程间通信,该函数中可以获得一个合理的recommandedInstallLocation的值,该值表示该APK推荐的安装路径;
2> 调用installLocationPolicy检查推荐安装路径。(系统Package不能安装在SD卡上)
3> createInstallArgs根据安装位置创建不同的InstallArgs,如果是内部安装,为FileInstallArgs对象,否则为SdInstallArgs对象
4> 正式安装前需要对APK进行必要的检查
5> 调用InstallArgs的copyAPK方法
<---待续--->
- PacakgeManagerService学习笔记七-APK installation
- PacakgeManagerService学习笔记八-APK installation
- PacakgeManagerService学习笔记九-APK installation
- Allegro学习笔记七
- 汇编语言学习笔记(七)
- C#学习笔记(七)
- HTML学习笔记七
- Struts2学习笔记七
- Lucene学习笔记(七)
- PHP学习笔记七
- Android 学习笔记(七)
- Oracle学习笔记(七)
- java学习笔记(七)
- oracle11g学习笔记(七)
- 学习笔记(七)
- c++学习笔记七
- Hibernate学习笔记七
- OpenGL学习笔记(七)
- 高管通用能力与素质
- 给大家拜年啦!祝福平台上台阶,祝愿大家马上给力!
- eclipse 项目不能自动编译的解决办法
- php学习之路之apache的安装
- 用PHP的 sockopen方式发送POST 或GET请求
- PacakgeManagerService学习笔记七-APK installation
- 50万用户够不够
- 我们的爱情快乐
- 打开第三方Activity前判断Intent能否被解析
- 开启战斗模式
- codeforces 388C Fox and Card Game
- 产品经理知识梳理(1)-产品构思基本原则
- 用C++11实现spinlock
- java.lang.NoClassDefFoundError: org/apache/juli/logging/LogFactory的解决