1. 程式人生 > >Android 7.0修改PMS邏輯新增許可權白名單

Android 7.0修改PMS邏輯新增許可權白名單

     今天有任務安排需要實現給任何一個應用在不動態申請許可權的情況下,實現許可權賦予,大體知道應用許可權的賦予邏輯是在PMS中,於是大概研究了下,最終的手段就是在install安裝時,就把應用程式AndroidManifest中請求的許可權賦予它,但是時間有限,跟蹤了下應用安裝的邏輯,往上走還是非常複雜,就暫且放下了。

     解決方案:

  在PMS的grantPermissionsLPw方法中的if ((changedInstallPermission || replace) && !ps.installPermissionsFixed && !isSystemApp(ps) || isUpdatedSystemApp(ps)){   判斷條件之前加上如下程式碼,其中的whiteList是自己定義的一個白名單陣列,儲存著目標應用的包名。

        if (Arrays.asList(whiteList).contains(pkg.packageName)) {
            final int permsSize = pkg.requestedPermissions.size();
            for (int i = 0; i < permsSize; i++) {
                final String name = pkg.requestedPermissions.get(i);
                final BasePermission bp = mSettings.mPermissions.get(name);
                if (null != bp && permissionsState.grantInstallPermission(bp) != PermissionsState.PERMISSION_OPERATION_FAILURE) {
                    Slog.d(TAG, "grant permission " + name + " to package " + pkg.packageName);
                    changedInstallPermission = true;
                }
            }
        }

     新增後的截圖如下:

     新增的程式碼的意思也非常清楚,就是對當前應用需要申請的許可權全部賦為true,這樣應用就可以不動態申請,就直接有了想要的許可權了;手機上所有應用的部分資訊都儲存在/data/system/packages.xml檔案中,應用申請的許可權在當前應用包名的xml根節點下明確記錄,例項截圖如下。

     本來想把install應用安裝的邏輯完全搞清楚,但是進來後發現這塊還真是複雜,加上時間不夠,有要事在身,就把install安裝的系統日誌貼出來吧,供大家參考。

     我是在cmd中adb install命令列執行安裝的,發現的入口點是在PackageInstallerSession.java類的commitLocked方法中呼叫PMS類的installStage方法來進行安裝的。PackageInstallerSession.java類的commitLocked方法原始碼如下:

    private void commitLocked(PackageInfo pkgInfo, ApplicationInfo appInfo)
            throws PackageManagerException {
        if (mDestroyed) {
            throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session destroyed");
        }
        if (!mSealed) {
            throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session not sealed");
        }

        try {
            resolveStageDir();
        } catch (IOException e) {
            throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
                    "Failed to resolve stage location", e);
        }

        // Verify that stage looks sane with respect to existing application.
        // This currently only ensures packageName, versionCode, and certificate
        // consistency.
        validateInstallLocked(pkgInfo, appInfo);

        Preconditions.checkNotNull(mPackageName);
        Preconditions.checkNotNull(mSignatures);
        Preconditions.checkNotNull(mResolvedBaseFile);

        if (!mPermissionsAccepted) {
            // User needs to accept permissions; give installer an intent they
            // can use to involve user.
            final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_PERMISSIONS);
            intent.setPackage(mContext.getPackageManager().getPermissionControllerPackageName());
            intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
            try {
                mRemoteObserver.onUserActionRequired(intent);
            } catch (RemoteException ignored) {
            }

            // Commit was keeping session marked as active until now; release
            // that extra refcount so session appears idle.
            close();
            return;
        }

        if (stageCid != null) {
            // Figure out the final installed size and resize the container once
            // and for all. Internally the parser handles straddling between two
            // locations when inheriting.
            final long finalSize = calculateInstalledSize();
            resizeContainer(stageCid, finalSize);
        }

        // Inherit any packages and native libraries from existing install that
        // haven't been overridden.
        if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
            try {
                final List<File> fromFiles = mResolvedInheritedFiles;
                final File toDir = resolveStageDir();

                if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
                if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
                    throw new IllegalStateException("mInheritedFilesBase == null");
                }

                if (isLinkPossible(fromFiles, toDir)) {
                    if (!mResolvedInstructionSets.isEmpty()) {
                        final File oatDir = new File(toDir, "oat");
                        createOatDirs(mResolvedInstructionSets, oatDir);
                    }
                    linkFiles(fromFiles, toDir, mInheritedFilesBase);
                } else {
                    // TODO: this should delegate to DCS so the system process
                    // avoids holding open FDs into containers.
                    copyFiles(fromFiles, toDir);
                }
            } catch (IOException e) {
                throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
                        "Failed to inherit existing install", e);
            }
        }

        // TODO: surface more granular state from dexopt
        mInternalProgress = 0.5f;
        computeProgressLocked(true);

        // Unpack native libraries
        extractNativeLibraries(mResolvedStageDir, params.abiOverride);

        // Container is ready to go, let's seal it up!
        if (stageCid != null) {
            finalizeAndFixContainer(stageCid);
        }

        // We've reached point of no return; call into PMS to install the stage.
        // Regardless of success or failure we always destroy session.
        final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() {
            @Override
            public void onUserActionRequired(Intent intent) {
                throw new IllegalStateException();
            }

            @Override
            public void onPackageInstalled(String basePackageName, int returnCode, String msg,
                    Bundle extras) {
                destroyInternal();
                dispatchSessionFinished(returnCode, msg, extras);
            }
        };

        final UserHandle user;
        if ((params.installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
            user = UserHandle.ALL;
        } else {
            user = new UserHandle(userId);
        }

        mRelinquished = true;
        mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params,
                installerPackageName, installerUid, user, mCertificates);
    }

     這裡的mPm就是PackageManagerService了,執行到installStage方法中,會先通過PMS中mHandler成員變數傳送一條INIT_COPY訊息,mHandler是PMS的內部類PackageHandler,它在handleMessage方法中就是直接呼叫doHandleMessage方法去處理安裝邏輯的,doHandleMessage方法原始碼如下:

