Android Kitkat的AppOps

Android Kitkat的AppOps

尽管KitKat的AOSP源代码注释掉了AppOps,表示它依然不成熟,但和4.3的时候相比,Kitkat的AppOps已经强大了不少。

新版AppOps出现了一个“保持唤醒状态”,后面可以看到,这个设置用来阻止应用程序获取wakelock(我没验证过它能不能实际做到)


除此以外,KitKat的AppOps还修正了几个bug,举些例子:


android.googlesource.com

4.3某些情况不能阻止拍照

CameraService and Stagefright: Support AppOps

Camera:
- Signal to AppOpsService when camera usage starts and stops
- Listen to permissions revocations and act on them
- Currently just kill camera connection when permissions lost

Stagefright:
- Pass on client name, UID to camera as needed

Bug: 8181262

android.googlesource.com

Fix AppOps exception for SMS quick reply feature.

Sending a quick SMS reply to an incoming phone call was failing
with a SecurityException due to new AppOps code. The root cause
was the insert() call in SmsProvider was calling back into itself
using the UID of the caller (com.android.mms) but the package name
for the callee (com.android.phone).

Wrapped the insert() method of SmsProvider with a helper function
to save the Binder identity and restore it on completion. This
allows the quick response to make its own provider queries using
its own UID as well as package name. Read/write security checks
will be performed by the content provider framework based on the
manifest file, before insert() is called.

Bug: 11006277

AppOps至少还有这些问题:

这里列出的所有43个Operations中,有的Operation没有对应的Android.Permission对象,而且checkOp()方法也只是一个不可靠的概念实现,有些Operation需要应用程序获取后才会有相应方法( startOP()/noteOp() )通知AppOpsManager。

于是,AppOps还做不到在安装应用程序之前便问用户允许哪些操作,另一方面目前也没有实现iOS那样在应用程序试图获取相关信息的同时时弹出询问的逻辑。

考虑到Kitkat只是注释掉setting app中有关AppOps设置的代码,而AppOpsManager实际上已经在4.3/4.4系统中默默地运行了,所以AppOps默认允许所有Ops,在4.4中设置为默认允许除了“编写短信”以外的所有Ops("编写短信"和“发送短信”不是一回事)

总之目前没有事先确认


在Android源代码里可以找到

[Android Source root]/packages/apps/Settings/src/com/android/settings/applications/AppOpsState.java

里面定义了几个OpsTemplate[1],每个

一共可以看到43个不同的AppOpsManager.OP_*常数,这便是AppOps目前能控制的资源。

AppOpsManager.OP_COARSE_LOCATION
AppOpsManager.OP_FINE_LOCATION
AppOpsManager.OP_GPS
AppOpsManager.OP_WIFI_SCAN
AppOpsManager.OP_NEIGHBORING_CELLS
AppOpsManager.OP_MONITOR_LOCATION
AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION
AppOpsManager.OP_READ_CONTACTS
AppOpsManager.OP_WRITE_CONTACTS
AppOpsManager.OP_READ_CALL_LOG
AppOpsManager.OP_WRITE_CALL_LOG
AppOpsManager.OP_READ_CALENDAR
AppOpsManager.OP_WRITE_CALENDAR
AppOpsManager.OP_READ_CLIPBOARD
AppOpsManager.OP_WRITE_CLIPBOARD
AppOpsManager.OP_READ_SMS
AppOpsManager.OP_RECEIVE_SMS
AppOpsManager.OP_RECEIVE_EMERGECY_SMS
AppOpsManager.OP_RECEIVE_MMS
AppOpsManager.OP_RECEIVE_WAP_PUSH
AppOpsManager.OP_WRITE_SMS
AppOpsManager.OP_SEND_SMS
AppOpsManager.OP_READ_ICC_SMS
AppOpsManager.OP_WRITE_ICC_SMS
AppOpsManager.OP_VIBRATE
AppOpsManager.OP_CAMERA
AppOpsManager.OP_RECORD_AUDIO
AppOpsManager.OP_PLAY_AUDIO
AppOpsManager.OP_TAKE_MEDIA_BUTTONS
AppOpsManager.OP_TAKE_AUDIO_FOCUS
AppOpsManager.OP_AUDIO_MASTER_VOLUME
AppOpsManager.OP_AUDIO_VOICE_VOLUME
AppOpsManager.OP_AUDIO_RING_VOLUME
AppOpsManager.OP_AUDIO_MEDIA_VOLUME
AppOpsManager.OP_AUDIO_ALARM_VOLUME
AppOpsManager.OP_AUDIO_NOTIFICATION_VOLUME
AppOpsManager.OP_AUDIO_BLUETOOTH_VOLUME
AppOpsManager.OP_POST_NOTIFICATION
AppOpsManager.OP_ACCESS_NOTIFICATIONS
AppOpsManager.OP_CALL_PHONE
AppOpsManager.OP_WRITE_SETTINGS
AppOpsManager.OP_SYSTEM_ALERT_WINDOW
AppOpsManager.OP_WAKE_LOCK

再转到

[Android Source root]/ frameworks/base/core/java/android/app/AppOpsManager.java

