前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[Android][Framework]PackageManagerService处理应用权限流程

[Android][Framework]PackageManagerService处理应用权限流程

作者头像
wOw
发布2020-01-21 10:30:52
1.7K1
发布2020-01-21 10:30:52
举报
文章被收录于专栏:wOw的Android小站wOw的Android小站

app种类

1、system app (有ApplicationInfo.FLAG_SYSTEM标记)

2、privileged app (有ApplicationInfo.FLAG_SYSTEM和ApplicationInfo.PRIVATE_FLAG_PRIVILEGE两个标记)

system app

system app 定义很明了,就是在PMS初始化安装app的时候赋予了ApplicationInfo.FLAG_SYSTEM这个标记

1、特定shareUID的app 代码在PMS的构造函数中

代码语言:javascript
复制
mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
        ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
        ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
        ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
        ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
        ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
        ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);

2、扫描安装特定目录的app 代码在PMS的构造函数中,扫描安装时给予PackageParser.PARSE_IS_SYSTEM标记的app,例如/vendor/overlay,/system/framework,/system/priv-app,/system/app,/vendor/app,/oem/app等,给予的PackageParser.PARSE_IS_SYSTEM最终会转换为ApplicationInfo.FLAG_SYSTEM,部分代码如下

代码语言:javascript
复制
File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
    scanDirTracedLI(vendorOverlayDir, mDefParseFlags
            | PackageParser.PARSE_IS_SYSTEM
            | PackageParser.PARSE_IS_SYSTEM_DIR
            | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
File customFrameworkDir = new File("/custom/framework");
    scanDirLI(customFrameworkDir, PackageParser.PARSE_IS_SYSTEM
            | PackageParser.PARSE_IS_SYSTEM_DIR,
            scanFlags | SCAN_NO_DEX, 0);
scanDirTracedLI(frameworkDir, mDefParseFlags
            | PackageParser.PARSE_IS_SYSTEM
            | PackageParser.PARSE_IS_SYSTEM_DIR
            | PackageParser.PARSE_IS_PRIVILEGED,
            scanFlags | SCAN_NO_DEX, 0);

flag转换的过程大致如下

代码语言:javascript
复制
-> scanDirLI(File dir, final int parseFlags, int scanFlags, long currentTime)
->  scanPackageTracedLI(PackageParser.Package pkg, final int policyFlags, 
        int scanFlags, long currentTime, UserHandle user)
-> scanPackageLI(PackageParser.Package pkg, final int policyFlags,
            int scanFlags, long currentTime, UserHandle user) 
-> scanPackageDirtyLI(PackageParser.Package pkg,
            final int policyFlags, final int scanFlags, long currentTime, UserHandle user)
//在scanPackageDirtyLI方法中将flag转换
// Apply policy
if ((policyFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
    pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
    ...
}

privileged app

privileged app在ApplicationInfo.FLAG_SYSTEM基础上还必须有ApplicationInfo.PRIVATE_FLAG_PRIVILEGED标记

1、特定shareUID的app 特定shareUID的app有ApplicationInfo.FLAG_SYSTEM的同时都有ApplicationInfo.PRIVATE_FLAG_PRIVILEGED

2、扫描特定目录app时,给予了PackageParser.PARSE_IS_SYSTEM标记和PackageParser.PARSE_IS_PRIVILEGED标记,目录有三个:system/framework,system/priv-app,vendor/priv-app 例如:

代码语言:javascript
复制
//vender/framework目录下有PackageParser.PARSE_IS_SYSTEM没有PackageParser.PARSE_IS_PRIVILEGED标记
File vendorFrameworkDir = new File(Environment.getVendorDirectory(), "framework");
scanDirTracedLI(vendorFrameworkDir, PackageParser.PARSE_IS_SYSTEM
    | PackageParser.PARSE_IS_SYSTEM_DIR,
    scanFlags | SCAN_NO_DEX, 0);

//system/framework目录下两个标记都有
scanDirTracedLI(frameworkDir, mDefParseFlags
    | PackageParser.PARSE_IS_SYSTEM
    | PackageParser.PARSE_IS_SYSTEM_DIR
    | PackageParser.PARSE_IS_PRIVILEGED,
    scanFlags | SCAN_NO_DEX, 0);

PackageParser.PARSE_IS_PRIVILEGED也是在scanPackageDirtyLI方法中转换的

代码语言:javascript
复制
if ((policyFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {
            pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
        }

PMS赋予apk的runtime权限

入口

PMS(PackageManagerService)在SystemServer中初始化完成最后调用PMS::systemReady,在systemReady方法中开始授予默认权限

代码语言:javascript
复制
final DefaultPermissionGrantPolicy mDefaultPermissionPolicy;
for (int userId : grantPermissionsUserIds) {
            mDefaultPermissionPolicy.grantDefaultPermissions(userId);
        }

DefaultPermissionGrantPolicy这个类就是管理默认权限的,最终的实现都是在PMS代码中

代码语言:javascript
复制
public void grantDefaultPermissions(int userId) {
    // 系统组件赋予Dangerous权限
        grantPermissionsToSysComponentsAndPrivApps(userId);
    // 指定app的指定权限
        grantDefaultSystemHandlerPermissions(userId);
    }

系统组件赋予Dangerous权限

代码语言:javascript
复制
private void grantPermissionsToSysComponentsAndPrivApps(int userId) {
        Log.i(TAG, "Granting permissions to platform components for user " + userId);

        synchronized (mService.mPackages) {
            for (PackageParser.Package pkg : mService.mPackages.values()) {
            // 过滤掉privileged app , FLAG_PERSISTENT标记app ,系统签名相同的app
                if (!isSysComponentOrPersistentPlatformSignedPrivAppLPr(pkg)
            // 判断targetSdkVersion > 22
                        || !doesPackageSupportRuntimePermissions(pkg)
            // 请求权限列表为空
                        || pkg.requestedPermissions.isEmpty()) {
                    continue;
                }
                Set<String> permissions = new ArraySet<>();
                final int permissionCount = pkg.requestedPermissions.size();
                for (int i = 0; i < permissionCount; i++) {
                    String permission = pkg.requestedPermissions.get(i);
                    BasePermission bp = mService.mSettings.mPermissions.get(permission);
            // 权限为Dangerous权限
                    if (bp != null && bp.isRuntime()) {
                        permissions.add(permission);
                    }
                }
                if (!permissions.isEmpty()) {
            // 添加权限
                    grantRuntimePermissionsLPw(pkg, permissions, true, userId);
                }
            }
        }
    }

接下来看下isSysComponentOrPersistentPlatformSignedPrivAppLPr和isRuntime的内容

代码语言:javascript
复制
private boolean isSysComponentOrPersistentPlatformSignedPrivAppLPr(PackageParser.Package pkg) {
    // UserID 小于10000
        if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) {
            return true;
        }
    // privileged app过滤
        if (!pkg.isPrivilegedApp()) {
            return false;
        }
    // 这两个判断过滤掉FLAG_PERSISTENT
        PackageSetting sysPkg = mService.mSettings.getDisabledSystemPkgLPr(pkg.packageName);
        if (sysPkg != null && sysPkg.pkg != null) {
            if ((sysPkg.pkg.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) {
                return false;
            }
        } else if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) {
            return false;
        }
    // 过滤掉系统签名相同的apk
        return PackageManagerService.compareSignatures(mService.mPlatformPackage.mSignatures,
                pkg.mSignatures) == PackageManager.SIGNATURE_MATCH;
    }
public boolean isRuntime() {
    // protectionLevel & PermissionInfo.PROTECTION_MASK_BASE 表示当前等级
        return (protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
                == PermissionInfo.PROTECTION_DANGEROUS;
    }

指定app的指定权限

这里是给指定某个app,给予它指定的几个权限,这里的代码十分类似,截取片段如下

代码语言:javascript
复制
private void grantDefaultSystemHandlerPermissions(int userId) {
    ...
    // Dialer
            if (dialerAppPackageNames == null) {
                Intent dialerIntent = new Intent(Intent.ACTION_DIAL);
                PackageParser.Package dialerPackage = getDefaultSystemHandlerActivityPackageLPr(
                        dialerIntent, userId);
                if (dialerPackage != null) {
                    grantDefaultPermissionsToDefaultSystemDialerAppLPr(dialerPackage, userId);
                }
            } else {
                for (String dialerAppPackageName : dialerAppPackageNames) {
                    PackageParser.Package dialerPackage = getSystemPackageLPr(dialerAppPackageName);
                    if (dialerPackage != null) {
                        grantDefaultPermissionsToDefaultSystemDialerAppLPr(dialerPackage, userId);
                    }
                }
            }

            // SMS
            if (smsAppPackageNames == null) {
                Intent smsIntent = new Intent(Intent.ACTION_MAIN);
                smsIntent.addCategory(Intent.CATEGORY_APP_MESSAGING);
                PackageParser.Package smsPackage = getDefaultSystemHandlerActivityPackageLPr(
                        smsIntent, userId);
                if (smsPackage != null) {
                   grantDefaultPermissionsToDefaultSystemSmsAppLPr(smsPackage, userId);
                }
            } else {
                for (String smsPackageName : smsAppPackageNames) {
                    PackageParser.Package smsPackage = getSystemPackageLPr(smsPackageName);
                    if (smsPackage != null) {
                        grantDefaultPermissionsToDefaultSystemSmsAppLPr(smsPackage, userId);
                    }
                }
            }
    ...
}
private void grantDefaultPermissionsToDefaultSystemDialerAppLPr(
            PackageParser.Package dialerPackage, int userId) {
        if (doesPackageSupportRuntimePermissions(dialerPackage)) {
            boolean isPhonePermFixed =
                    mService.hasSystemFeature(PackageManager.FEATURE_WATCH, 0);
            grantRuntimePermissionsLPw(
                    dialerPackage, PHONE_PERMISSIONS, isPhonePermFixed, userId);
            grantRuntimePermissionsLPw(dialerPackage, CONTACTS_PERMISSIONS, userId);
            grantRuntimePermissionsLPw(dialerPackage, SMS_PERMISSIONS, userId);
            grantRuntimePermissionsLPw(dialerPackage, MICROPHONE_PERMISSIONS, userId);
        }
    }

两种添加最后都走到了grantRuntimePermissionsLPw,我们接着分析grantRuntimePermissionsLPw函数

添加权限grantRuntimePermissionsLPw

grantRuntimePermissionsLPw赋予权限的代码,最终是交给PMS来处理,经过一些列判断后调用关键方法mService.grantRuntimePermission和mService.updatePermissionFlags,代码片段如下

代码语言:javascript
复制
private final PackageManagerService mService;
private void grantRuntimePermissionsLPw(PackageParser.Package pkg, Set<String> permissions,
    boolean systemFixed, boolean isDefaultPhoneOrSms, int userId) {
    ...
    mService.grantRuntimePermission(pkg.packageName, permission, userId);
    ...
    mService.updatePermissionFlags(permission, pkg.packageName,
    newFlags, newFlags, userId);
    ...
}

接着看PMS的grantRuntimePermission如何添加权限

代码语言:javascript
复制
    public void grantRuntimePermission(String packageName, String name, final int userId) {
        ...
    // 要添加权限,也需要“添加”权限
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
                "grantRuntimePermission");
    enforceCrossUserPermission(Binder.getCallingUid(), userId,
                true /* requireFullPermission */, true /* checkShell */,
                "grantRuntimePermission");
        ...
    // 添加权限
    final int result = permissionsState.grantRuntimePermission(bp, userId);
    switch (result) {
    case PermissionsState.PERMISSION_OPERATION_FAILURE: {
        return;
    }

    case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
        final int appId = UserHandle.getAppId(pkg.applicationInfo.uid);
        mHandler.post(new Runnable() {
        @Override
        public void run() {
            killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED);
        }
        });
    }
    break;
    }
    // PermissionsChanged监听
    mOnPermissionChangeListeners.onPermissionsChanged(uid);

    // 把数据更新到runtime-permissions.xml中
    mSettings.writeRuntimePermissionsForUserLPr(userId, false); 
}

最后grantRuntimePermission就是把permission存到mPermissions数据map中,再把数据跟新到/data/system/users/0/runtime-permissions.xml中,片段如下

代码语言:javascript
复制
<pkg name="com.google.android.apps.messaging">
  <item name="android.permission.READ_SMS" granted="true" flags="20" />
  <item name="android.permission.RECEIVE_WAP_PUSH" granted="true" flags="20" />
  <item name="android.permission.RECEIVE_MMS" granted="true" flags="20" />
  <item name="android.permission.RECEIVE_SMS" granted="true" flags="20" />
  <item name="android.permission.READ_PHONE_STATE" granted="true" flags="20" />
  <item name="android.permission.SEND_SMS" granted="true" flags="20" />
  <item name="android.permission.CALL_PHONE" granted="true" flags="20" />
  <item name="android.permission.WRITE_CONTACTS" granted="true" flags="20" />
  <item name="android.permission.READ_CONTACTS" granted="true" flags="20" />
</pkg>
<pkg name="com.google.android.setupwizard">
  <item name="android.permission.ACCESS_COARSE_LOCATION" granted="true" flags="20" />
  <item name="android.permission.CALL_PHONE" granted="true" flags="20" />
  <item name="android.permission.WRITE_CONTACTS" granted="true" flags="20" />
  <item name="android.permission.CAMERA" granted="true" flags="20" />
  <item name="android.permission.PROCESS_OUTGOING_CALLS" granted="true" flags="20" />
  <item name="android.permission.READ_CONTACTS" granted="true" flags="20" />
</pkg>

PMS赋予apk安装权限

过程精简如下:

代码语言:javascript
复制
-> scanDirLI(File dir, final int parseFlags, int scanFlags, long currentTime)
->  scanPackageTracedLI(PackageParser.Package pkg, final int policyFlags, 
        int scanFlags, long currentTime, UserHandle user)
-> scanPackageLI(PackageParser.Package pkg, final int policyFlags,
            int scanFlags, long currentTime, UserHandle user) 
-> scanPackageDirtyLI(PackageParser.Package pkg,
            final int policyFlags, final int scanFlags, long currentTime, UserHandle user)
-> updateSettingsLI(PackageParser.Package newPackage, String installerPackageName,
            int[] allUsers, PackageInstalledInfo res, UserHandle user)
-> updateSettingsInternalLI(PackageParser.Package newPackage,
            String installerPackageName, int[] allUsers, int[] installedForUsers,
            PackageInstalledInfo res, UserHandle user)
-> updatePermissionsLPw(String changingPkg, PackageParser.Package pkgInfo,
            int flags)
-> updatePermissionsLPw(String changingPkg,
            PackageParser.Package pkgInfo, String replaceVolumeUuid, int flags)
-> grantPermissionsLPw(PackageParser.Package pkg, boolean replace,
            String packageOfInterest)

在grantPermissionsLPw函数中做最后权限赋予操作,代码片段如下:

代码语言:javascript
复制
private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace,
        String packageOfInterest) {
 for (int i=0; i<N; i++) {
        final String name = pkg.requestedPermissions.get(i); // 权限名字
        final BasePermission bp = mSettings.mPermissions.get(name); // 权限信息
    ...

        final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE; // 权限级别ProtectionLevel
        final boolean appSupportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion
                >= Build.VERSION_CODES.M;
    // 根据权限级别定义grant
        switch (level) {
            case PermissionInfo.PROTECTION_NORMAL: {
                // For all apps normal permissions are install time ones.
                grant = GRANT_INSTALL;
            } break;

            case PermissionInfo.PROTECTION_DANGEROUS: {
                if (!appSupportsRuntimePermissions && !Build.isPermissionReviewRequired()) {
                    // For legacy apps dangerous permissions are install time ones.
                    grant = GRANT_INSTALL;
                } else if (origPermissions.hasInstallPermission(bp.name)) {
                    // For legacy apps that became modern, install becomes runtime.
                    grant = GRANT_UPGRADE;
                } else if (mPromoteSystemApps
                    && isSystemApp(ps)
                    && mExistingSystemPackages.contains(ps.name)) {
                    // For legacy system apps, install becomes runtime.
                    // We cannot check hasInstallPermission() for system apps since those
                    // permissions were granted implicitly and not persisted pre-M.
                    grant = GRANT_UPGRADE;
                } else {
                    // For modern apps keep runtime permissions unchanged.
                    grant = GRANT_RUNTIME;
                }
            } break;

            case PermissionInfo.PROTECTION_SIGNATURE: {
                // For all apps signature permissions are install time ones.
                allowedSig = grantSignaturePermission(perm, pkg, bp, origPermissions);
                if (allowedSig) {
                    grant = GRANT_INSTALL;
                }
            } break;
        }
    ...
        if (grant != GRANT_DENIED) {
            if (!isSystemApp(ps) && ps.installPermissionsFixed) {
                // If this is an existing, non-system package, then
                // we can't add any new permissions to it.
                if (!allowedSig && !origPermissions.hasInstallPermission(perm)) {
                    // Except...  if this is a permission that was added
                    // to the platform (note: need to only do this when
                    // updating the platform).
                    if (!isNewPlatformPermissionForPackage(perm, pkg)) {
                        grant = GRANT_DENIED;
                    }
                }
            }
    // 根据grant 选择权限给予方式
            switch (grant) {
                case GRANT_INSTALL: {
                    for (int userId : UserManagerService.getInstance().getUserIds()) {
                        if (origPermissions.getRuntimePermissionState(
                                bp.name, userId) != null) {
                            // Revoke the runtime permission and clear the flags.
                            origPermissions.revokeRuntimePermission(bp, userId);
                            origPermissions.updatePermissionFlags(bp, userId,
                                  PackageManager.MASK_PERMISSION_FLAGS, 0);
                            // If we revoked a permission permission, we have to write.
                            changedRuntimePermissionUserIds = ArrayUtils.appendInt(
                                    changedRuntimePermissionUserIds, userId);
                        }
                    }
                    // install权限
                    if (permissionsState.grantInstallPermission(bp) !=
                            PermissionsState.PERMISSION_OPERATION_FAILURE) {
                        changedInstallPermission = true;
                    }
                } break;

                case GRANT_RUNTIME: {
                    // Grant previously granted runtime permissions.
                    for (int userId : UserManagerService.getInstance().getUserIds()) {
                        PermissionState permissionState = origPermissions
                                .getRuntimePermissionState(bp.name, userId);
                        int flags = permissionState != null
                                ? permissionState.getFlags() : 0;
                        if (origPermissions.hasRuntimePermission(bp.name, userId)) {
                            if (permissionsState.grantRuntimePermission(bp, userId) ==
                                    PermissionsState.PERMISSION_OPERATION_FAILURE) {
                                // If we cannot put the permission as it was, we have to write.
                                changedRuntimePermissionUserIds = ArrayUtils.appendInt(
                                        changedRuntimePermissionUserIds, userId);
                            }
                            // If the app supports runtime permissions no need for a review.
                            /// M: CTA requirement - permission control
                            if (Build.isPermissionReviewRequired()
                                    && appSupportsRuntimePermissions
                                    && (flags & PackageManager
                                            .FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
                                flags &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
                                // Since we changed the flags, we have to write.
                                changedRuntimePermissionUserIds = ArrayUtils.appendInt(
                                        changedRuntimePermissionUserIds, userId);
                            }
                        /// M: CTA requirement - permission control
                        } else if (Build.isPermissionReviewRequired()
                                && !appSupportsRuntimePermissions) {
                            if (CtaUtils.isPlatformPermission(bp.sourcePackage, bp.name)
                                    && pkgReviewRequired) {
                                if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
                                    /// M: CTA requirement - review UI for all apps  @{
                                    Slog.d(TAG, "add review UI for legacy pkg = " +
                                            pkg.packageName + ", permission = " +
                                            bp.name + ", userId = " + userId +
                                            ", uid = " + pkg.mSharedUserId);
                                    ///@}
                                    flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
                                    // We changed the flags, hence have to write.
                                    changedRuntimePermissionUserIds = ArrayUtils.appendInt(
                                            changedRuntimePermissionUserIds, userId);
                                }
                            }
            // runtime权限
                            if (permissionsState.grantRuntimePermission(bp, userId)
                                    != PermissionsState.PERMISSION_OPERATION_FAILURE) {
                                // We changed the permission, hence have to write.
                                changedRuntimePermissionUserIds = ArrayUtils.appendInt(
                                        changedRuntimePermissionUserIds, userId);
                            }
                        /// M: CTA requirement - review UI for all apps  @{
                        } else if (appSupportsRuntimePermissions &&
                                pkgReviewRequired) {
                            if (CtaUtils.isPlatformPermission(bp.sourcePackage, bp.name)) {
                                if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0 &&
                                        (flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED)
                                        == 0) {
                                    Slog.d(TAG, "add review UI for non-legacy pkg = " +
                                            pkg.packageName + ", permission = " +
                                            bp.name + ", userId = " + userId +
                                            ", uid = " + pkg.mSharedUserId);
                                    flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
                                    // We changed the flags, hence have to write.
                                    changedRuntimePermissionUserIds = ArrayUtils.appendInt(
                                            changedRuntimePermissionUserIds, userId);
                                }
                            }
                        }
                        ///@}
                        // Propagate the permission flags.
                        permissionsState.updatePermissionFlags(bp, userId, flags, flags);
                    }
                } break;

                case GRANT_UPGRADE: {
                    // Grant runtime permissions for a previously held install permission.
                    PermissionState permissionState = origPermissions
                            .getInstallPermissionState(bp.name);
                    final int flags = permissionState != null ? permissionState.getFlags() : 0;

                    if (origPermissions.revokeInstallPermission(bp)
                            != PermissionsState.PERMISSION_OPERATION_FAILURE) {
                        // 跟新应用的权限
                        origPermissions.updatePermissionFlags(bp, UserHandle.USER_ALL,
                                PackageManager.MASK_PERMISSION_FLAGS, 0);
                        changedInstallPermission = true;
                    }

                    // If the permission runtime-permissions.xmlis not to be promoted to runtime we ignore it and
                    // also its other flags as they are not applicable to install permissions.
                    if ((flags & PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE) == 0) {
                        for (int userId : currentUserIds) {
                            if (permissionsState.grantRuntimePermission(bp, userId) !=
                                    PermissionsState.PERMISSION_OPERATION_FAILURE) {
                                // Transfer the permission flags.
                                permissionsState.updatePermissionFlags(bp, userId,
                                        flags, flags);
                                // If we granted the permission, we have to write.
                                changedRuntimePermissionUserIds = ArrayUtils.appendInt(
                                        changedRuntimePermissionUserIds, userId);
                            }
                        }
                    }
                } break;

                default: {
                    if (packageOfInterest == null
                            || packageOfInterest.equals(pkg.packageName)) {
                        Slog.w(TAG, "Not granting permission " + perm
                                + " to package " + pkg.packageName
                                + " because it was previously installed without");
                    }
                } break;
            }
        } else {
            if (permissionsState.revokeInstallPermission(bp) !=
                    PermissionsState.PERMISSION_OPERATION_FAILURE) {
                // Also drop the permission flags.
                permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
                        PackageManager.MASK_PERMISSION_FLAGS, 0);
                changedInstallPermission = true;
                Slog.i(TAG, "Un-granting permission " + perm
                        + " from package " + pkg.packageName
                        + " (protectionLevel=" + bp.protectionLevel
                        + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
                        + ")");
            } else if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) == 0) {
                // Don't print warning for app op permissions, since it is fine for them
                // not to be granted, there is a UI for the user to decide.
                if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) {
                    Slog.w(TAG, "Not granting permission " + perm
                            + " to package " + pkg.packageName
                            + " (protectionLevel=" + bp.protectionLevel
                            + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
                            + ")");
                }
            }
        }
    }

    if ((changedInstallPermission || replace) && !ps.installPermissionsFixed &&
            !isSystemApp(ps) || isUpdatedSystemApp(ps)){
        // This is the first that we have heard about this package, so the
        // permissions we have now selected are fixed until explicitly
        // changed.
        ps.installPermissionsFixed = true;
    }

    // 把runtime权限跟新到runtime-permissions.xml中
    for (int userId : changedRuntimePermissionUserIds) {
        mSettings.writeRuntimePermissionsForUserLPr(userId, runtimePermissionsRevoked);
    }

    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}

