Android权限机制

2025-07-28

Android权限分类

Adnroid的权限保护级别由两个部分组成:一部分是基本的权限分类,分为normal, dangerous, signature和internal四个级别:

permission level

另一部分是一些额外的标签,如:

permission flag

一个权限的保护级别由两个部分运算而来,比如18表示为0x2|0x10,即PROTECTION_NORMAL | PROTECTION_FLAG_PRIVILIGED

声明安装时权限

使用安装时权限,需要在AndroidManifest.xml文件中声明相应的权限:

<manifest ...>
    <uses-permission android:name="android.permission.***"/>
    <application ...>
        ...
    </application>
</manifest>
  • normal级别的权限,只需要在声明中指定相应的权限就行
  • signature级别的权限,需要通过系统签名打包APK
  • 对于PROTECTION_FLAG_PRIVILIGED,在9.0版本之后,Android引入了allow-list机制,对于特权应用priv-app,需要在/system, /product, /vendor等目录下的/etc/permissions/priv-app/privapp-permissions-xxx.xml声明应用可以使用的权限:
<permissions>
    <privapp-permissions package="xxx.xxx.xxx">
    <permission name="android.permission.xxx"/>
    ...
    </privapp-permissions>
    ...
</permissions>

请求运行时权限

Android权限工作流

flowchart LR
A{是否需要使用权限}--是-->B[在manifest中声明权限]
A--否-->C[执行相应功能]
B--是-->D{是否使用运行时权限}
D--否-->C
D--是-->F[请求用户授权权限]
F-->C

Android权限机制

permision arch

framework层

PackageManagerService管理包的信息,并通过Settings.java读写packages.xml文件:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<packages>
    <version sdkVersion="34" databaseVersion="3" buildFingerprint="..." fingerprint="..." />
    <version volumeUuid="primary_physical" sdkVersion="34" databaseVersion="3" buildFingerprint="..." fingerprint="..." />
    <permission-trees />
    <!--权限集合-->
    <permissions>
        ...
        <item name="android.permission.XXX" package="android" protection="18" />
        ...
    </permissions>
    <!--包信息-->
    <package name = "..." ... sharedUserId = "..." ... >
        <!--签名信息-->
        <sigs count="1" schemeVersion="3">
            <cert index="0" />
        </sigs>
        <proper-signing-keyset identifier="1" />
        <!--权限信息-->
        <perms>
            ...
        </perms>
    </package>
    ...
    <!--一些升级过的包的信息-->
    <updated-package ... />
    ...
    <!--一些userId信息-->
    <shared-user name="android.uid.system" userId="1000">
        <sigs count="1" schemeVersion="3">
            <cert index="2" />
        </sigs>
    </shared-user>
    ...
    <domain-verifications>
        <active>
            <package-state .../>
            ...
        </active>
        ...
    </domain-verifications>
    <!--签名信息-->
    <keyset-settings version="1">
        <keys>
            <public-key .../>
            ...
        </keys>
        <keysets>
            <keyset identifier="1">
                <key-id identifier="1" />
            </keyset>
            ...
        </keysets>
        <lastIssuedKeyId value="23" />
        <lastIssuedKeySetId value="23" />
    </keyset-settings>
</packages>

,在packages.xml中,permissions标签下定义了不同的权限,包含权限名,包名以及保护级别protection,保护级别由两部分组成,分别是

授权流程

包扫描

通过解析目录下的文件,得到一个PackageImpl对象:

public class PackageImpl implements ParsedPackage, AndroidPackageInternal,
        AndroidPackageHidden, ParsingPackage, ParsingPackageHidden, Parcelable {
    ...
    private String sharedUserId;

    private List<ParsedUsesPermission> usesPermissions = emptyList();
}

安装时权限授权

sequenceDiagram
autonumber

participant PackageManagerService
participant Settings
participant InstallPackageHelper
participant PermissionCallback
participant PermissionManagerServiceImpl
participant UidPermissionState
participant PermissionState

