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