void doHandleMessage(Message msg) {
            switch (msg.what) {
                case INIT_COPY: {
                    HandlerParams params = (HandlerParams) msg.obj;
                    int idx = mPendingInstalls.size();
                    if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
                    // If a bind was already initiated we dont really
                    // need to do anything. The pending install
                    // will be processed later on.
                    if (!mBound) {
                        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
                                System.identityHashCode(mHandler));
                        // If this is the only one pending we might
                        // have to bind to the service again.
                        if (!connectToService()) {
                            Slog.e(TAG, "Failed to bind to media container service");
                            params.serviceError();
                            Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
                                    System.identityHashCode(mHandler));
                            if (params.traceMethod != null) {
                                Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod,
                                        params.traceCookie);
                            }
                            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;
                }
                case MCS_BOUND: {
                    if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
                    if (msg.obj != null) {
                        mContainerService = (IMediaContainerService) msg.obj;
                        Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
                                System.identityHashCode(mHandler));
                    }
                    if (mContainerService == null) {
                        if (!mBound) {
                            // Something seriously wrong since we are not bound and we are not
                            // waiting for connection. Bail out.
                            Slog.e(TAG, "Cannot bind to media container service");
                            for (HandlerParams params : mPendingInstalls) {
                                // Indicate service bind error
                                params.serviceError();
                                Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                                        System.identityHashCode(params));
                                if (params.traceMethod != null) {
                                    Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER,
                                            params.traceMethod, params.traceCookie);
                                }
                                return;
                            }
                            mPendingInstalls.clear();
                        } else {
                            Slog.w(TAG, "Waiting to connect to media container service");
                        }
                    } else if (mPendingInstalls.size() > 0) {
                        HandlerParams params = mPendingInstalls.get(0);
                        if (params != null) {
                            Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                                    System.identityHashCode(params));
                            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
                            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");
                                        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 work");
                                    mHandler.sendEmptyMessage(MCS_BOUND);
                                }
                            }
                            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                        }
                    } else {
                        // Should never happen ideally.
                        Slog.w(TAG, "Empty queue");
                    }
                    break;
                }
                case MCS_RECONNECT: {
                    if (DEBUG_INSTALL) Slog.i(TAG, "mcs_reconnect");
                    if (mPendingInstalls.size() > 0) {
                        if (mBound) {
                            disconnectService();
                        }
                        if (!connectToService()) {
                            Slog.e(TAG, "Failed to bind to media container service");
                            for (HandlerParams params : mPendingInstalls) {
                                // Indicate service bind error
                                params.serviceError();
                                Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                                        System.identityHashCode(params));
                            }
                            mPendingInstalls.clear();
                        }
                    }
                    break;
                }
                case MCS_UNBIND: {
                    // If there is no actual work left, then time to unbind.
                    if (DEBUG_INSTALL) Slog.i(TAG, "mcs_unbind");

                    if (mPendingInstalls.size() == 0 && mPendingVerification.size() == 0) {
                        if (mBound) {
                            if (DEBUG_INSTALL) Slog.i(TAG, "calling disconnectService()");

                            disconnectService();
                        }
                    } else if (mPendingInstalls.size() > 0) {
                        // There are more pending requests in queue.
                        // Just post MCS_BOUND message to trigger processing
                        // of next pending install.
                        mHandler.sendEmptyMessage(MCS_BOUND);
                    }

                    break;
                }
                case MCS_GIVE_UP: {
                    if (DEBUG_INSTALL) Slog.i(TAG, "mcs_giveup too many retries");
                    HandlerParams params = mPendingInstalls.remove(0);
                    Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                            System.identityHashCode(params));
                    break;
                }
                case SEND_PENDING_BROADCAST: {
                    String packages[];
                    ArrayList<String> components[];
                    int size = 0;
                    int uids[];
                    Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
                    synchronized (mPackages) {
                        if (mPendingBroadcasts == null) {
                            return;
                        }
                        size = mPendingBroadcasts.size();
                        if (size <= 0) {
                            // Nothing to be done. Just return
                            return;
                        }
                        packages = new String[size];
                        components = new ArrayList[size];
                        uids = new int[size];
                        int i = 0;  // filling out the above arrays

                        for (int n = 0; n < mPendingBroadcasts.userIdCount(); n++) {
                            int packageUserId = mPendingBroadcasts.userIdAt(n);
                            Iterator<Map.Entry<String, ArrayList<String>>> it
                                    = mPendingBroadcasts.packagesForUserId(packageUserId)
                                            .entrySet().iterator();
                            while (it.hasNext() && i < size) {
                                Map.Entry<String, ArrayList<String>> ent = it.next();
                                packages[i] = ent.getKey();
                                components[i] = ent.getValue();
                                PackageSetting ps = mSettings.mPackages.get(ent.getKey());
                                uids[i] = (ps != null)
                                        ? UserHandle.getUid(packageUserId, ps.appId)
                                        : -1;
                                i++;
                            }
                        }
                        size = i;
                        mPendingBroadcasts.clear();
                    }
                    // Send broadcasts
                    for (int i = 0; i < size; i++) {
                        sendPackageChangedBroadcast(packages[i], true, components[i], uids[i]);
                    }
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                    break;
                }
                case START_CLEANING_PACKAGE: {
                    Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
                    final String packageName = (String)msg.obj;
                    final int userId = msg.arg1;
                    final boolean andCode = msg.arg2 != 0;
                    synchronized (mPackages) {
                        if (userId == UserHandle.USER_ALL) {
                            int[] users = sUserManager.getUserIds();
                            for (int user : users) {
                                mSettings.addPackageToCleanLPw(
                                        new PackageCleanItem(user, packageName, andCode));
                            }
                        } else {
                            mSettings.addPackageToCleanLPw(
                                    new PackageCleanItem(userId, packageName, andCode));
                        }
                    }
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                    startCleaningPackages();
                } break;
                case POST_INSTALL: {
                    if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);

                    PostInstallData data = mRunningInstalls.get(msg.arg1);
                    final boolean didRestore = (msg.arg2 != 0);
                    mRunningInstalls.delete(msg.arg1);

                    if (data != null) {
                        InstallArgs args = data.args;
                        PackageInstalledInfo parentRes = data.res;

                        final boolean grantPermissions = (args.installFlags
                                & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0;
                        final boolean killApp = (args.installFlags
                                & PackageManager.INSTALL_DONT_KILL_APP) == 0;
                        final String[] grantedPermissions = args.installGrantPermissions;

                        // Handle the parent package
                        handlePackagePostInstall(parentRes, grantPermissions, killApp,
                                grantedPermissions, didRestore, args.installerPackageName,
                                args.observer);

                        // Handle the child packages
                        final int childCount = (parentRes.addedChildPackages != null)
                                ? parentRes.addedChildPackages.size() : 0;
                        for (int i = 0; i < childCount; i++) {
                            PackageInstalledInfo childRes = parentRes.addedChildPackages.valueAt(i);
                            handlePackagePostInstall(childRes, grantPermissions, killApp,
                                    grantedPermissions, false, args.installerPackageName,
                                    args.observer);
                        }

                        // Log tracing if needed
                        if (args.traceMethod != null) {
                            Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, args.traceMethod,
                                    args.traceCookie);
                        }
                    } else {
                        Slog.e(TAG, "Bogus post-install token " + msg.arg1);
                    }

                    Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "postInstall", msg.arg1);
                } break;
                case UPDATED_MEDIA_STATUS: {
                    if (DEBUG_SD_INSTALL) Log.i(TAG, "Got message UPDATED_MEDIA_STATUS");
                    boolean reportStatus = msg.arg1 == 1;
                    boolean doGc = msg.arg2 == 1;
                    if (DEBUG_SD_INSTALL) Log.i(TAG, "reportStatus=" + reportStatus + ", doGc = " + doGc);
                    if (doGc) {
                        // Force a gc to clear up stale containers.
                        Runtime.getRuntime().gc();
                    }
                    if (msg.obj != null) {
                        @SuppressWarnings("unchecked")
                        Set<AsecInstallArgs> args = (Set<AsecInstallArgs>) msg.obj;
                        if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading all containers");
                        // Unload containers
                        unloadAllContainers(args);
                    }
                    if (reportStatus) {
                        try {
                            if (DEBUG_SD_INSTALL) Log.i(TAG, "Invoking MountService call back");
                            PackageHelper.getMountService().finishMediaUpdate();
                        } catch (RemoteException e) {
                            Log.e(TAG, "MountService not running?");
                        }
                    }
                } break;
                case WRITE_SETTINGS: {
                    Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
                    synchronized (mPackages) {
                        removeMessages(WRITE_SETTINGS);
                        removeMessages(WRITE_PACKAGE_RESTRICTIONS);
                        mSettings.writeLPr();
                        mDirtyUsers.clear();
                    }
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                } break;
                case WRITE_PACKAGE_RESTRICTIONS: {
                    Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
                    synchronized (mPackages) {
                        removeMessages(WRITE_PACKAGE_RESTRICTIONS);
                        for (int userId : mDirtyUsers) {
                            mSettings.writePackageRestrictionsLPr(userId);
                        }
                        mDirtyUsers.clear();
                    }
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                } break;
                case WRITE_PACKAGE_LIST: {
                    Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
                    synchronized (mPackages) {
                        removeMessages(WRITE_PACKAGE_LIST);
                        mSettings.writePackageListLPr(msg.arg1);
                    }
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                } break;
                case CHECK_PENDING_VERIFICATION: {
                    final int verificationId = msg.arg1;
                    final PackageVerificationState state = mPendingVerification.get(verificationId);

                    if ((state != null) && !state.timeoutExtended()) {
                        final InstallArgs args = state.getInstallArgs();
                        final Uri originUri = Uri.fromFile(args.origin.resolvedFile);

                        Slog.i(TAG, "Verification timed out for " + originUri);
                        mPendingVerification.remove(verificationId);

                        int ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;

                        if (getDefaultVerificationResponse() == PackageManager.VERIFICATION_ALLOW) {
                            Slog.i(TAG, "Continuing with installation of " + originUri);
                            state.setVerifierResponse(Binder.getCallingUid(),
                                    PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
                            broadcastPackageVerified(verificationId, originUri,
                                    PackageManager.VERIFICATION_ALLOW,
                                    state.getInstallArgs().getUser());
                            try {
                                ret = args.copyApk(mContainerService, true);
                            } catch (RemoteException e) {
                                Slog.e(TAG, "Could not contact the ContainerService");
                            }
                        } else {
                            broadcastPackageVerified(verificationId, originUri,
                                    PackageManager.VERIFICATION_REJECT,
                                    state.getInstallArgs().getUser());
                        }

                        Trace.asyncTraceEnd(
                                TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);

                        processPendingInstall(args, ret);
                        mHandler.sendEmptyMessage(MCS_UNBIND);
                    }
                    break;
                }
                case PACKAGE_VERIFIED: {
                    final int verificationId = msg.arg1;

                    final PackageVerificationState state = mPendingVerification.get(verificationId);
                    if (state == null) {
                        Slog.w(TAG, "Invalid verification token " + verificationId + " received");
                        break;
                    }

                    final PackageVerificationResponse response = (PackageVerificationResponse) msg.obj;

                    state.setVerifierResponse(response.callerUid, response.code);

                    if (state.isVerificationComplete()) {
                        mPendingVerification.remove(verificationId);

                        final InstallArgs args = state.getInstallArgs();
                        final Uri originUri = Uri.fromFile(args.origin.resolvedFile);

                        int ret;
                        if (state.isInstallAllowed()) {
                            ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
                            broadcastPackageVerified(verificationId, originUri,
                                    response.code, state.getInstallArgs().getUser());
                            try {
                                ret = args.copyApk(mContainerService, true);
                            } catch (RemoteException e) {
                                Slog.e(TAG, "Could not contact the ContainerService");
                            }
                        } else {
                            ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
                        }

                        Trace.asyncTraceEnd(
                                TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);

                        processPendingInstall(args, ret);
                        mHandler.sendEmptyMessage(MCS_UNBIND);
                    }

                    break;
                }
                case START_INTENT_FILTER_VERIFICATIONS: {
                    IFVerificationParams params = (IFVerificationParams) msg.obj;
                    verifyIntentFiltersIfNeeded(params.userId, params.verifierUid,
                            params.replacing, params.pkg);
                    break;
                }
                case INTENT_FILTER_VERIFIED: {
                    final int verificationId = msg.arg1;

                    final IntentFilterVerificationState state = mIntentFilterVerificationStates.get(
                            verificationId);
                    if (state == null) {
                        Slog.w(TAG, "Invalid IntentFilter verification token "
                                + verificationId + " received");
                        break;
                    }

                    final int userId = state.getUserId();

                    if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
                            "Processing IntentFilter verification with token:"
                            + verificationId + " and userId:" + userId);

                    final IntentFilterVerificationResponse response =
                            (IntentFilterVerificationResponse) msg.obj;

                    state.setVerifierResponse(response.callerUid, response.code);

                    if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
                            "IntentFilter verification with token:" + verificationId
                            + " and userId:" + userId
                            + " is settings verifier response with response code:"
                            + response.code);

                    if (response.code == PackageManager.INTENT_FILTER_VERIFICATION_FAILURE) {
                        if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Domains failing verification: "
                                + response.getFailedDomainsString());
                    }

                    if (state.isVerificationComplete()) {
                        mIntentFilterVerifier.receiveVerificationResponse(verificationId);
                    } else {
                        if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
                                "IntentFilter verification with token:" + verificationId
                                + " was not said to be complete");
                    }

                    break;
                }
            }

     在INIT_COPY中,成員變數mBound是在connectToService方法執行成功已經賦值為true了,所有會執行else分支,繼續發一條MCS_BOUND訊息,MCS_BOUND訊息中會執行else if (mPendingInstalls.size() > 0)分支,在這裡的if (params.startCopy())就會呼叫給應用賦予許可權的邏輯了,params的型別為HandlerParams,它的startCopy()拷貝完成後,最後呼叫handleReturnCode繼續處理,handleReturnCode是由子類InstallParams來實現的,它當中直接呼叫processPendingInstall往mHandler所在的執行緒上發了一條Runnable訊息,Runnable中繼續呼叫installPackageTracedLI處理,installPackageTracedLI方法又繼續呼叫installPackageLI方法處理,installPackageLI方法在執行到15451行的try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags, "installPackageLI"))邏輯時,因為是新安裝,此處理的replace為false,執行installNewPackageLIF方法繼續處理,方法註釋上也寫的很清楚了,是安裝新應用時執行的,installNewPackageLIF方法的原始碼如下:

    /*
     * Install a non-existing package.
     */
    private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags,
            int scanFlags, UserHandle user, String installerPackageName, String volumeUuid,
            PackageInstalledInfo res) {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installNewPackage");

        // Remember this for later, in case we need to rollback this install
        String pkgName = pkg.packageName;

        if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);

        synchronized(mPackages) {
            if (mSettings.mRenamedPackages.containsKey(pkgName)) {
                // A package with the same name is already installed, though
                // it has been renamed to an older name.  The package we
                // are trying to install should be installed as an update to
                // the existing one, but that has not been requested, so bail.
                res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName
                        + " without first uninstalling package running as "
                        + mSettings.mRenamedPackages.get(pkgName));
                return;
            }
            if (mPackages.containsKey(pkgName)) {
                // Don't allow installation over an existing package with the same name.
                res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName
                        + " without first uninstalling.");
                return;
            }
        }

        try {
            PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags,
                    System.currentTimeMillis(), user);

            updateSettingsLI(newPackage, installerPackageName, null, res, user);

            if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                prepareAppDataAfterInstallLIF(newPackage);

            } else {
                // Remove package from internal structures, but keep around any
                // data that might have already existed
                deletePackageLIF(pkgName, UserHandle.ALL, false, null,
                        PackageManager.DELETE_KEEP_DATA, res.removedInfo, true, null);
            }
        } catch (PackageManagerException e) {
            res.setError("Package couldn't be installed in " + pkg.codePath, e);
        }

        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }

    在這裡的try模組中執行updateSettingsLI更新Settings,又呼叫updateSettingsInternalLI處理,接著呼叫updatePermissionsLPw更新應用許可權,updatePermissionsLPw方法中就是直接呼叫updatePermissionsLPw方法處理,該方法中最後就會執行grantPermissionsLPw給應用寫許可權,而我們加在這裡的邏輯也就生效了。

     從這裡看,這還只是寫許可權的部分邏輯,應用安裝還涉及到其他很多問題,真是非常複雜,大家有研究清楚的,也請多多指教,最後把我在系統中加的日誌貼出來,供大家參考。

    Line 5990: 01-03 08:52:44.102  2257  2402 I System.out: stack, dalvik.system.VMStack.getThreadStackTrace(VMStack.java:-2)
    Line 5991: 01-03 08:52:44.103  2257  2402 I System.out: stack, java.lang.Thread.getStackTrace(Thread.java:1566)
    Line 5992: 01-03 08:52:44.103  2257  2402 I System.out: stack, com.android.server.pm.PackageManagerService.processPendingInstall(PackageManagerService.java:12578)
    Line 5993: 01-03 08:52:44.103  2257  2402 I System.out: stack, com.android.server.pm.PackageManagerService.-wrap33(PackageManagerService.java:-1)
    Line 5994: 01-03 08:52:44.103  2257  2402 I System.out: stack, com.android.server.pm.PackageManagerService$InstallParams.handleReturnCode(PackageManagerService.java:13384)
    Line 5995: 01-03 08:52:44.103  2257  2402 I System.out: stack, com.android.server.pm.PackageManagerService$HandlerParams.startCopy(PackageManagerService.java:12767)
    Line 5996: 01-03 08:52:44.103  2257  2402 I System.out: stack, com.android.server.pm.PackageManagerService$PackageHandler.doHandleMessage(PackageManagerService.java:1274)
    Line 5997: 01-03 08:52:44.103  2257  2402 I System.out: stack, com.android.server.pm.PackageManagerService$PackageHandler.handleMessage(PackageManagerService.java:1196)
    Line 5998: 01-03 08:52:44.103  2257  2402 I System.out: stack, android.os.Handler.dispatchMessage(Handler.java:102)
    Line 5999: 01-03 08:52:44.103  2257  2402 I System.out: stack, android.os.Looper.loop(Looper.java:154)
    Line 6000: 01-03 08:52:44.103  2257  2402 I System.out: stack, android.os.HandlerThread.run(HandlerThread.java:61)
    Line 6001: 01-03 08:52:44.104  2257  2402 I System.out: stack, com.android.server.ServiceThread.run(ServiceThread.java:46)
    Line 6100: 01-03 08:52:46.360  2257  2402 I System.out: stack, dalvik.system.VMStack.getThreadStackTrace(VMStack.java:-2)
    Line 6101: 01-03 08:52:46.361  2257  2402 I System.out: stack, java.lang.Thread.getStackTrace(Thread.java:1566)
    Line 6102: 01-03 08:52:46.361  2257  2402 I System.out: stack, com.android.server.pm.PackageManagerService.grantPermissionsLPw(PackageManagerService.java:10075)
    Line 6103: 01-03 08:52:46.361  2257  2402 I System.out: stack, com.android.server.pm.PackageManagerService.updatePermissionsLPw(PackageManagerService.java:10059)
    Line 6104: 01-03 08:52:46.361  2257  2402 I System.out: stack, com.android.server.pm.PackageManagerService.updatePermissionsLPw(PackageManagerService.java:9972)
    Line 6105: 01-03 08:52:46.361  2257  2402 I System.out: stack, com.android.server.pm.PackageManagerService.updateSettingsInternalLI(PackageManagerService.java:15044)
    Line 6106: 01-03 08:52:46.361  2257  2402 I System.out: stack, com.android.server.pm.PackageManagerService.updateSettingsLI(PackageManagerService.java:15013)
    Line 6107: 01-03 08:52:46.361  2257  2402 I System.out: stack, com.android.server.pm.PackageManagerService.installNewPackageLIF(PackageManagerService.java:14388)
    Line 6108: 01-03 08:52:46.361  2257  2402 I System.out: stack, com.android.server.pm.PackageManagerService.installPackageLI(PackageManagerService.java:15457)
    Line 6109: 01-03 08:52:46.361  2257  2402 I System.out: stack, com.android.server.pm.PackageManagerService.installPackageTracedLI(PackageManagerService.java:15105)
    Line 6110: 01-03 08:52:46.361  2257  2402 I System.out: stack, com.android.server.pm.PackageManagerService.-wrap26(PackageManagerService.java:-1)
    Line 6111: 01-03 08:52:46.361  2257  2402 I System.out: stack, com.android.server.pm.PackageManagerService$10.run(PackageManagerService.java:12596)
    Line 6112: 01-03 08:52:46.361  2257  2402 I System.out: stack, android.os.Handler.handleCallback(Handler.java:751)
    Line 6113: 01-03 08:52:46.361  2257  2402 I System.out: stack, android.os.Handler.dispatchMessage(Handler.java:95)
    Line 6114: 01-03 08:52:46.362  2257  2402 I System.out: stack, android.os.Looper.loop(Looper.java:154)
    Line 6115: 01-03 08:52:46.362  2257  2402 I System.out: stack, android.os.HandlerThread.run(HandlerThread.java:61)
    Line 6116: 01-03 08:52:46.362  2257  2402 I System.out: stack, com.android.server.ServiceThread.run(ServiceThread.java:46)