AppOpsManager.java revision f5d831915dd11e77cdcf5669228c55fe17a21c5e
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.os.Binder;
20import android.os.IBinder;
21import android.util.ArrayMap;
22import com.android.internal.app.IAppOpsService;
23import com.android.internal.app.IAppOpsCallback;
24
25import java.util.ArrayList;
26import java.util.List;
27
28import android.content.Context;
29import android.os.Parcel;
30import android.os.Parcelable;
31import android.os.Process;
32import android.os.RemoteException;
33
34/**
35 * API for interacting with "application operation" tracking.  Allows you to:
36 *
37 * <ul>
38 * <li> Note when operations are happening, and find out if they are allowed for the current
39 * caller.</li>
40 * <li> Disallow specific apps from doing specific operations.</li>
41 * <li> Collect all of the current information about operations that have been executed or are not
42 * being allowed.</li>
43 * <li> Monitor for changes in whether an operation is allowed.</li>
44 * </ul>
45 *
46 * <p>Each operation is identified by a single integer; these integers are a fixed set of
47 * operations, enumerated by the OP_* constants.
48 *
49 * <p></p>When checking operations, the result is a "mode" integer indicating the current setting
50 * for the operation under that caller: MODE_ALLOWED, MODE_IGNORED (don't execute the operation but
51 * fake its behavior enough so that the caller doesn't crash), MODE_ERRORED (through a
52 * SecurityException back to the caller; the normal operation calls will do this for you).
53 */
54public class AppOpsManager {
55    final Context mContext;
56    final IAppOpsService mService;
57    final ArrayMap<Callback, IAppOpsCallback> mModeWatchers
58            = new ArrayMap<Callback, IAppOpsCallback>();
59
60    static IBinder sToken;
61
62    public static final int MODE_ALLOWED = 0;
63    public static final int MODE_IGNORED = 1;
64    public static final int MODE_ERRORED = 2;
65
66    // when adding one of these:
67    //  - increment _NUM_OP
68    //  - add rows to sOpToSwitch, sOpNames, sOpPerms, sOpDefaultMode
69    //  - add descriptive strings to Settings/res/values/arrays.xml
70    //  - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app)
71
72    /** No operation specified. */
73    public static final int OP_NONE = -1;
74    /** Access to coarse location information. */
75    public static final int OP_COARSE_LOCATION = 0;
76    /** Access to fine location information. */
77    public static final int OP_FINE_LOCATION = 1;
78    /** Causing GPS to run. */
79    public static final int OP_GPS = 2;
80    /** @hide */
81    public static final int OP_VIBRATE = 3;
82    /** @hide */
83    public static final int OP_READ_CONTACTS = 4;
84    /** @hide */
85    public static final int OP_WRITE_CONTACTS = 5;
86    /** @hide */
87    public static final int OP_READ_CALL_LOG = 6;
88    /** @hide */
89    public static final int OP_WRITE_CALL_LOG = 7;
90    /** @hide */
91    public static final int OP_READ_CALENDAR = 8;
92    /** @hide */
93    public static final int OP_WRITE_CALENDAR = 9;
94    /** @hide */
95    public static final int OP_WIFI_SCAN = 10;
96    /** @hide */
97    public static final int OP_POST_NOTIFICATION = 11;
98    /** @hide */
99    public static final int OP_NEIGHBORING_CELLS = 12;
100    /** @hide */
101    public static final int OP_CALL_PHONE = 13;
102    /** @hide */
103    public static final int OP_READ_SMS = 14;
104    /** @hide */
105    public static final int OP_WRITE_SMS = 15;
106    /** @hide */
107    public static final int OP_RECEIVE_SMS = 16;
108    /** @hide */
109    public static final int OP_RECEIVE_EMERGECY_SMS = 17;
110    /** @hide */
111    public static final int OP_RECEIVE_MMS = 18;
112    /** @hide */
113    public static final int OP_RECEIVE_WAP_PUSH = 19;
114    /** @hide */
115    public static final int OP_SEND_SMS = 20;
116    /** @hide */
117    public static final int OP_READ_ICC_SMS = 21;
118    /** @hide */
119    public static final int OP_WRITE_ICC_SMS = 22;
120    /** @hide */
121    public static final int OP_WRITE_SETTINGS = 23;
122    /** @hide */
123    public static final int OP_SYSTEM_ALERT_WINDOW = 24;
124    /** @hide */
125    public static final int OP_ACCESS_NOTIFICATIONS = 25;
126    /** @hide */
127    public static final int OP_CAMERA = 26;
128    /** @hide */
129    public static final int OP_RECORD_AUDIO = 27;
130    /** @hide */
131    public static final int OP_PLAY_AUDIO = 28;
132    /** @hide */
133    public static final int OP_READ_CLIPBOARD = 29;
134    /** @hide */
135    public static final int OP_WRITE_CLIPBOARD = 30;
136    /** @hide */
137    public static final int OP_TAKE_MEDIA_BUTTONS = 31;
138    /** @hide */
139    public static final int OP_TAKE_AUDIO_FOCUS = 32;
140    /** @hide */
141    public static final int OP_AUDIO_MASTER_VOLUME = 33;
142    /** @hide */
143    public static final int OP_AUDIO_VOICE_VOLUME = 34;
144    /** @hide */
145    public static final int OP_AUDIO_RING_VOLUME = 35;
146    /** @hide */
147    public static final int OP_AUDIO_MEDIA_VOLUME = 36;
148    /** @hide */
149    public static final int OP_AUDIO_ALARM_VOLUME = 37;
150    /** @hide */
151    public static final int OP_AUDIO_NOTIFICATION_VOLUME = 38;
152    /** @hide */
153    public static final int OP_AUDIO_BLUETOOTH_VOLUME = 39;
154    /** @hide */
155    public static final int OP_WAKE_LOCK = 40;
156    /** Continually monitoring location data. */
157    public static final int OP_MONITOR_LOCATION = 41;
158    /** Continually monitoring location data with a relatively high power request. */
159    public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42;
160    /** @hide */
161    public static final int _NUM_OP = 43;
162
163    /**
164     * This maps each operation to the operation that serves as the
165     * switch to determine whether it is allowed.  Generally this is
166     * a 1:1 mapping, but for some things (like location) that have
167     * multiple low-level operations being tracked that should be
168     * presented to the user as one switch then this can be used to
169     * make them all controlled by the same single operation.
170     */
171    private static int[] sOpToSwitch = new int[] {
172            OP_COARSE_LOCATION,
173            OP_COARSE_LOCATION,
174            OP_COARSE_LOCATION,
175            OP_VIBRATE,
176            OP_READ_CONTACTS,
177            OP_WRITE_CONTACTS,
178            OP_READ_CALL_LOG,
179            OP_WRITE_CALL_LOG,
180            OP_READ_CALENDAR,
181            OP_WRITE_CALENDAR,
182            OP_COARSE_LOCATION,
183            OP_POST_NOTIFICATION,
184            OP_COARSE_LOCATION,
185            OP_CALL_PHONE,
186            OP_READ_SMS,
187            OP_WRITE_SMS,
188            OP_RECEIVE_SMS,
189            OP_RECEIVE_SMS,
190            OP_RECEIVE_SMS,
191            OP_RECEIVE_SMS,
192            OP_SEND_SMS,
193            OP_READ_SMS,
194            OP_WRITE_SMS,
195            OP_WRITE_SETTINGS,
196            OP_SYSTEM_ALERT_WINDOW,
197            OP_ACCESS_NOTIFICATIONS,
198            OP_CAMERA,
199            OP_RECORD_AUDIO,
200            OP_PLAY_AUDIO,
201            OP_READ_CLIPBOARD,
202            OP_WRITE_CLIPBOARD,
203            OP_TAKE_MEDIA_BUTTONS,
204            OP_TAKE_AUDIO_FOCUS,
205            OP_AUDIO_MASTER_VOLUME,
206            OP_AUDIO_VOICE_VOLUME,
207            OP_AUDIO_RING_VOLUME,
208            OP_AUDIO_MEDIA_VOLUME,
209            OP_AUDIO_ALARM_VOLUME,
210            OP_AUDIO_NOTIFICATION_VOLUME,
211            OP_AUDIO_BLUETOOTH_VOLUME,
212            OP_WAKE_LOCK,
213            OP_COARSE_LOCATION,
214            OP_COARSE_LOCATION,
215    };
216
217    /**
218     * This provides a simple name for each operation to be used
219     * in debug output.
220     */
221    private static String[] sOpNames = new String[] {
222            "COARSE_LOCATION",
223            "FINE_LOCATION",
224            "GPS",
225            "VIBRATE",
226            "READ_CONTACTS",
227            "WRITE_CONTACTS",
228            "READ_CALL_LOG",
229            "WRITE_CALL_LOG",
230            "READ_CALENDAR",
231            "WRITE_CALENDAR",
232            "WIFI_SCAN",
233            "POST_NOTIFICATION",
234            "NEIGHBORING_CELLS",
235            "CALL_PHONE",
236            "READ_SMS",
237            "WRITE_SMS",
238            "RECEIVE_SMS",
239            "RECEIVE_EMERGECY_SMS",
240            "RECEIVE_MMS",
241            "RECEIVE_WAP_PUSH",
242            "SEND_SMS",
243            "READ_ICC_SMS",
244            "WRITE_ICC_SMS",
245            "WRITE_SETTINGS",
246            "SYSTEM_ALERT_WINDOW",
247            "ACCESS_NOTIFICATIONS",
248            "CAMERA",
249            "RECORD_AUDIO",
250            "PLAY_AUDIO",
251            "READ_CLIPBOARD",
252            "WRITE_CLIPBOARD",
253            "TAKE_MEDIA_BUTTONS",
254            "TAKE_AUDIO_FOCUS",
255            "AUDIO_MASTER_VOLUME",
256            "AUDIO_VOICE_VOLUME",
257            "AUDIO_RING_VOLUME",
258            "AUDIO_MEDIA_VOLUME",
259            "AUDIO_ALARM_VOLUME",
260            "AUDIO_NOTIFICATION_VOLUME",
261            "AUDIO_BLUETOOTH_VOLUME",
262            "WAKE_LOCK",
263            "MONITOR_LOCATION",
264            "MONITOR_HIGH_POWER_LOCATION",
265    };
266
267    /**
268     * This optionally maps a permission to an operation.  If there
269     * is no permission associated with an operation, it is null.
270     */
271    private static String[] sOpPerms = new String[] {
272            android.Manifest.permission.ACCESS_COARSE_LOCATION,
273            android.Manifest.permission.ACCESS_FINE_LOCATION,
274            null,
275            android.Manifest.permission.VIBRATE,
276            android.Manifest.permission.READ_CONTACTS,
277            android.Manifest.permission.WRITE_CONTACTS,
278            android.Manifest.permission.READ_CALL_LOG,
279            android.Manifest.permission.WRITE_CALL_LOG,
280            android.Manifest.permission.READ_CALENDAR,
281            android.Manifest.permission.WRITE_CALENDAR,
282            null, // no permission required for notifications
283            android.Manifest.permission.ACCESS_WIFI_STATE,
284            null, // neighboring cells shares the coarse location perm
285            android.Manifest.permission.CALL_PHONE,
286            android.Manifest.permission.READ_SMS,
287            android.Manifest.permission.WRITE_SMS,
288            android.Manifest.permission.RECEIVE_SMS,
289            android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST,
290            android.Manifest.permission.RECEIVE_MMS,
291            android.Manifest.permission.RECEIVE_WAP_PUSH,
292            android.Manifest.permission.SEND_SMS,
293            android.Manifest.permission.READ_SMS,
294            android.Manifest.permission.WRITE_SMS,
295            android.Manifest.permission.WRITE_SETTINGS,
296            android.Manifest.permission.SYSTEM_ALERT_WINDOW,
297            android.Manifest.permission.ACCESS_NOTIFICATIONS,
298            android.Manifest.permission.CAMERA,
299            android.Manifest.permission.RECORD_AUDIO,
300            null, // no permission for playing audio
301            null, // no permission for reading clipboard
302            null, // no permission for writing clipboard
303            null, // no permission for taking media buttons
304            null, // no permission for taking audio focus
305            null, // no permission for changing master volume
306            null, // no permission for changing voice volume
307            null, // no permission for changing ring volume
308            null, // no permission for changing media volume
309            null, // no permission for changing alarm volume
310            null, // no permission for changing notification volume
311            null, // no permission for changing bluetooth volume
312            android.Manifest.permission.WAKE_LOCK,
313            null, // no permission for generic location monitoring
314            null, // no permission for high power location monitoring
315    };
316
317    /**
318     * This specifies the default mode for each operation.
319     */
320    private static int[] sOpDefaultMode = new int[] {
321            AppOpsManager.MODE_ALLOWED,
322            AppOpsManager.MODE_ALLOWED,
323            AppOpsManager.MODE_ALLOWED,
324            AppOpsManager.MODE_ALLOWED,
325            AppOpsManager.MODE_ALLOWED,
326            AppOpsManager.MODE_ALLOWED,
327            AppOpsManager.MODE_ALLOWED,
328            AppOpsManager.MODE_ALLOWED,
329            AppOpsManager.MODE_ALLOWED,
330            AppOpsManager.MODE_ALLOWED,
331            AppOpsManager.MODE_ALLOWED,
332            AppOpsManager.MODE_ALLOWED,
333            AppOpsManager.MODE_ALLOWED,
334            AppOpsManager.MODE_ALLOWED,
335            AppOpsManager.MODE_ALLOWED,
336            AppOpsManager.MODE_IGNORED, // OP_WRITE_SMS
337            AppOpsManager.MODE_ALLOWED,
338            AppOpsManager.MODE_ALLOWED,
339            AppOpsManager.MODE_ALLOWED,
340            AppOpsManager.MODE_ALLOWED,
341            AppOpsManager.MODE_ALLOWED,
342            AppOpsManager.MODE_ALLOWED,
343            AppOpsManager.MODE_ALLOWED,
344            AppOpsManager.MODE_ALLOWED,
345            AppOpsManager.MODE_ALLOWED,
346            AppOpsManager.MODE_ALLOWED,
347            AppOpsManager.MODE_ALLOWED,
348            AppOpsManager.MODE_ALLOWED,
349            AppOpsManager.MODE_ALLOWED,
350            AppOpsManager.MODE_ALLOWED,
351            AppOpsManager.MODE_ALLOWED,
352            AppOpsManager.MODE_ALLOWED,
353            AppOpsManager.MODE_ALLOWED,
354            AppOpsManager.MODE_ALLOWED,
355            AppOpsManager.MODE_ALLOWED,
356            AppOpsManager.MODE_ALLOWED,
357            AppOpsManager.MODE_ALLOWED,
358            AppOpsManager.MODE_ALLOWED,
359            AppOpsManager.MODE_ALLOWED,
360            AppOpsManager.MODE_ALLOWED,
361            AppOpsManager.MODE_ALLOWED,
362            AppOpsManager.MODE_ALLOWED,
363            AppOpsManager.MODE_ALLOWED,
364    };
365
366    /**
367     * Retrieve the op switch that controls the given operation.
368     * @hide
369     */
370    public static int opToSwitch(int op) {
371        return sOpToSwitch[op];
372    }
373
374    /**
375     * Retrieve a non-localized name for the operation, for debugging output.
376     */
377    public static String opToName(int op) {
378        if (op == OP_NONE) return "NONE";
379        return op < sOpNames.length ? sOpNames[op] : ("Unknown(" + op + ")");
380    }
381
382    /**
383     * Retrieve the permission associated with an operation, or null if there is not one.
384     * @hide
385     */
386    public static String opToPermission(int op) {
387        return sOpPerms[op];
388    }
389
390    /**
391     * Retrieve the default mode for the operation.
392     * @hide
393     */
394    public static int opToDefaultMode(int op) {
395        return sOpDefaultMode[op];
396    }
397
398    /**
399     * Class holding all of the operation information associated with an app.
400     * @hide
401     */
402    public static class PackageOps implements Parcelable {
403        private final String mPackageName;
404        private final int mUid;
405        private final List<OpEntry> mEntries;
406
407        public PackageOps(String packageName, int uid, List<OpEntry> entries) {
408            mPackageName = packageName;
409            mUid = uid;
410            mEntries = entries;
411        }
412
413        public String getPackageName() {
414            return mPackageName;
415        }
416
417        public int getUid() {
418            return mUid;
419        }
420
421        public List<OpEntry> getOps() {
422            return mEntries;
423        }
424
425        @Override
426        public int describeContents() {
427            return 0;
428        }
429
430        @Override
431        public void writeToParcel(Parcel dest, int flags) {
432            dest.writeString(mPackageName);
433            dest.writeInt(mUid);
434            dest.writeInt(mEntries.size());
435            for (int i=0; i<mEntries.size(); i++) {
436                mEntries.get(i).writeToParcel(dest, flags);
437            }
438        }
439
440        PackageOps(Parcel source) {
441            mPackageName = source.readString();
442            mUid = source.readInt();
443            mEntries = new ArrayList<OpEntry>();
444            final int N = source.readInt();
445            for (int i=0; i<N; i++) {
446                mEntries.add(OpEntry.CREATOR.createFromParcel(source));
447            }
448        }
449
450        public static final Creator<PackageOps> CREATOR = new Creator<PackageOps>() {
451            @Override public PackageOps createFromParcel(Parcel source) {
452                return new PackageOps(source);
453            }
454
455            @Override public PackageOps[] newArray(int size) {
456                return new PackageOps[size];
457            }
458        };
459    }
460
461    /**
462     * Class holding the information about one unique operation of an application.
463     * @hide
464     */
465    public static class OpEntry implements Parcelable {
466        private final int mOp;
467        private final int mMode;
468        private final long mTime;
469        private final long mRejectTime;
470        private final int mDuration;
471
472        public OpEntry(int op, int mode, long time, long rejectTime, int duration) {
473            mOp = op;
474            mMode = mode;
475            mTime = time;
476            mRejectTime = rejectTime;
477            mDuration = duration;
478        }
479
480        public int getOp() {
481            return mOp;
482        }
483
484        public int getMode() {
485            return mMode;
486        }
487
488        public long getTime() {
489            return mTime;
490        }
491
492        public long getRejectTime() {
493            return mRejectTime;
494        }
495
496        public boolean isRunning() {
497            return mDuration == -1;
498        }
499
500        public int getDuration() {
501            return mDuration == -1 ? (int)(System.currentTimeMillis()-mTime) : mDuration;
502        }
503
504        @Override
505        public int describeContents() {
506            return 0;
507        }
508
509        @Override
510        public void writeToParcel(Parcel dest, int flags) {
511            dest.writeInt(mOp);
512            dest.writeInt(mMode);
513            dest.writeLong(mTime);
514            dest.writeLong(mRejectTime);
515            dest.writeInt(mDuration);
516        }
517
518        OpEntry(Parcel source) {
519            mOp = source.readInt();
520            mMode = source.readInt();
521            mTime = source.readLong();
522            mRejectTime = source.readLong();
523            mDuration = source.readInt();
524        }
525
526        public static final Creator<OpEntry> CREATOR = new Creator<OpEntry>() {
527            @Override public OpEntry createFromParcel(Parcel source) {
528                return new OpEntry(source);
529            }
530
531            @Override public OpEntry[] newArray(int size) {
532                return new OpEntry[size];
533            }
534        };
535    }
536
537    /**
538     * Callback for notification of changes to operation state.
539     */
540    public interface Callback {
541        public void opChanged(int op, String packageName);
542    }
543
544    AppOpsManager(Context context, IAppOpsService service) {
545        mContext = context;
546        mService = service;
547    }
548
549    /**
550     * Retrieve current operation state for all applications.
551     *
552     * @param ops The set of operations you are interested in, or null if you want all of them.
553     * @hide
554     */
555    public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
556        try {
557            return mService.getPackagesForOps(ops);
558        } catch (RemoteException e) {
559        }
560        return null;
561    }
562
563    /**
564     * Retrieve current operation state for one application.
565     *
566     * @param uid The uid of the application of interest.
567     * @param packageName The name of the application of interest.
568     * @param ops The set of operations you are interested in, or null if you want all of them.
569     * @hide
570     */
571    public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, int[] ops) {
572        try {
573            return mService.getOpsForPackage(uid, packageName, ops);
574        } catch (RemoteException e) {
575        }
576        return null;
577    }
578
579    /** @hide */
580    public void setMode(int code, int uid, String packageName, int mode) {
581        try {
582            mService.setMode(code, uid, packageName, mode);
583        } catch (RemoteException e) {
584        }
585    }
586
587    /** @hide */
588    public void resetAllModes() {
589        try {
590            mService.resetAllModes();
591        } catch (RemoteException e) {
592        }
593    }
594
595    /**
596     * Monitor for changes to the operating mode for the given op in the given app package.
597     * @param op The operation to monitor, one of OP_*.
598     * @param packageName The name of the application to monitor.
599     * @param callback Where to report changes.
600     */
601    public void startWatchingMode(int op, String packageName, final Callback callback) {
602        synchronized (mModeWatchers) {
603            IAppOpsCallback cb = mModeWatchers.get(callback);
604            if (cb == null) {
605                cb = new IAppOpsCallback.Stub() {
606                    public void opChanged(int op, String packageName) {
607                        callback.opChanged(op, packageName);
608                    }
609                };
610                mModeWatchers.put(callback, cb);
611            }
612            try {
613                mService.startWatchingMode(op, packageName, cb);
614            } catch (RemoteException e) {
615            }
616        }
617    }
618
619    /**
620     * Stop monitoring that was previously started with {@link #startWatchingMode}.  All
621     * monitoring associated with this callback will be removed.
622     */
623    public void stopWatchingMode(Callback callback) {
624        synchronized (mModeWatchers) {
625            IAppOpsCallback cb = mModeWatchers.get(callback);
626            if (cb != null) {
627                try {
628                    mService.stopWatchingMode(cb);
629                } catch (RemoteException e) {
630                }
631            }
632        }
633    }
634
635    private String buildSecurityExceptionMsg(int op, int uid, String packageName) {
636        return packageName + " from uid " + uid + " not allowed to perform " + sOpNames[op];
637    }
638
639    /**
640     * Do a quick check for whether an application might be able to perform an operation.
641     * This is <em>not</em> a security check; you must use {@link #noteOp(int, int, String)}
642     * or {@link #startOp(int, int, String)} for your actual security checks, which also
643     * ensure that the given uid and package name are consistent.  This function can just be
644     * used for a quick check to see if an operation has been disabled for the application,
645     * as an early reject of some work.  This does not modify the time stamp or other data
646     * about the operation.
647     * @param op The operation to check.  One of the OP_* constants.
648     * @param uid The user id of the application attempting to perform the operation.
649     * @param packageName The name of the application attempting to perform the operation.
650     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
651     * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
652     * causing the app to crash).
653     * @throws SecurityException If the app has been configured to crash on this op.
654     */
655    public int checkOp(int op, int uid, String packageName) {
656        try {
657            int mode = mService.checkOperation(op, uid, packageName);
658            if (mode == MODE_ERRORED) {
659                throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
660            }
661            return mode;
662        } catch (RemoteException e) {
663        }
664        return MODE_IGNORED;
665    }
666
667    /**
668     * Like {@link #checkOp} but instead of throwing a {@link SecurityException} it
669     * returns {@link #MODE_ERRORED}.
670     */
671    public int checkOpNoThrow(int op, int uid, String packageName) {
672        try {
673            return mService.checkOperation(op, uid, packageName);
674        } catch (RemoteException e) {
675        }
676        return MODE_IGNORED;
677    }
678
679    /**
680     * Do a quick check to validate if a package name belongs to a UID.
681     *
682     * @throws SecurityException if the package name doesn't belong to the given
683     *             UID, or if ownership cannot be verified.
684     */
685    public void checkPackage(int uid, String packageName) {
686        try {
687            if (mService.checkPackage(uid, packageName) != MODE_ALLOWED) {
688                throw new SecurityException(
689                        "Package " + packageName + " does not belong to " + uid);
690            }
691        } catch (RemoteException e) {
692            throw new SecurityException("Unable to verify package ownership", e);
693        }
694    }
695
696    /**
697     * Make note of an application performing an operation.  Note that you must pass
698     * in both the uid and name of the application to be checked; this function will verify
699     * that these two match, and if not, return {@link #MODE_IGNORED}.  If this call
700     * succeeds, the last execution time of the operation for this app will be updated to
701     * the current time.
702     * @param op The operation to note.  One of the OP_* constants.
703     * @param uid The user id of the application attempting to perform the operation.
704     * @param packageName The name of the application attempting to perform the operation.
705     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
706     * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
707     * causing the app to crash).
708     * @throws SecurityException If the app has been configured to crash on this op.
709     */
710    public int noteOp(int op, int uid, String packageName) {
711        try {
712            int mode = mService.noteOperation(op, uid, packageName);
713            if (mode == MODE_ERRORED) {
714                throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
715            }
716            return mode;
717        } catch (RemoteException e) {
718        }
719        return MODE_IGNORED;
720    }
721
722    /**
723     * Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
724     * returns {@link #MODE_ERRORED}.
725     */
726    public int noteOpNoThrow(int op, int uid, String packageName) {
727        try {
728            return mService.noteOperation(op, uid, packageName);
729        } catch (RemoteException e) {
730        }
731        return MODE_IGNORED;
732    }
733
734    /** @hide */
735    public int noteOp(int op) {
736        return noteOp(op, Process.myUid(), mContext.getOpPackageName());
737    }
738
739    /** @hide */
740    public static IBinder getToken(IAppOpsService service) {
741        synchronized (AppOpsManager.class) {
742            if (sToken != null) {
743                return sToken;
744            }
745            try {
746                sToken = service.getToken(new Binder());
747            } catch (RemoteException e) {
748                // System is dead, whatevs.
749            }
750            return sToken;
751        }
752    }
753
754    /**
755     * Report that an application has started executing a long-running operation.  Note that you
756     * must pass in both the uid and name of the application to be checked; this function will
757     * verify that these two match, and if not, return {@link #MODE_IGNORED}.  If this call
758     * succeeds, the last execution time of the operation for this app will be updated to
759     * the current time and the operation will be marked as "running".  In this case you must
760     * later call {@link #finishOp(int, int, String)} to report when the application is no
761     * longer performing the operation.
762     * @param op The operation to start.  One of the OP_* constants.
763     * @param uid The user id of the application attempting to perform the operation.
764     * @param packageName The name of the application attempting to perform the operation.
765     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
766     * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
767     * causing the app to crash).
768     * @throws SecurityException If the app has been configured to crash on this op.
769     */
770    public int startOp(int op, int uid, String packageName) {
771        try {
772            int mode = mService.startOperation(getToken(mService), op, uid, packageName);
773            if (mode == MODE_ERRORED) {
774                throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
775            }
776            return mode;
777        } catch (RemoteException e) {
778        }
779        return MODE_IGNORED;
780    }
781
782    /**
783     * Like {@link #startOp} but instead of throwing a {@link SecurityException} it
784     * returns {@link #MODE_ERRORED}.
785     */
786    public int startOpNoThrow(int op, int uid, String packageName) {
787        try {
788            return mService.startOperation(getToken(mService), op, uid, packageName);
789        } catch (RemoteException e) {
790        }
791        return MODE_IGNORED;
792    }
793
794    /** @hide */
795    public int startOp(int op) {
796        return startOp(op, Process.myUid(), mContext.getOpPackageName());
797    }
798
799    /**
800     * Report that an application is no longer performing an operation that had previously
801     * been started with {@link #startOp(int, int, String)}.  There is no validation of input
802     * or result; the parameters supplied here must be the exact same ones previously passed
803     * in when starting the operation.
804     */
805    public void finishOp(int op, int uid, String packageName) {
806        try {
807            mService.finishOperation(getToken(mService), op, uid, packageName);
808        } catch (RemoteException e) {
809        }
810    }
811
812    public void finishOp(int op) {
813        finishOp(op, Process.myUid(), mContext.getOpPackageName());
814    }
815}
816