关于AppOpsManager部分

1.基本技能储备

binder通信这个是必须知道的。
解释一下appops这个功能:这个功能其实与android的manifest权限管理是完全没有联系的,应该说是完全没有关系的两个模块(当然也不能说完全没有关系,因为在权限检查的时候会先进行manifest的权限检查,再进行appops的权限检查)。

2.appops如何实现的

总结

其实appops的基本原理就是通过在需要进行权限检查的地方插入固定的权限检查代码,来实现权限拦截的目的

1.appopsmanager分析

1.权限标志位

appopsmanager就是binder通信中的bp端了,那就先从bp端入手吧。 appopsmanager.java位置就是在sourcecode/framework/base/core/java/android/app

在appopsmanager的开头就定义了不同的权限标志位,如:

/** @hide Access to coarse location information. */
public static final int OP_COARSE_LOCATION = 0;
/** @hide Access to fine location information. */
public static final int OP_FINE_LOCATION = 1;

上面就是截取的一部分,OP_COARSE_LOCATION是获取粗略位置的权限,如果需要添加权限可以在对应的最后添加标志位,但是也要记得在使用到权限的地方添加权限检查的方法。

2.设置权限检查的代码

在有了权限标志位之后,我们当然是需要在对应的位置添加权限检查的代码,来检查某个应用是否有权限去执行操作。

if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
            return false;
        }

这段代码是framework/base/services/core/java/android/server/locationmanagerservice中的一段检查OP_COARSE_LOCATION的代码。其中调用的noteopnothrow方法就是权限检查的方法。
权限检查的方法其实分为两种(都在appopsmanager类中):
1.noteop:针对短时间一次性操作,如读取短信或者发送短信等。
2.startop:针对长时间操作,如wakelock,以及gps等。
当然了,该方法传入的参数也是显而易见的,uid以及packagename。通过这两个参数可以得到设置的权限OP的状态是允许还是拒绝,如果不是允许的话就会返回权限不允许。

3.设置权限状态

有了权限检查的部分,那么下面就是要知道如何设置权限了:
在appopsmanager中有方法setmode方法

/** @hide */
public void setMode(int code, int uid, String packageName, int mode) {
    try {
        mService.setMode(code, uid, packageName, mode);
    } catch (RemoteException e) {
    }
}

参数的含义:
code:就是上方对应的op,想设置的某个权限。
uid:设置的应用的uid。
packagename:包名。
mode:当然了,就是对应的mode。
mode的话在appopsmanager中是有静态值对应的,有MODE_ALLOW,MODE_ERROR,MODE_IGNORE也就是拒绝了。

结束语

那么,现在从权限的开始,也就是添加,到权限的检查,以及权限的设置都已经说完了。但是它们究竟是如何实现的,那其实就需要去看对应的bn端的代码。所以下一篇就是appopsservice的代码解读了。