OSDN Git Service

am 8cd5592c: am bce05d91: am 45e56fd5: cherypick from mr2: Ib7e08e719b6b9c9b1e8116e6e...
[android-x86/frameworks-base.git] / core / java / android / app / AppOpsManager.java
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package android.app;
18
19 import android.Manifest;
20 import com.android.internal.app.IAppOpsService;
21 import com.android.internal.app.IAppOpsCallback;
22
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
26
27 import android.content.Context;
28 import android.os.Parcel;
29 import android.os.Parcelable;
30 import android.os.Process;
31 import android.os.RemoteException;
32
33 /**
34  * API for interacting with "application operation" tracking.  Allows you to:
35  *
36  * - Note when operations are happening, and find out if they are allowed for the current caller.
37  * - Disallow specific apps from doing specific operations.
38  * - Collect all of the current information about operations that have been executed or are not
39  * being allowed.
40  * - Monitor for changes in whether an operation is allowed.
41  *
42  * Each operation is identified by a single integer; these integers are a fixed set of
43  * operations, enumerated by the OP_* constants.
44  *
45  * When checking operations, the result is a "mode" integer indicating the current setting
46  * for the operation under that caller: MODE_ALLOWED, MODE_IGNORED (don't execute the operation but
47  * fake its behavior enough so that the caller doesn't crash), MODE_ERRORED (through a
48  * SecurityException back to the caller; the normal operation calls will do this for you).
49  *
50  * @hide
51  */
52 public class AppOpsManager {
53     final Context mContext;
54     final IAppOpsService mService;
55     final HashMap<Callback, IAppOpsCallback> mModeWatchers
56             = new HashMap<Callback, IAppOpsCallback>();
57
58     public static final int MODE_ALLOWED = 0;
59     public static final int MODE_IGNORED = 1;
60     public static final int MODE_ERRORED = 2;
61
62     // when adding one of these:
63     //  - increment _NUM_OP
64     //  - add rows to sOpToSwitch, sOpNames, sOpPerms
65     //  - add descriptive strings to Settings/res/values/arrays.xml
66     public static final int OP_NONE = -1;
67     public static final int OP_COARSE_LOCATION = 0;
68     public static final int OP_FINE_LOCATION = 1;
69     public static final int OP_GPS = 2;
70     public static final int OP_VIBRATE = 3;
71     public static final int OP_READ_CONTACTS = 4;
72     public static final int OP_WRITE_CONTACTS = 5;
73     public static final int OP_READ_CALL_LOG = 6;
74     public static final int OP_WRITE_CALL_LOG = 7;
75     public static final int OP_READ_CALENDAR = 8;
76     public static final int OP_WRITE_CALENDAR = 9;
77     public static final int OP_WIFI_SCAN = 10;
78     public static final int OP_POST_NOTIFICATION = 11;
79     public static final int OP_NEIGHBORING_CELLS = 12;
80     public static final int OP_CALL_PHONE = 13;
81     public static final int OP_READ_SMS = 14;
82     public static final int OP_WRITE_SMS = 15;
83     public static final int OP_RECEIVE_SMS = 16;
84     public static final int OP_RECEIVE_EMERGECY_SMS = 17;
85     public static final int OP_RECEIVE_MMS = 18;
86     public static final int OP_RECEIVE_WAP_PUSH = 19;
87     public static final int OP_SEND_SMS = 20;
88     public static final int OP_READ_ICC_SMS = 21;
89     public static final int OP_WRITE_ICC_SMS = 22;
90     public static final int OP_WRITE_SETTINGS = 23;
91     public static final int OP_SYSTEM_ALERT_WINDOW = 24;
92     public static final int OP_ACCESS_NOTIFICATIONS = 25;
93     public static final int OP_CAMERA = 26;
94     public static final int OP_RECORD_AUDIO = 27;
95     public static final int OP_PLAY_AUDIO = 28;
96     public static final int OP_READ_CLIPBOARD = 29;
97     public static final int OP_WRITE_CLIPBOARD = 30;
98     /** @hide */
99     public static final int _NUM_OP = 31;
100
101     /**
102      * This maps each operation to the operation that serves as the
103      * switch to determine whether it is allowed.  Generally this is
104      * a 1:1 mapping, but for some things (like location) that have
105      * multiple low-level operations being tracked that should be
106      * presented to hte user as one switch then this can be used to
107      * make them all controlled by the same single operation.
108      */
109     private static int[] sOpToSwitch = new int[] {
110             OP_COARSE_LOCATION,
111             OP_COARSE_LOCATION,
112             OP_COARSE_LOCATION,
113             OP_VIBRATE,
114             OP_READ_CONTACTS,
115             OP_WRITE_CONTACTS,
116             OP_READ_CALL_LOG,
117             OP_WRITE_CALL_LOG,
118             OP_READ_CALENDAR,
119             OP_WRITE_CALENDAR,
120             OP_COARSE_LOCATION,
121             OP_POST_NOTIFICATION,
122             OP_COARSE_LOCATION,
123             OP_CALL_PHONE,
124             OP_READ_SMS,
125             OP_WRITE_SMS,
126             OP_READ_SMS,
127             OP_READ_SMS,
128             OP_READ_SMS,
129             OP_READ_SMS,
130             OP_WRITE_SMS,
131             OP_READ_SMS,
132             OP_WRITE_SMS,
133             OP_WRITE_SETTINGS,
134             OP_SYSTEM_ALERT_WINDOW,
135             OP_ACCESS_NOTIFICATIONS,
136             OP_CAMERA,
137             OP_RECORD_AUDIO,
138             OP_PLAY_AUDIO,
139             OP_READ_CLIPBOARD,
140             OP_WRITE_CLIPBOARD,
141     };
142
143     /**
144      * This provides a simple name for each operation to be used
145      * in debug output.
146      */
147     private static String[] sOpNames = new String[] {
148             "COARSE_LOCATION",
149             "FINE_LOCATION",
150             "GPS",
151             "VIBRATE",
152             "READ_CONTACTS",
153             "WRITE_CONTACTS",
154             "READ_CALL_LOG",
155             "WRITE_CALL_LOG",
156             "READ_CALENDAR",
157             "WRITE_CALENDAR",
158             "WIFI_SCAN",
159             "POST_NOTIFICATION",
160             "NEIGHBORING_CELLS",
161             "CALL_PHONE",
162             "READ_SMS",
163             "WRITE_SMS",
164             "RECEIVE_SMS",
165             "RECEIVE_EMERGECY_SMS",
166             "RECEIVE_MMS",
167             "RECEIVE_WAP_PUSH",
168             "SEND_SMS",
169             "READ_ICC_SMS",
170             "WRITE_ICC_SMS",
171             "WRITE_SETTINGS",
172             "SYSTEM_ALERT_WINDOW",
173             "ACCESS_NOTIFICATIONS",
174             "CAMERA",
175             "RECORD_AUDIO",
176             "PLAY_AUDIO",
177             "READ_CLIPBOARD",
178             "WRITE_CLIPBOARD",
179     };
180
181     /**
182      * This optionally maps a permission to an operation.  If there
183      * is no permission associated with an operation, it is null.
184      */
185     private static String[] sOpPerms = new String[] {
186             android.Manifest.permission.ACCESS_COARSE_LOCATION,
187             android.Manifest.permission.ACCESS_FINE_LOCATION,
188             null,
189             android.Manifest.permission.VIBRATE,
190             android.Manifest.permission.READ_CONTACTS,
191             android.Manifest.permission.WRITE_CONTACTS,
192             android.Manifest.permission.READ_CALL_LOG,
193             android.Manifest.permission.WRITE_CALL_LOG,
194             android.Manifest.permission.READ_CALENDAR,
195             android.Manifest.permission.WRITE_CALENDAR,
196             null, // no permission required for notifications
197             android.Manifest.permission.ACCESS_WIFI_STATE,
198             null, // neighboring cells shares the coarse location perm
199             android.Manifest.permission.CALL_PHONE,
200             android.Manifest.permission.READ_SMS,
201             android.Manifest.permission.WRITE_SMS,
202             android.Manifest.permission.RECEIVE_SMS,
203             android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST,
204             android.Manifest.permission.RECEIVE_MMS,
205             android.Manifest.permission.RECEIVE_WAP_PUSH,
206             android.Manifest.permission.SEND_SMS,
207             android.Manifest.permission.READ_SMS,
208             android.Manifest.permission.WRITE_SMS,
209             android.Manifest.permission.WRITE_SETTINGS,
210             android.Manifest.permission.SYSTEM_ALERT_WINDOW,
211             android.Manifest.permission.ACCESS_NOTIFICATIONS,
212             android.Manifest.permission.CAMERA,
213             android.Manifest.permission.RECORD_AUDIO,
214             null, // no permission for playing audio
215             null, // no permission for reading clipboard
216             null, // no permission for writing clipboard
217     };
218
219     /**
220      * Retrieve the op switch that controls the given operation.
221      */
222     public static int opToSwitch(int op) {
223         return sOpToSwitch[op];
224     }
225
226     /**
227      * Retrieve a non-localized name for the operation, for debugging output.
228      */
229     public static String opToName(int op) {
230         if (op == OP_NONE) return "NONE";
231         return op < sOpNames.length ? sOpNames[op] : ("Unknown(" + op + ")");
232     }
233
234     /**
235      * Retrieve the permission associated with an operation, or null if there is not one.
236      */
237     public static String opToPermission(int op) {
238         return sOpPerms[op];
239     }
240
241     /**
242      * Class holding all of the operation information associated with an app.
243      */
244     public static class PackageOps implements Parcelable {
245         private final String mPackageName;
246         private final int mUid;
247         private final List<OpEntry> mEntries;
248
249         public PackageOps(String packageName, int uid, List<OpEntry> entries) {
250             mPackageName = packageName;
251             mUid = uid;
252             mEntries = entries;
253         }
254
255         public String getPackageName() {
256             return mPackageName;
257         }
258
259         public int getUid() {
260             return mUid;
261         }
262
263         public List<OpEntry> getOps() {
264             return mEntries;
265         }
266
267         @Override
268         public int describeContents() {
269             return 0;
270         }
271
272         @Override
273         public void writeToParcel(Parcel dest, int flags) {
274             dest.writeString(mPackageName);
275             dest.writeInt(mUid);
276             dest.writeInt(mEntries.size());
277             for (int i=0; i<mEntries.size(); i++) {
278                 mEntries.get(i).writeToParcel(dest, flags);
279             }
280         }
281
282         PackageOps(Parcel source) {
283             mPackageName = source.readString();
284             mUid = source.readInt();
285             mEntries = new ArrayList<OpEntry>();
286             final int N = source.readInt();
287             for (int i=0; i<N; i++) {
288                 mEntries.add(OpEntry.CREATOR.createFromParcel(source));
289             }
290         }
291
292         public static final Creator<PackageOps> CREATOR = new Creator<PackageOps>() {
293             @Override public PackageOps createFromParcel(Parcel source) {
294                 return new PackageOps(source);
295             }
296
297             @Override public PackageOps[] newArray(int size) {
298                 return new PackageOps[size];
299             }
300         };
301     }
302
303     /**
304      * Class holding the information about one unique operation of an application.
305      */
306     public static class OpEntry implements Parcelable {
307         private final int mOp;
308         private final int mMode;
309         private final long mTime;
310         private final long mRejectTime;
311         private final int mDuration;
312
313         public OpEntry(int op, int mode, long time, long rejectTime, int duration) {
314             mOp = op;
315             mMode = mode;
316             mTime = time;
317             mRejectTime = rejectTime;
318             mDuration = duration;
319         }
320
321         public int getOp() {
322             return mOp;
323         }
324
325         public int getMode() {
326             return mMode;
327         }
328
329         public long getTime() {
330             return mTime;
331         }
332
333         public long getRejectTime() {
334             return mRejectTime;
335         }
336
337         public boolean isRunning() {
338             return mDuration == -1;
339         }
340
341         public int getDuration() {
342             return mDuration == -1 ? (int)(System.currentTimeMillis()-mTime) : mDuration;
343         }
344
345         @Override
346         public int describeContents() {
347             return 0;
348         }
349
350         @Override
351         public void writeToParcel(Parcel dest, int flags) {
352             dest.writeInt(mOp);
353             dest.writeInt(mMode);
354             dest.writeLong(mTime);
355             dest.writeLong(mRejectTime);
356             dest.writeInt(mDuration);
357         }
358
359         OpEntry(Parcel source) {
360             mOp = source.readInt();
361             mMode = source.readInt();
362             mTime = source.readLong();
363             mRejectTime = source.readLong();
364             mDuration = source.readInt();
365         }
366
367         public static final Creator<OpEntry> CREATOR = new Creator<OpEntry>() {
368             @Override public OpEntry createFromParcel(Parcel source) {
369                 return new OpEntry(source);
370             }
371
372             @Override public OpEntry[] newArray(int size) {
373                 return new OpEntry[size];
374             }
375         };
376     }
377
378     /**
379      * Callback for notification of changes to operation state.
380      */
381     public interface Callback {
382         public void opChanged(int op, String packageName);
383     }
384
385     public AppOpsManager(Context context, IAppOpsService service) {
386         mContext = context;
387         mService = service;
388     }
389
390     /**
391      * Retrieve current operation state for all applications.
392      *
393      * @param ops The set of operations you are interested in, or null if you want all of them.
394      */
395     public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
396         try {
397             return mService.getPackagesForOps(ops);
398         } catch (RemoteException e) {
399         }
400         return null;
401     }
402
403     /**
404      * Retrieve current operation state for one application.
405      *
406      * @param uid The uid of the application of interest.
407      * @param packageName The name of the application of interest.
408      * @param ops The set of operations you are interested in, or null if you want all of them.
409      */
410     public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, int[] ops) {
411         try {
412             return mService.getOpsForPackage(uid, packageName, ops);
413         } catch (RemoteException e) {
414         }
415         return null;
416     }
417
418     public void setMode(int code, int uid, String packageName, int mode) {
419         try {
420             mService.setMode(code, uid, packageName, mode);
421         } catch (RemoteException e) {
422         }
423     }
424
425     public void startWatchingMode(int op, String packageName, final Callback callback) {
426         synchronized (mModeWatchers) {
427             IAppOpsCallback cb = mModeWatchers.get(callback);
428             if (cb == null) {
429                 cb = new IAppOpsCallback.Stub() {
430                     public void opChanged(int op, String packageName) {
431                         callback.opChanged(op, packageName);
432                     }
433                 };
434                 mModeWatchers.put(callback, cb);
435             }
436             try {
437                 mService.startWatchingMode(op, packageName, cb);
438             } catch (RemoteException e) {
439             }
440         }
441     }
442
443     public void stopWatchingMode(Callback callback) {
444         synchronized (mModeWatchers) {
445             IAppOpsCallback cb = mModeWatchers.get(callback);
446             if (cb != null) {
447                 try {
448                     mService.stopWatchingMode(cb);
449                 } catch (RemoteException e) {
450                 }
451             }
452         }
453     }
454
455     public int checkOp(int op, int uid, String packageName) {
456         try {
457             int mode = mService.checkOperation(op, uid, packageName);
458             if (mode == MODE_ERRORED) {
459                 throw new SecurityException("Operation not allowed");
460             }
461             return mode;
462         } catch (RemoteException e) {
463         }
464         return MODE_IGNORED;
465     }
466
467     public int checkOpNoThrow(int op, int uid, String packageName) {
468         try {
469             return mService.checkOperation(op, uid, packageName);
470         } catch (RemoteException e) {
471         }
472         return MODE_IGNORED;
473     }
474
475     public int noteOp(int op, int uid, String packageName) {
476         try {
477             int mode = mService.noteOperation(op, uid, packageName);
478             if (mode == MODE_ERRORED) {
479                 throw new SecurityException("Operation not allowed");
480             }
481             return mode;
482         } catch (RemoteException e) {
483         }
484         return MODE_IGNORED;
485     }
486
487     public int noteOpNoThrow(int op, int uid, String packageName) {
488         try {
489             return mService.noteOperation(op, uid, packageName);
490         } catch (RemoteException e) {
491         }
492         return MODE_IGNORED;
493     }
494
495     public int noteOp(int op) {
496         return noteOp(op, Process.myUid(), mContext.getBasePackageName());
497     }
498
499     public int startOp(int op, int uid, String packageName) {
500         try {
501             int mode = mService.startOperation(op, uid, packageName);
502             if (mode == MODE_ERRORED) {
503                 throw new SecurityException("Operation not allowed");
504             }
505             return mode;
506         } catch (RemoteException e) {
507         }
508         return MODE_IGNORED;
509     }
510
511     public int startOpNoThrow(int op, int uid, String packageName) {
512         try {
513             return mService.startOperation(op, uid, packageName);
514         } catch (RemoteException e) {
515         }
516         return MODE_IGNORED;
517     }
518
519     public int startOp(int op) {
520         return startOp(op, Process.myUid(), mContext.getBasePackageName());
521     }
522
523     public void finishOp(int op, int uid, String packageName) {
524         try {
525             mService.finishOperation(op, uid, packageName);
526         } catch (RemoteException e) {
527         }
528     }
529
530     public void finishOp(int op) {
531         finishOp(op, Process.myUid(), mContext.getBasePackageName());
532     }
533 }