Android AppOpsService服务实践贴

来源:互联网 发布:广州南航信息中心 知乎 编辑:程序博客网 时间:2024/06/08 18:37

版本信息:Android 4.4.2


一、与AppOpsService因缘

自己整了个系统服务,然后在系统服务中通过Settings设置属性值、读写系统数据库:

private boolean setStaticIpInfo(int index, String value) {boolean ret = false;try {ret = System.putString(mContext.getContentResolver(), mSettingNames[index], value);return true;} catch (Exception e) {e.printStackTrace();ret = false;}return ret;}

结果,老给报错误:
Package android does not belong to 10023
对应错误出处:
AppOpsManager.java (frameworks\base\core\java\android\app)public void checkPackage(int uid, String packageName) {    try {        if (mService.checkPackage(uid, packageName) != MODE_ALLOWED) {            throw new SecurityException(                    "Package " + packageName + " does not belong to " + uid);        }    }}

Bad call: specified package android under uid 10023 but it is really 1000
对应错误出处:
AppOpsService.java (frameworks\base\services\java\com\android\server)private Ops getOpsLocked(int uid, String packageName, boolean edit) {    if (pkgUid != uid) {        // Oops!  The package name is not valid for the uid they are calling        // under.  Abort.        Slog.w(TAG, "Bad call: specified package " + packageName                + " under uid " + uid + " but it is really " + pkgUid);        return null;    }}

二、为什么报这些错误

AppOpsService是一个系统服务,从版本4..4.2(Added in API level 19)之后引进(据说),用来对系统权限进行检测,以运行/禁止某种操作。
“AppOpsManager是一个访问AppOpsService服务的类,同时有 Java 和 C 的实现,为了应对某些 native code 的服务,比如说 Camera。”
要想使用AppOpsService功能,就需要在权限检测的地方添加这部分代码,比如:
对于以上的错误,Settings在put数据之前,就添加了AppOpsService功能:

SettingsProvider.java (frameworks\base\packages\settingsprovider\src\com\android\providers\settings)@Overridepublic Bundle call(String method, String request, Bundle args) {    // Framework can't do automatic permission checking for calls, so we need    // to do it here.    if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS)            != PackageManager.PERMISSION_GRANTED) {        throw new SecurityException(                String.format("Permission denial: writing to settings requires %1$s",                              android.Manifest.permission.WRITE_SETTINGS));    }    // Also need to take care of app op.    if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SETTINGS, Binder.getCallingUid(),            getCallingPackage()) != AppOpsManager.MODE_ALLOWED) {        return null;    }    final ContentValues values = new ContentValues();    values.put(Settings.NameValueTable.NAME, request);    values.put(Settings.NameValueTable.VALUE, newValue);}

可知,在更改数据前,先进行常规的WRITE_SETTINGS检查,然后利用AppOpsService进行进一步检查。

三、问题解决

由于特殊情况,直接把AppOpsService服务注释掉了。
但是,对于API版本6.0(API level 23)及以上,可以参考:
https://developer.android.com/reference/android/provider/Settings.System.html#canWrite%28android.content.Context%2


1 0