grantPermissionsLPw函数根据权限等级,来赋予权限。注意:这里的安装时赋予的runtime权限是之前已经赋予过此apk的权限才会执行到GRANT_RUNTIME 回到上面的精简过程: updateSettingsInternalLI方法中调用updatePermissionsLPw后,最后会调用mSettings.writeLPr(); 这些权限信息就被写到data/system/packages.xml中了,举例片段代码:

代码语言:javascript
复制
...
<package name="com.android.settings" codePath="/system/priv-app/Settings" nativeLibraryPath="/system/priv-app/Settings/lib" primaryCpuAbi="arm64-v8a" publicFlags="944258629" privateFlags="8" ft="15f7a5ec8a8" it="15f7a5ec8a8" ut="15f7a5ec8a8" version="25" sharedUserId="1000" isOrphaned="true">
        <sigs count="1">
            <cert index="1" />
        </sigs>
        <perms>
            <item name="android.permission.BIND_INCALL_SERVICE" granted="true" flags="0" />
            <item name="android.permission.WRITE_SETTINGS" granted="true" flags="0" />
            <item name="com.google.android.gm.permission.WRITE_GMAIL" granted="true" flags="0" />
            <item name="android.permission.CONFIGURE_WIFI_DISPLAY" granted="true" flags="0" />
            <item name="android.permission.CONFIGURE_DISPLAY_COLOR_MODE" granted="true" flags="0" />
            <item name="android.permission.ACCESS_WIMAX_STATE" granted="true" flags="0" />
            <item name="com.qualcomm.permission.READPROC" granted="true" flags="0" />
            <item name="android.permission.RESTART_PACKAGES" granted="true" flags="0" />
            <item name="android.permission.USE_CREDENTIALS" granted="true" flags="0" />
            <item name="android.permission.MODIFY_AUDIO_SETTINGS" granted="true" flags="0" />
            <item name="android.permission.ACCESS_CHECKIN_PROPERTIES" granted="true" flags="0" />
            <item name="android.permission.MODIFY_AUDIO_ROUTING" granted="true" flags="0" />
    ...

小结

1、PMS扫描安装时赋予安装权限

2、PMS在systemReady函数中调用mDefaultPermissionPolicy.grantDefaultPermissions来赋予运行权限即dangerous权限

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-04-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • app种类
    • system app
      • privileged app
      • PMS赋予apk的runtime权限
        • 入口
          • 系统组件赋予Dangerous权限
            • 指定app的指定权限
              • 添加权限grantRuntimePermissionsLPw
              • PMS赋予apk安装权限
              • 小结
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档