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");        }    };


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

<---待续--->




0 0
原创粉丝点击