PacakgeManagerService学习笔记七-APK installation
2014-02-07 16:55
330 查看
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=/system export 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");
}
};
2.MCS_BOUND
/*省略*/
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
- PackageManagerService学习笔记一
- PowerManagerService学习笔记
- PackageManagerService学习笔记二-构造方法
- android内核剖析学习笔记:AMS(ActivityManagerService)内部原理和工作机制
- PackageManagerService学习笔记五-构造方法
- 深入安卓(packageManagerService,activityManagerService_)——极客学院学习笔记
- Binder学习笔记(四)—— ServiceManager如何响应checkService请求
- Binder学习笔记(四)—— ServiceManager如何响应checkService请求
- Binder学习笔记(七)—— ServiceManager如何响应addService请求 ?
- PackageManagerService学习笔记六-构造函数
- Binder学习笔记(二)——defaultServiceManager()返回了什么?
- SystemService 学习笔记之ConnectivityManager
- Binder学习笔记(二)——defaultServiceManager()返回了什么?
- PackageManagerService学习笔记四-构造方法(扫描Package)
- ActivityManagerService的学习笔记
- PowerManagerService学习笔记一
- Android开发学习笔记:Service的简介和启动方式