AppOpsManager.java revision 7b7c58b3842d47c4c8df4876e2e2248c58477d97
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.annotation.SystemApi;
20import android.app.usage.UsageStatsManager;
21import android.content.Context;
22import android.media.AudioAttributes.AttributeUsage;
23import android.os.Binder;
24import android.os.IBinder;
25import android.os.Parcel;
26import android.os.Parcelable;
27import android.os.Process;
28import android.os.RemoteException;
29import android.os.UserHandle;
30import android.os.UserManager;
31import android.util.ArrayMap;
32
33import com.android.internal.app.IAppOpsCallback;
34import com.android.internal.app.IAppOpsService;
35
36import java.util.ArrayList;
37import java.util.HashMap;
38import 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 */
48public 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) {
715                sOpStrToOp.put(sOpToString[i], i);
716            }
717        }
718    }
719
720    /**
721     * Retrieve the op switch that controls the given operation.
722     * @hide
723     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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
799        public PackageOps(String packageName, int uid, List<OpEntry> entries) {
800            mPackageName = packageName;
801            mUid = uid;
802            mEntries = entries;
803        }
804
805        public String getPackageName() {
806            return mPackageName;
807        }
808
809        public int getUid() {
810            return mUid;
811        }
812
813        public List<OpEntry> getOps() {
814            return mEntries;
815        }
816
817        @Override
818        public int describeContents() {
819            return 0;
820        }
821
822        @Override
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
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
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
872        public int getOp() {
873            return mOp;
874        }
875
876        public int getMode() {
877            return mMode;
878        }
879
880        public long getTime() {
881            return mTime;
882        }
883
884        public long getRejectTime() {
885            return mRejectTime;
886        }
887
888        public boolean isRunning() {
889            return mDuration == -1;
890        }
891
892        public int getDuration() {
893            return mDuration == -1 ? (int)(System.currentTimeMillis()-mTime) : mDuration;
894        }
895
896        @Override
897        public int describeContents() {
898            return 0;
899        }
900
901        @Override
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
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 {
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 {
942        public void onOpChanged(String op, String packageName) { }
943        public void onOpChanged(int op, String packageName) { }
944    }
945
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     */
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     */
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 */
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     */
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 */
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     */
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     */
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     */
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
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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 */
1310    public int noteOp(int op) {
1311        return noteOp(op, Process.myUid(), mContext.getOpPackageName());
1312    }
1313
1314    /** @hide */
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     */
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     */
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 */
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     */
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 */
1391    public void finishOp(int op) {
1392        finishOp(op, Process.myUid(), mContext.getOpPackageName());
1393    }
1394}
1395