美文网首页
基于Android9.0的PackageManagerServi

基于Android9.0的PackageManagerServi

作者: android_coder | 来源:发表于2019-05-12 15:54 被阅读0次

    PackageManagerService启动流程(下)
    我们先看下PMS的启动过程,这部分主要是涉及SystemServer的startOtherServices方法

    if (!mOnlyCore) {
            traceBeginAndSlog("UpdatePackagesIfNeeded");
            try {
                mPackageManagerService.updatePackagesIfNeeded();
            } catch (Throwable e) {
                reportWtf("update packages", e);
            }
            traceEnd();
        }
    
        traceBeginAndSlog("PerformFstrimIfNeeded");
        try {
            mPackageManagerService.performFstrimIfNeeded();
        } catch (Throwable e) {
            reportWtf("performing fstrim", e);
        }
     traceEnd();
    ......
    traceBeginAndSlog("MakePackageManagerServiceReady");
    mPackageManagerService.systemReady();
    traceEnd();
    ........
    // Wait for all packages to be prepared
    mPackageManagerService.waitForAppDataPrepared();
    ........
    

    上部分我们主要是介绍PMS的初始化过程,这部分我们主要涉及到下面的几个方法

    mPackageManagerService.updatePackagesIfNeeded
    mPackageManagerService.performFstrimIfNeeded
    mPackageManagerService.systemReady
    mPackageManagerService.waitForAppDataPrepared
    

    我们接下来按照上面的几个方法介绍

    PMS之updatePackagesIfNeeded

    public void updatePackagesIfNeeded() {
        //只有system或是root用户才有权限
        enforceSystemOrRoot("Only the system can request package update");
    
        // We need to re-extract after an OTA.
        boolean causeUpgrade = isUpgrade();//判断是否是ota
    
        // First boot or factory reset.
        // Note: we also handle devices that are upgrading to N right now as if it is their
        //       first boot, as they do not have profile data.
        boolean causeFirstBoot = isFirstBoot() || mIsPreNUpgrade;//是否是第一次启动或是升级到Android N
        // We need to re-extract after a pruned cache, as AoT-ed files will be out of date.
        //判断是否有清除过dalvik虚拟机的缓存
        boolean causePrunedCache = VMRuntime.didPruneDalvikCache();
        //如果上面的三个都没有,那么就不进行任何操作
        if (!causeUpgrade && !causeFirstBoot && !causePrunedCache) {
            return;
        }
        List<PackageParser.Package> pkgs;
        synchronized (mPackages) {
        //按照package的优先级进行排序,core app >system app > other app
            pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this);
        }
        final long startTime = System.nanoTime();//记录开始时间
        final int[] stats = performDexOptUpgrade(pkgs, mIsPreNUpgrade /* showDialog */,
                    causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT,
                    false /* bootComplete */);
        final int elapsedTimeSeconds =
                (int) TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - startTime);
        MetricsLogger.histogram(mContext, "opt_dialog_num_dexopted", stats[0]);
        MetricsLogger.histogram(mContext, "opt_dialog_num_skipped", stats[1]);
        MetricsLogger.histogram(mContext, "opt_dialog_num_failed", stats[2]);
        MetricsLogger.histogram(mContext, "opt_dialog_num_total", getOptimizablePackages().size());
        MetricsLogger.histogram(mContext, "opt_dialog_time_s", elapsedTimeSeconds);
    }
    

    PMS之performDexOptUpgrade

    //odex优化操作
    private int[] performDexOptUpgrade(List<PackageParser.Package> pkgs, boolean showDialog,
            final int compilationReason, boolean bootComplete) {
        int numberOfPackagesVisited = 0;
        int numberOfPackagesOptimized = 0;
        int numberOfPackagesSkipped = 0;
        int numberOfPackagesFailed = 0;
        final int numberOfPackagesToDexopt = pkgs.size();
        for (PackageParser.Package pkg : pkgs) {
            numberOfPackagesVisited++;
            boolean useProfileForDexopt = false;
            //第一次启动或是ota升级之后并且是系统应用才会进行odex
            if ((isFirstBoot() || isUpgrade()) && isSystemApp(pkg)) {
                // Copy over initial preopt profiles since we won't get any JIT samples for methods
                // that are already compiled.
                File profileFile = new File(getPrebuildProfilePath(pkg));
                // Copy profile if it exists.
                //判断profile文件是否存在
                if (profileFile.exists()) {
                    try {
                        // We could also do this lazily before calling dexopt in
                        // PackageDexOptimizer to prevent this happening on first boot. The issue
                        // is that we don't have a good way to say "do this only once".
                        if (!mInstaller.copySystemProfile(profileFile.getAbsolutePath(),
                                pkg.applicationInfo.uid, pkg.packageName,
                                ArtManager.getProfileName(null))) {
                            Log.e(TAG, "Installer failed to copy system profile!");
                        } else {
                            // Disabled as this causes speed-profile compilation during first boot
                            // even if things are already compiled.
                            // useProfileForDexopt = true;
                        }
                    } catch (Exception e) {
                        Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath() + " ",
                                e);
                    }
                } else {
                    PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(pkg.packageName);
                    // Handle compressed APKs in this path. Only do this for stubs with profiles to
                    // minimize the number off apps being speed-profile compiled during first boot.
                    // The other paths will not change the filter.
                    if (disabledPs != null && disabledPs.pkg.isStub) {
                        // The package is the stub one, remove the stub suffix to get the normal
                        // package and APK names.
                        String systemProfilePath =
                                getPrebuildProfilePath(disabledPs.pkg).replace(STUB_SUFFIX, "");
                        profileFile = new File(systemProfilePath);
                        // If we have a profile for a compressed APK, copy it to the reference
                        // location.
                        // Note that copying the profile here will cause it to override the
                        // reference profile every OTA even though the existing reference profile
                        // may have more data. We can't copy during decompression since the
                        // directories are not set up at that point.
                        if (profileFile.exists()) {
                            try {
                                // We could also do this lazily before calling dexopt in
                                // PackageDexOptimizer to prevent this happening on first boot. The
                                // issue is that we don't have a good way to say "do this only
                                // once".
                                if (!mInstaller.copySystemProfile(profileFile.getAbsolutePath(),
                                        pkg.applicationInfo.uid, pkg.packageName,
                                        ArtManager.getProfileName(null))) {
                                    Log.e(TAG, "Failed to copy system profile for stub package!");
                                } else {
                                    useProfileForDexopt = true;
                                }
                            } catch (Exception e) {
                                Log.e(TAG, "Failed to copy profile " +
                                        profileFile.getAbsolutePath() + " ", e);
                            }
                        }
                    }
                }
            }
            if (!PackageDexOptimizer.canOptimizePackage(pkg)) {
                if (DEBUG_DEXOPT) {
                    Log.i(TAG, "Skipping update of of non-optimizable app " + pkg.packageName);
                }
                numberOfPackagesSkipped++;
                continue;
            }
            if (DEBUG_DEXOPT) {
                Log.i(TAG, "Updating app " + numberOfPackagesVisited + " of " +
                        numberOfPackagesToDexopt + ": " + pkg.packageName);
            }
            if (showDialog) {
                try {
                    ActivityManager.getService().showBootMessage(
                            mContext.getResources().getString(R.string.android_upgrading_apk,
                                    numberOfPackagesVisited, numberOfPackagesToDexopt), true);
                } catch (RemoteException e) {
                }
                synchronized (mPackages) {
                    mDexOptDialogShown = true;
                }
            }
            int pkgCompilationReason = compilationReason;
            if (useProfileForDexopt) {
                // Use background dexopt mode to try and use the profile. Note that this does not
                // guarantee usage of the profile.
                pkgCompilationReason = PackageManagerService.REASON_BACKGROUND_DEXOPT;
            }
            // checkProfiles is false to avoid merging profiles during boot which
            // might interfere with background compilation (b/28612421).
            // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will
            // behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a
            // trade-off worth doing to save boot time work.
            int dexoptFlags = bootComplete ? DexoptOptions.DEXOPT_BOOT_COMPLETE : 0;
            if (compilationReason == REASON_FIRST_BOOT) {
                // TODO: This doesn't cover the upgrade case, we should check for this too.
                dexoptFlags |= DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE;
            }
            //最终是调用mInstaller.dexopt完成优化的,installd守护进程,installer安装器和Installd通信
            int primaryDexOptStaus = performDexOptTraced(new DexoptOptions(
                    pkg.packageName,
                    pkgCompilationReason,
                    dexoptFlags));
            switch (primaryDexOptStaus) {
                case PackageDexOptimizer.DEX_OPT_PERFORMED:
                    numberOfPackagesOptimized++;//odex优化完成的应用
                    break;
                case PackageDexOptimizer.DEX_OPT_SKIPPED:
                    numberOfPackagesSkipped++;//跳过的应用
                    break;
                case PackageDexOptimizer.DEX_OPT_FAILED:
                    numberOfPackagesFailed++;//失败的应用
                    break;
                default:
                    Log.e(TAG, "Unexpected dexopt return code " + primaryDexOptStaus);
                    break;
            }
        }
        return new int[] { numberOfPackagesOptimized, numberOfPackagesSkipped,
                numberOfPackagesFailed };
    }
    上面的方法主要是判断是否需要对package进行更新,如果需要更新那么按照优先级完成dex优化
    

    PMS之performFstrimIfNeeded

    public void performFstrimIfNeeded() {
        enforceSystemOrRoot("Only the system can request fstrim");
        // Before everything else, see whether we need to fstrim.
        try {
            //获取mountSerice服务
            IStorageManager sm = PackageHelper.getStorageManager();
            if (sm != null) {
                boolean doTrim = false;
                //获取执行FTRIM间隔,默认是3天,可以通过setting provider更改这个时间
                final long interval = android.provider.Settings.Global.getLong(
                        mContext.getContentResolver(),
                        android.provider.Settings.Global.FSTRIM_MANDATORY_INTERVAL,
                        DEFAULT_MANDATORY_FSTRIM_INTERVAL);
                if (interval > 0) {
                    final long timeSinceLast = System.currentTimeMillis() - sm.lastMaintenance();
                    if (timeSinceLast > interval) {
                        doTrim = true;//如果超过了三天就进行磁盘清理
                        Slog.w(TAG, "No disk maintenance in " + timeSinceLast
                                + "; running immediately");
                    }
                }
                if (doTrim) {
                    final boolean dexOptDialogShown;
                    synchronized (mPackages) {
                        dexOptDialogShown = mDexOptDialogShown;
                    }
                    if (!isFirstBoot() && dexOptDialogShown) {
                        //如果不是第一次启动,显示一个提示框
                        try {
                            ActivityManager.getService().showBootMessage(
                                    mContext.getResources().getString(
                                            R.string.android_upgrading_fstrim), true);
                        } catch (RemoteException e) {
                        }
                    }
                    // 发送消息H_FSTRIM给handler,然后再向vold发送fstrim命令
                    sm.runMaintenance();
                }
            } else {
                Slog.e(TAG, "storageManager service unavailable!");
            }
        } catch (RemoteException e) {
            // Can't happen; StorageManagerService is local
        }
    }
    

    上面主要是执行磁盘清理工作,释放磁盘空间。

    PMS之SystemReady

    traceBeginAndSlog("MakePackageManagerServiceReady");
    mPackageManagerService.systemReady();
    traceEnd();
    ...............................................................................
    public void systemReady() {
        enforceSystemOrRoot("Only the system can claim the system is ready");
        mSystemReady = true;
        final ContentResolver resolver = mContext.getContentResolver();
        ContentObserver co = new ContentObserver(mHandler) {
            @Override
            public void onChange(boolean selfChange) {
                mWebInstantAppsDisabled =
                        (Global.getInt(resolver, Global.ENABLE_EPHEMERAL_FEATURE, 1) == 0) ||
                                (Secure.getInt(resolver, Secure.INSTANT_APPS_ENABLED, 1) == 0);
            }
        };//小程序
       mContext.getContentResolver().registerContentObserver(android.provider.Settings.Global
                        .getUriFor(Global.ENABLE_EPHEMERAL_FEATURE),
                false, co, UserHandle.USER_SYSTEM);
      mContext.getContentResolver().registerContentObserver(android.provider.Settings.Secure
                        .getUriFor(Secure.INSTANT_APPS_ENABLED), false, co, UserHandle.USER_SYSTEM);
        co.onChange(true);//注册一个监听
        // Disable any carrier apps. We do this very early in boot to prevent the apps from being
        // disabled after already being started.
        CarrierAppUtils.disableCarrierAppsUntilPrivileged(mContext.getOpPackageName(), this,
                mContext.getContentResolver(), UserHandle.USER_SYSTEM);
        // Read the compatibilty setting when the system is ready.
        boolean compatibilityModeEnabled = android.provider.Settings.Global.getInt(
                mContext.getContentResolver(),
                android.provider.Settings.Global.COMPATIBILITY_MODE, 1) == 1;
        PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
        if (DEBUG_SETTINGS) {
            Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
        }
        int[] grantPermissionsUserIds = EMPTY_INT_ARRAY;
        synchronized (mPackages) {
            // Verify that all of the preferred activity components actually
            // exist.  It is possible for applications to be updated and at
            // that point remove a previously declared activity component that
            // had been set as a preferred activity.  We try to clean this up
            // the next time we encounter that preferred activity, but it is
            // possible for the user flow to never be able to return to that
            // situation so here we do a sanity check to make sure we haven't
            // left any junk around.
            ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
            for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
                PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
                removed.clear();
                for (PreferredActivity pa : pir.filterSet()) {
                    if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
                        removed.add(pa);
                    }
                }//移除不存在的先前用户设置保存的优先选择的activity组件
                if (removed.size() > 0) {
                    for (int r=0; r<removed.size(); r++) {
                        PreferredActivity pa = removed.get(r);
                        Slog.w(TAG, "Removing dangling preferred activity: "
                                + pa.mPref.mComponent);
                        pir.removeFilter(pa);
                    }
                    mSettings.writePackageRestrictionsLPr(
                            mSettings.mPreferredActivities.keyAt(i));//写入到文件中
                }
            }
            for (int userId : UserManagerService.getInstance().getUserIds()) {
                if (!mSettings.areDefaultRuntimePermissionsGrantedLPr(userId)) {
                    grantPermissionsUserIds = ArrayUtils.appendInt(
                            grantPermissionsUserIds, userId);
                }
            }
        }
        sUserManager.systemReady();//多用户服务的systemReady方法
        // If we upgraded grant all default permissions before kicking off.
        for (int userId : grantPermissionsUserIds) {
            mDefaultPermissionPolicy.grantDefaultPermissions(userId);//默认授权操作
        }
        if (grantPermissionsUserIds == EMPTY_INT_ARRAY) {
            // If we did not grant default permissions, we preload from this the
            // default permission exceptions lazily to ensure we don't hit the
            // disk on a new user creation.
            mDefaultPermissionPolicy.scheduleReadDefaultPermissionExceptions();
        }
        // Now that we've scanned all packages, and granted any default
        // permissions, ensure permissions are updated. Beware of dragons if you
        // try optimizing this.
        synchronized (mPackages) {
            mPermissionManager.updateAllPermissions(
                    StorageManager.UUID_PRIVATE_INTERNAL, false, mPackages.values(),
                    mPermissionCallback);//更新权限信息
        }
        // Kick off any messages waiting for system ready
        if (mPostSystemReadyMessages != null) {
            for (Message msg : mPostSystemReadyMessages) {
                msg.sendToTarget();
            }
            mPostSystemReadyMessages = null;
        }
        // Watch for external volumes that come and go over time
        final StorageManager storage = mContext.getSystemService(StorageManager.class);
        storage.registerListener(mStorageListener);
        mInstallerService.systemReady();
        mDexManager.systemReady();
        mPackageDexOptimizer.systemReady();
        StorageManagerInternal StorageManagerInternal = LocalServices.getService(
                StorageManagerInternal.class);
        StorageManagerInternal.addExternalStoragePolicy(
                new StorageManagerInternal.ExternalStorageMountPolicy() {
            @Override
            public int getMountMode(int uid, String packageName) {
                if (Process.isIsolated(uid)) {
                    return Zygote.MOUNT_EXTERNAL_NONE;
                }
                if (checkUidPermission(READ_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) {
                    return Zygote.MOUNT_EXTERNAL_DEFAULT;
                }
                if (checkUidPermission(WRITE_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) {
                    return Zygote.MOUNT_EXTERNAL_READ;
                }
                return Zygote.MOUNT_EXTERNAL_WRITE;
            }
            @Override
            public boolean hasExternalStorage(int uid, String packageName) {
                return true;
            }
        });
        //清除过期的userid和app
        // Now that we're mostly running, clean up stale users and apps
        sUserManager.reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);
        reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL);
        mPermissionManager.systemReady();
        if (mInstantAppResolverConnection != null) {
            mContext.registerReceiver(new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    mInstantAppResolverConnection.optimisticBind();
                    mContext.unregisterReceiver(this);
                }
            }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
        }
    }
    

    PMS之grantDefaultPermissions

    public void grantDefaultPermissions(int userId) {
        grantPermissionsToSysComponentsAndPrivApps(userId);
        grantDefaultSystemHandlerPermissions(userId);
        grantDefaultPermissionExceptions(userId);
    }
    ...........................................
    private void grantPermissionsToSysComponentsAndPrivApps(int userId) {
        Log.i(TAG, "Granting permissions to platform components for user " + userId);
        final PackageList packageList = mServiceInternal.getPackageList();
        for (String packageName : packageList.getPackageNames()) {
            final PackageParser.Package pkg = mServiceInternal.getPackage(packageName);
            if (pkg == null) {
                continue;
            }
            if (!isSysComponentOrPersistentPlatformSignedPrivApp(pkg)//不是系统组件或是常驻的priv-app
                    || !doesPackageSupportRuntimePermissions(pkg)//不支持dangerous权限
                    || pkg.requestedPermissions.isEmpty()) {//没有请求权限
                continue;
            }
            grantRuntimePermissionsForPackage(userId, pkg);
        }
    }
    .................................................
    private void grantRuntimePermissionsForPackage(int userId, PackageParser.Package pkg) {
        Set<String> permissions = new ArraySet<>();
        for (String permission :  pkg.requestedPermissions) {
            final BasePermission bp = mPermissionManager.getPermission(permission);
            if (bp == null) {
                continue;
            }
            if (bp.isRuntime()) {//如果是dangerous权限
                permissions.add(permission);
            }
        }
        if (!permissions.isEmpty()) {
            grantRuntimePermissions(pkg, permissions, true, userId);
        }
    }
    ..................................................
    private void grantRuntimePermissions(PackageParser.Package pkg, Set<String> permissions,
            boolean systemFixed, boolean ignoreSystemPackage, int userId) {
        if (pkg.requestedPermissions.isEmpty()) {
            return;
        }
        List<String> requestedPermissions = pkg.requestedPermissions;
        Set<String> grantablePermissions = null;
    
        // In some cases, like for the Phone or SMS app, we grant permissions regardless
        // of if the version on the system image declares the permission as used since
        // selecting the app as the default for that function the user makes a deliberate
        // choice to grant this app the permissions needed to function. For all other
        // apps, (default grants on first boot and user creation) we don't grant default
        // permissions if the version on the system image does not declare them.
        if (!ignoreSystemPackage && pkg.isUpdatedSystemApp()) {//系统应用升级
            final PackageParser.Package disabledPkg =
                    mServiceInternal.getDisabledPackage(pkg.packageName);
            if (disabledPkg != null) {//被disable掉的应用
                if (disabledPkg.requestedPermissions.isEmpty()) {
                    return;
                }
                if (!requestedPermissions.equals(disabledPkg.requestedPermissions)) {
                    grantablePermissions = new ArraySet<>(requestedPermissions);
                    requestedPermissions = disabledPkg.requestedPermissions;
                }
            }
        }
        final int grantablePermissionCount = requestedPermissions.size();
        for (int i = 0; i < grantablePermissionCount; i++) {
            String permission = requestedPermissions.get(i);
    
            // If there is a disabled system app it may request a permission the updated
            // version ot the data partition doesn't, In this case skip the permission.
            if (grantablePermissions != null && !grantablePermissions.contains(permission)) {
                continue;//如果系统应用升级了 但是最新的版本不存在该权限
            }
            if (permissions.contains(permission)) {
                final int flags = mServiceInternal.getPermissionFlagsTEMP(
                        permission, pkg.packageName, userId);
    
                // If any flags are set to the permission, then it is either set in
                // its current state by the system or device/profile owner or the user.
                // In all these cases we do not want to clobber the current state.
                // Unless the caller wants to override user choices. The override is
                // to make sure we can grant the needed permission to the default
                // sms and phone apps after the user chooses this in the UI.
                if (flags == 0 || ignoreSystemPackage) {
                    // Never clobber policy fixed permissions.
                    // We must allow the grant of a system-fixed permission because
                    // system-fixed is sticky, but the permission itself may be revoked.
                    if ((flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
                        continue;
                    }
    
                    mServiceInternal.grantRuntimePermission(
                            pkg.packageName, permission, userId, false);
                    if (DEBUG) {
                        Log.i(TAG, "Granted " + (systemFixed ? "fixed " : "not fixed ")
                                + permission + " to default handler " + pkg.packageName);
                    }
                    int newFlags = PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
                    if (systemFixed) {
                        newFlags |= PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
                    }
                    //最终是通过updatePermissionFlag来完成的
                    mServiceInternal.updatePermissionFlagsTEMP(permission, pkg.packageName,
                            newFlags, newFlags, userId);
                }
                // If a component gets a permission for being the default handler A
                // and also default handler B, we grant the weaker grant form.
                if ((flags & PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0
                        && (flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0
                        && !systemFixed) {
                    if (DEBUG) {
                        Log.i(TAG, "Granted not fixed " + permission + " to default handler "
                                + pkg.packageName);
                    }
                    mServiceInternal.updatePermissionFlagsTEMP(permission, pkg.packageName,
                            PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, 0, userId);
                }
            }
        }
    }
    .....................................................................
    private void updatePermissionFlags(String permName, String packageName, int flagMask,
            int flagValues, int callingUid, int userId, PermissionCallback callback) {
        if (!mUserManagerInt.exists(userId)) {
            return;
        }
        enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");
        enforceCrossUserPermission(callingUid, userId,
                true,  // requireFullPermission
                true,  // checkShell
                false, // requirePermissionWhenSameUser
                "updatePermissionFlags");
        // Only the system can change these flags and nothing else.
        if (callingUid != Process.SYSTEM_UID) {
            flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
            flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
            flagMask &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
            flagValues &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
            flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
        }
        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
        if (pkg == null || pkg.mExtras == null) {
            throw new IllegalArgumentException("Unknown package: " + packageName);
        }
        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
            throw new IllegalArgumentException("Unknown package: " + packageName);
        }
        final BasePermission bp;
        synchronized (mLock) {
            bp = mSettings.getPermissionLocked(permName);
        }
        if (bp == null) {
            throw new IllegalArgumentException("Unknown permission: " + permName);
        }
        final PackageSetting ps = (PackageSetting) pkg.mExtras;
        final PermissionsState permissionsState = ps.getPermissionsState();
        final boolean hadState =
                permissionsState.getRuntimePermissionState(permName, userId) != null;
        final boolean permissionUpdated =
                permissionsState.updatePermissionFlags(bp, userId, flagMask, flagValues);
        if (permissionUpdated && callback != null) {
            // Install and runtime permissions are stored in different places,
            // so figure out what permission changed and persist the change.
            if (permissionsState.getInstallPermissionState(permName) != null) {
                callback.onInstallPermissionUpdated();
            } else if (permissionsState.getRuntimePermissionState(permName, userId) != null
                    || hadState) {
                callback.onPermissionUpdated(new int[] { userId }, false);
            }
        }
    }
    

    onPermissionUpdated的实现

    //把runtime权限跟新到runtime-permissions.xml中

      @Override
      public void onPermissionUpdated(int[] updatedUserIds, boolean sync) {
            synchronized (mPackages) {
                for (int userId : updatedUserIds) {
                    mSettings.writeRuntimePermissionsForUserLPr(userId, sync);
                }
            }
      }
    

    systemReady主要完成的是默认授权和更新package的信息,通知在等待pms的一些组件

    PMS之waitForAppDataPrepared

    public void waitForAppDataPrepared() {
        if (mPrepareAppDataFuture == null) {
            return;
        }
        ConcurrentUtils.waitForFutureNoInterrupt(mPrepareAppDataFuture, "wait for prepareAppData");
        mPrepareAppDataFuture = null;
    }
    ....................................................
    public static <T> T waitForFutureNoInterrupt(Future<T> future, String description) {
        try {
            return future.get();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new IllegalStateException(description + " interrupted");
        } catch (ExecutionException e) {
            throw new RuntimeException(description + " failed", e);
        }
    }
    

    获取特定的feature
    至此pms启动流程的下半部分就分析完成

    相关文章

      网友评论

          本文标题:基于Android9.0的PackageManagerServi

          本文链接:https://www.haomeiwen.com/subject/fumcaqtx.html