Note over PackageManagerService,PermissionState: 更新安装包信息
activate InstallPackageHelper
InstallPackageHelper->>InstallPackageHelper: commitPackagesLocked
activate InstallPackageHelper
InstallPackageHelper->>InstallPackageHelper: updateSettingsLI  
activate InstallPackageHelper
InstallPackageHelper->>InstallPackageHelper: updateSetinggsInternalLI
InstallPackageHelper->>PermissionManagerServiceImpl: onPackageInstalled
activate PermissionManagerServiceImpl
deactivate InstallPackageHelper
deactivate InstallPackageHelper
deactivate InstallPackageHelper
activate PermissionManagerServiceImpl
PermissionManagerServiceImpl->>PermissionManagerServiceImpl: onPackageInstalledInternal
activate PermissionManagerServiceImpl
Note over PackageManagerService,PermissionState: 进行授权
PermissionManagerServiceImpl->>PermissionManagerServiceImpl: updatePermissions
activate PermissionManagerServiceImpl
PermissionManagerServiceImpl->>PermissionManagerServiceImpl: restorePermissionState
PermissionManagerServiceImpl->>UidPermissionState: grantPermission
activate UidPermissionState
UidPermissionState->>PermissionState: grant
PermissionState-->>UidPermissionState: 
UidPermissionState-->>PermissionManagerServiceImpl: 
deactivate UidPermissionState
Note over PackageManagerService,PermissionState: 持久化
PermissionManagerServiceImpl->>+PermissionCallback: onPermissionUpdated 
activate PackageManagerService
PermissionCallback->>-PackageManagerService: writeSettings
activate PackageManagerService
PackageManagerService->>PackageManagerService: writeSettingsLPrTEMP
PackageManagerService->>Settings: writeLPr
deactivate PackageManagerService
deactivate PackageManagerService
deactivate PermissionManagerServiceImpl
deactivate PermissionManagerServiceImpl
deactivate PermissionManagerServiceImpl
deactivate PermissionManagerServiceImpl

onPackageInstalled

public void onPackageInstalled(@NonNull AndroidPackage pkg, int previousAppId,
        @NonNull PermissionManagerServiceInternal.PackageInstalledParams params,
        @UserIdInt int userId) {
    ...
    onPackageInstalledInternal(pkg, previousAppId, params, userIds);
}

onPackageInstalledInternal

private void onPackageInstalledInternal(@NonNull AndroidPackage pkg, int previousAppId,
        @NonNull PermissionManagerServiceInternal.PackageInstalledParams params,
        @UserIdInt int[] userIds) {
    ...
    updatePermissions(pkg.getPackageName(), pkg);
    for (final int userId : userIds) {
        addAllowlistedRestrictedPermissionsInternal(pkg,
                params.getAllowlistedRestrictedPermissions(),
                FLAG_PERMISSION_WHITELIST_INSTALLER, userId);
        grantRequestedPermissionsInternal(pkg, params.getPermissionStates(), userId);
    }
}

updatePermissions

private void updatePermissions(@NonNull String packageName, @Nullable AndroidPackage pkg) {
    /**
    *如果传入的pkg为空,需要更新所有包的权限并替换包的权限信息
    *否则只替换报的权限信息
    **/
    final int flags =
            (pkg == null ? UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG
                    : UPDATE_PERMISSIONS_REPLACE_PKG);
    //调用另一个updatePermission方法
    updatePermissions(
            packageName, pkg, getVolumeUuidForPackage(pkg), flags, mDefaultPermissionCallback);
}


private void updatePermissions(final @Nullable String changingPkgName,
        final @Nullable AndroidPackage changingPkg,
        final @Nullable String replaceVolumeUuid,
        @UpdatePermissionFlags int flags,
        final @Nullable PermissionCallback callback) {
    //callback为PermissionManagerServiceImpl内部定义的mDefaultPermissionCallback
    if ((flags & UPDATE_PERMISSIONS_ALL) != 0) {
        final boolean replaceAll = ((flags & UPDATE_PERMISSIONS_REPLACE_ALL) != 0);
        mPackageManagerInt.forEachPackage((AndroidPackage pkg) -> {
            ...
            restorePermissionState(pkg, replace, changingPkgName, callback,
                    UserHandle.USER_ALL);
        });
    }
    if (changingPkg != null) {
        ...
        restorePermissionState(changingPkg, replace, changingPkgName, callback,
                UserHandle.USER_ALL);
    }
}

restorePermissionState

