1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.app;
18 
19 import android.annotation.SystemApi;
20 import android.app.usage.UsageStatsManager;
21 import android.content.Context;
22 import android.media.AudioAttributes.AttributeUsage;
23 import android.os.Binder;
24 import android.os.IBinder;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 import android.os.Process;
28 import android.os.RemoteException;
29 import android.os.UserHandle;
30 import android.os.UserManager;
31 import android.util.ArrayMap;
32 
33 import com.android.internal.app.IAppOpsCallback;
34 import com.android.internal.app.IAppOpsService;
35 
36 import java.util.ArrayList;
37 import java.util.HashMap;
38 import java.util.List;
39 
40 /**
41  * API for interacting with "application operation" tracking.
42  *
43  * <p>This API is not generally intended for third party application developers; most
44  * features are only available to system applications.  Obtain an instance of it through
45  * {@link Context#getSystemService(String) Context.getSystemService} with
46  * {@link Context#APP_OPS_SERVICE Context.APP_OPS_SERVICE}.</p>
47  */
48 public class AppOpsManager {
49     /**
50      * <p>App ops allows callers to:</p>
51      *
52      * <ul>
53      * <li> Note when operations are happening, and find out if they are allowed for the current
54      * caller.</li>
55      * <li> Disallow specific apps from doing specific operations.</li>
56      * <li> Collect all of the current information about operations that have been executed or
57      * are not being allowed.</li>
58      * <li> Monitor for changes in whether an operation is allowed.</li>
59      * </ul>
60      *
61      * <p>Each operation is identified by a single integer; these integers are a fixed set of
62      * operations, enumerated by the OP_* constants.
63      *
64      * <p></p>When checking operations, the result is a "mode" integer indicating the current
65      * setting for the operation under that caller: MODE_ALLOWED, MODE_IGNORED (don't execute
66      * the operation but fake its behavior enough so that the caller doesn't crash),
67      * MODE_ERRORED (throw a SecurityException back to the caller; the normal operation calls
68      * will do this for you).
69      */
70 
71     final Context mContext;
72     final IAppOpsService mService;
73     final ArrayMap<OnOpChangedListener, IAppOpsCallback> mModeWatchers
74             = new ArrayMap<OnOpChangedListener, IAppOpsCallback>();
75 
76     static IBinder sToken;
77 
78     /**
79      * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller is
80      * allowed to perform the given operation.
81      */
82     public static final int MODE_ALLOWED = 0;
83 
84     /**
85      * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller is
86      * not allowed to perform the given operation, and this attempt should
87      * <em>silently fail</em> (it should not cause the app to crash).
88      */
89     public static final int MODE_IGNORED = 1;
90 
91     /**
92      * Result from {@link #checkOpNoThrow}, {@link #noteOpNoThrow}, {@link #startOpNoThrow}: the
93      * given caller is not allowed to perform the given operation, and this attempt should
94      * cause it to have a fatal error, typically a {@link SecurityException}.
95      */
96     public static final int MODE_ERRORED = 2;
97 
98     /**
99      * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller should
100      * use its default security check.  This mode is not normally used; it should only be used
101      * with appop permissions, and callers must explicitly check for it and deal with it.
102      */
103     public static final int MODE_DEFAULT = 3;
104 
105     // when adding one of these:
106     //  - increment _NUM_OP
107     //  - add rows to sOpToSwitch, sOpToString, sOpNames, sOpPerms, sOpDefaultMode
108     //  - add descriptive strings to Settings/res/values/arrays.xml
109     //  - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app)
110 
111     /** @hide No operation specified. */
112     public static final int OP_NONE = -1;
113     /** @hide Access to coarse location information. */
114     public static final int OP_COARSE_LOCATION = 0;
115     /** @hide Access to fine location information. */
116     public static final int OP_FINE_LOCATION = 1;
117     /** @hide Causing GPS to run. */
118     public static final int OP_GPS = 2;
119     /** @hide */
120     public static final int OP_VIBRATE = 3;
121     /** @hide */
122     public static final int OP_READ_CONTACTS = 4;
123     /** @hide */
124     public static final int OP_WRITE_CONTACTS = 5;
125     /** @hide */
126     public static final int OP_READ_CALL_LOG = 6;
127     /** @hide */
128     public static final int OP_WRITE_CALL_LOG = 7;
129     /** @hide */
130     public static final int OP_READ_CALENDAR = 8;
131     /** @hide */
132     public static final int OP_WRITE_CALENDAR = 9;
133     /** @hide */
134     public static final int OP_WIFI_SCAN = 10;
135     /** @hide */
136     public static final int OP_POST_NOTIFICATION = 11;
137     /** @hide */
138     public static final int OP_NEIGHBORING_CELLS = 12;
139     /** @hide */
140     public static final int OP_CALL_PHONE = 13;
141     /** @hide */
142     public static final int OP_READ_SMS = 14;
143     /** @hide */
144     public static final int OP_WRITE_SMS = 15;
145     /** @hide */
146     public static final int OP_RECEIVE_SMS = 16;
147     /** @hide */
148     public static final int OP_RECEIVE_EMERGECY_SMS = 17;
149     /** @hide */
150     public static final int OP_RECEIVE_MMS = 18;
151     /** @hide */
152     public static final int OP_RECEIVE_WAP_PUSH = 19;
153     /** @hide */
154     public static final int OP_SEND_SMS = 20;
155     /** @hide */
156     public static final int OP_READ_ICC_SMS = 21;
157     /** @hide */
158     public static final int OP_WRITE_ICC_SMS = 22;
159     /** @hide */
160     public static final int OP_WRITE_SETTINGS = 23;
161     /** @hide */
162     public static final int OP_SYSTEM_ALERT_WINDOW = 24;
163     /** @hide */
164     public static final int OP_ACCESS_NOTIFICATIONS = 25;
165     /** @hide */
166     public static final int OP_CAMERA = 26;
167     /** @hide */
168     public static final int OP_RECORD_AUDIO = 27;
169     /** @hide */
170     public static final int OP_PLAY_AUDIO = 28;
171     /** @hide */
172     public static final int OP_READ_CLIPBOARD = 29;
173     /** @hide */
174     public static final int OP_WRITE_CLIPBOARD = 30;
175     /** @hide */
176     public static final int OP_TAKE_MEDIA_BUTTONS = 31;
177     /** @hide */
178     public static final int OP_TAKE_AUDIO_FOCUS = 32;
179     /** @hide */
180     public static final int OP_AUDIO_MASTER_VOLUME = 33;
181     /** @hide */
182     public static final int OP_AUDIO_VOICE_VOLUME = 34;
183     /** @hide */
184     public static final int OP_AUDIO_RING_VOLUME = 35;
185     /** @hide */
186     public static final int OP_AUDIO_MEDIA_VOLUME = 36;
187     /** @hide */
188     public static final int OP_AUDIO_ALARM_VOLUME = 37;
189     /** @hide */
190     public static final int OP_AUDIO_NOTIFICATION_VOLUME = 38;
191     /** @hide */
192     public static final int OP_AUDIO_BLUETOOTH_VOLUME = 39;
193     /** @hide */
194     public static final int OP_WAKE_LOCK = 40;
195     /** @hide Continually monitoring location data. */
196     public static final int OP_MONITOR_LOCATION = 41;
197     /** @hide Continually monitoring location data with a relatively high power request. */
198     public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42;
199     /** @hide Retrieve current usage stats via {@link UsageStatsManager}. */
200     public static final int OP_GET_USAGE_STATS = 43;
201     /** @hide */
202     public static final int OP_MUTE_MICROPHONE = 44;
203     /** @hide */
204     public static final int OP_TOAST_WINDOW = 45;
205     /** @hide Capture the device's display contents and/or audio */
206     public static final int OP_PROJECT_MEDIA = 46;
207     /** @hide Activate a VPN connection without user intervention. */
208     public static final int OP_ACTIVATE_VPN = 47;
209     /** @hide */
210     public static final int _NUM_OP = 48;
211 
212     /** Access to coarse location information. */
213     public static final String OPSTR_COARSE_LOCATION =
214             "android:coarse_location";
215     /** Access to fine location information. */
216     public static final String OPSTR_FINE_LOCATION =
217             "android:fine_location";
218     /** Continually monitoring location data. */
219     public static final String OPSTR_MONITOR_LOCATION
220             = "android:monitor_location";
221     /** Continually monitoring location data with a relatively high power request. */
222     public static final String OPSTR_MONITOR_HIGH_POWER_LOCATION
223             = "android:monitor_location_high_power";
224     /** Access to {@link android.app.usage.UsageStatsManager}. */
225     public static final String OPSTR_GET_USAGE_STATS
226             = "android:get_usage_stats";
227     /** Activate a VPN connection without user intervention. @hide */
228     @SystemApi
229     public static final String OPSTR_ACTIVATE_VPN = "android:activate_vpn";
230 
231     /**
232      * This maps each operation to the operation that serves as the
233      * switch to determine whether it is allowed.  Generally this is
234      * a 1:1 mapping, but for some things (like location) that have
235      * multiple low-level operations being tracked that should be
236      * presented to the user as one switch then this can be used to
237      * make them all controlled by the same single operation.
238      */
239     private static int[] sOpToSwitch = new int[] {
240             OP_COARSE_LOCATION,
241             OP_COARSE_LOCATION,
242             OP_COARSE_LOCATION,
243             OP_VIBRATE,
244             OP_READ_CONTACTS,
245             OP_WRITE_CONTACTS,
246             OP_READ_CALL_LOG,
247             OP_WRITE_CALL_LOG,
248             OP_READ_CALENDAR,
249             OP_WRITE_CALENDAR,
250             OP_COARSE_LOCATION,
251             OP_POST_NOTIFICATION,
252             OP_COARSE_LOCATION,
253             OP_CALL_PHONE,
254             OP_READ_SMS,
255             OP_WRITE_SMS,
256             OP_RECEIVE_SMS,
257             OP_RECEIVE_SMS,
258             OP_RECEIVE_SMS,
259             OP_RECEIVE_SMS,
260             OP_SEND_SMS,
261             OP_READ_SMS,
262             OP_WRITE_SMS,
263             OP_WRITE_SETTINGS,
264             OP_SYSTEM_ALERT_WINDOW,
265             OP_ACCESS_NOTIFICATIONS,
266             OP_CAMERA,
267             OP_RECORD_AUDIO,
268             OP_PLAY_AUDIO,
269             OP_READ_CLIPBOARD,
270             OP_WRITE_CLIPBOARD,
271             OP_TAKE_MEDIA_BUTTONS,
272             OP_TAKE_AUDIO_FOCUS,
273             OP_AUDIO_MASTER_VOLUME,
274             OP_AUDIO_VOICE_VOLUME,
275             OP_AUDIO_RING_VOLUME,
276             OP_AUDIO_MEDIA_VOLUME,
277             OP_AUDIO_ALARM_VOLUME,
278             OP_AUDIO_NOTIFICATION_VOLUME,
279             OP_AUDIO_BLUETOOTH_VOLUME,
280             OP_WAKE_LOCK,
281             OP_COARSE_LOCATION,
282             OP_COARSE_LOCATION,
283             OP_GET_USAGE_STATS,
284             OP_MUTE_MICROPHONE,
285             OP_TOAST_WINDOW,
286             OP_PROJECT_MEDIA,
287             OP_ACTIVATE_VPN,
288     };
289 
290     /**
291      * This maps each operation to the public string constant for it.
292      * If it doesn't have a public string constant, it maps to null.
293      */
294     private static String[] sOpToString = new String[] {
295             OPSTR_COARSE_LOCATION,
296             OPSTR_FINE_LOCATION,
297             null,
298             null,
299             null,
300             null,
301             null,
302             null,
303             null,
304             null,
305             null,
306             null,
307             null,
308             null,
309             null,
310             null,
311             null,
312             null,
313             null,
314             null,
315             null,
316             null,
317             null,
318             null,
319             null,
320             null,
321             null,
322             null,
323             null,
324             null,
325             null,
326             null,
327             null,
328             null,
329             null,
330             null,
331             null,
332             null,
333             null,
334             null,
335             null,
336             OPSTR_MONITOR_LOCATION,
337             OPSTR_MONITOR_HIGH_POWER_LOCATION,
338             OPSTR_GET_USAGE_STATS,
339             null,
340             null,
341             null,
342             OPSTR_ACTIVATE_VPN,
343     };
344 
345     /**
346      * This provides a simple name for each operation to be used
347      * in debug output.
348      */
349     private static String[] sOpNames = new String[] {
350             "COARSE_LOCATION",
351             "FINE_LOCATION",
352             "GPS",
353             "VIBRATE",
354             "READ_CONTACTS",
355             "WRITE_CONTACTS",
356             "READ_CALL_LOG",
357             "WRITE_CALL_LOG",
358             "READ_CALENDAR",
359             "WRITE_CALENDAR",
360             "WIFI_SCAN",
361             "POST_NOTIFICATION",
362             "NEIGHBORING_CELLS",
363             "CALL_PHONE",
364             "READ_SMS",
365             "WRITE_SMS",
366             "RECEIVE_SMS",
367             "RECEIVE_EMERGECY_SMS",
368             "RECEIVE_MMS",
369             "RECEIVE_WAP_PUSH",
370             "SEND_SMS",
371             "READ_ICC_SMS",
372             "WRITE_ICC_SMS",
373             "WRITE_SETTINGS",
374             "SYSTEM_ALERT_WINDOW",
375             "ACCESS_NOTIFICATIONS",
376             "CAMERA",
377             "RECORD_AUDIO",
378             "PLAY_AUDIO",
379             "READ_CLIPBOARD",
380             "WRITE_CLIPBOARD",
381             "TAKE_MEDIA_BUTTONS",
382             "TAKE_AUDIO_FOCUS",
383             "AUDIO_MASTER_VOLUME",
384             "AUDIO_VOICE_VOLUME",
385             "AUDIO_RING_VOLUME",
386             "AUDIO_MEDIA_VOLUME",
387             "AUDIO_ALARM_VOLUME",
388             "AUDIO_NOTIFICATION_VOLUME",
389             "AUDIO_BLUETOOTH_VOLUME",
390             "WAKE_LOCK",
391             "MONITOR_LOCATION",
392             "MONITOR_HIGH_POWER_LOCATION",
393             "GET_USAGE_STATS",
394             "MUTE_MICROPHONE",
395             "TOAST_WINDOW",
396             "PROJECT_MEDIA",
397             "ACTIVATE_VPN",
398     };
399 
400     /**
401      * This optionally maps a permission to an operation.  If there
402      * is no permission associated with an operation, it is null.
403      */
404     private static String[] sOpPerms = new String[] {
405             android.Manifest.permission.ACCESS_COARSE_LOCATION,
406             android.Manifest.permission.ACCESS_FINE_LOCATION,
407             null,
408             android.Manifest.permission.VIBRATE,
409             android.Manifest.permission.READ_CONTACTS,
410             android.Manifest.permission.WRITE_CONTACTS,
411             android.Manifest.permission.READ_CALL_LOG,
412             android.Manifest.permission.WRITE_CALL_LOG,
413             android.Manifest.permission.READ_CALENDAR,
414             android.Manifest.permission.WRITE_CALENDAR,
415             android.Manifest.permission.ACCESS_WIFI_STATE,
416             null, // no permission required for notifications
417             null, // neighboring cells shares the coarse location perm
418             android.Manifest.permission.CALL_PHONE,
419             android.Manifest.permission.READ_SMS,
420             android.Manifest.permission.WRITE_SMS,
421             android.Manifest.permission.RECEIVE_SMS,
422             android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST,
423             android.Manifest.permission.RECEIVE_MMS,
424             android.Manifest.permission.RECEIVE_WAP_PUSH,
425             android.Manifest.permission.SEND_SMS,
426             android.Manifest.permission.READ_SMS,
427             android.Manifest.permission.WRITE_SMS,
428             android.Manifest.permission.WRITE_SETTINGS,
429             android.Manifest.permission.SYSTEM_ALERT_WINDOW,
430             android.Manifest.permission.ACCESS_NOTIFICATIONS,
431             android.Manifest.permission.CAMERA,
432             android.Manifest.permission.RECORD_AUDIO,
433             null, // no permission for playing audio
434             null, // no permission for reading clipboard
435             null, // no permission for writing clipboard
436             null, // no permission for taking media buttons
437             null, // no permission for taking audio focus
438             null, // no permission for changing master volume
439             null, // no permission for changing voice volume
440             null, // no permission for changing ring volume
441             null, // no permission for changing media volume
442             null, // no permission for changing alarm volume
443             null, // no permission for changing notification volume
444             null, // no permission for changing bluetooth volume
445             android.Manifest.permission.WAKE_LOCK,
446             null, // no permission for generic location monitoring
447             null, // no permission for high power location monitoring
448             android.Manifest.permission.PACKAGE_USAGE_STATS,
449             null, // no permission for muting/unmuting microphone
450             null, // no permission for displaying toasts
451             null, // no permission for projecting media
452             null, // no permission for activating vpn
453     };
454 
455     /**
456      * Specifies whether an Op should be restricted by a user restriction.
457      * Each Op should be filled with a restriction string from UserManager or
458      * null to specify it is not affected by any user restriction.
459      */
460     private static String[] sOpRestrictions = new String[] {
461             UserManager.DISALLOW_SHARE_LOCATION, //COARSE_LOCATION
462             UserManager.DISALLOW_SHARE_LOCATION, //FINE_LOCATION
463             UserManager.DISALLOW_SHARE_LOCATION, //GPS
464             null, //VIBRATE
465             null, //READ_CONTACTS
466             null, //WRITE_CONTACTS
467             UserManager.DISALLOW_OUTGOING_CALLS, //READ_CALL_LOG
468             UserManager.DISALLOW_OUTGOING_CALLS, //WRITE_CALL_LOG
469             null, //READ_CALENDAR
470             null, //WRITE_CALENDAR
471             UserManager.DISALLOW_SHARE_LOCATION, //WIFI_SCAN
472             null, //POST_NOTIFICATION
473             null, //NEIGHBORING_CELLS
474             null, //CALL_PHONE
475             UserManager.DISALLOW_SMS, //READ_SMS
476             UserManager.DISALLOW_SMS, //WRITE_SMS
477             UserManager.DISALLOW_SMS, //RECEIVE_SMS
478             null, //RECEIVE_EMERGENCY_SMS
479             UserManager.DISALLOW_SMS, //RECEIVE_MMS
480             null, //RECEIVE_WAP_PUSH
481             UserManager.DISALLOW_SMS, //SEND_SMS
482             UserManager.DISALLOW_SMS, //READ_ICC_SMS
483             UserManager.DISALLOW_SMS, //WRITE_ICC_SMS
484             null, //WRITE_SETTINGS
485             UserManager.DISALLOW_CREATE_WINDOWS, //SYSTEM_ALERT_WINDOW
486             null, //ACCESS_NOTIFICATIONS
487             null, //CAMERA
488             null, //RECORD_AUDIO
489             null, //PLAY_AUDIO
490             null, //READ_CLIPBOARD
491             null, //WRITE_CLIPBOARD
492             null, //TAKE_MEDIA_BUTTONS
493             null, //TAKE_AUDIO_FOCUS
494             UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_MASTER_VOLUME
495             UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_VOICE_VOLUME
496             UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_RING_VOLUME
497             UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_MEDIA_VOLUME
498             UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_ALARM_VOLUME
499             UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_NOTIFICATION_VOLUME
500             UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_BLUETOOTH_VOLUME
501             null, //WAKE_LOCK
502             UserManager.DISALLOW_SHARE_LOCATION, //MONITOR_LOCATION
503             UserManager.DISALLOW_SHARE_LOCATION, //MONITOR_HIGH_POWER_LOCATION
504             null, //GET_USAGE_STATS
505             UserManager.DISALLOW_UNMUTE_MICROPHONE, // MUTE_MICROPHONE
506             UserManager.DISALLOW_CREATE_WINDOWS, // TOAST_WINDOW
507             null, //PROJECT_MEDIA
508             UserManager.DISALLOW_CONFIG_VPN, // ACTIVATE_VPN
509     };
510 
511     /**
512      * This specifies whether each option should allow the system
513      * (and system ui) to bypass the user restriction when active.
514      */
515     private static boolean[] sOpAllowSystemRestrictionBypass = new boolean[] {
516             false, //COARSE_LOCATION
517             false, //FINE_LOCATION
518             false, //GPS
519             false, //VIBRATE
520             false, //READ_CONTACTS
521             false, //WRITE_CONTACTS
522             false, //READ_CALL_LOG
523             false, //WRITE_CALL_LOG
524             false, //READ_CALENDAR
525             false, //WRITE_CALENDAR
526             true, //WIFI_SCAN
527             false, //POST_NOTIFICATION
528             false, //NEIGHBORING_CELLS
529             false, //CALL_PHONE
530             false, //READ_SMS
531             false, //WRITE_SMS
532             false, //RECEIVE_SMS
533             false, //RECEIVE_EMERGECY_SMS
534             false, //RECEIVE_MMS
535             false, //RECEIVE_WAP_PUSH
536             false, //SEND_SMS
537             false, //READ_ICC_SMS
538             false, //WRITE_ICC_SMS
539             false, //WRITE_SETTINGS
540             true, //SYSTEM_ALERT_WINDOW
541             false, //ACCESS_NOTIFICATIONS
542             false, //CAMERA
543             false, //RECORD_AUDIO
544             false, //PLAY_AUDIO
545             false, //READ_CLIPBOARD
546             false, //WRITE_CLIPBOARD
547             false, //TAKE_MEDIA_BUTTONS
548             false, //TAKE_AUDIO_FOCUS
549             false, //AUDIO_MASTER_VOLUME
550             false, //AUDIO_VOICE_VOLUME
551             false, //AUDIO_RING_VOLUME
552             false, //AUDIO_MEDIA_VOLUME
553             false, //AUDIO_ALARM_VOLUME
554             false, //AUDIO_NOTIFICATION_VOLUME
555             false, //AUDIO_BLUETOOTH_VOLUME
556             false, //WAKE_LOCK
557             false, //MONITOR_LOCATION
558             false, //MONITOR_HIGH_POWER_LOCATION
559             false, //GET_USAGE_STATS
560             false, //MUTE_MICROPHONE
561             true, //TOAST_WINDOW
562             false, //PROJECT_MEDIA
563             false, //ACTIVATE_VPN
564     };
565 
566     /**
567      * This specifies the default mode for each operation.
568      */
569     private static int[] sOpDefaultMode = new int[] {
570             AppOpsManager.MODE_ALLOWED,
571             AppOpsManager.MODE_ALLOWED,
572             AppOpsManager.MODE_ALLOWED,
573             AppOpsManager.MODE_ALLOWED,
574             AppOpsManager.MODE_ALLOWED,
575             AppOpsManager.MODE_ALLOWED,
576             AppOpsManager.MODE_ALLOWED,
577             AppOpsManager.MODE_ALLOWED,
578             AppOpsManager.MODE_ALLOWED,
579             AppOpsManager.MODE_ALLOWED,
580             AppOpsManager.MODE_ALLOWED,
581             AppOpsManager.MODE_ALLOWED,
582             AppOpsManager.MODE_ALLOWED,
583             AppOpsManager.MODE_ALLOWED,
584             AppOpsManager.MODE_ALLOWED,
585             AppOpsManager.MODE_IGNORED, // OP_WRITE_SMS
586             AppOpsManager.MODE_ALLOWED,
587             AppOpsManager.MODE_ALLOWED,
588             AppOpsManager.MODE_ALLOWED,
589             AppOpsManager.MODE_ALLOWED,
590             AppOpsManager.MODE_ALLOWED,
591             AppOpsManager.MODE_ALLOWED,
592             AppOpsManager.MODE_ALLOWED,
593             AppOpsManager.MODE_ALLOWED,
594             AppOpsManager.MODE_ALLOWED,
595             AppOpsManager.MODE_ALLOWED,
596             AppOpsManager.MODE_ALLOWED,
597             AppOpsManager.MODE_ALLOWED,
598             AppOpsManager.MODE_ALLOWED,
599             AppOpsManager.MODE_ALLOWED,
600             AppOpsManager.MODE_ALLOWED,
601             AppOpsManager.MODE_ALLOWED,
602             AppOpsManager.MODE_ALLOWED,
603             AppOpsManager.MODE_ALLOWED,
604             AppOpsManager.MODE_ALLOWED,
605             AppOpsManager.MODE_ALLOWED,
606             AppOpsManager.MODE_ALLOWED,
607             AppOpsManager.MODE_ALLOWED,
608             AppOpsManager.MODE_ALLOWED,
609             AppOpsManager.MODE_ALLOWED,
610             AppOpsManager.MODE_ALLOWED,
611             AppOpsManager.MODE_ALLOWED,
612             AppOpsManager.MODE_ALLOWED,
613             AppOpsManager.MODE_DEFAULT, // OP_GET_USAGE_STATS
614             AppOpsManager.MODE_ALLOWED,
615             AppOpsManager.MODE_ALLOWED,
616             AppOpsManager.MODE_IGNORED, // OP_PROJECT_MEDIA
617             AppOpsManager.MODE_IGNORED, // OP_ACTIVATE_VPN
618     };
619 
620     /**
621      * This specifies whether each option is allowed to be reset
622      * when resetting all app preferences.  Disable reset for
623      * app ops that are under strong control of some part of the
624      * system (such as OP_WRITE_SMS, which should be allowed only
625      * for whichever app is selected as the current SMS app).
626      */
627     private static boolean[] sOpDisableReset = new boolean[] {
628             false,
629             false,
630             false,
631             false,
632             false,
633             false,
634             false,
635             false,
636             false,
637             false,
638             false,
639             false,
640             false,
641             false,
642             false,
643             true,      // OP_WRITE_SMS
644             false,
645             false,
646             false,
647             false,
648             false,
649             false,
650             false,
651             false,
652             false,
653             false,
654             false,
655             false,
656             false,
657             false,
658             false,
659             false,
660             false,
661             false,
662             false,
663             false,
664             false,
665             false,
666             false,
667             false,
668             false,
669             false,
670             false,
671             false,
672             false,
673             false,
674             false,
675             false,
676     };
677 
678     private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>();
679 
680     static {
681         if (sOpToSwitch.length != _NUM_OP) {
682             throw new IllegalStateException("sOpToSwitch length " + sOpToSwitch.length
683                     + " should be " + _NUM_OP);
684         }
685         if (sOpToString.length != _NUM_OP) {
686             throw new IllegalStateException("sOpToString length " + sOpToString.length
687                     + " should be " + _NUM_OP);
688         }
689         if (sOpNames.length != _NUM_OP) {
690             throw new IllegalStateException("sOpNames length " + sOpNames.length
691                     + " should be " + _NUM_OP);
692         }
693         if (sOpPerms.length != _NUM_OP) {
694             throw new IllegalStateException("sOpPerms length " + sOpPerms.length
695                     + " should be " + _NUM_OP);
696         }
697         if (sOpDefaultMode.length != _NUM_OP) {
698             throw new IllegalStateException("sOpDefaultMode length " + sOpDefaultMode.length
699                     + " should be " + _NUM_OP);
700         }
701         if (sOpDisableReset.length != _NUM_OP) {
702             throw new IllegalStateException("sOpDisableReset length " + sOpDisableReset.length
703                     + " should be " + _NUM_OP);
704         }
705         if (sOpRestrictions.length != _NUM_OP) {
706             throw new IllegalStateException("sOpRestrictions length " + sOpRestrictions.length
707                     + " should be " + _NUM_OP);
708         }
709         if (sOpAllowSystemRestrictionBypass.length != _NUM_OP) {
710             throw new IllegalStateException("sOpAllowSYstemRestrictionsBypass length "
711                     + sOpRestrictions.length + " should be " + _NUM_OP);
712         }
713         for (int i=0; i<_NUM_OP; i++) {
714             if (sOpToString[i] != null) {
sOpStrToOp.put(sOpToString[i], i)715                 sOpStrToOp.put(sOpToString[i], i);
716             }
717         }
718     }
719 
720     /**
721      * Retrieve the op switch that controls the given operation.
722      * @hide
723      */
opToSwitch(int op)724     public static int opToSwitch(int op) {
725         return sOpToSwitch[op];
726     }
727 
728     /**
729      * Retrieve a non-localized name for the operation, for debugging output.
730      * @hide
731      */
opToName(int op)732     public static String opToName(int op) {
733         if (op == OP_NONE) return "NONE";
734         return op < sOpNames.length ? sOpNames[op] : ("Unknown(" + op + ")");
735     }
736 
737     /**
738      * @hide
739      */
strDebugOpToOp(String op)740     public static int strDebugOpToOp(String op) {
741         for (int i=0; i<sOpNames.length; i++) {
742             if (sOpNames[i].equals(op)) {
743                 return i;
744             }
745         }
746         throw new IllegalArgumentException("Unknown operation string: " + op);
747     }
748 
749     /**
750      * Retrieve the permission associated with an operation, or null if there is not one.
751      * @hide
752      */
opToPermission(int op)753     public static String opToPermission(int op) {
754         return sOpPerms[op];
755     }
756 
757     /**
758      * Retrieve the user restriction associated with an operation, or null if there is not one.
759      * @hide
760      */
opToRestriction(int op)761     public static String opToRestriction(int op) {
762         return sOpRestrictions[op];
763     }
764 
765     /**
766      * Retrieve whether the op allows the system (and system ui) to
767      * bypass the user restriction.
768      * @hide
769      */
opAllowSystemBypassRestriction(int op)770     public static boolean opAllowSystemBypassRestriction(int op) {
771         return sOpAllowSystemRestrictionBypass[op];
772     }
773 
774     /**
775      * Retrieve the default mode for the operation.
776      * @hide
777      */
opToDefaultMode(int op)778     public static int opToDefaultMode(int op) {
779         return sOpDefaultMode[op];
780     }
781 
782     /**
783      * Retrieve whether the op allows itself to be reset.
784      * @hide
785      */
opAllowsReset(int op)786     public static boolean opAllowsReset(int op) {
787         return !sOpDisableReset[op];
788     }
789 
790     /**
791      * Class holding all of the operation information associated with an app.
792      * @hide
793      */
794     public static class PackageOps implements Parcelable {
795         private final String mPackageName;
796         private final int mUid;
797         private final List<OpEntry> mEntries;
798 
PackageOps(String packageName, int uid, List<OpEntry> entries)799         public PackageOps(String packageName, int uid, List<OpEntry> entries) {
800             mPackageName = packageName;
801             mUid = uid;
802             mEntries = entries;
803         }
804 
getPackageName()805         public String getPackageName() {
806             return mPackageName;
807         }
808 
getUid()809         public int getUid() {
810             return mUid;
811         }
812 
getOps()813         public List<OpEntry> getOps() {
814             return mEntries;
815         }
816 
817         @Override
describeContents()818         public int describeContents() {
819             return 0;
820         }
821 
822         @Override
writeToParcel(Parcel dest, int flags)823         public void writeToParcel(Parcel dest, int flags) {
824             dest.writeString(mPackageName);
825             dest.writeInt(mUid);
826             dest.writeInt(mEntries.size());
827             for (int i=0; i<mEntries.size(); i++) {
828                 mEntries.get(i).writeToParcel(dest, flags);
829             }
830         }
831 
PackageOps(Parcel source)832         PackageOps(Parcel source) {
833             mPackageName = source.readString();
834             mUid = source.readInt();
835             mEntries = new ArrayList<OpEntry>();
836             final int N = source.readInt();
837             for (int i=0; i<N; i++) {
838                 mEntries.add(OpEntry.CREATOR.createFromParcel(source));
839             }
840         }
841 
842         public static final Creator<PackageOps> CREATOR = new Creator<PackageOps>() {
843             @Override public PackageOps createFromParcel(Parcel source) {
844                 return new PackageOps(source);
845             }
846 
847             @Override public PackageOps[] newArray(int size) {
848                 return new PackageOps[size];
849             }
850         };
851     }
852 
853     /**
854      * Class holding the information about one unique operation of an application.
855      * @hide
856      */
857     public static class OpEntry implements Parcelable {
858         private final int mOp;
859         private final int mMode;
860         private final long mTime;
861         private final long mRejectTime;
862         private final int mDuration;
863 
OpEntry(int op, int mode, long time, long rejectTime, int duration)864         public OpEntry(int op, int mode, long time, long rejectTime, int duration) {
865             mOp = op;
866             mMode = mode;
867             mTime = time;
868             mRejectTime = rejectTime;
869             mDuration = duration;
870         }
871 
getOp()872         public int getOp() {
873             return mOp;
874         }
875 
getMode()876         public int getMode() {
877             return mMode;
878         }
879 
getTime()880         public long getTime() {
881             return mTime;
882         }
883 
getRejectTime()884         public long getRejectTime() {
885             return mRejectTime;
886         }
887 
isRunning()888         public boolean isRunning() {
889             return mDuration == -1;
890         }
891 
getDuration()892         public int getDuration() {
893             return mDuration == -1 ? (int)(System.currentTimeMillis()-mTime) : mDuration;
894         }
895 
896         @Override
describeContents()897         public int describeContents() {
898             return 0;
899         }
900 
901         @Override
writeToParcel(Parcel dest, int flags)902         public void writeToParcel(Parcel dest, int flags) {
903             dest.writeInt(mOp);
904             dest.writeInt(mMode);
905             dest.writeLong(mTime);
906             dest.writeLong(mRejectTime);
907             dest.writeInt(mDuration);
908         }
909 
OpEntry(Parcel source)910         OpEntry(Parcel source) {
911             mOp = source.readInt();
912             mMode = source.readInt();
913             mTime = source.readLong();
914             mRejectTime = source.readLong();
915             mDuration = source.readInt();
916         }
917 
918         public static final Creator<OpEntry> CREATOR = new Creator<OpEntry>() {
919             @Override public OpEntry createFromParcel(Parcel source) {
920                 return new OpEntry(source);
921             }
922 
923             @Override public OpEntry[] newArray(int size) {
924                 return new OpEntry[size];
925             }
926         };
927     }
928 
929     /**
930      * Callback for notification of changes to operation state.
931      */
932     public interface OnOpChangedListener {
onOpChanged(String op, String packageName)933         public void onOpChanged(String op, String packageName);
934     }
935 
936     /**
937      * Callback for notification of changes to operation state.
938      * This allows you to see the raw op codes instead of strings.
939      * @hide
940      */
941     public static class OnOpChangedInternalListener implements OnOpChangedListener {
onOpChanged(String op, String packageName)942         public void onOpChanged(String op, String packageName) { }
onOpChanged(int op, String packageName)943         public void onOpChanged(int op, String packageName) { }
944     }
945 
AppOpsManager(Context context, IAppOpsService service)946     AppOpsManager(Context context, IAppOpsService service) {
947         mContext = context;
948         mService = service;
949     }
950 
951     /**
952      * Retrieve current operation state for all applications.
953      *
954      * @param ops The set of operations you are interested in, or null if you want all of them.
955      * @hide
956      */
getPackagesForOps(int[] ops)957     public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
958         try {
959             return mService.getPackagesForOps(ops);
960         } catch (RemoteException e) {
961         }
962         return null;
963     }
964 
965     /**
966      * Retrieve current operation state for one application.
967      *
968      * @param uid The uid of the application of interest.
969      * @param packageName The name of the application of interest.
970      * @param ops The set of operations you are interested in, or null if you want all of them.
971      * @hide
972      */
getOpsForPackage(int uid, String packageName, int[] ops)973     public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, int[] ops) {
974         try {
975             return mService.getOpsForPackage(uid, packageName, ops);
976         } catch (RemoteException e) {
977         }
978         return null;
979     }
980 
981     /** @hide */
setMode(int code, int uid, String packageName, int mode)982     public void setMode(int code, int uid, String packageName, int mode) {
983         try {
984             mService.setMode(code, uid, packageName, mode);
985         } catch (RemoteException e) {
986         }
987     }
988 
989     /**
990      * Set a non-persisted restriction on an audio operation at a stream-level.
991      * Restrictions are temporary additional constraints imposed on top of the persisted rules
992      * defined by {@link #setMode}.
993      *
994      * @param code The operation to restrict.
995      * @param usage The {@link android.media.AudioAttributes} usage value.
996      * @param mode The restriction mode (MODE_IGNORED,MODE_ERRORED) or MODE_ALLOWED to unrestrict.
997      * @param exceptionPackages Optional list of packages to exclude from the restriction.
998      * @hide
999      */
setRestriction(int code, @AttributeUsage int usage, int mode, String[] exceptionPackages)1000     public void setRestriction(int code, @AttributeUsage int usage, int mode,
1001             String[] exceptionPackages) {
1002         try {
1003             final int uid = Binder.getCallingUid();
1004             mService.setAudioRestriction(code, usage, uid, mode, exceptionPackages);
1005         } catch (RemoteException e) {
1006         }
1007     }
1008 
1009     /** @hide */
resetAllModes()1010     public void resetAllModes() {
1011         try {
1012             mService.resetAllModes(UserHandle.myUserId(), null);
1013         } catch (RemoteException e) {
1014         }
1015     }
1016 
1017     /**
1018      * Monitor for changes to the operating mode for the given op in the given app package.
1019      * @param op The operation to monitor, one of OPSTR_*.
1020      * @param packageName The name of the application to monitor.
1021      * @param callback Where to report changes.
1022      */
startWatchingMode(String op, String packageName, final OnOpChangedListener callback)1023     public void startWatchingMode(String op, String packageName,
1024             final OnOpChangedListener callback) {
1025         startWatchingMode(strOpToOp(op), packageName, callback);
1026     }
1027 
1028     /**
1029      * Monitor for changes to the operating mode for the given op in the given app package.
1030      * @param op The operation to monitor, one of OP_*.
1031      * @param packageName The name of the application to monitor.
1032      * @param callback Where to report changes.
1033      * @hide
1034      */
startWatchingMode(int op, String packageName, final OnOpChangedListener callback)1035     public void startWatchingMode(int op, String packageName, final OnOpChangedListener callback) {
1036         synchronized (mModeWatchers) {
1037             IAppOpsCallback cb = mModeWatchers.get(callback);
1038             if (cb == null) {
1039                 cb = new IAppOpsCallback.Stub() {
1040                     public void opChanged(int op, String packageName) {
1041                         if (callback instanceof OnOpChangedInternalListener) {
1042                             ((OnOpChangedInternalListener)callback).onOpChanged(op, packageName);
1043                         }
1044                         if (sOpToString[op] != null) {
1045                             callback.onOpChanged(sOpToString[op], packageName);
1046                         }
1047                     }
1048                 };
1049                 mModeWatchers.put(callback, cb);
1050             }
1051             try {
1052                 mService.startWatchingMode(op, packageName, cb);
1053             } catch (RemoteException e) {
1054             }
1055         }
1056     }
1057 
1058     /**
1059      * Stop monitoring that was previously started with {@link #startWatchingMode}.  All
1060      * monitoring associated with this callback will be removed.
1061      */
stopWatchingMode(OnOpChangedListener callback)1062     public void stopWatchingMode(OnOpChangedListener callback) {
1063         synchronized (mModeWatchers) {
1064             IAppOpsCallback cb = mModeWatchers.get(callback);
1065             if (cb != null) {
1066                 try {
1067                     mService.stopWatchingMode(cb);
1068                 } catch (RemoteException e) {
1069                 }
1070             }
1071         }
1072     }
1073 
buildSecurityExceptionMsg(int op, int uid, String packageName)1074     private String buildSecurityExceptionMsg(int op, int uid, String packageName) {
1075         return packageName + " from uid " + uid + " not allowed to perform " + sOpNames[op];
1076     }
1077 
1078     /**
1079      * {@hide}
1080      */
strOpToOp(String op)1081     public static int strOpToOp(String op) {
1082         Integer val = sOpStrToOp.get(op);
1083         if (val == null) {
1084             throw new IllegalArgumentException("Unknown operation string: " + op);
1085         }
1086         return val;
1087     }
1088 
1089     /**
1090      * Do a quick check for whether an application might be able to perform an operation.
1091      * This is <em>not</em> a security check; you must use {@link #noteOp(String, int, String)}
1092      * or {@link #startOp(String, int, String)} for your actual security checks, which also
1093      * ensure that the given uid and package name are consistent.  This function can just be
1094      * used for a quick check to see if an operation has been disabled for the application,
1095      * as an early reject of some work.  This does not modify the time stamp or other data
1096      * about the operation.
1097      * @param op The operation to check.  One of the OPSTR_* constants.
1098      * @param uid The user id of the application attempting to perform the operation.
1099      * @param packageName The name of the application attempting to perform the operation.
1100      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
1101      * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
1102      * causing the app to crash).
1103      * @throws SecurityException If the app has been configured to crash on this op.
1104      */
checkOp(String op, int uid, String packageName)1105     public int checkOp(String op, int uid, String packageName) {
1106         return checkOp(strOpToOp(op), uid, packageName);
1107     }
1108 
1109     /**
1110      * Like {@link #checkOp} but instead of throwing a {@link SecurityException} it
1111      * returns {@link #MODE_ERRORED}.
1112      */
checkOpNoThrow(String op, int uid, String packageName)1113     public int checkOpNoThrow(String op, int uid, String packageName) {
1114         return checkOpNoThrow(strOpToOp(op), uid, packageName);
1115     }
1116 
1117     /**
1118      * Make note of an application performing an operation.  Note that you must pass
1119      * in both the uid and name of the application to be checked; this function will verify
1120      * that these two match, and if not, return {@link #MODE_IGNORED}.  If this call
1121      * succeeds, the last execution time of the operation for this app will be updated to
1122      * the current time.
1123      * @param op The operation to note.  One of the OPSTR_* constants.
1124      * @param uid The user id of the application attempting to perform the operation.
1125      * @param packageName The name of the application attempting to perform the operation.
1126      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
1127      * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
1128      * causing the app to crash).
1129      * @throws SecurityException If the app has been configured to crash on this op.
1130      */
noteOp(String op, int uid, String packageName)1131     public int noteOp(String op, int uid, String packageName) {
1132         return noteOp(strOpToOp(op), uid, packageName);
1133     }
1134 
1135     /**
1136      * Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
1137      * returns {@link #MODE_ERRORED}.
1138      */
noteOpNoThrow(String op, int uid, String packageName)1139     public int noteOpNoThrow(String op, int uid, String packageName) {
1140         return noteOpNoThrow(strOpToOp(op), uid, packageName);
1141     }
1142 
1143     /**
1144      * Report that an application has started executing a long-running operation.  Note that you
1145      * must pass in both the uid and name of the application to be checked; this function will
1146      * verify that these two match, and if not, return {@link #MODE_IGNORED}.  If this call
1147      * succeeds, the last execution time of the operation for this app will be updated to
1148      * the current time and the operation will be marked as "running".  In this case you must
1149      * later call {@link #finishOp(String, int, String)} to report when the application is no
1150      * longer performing the operation.
1151      * @param op The operation to start.  One of the OPSTR_* constants.
1152      * @param uid The user id of the application attempting to perform the operation.
1153      * @param packageName The name of the application attempting to perform the operation.
1154      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
1155      * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
1156      * causing the app to crash).
1157      * @throws SecurityException If the app has been configured to crash on this op.
1158      */
startOp(String op, int uid, String packageName)1159     public int startOp(String op, int uid, String packageName) {
1160         return startOp(strOpToOp(op), uid, packageName);
1161     }
1162 
1163     /**
1164      * Like {@link #startOp} but instead of throwing a {@link SecurityException} it
1165      * returns {@link #MODE_ERRORED}.
1166      */
startOpNoThrow(String op, int uid, String packageName)1167     public int startOpNoThrow(String op, int uid, String packageName) {
1168         return startOpNoThrow(strOpToOp(op), uid, packageName);
1169     }
1170 
1171     /**
1172      * Report that an application is no longer performing an operation that had previously
1173      * been started with {@link #startOp(String, int, String)}.  There is no validation of input
1174      * or result; the parameters supplied here must be the exact same ones previously passed
1175      * in when starting the operation.
1176      */
finishOp(String op, int uid, String packageName)1177     public void finishOp(String op, int uid, String packageName) {
1178         finishOp(strOpToOp(op), uid, packageName);
1179     }
1180 
1181     /**
1182      * Do a quick check for whether an application might be able to perform an operation.
1183      * This is <em>not</em> a security check; you must use {@link #noteOp(int, int, String)}
1184      * or {@link #startOp(int, int, String)} for your actual security checks, which also
1185      * ensure that the given uid and package name are consistent.  This function can just be
1186      * used for a quick check to see if an operation has been disabled for the application,
1187      * as an early reject of some work.  This does not modify the time stamp or other data
1188      * about the operation.
1189      * @param op The operation to check.  One of the OP_* constants.
1190      * @param uid The user id of the application attempting to perform the operation.
1191      * @param packageName The name of the application attempting to perform the operation.
1192      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
1193      * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
1194      * causing the app to crash).
1195      * @throws SecurityException If the app has been configured to crash on this op.
1196      * @hide
1197      */
checkOp(int op, int uid, String packageName)1198     public int checkOp(int op, int uid, String packageName) {
1199         try {
1200             int mode = mService.checkOperation(op, uid, packageName);
1201             if (mode == MODE_ERRORED) {
1202                 throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
1203             }
1204             return mode;
1205         } catch (RemoteException e) {
1206         }
1207         return MODE_IGNORED;
1208     }
1209 
1210     /**
1211      * Like {@link #checkOp} but instead of throwing a {@link SecurityException} it
1212      * returns {@link #MODE_ERRORED}.
1213      * @hide
1214      */
checkOpNoThrow(int op, int uid, String packageName)1215     public int checkOpNoThrow(int op, int uid, String packageName) {
1216         try {
1217             return mService.checkOperation(op, uid, packageName);
1218         } catch (RemoteException e) {
1219         }
1220         return MODE_IGNORED;
1221     }
1222 
1223     /**
1224      * Do a quick check to validate if a package name belongs to a UID.
1225      *
1226      * @throws SecurityException if the package name doesn't belong to the given
1227      *             UID, or if ownership cannot be verified.
1228      */
checkPackage(int uid, String packageName)1229     public void checkPackage(int uid, String packageName) {
1230         try {
1231             if (mService.checkPackage(uid, packageName) != MODE_ALLOWED) {
1232                 throw new SecurityException(
1233                         "Package " + packageName + " does not belong to " + uid);
1234             }
1235         } catch (RemoteException e) {
1236             throw new SecurityException("Unable to verify package ownership", e);
1237         }
1238     }
1239 
1240     /**
1241      * Like {@link #checkOp} but at a stream-level for audio operations.
1242      * @hide
1243      */
checkAudioOp(int op, int stream, int uid, String packageName)1244     public int checkAudioOp(int op, int stream, int uid, String packageName) {
1245         try {
1246             final int mode = mService.checkAudioOperation(op, stream, uid, packageName);
1247             if (mode == MODE_ERRORED) {
1248                 throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
1249             }
1250             return mode;
1251         } catch (RemoteException e) {
1252         }
1253         return MODE_IGNORED;
1254     }
1255 
1256     /**
1257      * Like {@link #checkAudioOp} but instead of throwing a {@link SecurityException} it
1258      * returns {@link #MODE_ERRORED}.
1259      * @hide
1260      */
checkAudioOpNoThrow(int op, int stream, int uid, String packageName)1261     public int checkAudioOpNoThrow(int op, int stream, int uid, String packageName) {
1262         try {
1263             return mService.checkAudioOperation(op, stream, uid, packageName);
1264         } catch (RemoteException e) {
1265         }
1266         return MODE_IGNORED;
1267     }
1268 
1269     /**
1270      * Make note of an application performing an operation.  Note that you must pass
1271      * in both the uid and name of the application to be checked; this function will verify
1272      * that these two match, and if not, return {@link #MODE_IGNORED}.  If this call
1273      * succeeds, the last execution time of the operation for this app will be updated to
1274      * the current time.
1275      * @param op The operation to note.  One of the OP_* constants.
1276      * @param uid The user id of the application attempting to perform the operation.
1277      * @param packageName The name of the application attempting to perform the operation.
1278      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
1279      * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
1280      * causing the app to crash).
1281      * @throws SecurityException If the app has been configured to crash on this op.
1282      * @hide
1283      */
noteOp(int op, int uid, String packageName)1284     public int noteOp(int op, int uid, String packageName) {
1285         try {
1286             int mode = mService.noteOperation(op, uid, packageName);
1287             if (mode == MODE_ERRORED) {
1288                 throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
1289             }
1290             return mode;
1291         } catch (RemoteException e) {
1292         }
1293         return MODE_IGNORED;
1294     }
1295 
1296     /**
1297      * Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
1298      * returns {@link #MODE_ERRORED}.
1299      * @hide
1300      */
noteOpNoThrow(int op, int uid, String packageName)1301     public int noteOpNoThrow(int op, int uid, String packageName) {
1302         try {
1303             return mService.noteOperation(op, uid, packageName);
1304         } catch (RemoteException e) {
1305         }
1306         return MODE_IGNORED;
1307     }
1308 
1309     /** @hide */
noteOp(int op)1310     public int noteOp(int op) {
1311         return noteOp(op, Process.myUid(), mContext.getOpPackageName());
1312     }
1313 
1314     /** @hide */
getToken(IAppOpsService service)1315     public static IBinder getToken(IAppOpsService service) {
1316         synchronized (AppOpsManager.class) {
1317             if (sToken != null) {
1318                 return sToken;
1319             }
1320             try {
1321                 sToken = service.getToken(new Binder());
1322             } catch (RemoteException e) {
1323                 // System is dead, whatevs.
1324             }
1325             return sToken;
1326         }
1327     }
1328 
1329     /**
1330      * Report that an application has started executing a long-running operation.  Note that you
1331      * must pass in both the uid and name of the application to be checked; this function will
1332      * verify that these two match, and if not, return {@link #MODE_IGNORED}.  If this call
1333      * succeeds, the last execution time of the operation for this app will be updated to
1334      * the current time and the operation will be marked as "running".  In this case you must
1335      * later call {@link #finishOp(int, int, String)} to report when the application is no
1336      * longer performing the operation.
1337      * @param op The operation to start.  One of the OP_* constants.
1338      * @param uid The user id of the application attempting to perform the operation.
1339      * @param packageName The name of the application attempting to perform the operation.
1340      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
1341      * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
1342      * causing the app to crash).
1343      * @throws SecurityException If the app has been configured to crash on this op.
1344      * @hide
1345      */
startOp(int op, int uid, String packageName)1346     public int startOp(int op, int uid, String packageName) {
1347         try {
1348             int mode = mService.startOperation(getToken(mService), op, uid, packageName);
1349             if (mode == MODE_ERRORED) {
1350                 throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
1351             }
1352             return mode;
1353         } catch (RemoteException e) {
1354         }
1355         return MODE_IGNORED;
1356     }
1357 
1358     /**
1359      * Like {@link #startOp} but instead of throwing a {@link SecurityException} it
1360      * returns {@link #MODE_ERRORED}.
1361      * @hide
1362      */
startOpNoThrow(int op, int uid, String packageName)1363     public int startOpNoThrow(int op, int uid, String packageName) {
1364         try {
1365             return mService.startOperation(getToken(mService), op, uid, packageName);
1366         } catch (RemoteException e) {
1367         }
1368         return MODE_IGNORED;
1369     }
1370 
1371     /** @hide */
startOp(int op)1372     public int startOp(int op) {
1373         return startOp(op, Process.myUid(), mContext.getOpPackageName());
1374     }
1375 
1376     /**
1377      * Report that an application is no longer performing an operation that had previously
1378      * been started with {@link #startOp(int, int, String)}.  There is no validation of input
1379      * or result; the parameters supplied here must be the exact same ones previously passed
1380      * in when starting the operation.
1381      * @hide
1382      */
finishOp(int op, int uid, String packageName)1383     public void finishOp(int op, int uid, String packageName) {
1384         try {
1385             mService.finishOperation(getToken(mService), op, uid, packageName);
1386         } catch (RemoteException e) {
1387         }
1388     }
1389 
1390     /** @hide */
finishOp(int op)1391     public void finishOp(int op) {
1392         finishOp(op, Process.myUid(), mContext.getOpPackageName());
1393     }
1394 }
1395