android p 权限流程,Android native 权限控制流程

关联文章:

前言:

在 Android Runtime Permission 详解 中详细的说明了permission 在Android 6.0 前后的区别,对于M 以后应用可以通过checkPermission 、requestPermission 等一系列的接口控制,但是在M之前的应用是看不到这样的接口,功能的开启会直接调用接口,例如Camera,会直接调用open 的接口。

那我们如何来控制这些权限的呢?在M 之后的系统中,native 的接口里会通过checkPermission 的接口,来确认是否拥有改功能对应的权限,例如Camera,会check android.permission.CAMERA 这个权限。

这一篇博文就是分析M 之后系统对于权限native接口的控制流程。

源码分析:

首先来看IServiceManager.h:

namespace android {

// ----------------------------------------------------------------------

class IServiceManager : public IInterface

{

...

...

};

sp defaultServiceManager();

template

status_t getService(const String16& name, sp* outService)

{

const sp sm = defaultServiceManager();

if (sm != NULL) {

*outService = interface_cast(sm->getService(name));

if ((*outService) != NULL) return NO_ERROR;

}

return NAME_NOT_FOUND;

}

bool checkCallingPermission(const String16& permission);

bool checkCallingPermission(const String16& permission,

int32_t* outPid, int32_t* outUid);

bool checkPermission(const String16& permission, pid_t pid, uid_t uid);

}; // namespace android

1、首先命名空间是android,所以有的地方通过接口android::checkPermission 来调用此处的接口

例如,PermissionCache.cpp 中:

bool PermissionCache::checkPermission(

const String16& permission, pid_t pid, uid_t uid) {

if ((uid == 0) || (pid == getpid())) {

// root and ourselves is always okay

return true;

}

PermissionCache& pc(PermissionCache::getInstance());

bool granted = false;

if (pc.check(&granted, permission, uid) != NO_ERROR) {

nsecs_t t = -systemTime();

granted = android::checkPermission(permission, pid, uid);

t += systemTime();

ALOGD("checking %s for uid=%d => %s (%d us)",

String8(permission).string(), uid,

granted?"granted":"denied", (int)ns2us(t));

pc.cache(permission, uid, granted);

}

return granted;

2、之所以首先来看IServiceManager.h,是因为其中提供了很多android 空间中的公共接口,例如defaultServiceManager()、getService()、checkPermission()

最终checkPermission() 实现的地方是在IServiceManger.cpp 中:

bool checkPermission(const String16& permission, pid_t pid, uid_t uid)

{

sp pc;

gDefaultServiceManagerLock.lock();

pc = gPermissionController;

gDefaultServiceManagerLock.unlock();

int64_t startTime = 0;

while (true) {

if (pc != NULL) {

bool res = pc->checkPermission(permission, pid, uid);

...

}

...

}

...

}

通过IPermissionController 来调用checkPermission()

来看下IPermissionController.h:

class IPermissionController : public IInterface

{

public:

DECLARE_META_INTERFACE(PermissionController)

virtual bool checkPermission(const String16& permission, int32_t pid, int32_t uid) = 0;

virtual void getPackagesForUid(const uid_t uid, Vector &packages) = 0;

virtual bool isRuntimePermission(const String16& permission) = 0;

enum {

CHECK_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,

GET_PACKAGES_FOR_UID_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 1,

IS_RUNTIME_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 2

};

};

class BnPermissionController : public BnInterface

{

public:

virtual status_t onTransact( uint32_t code,

const Parcel& data,

Parcel* reply,

uint32_t flags = 0);

};

实现的地方就看BnPermissionController 的地方了,从整个项目来看,native 会启动一个permission 的native service,详细看framework/native/services/nativeperms/nativeperms.cpp:

class PermissionService : public android::os::BnPermissionController {

public:

::android::binder::Status checkPermission(

const ::android::String16& permission, int32_t pid, int32_t uid,

bool* _aidl_return) {

(void)permission;

(void)pid;

(void)uid;

*_aidl_return = true;

return binder::Status::ok();

}

再来看下Java 中android.os.IPermissionController,首先来看aidl,

package android.os;

/** @hide */

interface IPermissionController {

boolean checkPermission(String permission, int pid, int uid);

String[] getPackagesForUid(int uid);

boolean isRuntimePermission(String permission);

}

跟着这个aidl 来知道它的service 端,在ActivityManagerService.java中,

public void setSystemProcess() {

try {

ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);

ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);

ServiceManager.addService("meminfo", new MemBinder(this));

ServiceManager.addService("gfxinfo", new GraphicsBinder(this));

ServiceManager.addService("dbinfo", new DbBinder(this));

if (MONITOR_CPU_USAGE) {

ServiceManager.addService("cpuinfo", new CpuBinder(this));

}

ServiceManager.addService("permission", new PermissionController(this));//这里添加permission 的service

ServiceManager.addService("processinfo", new ProcessInfoService(this));

接着就是service 端:

static class PermissionController extends IPermissionController.Stub {

ActivityManagerService mActivityManagerService;

PermissionController(ActivityManagerService activityManagerService) {

mActivityManagerService = activityManagerService;

}

@Override

public boolean checkPermission(String permission, int pid, int uid) {

return mActivityManagerService.checkPermission(permission, pid,

uid) == PackageManager.PERMISSION_GRANTED;

}

接着:

@Override

public int checkPermission(String permission, int pid, int uid) {

if (permission == null) {

return PackageManager.PERMISSION_DENIED;

}

return checkComponentPermission(permission, pid, uid, -1, true);

}

接着:

int checkComponentPermission(String permission, int pid, int uid,

int owningUid, boolean exported) {

if (pid == MY_PID) {

return PackageManager.PERMISSION_GRANTED;

}

return ActivityManager.checkComponentPermission(permission, uid,

owningUid, exported);

}

接着:

public static int checkComponentPermission(String permission, int uid,

int owningUid, boolean exported) {

...

...

try {

return AppGlobals.getPackageManager()

.checkUidPermission(permission, uid);

} catch (RemoteException e) {

throw e.rethrowFromSystemServer();

}

}

最终会调到PMS 中的checkUidPermission,完成最后的确认工作。

这里source code 基本都是逻辑问题,不需要详细讲解,有什么问题可以随时交流。

checkUidPermission 的source code 这里暂不贴出来,详细可以看下 android grantRuntimePermission 详解

其实,最主要的是PermissionsState 中的mPermissions,如果grant 了,那么里面会有这样的permission,如果是revoke 的,那么就不会有这样的permission。当然,对于M 之前的app,这里默认肯定都是granted的。

这一篇博文主要是分析native 的check 流程,至于CTA 要求M 之前app 同样需要弹出对话框提示用户,看另一篇博文。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值