private void restorePermissionState(@NonNull AndroidPackage pkg, boolean replace,
        @Nullable String changingPackageName, @Nullable PermissionCallback callback,
        @UserIdInt int filterUserId) {
    final PackageStateInternal ps =
        mPackageManagerInt.getPackageStateInternal(pkg.getPackageName());
    ...

    for (final String permissionName : pkg.getRequestedPermissions()) {
        final Permission permission;
        synchronized (mLock) {
            permission = mRegistry.getPermission(permissionName);
        }
        if (permission == null) {
            continue;
        }
        //如果权限是privileged权限且在allowlist中进行了授权
        if (permission.isPrivileged()
                && checkPrivilegedPermissionAllowlist(pkg, ps, permission)) {
            if (isPrivilegedPermissionAllowlisted == null) {
                isPrivilegedPermissionAllowlisted = new ArraySet<>();
            }
            isPrivilegedPermissionAllowlisted.add(permissionName);
        }
        //如果权限是signature权限
        if (permission.isSignature() && (shouldGrantPermissionBySignature(pkg, permission)
                || shouldGrantPermissionByProtectionFlags(pkg, ps, permission,
                        shouldGrantPrivilegedPermissionIfWasGranted))) {
            if (shouldGrantSignaturePermission == null) {
                shouldGrantSignaturePermission = new ArraySet<>();
            }
            shouldGrantSignaturePermission.add(permissionName);
        }
        //内部权限
        if (permission.isInternal()
                && shouldGrantPermissionByProtectionFlags(pkg, ps, permission,
                        shouldGrantPrivilegedPermissionIfWasGranted)) {
            if (shouldGrantInternalPermission == null) {
                shouldGrantInternalPermission = new ArraySet<>();
            }
            shouldGrantInternalPermission.add(permissionName);
        }
    }

    //特定uid显式请求的权限
    Collection<String> uidRequestedPermissions;
    //特定uid隐式具有的权限
    Collection<String> uidImplicitPermissions;

    ...

    //进行权限授予的操作
    ...

    //调用callback的onPermissionUpdated方法
    if (callback != null) {
        callback.onPermissionUpdated(updatedUserIds,
                (changingPackageName != null && replace && installPermissionsChanged)
                        || runtimePermissionsRevoked, pkg.getUid());
    }
    
}

,方法维护了三个列表: isPrivilegedPermissionAllowlistedshouldGrantSignaturePermissionshouldGrantInternalPermission,表示需要授予包的不同级别的权限,方法同时维护了两个集合:uidRequestedPermissionsuidImplicitPermissions,表示与应用声明的sharedUserId相同的其他应用声明的权限和该sharedUserId下的隐式权限

权限授予的逻辑大致如下图: install permission grant

grantPermission

public boolean grantPermission(@NonNull Permission permission) {
    final PermissionState permissionState = getOrCreatePermissionState(permission);
    return permissionState.grant();
}

grant

public boolean grant() {
    synchronized (mLock) {
        if (mGranted) {
            return false;
        }
        mGranted = true;
        UidPermissionState.invalidateCache();
        return true;
    }
}

onPermissionUpdated

private final PermissionCallback mDefaultPermissionCallback = new PermissionCallback() {
    ...

    @Override
    public void onInstallPermissionUpdated() {
        mPackageManagerInt.writeSettings(true);
    }
};

PermissionManagerServiceImpl中声明了一个mDefaultPermissionCallback作为permission操作的callback调用对象,其onInstallPermissionUpdated方法在restorePermissionState方法中被调用,并调用PackageMangerService::writeSettings方法

writeSettings & writeSettingsLPrTEMP

void writeSettings(boolean sync) {
    synchronized (mLock) {
        ...
        writeSettingsLPrTEMP(sync);
        ...
    }
}

void writeSettingsLPrTEMP(boolean sync) {
    snapshotComputer(false);
    mPermissionManager.writeLegacyPermissionsTEMP(mSettings.mPermissions);
    mSettings.writeLPr(mLiveComputer, sync);
}

运行时权限授权

运行时权限授权主要通过PermissionManagerServicegrantRuntimePermissionInternal方法,并调用了UidPermissionState::grantPermission方法,之后,执行了如下代码:

final int uid = UserHandle.getUid(userId, pkg.getUid());
if (callback != null) {
    if (isRuntimePermission) {
        callback.onPermissionGranted(uid, userId);
    } else {
        callback.onInstallPermissionGranted();
    }
    if (permissionHasGids) {
        callback.onGidsChanged(UserHandle.getAppId(pkg.getUid()), userId);
    }
}

,如果权限是运行时权限,则调用onPermissionGranted方法,否则调用onInstallPermissionGranted方法,如果权限对应着权限组,则需要调用onGidsChanged方法