前言:
在公司中做Framework的定制也已经两年多了,陆陆续续的也改了不少的系统服务,替客户制定过不少api接口。之前关于一些需要系统级权限的接口也都是通过将apk进行系统签名的方式来实现的,虽然这种做法也并无不妥,但是仔细考虑了一下应该还是有其他方式可以让apk与系统的耦合度变的更低的。(大不了就是在其他机器上调用不了这个接口了)
网上找了一下也早就已经有人对权限机制和安全机制做过一些分析,但是都不太涉及到具体的调用链,而且一般都是添加新的权限限制而不是绕开原有限制。
浅析Android权限机制(一) —— Android的权限机制
Android安全机制(2) Android Permission权限控制机制
好了,接下来就是一些系统Framework的接口调用追踪了,只想看解决方案的话可以直接拉到最后。
调用流程(MT8735_M平台):
这里我们就挑一个具体的案例来分析吧,以蓝牙作为例子,apk如果需要管理蓝牙连接,就必须声明蓝牙相关的permission,那么这个permission的检查又是在哪里进行的呢。
BluetoothManagerService.java
public boolean enable() {
if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
(!checkIfCallerIsForegroundUser())) {
Log.w(TAG,"enable(): not allowed for non-active and non system user");
return false;
}
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
if (DBG) {
Log.d(TAG,"enable(): mBluetooth =" + mBluetooth +
" mBinding = " + mBinding);
}
从这个enable函数可以看到,在执行enable函数开启蓝牙时,会先检查是否是系统进程,如果不是系统进程的话就需要在前台运行。
然后就通过Context(aondroid.content.Context)类的enforceCallingOrSelfPermission函数来检查相应的权限,这里的权限是一个常量,具体的定义是
private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
现在我们转到Context.java这个类里去看看:
/**
* Determine whether the calling process of an IPC <em>or you</em> have been
* granted a particular permission. This is the same as
* {@link #checkCallingPermission}, except it grants your own permissions
* if you are not currently processing an IPC. Use with care!
*
* @param permission The name of the permission being checked.
*
* @return {@link PackageManager#PERMISSION_GRANTED} if the calling
* pid/uid is allowed that permission, or
* {@link PackageManager#PERMISSION_DENIED} if it is not.
*
* @see PackageManager#checkPermission(String, String)
* @see #checkPermission
* @see #checkCallingPermission
*/
@CheckResult(suggest="#enforceCallingOrSelfPermission