blob: 8d472362bc3ed8a0361fba6229a3ecef77fbffc0 [file] [log] [blame]
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001/*
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
Dianne Hackborne98f5db2013-07-17 17:23:25 -070019import android.os.Binder;
20import android.os.IBinder;
Dianne Hackborn3e82ba12013-07-16 13:23:55 -070021import android.util.ArrayMap;
Dianne Hackborna06de0f2012-12-11 16:34:47 -080022import com.android.internal.app.IAppOpsService;
Dianne Hackbornc2293022013-02-06 23:14:49 -080023import com.android.internal.app.IAppOpsCallback;
Dianne Hackborna06de0f2012-12-11 16:34:47 -080024
Dianne Hackborn35654b62013-01-14 17:38:02 -080025import java.util.ArrayList;
26import java.util.List;
27
Dianne Hackborna06de0f2012-12-11 16:34:47 -080028import android.content.Context;
Dianne Hackborn35654b62013-01-14 17:38:02 -080029import android.os.Parcel;
30import android.os.Parcelable;
Dianne Hackborna06de0f2012-12-11 16:34:47 -080031import android.os.Process;
32import android.os.RemoteException;
33
Dianne Hackbornd7d28e62013-02-12 14:59:53 -080034/**
35 * API for interacting with "application operation" tracking. Allows you to:
36 *
Dianne Hackborn1304f4a2013-07-09 18:17:27 -070037 * <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>
Dianne Hackbornd7d28e62013-02-12 14:59:53 -080045 *
Dianne Hackborn1304f4a2013-07-09 18:17:27 -070046 * <p>Each operation is identified by a single integer; these integers are a fixed set of
Dianne Hackbornd7d28e62013-02-12 14:59:53 -080047 * operations, enumerated by the OP_* constants.
48 *
Dianne Hackborn1304f4a2013-07-09 18:17:27 -070049 * <p></p>When checking operations, the result is a "mode" integer indicating the current setting
Dianne Hackbornd7d28e62013-02-12 14:59:53 -080050 * 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).
Dianne Hackbornd7d28e62013-02-12 14:59:53 -080053 */
Dianne Hackborna06de0f2012-12-11 16:34:47 -080054public class AppOpsManager {
55 final Context mContext;
56 final IAppOpsService mService;
Dianne Hackborn3e82ba12013-07-16 13:23:55 -070057 final ArrayMap<Callback, IAppOpsCallback> mModeWatchers
58 = new ArrayMap<Callback, IAppOpsCallback>();
Dianne Hackborna06de0f2012-12-11 16:34:47 -080059
Dianne Hackborne98f5db2013-07-17 17:23:25 -070060 static IBinder sToken;
61
Dianne Hackborna06de0f2012-12-11 16:34:47 -080062 public static final int MODE_ALLOWED = 0;
63 public static final int MODE_IGNORED = 1;
64 public static final int MODE_ERRORED = 2;
65
Daniel Sandlerfde19b12013-01-17 00:21:05 -050066 // when adding one of these:
67 // - increment _NUM_OP
68 // - add rows to sOpToSwitch, sOpNames, sOpPerms
69 // - add descriptive strings to Settings/res/values/arrays.xml
Dianne Hackborn1304f4a2013-07-09 18:17:27 -070070
71 /** No operation specified. */
Dianne Hackbornf51f6122013-02-04 18:23:34 -080072 public static final int OP_NONE = -1;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -070073 /** Access to coarse location information. */
Dianne Hackborn35654b62013-01-14 17:38:02 -080074 public static final int OP_COARSE_LOCATION = 0;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -070075 /** Access to fine location information. */
Dianne Hackborn35654b62013-01-14 17:38:02 -080076 public static final int OP_FINE_LOCATION = 1;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -070077 /** Causing GPS to run. */
Dianne Hackborn35654b62013-01-14 17:38:02 -080078 public static final int OP_GPS = 2;
Dianne Hackbornf265ea92013-01-31 15:00:51 -080079 /** @hide */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -070080 public static final int OP_VIBRATE = 3;
81 /** @hide */
82 public static final int OP_READ_CONTACTS = 4;
83 /** @hide */
84 public static final int OP_WRITE_CONTACTS = 5;
85 /** @hide */
86 public static final int OP_READ_CALL_LOG = 6;
87 /** @hide */
88 public static final int OP_WRITE_CALL_LOG = 7;
89 /** @hide */
90 public static final int OP_READ_CALENDAR = 8;
91 /** @hide */
92 public static final int OP_WRITE_CALENDAR = 9;
93 /** @hide */
94 public static final int OP_WIFI_SCAN = 10;
95 /** @hide */
96 public static final int OP_POST_NOTIFICATION = 11;
97 /** @hide */
98 public static final int OP_NEIGHBORING_CELLS = 12;
99 /** @hide */
100 public static final int OP_CALL_PHONE = 13;
101 /** @hide */
102 public static final int OP_READ_SMS = 14;
103 /** @hide */
104 public static final int OP_WRITE_SMS = 15;
105 /** @hide */
106 public static final int OP_RECEIVE_SMS = 16;
107 /** @hide */
108 public static final int OP_RECEIVE_EMERGECY_SMS = 17;
109 /** @hide */
110 public static final int OP_RECEIVE_MMS = 18;
111 /** @hide */
112 public static final int OP_RECEIVE_WAP_PUSH = 19;
113 /** @hide */
114 public static final int OP_SEND_SMS = 20;
115 /** @hide */
116 public static final int OP_READ_ICC_SMS = 21;
117 /** @hide */
118 public static final int OP_WRITE_ICC_SMS = 22;
119 /** @hide */
120 public static final int OP_WRITE_SETTINGS = 23;
121 /** @hide */
122 public static final int OP_SYSTEM_ALERT_WINDOW = 24;
123 /** @hide */
124 public static final int OP_ACCESS_NOTIFICATIONS = 25;
125 /** @hide */
126 public static final int OP_CAMERA = 26;
127 /** @hide */
128 public static final int OP_RECORD_AUDIO = 27;
129 /** @hide */
130 public static final int OP_PLAY_AUDIO = 28;
131 /** @hide */
132 public static final int OP_READ_CLIPBOARD = 29;
133 /** @hide */
134 public static final int OP_WRITE_CLIPBOARD = 30;
135 /** @hide */
136 public static final int OP_TAKE_MEDIA_BUTTONS = 31;
137 /** @hide */
138 public static final int OP_TAKE_AUDIO_FOCUS = 32;
139 /** @hide */
140 public static final int OP_AUDIO_MASTER_VOLUME = 33;
141 /** @hide */
142 public static final int OP_AUDIO_VOICE_VOLUME = 34;
143 /** @hide */
144 public static final int OP_AUDIO_RING_VOLUME = 35;
145 /** @hide */
146 public static final int OP_AUDIO_MEDIA_VOLUME = 36;
147 /** @hide */
148 public static final int OP_AUDIO_ALARM_VOLUME = 37;
149 /** @hide */
150 public static final int OP_AUDIO_NOTIFICATION_VOLUME = 38;
151 /** @hide */
152 public static final int OP_AUDIO_BLUETOOTH_VOLUME = 39;
153 /** @hide */
154 public static final int OP_WAKE_LOCK = 40;
155 /** Continually monitoring location data. */
156 public static final int OP_MONITOR_LOCATION = 41;
157 /** @hide */
158 public static final int _NUM_OP = 42;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800159
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800160 /**
161 * This maps each operation to the operation that serves as the
162 * switch to determine whether it is allowed. Generally this is
163 * a 1:1 mapping, but for some things (like location) that have
164 * multiple low-level operations being tracked that should be
165 * presented to hte user as one switch then this can be used to
166 * make them all controlled by the same single operation.
167 */
168 private static int[] sOpToSwitch = new int[] {
169 OP_COARSE_LOCATION,
170 OP_COARSE_LOCATION,
171 OP_COARSE_LOCATION,
172 OP_VIBRATE,
173 OP_READ_CONTACTS,
174 OP_WRITE_CONTACTS,
175 OP_READ_CALL_LOG,
176 OP_WRITE_CALL_LOG,
177 OP_READ_CALENDAR,
178 OP_WRITE_CALENDAR,
179 OP_COARSE_LOCATION,
180 OP_POST_NOTIFICATION,
181 OP_COARSE_LOCATION,
182 OP_CALL_PHONE,
Dianne Hackbornf51f6122013-02-04 18:23:34 -0800183 OP_READ_SMS,
184 OP_WRITE_SMS,
185 OP_READ_SMS,
186 OP_READ_SMS,
187 OP_READ_SMS,
188 OP_READ_SMS,
189 OP_WRITE_SMS,
190 OP_READ_SMS,
191 OP_WRITE_SMS,
Dianne Hackborn961321f2013-02-05 17:22:41 -0800192 OP_WRITE_SETTINGS,
Dianne Hackbornc2293022013-02-06 23:14:49 -0800193 OP_SYSTEM_ALERT_WINDOW,
Daniel Sandlerfde19b12013-01-17 00:21:05 -0500194 OP_ACCESS_NOTIFICATIONS,
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800195 OP_CAMERA,
196 OP_RECORD_AUDIO,
197 OP_PLAY_AUDIO,
Dianne Hackbornefcc1a22013-02-25 18:02:35 -0800198 OP_READ_CLIPBOARD,
199 OP_WRITE_CLIPBOARD,
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700200 OP_TAKE_MEDIA_BUTTONS,
201 OP_TAKE_AUDIO_FOCUS,
202 OP_AUDIO_MASTER_VOLUME,
203 OP_AUDIO_VOICE_VOLUME,
204 OP_AUDIO_RING_VOLUME,
205 OP_AUDIO_MEDIA_VOLUME,
206 OP_AUDIO_ALARM_VOLUME,
207 OP_AUDIO_NOTIFICATION_VOLUME,
208 OP_AUDIO_BLUETOOTH_VOLUME,
Dianne Hackborn713df152013-05-17 11:27:57 -0700209 OP_WAKE_LOCK,
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700210 OP_COARSE_LOCATION,
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800211 };
212
213 /**
214 * This provides a simple name for each operation to be used
215 * in debug output.
216 */
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800217 private static String[] sOpNames = new String[] {
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800218 "COARSE_LOCATION",
219 "FINE_LOCATION",
220 "GPS",
221 "VIBRATE",
222 "READ_CONTACTS",
223 "WRITE_CONTACTS",
224 "READ_CALL_LOG",
225 "WRITE_CALL_LOG",
226 "READ_CALENDAR",
227 "WRITE_CALENDAR",
228 "WIFI_SCAN",
229 "POST_NOTIFICATION",
230 "NEIGHBORING_CELLS",
231 "CALL_PHONE",
Dianne Hackbornf51f6122013-02-04 18:23:34 -0800232 "READ_SMS",
233 "WRITE_SMS",
234 "RECEIVE_SMS",
235 "RECEIVE_EMERGECY_SMS",
236 "RECEIVE_MMS",
237 "RECEIVE_WAP_PUSH",
238 "SEND_SMS",
239 "READ_ICC_SMS",
240 "WRITE_ICC_SMS",
Dianne Hackborn961321f2013-02-05 17:22:41 -0800241 "WRITE_SETTINGS",
Dianne Hackbornc2293022013-02-06 23:14:49 -0800242 "SYSTEM_ALERT_WINDOW",
Daniel Sandlerfde19b12013-01-17 00:21:05 -0500243 "ACCESS_NOTIFICATIONS",
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800244 "CAMERA",
245 "RECORD_AUDIO",
246 "PLAY_AUDIO",
Dianne Hackbornefcc1a22013-02-25 18:02:35 -0800247 "READ_CLIPBOARD",
248 "WRITE_CLIPBOARD",
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700249 "TAKE_MEDIA_BUTTONS",
250 "TAKE_AUDIO_FOCUS",
251 "AUDIO_MASTER_VOLUME",
252 "AUDIO_VOICE_VOLUME",
253 "AUDIO_RING_VOLUME",
254 "AUDIO_MEDIA_VOLUME",
255 "AUDIO_ALARM_VOLUME",
256 "AUDIO_NOTIFICATION_VOLUME",
257 "AUDIO_BLUETOOTH_VOLUME",
Dianne Hackborn713df152013-05-17 11:27:57 -0700258 "WAKE_LOCK",
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700259 "MONITOR_LOCATION",
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800260 };
261
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800262 /**
263 * This optionally maps a permission to an operation. If there
264 * is no permission associated with an operation, it is null.
265 */
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800266 private static String[] sOpPerms = new String[] {
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800267 android.Manifest.permission.ACCESS_COARSE_LOCATION,
268 android.Manifest.permission.ACCESS_FINE_LOCATION,
269 null,
270 android.Manifest.permission.VIBRATE,
271 android.Manifest.permission.READ_CONTACTS,
272 android.Manifest.permission.WRITE_CONTACTS,
273 android.Manifest.permission.READ_CALL_LOG,
274 android.Manifest.permission.WRITE_CALL_LOG,
275 android.Manifest.permission.READ_CALENDAR,
276 android.Manifest.permission.WRITE_CALENDAR,
277 null, // no permission required for notifications
278 android.Manifest.permission.ACCESS_WIFI_STATE,
279 null, // neighboring cells shares the coarse location perm
280 android.Manifest.permission.CALL_PHONE,
Dianne Hackbornf51f6122013-02-04 18:23:34 -0800281 android.Manifest.permission.READ_SMS,
282 android.Manifest.permission.WRITE_SMS,
283 android.Manifest.permission.RECEIVE_SMS,
284 android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST,
285 android.Manifest.permission.RECEIVE_MMS,
286 android.Manifest.permission.RECEIVE_WAP_PUSH,
287 android.Manifest.permission.SEND_SMS,
288 android.Manifest.permission.READ_SMS,
289 android.Manifest.permission.WRITE_SMS,
Dianne Hackborn961321f2013-02-05 17:22:41 -0800290 android.Manifest.permission.WRITE_SETTINGS,
Dianne Hackbornc2293022013-02-06 23:14:49 -0800291 android.Manifest.permission.SYSTEM_ALERT_WINDOW,
Daniel Sandlerfde19b12013-01-17 00:21:05 -0500292 android.Manifest.permission.ACCESS_NOTIFICATIONS,
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800293 android.Manifest.permission.CAMERA,
294 android.Manifest.permission.RECORD_AUDIO,
295 null, // no permission for playing audio
Dianne Hackbornefcc1a22013-02-25 18:02:35 -0800296 null, // no permission for reading clipboard
297 null, // no permission for writing clipboard
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700298 null, // no permission for taking media buttons
299 null, // no permission for taking audio focus
300 null, // no permission for changing master volume
301 null, // no permission for changing voice volume
302 null, // no permission for changing ring volume
303 null, // no permission for changing media volume
304 null, // no permission for changing alarm volume
305 null, // no permission for changing notification volume
306 null, // no permission for changing bluetooth volume
Dianne Hackborn713df152013-05-17 11:27:57 -0700307 android.Manifest.permission.WAKE_LOCK,
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700308 null, // no permission for generic location monitoring
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800309 };
310
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800311 /**
312 * Retrieve the op switch that controls the given operation.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700313 * @hide
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800314 */
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800315 public static int opToSwitch(int op) {
316 return sOpToSwitch[op];
317 }
318
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800319 /**
320 * Retrieve a non-localized name for the operation, for debugging output.
321 */
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800322 public static String opToName(int op) {
Dianne Hackbornc2293022013-02-06 23:14:49 -0800323 if (op == OP_NONE) return "NONE";
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800324 return op < sOpNames.length ? sOpNames[op] : ("Unknown(" + op + ")");
325 }
326
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800327 /**
328 * Retrieve the permission associated with an operation, or null if there is not one.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700329 * @hide
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800330 */
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800331 public static String opToPermission(int op) {
332 return sOpPerms[op];
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800333 }
334
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800335 /**
336 * Class holding all of the operation information associated with an app.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700337 * @hide
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800338 */
Dianne Hackborn35654b62013-01-14 17:38:02 -0800339 public static class PackageOps implements Parcelable {
340 private final String mPackageName;
341 private final int mUid;
342 private final List<OpEntry> mEntries;
343
344 public PackageOps(String packageName, int uid, List<OpEntry> entries) {
345 mPackageName = packageName;
346 mUid = uid;
347 mEntries = entries;
348 }
349
350 public String getPackageName() {
351 return mPackageName;
352 }
353
354 public int getUid() {
355 return mUid;
356 }
357
358 public List<OpEntry> getOps() {
359 return mEntries;
360 }
361
362 @Override
363 public int describeContents() {
364 return 0;
365 }
366
367 @Override
368 public void writeToParcel(Parcel dest, int flags) {
369 dest.writeString(mPackageName);
370 dest.writeInt(mUid);
371 dest.writeInt(mEntries.size());
372 for (int i=0; i<mEntries.size(); i++) {
373 mEntries.get(i).writeToParcel(dest, flags);
374 }
375 }
376
377 PackageOps(Parcel source) {
378 mPackageName = source.readString();
379 mUid = source.readInt();
380 mEntries = new ArrayList<OpEntry>();
381 final int N = source.readInt();
382 for (int i=0; i<N; i++) {
383 mEntries.add(OpEntry.CREATOR.createFromParcel(source));
384 }
385 }
386
387 public static final Creator<PackageOps> CREATOR = new Creator<PackageOps>() {
388 @Override public PackageOps createFromParcel(Parcel source) {
389 return new PackageOps(source);
390 }
391
392 @Override public PackageOps[] newArray(int size) {
393 return new PackageOps[size];
394 }
395 };
396 }
397
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800398 /**
399 * Class holding the information about one unique operation of an application.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700400 * @hide
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800401 */
Dianne Hackborn35654b62013-01-14 17:38:02 -0800402 public static class OpEntry implements Parcelable {
403 private final int mOp;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800404 private final int mMode;
Dianne Hackborn35654b62013-01-14 17:38:02 -0800405 private final long mTime;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800406 private final long mRejectTime;
Dianne Hackborn35654b62013-01-14 17:38:02 -0800407 private final int mDuration;
408
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800409 public OpEntry(int op, int mode, long time, long rejectTime, int duration) {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800410 mOp = op;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800411 mMode = mode;
Dianne Hackborn35654b62013-01-14 17:38:02 -0800412 mTime = time;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800413 mRejectTime = rejectTime;
Dianne Hackborn35654b62013-01-14 17:38:02 -0800414 mDuration = duration;
415 }
416
417 public int getOp() {
418 return mOp;
419 }
420
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800421 public int getMode() {
422 return mMode;
423 }
424
Dianne Hackborn35654b62013-01-14 17:38:02 -0800425 public long getTime() {
426 return mTime;
427 }
428
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800429 public long getRejectTime() {
430 return mRejectTime;
431 }
432
Dianne Hackborn35654b62013-01-14 17:38:02 -0800433 public boolean isRunning() {
434 return mDuration == -1;
435 }
436
437 public int getDuration() {
438 return mDuration == -1 ? (int)(System.currentTimeMillis()-mTime) : mDuration;
439 }
440
441 @Override
442 public int describeContents() {
443 return 0;
444 }
445
446 @Override
447 public void writeToParcel(Parcel dest, int flags) {
448 dest.writeInt(mOp);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800449 dest.writeInt(mMode);
Dianne Hackborn35654b62013-01-14 17:38:02 -0800450 dest.writeLong(mTime);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800451 dest.writeLong(mRejectTime);
Dianne Hackborn35654b62013-01-14 17:38:02 -0800452 dest.writeInt(mDuration);
453 }
454
455 OpEntry(Parcel source) {
456 mOp = source.readInt();
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800457 mMode = source.readInt();
Dianne Hackborn35654b62013-01-14 17:38:02 -0800458 mTime = source.readLong();
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800459 mRejectTime = source.readLong();
Dianne Hackborn35654b62013-01-14 17:38:02 -0800460 mDuration = source.readInt();
461 }
462
463 public static final Creator<OpEntry> CREATOR = new Creator<OpEntry>() {
464 @Override public OpEntry createFromParcel(Parcel source) {
465 return new OpEntry(source);
466 }
467
468 @Override public OpEntry[] newArray(int size) {
469 return new OpEntry[size];
470 }
471 };
472 }
473
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800474 /**
475 * Callback for notification of changes to operation state.
476 */
Dianne Hackbornc2293022013-02-06 23:14:49 -0800477 public interface Callback {
478 public void opChanged(int op, String packageName);
479 }
480
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700481 AppOpsManager(Context context, IAppOpsService service) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800482 mContext = context;
483 mService = service;
484 }
485
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800486 /**
487 * Retrieve current operation state for all applications.
488 *
489 * @param ops The set of operations you are interested in, or null if you want all of them.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700490 * @hide
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800491 */
Dianne Hackborn35654b62013-01-14 17:38:02 -0800492 public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
493 try {
494 return mService.getPackagesForOps(ops);
495 } catch (RemoteException e) {
496 }
497 return null;
498 }
499
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800500 /**
501 * Retrieve current operation state for one application.
502 *
503 * @param uid The uid of the application of interest.
504 * @param packageName The name of the application of interest.
505 * @param ops The set of operations you are interested in, or null if you want all of them.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700506 * @hide
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800507 */
Dianne Hackborn72e39832013-01-18 18:36:09 -0800508 public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, int[] ops) {
509 try {
510 return mService.getOpsForPackage(uid, packageName, ops);
511 } catch (RemoteException e) {
512 }
513 return null;
514 }
515
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700516 /** @hide */
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800517 public void setMode(int code, int uid, String packageName, int mode) {
518 try {
519 mService.setMode(code, uid, packageName, mode);
520 } catch (RemoteException e) {
521 }
522 }
523
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700524 /**
525 * Monitor for changes to the operating mode for the given op in the given app package.
526 * @param op The operation to monitor, one of OP_*.
527 * @param packageName The name of the application to monitor.
528 * @param callback Where to report changes.
529 */
Dianne Hackbornc2293022013-02-06 23:14:49 -0800530 public void startWatchingMode(int op, String packageName, final Callback callback) {
531 synchronized (mModeWatchers) {
532 IAppOpsCallback cb = mModeWatchers.get(callback);
533 if (cb == null) {
534 cb = new IAppOpsCallback.Stub() {
535 public void opChanged(int op, String packageName) {
536 callback.opChanged(op, packageName);
537 }
538 };
539 mModeWatchers.put(callback, cb);
540 }
541 try {
542 mService.startWatchingMode(op, packageName, cb);
543 } catch (RemoteException e) {
544 }
545 }
546 }
547
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700548 /**
549 * Stop monitoring that was previously started with {@link #startWatchingMode}. All
550 * monitoring associated with this callback will be removed.
551 */
Dianne Hackbornc2293022013-02-06 23:14:49 -0800552 public void stopWatchingMode(Callback callback) {
553 synchronized (mModeWatchers) {
554 IAppOpsCallback cb = mModeWatchers.get(callback);
555 if (cb != null) {
556 try {
557 mService.stopWatchingMode(cb);
558 } catch (RemoteException e) {
559 }
560 }
561 }
562 }
563
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700564 /**
565 * Do a quick check for whether an application might be able to perform an operation.
566 * This is <em>not</em> a security check; you must use {@link #noteOp(int, int, String)}
567 * or {@link #startOp(int, int, String)} for your actual security checks, which also
568 * ensure that the given uid and package name are consistent. This function can just be
569 * used for a quick check to see if an operation has been disabled for the application,
570 * as an early reject of some work. This does not modify the time stamp or other data
571 * about the operation.
572 * @param op The operation to check. One of the OP_* constants.
573 * @param uid The user id of the application attempting to perform the operation.
574 * @param packageName The name of the application attempting to perform the operation.
575 * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
576 * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
577 * causing the app to crash).
578 * @throws SecurityException If the app has been configured to crash on this op.
579 */
Dianne Hackborn35654b62013-01-14 17:38:02 -0800580 public int checkOp(int op, int uid, String packageName) {
581 try {
582 int mode = mService.checkOperation(op, uid, packageName);
583 if (mode == MODE_ERRORED) {
584 throw new SecurityException("Operation not allowed");
585 }
586 return mode;
587 } catch (RemoteException e) {
588 }
589 return MODE_IGNORED;
590 }
591
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700592 /**
593 * Like {@link #checkOp} but instead of throwing a {@link SecurityException} it
594 * returns {@link #MODE_ERRORED}.
595 */
Dianne Hackborn35654b62013-01-14 17:38:02 -0800596 public int checkOpNoThrow(int op, int uid, String packageName) {
597 try {
598 return mService.checkOperation(op, uid, packageName);
599 } catch (RemoteException e) {
600 }
601 return MODE_IGNORED;
602 }
603
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700604 /**
605 * Make note of an application performing an operation. Note that you must pass
606 * in both the uid and name of the application to be checked; this function will verify
607 * that these two match, and if not, return {@link #MODE_IGNORED}. If this call
608 * succeeds, the last execution time of the operation for this app will be updated to
609 * the current time.
610 * @param op The operation to note. One of the OP_* constants.
611 * @param uid The user id of the application attempting to perform the operation.
612 * @param packageName The name of the application attempting to perform the operation.
613 * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
614 * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
615 * causing the app to crash).
616 * @throws SecurityException If the app has been configured to crash on this op.
617 */
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800618 public int noteOp(int op, int uid, String packageName) {
619 try {
620 int mode = mService.noteOperation(op, uid, packageName);
621 if (mode == MODE_ERRORED) {
622 throw new SecurityException("Operation not allowed");
623 }
624 return mode;
625 } catch (RemoteException e) {
626 }
627 return MODE_IGNORED;
628 }
629
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700630 /**
631 * Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
632 * returns {@link #MODE_ERRORED}.
633 */
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800634 public int noteOpNoThrow(int op, int uid, String packageName) {
635 try {
636 return mService.noteOperation(op, uid, packageName);
637 } catch (RemoteException e) {
638 }
639 return MODE_IGNORED;
640 }
641
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700642 /** @hide */
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800643 public int noteOp(int op) {
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -0800644 return noteOp(op, Process.myUid(), mContext.getBasePackageName());
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800645 }
646
Dianne Hackborne98f5db2013-07-17 17:23:25 -0700647 /** @hide */
648 public static IBinder getToken(IAppOpsService service) {
649 synchronized (AppOpsManager.class) {
650 if (sToken != null) {
651 return sToken;
652 }
653 try {
654 sToken = service.getToken(new Binder());
655 } catch (RemoteException e) {
656 // System is dead, whatevs.
657 }
658 return sToken;
659 }
660 }
661
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700662 /**
663 * Report that an application has started executing a long-running operation. Note that you
664 * must pass in both the uid and name of the application to be checked; this function will
665 * verify that these two match, and if not, return {@link #MODE_IGNORED}. If this call
666 * succeeds, the last execution time of the operation for this app will be updated to
667 * the current time and the operation will be marked as "running". In this case you must
668 * later call {@link #finishOp(int, int, String)} to report when the application is no
669 * longer performing the operation.
670 * @param op The operation to start. One of the OP_* constants.
671 * @param uid The user id of the application attempting to perform the operation.
672 * @param packageName The name of the application attempting to perform the operation.
673 * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
674 * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
675 * causing the app to crash).
676 * @throws SecurityException If the app has been configured to crash on this op.
677 */
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800678 public int startOp(int op, int uid, String packageName) {
679 try {
Dianne Hackborne98f5db2013-07-17 17:23:25 -0700680 int mode = mService.startOperation(getToken(mService), op, uid, packageName);
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800681 if (mode == MODE_ERRORED) {
682 throw new SecurityException("Operation not allowed");
683 }
684 return mode;
685 } catch (RemoteException e) {
686 }
687 return MODE_IGNORED;
688 }
689
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700690 /**
691 * Like {@link #startOp} but instead of throwing a {@link SecurityException} it
692 * returns {@link #MODE_ERRORED}.
693 */
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800694 public int startOpNoThrow(int op, int uid, String packageName) {
695 try {
Dianne Hackborne98f5db2013-07-17 17:23:25 -0700696 return mService.startOperation(getToken(mService), op, uid, packageName);
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800697 } catch (RemoteException e) {
698 }
699 return MODE_IGNORED;
700 }
701
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700702 /** @hide */
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800703 public int startOp(int op) {
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -0800704 return startOp(op, Process.myUid(), mContext.getBasePackageName());
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800705 }
706
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700707 /**
708 * Report that an application is no longer performing an operation that had previously
709 * been started with {@link #startOp(int, int, String)}. There is no validation of input
710 * or result; the parameters supplied here must be the exact same ones previously passed
711 * in when starting the operation.
712 */
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800713 public void finishOp(int op, int uid, String packageName) {
714 try {
Dianne Hackborne98f5db2013-07-17 17:23:25 -0700715 mService.finishOperation(getToken(mService), op, uid, packageName);
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800716 } catch (RemoteException e) {
717 }
718 }
719
720 public void finishOp(int op) {
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -0800721 finishOp(op, Process.myUid(), mContext.getBasePackageName());
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800722 }
723}