可以找到这样的注释:

App ops allows callers to:
Note when operations are happening, and find out if they are allowed for the current caller.
Disallow specific apps from doing specific operations.
Collect all of the current information about operations that have been executed or are not being allowed.
Monitor for changes in whether an operation is allowed.
Each operation is identified by a single integer; these integers are a fixed set of operations, enumerated by the OP_* constants.
When checking operations, the result is a "mode" integer indicating the current setting for the operation under that caller: MODE_ALLOWED, MODE_IGNORED (don't execute the operation but fake its behavior enough so that the caller doesn't crash), MODE_ERRORED (throw a SecurityException back to the caller; the normal operation calls will do this for you).

AppOps也是用了类似Xprivacy/PDroid的“返回一个符合格式但内容为空”的做法


注[1]:定义的OpsTemplate

      public static final OpsTemplate LOCATION_TEMPLATE = new OpsTemplate(
            new int[] { AppOpsManager.OP_COARSE_LOCATION,
                    AppOpsManager.OP_FINE_LOCATION,
                    AppOpsManager.OP_GPS,
                    AppOpsManager.OP_WIFI_SCAN,
                    AppOpsManager.OP_NEIGHBORING_CELLS,
                    AppOpsManager.OP_MONITOR_LOCATION,
                    AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION},
            new boolean[] { true,
                    true,
                    false,
                    false,
                    false,
                    false,
                    false}
            );

    public static final OpsTemplate PERSONAL_TEMPLATE = new OpsTemplate(
            new int[] { AppOpsManager.OP_READ_CONTACTS,
                    AppOpsManager.OP_WRITE_CONTACTS,
                    AppOpsManager.OP_READ_CALL_LOG,
                    AppOpsManager.OP_WRITE_CALL_LOG,
                    AppOpsManager.OP_READ_CALENDAR,
                    AppOpsManager.OP_WRITE_CALENDAR,
                    AppOpsManager.OP_READ_CLIPBOARD,
                    AppOpsManager.OP_WRITE_CLIPBOARD },
            new boolean[] { true,
                    true,
                    true,
                    true,
                    true,
                    true,
                    false,
                    false }
            );

    public static final OpsTemplate MESSAGING_TEMPLATE = new OpsTemplate(
            new int[] { AppOpsManager.OP_READ_SMS,
                    AppOpsManager.OP_RECEIVE_SMS,
                    AppOpsManager.OP_RECEIVE_EMERGECY_SMS,
                    AppOpsManager.OP_RECEIVE_MMS,
                    AppOpsManager.OP_RECEIVE_WAP_PUSH,
                    AppOpsManager.OP_WRITE_SMS,
                    AppOpsManager.OP_SEND_SMS,
                    AppOpsManager.OP_READ_ICC_SMS,
                    AppOpsManager.OP_WRITE_ICC_SMS },
            new boolean[] { true,
                    true,
                    true,
                    true,
                    true,
                    true,
                    true,
                    true,
                    true }
            );

    public static final OpsTemplate MEDIA_TEMPLATE = new OpsTemplate(
            new int[] { AppOpsManager.OP_VIBRATE,
                    AppOpsManager.OP_CAMERA,
                    AppOpsManager.OP_RECORD_AUDIO,
                    AppOpsManager.OP_PLAY_AUDIO,
                    AppOpsManager.OP_TAKE_MEDIA_BUTTONS,
                    AppOpsManager.OP_TAKE_AUDIO_FOCUS,
                    AppOpsManager.OP_AUDIO_MASTER_VOLUME,
                    AppOpsManager.OP_AUDIO_VOICE_VOLUME,
                    AppOpsManager.OP_AUDIO_RING_VOLUME,
                    AppOpsManager.OP_AUDIO_MEDIA_VOLUME,
                    AppOpsManager.OP_AUDIO_ALARM_VOLUME,
                    AppOpsManager.OP_AUDIO_NOTIFICATION_VOLUME,
                    AppOpsManager.OP_AUDIO_BLUETOOTH_VOLUME, },
            new boolean[] { false,
                    true,
                    true,
                    false,
                    false,
                    false,
                    false,
                    false,
                    false,
                    false,
                    false,
                    false,
                    false }
            );

    public static final OpsTemplate DEVICE_TEMPLATE = new OpsTemplate(
            new int[] { AppOpsManager.OP_POST_NOTIFICATION,
                    AppOpsManager.OP_ACCESS_NOTIFICATIONS,
                    AppOpsManager.OP_CALL_PHONE,
                    AppOpsManager.OP_WRITE_SETTINGS,
                    AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
                    AppOpsManager.OP_WAKE_LOCK },
            new boolean[] { false,
                    true,
                    true,
                    true,
                    true,
                    true,  }
            );

    public static final OpsTemplate[] ALL_TEMPLATES = new OpsTemplate[] {
            LOCATION_TEMPLATE, PERSONAL_TEMPLATE, MESSAGING_TEMPLATE,
            MEDIA_TEMPLATE, DEVICE_TEMPLATE
    };

Portions of this page are reproduced from work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.

编辑于 2013-11-22