| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.app; |
| |
| import android.Manifest; |
| import android.annotation.NonNull; |
| import android.annotation.RequiresPermission; |
| import android.annotation.SystemApi; |
| import android.annotation.SystemService; |
| import android.annotation.TestApi; |
| import android.app.usage.UsageStatsManager; |
| import android.content.Context; |
| import android.media.AudioAttributes.AttributeUsage; |
| import android.os.Binder; |
| import android.os.IBinder; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| import android.os.Process; |
| import android.os.RemoteException; |
| import android.os.UserManager; |
| import android.util.ArrayMap; |
| |
| import com.android.internal.app.IAppOpsActiveCallback; |
| import com.android.internal.app.IAppOpsCallback; |
| import com.android.internal.app.IAppOpsService; |
| import com.android.internal.util.Preconditions; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.List; |
| |
| /** |
| * API for interacting with "application operation" tracking. |
| * |
| * <p>This API is not generally intended for third party application developers; most |
| * features are only available to system applications. |
| */ |
| @SystemService(Context.APP_OPS_SERVICE) |
| public class AppOpsManager { |
| /** |
| * <p>App ops allows callers to:</p> |
| * |
| * <ul> |
| * <li> Note when operations are happening, and find out if they are allowed for the current |
| * caller.</li> |
| * <li> Disallow specific apps from doing specific operations.</li> |
| * <li> Collect all of the current information about operations that have been executed or |
| * are not being allowed.</li> |
| * <li> Monitor for changes in whether an operation is allowed.</li> |
| * </ul> |
| * |
| * <p>Each operation is identified by a single integer; these integers are a fixed set of |
| * operations, enumerated by the OP_* constants. |
| * |
| * <p></p>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). |
| */ |
| |
| final Context mContext; |
| final IAppOpsService mService; |
| final ArrayMap<OnOpChangedListener, IAppOpsCallback> mModeWatchers = new ArrayMap<>(); |
| final ArrayMap<OnOpActiveChangedListener, IAppOpsActiveCallback> mActiveWatchers = |
| new ArrayMap<>(); |
| |
| static IBinder sToken; |
| |
| /** |
| * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller is |
| * allowed to perform the given operation. |
| */ |
| public static final int MODE_ALLOWED = 0; |
| |
| /** |
| * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller is |
| * not allowed to perform the given operation, and this attempt should |
| * <em>silently fail</em> (it should not cause the app to crash). |
| */ |
| public static final int MODE_IGNORED = 1; |
| |
| /** |
| * Result from {@link #checkOpNoThrow}, {@link #noteOpNoThrow}, {@link #startOpNoThrow}: the |
| * given caller is not allowed to perform the given operation, and this attempt should |
| * cause it to have a fatal error, typically a {@link SecurityException}. |
| */ |
| public static final int MODE_ERRORED = 2; |
| |
| /** |
| * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller should |
| * use its default security check. This mode is not normally used; it should only be used |
| * with appop permissions, and callers must explicitly check for it and deal with it. |
| */ |
| public static final int MODE_DEFAULT = 3; |
| |
| /** |
| * Special mode that means "allow only when app is in foreground." This is <b>not</b> |
| * returned from {@link #checkOp}, {@link #noteOp}, {@link #startOp}; rather, when this |
| * mode is set, these functions will return {@link #MODE_ALLOWED} when the app being |
| * checked is currently in the foreground, otherwise {@link #MODE_IGNORED}. |
| */ |
| public static final int MODE_FOREGROUND = 4; |
| |
| /** |
| * Flag for {@link #startWatchingMode(String, String, int, OnOpChangedListener)}: |
| * Also get reports if the foreground state of an op's uid changes. This only works |
| * when watching a particular op, not when watching a package. |
| */ |
| public static final int WATCH_FOREGROUND_CHANGES = 1 << 0; |
| |
| /** |
| * @hide |
| */ |
| public static final String[] MODE_NAMES = new String[] { |
| "allow", // MODE_ALLOWED |
| "ignore", // MODE_IGNORED |
| "deny", // MODE_ERRORED |
| "default", // MODE_DEFAULT |
| "foreground", // MODE_FOREGROUND |
| }; |
| |
| /** |
| * Metrics about an op when its uid is persistent. |
| * @hide |
| */ |
| public static final int UID_STATE_PERSISTENT = 0; |
| |
| /** |
| * Metrics about an op when its uid is at the top. |
| * @hide |
| */ |
| public static final int UID_STATE_TOP = 1; |
| |
| /** |
| * Metrics about an op when its uid is running a foreground service. |
| * @hide |
| */ |
| public static final int UID_STATE_FOREGROUND_SERVICE = 2; |
| |
| /** |
| * Last UID state in which we don't restrict what an op can do. |
| * @hide |
| */ |
| public static final int UID_STATE_LAST_NON_RESTRICTED = UID_STATE_FOREGROUND_SERVICE; |
| |
| /** |
| * Metrics about an op when its uid is in the foreground for any other reasons. |
| * @hide |
| */ |
| public static final int UID_STATE_FOREGROUND = 3; |
| |
| /** |
| * Metrics about an op when its uid is in the background for any reason. |
| * @hide |
| */ |
| public static final int UID_STATE_BACKGROUND = 4; |
| |
| /** |
| * Metrics about an op when its uid is cached. |
| * @hide |
| */ |
| public static final int UID_STATE_CACHED = 5; |
| |
| /** |
| * Number of uid states we track. |
| * @hide |
| */ |
| public static final int _NUM_UID_STATE = 6; |
| |
| // when adding one of these: |
| // - increment _NUM_OP |
| // - define an OPSTR_* constant (marked as @SystemApi) |
| // - add rows to sOpToSwitch, sOpToString, sOpNames, sOpToPerms, sOpDefault |
| // - add descriptive strings to Settings/res/values/arrays.xml |
| // - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app) |
| |
| /** @hide No operation specified. */ |
| public static final int OP_NONE = -1; |
| /** @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; |
| /** @hide Causing GPS to run. */ |
| public static final int OP_GPS = 2; |
| /** @hide */ |
| public static final int OP_VIBRATE = 3; |
| /** @hide */ |
| public static final int OP_READ_CONTACTS = 4; |
| /** @hide */ |
| public static final int OP_WRITE_CONTACTS = 5; |
| /** @hide */ |
| public static final int OP_READ_CALL_LOG = 6; |
| /** @hide */ |
| public static final int OP_WRITE_CALL_LOG = 7; |
| /** @hide */ |
| public static final int OP_READ_CALENDAR = 8; |
| /** @hide */ |
| public static final int OP_WRITE_CALENDAR = 9; |
| /** @hide */ |
| public static final int OP_WIFI_SCAN = 10; |
| /** @hide */ |
| public static final int OP_POST_NOTIFICATION = 11; |
| /** @hide */ |
| public static final int OP_NEIGHBORING_CELLS = 12; |
| /** @hide */ |
| public static final int OP_CALL_PHONE = 13; |
| /** @hide */ |
| public static final int OP_READ_SMS = 14; |
| /** @hide */ |
| public static final int OP_WRITE_SMS = 15; |
| /** @hide */ |
| public static final int OP_RECEIVE_SMS = 16; |
| /** @hide */ |
| public static final int OP_RECEIVE_EMERGECY_SMS = 17; |
| /** @hide */ |
| public static final int OP_RECEIVE_MMS = 18; |
| /** @hide */ |
| public static final int OP_RECEIVE_WAP_PUSH = 19; |
| /** @hide */ |
| public static final int OP_SEND_SMS = 20; |
| /** @hide */ |
| public static final int OP_READ_ICC_SMS = 21; |
| /** @hide */ |
| public static final int OP_WRITE_ICC_SMS = 22; |
| /** @hide */ |
| public static final int OP_WRITE_SETTINGS = 23; |
| /** @hide Required to draw on top of other apps. */ |
| @TestApi |
| public static final int OP_SYSTEM_ALERT_WINDOW = 24; |
| /** @hide */ |
| public static final int OP_ACCESS_NOTIFICATIONS = 25; |
| /** @hide */ |
| public static final int OP_CAMERA = 26; |
| /** @hide */ |
| @TestApi |
| public static final int OP_RECORD_AUDIO = 27; |
| /** @hide */ |
| public static final int OP_PLAY_AUDIO = 28; |
| /** @hide */ |
| public static final int OP_READ_CLIPBOARD = 29; |
| /** @hide */ |
| public static final int OP_WRITE_CLIPBOARD = 30; |
| /** @hide */ |
| public static final int OP_TAKE_MEDIA_BUTTONS = 31; |
| /** @hide */ |
| public static final int OP_TAKE_AUDIO_FOCUS = 32; |
| /** @hide */ |
| public static final int OP_AUDIO_MASTER_VOLUME = 33; |
| /** @hide */ |
| public static final int OP_AUDIO_VOICE_VOLUME = 34; |
| /** @hide */ |
| public static final int OP_AUDIO_RING_VOLUME = 35; |
| /** @hide */ |
| public static final int OP_AUDIO_MEDIA_VOLUME = 36; |
| /** @hide */ |
| public static final int OP_AUDIO_ALARM_VOLUME = 37; |
| /** @hide */ |
| public static final int OP_AUDIO_NOTIFICATION_VOLUME = 38; |
| /** @hide */ |
| public static final int OP_AUDIO_BLUETOOTH_VOLUME = 39; |
| /** @hide */ |
| public static final int OP_WAKE_LOCK = 40; |
| /** @hide Continually monitoring location data. */ |
| public static final int OP_MONITOR_LOCATION = 41; |
| /** @hide Continually monitoring location data with a relatively high power request. */ |
| public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42; |
| /** @hide Retrieve current usage stats via {@link UsageStatsManager}. */ |
| public static final int OP_GET_USAGE_STATS = 43; |
| /** @hide */ |
| public static final int OP_MUTE_MICROPHONE = 44; |
| /** @hide */ |
| public static final int OP_TOAST_WINDOW = 45; |
| /** @hide Capture the device's display contents and/or audio */ |
| public static final int OP_PROJECT_MEDIA = 46; |
| /** @hide Activate a VPN connection without user intervention. */ |
| public static final int OP_ACTIVATE_VPN = 47; |
| /** @hide Access the WallpaperManagerAPI to write wallpapers. */ |
| public static final int OP_WRITE_WALLPAPER = 48; |
| /** @hide Received the assist structure from an app. */ |
| public static final int OP_ASSIST_STRUCTURE = 49; |
| /** @hide Received a screenshot from assist. */ |
| public static final int OP_ASSIST_SCREENSHOT = 50; |
| /** @hide Read the phone state. */ |
| public static final int OP_READ_PHONE_STATE = 51; |
| /** @hide Add voicemail messages to the voicemail content provider. */ |
| public static final int OP_ADD_VOICEMAIL = 52; |
| /** @hide Access APIs for SIP calling over VOIP or WiFi. */ |
| public static final int OP_USE_SIP = 53; |
| /** @hide Intercept outgoing calls. */ |
| public static final int OP_PROCESS_OUTGOING_CALLS = 54; |
| /** @hide User the fingerprint API. */ |
| public static final int OP_USE_FINGERPRINT = 55; |
| /** @hide Access to body sensors such as heart rate, etc. */ |
| public static final int OP_BODY_SENSORS = 56; |
| /** @hide Read previously received cell broadcast messages. */ |
| public static final int OP_READ_CELL_BROADCASTS = 57; |
| /** @hide Inject mock location into the system. */ |
| public static final int OP_MOCK_LOCATION = 58; |
| /** @hide Read external storage. */ |
| public static final int OP_READ_EXTERNAL_STORAGE = 59; |
| /** @hide Write external storage. */ |
| public static final int OP_WRITE_EXTERNAL_STORAGE = 60; |
| /** @hide Turned on the screen. */ |
| public static final int OP_TURN_SCREEN_ON = 61; |
| /** @hide Get device accounts. */ |
| public static final int OP_GET_ACCOUNTS = 62; |
| /** @hide Control whether an application is allowed to run in the background. */ |
| public static final int OP_RUN_IN_BACKGROUND = 63; |
| /** @hide */ |
| public static final int OP_AUDIO_ACCESSIBILITY_VOLUME = 64; |
| /** @hide Read the phone number. */ |
| public static final int OP_READ_PHONE_NUMBERS = 65; |
| /** @hide Request package installs through package installer */ |
| public static final int OP_REQUEST_INSTALL_PACKAGES = 66; |
| /** @hide Enter picture-in-picture. */ |
| public static final int OP_PICTURE_IN_PICTURE = 67; |
| /** @hide Instant app start foreground service. */ |
| public static final int OP_INSTANT_APP_START_FOREGROUND = 68; |
| /** @hide Answer incoming phone calls */ |
| public static final int OP_ANSWER_PHONE_CALLS = 69; |
| /** @hide Run jobs when in background */ |
| public static final int OP_RUN_ANY_IN_BACKGROUND = 70; |
| /** @hide Change Wi-Fi connectivity state */ |
| public static final int OP_CHANGE_WIFI_STATE = 71; |
| /** @hide Request package deletion through package installer */ |
| public static final int OP_REQUEST_DELETE_PACKAGES = 72; |
| /** @hide Bind an accessibility service. */ |
| public static final int OP_BIND_ACCESSIBILITY_SERVICE = 73; |
| /** @hide Continue handover of a call from another app */ |
| public static final int OP_ACCEPT_HANDOVER = 74; |
| /** @hide Create and Manage IPsec Tunnels */ |
| public static final int OP_MANAGE_IPSEC_TUNNELS = 75; |
| /** @hide Any app start foreground service. */ |
| public static final int OP_START_FOREGROUND = 76; |
| /** @hide */ |
| public static final int OP_BLUETOOTH_SCAN = 77; |
| /** @hide Use the face authentication API. */ |
| public static final int OP_USE_FACE = 78; |
| /** @hide */ |
| public static final int _NUM_OP = 79; |
| |
| /** Access to coarse location information. */ |
| public static final String OPSTR_COARSE_LOCATION = "android:coarse_location"; |
| /** Access to fine location information. */ |
| public static final String OPSTR_FINE_LOCATION = |
| "android:fine_location"; |
| /** Continually monitoring location data. */ |
| public static final String OPSTR_MONITOR_LOCATION |
| = "android:monitor_location"; |
| /** Continually monitoring location data with a relatively high power request. */ |
| public static final String OPSTR_MONITOR_HIGH_POWER_LOCATION |
| = "android:monitor_location_high_power"; |
| /** Access to {@link android.app.usage.UsageStatsManager}. */ |
| public static final String OPSTR_GET_USAGE_STATS |
| = "android:get_usage_stats"; |
| /** Activate a VPN connection without user intervention. @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_ACTIVATE_VPN |
| = "android:activate_vpn"; |
| /** Allows an application to read the user's contacts data. */ |
| public static final String OPSTR_READ_CONTACTS |
| = "android:read_contacts"; |
| /** Allows an application to write to the user's contacts data. */ |
| public static final String OPSTR_WRITE_CONTACTS |
| = "android:write_contacts"; |
| /** Allows an application to read the user's call log. */ |
| public static final String OPSTR_READ_CALL_LOG |
| = "android:read_call_log"; |
| /** Allows an application to write to the user's call log. */ |
| public static final String OPSTR_WRITE_CALL_LOG |
| = "android:write_call_log"; |
| /** Allows an application to read the user's calendar data. */ |
| public static final String OPSTR_READ_CALENDAR |
| = "android:read_calendar"; |
| /** Allows an application to write to the user's calendar data. */ |
| public static final String OPSTR_WRITE_CALENDAR |
| = "android:write_calendar"; |
| /** Allows an application to initiate a phone call. */ |
| public static final String OPSTR_CALL_PHONE |
| = "android:call_phone"; |
| /** Allows an application to read SMS messages. */ |
| public static final String OPSTR_READ_SMS |
| = "android:read_sms"; |
| /** Allows an application to receive SMS messages. */ |
| public static final String OPSTR_RECEIVE_SMS |
| = "android:receive_sms"; |
| /** Allows an application to receive MMS messages. */ |
| public static final String OPSTR_RECEIVE_MMS |
| = "android:receive_mms"; |
| /** Allows an application to receive WAP push messages. */ |
| public static final String OPSTR_RECEIVE_WAP_PUSH |
| = "android:receive_wap_push"; |
| /** Allows an application to send SMS messages. */ |
| public static final String OPSTR_SEND_SMS |
| = "android:send_sms"; |
| /** Required to be able to access the camera device. */ |
| public static final String OPSTR_CAMERA |
| = "android:camera"; |
| /** Required to be able to access the microphone device. */ |
| public static final String OPSTR_RECORD_AUDIO |
| = "android:record_audio"; |
| /** Required to access phone state related information. */ |
| public static final String OPSTR_READ_PHONE_STATE |
| = "android:read_phone_state"; |
| /** Required to access phone state related information. */ |
| public static final String OPSTR_ADD_VOICEMAIL |
| = "android:add_voicemail"; |
| /** Access APIs for SIP calling over VOIP or WiFi */ |
| public static final String OPSTR_USE_SIP |
| = "android:use_sip"; |
| /** Access APIs for diverting outgoing calls */ |
| public static final String OPSTR_PROCESS_OUTGOING_CALLS |
| = "android:process_outgoing_calls"; |
| /** Use the fingerprint API. */ |
| public static final String OPSTR_USE_FINGERPRINT |
| = "android:use_fingerprint"; |
| /** Access to body sensors such as heart rate, etc. */ |
| public static final String OPSTR_BODY_SENSORS |
| = "android:body_sensors"; |
| /** Read previously received cell broadcast messages. */ |
| public static final String OPSTR_READ_CELL_BROADCASTS |
| = "android:read_cell_broadcasts"; |
| /** Inject mock location into the system. */ |
| public static final String OPSTR_MOCK_LOCATION |
| = "android:mock_location"; |
| /** Read external storage. */ |
| public static final String OPSTR_READ_EXTERNAL_STORAGE |
| = "android:read_external_storage"; |
| /** Write external storage. */ |
| public static final String OPSTR_WRITE_EXTERNAL_STORAGE |
| = "android:write_external_storage"; |
| /** Required to draw on top of other apps. */ |
| public static final String OPSTR_SYSTEM_ALERT_WINDOW |
| = "android:system_alert_window"; |
| /** Required to write/modify/update system settingss. */ |
| public static final String OPSTR_WRITE_SETTINGS |
| = "android:write_settings"; |
| /** @hide Get device accounts. */ |
| @SystemApi @TestApi |
| public static final String OPSTR_GET_ACCOUNTS |
| = "android:get_accounts"; |
| public static final String OPSTR_READ_PHONE_NUMBERS |
| = "android:read_phone_numbers"; |
| /** Access to picture-in-picture. */ |
| public static final String OPSTR_PICTURE_IN_PICTURE |
| = "android:picture_in_picture"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_INSTANT_APP_START_FOREGROUND |
| = "android:instant_app_start_foreground"; |
| /** Answer incoming phone calls */ |
| public static final String OPSTR_ANSWER_PHONE_CALLS |
| = "android:answer_phone_calls"; |
| /** |
| * Accept call handover |
| * @hide |
| */ |
| @SystemApi @TestApi |
| public static final String OPSTR_ACCEPT_HANDOVER |
| = "android:accept_handover"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_GPS = "android:gps"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_VIBRATE = "android:vibrate"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_WIFI_SCAN = "android:wifi_scan"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_POST_NOTIFICATION = "android:post_notification"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_NEIGHBORING_CELLS = "android:neighboring_cells"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_WRITE_SMS = "android:write_sms"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_RECEIVE_EMERGENCY_BROADCAST = |
| "android:receive_emergency_broadcast"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_READ_ICC_SMS = "android:read_icc_sms"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_WRITE_ICC_SMS = "android:write_icc_sms"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_ACCESS_NOTIFICATIONS = "android:access_notifications"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_PLAY_AUDIO = "android:play_audio"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_READ_CLIPBOARD = "android:read_clipboard"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_WRITE_CLIPBOARD = "android:write_clipboard"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_TAKE_MEDIA_BUTTONS = "android:take_media_buttons"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_TAKE_AUDIO_FOCUS = "android:take_audio_focus"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_AUDIO_MASTER_VOLUME = "android:audio_master_volume"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_AUDIO_VOICE_VOLUME = "android:audio_voice_volume"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_AUDIO_RING_VOLUME = "android:audio_ring_volume"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_AUDIO_MEDIA_VOLUME = "android:audio_media_volume"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_AUDIO_ALARM_VOLUME = "android:audio_alarm_volume"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_AUDIO_NOTIFICATION_VOLUME = |
| "android:audio_notification_volume"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_AUDIO_BLUETOOTH_VOLUME = "android:audio_bluetooth_volume"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_WAKE_LOCK = "android:wake_lock"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_MUTE_MICROPHONE = "android:mute_microphone"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_TOAST_WINDOW = "android:toast_window"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_PROJECT_MEDIA = "android:project_media"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_WRITE_WALLPAPER = "android:write_wallpaper"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_ASSIST_STRUCTURE = "android:assist_structure"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_ASSIST_SCREENSHOT = "android:assist_screenshot"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_TURN_SCREEN_ON = "android:turn_screen_on"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_RUN_IN_BACKGROUND = "android:run_in_background"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_AUDIO_ACCESSIBILITY_VOLUME = |
| "android:audio_accessibility_volume"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_REQUEST_INSTALL_PACKAGES = "android:request_install_packages"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_RUN_ANY_IN_BACKGROUND = "android:run_any_in_background"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_CHANGE_WIFI_STATE = "android:change_wifi_state"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_REQUEST_DELETE_PACKAGES = "android:request_delete_packages"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_BIND_ACCESSIBILITY_SERVICE = |
| "android:bind_accessibility_service"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_MANAGE_IPSEC_TUNNELS = "android:manage_ipsec_tunnels"; |
| /** @hide */ |
| @SystemApi @TestApi |
| public static final String OPSTR_START_FOREGROUND = "android:start_foreground"; |
| /** @hide */ |
| public static final String OPSTR_BLUETOOTH_SCAN = "android:bluetooth_scan"; |
| |
| /** @hide Use the face authentication API. */ |
| public static final String OPSTR_USE_FACE = "android:use_face"; |
| |
| // Warning: If an permission is added here it also has to be added to |
| // com.android.packageinstaller.permission.utils.EventLogger |
| private static final int[] RUNTIME_AND_APPOP_PERMISSIONS_OPS = { |
| // RUNTIME PERMISSIONS |
| // Contacts |
| OP_READ_CONTACTS, |
| OP_WRITE_CONTACTS, |
| OP_GET_ACCOUNTS, |
| // Calendar |
| OP_READ_CALENDAR, |
| OP_WRITE_CALENDAR, |
| // SMS |
| OP_SEND_SMS, |
| OP_RECEIVE_SMS, |
| OP_READ_SMS, |
| OP_RECEIVE_WAP_PUSH, |
| OP_RECEIVE_MMS, |
| OP_READ_CELL_BROADCASTS, |
| // Storage |
| OP_READ_EXTERNAL_STORAGE, |
| OP_WRITE_EXTERNAL_STORAGE, |
| // Location |
| OP_COARSE_LOCATION, |
| OP_FINE_LOCATION, |
| // Phone |
| OP_READ_PHONE_STATE, |
| OP_READ_PHONE_NUMBERS, |
| OP_CALL_PHONE, |
| OP_READ_CALL_LOG, |
| OP_WRITE_CALL_LOG, |
| OP_ADD_VOICEMAIL, |
| OP_USE_SIP, |
| OP_PROCESS_OUTGOING_CALLS, |
| OP_ANSWER_PHONE_CALLS, |
| OP_ACCEPT_HANDOVER, |
| // Microphone |
| OP_RECORD_AUDIO, |
| // Camera |
| OP_CAMERA, |
| // Body sensors |
| OP_BODY_SENSORS, |
| |
| // APPOP PERMISSIONS |
| OP_ACCESS_NOTIFICATIONS, |
| OP_SYSTEM_ALERT_WINDOW, |
| OP_WRITE_SETTINGS, |
| OP_REQUEST_INSTALL_PACKAGES, |
| OP_START_FOREGROUND, |
| }; |
| |
| /** |
| * This maps each operation to the operation that serves as the |
| * switch to determine whether it is allowed. Generally this is |
| * a 1:1 mapping, but for some things (like location) that have |
| * multiple low-level operations being tracked that should be |
| * presented to the user as one switch then this can be used to |
| * make them all controlled by the same single operation. |
| */ |
| private static int[] sOpToSwitch = new int[] { |
| OP_COARSE_LOCATION, // COARSE_LOCATION |
| OP_COARSE_LOCATION, // FINE_LOCATION |
| OP_COARSE_LOCATION, // GPS |
| OP_VIBRATE, // VIBRATE |
| OP_READ_CONTACTS, // READ_CONTACTS |
| OP_WRITE_CONTACTS, // WRITE_CONTACTS |
| OP_READ_CALL_LOG, // READ_CALL_LOG |
| OP_WRITE_CALL_LOG, // WRITE_CALL_LOG |
| OP_READ_CALENDAR, // READ_CALENDAR |
| OP_WRITE_CALENDAR, // WRITE_CALENDAR |
| OP_COARSE_LOCATION, // WIFI_SCAN |
| OP_POST_NOTIFICATION, // POST_NOTIFICATION |
| OP_COARSE_LOCATION, // NEIGHBORING_CELLS |
| OP_CALL_PHONE, // CALL_PHONE |
| OP_READ_SMS, // READ_SMS |
| OP_WRITE_SMS, // WRITE_SMS |
| OP_RECEIVE_SMS, // RECEIVE_SMS |
| OP_RECEIVE_SMS, // RECEIVE_EMERGECY_SMS |
| OP_RECEIVE_MMS, // RECEIVE_MMS |
| OP_RECEIVE_WAP_PUSH, // RECEIVE_WAP_PUSH |
| OP_SEND_SMS, // SEND_SMS |
| OP_READ_SMS, // READ_ICC_SMS |
| OP_WRITE_SMS, // WRITE_ICC_SMS |
| OP_WRITE_SETTINGS, // WRITE_SETTINGS |
| OP_SYSTEM_ALERT_WINDOW, // SYSTEM_ALERT_WINDOW |
| OP_ACCESS_NOTIFICATIONS, // ACCESS_NOTIFICATIONS |
| OP_CAMERA, // CAMERA |
| OP_RECORD_AUDIO, // RECORD_AUDIO |
| OP_PLAY_AUDIO, // PLAY_AUDIO |
| OP_READ_CLIPBOARD, // READ_CLIPBOARD |
| OP_WRITE_CLIPBOARD, // WRITE_CLIPBOARD |
| OP_TAKE_MEDIA_BUTTONS, // TAKE_MEDIA_BUTTONS |
| OP_TAKE_AUDIO_FOCUS, // TAKE_AUDIO_FOCUS |
| OP_AUDIO_MASTER_VOLUME, // AUDIO_MASTER_VOLUME |
| OP_AUDIO_VOICE_VOLUME, // AUDIO_VOICE_VOLUME |
| OP_AUDIO_RING_VOLUME, // AUDIO_RING_VOLUME |
| OP_AUDIO_MEDIA_VOLUME, // AUDIO_MEDIA_VOLUME |
| OP_AUDIO_ALARM_VOLUME, // AUDIO_ALARM_VOLUME |
| OP_AUDIO_NOTIFICATION_VOLUME, // AUDIO_NOTIFICATION_VOLUME |
| OP_AUDIO_BLUETOOTH_VOLUME, // AUDIO_BLUETOOTH_VOLUME |
| OP_WAKE_LOCK, // WAKE_LOCK |
| OP_COARSE_LOCATION, // MONITOR_LOCATION |
| OP_COARSE_LOCATION, // MONITOR_HIGH_POWER_LOCATION |
| OP_GET_USAGE_STATS, // GET_USAGE_STATS |
| OP_MUTE_MICROPHONE, // MUTE_MICROPHONE |
| OP_TOAST_WINDOW, // TOAST_WINDOW |
| OP_PROJECT_MEDIA, // PROJECT_MEDIA |
| OP_ACTIVATE_VPN, // ACTIVATE_VPN |
| OP_WRITE_WALLPAPER, // WRITE_WALLPAPER |
| OP_ASSIST_STRUCTURE, // ASSIST_STRUCTURE |
| OP_ASSIST_SCREENSHOT, // ASSIST_SCREENSHOT |
| OP_READ_PHONE_STATE, // READ_PHONE_STATE |
| OP_ADD_VOICEMAIL, // ADD_VOICEMAIL |
| OP_USE_SIP, // USE_SIP |
| OP_PROCESS_OUTGOING_CALLS, // PROCESS_OUTGOING_CALLS |
| OP_USE_FINGERPRINT, // USE_FINGERPRINT |
| OP_BODY_SENSORS, // BODY_SENSORS |
| OP_READ_CELL_BROADCASTS, // READ_CELL_BROADCASTS |
| OP_MOCK_LOCATION, // MOCK_LOCATION |
| OP_READ_EXTERNAL_STORAGE, // READ_EXTERNAL_STORAGE |
| OP_WRITE_EXTERNAL_STORAGE, // WRITE_EXTERNAL_STORAGE |
| OP_TURN_SCREEN_ON, // TURN_SCREEN_ON |
| OP_GET_ACCOUNTS, // GET_ACCOUNTS |
| OP_RUN_IN_BACKGROUND, // RUN_IN_BACKGROUND |
| OP_AUDIO_ACCESSIBILITY_VOLUME, // AUDIO_ACCESSIBILITY_VOLUME |
| OP_READ_PHONE_NUMBERS, // READ_PHONE_NUMBERS |
| OP_REQUEST_INSTALL_PACKAGES, // REQUEST_INSTALL_PACKAGES |
| OP_PICTURE_IN_PICTURE, // ENTER_PICTURE_IN_PICTURE_ON_HIDE |
| OP_INSTANT_APP_START_FOREGROUND, // INSTANT_APP_START_FOREGROUND |
| OP_ANSWER_PHONE_CALLS, // ANSWER_PHONE_CALLS |
| OP_RUN_ANY_IN_BACKGROUND, // OP_RUN_ANY_IN_BACKGROUND |
| OP_CHANGE_WIFI_STATE, // OP_CHANGE_WIFI_STATE |
| OP_REQUEST_DELETE_PACKAGES, // OP_REQUEST_DELETE_PACKAGES |
| OP_BIND_ACCESSIBILITY_SERVICE, // OP_BIND_ACCESSIBILITY_SERVICE |
| OP_ACCEPT_HANDOVER, // ACCEPT_HANDOVER |
| OP_MANAGE_IPSEC_TUNNELS, // MANAGE_IPSEC_HANDOVERS |
| OP_START_FOREGROUND, // START_FOREGROUND |
| OP_COARSE_LOCATION, // BLUETOOTH_SCAN |
| OP_USE_FACE, // FACE |
| }; |
| |
| /** |
| * This maps each operation to the public string constant for it. |
| */ |
| private static String[] sOpToString = new String[]{ |
| OPSTR_COARSE_LOCATION, |
| OPSTR_FINE_LOCATION, |
| OPSTR_GPS, |
| OPSTR_VIBRATE, |
| OPSTR_READ_CONTACTS, |
| OPSTR_WRITE_CONTACTS, |
| OPSTR_READ_CALL_LOG, |
| OPSTR_WRITE_CALL_LOG, |
| OPSTR_READ_CALENDAR, |
| OPSTR_WRITE_CALENDAR, |
| OPSTR_WIFI_SCAN, |
| OPSTR_POST_NOTIFICATION, |
| OPSTR_NEIGHBORING_CELLS, |
| OPSTR_CALL_PHONE, |
| OPSTR_READ_SMS, |
| OPSTR_WRITE_SMS, |
| OPSTR_RECEIVE_SMS, |
| OPSTR_RECEIVE_EMERGENCY_BROADCAST, |
| OPSTR_RECEIVE_MMS, |
| OPSTR_RECEIVE_WAP_PUSH, |
| OPSTR_SEND_SMS, |
| OPSTR_READ_ICC_SMS, |
| OPSTR_WRITE_ICC_SMS, |
| OPSTR_WRITE_SETTINGS, |
| OPSTR_SYSTEM_ALERT_WINDOW, |
| OPSTR_ACCESS_NOTIFICATIONS, |
| OPSTR_CAMERA, |
| OPSTR_RECORD_AUDIO, |
| OPSTR_PLAY_AUDIO, |
| OPSTR_READ_CLIPBOARD, |
| OPSTR_WRITE_CLIPBOARD, |
| OPSTR_TAKE_MEDIA_BUTTONS, |
| OPSTR_TAKE_AUDIO_FOCUS, |
| OPSTR_AUDIO_MASTER_VOLUME, |
| OPSTR_AUDIO_VOICE_VOLUME, |
| OPSTR_AUDIO_RING_VOLUME, |
| OPSTR_AUDIO_MEDIA_VOLUME, |
| OPSTR_AUDIO_ALARM_VOLUME, |
| OPSTR_AUDIO_NOTIFICATION_VOLUME, |
| OPSTR_AUDIO_BLUETOOTH_VOLUME, |
| OPSTR_WAKE_LOCK, |
| OPSTR_MONITOR_LOCATION, |
| OPSTR_MONITOR_HIGH_POWER_LOCATION, |
| OPSTR_GET_USAGE_STATS, |
| OPSTR_MUTE_MICROPHONE, |
| OPSTR_TOAST_WINDOW, |
| OPSTR_PROJECT_MEDIA, |
| OPSTR_ACTIVATE_VPN, |
| OPSTR_WRITE_WALLPAPER, |
| OPSTR_ASSIST_STRUCTURE, |
| OPSTR_ASSIST_SCREENSHOT, |
| OPSTR_READ_PHONE_STATE, |
| OPSTR_ADD_VOICEMAIL, |
| OPSTR_USE_SIP, |
| OPSTR_PROCESS_OUTGOING_CALLS, |
| OPSTR_USE_FINGERPRINT, |
| OPSTR_BODY_SENSORS, |
| OPSTR_READ_CELL_BROADCASTS, |
| OPSTR_MOCK_LOCATION, |
| OPSTR_READ_EXTERNAL_STORAGE, |
| OPSTR_WRITE_EXTERNAL_STORAGE, |
| OPSTR_TURN_SCREEN_ON, |
| OPSTR_GET_ACCOUNTS, |
| OPSTR_RUN_IN_BACKGROUND, |
| OPSTR_AUDIO_ACCESSIBILITY_VOLUME, |
| OPSTR_READ_PHONE_NUMBERS, |
| OPSTR_REQUEST_INSTALL_PACKAGES, |
| OPSTR_PICTURE_IN_PICTURE, |
| OPSTR_INSTANT_APP_START_FOREGROUND, |
| OPSTR_ANSWER_PHONE_CALLS, |
| OPSTR_RUN_ANY_IN_BACKGROUND, |
| OPSTR_CHANGE_WIFI_STATE, |
| OPSTR_REQUEST_DELETE_PACKAGES, |
| OPSTR_BIND_ACCESSIBILITY_SERVICE, |
| OPSTR_ACCEPT_HANDOVER, |
| OPSTR_MANAGE_IPSEC_TUNNELS, |
| OPSTR_START_FOREGROUND, |
| OPSTR_BLUETOOTH_SCAN, |
| OPSTR_USE_FACE, |
| }; |
| |
| /** |
| * This provides a simple name for each operation to be used |
| * in debug output. |
| */ |
| private static String[] sOpNames = new String[] { |
| "COARSE_LOCATION", |
| "FINE_LOCATION", |
| "GPS", |
| "VIBRATE", |
| "READ_CONTACTS", |
| "WRITE_CONTACTS", |
| "READ_CALL_LOG", |
| "WRITE_CALL_LOG", |
| "READ_CALENDAR", |
| "WRITE_CALENDAR", |
| "WIFI_SCAN", |
| "POST_NOTIFICATION", |
| "NEIGHBORING_CELLS", |
| "CALL_PHONE", |
| "READ_SMS", |
| "WRITE_SMS", |
| "RECEIVE_SMS", |
| "RECEIVE_EMERGECY_SMS", |
| "RECEIVE_MMS", |
| "RECEIVE_WAP_PUSH", |
| "SEND_SMS", |
| "READ_ICC_SMS", |
| "WRITE_ICC_SMS", |
| "WRITE_SETTINGS", |
| "SYSTEM_ALERT_WINDOW", |
| "ACCESS_NOTIFICATIONS", |
| "CAMERA", |
| "RECORD_AUDIO", |
| "PLAY_AUDIO", |
| "READ_CLIPBOARD", |
| "WRITE_CLIPBOARD", |
| "TAKE_MEDIA_BUTTONS", |
| "TAKE_AUDIO_FOCUS", |
| "AUDIO_MASTER_VOLUME", |
| "AUDIO_VOICE_VOLUME", |
| "AUDIO_RING_VOLUME", |
| "AUDIO_MEDIA_VOLUME", |
| "AUDIO_ALARM_VOLUME", |
| "AUDIO_NOTIFICATION_VOLUME", |
| "AUDIO_BLUETOOTH_VOLUME", |
| "WAKE_LOCK", |
| "MONITOR_LOCATION", |
| "MONITOR_HIGH_POWER_LOCATION", |
| "GET_USAGE_STATS", |
| "MUTE_MICROPHONE", |
| "TOAST_WINDOW", |
| "PROJECT_MEDIA", |
| "ACTIVATE_VPN", |
| "WRITE_WALLPAPER", |
| "ASSIST_STRUCTURE", |
| "ASSIST_SCREENSHOT", |
| "OP_READ_PHONE_STATE", |
| "ADD_VOICEMAIL", |
| "USE_SIP", |
| "PROCESS_OUTGOING_CALLS", |
| "USE_FINGERPRINT", |
| "BODY_SENSORS", |
| "READ_CELL_BROADCASTS", |
| "MOCK_LOCATION", |
| "READ_EXTERNAL_STORAGE", |
| "WRITE_EXTERNAL_STORAGE", |
| "TURN_ON_SCREEN", |
| "GET_ACCOUNTS", |
| "RUN_IN_BACKGROUND", |
| "AUDIO_ACCESSIBILITY_VOLUME", |
| "READ_PHONE_NUMBERS", |
| "REQUEST_INSTALL_PACKAGES", |
| "PICTURE_IN_PICTURE", |
| "INSTANT_APP_START_FOREGROUND", |
| "ANSWER_PHONE_CALLS", |
| "RUN_ANY_IN_BACKGROUND", |
| "CHANGE_WIFI_STATE", |
| "REQUEST_DELETE_PACKAGES", |
| "BIND_ACCESSIBILITY_SERVICE", |
| "ACCEPT_HANDOVER", |
| "MANAGE_IPSEC_TUNNELS", |
| "START_FOREGROUND", |
| "BLUETOOTH_SCAN", |
| "USE_FACE", |
| }; |
| |
| /** |
| * This optionally maps a permission to an operation. If there |
| * is no permission associated with an operation, it is null. |
| */ |
| private static String[] sOpPerms = new String[] { |
| android.Manifest.permission.ACCESS_COARSE_LOCATION, |
| android.Manifest.permission.ACCESS_FINE_LOCATION, |
| null, |
| android.Manifest.permission.VIBRATE, |
| android.Manifest.permission.READ_CONTACTS, |
| android.Manifest.permission.WRITE_CONTACTS, |
| android.Manifest.permission.READ_CALL_LOG, |
| android.Manifest.permission.WRITE_CALL_LOG, |
| android.Manifest.permission.READ_CALENDAR, |
| android.Manifest.permission.WRITE_CALENDAR, |
| android.Manifest.permission.ACCESS_WIFI_STATE, |
| null, // no permission required for notifications |
| null, // neighboring cells shares the coarse location perm |
| android.Manifest.permission.CALL_PHONE, |
| android.Manifest.permission.READ_SMS, |
| null, // no permission required for writing sms |
| android.Manifest.permission.RECEIVE_SMS, |
| android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST, |
| android.Manifest.permission.RECEIVE_MMS, |
| android.Manifest.permission.RECEIVE_WAP_PUSH, |
| android.Manifest.permission.SEND_SMS, |
| android.Manifest.permission.READ_SMS, |
| null, // no permission required for writing icc sms |
| android.Manifest.permission.WRITE_SETTINGS, |
| android.Manifest.permission.SYSTEM_ALERT_WINDOW, |
| android.Manifest.permission.ACCESS_NOTIFICATIONS, |
| android.Manifest.permission.CAMERA, |
| android.Manifest.permission.RECORD_AUDIO, |
| null, // no permission for playing audio |
| null, // no permission for reading clipboard |
| null, // no permission for writing clipboard |
| null, // no permission for taking media buttons |
| null, // no permission for taking audio focus |
| null, // no permission for changing master volume |
| null, // no permission for changing voice volume |
| null, // no permission for changing ring volume |
| null, // no permission for changing media volume |
| null, // no permission for changing alarm volume |
| null, // no permission for changing notification volume |
| null, // no permission for changing bluetooth volume |
| android.Manifest.permission.WAKE_LOCK, |
| null, // no permission for generic location monitoring |
| null, // no permission for high power location monitoring |
| android.Manifest.permission.PACKAGE_USAGE_STATS, |
| null, // no permission for muting/unmuting microphone |
| null, // no permission for displaying toasts |
| null, // no permission for projecting media |
| null, // no permission for activating vpn |
| null, // no permission for supporting wallpaper |
| null, // no permission for receiving assist structure |
| null, // no permission for receiving assist screenshot |
| Manifest.permission.READ_PHONE_STATE, |
| Manifest.permission.ADD_VOICEMAIL, |
| Manifest.permission.USE_SIP, |
| Manifest.permission.PROCESS_OUTGOING_CALLS, |
| Manifest.permission.USE_FINGERPRINT, |
| Manifest.permission.BODY_SENSORS, |
| Manifest.permission.READ_CELL_BROADCASTS, |
| null, |
| Manifest.permission.READ_EXTERNAL_STORAGE, |
| Manifest.permission.WRITE_EXTERNAL_STORAGE, |
| null, // no permission for turning the screen on |
| Manifest.permission.GET_ACCOUNTS, |
| null, // no permission for running in background |
| null, // no permission for changing accessibility volume |
| Manifest.permission.READ_PHONE_NUMBERS, |
| Manifest.permission.REQUEST_INSTALL_PACKAGES, |
| null, // no permission for entering picture-in-picture on hide |
| Manifest.permission.INSTANT_APP_FOREGROUND_SERVICE, |
| Manifest.permission.ANSWER_PHONE_CALLS, |
| null, // no permission for OP_RUN_ANY_IN_BACKGROUND |
| Manifest.permission.CHANGE_WIFI_STATE, |
| Manifest.permission.REQUEST_DELETE_PACKAGES, |
| Manifest.permission.BIND_ACCESSIBILITY_SERVICE, |
| Manifest.permission.ACCEPT_HANDOVER, |
| null, // no permission for OP_MANAGE_IPSEC_TUNNELS |
| Manifest.permission.FOREGROUND_SERVICE, |
| null, // no permission for OP_BLUETOOTH_SCAN |
| Manifest.permission.USE_BIOMETRIC, |
| }; |
| |
| /** |
| * Specifies whether an Op should be restricted by a user restriction. |
| * Each Op should be filled with a restriction string from UserManager or |
| * null to specify it is not affected by any user restriction. |
| */ |
| private static String[] sOpRestrictions = new String[] { |
| UserManager.DISALLOW_SHARE_LOCATION, //COARSE_LOCATION |
| UserManager.DISALLOW_SHARE_LOCATION, //FINE_LOCATION |
| UserManager.DISALLOW_SHARE_LOCATION, //GPS |
| null, //VIBRATE |
| null, //READ_CONTACTS |
| null, //WRITE_CONTACTS |
| UserManager.DISALLOW_OUTGOING_CALLS, //READ_CALL_LOG |
| UserManager.DISALLOW_OUTGOING_CALLS, //WRITE_CALL_LOG |
| null, //READ_CALENDAR |
| null, //WRITE_CALENDAR |
| UserManager.DISALLOW_SHARE_LOCATION, //WIFI_SCAN |
| null, //POST_NOTIFICATION |
| null, //NEIGHBORING_CELLS |
| null, //CALL_PHONE |
| UserManager.DISALLOW_SMS, //READ_SMS |
| UserManager.DISALLOW_SMS, //WRITE_SMS |
| UserManager.DISALLOW_SMS, //RECEIVE_SMS |
| null, //RECEIVE_EMERGENCY_SMS |
| UserManager.DISALLOW_SMS, //RECEIVE_MMS |
| null, //RECEIVE_WAP_PUSH |
| UserManager.DISALLOW_SMS, //SEND_SMS |
| UserManager.DISALLOW_SMS, //READ_ICC_SMS |
| UserManager.DISALLOW_SMS, //WRITE_ICC_SMS |
| null, //WRITE_SETTINGS |
| UserManager.DISALLOW_CREATE_WINDOWS, //SYSTEM_ALERT_WINDOW |
| null, //ACCESS_NOTIFICATIONS |
| UserManager.DISALLOW_CAMERA, //CAMERA |
| UserManager.DISALLOW_RECORD_AUDIO, //RECORD_AUDIO |
| null, //PLAY_AUDIO |
| null, //READ_CLIPBOARD |
| null, //WRITE_CLIPBOARD |
| null, //TAKE_MEDIA_BUTTONS |
| null, //TAKE_AUDIO_FOCUS |
| UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_MASTER_VOLUME |
| UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_VOICE_VOLUME |
| UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_RING_VOLUME |
| UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_MEDIA_VOLUME |
| UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_ALARM_VOLUME |
| UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_NOTIFICATION_VOLUME |
| UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_BLUETOOTH_VOLUME |
| null, //WAKE_LOCK |
| UserManager.DISALLOW_SHARE_LOCATION, //MONITOR_LOCATION |
| UserManager.DISALLOW_SHARE_LOCATION, //MONITOR_HIGH_POWER_LOCATION |
| null, //GET_USAGE_STATS |
| UserManager.DISALLOW_UNMUTE_MICROPHONE, // MUTE_MICROPHONE |
| UserManager.DISALLOW_CREATE_WINDOWS, // TOAST_WINDOW |
| null, //PROJECT_MEDIA |
| null, // ACTIVATE_VPN |
| UserManager.DISALLOW_WALLPAPER, // WRITE_WALLPAPER |
| null, // ASSIST_STRUCTURE |
| null, // ASSIST_SCREENSHOT |
| null, // READ_PHONE_STATE |
| null, // ADD_VOICEMAIL |
| null, // USE_SIP |
| null, // PROCESS_OUTGOING_CALLS |
| null, // USE_FINGERPRINT |
| null, // BODY_SENSORS |
| null, // READ_CELL_BROADCASTS |
| null, // MOCK_LOCATION |
| null, // READ_EXTERNAL_STORAGE |
| null, // WRITE_EXTERNAL_STORAGE |
| null, // TURN_ON_SCREEN |
| null, // GET_ACCOUNTS |
| null, // RUN_IN_BACKGROUND |
| UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_ACCESSIBILITY_VOLUME |
| null, // READ_PHONE_NUMBERS |
| null, // REQUEST_INSTALL_PACKAGES |
| null, // ENTER_PICTURE_IN_PICTURE_ON_HIDE |
| null, // INSTANT_APP_START_FOREGROUND |
| null, // ANSWER_PHONE_CALLS |
| null, // OP_RUN_ANY_IN_BACKGROUND |
| null, // OP_CHANGE_WIFI_STATE |
| null, // REQUEST_DELETE_PACKAGES |
| null, // OP_BIND_ACCESSIBILITY_SERVICE |
| null, // ACCEPT_HANDOVER |
| null, // MANAGE_IPSEC_TUNNELS |
| null, // START_FOREGROUND |
| null, // maybe should be UserManager.DISALLOW_SHARE_LOCATION, //BLUETOOTH_SCAN |
| null, // USE_FACE |
| }; |
| |
| /** |
| * This specifies whether each option should allow the system |
| * (and system ui) to bypass the user restriction when active. |
| */ |
| private static boolean[] sOpAllowSystemRestrictionBypass = new boolean[] { |
| true, //COARSE_LOCATION |
| true, //FINE_LOCATION |
| false, //GPS |
| false, //VIBRATE |
| false, //READ_CONTACTS |
| false, //WRITE_CONTACTS |
| false, //READ_CALL_LOG |
| false, //WRITE_CALL_LOG |
| false, //READ_CALENDAR |
| false, //WRITE_CALENDAR |
| true, //WIFI_SCAN |
| false, //POST_NOTIFICATION |
| false, //NEIGHBORING_CELLS |
| false, //CALL_PHONE |
| false, //READ_SMS |
| false, //WRITE_SMS |
| false, //RECEIVE_SMS |
| false, //RECEIVE_EMERGECY_SMS |
| false, //RECEIVE_MMS |
| false, //RECEIVE_WAP_PUSH |
| false, //SEND_SMS |
| false, //READ_ICC_SMS |
| false, //WRITE_ICC_SMS |
| false, //WRITE_SETTINGS |
| true, //SYSTEM_ALERT_WINDOW |
| false, //ACCESS_NOTIFICATIONS |
| false, //CAMERA |
| false, //RECORD_AUDIO |
| false, //PLAY_AUDIO |
| false, //READ_CLIPBOARD |
| false, //WRITE_CLIPBOARD |
| false, //TAKE_MEDIA_BUTTONS |
| false, //TAKE_AUDIO_FOCUS |
| false, //AUDIO_MASTER_VOLUME |
| false, //AUDIO_VOICE_VOLUME |
| false, //AUDIO_RING_VOLUME |
| false, //AUDIO_MEDIA_VOLUME |
| false, //AUDIO_ALARM_VOLUME |
| false, //AUDIO_NOTIFICATION_VOLUME |
| false, //AUDIO_BLUETOOTH_VOLUME |
| false, //WAKE_LOCK |
| false, //MONITOR_LOCATION |
| false, //MONITOR_HIGH_POWER_LOCATION |
| false, //GET_USAGE_STATS |
| false, //MUTE_MICROPHONE |
| true, //TOAST_WINDOW |
| false, //PROJECT_MEDIA |
| false, //ACTIVATE_VPN |
| false, //WALLPAPER |
| false, //ASSIST_STRUCTURE |
| false, //ASSIST_SCREENSHOT |
| false, //READ_PHONE_STATE |
| false, //ADD_VOICEMAIL |
| false, // USE_SIP |
| false, // PROCESS_OUTGOING_CALLS |
| false, // USE_FINGERPRINT |
| false, // BODY_SENSORS |
| false, // READ_CELL_BROADCASTS |
| false, // MOCK_LOCATION |
| false, // READ_EXTERNAL_STORAGE |
| false, // WRITE_EXTERNAL_STORAGE |
| false, // TURN_ON_SCREEN |
| false, // GET_ACCOUNTS |
| false, // RUN_IN_BACKGROUND |
| false, // AUDIO_ACCESSIBILITY_VOLUME |
| false, // READ_PHONE_NUMBERS |
| false, // REQUEST_INSTALL_PACKAGES |
| false, // ENTER_PICTURE_IN_PICTURE_ON_HIDE |
| false, // INSTANT_APP_START_FOREGROUND |
| false, // ANSWER_PHONE_CALLS |
| false, // OP_RUN_ANY_IN_BACKGROUND |
| false, // OP_CHANGE_WIFI_STATE |
| false, // OP_REQUEST_DELETE_PACKAGES |
| false, // OP_BIND_ACCESSIBILITY_SERVICE |
| false, // ACCEPT_HANDOVER |
| false, // MANAGE_IPSEC_HANDOVERS |
| false, // START_FOREGROUND |
| true, // BLUETOOTH_SCAN |
| false, // USE_FACE |
| }; |
| |
| /** |
| * This specifies the default mode for each operation. |
| */ |
| private static int[] sOpDefaultMode = new int[] { |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_IGNORED, // OP_WRITE_SMS |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_DEFAULT, // OP_WRITE_SETTINGS |
| AppOpsManager.MODE_DEFAULT, // OP_SYSTEM_ALERT_WINDOW |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_DEFAULT, // OP_GET_USAGE_STATS |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_IGNORED, // OP_PROJECT_MEDIA |
| AppOpsManager.MODE_IGNORED, // OP_ACTIVATE_VPN |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ERRORED, // OP_MOCK_LOCATION |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, // OP_TURN_ON_SCREEN |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_ALLOWED, // OP_RUN_IN_BACKGROUND |
| AppOpsManager.MODE_ALLOWED, // OP_AUDIO_ACCESSIBILITY_VOLUME |
| AppOpsManager.MODE_ALLOWED, |
| AppOpsManager.MODE_DEFAULT, // OP_REQUEST_INSTALL_PACKAGES |
| AppOpsManager.MODE_ALLOWED, // OP_PICTURE_IN_PICTURE |
| AppOpsManager.MODE_DEFAULT, // OP_INSTANT_APP_START_FOREGROUND |
| AppOpsManager.MODE_ALLOWED, // ANSWER_PHONE_CALLS |
| AppOpsManager.MODE_ALLOWED, // OP_RUN_ANY_IN_BACKGROUND |
| AppOpsManager.MODE_ALLOWED, // OP_CHANGE_WIFI_STATE |
| AppOpsManager.MODE_ALLOWED, // REQUEST_DELETE_PACKAGES |
| AppOpsManager.MODE_ALLOWED, // OP_BIND_ACCESSIBILITY_SERVICE |
| AppOpsManager.MODE_ALLOWED, // ACCEPT_HANDOVER |
| AppOpsManager.MODE_ERRORED, // MANAGE_IPSEC_TUNNELS |
| AppOpsManager.MODE_ALLOWED, // OP_START_FOREGROUND |
| AppOpsManager.MODE_ALLOWED, // OP_BLUETOOTH_SCAN |
| AppOpsManager.MODE_ALLOWED, // USE_FACE |
| }; |
| |
| /** |
| * This specifies whether each option is allowed to be reset |
| * when resetting all app preferences. Disable reset for |
| * app ops that are under strong control of some part of the |
| * system (such as OP_WRITE_SMS, which should be allowed only |
| * for whichever app is selected as the current SMS app). |
| */ |
| private static boolean[] sOpDisableReset = new boolean[] { |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| true, // OP_WRITE_SMS |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, // OP_AUDIO_ACCESSIBILITY_VOLUME |
| false, |
| false, // OP_REQUEST_INSTALL_PACKAGES |
| false, // OP_PICTURE_IN_PICTURE |
| false, |
| false, // ANSWER_PHONE_CALLS |
| false, // OP_RUN_ANY_IN_BACKGROUND |
| false, // OP_CHANGE_WIFI_STATE |
| false, // OP_REQUEST_DELETE_PACKAGES |
| false, // OP_BIND_ACCESSIBILITY_SERVICE |
| false, // ACCEPT_HANDOVER |
| false, // MANAGE_IPSEC_TUNNELS |
| false, // START_FOREGROUND |
| false, // BLUETOOTH_SCAN |
| false, // USE_FACE |
| }; |
| |
| /** |
| * Mapping from an app op name to the app op code. |
| */ |
| private static HashMap<String, Integer> sOpStrToOp = new HashMap<>(); |
| |
| /** |
| * Mapping from a permission to the corresponding app op. |
| */ |
| private static HashMap<String, Integer> sPermToOp = new HashMap<>(); |
| |
| static { |
| if (sOpToSwitch.length != _NUM_OP) { |
| throw new IllegalStateException("sOpToSwitch length " + sOpToSwitch.length |
| + " should be " + _NUM_OP); |
| } |
| if (sOpToString.length != _NUM_OP) { |
| throw new IllegalStateException("sOpToString length " + sOpToString.length |
| + " should be " + _NUM_OP); |
| } |
| if (sOpNames.length != _NUM_OP) { |
| throw new IllegalStateException("sOpNames length " + sOpNames.length |
| + " should be " + _NUM_OP); |
| } |
| if (sOpPerms.length != _NUM_OP) { |
| throw new IllegalStateException("sOpPerms length " + sOpPerms.length |
| + " should be " + _NUM_OP); |
| } |
| if (sOpDefaultMode.length != _NUM_OP) { |
| throw new IllegalStateException("sOpDefaultMode length " + sOpDefaultMode.length |
| + " should be " + _NUM_OP); |
| } |
| if (sOpDisableReset.length != _NUM_OP) { |
| throw new IllegalStateException("sOpDisableReset length " + sOpDisableReset.length |
| + " should be " + _NUM_OP); |
| } |
| if (sOpRestrictions.length != _NUM_OP) { |
| throw new IllegalStateException("sOpRestrictions length " + sOpRestrictions.length |
| + " should be " + _NUM_OP); |
| } |
| if (sOpAllowSystemRestrictionBypass.length != _NUM_OP) { |
| throw new IllegalStateException("sOpAllowSYstemRestrictionsBypass length " |
| + sOpRestrictions.length + " should be " + _NUM_OP); |
| } |
| for (int i=0; i<_NUM_OP; i++) { |
| if (sOpToString[i] != null) { |
| sOpStrToOp.put(sOpToString[i], i); |
| } |
| } |
| for (int op : RUNTIME_AND_APPOP_PERMISSIONS_OPS) { |
| if (sOpPerms[op] != null) { |
| sPermToOp.put(sOpPerms[op], op); |
| } |
| } |
| } |
| |
| /** |
| * Retrieve the op switch that controls the given operation. |
| * @hide |
| */ |
| public static int opToSwitch(int op) { |
| return sOpToSwitch[op]; |
| } |
| |
| /** |
| * Retrieve a non-localized name for the operation, for debugging output. |
| * @hide |
| */ |
| public static String opToName(int op) { |
| if (op == OP_NONE) return "NONE"; |
| return op < sOpNames.length ? sOpNames[op] : ("Unknown(" + op + ")"); |
| } |
| |
| /** |
| * @hide |
| */ |
| public static int strDebugOpToOp(String op) { |
| for (int i=0; i<sOpNames.length; i++) { |
| if (sOpNames[i].equals(op)) { |
| return i; |
| } |
| } |
| throw new IllegalArgumentException("Unknown operation string: " + op); |
| } |
| |
| /** |
| * Retrieve the permission associated with an operation, or null if there is not one. |
| * @hide |
| */ |
| @TestApi |
| public static String opToPermission(int op) { |
| return sOpPerms[op]; |
| } |
| |
| /** |
| * Retrieve the user restriction associated with an operation, or null if there is not one. |
| * @hide |
| */ |
| public static String opToRestriction(int op) { |
| return sOpRestrictions[op]; |
| } |
| |
| /** |
| * Retrieve the app op code for a permission, or null if there is not one. |
| * This API is intended to be used for mapping runtime or appop permissions |
| * to the corresponding app op. |
| * @hide |
| */ |
| @TestApi |
| public static int permissionToOpCode(String permission) { |
| Integer boxedOpCode = sPermToOp.get(permission); |
| return boxedOpCode != null ? boxedOpCode : OP_NONE; |
| } |
| |
| /** |
| * Retrieve whether the op allows the system (and system ui) to |
| * bypass the user restriction. |
| * @hide |
| */ |
| public static boolean opAllowSystemBypassRestriction(int op) { |
| return sOpAllowSystemRestrictionBypass[op]; |
| } |
| |
| /** |
| * Retrieve the default mode for the operation. |
| * @hide |
| */ |
| public static int opToDefaultMode(int op) { |
| return sOpDefaultMode[op]; |
| } |
| |
| /** |
| * Retrieve the human readable mode. |
| * @hide |
| */ |
| public static String modeToName(int mode) { |
| if (mode >= 0 && mode < MODE_NAMES.length) { |
| return MODE_NAMES[mode]; |
| } |
| return "mode=" + mode; |
| } |
| |
| /** |
| * Retrieve whether the op allows itself to be reset. |
| * @hide |
| */ |
| public static boolean opAllowsReset(int op) { |
| return !sOpDisableReset[op]; |
| } |
| |
| /** |
| * Class holding all of the operation information associated with an app. |
| * @hide |
| */ |
| @SystemApi |
| public static final class PackageOps implements Parcelable { |
| private final String mPackageName; |
| private final int mUid; |
| private final List<OpEntry> mEntries; |
| |
| /** |
| * @hide |
| */ |
| public PackageOps(String packageName, int uid, List<OpEntry> entries) { |
| mPackageName = packageName; |
| mUid = uid; |
| mEntries = entries; |
| } |
| |
| public String getPackageName() { |
| return mPackageName; |
| } |
| |
| public int getUid() { |
| return mUid; |
| } |
| |
| public List<OpEntry> getOps() { |
| return mEntries; |
| } |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| @Override |
| public void writeToParcel(Parcel dest, int flags) { |
| dest.writeString(mPackageName); |
| dest.writeInt(mUid); |
| dest.writeInt(mEntries.size()); |
| for (int i=0; i<mEntries.size(); i++) { |
| mEntries.get(i).writeToParcel(dest, flags); |
| } |
| } |
| |
| PackageOps(Parcel source) { |
| mPackageName = source.readString(); |
| mUid = source.readInt(); |
| mEntries = new ArrayList<OpEntry>(); |
| final int N = source.readInt(); |
| for (int i=0; i<N; i++) { |
| mEntries.add(OpEntry.CREATOR.createFromParcel(source)); |
| } |
| } |
| |
| public static final Creator<PackageOps> CREATOR = new Creator<PackageOps>() { |
| @Override public PackageOps createFromParcel(Parcel source) { |
| return new PackageOps(source); |
| } |
| |
| @Override public PackageOps[] newArray(int size) { |
| return new PackageOps[size]; |
| } |
| }; |
| } |
| |
| /** |
| * Class holding the information about one unique operation of an application. |
| * @hide |
| */ |
| @SystemApi |
| public static final class OpEntry implements Parcelable { |
| private final int mOp; |
| private final int mMode; |
| private final long[] mTimes; |
| private final long[] mRejectTimes; |
| private final int mDuration; |
| private final int mProxyUid; |
| private final boolean mRunning; |
| private final String mProxyPackageName; |
| |
| /** |
| * @hide |
| */ |
| public OpEntry(int op, int mode, long time, long rejectTime, int duration, |
| int proxyUid, String proxyPackage) { |
| mOp = op; |
| mMode = mode; |
| mTimes = new long[_NUM_UID_STATE]; |
| mRejectTimes = new long[_NUM_UID_STATE]; |
| mTimes[0] = time; |
| mRejectTimes[0] = rejectTime; |
| mDuration = duration; |
| mRunning = duration == -1; |
| mProxyUid = proxyUid; |
| mProxyPackageName = proxyPackage; |
| } |
| |
| /** |
| * @hide |
| */ |
| public OpEntry(int op, int mode, long[] times, long[] rejectTimes, int duration, |
| boolean running, int proxyUid, String proxyPackage) { |
| mOp = op; |
| mMode = mode; |
| mTimes = new long[_NUM_UID_STATE]; |
| mRejectTimes = new long[_NUM_UID_STATE]; |
| System.arraycopy(times, 0, mTimes, 0, _NUM_UID_STATE); |
| System.arraycopy(rejectTimes, 0, mRejectTimes, 0, _NUM_UID_STATE); |
| mDuration = duration; |
| mRunning = running; |
| mProxyUid = proxyUid; |
| mProxyPackageName = proxyPackage; |
| } |
| |
| /** |
| * @hide |
| */ |
| public OpEntry(int op, int mode, long[] times, long[] rejectTimes, int duration, |
| int proxyUid, String proxyPackage) { |
| this(op, mode, times, rejectTimes, duration, duration == -1, proxyUid, proxyPackage); |
| } |
| |
| /** |
| * @hide |
| */ |
| public int getOp() { |
| return mOp; |
| } |
| |
| /** |
| * Return this entry's op string name, such as {@link #OPSTR_COARSE_LOCATION}. |
| */ |
| public String getOpStr() { |
| return sOpToString[mOp]; |
| } |
| |
| /** |
| * Return this entry's current mode, such as {@link #MODE_ALLOWED}. |
| */ |
| public int getMode() { |
| return mMode; |
| } |
| |
| /** |
| * @hide |
| */ |
| public long getTime() { |
| return maxTime(mTimes, 0, _NUM_UID_STATE); |
| } |
| |
| /** |
| * Return the last wall clock time this op was accessed by the app. |
| */ |
| public long getLastAccessTime() { |
| return maxTime(mTimes, 0, _NUM_UID_STATE); |
| } |
| |
| /** |
| * Return the last wall clock time this op was accessed by the app while in the foreground. |
| */ |
| public long getLastAccessForegroundTime() { |
| return maxTime(mTimes, UID_STATE_PERSISTENT, UID_STATE_LAST_NON_RESTRICTED + 1); |
| } |
| |
| /** |
| * Return the last wall clock time this op was accessed by the app while in the background. |
| */ |
| public long getLastAccessBackgroundTime() { |
| return maxTime(mTimes, UID_STATE_LAST_NON_RESTRICTED + 1, _NUM_UID_STATE); |
| } |
| |
| /** |
| * @hide |
| */ |
| public long getLastTimeFor(int uidState) { |
| return mTimes[uidState]; |
| } |
| |
| /** |
| * @hide |
| */ |
| public long getRejectTime() { |
| return maxTime(mRejectTimes, 0, _NUM_UID_STATE); |
| } |
| |
| /** |
| * Return the last wall clock time the app made an attempt to access this op but |
| * was rejected. |
| */ |
| public long getLastRejectTime() { |
| return maxTime(mRejectTimes, 0, _NUM_UID_STATE); |
| } |
| |
| /** |
| * Return the last wall clock time the app made an attempt to access this op while in |
| * the foreground but was rejected. |
| */ |
| public long getLastRejectForegroundTime() { |
| return maxTime(mRejectTimes, UID_STATE_PERSISTENT, UID_STATE_LAST_NON_RESTRICTED + 1); |
| } |
| |
| /** |
| * Return the last wall clock time the app made an attempt to access this op while in |
| * the background but was rejected. |
| */ |
| public long getLastRejectBackgroundTime() { |
| return maxTime(mRejectTimes, UID_STATE_LAST_NON_RESTRICTED + 1, _NUM_UID_STATE); |
| } |
| |
| /** |
| * @hide |
| */ |
| public long getLastRejectTimeFor(int uidState) { |
| return mRejectTimes[uidState]; |
| } |
| |
| public boolean isRunning() { |
| return mRunning; |
| } |
| |
| public int getDuration() { |
| return mDuration; |
| } |
| |
| public int getProxyUid() { |
| return mProxyUid; |
| } |
| |
| public String getProxyPackageName() { |
| return mProxyPackageName; |
| } |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| @Override |
| public void writeToParcel(Parcel dest, int flags) { |
| dest.writeInt(mOp); |
| dest.writeInt(mMode); |
| dest.writeLongArray(mTimes); |
| dest.writeLongArray(mRejectTimes); |
| dest.writeInt(mDuration); |
| dest.writeBoolean(mRunning); |
| dest.writeInt(mProxyUid); |
| dest.writeString(mProxyPackageName); |
| } |
| |
| OpEntry(Parcel source) { |
| mOp = source.readInt(); |
| mMode = source.readInt(); |
| mTimes = source.createLongArray(); |
| mRejectTimes = source.createLongArray(); |
| mDuration = source.readInt(); |
| mRunning = source.readBoolean(); |
| mProxyUid = source.readInt(); |
| mProxyPackageName = source.readString(); |
| } |
| |
| public static final Creator<OpEntry> CREATOR = new Creator<OpEntry>() { |
| @Override public OpEntry createFromParcel(Parcel source) { |
| return new OpEntry(source); |
| } |
| |
| @Override public OpEntry[] newArray(int size) { |
| return new OpEntry[size]; |
| } |
| }; |
| } |
| |
| /** |
| * Callback for notification of changes to operation state. |
| */ |
| public interface OnOpChangedListener { |
| public void onOpChanged(String op, String packageName); |
| } |
| |
| /** |
| * Callback for notification of changes to operation active state. |
| * |
| * @hide |
| */ |
| @TestApi |
| public interface OnOpActiveChangedListener { |
| /** |
| * Called when the active state of an app op changes. |
| * |
| * @param code The op code. |
| * @param uid The UID performing the operation. |
| * @param packageName The package performing the operation. |
| * @param active Whether the operation became active or inactive. |
| */ |
| void onOpActiveChanged(int code, int uid, String packageName, boolean active); |
| } |
| |
| /** |
| * Callback for notification of changes to operation state. |
| * This allows you to see the raw op codes instead of strings. |
| * @hide |
| */ |
| public static class OnOpChangedInternalListener implements OnOpChangedListener { |
| public void onOpChanged(String op, String packageName) { } |
| public void onOpChanged(int op, String packageName) { } |
| } |
| |
| AppOpsManager(Context context, IAppOpsService service) { |
| mContext = context; |
| mService = service; |
| } |
| |
| /** |
| * Retrieve current operation state for all applications. |
| * |
| * @param ops The set of operations you are interested in, or null if you want all of them. |
| * @hide |
| */ |
| @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) |
| public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) { |
| try { |
| return mService.getPackagesForOps(ops); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Retrieve current operation state for one application. |
| * |
| * @param uid The uid of the application of interest. |
| * @param packageName The name of the application of interest. |
| * @param ops The set of operations you are interested in, or null if you want all of them. |
| * @hide |
| */ |
| @SystemApi |
| @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) |
| public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, int[] ops) { |
| try { |
| return mService.getOpsForPackage(uid, packageName, ops); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Sets given app op in the specified mode for app ops in the UID. |
| * This applies to all apps currently in the UID or installed in |
| * this UID in the future. |
| * |
| * @param code The app op. |
| * @param uid The UID for which to set the app. |
| * @param mode The app op mode to set. |
| * @hide |
| */ |
| @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES) |
| public void setUidMode(int code, int uid, int mode) { |
| try { |
| mService.setUidMode(code, uid, mode); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Sets given app op in the specified mode for app ops in the UID. |
| * This applies to all apps currently in the UID or installed in |
| * this UID in the future. |
| * |
| * @param appOp The app op. |
| * @param uid The UID for which to set the app. |
| * @param mode The app op mode to set. |
| * @hide |
| */ |
| @SystemApi |
| @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES) |
| public void setUidMode(String appOp, int uid, int mode) { |
| try { |
| mService.setUidMode(AppOpsManager.strOpToOp(appOp), uid, mode); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** @hide */ |
| public void setUserRestriction(int code, boolean restricted, IBinder token) { |
| setUserRestriction(code, restricted, token, /*exceptionPackages*/null); |
| } |
| |
| /** @hide */ |
| public void setUserRestriction(int code, boolean restricted, IBinder token, |
| String[] exceptionPackages) { |
| setUserRestrictionForUser(code, restricted, token, exceptionPackages, mContext.getUserId()); |
| } |
| |
| /** @hide */ |
| public void setUserRestrictionForUser(int code, boolean restricted, IBinder token, |
| String[] exceptionPackages, int userId) { |
| try { |
| mService.setUserRestriction(code, restricted, token, userId, exceptionPackages); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** @hide */ |
| @TestApi |
| @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES) |
| public void setMode(int code, int uid, String packageName, int mode) { |
| try { |
| mService.setMode(code, uid, packageName, mode); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Change the operating mode for the given op in the given app package. You must pass |
| * in both the uid and name of the application whose mode is being modified; if these |
| * do not match, the modification will not be applied. |
| * |
| * @param op The operation to modify. One of the OPSTR_* constants. |
| * @param uid The user id of the application whose mode will be changed. |
| * @param packageName The name of the application package name whose mode will |
| * be changed. |
| * @hide |
| */ |
| @SystemApi |
| @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES) |
| public void setMode(String op, int uid, String packageName, int mode) { |
| try { |
| mService.setMode(strOpToOp(op), uid, packageName, mode); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Set a non-persisted restriction on an audio operation at a stream-level. |
| * Restrictions are temporary additional constraints imposed on top of the persisted rules |
| * defined by {@link #setMode}. |
| * |
| * @param code The operation to restrict. |
| * @param usage The {@link android.media.AudioAttributes} usage value. |
| * @param mode The restriction mode (MODE_IGNORED,MODE_ERRORED) or MODE_ALLOWED to unrestrict. |
| * @param exceptionPackages Optional list of packages to exclude from the restriction. |
| * @hide |
| */ |
| @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES) |
| public void setRestriction(int code, @AttributeUsage int usage, int mode, |
| String[] exceptionPackages) { |
| try { |
| final int uid = Binder.getCallingUid(); |
| mService.setAudioRestriction(code, usage, uid, mode, exceptionPackages); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** @hide */ |
| @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES) |
| public void resetAllModes() { |
| try { |
| mService.resetAllModes(mContext.getUserId(), null); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Gets the app op name associated with a given permission. |
| * The app op name is one of the public constants defined |
| * in this class such as {@link #OPSTR_COARSE_LOCATION}. |
| * This API is intended to be used for mapping runtime |
| * permissions to the corresponding app op. |
| * |
| * @param permission The permission. |
| * @return The app op associated with the permission or null. |
| */ |
| public static String permissionToOp(String permission) { |
| final Integer opCode = sPermToOp.get(permission); |
| if (opCode == null) { |
| return null; |
| } |
| return sOpToString[opCode]; |
| } |
| |
| /** |
| * Monitor for changes to the operating mode for the given op in the given app package. |
| * You can watch op changes only for your UID. |
| * |
| * @param op The operation to monitor, one of OPSTR_*. |
| * @param packageName The name of the application to monitor. |
| * @param callback Where to report changes. |
| */ |
| public void startWatchingMode(String op, String packageName, |
| final OnOpChangedListener callback) { |
| startWatchingMode(strOpToOp(op), packageName, callback); |
| } |
| |
| /** |
| * Monitor for changes to the operating mode for the given op in the given app package. |
| * You can watch op changes only for your UID. |
| * |
| * @param op The operation to monitor, one of OPSTR_*. |
| * @param packageName The name of the application to monitor. |
| * @param flags Option flags: any combination of {@link #WATCH_FOREGROUND_CHANGES} or 0. |
| * @param callback Where to report changes. |
| */ |
| public void startWatchingMode(String op, String packageName, int flags, |
| final OnOpChangedListener callback) { |
| startWatchingMode(strOpToOp(op), packageName, flags, callback); |
| } |
| |
| /** |
| * Monitor for changes to the operating mode for the given op in the given app package. |
| * |
| * <p> If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission |
| * you can watch changes only for your UID. |
| * |
| * @param op The operation to monitor, one of OP_*. |
| * @param packageName The name of the application to monitor. |
| * @param callback Where to report changes. |
| * @hide |
| */ |
| @RequiresPermission(value=android.Manifest.permission.WATCH_APPOPS, conditional=true) |
| public void startWatchingMode(int op, String packageName, final OnOpChangedListener callback) { |
| startWatchingMode(op, packageName, 0, callback); |
| } |
| |
| /** |
| * Monitor for changes to the operating mode for the given op in the given app package. |
| * |
| * <p> If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission |
| * you can watch changes only for your UID. |
| * |
| * @param op The operation to monitor, one of OP_*. |
| * @param packageName The name of the application to monitor. |
| * @param flags Option flags: any combination of {@link #WATCH_FOREGROUND_CHANGES} or 0. |
| * @param callback Where to report changes. |
| * @hide |
| */ |
| @RequiresPermission(value=android.Manifest.permission.WATCH_APPOPS, conditional=true) |
| public void startWatchingMode(int op, String packageName, int flags, |
| final OnOpChangedListener callback) { |
| synchronized (mModeWatchers) { |
| IAppOpsCallback cb = mModeWatchers.get(callback); |
| if (cb == null) { |
| cb = new IAppOpsCallback.Stub() { |
| public void opChanged(int op, int uid, String packageName) { |
| if (callback instanceof OnOpChangedInternalListener) { |
| ((OnOpChangedInternalListener)callback).onOpChanged(op, packageName); |
| } |
| if (sOpToString[op] != null) { |
| callback.onOpChanged(sOpToString[op], packageName); |
| } |
| } |
| }; |
| mModeWatchers.put(callback, cb); |
| } |
| try { |
| mService.startWatchingModeWithFlags(op, packageName, flags, cb); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| } |
| |
| /** |
| * Stop monitoring that was previously started with {@link #startWatchingMode}. All |
| * monitoring associated with this callback will be removed. |
| */ |
| public void stopWatchingMode(OnOpChangedListener callback) { |
| synchronized (mModeWatchers) { |
| IAppOpsCallback cb = mModeWatchers.get(callback); |
| if (cb != null) { |
| try { |
| mService.stopWatchingMode(cb); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Start watching for changes to the active state of app ops. An app op may be |
| * long running and it has a clear start and stop delimiters. If an op is being |
| * started or stopped by any package you will get a callback. To change the |
| * watched ops for a registered callback you need to unregister and register it |
| * again. |
| * |
| * <p> If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission |
| * you can watch changes only for your UID. |
| * |
| * @param ops The ops to watch. |
| * @param callback Where to report changes. |
| * |
| * @see #isOperationActive(int, int, String) |
| * @see #stopWatchingActive(OnOpActiveChangedListener) |
| * @see #startOp(int, int, String) |
| * @see #finishOp(int, int, String) |
| * |
| * @hide |
| */ |
| @TestApi |
| // TODO: Uncomment below annotation once b/73559440 is fixed |
| // @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true) |
| public void startWatchingActive(@NonNull int[] ops, |
| @NonNull OnOpActiveChangedListener callback) { |
| Preconditions.checkNotNull(ops, "ops cannot be null"); |
| Preconditions.checkNotNull(callback, "callback cannot be null"); |
| IAppOpsActiveCallback cb; |
| synchronized (mActiveWatchers) { |
| cb = mActiveWatchers.get(callback); |
| if (cb != null) { |
| return; |
| } |
| cb = new IAppOpsActiveCallback.Stub() { |
| @Override |
| public void opActiveChanged(int op, int uid, String packageName, boolean active) { |
| callback.onOpActiveChanged(op, uid, packageName, active); |
| } |
| }; |
| mActiveWatchers.put(callback, cb); |
| } |
| try { |
| mService.startWatchingActive(ops, cb); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Stop watching for changes to the active state of an app op. An app op may be |
| * long running and it has a clear start and stop delimiters. Unregistering a |
| * non-registered callback has no effect. |
| * |
| * @see #isOperationActive#(int, int, String) |
| * @see #startWatchingActive(int[], OnOpActiveChangedListener) |
| * @see #startOp(int, int, String) |
| * @see #finishOp(int, int, String) |
| * |
| * @hide |
| */ |
| @TestApi |
| public void stopWatchingActive(@NonNull OnOpActiveChangedListener callback) { |
| synchronized (mActiveWatchers) { |
| final IAppOpsActiveCallback cb = mActiveWatchers.get(callback); |
| if (cb != null) { |
| try { |
| mService.stopWatchingActive(cb); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| } |
| } |
| |
| private String buildSecurityExceptionMsg(int op, int uid, String packageName) { |
| return packageName + " from uid " + uid + " not allowed to perform " + sOpNames[op]; |
| } |
| |
| /** |
| * {@hide} |
| */ |
| @TestApi |
| public static int strOpToOp(String op) { |
| Integer val = sOpStrToOp.get(op); |
| if (val == null) { |
| throw new IllegalArgumentException("Unknown operation string: " + op); |
| } |
| return val; |
| } |
| |
| /** |
| * Do a quick check for whether an application might be able to perform an operation. |
| * This is <em>not</em> a security check; you must use {@link #noteOp(String, int, String)} |
| * or {@link #startOp(String, int, String)} for your actual security checks, which also |
| * ensure that the given uid and package name are consistent. This function can just be |
| * used for a quick check to see if an operation has been disabled for the application, |
| * as an early reject of some work. This does not modify the time stamp or other data |
| * about the operation. |
| * |
| * <p>Important things this will not do (which you need to ultimate use |
| * {@link #noteOp(String, int, String)} or {@link #startOp(String, int, String)} to cover):</p> |
| * <ul> |
| * <li>Verifying the uid and package are consistent, so callers can't spoof |
| * their identity.</li> |
| * <li>Taking into account the current foreground/background state of the |
| * app; apps whose mode varies by this state will always be reported |
| * as {@link #MODE_ALLOWED}.</li> |
| * </ul> |
| * |
| * @param op The operation to check. One of the OPSTR_* constants. |
| * @param uid The user id of the application attempting to perform the operation. |
| * @param packageName The name of the application attempting to perform the operation. |
| * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or |
| * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without |
| * causing the app to crash). |
| * @throws SecurityException If the app has been configured to crash on this op. |
| */ |
| public int unsafeCheckOp(String op, int uid, String packageName) { |
| return checkOp(strOpToOp(op), uid, packageName); |
| } |
| |
| /** |
| * @deprecated Renamed to {@link #unsafeCheckOp(String, int, String)}. |
| */ |
| @Deprecated |
| public int checkOp(String op, int uid, String packageName) { |
| return checkOp(strOpToOp(op), uid, packageName); |
| } |
| |
| /** |
| * Like {@link #checkOp} but instead of throwing a {@link SecurityException} it |
| * returns {@link #MODE_ERRORED}. |
| */ |
| public int unsafeCheckOpNoThrow(String op, int uid, String packageName) { |
| return checkOpNoThrow(strOpToOp(op), uid, packageName); |
| } |
| |
| /** |
| * @deprecated Renamed to {@link #unsafeCheckOpNoThrow(String, int, String)}. |
| */ |
| @Deprecated |
| public int checkOpNoThrow(String op, int uid, String packageName) { |
| return checkOpNoThrow(strOpToOp(op), uid, packageName); |
| } |
| |
| /** |
| * Like {@link #checkOp} but returns the <em>raw</em> mode associated with the op. |
| * Does not throw a security exception, does not translate {@link #MODE_FOREGROUND}. |
| */ |
| public int unsafeCheckOpRaw(String op, int uid, String packageName) { |
| try { |
| return mService.checkOperation(strOpToOp(op), uid, packageName); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Make note of an application performing an operation. Note that you must pass |
| * in both the uid and name of the application to be checked; this function will verify |
| * that these two match, and if not, return {@link #MODE_IGNORED}. If this call |
| * succeeds, the last execution time of the operation for this app will be updated to |
| * the current time. |
| * @param op The operation to note. One of the OPSTR_* constants. |
| * @param uid The user id of the application attempting to perform the operation. |
| * @param packageName The name of the application attempting to perform the operation. |
| * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or |
| * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without |
| * causing the app to crash). |
| * @throws SecurityException If the app has been configured to crash on this op. |
| */ |
| public int noteOp(String op, int uid, String packageName) { |
| return noteOp(strOpToOp(op), uid, packageName); |
| } |
| |
| /** |
| * Like {@link #noteOp} but instead of throwing a {@link SecurityException} it |
| * returns {@link #MODE_ERRORED}. |
| */ |
| public int noteOpNoThrow(String op, int uid, String packageName) { |
| return noteOpNoThrow(strOpToOp(op), uid, packageName); |
| } |
| |
| /** |
| * Make note of an application performing an operation on behalf of another |
| * application when handling an IPC. Note that you must pass the package name |
| * of the application that is being proxied while its UID will be inferred from |
| * the IPC state; this function will verify that the calling uid and proxied |
| * package name match, and if not, return {@link #MODE_IGNORED}. If this call |
| * succeeds, the last execution time of the operation for the proxied app and |
| * your app will be updated to the current time. |
| * @param op The operation to note. One of the OPSTR_* constants. |
| * @param proxiedPackageName The name of the application calling into the proxy application. |
| * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or |
| * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without |
| * causing the app to crash). |
| * @throws SecurityException If the app has been configured to crash on this op. |
| */ |
| public int noteProxyOp(String op, String proxiedPackageName) { |
| return noteProxyOp(strOpToOp(op), proxiedPackageName); |
| } |
| |
| /** |
| * Like {@link #noteProxyOp(String, String)} but instead |
| * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}. |
| */ |
| public int noteProxyOpNoThrow(String op, String proxiedPackageName) { |
| return noteProxyOpNoThrow(strOpToOp(op), proxiedPackageName); |
| } |
| |
| /** |
| * Report that an application has started executing a long-running operation. Note that you |
| * must pass in both the uid and name of the application to be checked; this function will |
| * verify that these two match, and if not, return {@link #MODE_IGNORED}. If this call |
| * succeeds, the last execution time of the operation for this app will be updated to |
| * the current time and the operation will be marked as "running". In this case you must |
| * later call {@link #finishOp(String, int, String)} to report when the application is no |
| * longer performing the operation. |
| * @param op The operation to start. One of the OPSTR_* constants. |
| * @param uid The user id of the application attempting to perform the operation. |
| * @param packageName The name of the application attempting to perform the operation. |
| * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or |
| * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without |
| * causing the app to crash). |
| * @throws SecurityException If the app has been configured to crash on this op. |
| */ |
| public int startOp(String op, int uid, String packageName) { |
| return startOp(strOpToOp(op), uid, packageName); |
| } |
| |
| /** |
| * Like {@link #startOp} but instead of throwing a {@link SecurityException} it |
| * returns {@link #MODE_ERRORED}. |
| */ |
| public int startOpNoThrow(String op, int uid, String packageName) { |
| return startOpNoThrow(strOpToOp(op), uid, packageName); |
| } |
| |
| /** |
| * Report that an application is no longer performing an operation that had previously |
| * been started with {@link #startOp(String, int, String)}. There is no validation of input |
| * or result; the parameters supplied here must be the exact same ones previously passed |
| * in when starting the operation. |
| */ |
| public void finishOp(String op, int uid, String packageName) { |
| finishOp(strOpToOp(op), uid, packageName); |
| } |
| |
| /** |
| * Do a quick check for whether an application might be able to perform an operation. |
| * This is <em>not</em> a security check; you must use {@link #noteOp(int, int, String)} |
| * or {@link #startOp(int, int, String)} for your actual security checks, which also |
| * ensure that the given uid and package name are consistent. This function can just be |
| * used for a quick check to see if an operation has been disabled for the application, |
| * as an early reject of some work. This does not modify the time stamp or other data |
| * about the operation. |
| * |
| * <p>Important things this will not do (which you need to ultimate use |
| * {@link #noteOp(int, int, String)} or {@link #startOp(int, int, String)} to cover):</p> |
| * <ul> |
| * <li>Verifying the uid and package are consistent, so callers can't spoof |
| * their identity.</li> |
| * <li>Taking into account the current foreground/background state of the |
| * app; apps whose mode varies by this state will always be reported |
| * as {@link #MODE_ALLOWED}.</li> |
| * </ul> |
| * |
| * @param op The operation to check. One of the OP_* constants. |
| * @param uid The user id of the application attempting to perform the operation. |
| * @param packageName The name of the application attempting to perform the operation. |
| * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or |
| * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without |
| * causing the app to crash). |
| * @throws SecurityException If the app has been configured to crash on this op. |
| * @hide |
| */ |
| public int checkOp(int op, int uid, String packageName) { |
| try { |
| int mode = mService.checkOperation(op, uid, packageName); |
| if (mode == MODE_ERRORED) { |
| throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName)); |
| } |
| return mode; |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Like {@link #checkOp} but instead of throwing a {@link SecurityException} it |
| * returns {@link #MODE_ERRORED}. |
| * @hide |
| */ |
| public int checkOpNoThrow(int op, int uid, String packageName) { |
| try { |
| int mode = mService.checkOperation(op, uid, packageName); |
| return mode == AppOpsManager.MODE_FOREGROUND ? AppOpsManager.MODE_ALLOWED : mode; |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Do a quick check to validate if a package name belongs to a UID. |
| * |
| * @throws SecurityException if the package name doesn't belong to the given |
| * UID, or if ownership cannot be verified. |
| */ |
| 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); |
| } |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Like {@link #checkOp} but at a stream-level for audio operations. |
| * @hide |
| */ |
| public int checkAudioOp(int op, int stream, int uid, String packageName) { |
| try { |
| final int mode = mService.checkAudioOperation(op, stream, uid, packageName); |
| if (mode == MODE_ERRORED) { |
| throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName)); |
| } |
| return mode; |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Like {@link #checkAudioOp} but instead of throwing a {@link SecurityException} it |
| * returns {@link #MODE_ERRORED}. |
| * @hide |
| */ |
| public int checkAudioOpNoThrow(int op, int stream, int uid, String packageName) { |
| try { |
| return mService.checkAudioOperation(op, stream, uid, packageName); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Make note of an application performing an operation. Note that you must pass |
| * in both the uid and name of the application to be checked; this function will verify |
| * that these two match, and if not, return {@link #MODE_IGNORED}. If this call |
| * succeeds, the last execution time of the operation for this app will be updated to |
| * the current time. |
| * @param op The operation to note. One of the OP_* constants. |
| * @param uid The user id of the application attempting to perform the operation. |
| * @param packageName The name of the application attempting to perform the operation. |
| * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or |
| * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without |
| * causing the app to crash). |
| * @throws SecurityException If the app has been configured to crash on this op. |
| * @hide |
| */ |
| public int noteOp(int op, int uid, String packageName) { |
| final int mode = noteOpNoThrow(op, uid, packageName); |
| if (mode == MODE_ERRORED) { |
| throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName)); |
| } |
| return mode; |
| } |
| |
| /** |
| * Make note of an application performing an operation on behalf of another |
| * application when handling an IPC. Note that you must pass the package name |
| * of the application that is being proxied while its UID will be inferred from |
| * the IPC state; this function will verify that the calling uid and proxied |
| * package name match, and if not, return {@link #MODE_IGNORED}. If this call |
| * succeeds, the last execution time of the operation for the proxied app and |
| * your app will be updated to the current time. |
| * @param op The operation to note. One of the OPSTR_* constants. |
| * @param proxiedPackageName The name of the application calling into the proxy application. |
| * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or |
| * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without |
| * causing the app to crash). |
| * @throws SecurityException If the proxy or proxied app has been configured to |
| * crash on this op. |
| * |
| * @hide |
| */ |
| public int noteProxyOp(int op, String proxiedPackageName) { |
| int mode = noteProxyOpNoThrow(op, proxiedPackageName); |
| if (mode == MODE_ERRORED) { |
| throw new SecurityException("Proxy package " + mContext.getOpPackageName() |
| + " from uid " + Process.myUid() + " or calling package " |
| + proxiedPackageName + " from uid " + Binder.getCallingUid() |
| + " not allowed to perform " + sOpNames[op]); |
| } |
| return mode; |
| } |
| |
| /** |
| * Like {@link #noteProxyOp(int, String)} but instead |
| * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}. |
| * @hide |
| */ |
| public int noteProxyOpNoThrow(int op, String proxiedPackageName) { |
| try { |
| return mService.noteProxyOperation(op, mContext.getOpPackageName(), |
| Binder.getCallingUid(), proxiedPackageName); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Like {@link #noteOp} but instead of throwing a {@link SecurityException} it |
| * returns {@link #MODE_ERRORED}. |
| * @hide |
| */ |
| public int noteOpNoThrow(int op, int uid, String packageName) { |
| try { |
| return mService.noteOperation(op, uid, packageName); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** @hide */ |
| public int noteOp(int op) { |
| return noteOp(op, Process.myUid(), mContext.getOpPackageName()); |
| } |
| |
| /** @hide */ |
| public static IBinder getToken(IAppOpsService service) { |
| synchronized (AppOpsManager.class) { |
| if (sToken != null) { |
| return sToken; |
| } |
| try { |
| sToken = service.getToken(new Binder()); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| return sToken; |
| } |
| } |
| |
| /** @hide */ |
| public int startOp(int op) { |
| return startOp(op, Process.myUid(), mContext.getOpPackageName()); |
| } |
| |
| /** |
| * Report that an application has started executing a long-running operation. Note that you |
| * must pass in both the uid and name of the application to be checked; this function will |
| * verify that these two match, and if not, return {@link #MODE_IGNORED}. If this call |
| * succeeds, the last execution time of the operation for this app will be updated to |
| * the current time and the operation will be marked as "running". In this case you must |
| * later call {@link #finishOp(int, int, String)} to report when the application is no |
| * longer performing the operation. |
| * |
| * @param op The operation to start. One of the OP_* constants. |
| * @param uid The user id of the application attempting to perform the operation. |
| * @param packageName The name of the application attempting to perform the operation. |
| * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or |
| * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without |
| * causing the app to crash). |
| * @throws SecurityException If the app has been configured to crash on this op. |
| * @hide |
| */ |
| public int startOp(int op, int uid, String packageName) { |
| return startOp(op, uid, packageName, false); |
| } |
| |
| /** |
| * Report that an application has started executing a long-running operation. Similar |
| * to {@link #startOp(String, int, String) except that if the mode is {@link #MODE_DEFAULT} |
| * the operation should succeed since the caller has performed its standard permission |
| * checks which passed and would perform the protected operation for this mode. |
| * |
| * @param op The operation to start. One of the OP_* constants. |
| * @param uid The user id of the application attempting to perform the operation. |
| * @param packageName The name of the application attempting to perform the operation. |
| * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or |
| * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without |
| * causing the app to crash). |
| * @param startIfModeDefault Whether to start if mode is {@link #MODE_DEFAULT}. |
| * |
| * @throws SecurityException If the app has been configured to crash on this op or |
| * the package is not in the passed in UID. |
| * |
| * @hide |
| */ |
| public int startOp(int op, int uid, String packageName, boolean startIfModeDefault) { |
| final int mode = startOpNoThrow(op, uid, packageName, startIfModeDefault); |
| if (mode == MODE_ERRORED) { |
| throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName)); |
| } |
| return mode; |
| } |
| |
| /** |
| * Like {@link #startOp} but instead of throwing a {@link SecurityException} it |
| * returns {@link #MODE_ERRORED}. |
| * @hide |
| */ |
| public int startOpNoThrow(int op, int uid, String packageName) { |
| return startOpNoThrow(op, uid, packageName, false); |
| } |
| |
| /** |
| * Like {@link #startOp(int, int, String, boolean)} but instead of throwing a |
| * {@link SecurityException} it returns {@link #MODE_ERRORED}. |
| * |
| * @param op The operation to start. One of the OP_* constants. |
| * @param uid The user id of the application attempting to perform the operation. |
| * @param packageName The name of the application attempting to perform the operation. |
| * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or |
| * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without |
| * causing the app to crash). |
| * @param startIfModeDefault Whether to start if mode is {@link #MODE_DEFAULT}. |
| * |
| * @hide |
| */ |
| public int startOpNoThrow(int op, int uid, String packageName, boolean startIfModeDefault) { |
| try { |
| return mService.startOperation(getToken(mService), op, uid, packageName, |
| startIfModeDefault); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Report that an application is no longer performing an operation that had previously |
| * been started with {@link #startOp(int, int, String)}. There is no validation of input |
| * or result; the parameters supplied here must be the exact same ones previously passed |
| * in when starting the operation. |
| * @hide |
| */ |
| public void finishOp(int op, int uid, String packageName) { |
| try { |
| mService.finishOperation(getToken(mService), op, uid, packageName); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** @hide */ |
| public void finishOp(int op) { |
| finishOp(op, Process.myUid(), mContext.getOpPackageName()); |
| } |
| |
| /** |
| * Checks whether the given op for a UID and package is active. |
| * |
| * <p> If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission |
| * you can query only for your UID. |
| * |
| * @see #startWatchingActive(int[], OnOpActiveChangedListener) |
| * @see #stopWatchingMode(OnOpChangedListener) |
| * @see #finishOp(int) |
| * @see #startOp(int) |
| * |
| * @hide */ |
| @TestApi |
| // TODO: Uncomment below annotation once b/73559440 is fixed |
| // @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true) |
| public boolean isOperationActive(int code, int uid, String packageName) { |
| try { |
| return mService.isOperationActive(code, uid, packageName); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Returns all supported operation names. |
| * @hide |
| */ |
| @SystemApi |
| @TestApi |
| public static String[] getOpStrs() { |
| return Arrays.copyOf(sOpToString, sOpToString.length); |
| } |
| |
| |
| /** |
| * @return number of App ops |
| * @hide |
| */ |
| @TestApi |
| public static int getNumOps() { |
| return _NUM_OP; |
| } |
| |
| /** |
| * @hide |
| */ |
| public static long maxTime(long[] times, int start, int end) { |
| long time = 0; |
| for (int i = start; i < end; i++) { |
| if (times[i] > time) { |
| time = times[i]; |
| } |
| } |
| return time; |
| } |
| } |