您的位置:首页 > 其它

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方法

<---待续--->
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: