blob: aece46298364d7cd7713046c56d8d2118f4f60ec [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;
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -070026import java.util.HashMap;
Dianne Hackborn35654b62013-01-14 17:38:02 -080027import java.util.List;
28
Dianne Hackborna06de0f2012-12-11 16:34:47 -080029import android.content.Context;
Dianne Hackborn35654b62013-01-14 17:38:02 -080030import android.os.Parcel;
31import android.os.Parcelable;
Dianne Hackborna06de0f2012-12-11 16:34:47 -080032import android.os.Process;
33import android.os.RemoteException;
34
Dianne Hackbornd7d28e62013-02-12 14:59:53 -080035/**
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -070036 * API for interacting with "application operation" tracking.
Dianne Hackbornd7d28e62013-02-12 14:59:53 -080037 *
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -070038 * <p>This API is not generally intended for third party application developers; most
39 * features are only available to system applicatins. Obtain an instance of it through
40 * {@link Context#getSystemService(String) Context.getSystemService} with
41 * {@link Context#APP_OPS_SERVICE Context.APP_OPS_SERVICE}.</p>
Dianne Hackbornd7d28e62013-02-12 14:59:53 -080042 */
Dianne Hackborna06de0f2012-12-11 16:34:47 -080043public class AppOpsManager {
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -070044 /**
45 * <p>App ops allows callers to:</p>
46 *
47 * <ul>
48 * <li> Note when operations are happening, and find out if they are allowed for the current
49 * caller.</li>
50 * <li> Disallow specific apps from doing specific operations.</li>
51 * <li> Collect all of the current information about operations that have been executed or
52 * are not being allowed.</li>
53 * <li> Monitor for changes in whether an operation is allowed.</li>
54 * </ul>
55 *
56 * <p>Each operation is identified by a single integer; these integers are a fixed set of
57 * operations, enumerated by the OP_* constants.
58 *
59 * <p></p>When checking operations, the result is a "mode" integer indicating the current
60 * setting for the operation under that caller: MODE_ALLOWED, MODE_IGNORED (don't execute
61 * the operation but fake its behavior enough so that the caller doesn't crash),
62 * MODE_ERRORED (throw a SecurityException back to the caller; the normal operation calls
63 * will do this for you).
64 */
65
Dianne Hackborna06de0f2012-12-11 16:34:47 -080066 final Context mContext;
67 final IAppOpsService mService;
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -070068 final ArrayMap<OnOpChangedListener, IAppOpsCallback> mModeWatchers
69 = new ArrayMap<OnOpChangedListener, IAppOpsCallback>();
Dianne Hackborna06de0f2012-12-11 16:34:47 -080070
Dianne Hackborne98f5db2013-07-17 17:23:25 -070071 static IBinder sToken;
72
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -070073 /**
74 * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller is
75 * allowed to perform the given operation.
76 */
Dianne Hackborna06de0f2012-12-11 16:34:47 -080077 public static final int MODE_ALLOWED = 0;
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -070078
79 /**
80 * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller is
81 * not allowed to perform the given operation, and this attempt should
82 * <em>silently fail</em> (it should not cause the app to crash).
83 */
Dianne Hackborna06de0f2012-12-11 16:34:47 -080084 public static final int MODE_IGNORED = 1;
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -070085
86 /**
87 * Result from {@link #checkOpNoThrow}, {@link #noteOpNoThrow}, {@link #startOpNoThrow}: the
88 * given caller is not allowed to perform the given operation, and this attempt should
89 * cause it to have a fatal error, typically a {@link SecurityException}.
90 */
Dianne Hackborna06de0f2012-12-11 16:34:47 -080091 public static final int MODE_ERRORED = 2;
92
Daniel Sandlerfde19b12013-01-17 00:21:05 -050093 // when adding one of these:
94 // - increment _NUM_OP
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -070095 // - add rows to sOpToSwitch, sOpToString, sOpNames, sOpPerms, sOpDefaultMode
Daniel Sandlerfde19b12013-01-17 00:21:05 -050096 // - add descriptive strings to Settings/res/values/arrays.xml
David Christie0b837452013-07-29 16:02:13 -070097 // - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app)
Dianne Hackborn1304f4a2013-07-09 18:17:27 -070098
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -070099 /** @hide No operation specified. */
Dianne Hackbornf51f6122013-02-04 18:23:34 -0800100 public static final int OP_NONE = -1;
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700101 /** @hide Access to coarse location information. */
Dianne Hackborn35654b62013-01-14 17:38:02 -0800102 public static final int OP_COARSE_LOCATION = 0;
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700103 /** @hide Access to fine location information. */
Dianne Hackborn35654b62013-01-14 17:38:02 -0800104 public static final int OP_FINE_LOCATION = 1;
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700105 /** @hide Causing GPS to run. */
Dianne Hackborn35654b62013-01-14 17:38:02 -0800106 public static final int OP_GPS = 2;
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800107 /** @hide */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700108 public static final int OP_VIBRATE = 3;
109 /** @hide */
110 public static final int OP_READ_CONTACTS = 4;
111 /** @hide */
112 public static final int OP_WRITE_CONTACTS = 5;
113 /** @hide */
114 public static final int OP_READ_CALL_LOG = 6;
115 /** @hide */
116 public static final int OP_WRITE_CALL_LOG = 7;
117 /** @hide */
118 public static final int OP_READ_CALENDAR = 8;
119 /** @hide */
120 public static final int OP_WRITE_CALENDAR = 9;
121 /** @hide */
122 public static final int OP_WIFI_SCAN = 10;
123 /** @hide */
124 public static final int OP_POST_NOTIFICATION = 11;
125 /** @hide */
126 public static final int OP_NEIGHBORING_CELLS = 12;
127 /** @hide */
128 public static final int OP_CALL_PHONE = 13;
129 /** @hide */
130 public static final int OP_READ_SMS = 14;
131 /** @hide */
132 public static final int OP_WRITE_SMS = 15;
133 /** @hide */
134 public static final int OP_RECEIVE_SMS = 16;
135 /** @hide */
136 public static final int OP_RECEIVE_EMERGECY_SMS = 17;
137 /** @hide */
138 public static final int OP_RECEIVE_MMS = 18;
139 /** @hide */
140 public static final int OP_RECEIVE_WAP_PUSH = 19;
141 /** @hide */
142 public static final int OP_SEND_SMS = 20;
143 /** @hide */
144 public static final int OP_READ_ICC_SMS = 21;
145 /** @hide */
146 public static final int OP_WRITE_ICC_SMS = 22;
147 /** @hide */
148 public static final int OP_WRITE_SETTINGS = 23;
149 /** @hide */
150 public static final int OP_SYSTEM_ALERT_WINDOW = 24;
151 /** @hide */
152 public static final int OP_ACCESS_NOTIFICATIONS = 25;
153 /** @hide */
154 public static final int OP_CAMERA = 26;
155 /** @hide */
156 public static final int OP_RECORD_AUDIO = 27;
157 /** @hide */
158 public static final int OP_PLAY_AUDIO = 28;
159 /** @hide */
160 public static final int OP_READ_CLIPBOARD = 29;
161 /** @hide */
162 public static final int OP_WRITE_CLIPBOARD = 30;
163 /** @hide */
164 public static final int OP_TAKE_MEDIA_BUTTONS = 31;
165 /** @hide */
166 public static final int OP_TAKE_AUDIO_FOCUS = 32;
167 /** @hide */
168 public static final int OP_AUDIO_MASTER_VOLUME = 33;
169 /** @hide */
170 public static final int OP_AUDIO_VOICE_VOLUME = 34;
171 /** @hide */
172 public static final int OP_AUDIO_RING_VOLUME = 35;
173 /** @hide */
174 public static final int OP_AUDIO_MEDIA_VOLUME = 36;
175 /** @hide */
176 public static final int OP_AUDIO_ALARM_VOLUME = 37;
177 /** @hide */
178 public static final int OP_AUDIO_NOTIFICATION_VOLUME = 38;
179 /** @hide */
180 public static final int OP_AUDIO_BLUETOOTH_VOLUME = 39;
181 /** @hide */
182 public static final int OP_WAKE_LOCK = 40;
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700183 /** @hide Continually monitoring location data. */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700184 public static final int OP_MONITOR_LOCATION = 41;
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700185 /** @hide Continually monitoring location data with a relatively high power request. */
David Christie0b837452013-07-29 16:02:13 -0700186 public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700187 /** @hide */
David Christie0b837452013-07-29 16:02:13 -0700188 public static final int _NUM_OP = 43;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800189
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700190 /** Access to coarse location information. */
191 public static final String OPSTR_COARSE_LOCATION =
192 "android:coarse_location";
193 /** Access to fine location information. */
194 public static final String OPSTR_FINE_LOCATION =
195 "android:fine_location";
196 /** Continually monitoring location data. */
197 public static final String OPSTR_MONITOR_LOCATION
198 = "android:monitor_location";
199 /** Continually monitoring location data with a relatively high power request. */
200 public static final String OPSTR_MONITOR_HIGH_POWER_LOCATION
201 = "android:monitor_location_high_power";
202
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800203 /**
204 * This maps each operation to the operation that serves as the
205 * switch to determine whether it is allowed. Generally this is
206 * a 1:1 mapping, but for some things (like location) that have
207 * multiple low-level operations being tracked that should be
David Christie0b837452013-07-29 16:02:13 -0700208 * presented to the user as one switch then this can be used to
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800209 * make them all controlled by the same single operation.
210 */
211 private static int[] sOpToSwitch = new int[] {
212 OP_COARSE_LOCATION,
213 OP_COARSE_LOCATION,
214 OP_COARSE_LOCATION,
215 OP_VIBRATE,
216 OP_READ_CONTACTS,
217 OP_WRITE_CONTACTS,
218 OP_READ_CALL_LOG,
219 OP_WRITE_CALL_LOG,
220 OP_READ_CALENDAR,
221 OP_WRITE_CALENDAR,
222 OP_COARSE_LOCATION,
223 OP_POST_NOTIFICATION,
224 OP_COARSE_LOCATION,
225 OP_CALL_PHONE,
Dianne Hackbornf51f6122013-02-04 18:23:34 -0800226 OP_READ_SMS,
227 OP_WRITE_SMS,
David Braun18966a82013-09-10 13:14:46 -0700228 OP_RECEIVE_SMS,
229 OP_RECEIVE_SMS,
230 OP_RECEIVE_SMS,
231 OP_RECEIVE_SMS,
232 OP_SEND_SMS,
Dianne Hackbornf51f6122013-02-04 18:23:34 -0800233 OP_READ_SMS,
234 OP_WRITE_SMS,
Dianne Hackborn961321f2013-02-05 17:22:41 -0800235 OP_WRITE_SETTINGS,
Dianne Hackbornc2293022013-02-06 23:14:49 -0800236 OP_SYSTEM_ALERT_WINDOW,
Daniel Sandlerfde19b12013-01-17 00:21:05 -0500237 OP_ACCESS_NOTIFICATIONS,
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800238 OP_CAMERA,
239 OP_RECORD_AUDIO,
240 OP_PLAY_AUDIO,
Dianne Hackbornefcc1a22013-02-25 18:02:35 -0800241 OP_READ_CLIPBOARD,
242 OP_WRITE_CLIPBOARD,
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700243 OP_TAKE_MEDIA_BUTTONS,
244 OP_TAKE_AUDIO_FOCUS,
245 OP_AUDIO_MASTER_VOLUME,
246 OP_AUDIO_VOICE_VOLUME,
247 OP_AUDIO_RING_VOLUME,
248 OP_AUDIO_MEDIA_VOLUME,
249 OP_AUDIO_ALARM_VOLUME,
250 OP_AUDIO_NOTIFICATION_VOLUME,
251 OP_AUDIO_BLUETOOTH_VOLUME,
Dianne Hackborn713df152013-05-17 11:27:57 -0700252 OP_WAKE_LOCK,
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700253 OP_COARSE_LOCATION,
David Christie0b837452013-07-29 16:02:13 -0700254 OP_COARSE_LOCATION,
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800255 };
256
257 /**
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700258 * This maps each operation to the public string constant for it.
259 * If it doesn't have a public string constant, it maps to null.
260 */
261 private static String[] sOpToString = new String[] {
262 OPSTR_COARSE_LOCATION,
263 OPSTR_FINE_LOCATION,
264 null,
265 null,
266 null,
267 null,
268 null,
269 null,
270 null,
271 null,
272 null,
273 null,
274 null,
275 null,
276 null,
277 null,
278 null,
279 null,
280 null,
281 null,
282 null,
283 null,
284 null,
285 null,
286 null,
287 null,
288 null,
289 null,
290 null,
291 null,
292 null,
293 null,
294 null,
295 null,
296 null,
297 null,
298 null,
299 null,
300 null,
301 null,
302 null,
303 OPSTR_MONITOR_LOCATION,
304 OPSTR_MONITOR_HIGH_POWER_LOCATION,
305 };
306
307 /**
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800308 * This provides a simple name for each operation to be used
309 * in debug output.
310 */
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800311 private static String[] sOpNames = new String[] {
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800312 "COARSE_LOCATION",
313 "FINE_LOCATION",
314 "GPS",
315 "VIBRATE",
316 "READ_CONTACTS",
317 "WRITE_CONTACTS",
318 "READ_CALL_LOG",
319 "WRITE_CALL_LOG",
320 "READ_CALENDAR",
321 "WRITE_CALENDAR",
322 "WIFI_SCAN",
323 "POST_NOTIFICATION",
324 "NEIGHBORING_CELLS",
325 "CALL_PHONE",
Dianne Hackbornf51f6122013-02-04 18:23:34 -0800326 "READ_SMS",
327 "WRITE_SMS",
328 "RECEIVE_SMS",
329 "RECEIVE_EMERGECY_SMS",
330 "RECEIVE_MMS",
331 "RECEIVE_WAP_PUSH",
332 "SEND_SMS",
333 "READ_ICC_SMS",
334 "WRITE_ICC_SMS",
Dianne Hackborn961321f2013-02-05 17:22:41 -0800335 "WRITE_SETTINGS",
Dianne Hackbornc2293022013-02-06 23:14:49 -0800336 "SYSTEM_ALERT_WINDOW",
Daniel Sandlerfde19b12013-01-17 00:21:05 -0500337 "ACCESS_NOTIFICATIONS",
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800338 "CAMERA",
339 "RECORD_AUDIO",
340 "PLAY_AUDIO",
Dianne Hackbornefcc1a22013-02-25 18:02:35 -0800341 "READ_CLIPBOARD",
342 "WRITE_CLIPBOARD",
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700343 "TAKE_MEDIA_BUTTONS",
344 "TAKE_AUDIO_FOCUS",
345 "AUDIO_MASTER_VOLUME",
346 "AUDIO_VOICE_VOLUME",
347 "AUDIO_RING_VOLUME",
348 "AUDIO_MEDIA_VOLUME",
349 "AUDIO_ALARM_VOLUME",
350 "AUDIO_NOTIFICATION_VOLUME",
351 "AUDIO_BLUETOOTH_VOLUME",
Dianne Hackborn713df152013-05-17 11:27:57 -0700352 "WAKE_LOCK",
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700353 "MONITOR_LOCATION",
David Christie0b837452013-07-29 16:02:13 -0700354 "MONITOR_HIGH_POWER_LOCATION",
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800355 };
356
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800357 /**
358 * This optionally maps a permission to an operation. If there
359 * is no permission associated with an operation, it is null.
360 */
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800361 private static String[] sOpPerms = new String[] {
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800362 android.Manifest.permission.ACCESS_COARSE_LOCATION,
363 android.Manifest.permission.ACCESS_FINE_LOCATION,
364 null,
365 android.Manifest.permission.VIBRATE,
366 android.Manifest.permission.READ_CONTACTS,
367 android.Manifest.permission.WRITE_CONTACTS,
368 android.Manifest.permission.READ_CALL_LOG,
369 android.Manifest.permission.WRITE_CALL_LOG,
370 android.Manifest.permission.READ_CALENDAR,
371 android.Manifest.permission.WRITE_CALENDAR,
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800372 android.Manifest.permission.ACCESS_WIFI_STATE,
Robert Craigf97616c2013-10-07 12:32:02 -0400373 null, // no permission required for notifications
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800374 null, // neighboring cells shares the coarse location perm
375 android.Manifest.permission.CALL_PHONE,
Dianne Hackbornf51f6122013-02-04 18:23:34 -0800376 android.Manifest.permission.READ_SMS,
377 android.Manifest.permission.WRITE_SMS,
378 android.Manifest.permission.RECEIVE_SMS,
379 android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST,
380 android.Manifest.permission.RECEIVE_MMS,
381 android.Manifest.permission.RECEIVE_WAP_PUSH,
382 android.Manifest.permission.SEND_SMS,
383 android.Manifest.permission.READ_SMS,
384 android.Manifest.permission.WRITE_SMS,
Dianne Hackborn961321f2013-02-05 17:22:41 -0800385 android.Manifest.permission.WRITE_SETTINGS,
Dianne Hackbornc2293022013-02-06 23:14:49 -0800386 android.Manifest.permission.SYSTEM_ALERT_WINDOW,
Daniel Sandlerfde19b12013-01-17 00:21:05 -0500387 android.Manifest.permission.ACCESS_NOTIFICATIONS,
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800388 android.Manifest.permission.CAMERA,
389 android.Manifest.permission.RECORD_AUDIO,
390 null, // no permission for playing audio
Dianne Hackbornefcc1a22013-02-25 18:02:35 -0800391 null, // no permission for reading clipboard
392 null, // no permission for writing clipboard
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700393 null, // no permission for taking media buttons
394 null, // no permission for taking audio focus
395 null, // no permission for changing master volume
396 null, // no permission for changing voice volume
397 null, // no permission for changing ring volume
398 null, // no permission for changing media volume
399 null, // no permission for changing alarm volume
400 null, // no permission for changing notification volume
401 null, // no permission for changing bluetooth volume
Dianne Hackborn713df152013-05-17 11:27:57 -0700402 android.Manifest.permission.WAKE_LOCK,
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700403 null, // no permission for generic location monitoring
David Christie0b837452013-07-29 16:02:13 -0700404 null, // no permission for high power location monitoring
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800405 };
406
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800407 /**
David Braunf5d83192013-09-16 13:43:51 -0700408 * This specifies the default mode for each operation.
409 */
410 private static int[] sOpDefaultMode = new int[] {
411 AppOpsManager.MODE_ALLOWED,
412 AppOpsManager.MODE_ALLOWED,
413 AppOpsManager.MODE_ALLOWED,
414 AppOpsManager.MODE_ALLOWED,
415 AppOpsManager.MODE_ALLOWED,
416 AppOpsManager.MODE_ALLOWED,
417 AppOpsManager.MODE_ALLOWED,
418 AppOpsManager.MODE_ALLOWED,
419 AppOpsManager.MODE_ALLOWED,
420 AppOpsManager.MODE_ALLOWED,
421 AppOpsManager.MODE_ALLOWED,
422 AppOpsManager.MODE_ALLOWED,
423 AppOpsManager.MODE_ALLOWED,
424 AppOpsManager.MODE_ALLOWED,
425 AppOpsManager.MODE_ALLOWED,
426 AppOpsManager.MODE_IGNORED, // OP_WRITE_SMS
427 AppOpsManager.MODE_ALLOWED,
428 AppOpsManager.MODE_ALLOWED,
429 AppOpsManager.MODE_ALLOWED,
430 AppOpsManager.MODE_ALLOWED,
431 AppOpsManager.MODE_ALLOWED,
432 AppOpsManager.MODE_ALLOWED,
433 AppOpsManager.MODE_ALLOWED,
434 AppOpsManager.MODE_ALLOWED,
435 AppOpsManager.MODE_ALLOWED,
436 AppOpsManager.MODE_ALLOWED,
437 AppOpsManager.MODE_ALLOWED,
438 AppOpsManager.MODE_ALLOWED,
439 AppOpsManager.MODE_ALLOWED,
440 AppOpsManager.MODE_ALLOWED,
441 AppOpsManager.MODE_ALLOWED,
442 AppOpsManager.MODE_ALLOWED,
443 AppOpsManager.MODE_ALLOWED,
444 AppOpsManager.MODE_ALLOWED,
445 AppOpsManager.MODE_ALLOWED,
446 AppOpsManager.MODE_ALLOWED,
447 AppOpsManager.MODE_ALLOWED,
448 AppOpsManager.MODE_ALLOWED,
449 AppOpsManager.MODE_ALLOWED,
450 AppOpsManager.MODE_ALLOWED,
451 AppOpsManager.MODE_ALLOWED,
452 AppOpsManager.MODE_ALLOWED,
453 AppOpsManager.MODE_ALLOWED,
454 };
455
Dianne Hackborn8828d3a2013-09-25 16:47:10 -0700456 /**
457 * This specifies whether each option is allowed to be reset
458 * when resetting all app preferences. Disable reset for
459 * app ops that are under strong control of some part of the
460 * system (such as OP_WRITE_SMS, which should be allowed only
461 * for whichever app is selected as the current SMS app).
462 */
463 private static boolean[] sOpDisableReset = new boolean[] {
464 false,
465 false,
466 false,
467 false,
468 false,
469 false,
470 false,
471 false,
472 false,
473 false,
474 false,
475 false,
476 false,
477 false,
478 false,
479 true, // OP_WRITE_SMS
480 false,
481 false,
482 false,
483 false,
484 false,
485 false,
486 false,
487 false,
488 false,
489 false,
490 false,
491 false,
492 false,
493 false,
494 false,
495 false,
496 false,
497 false,
498 false,
499 false,
500 false,
501 false,
502 false,
503 false,
504 false,
505 false,
506 false,
507 };
508
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700509 private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>();
510
511 static {
512 if (sOpToSwitch.length != _NUM_OP) {
Dianne Hackborn8828d3a2013-09-25 16:47:10 -0700513 throw new IllegalStateException("sOpToSwitch length " + sOpToSwitch.length
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700514 + " should be " + _NUM_OP);
515 }
516 if (sOpToString.length != _NUM_OP) {
Dianne Hackborn8828d3a2013-09-25 16:47:10 -0700517 throw new IllegalStateException("sOpToString length " + sOpToString.length
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700518 + " should be " + _NUM_OP);
519 }
520 if (sOpNames.length != _NUM_OP) {
Dianne Hackborn8828d3a2013-09-25 16:47:10 -0700521 throw new IllegalStateException("sOpNames length " + sOpNames.length
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700522 + " should be " + _NUM_OP);
523 }
524 if (sOpPerms.length != _NUM_OP) {
Dianne Hackborn8828d3a2013-09-25 16:47:10 -0700525 throw new IllegalStateException("sOpPerms length " + sOpPerms.length
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700526 + " should be " + _NUM_OP);
527 }
528 if (sOpDefaultMode.length != _NUM_OP) {
Dianne Hackborn8828d3a2013-09-25 16:47:10 -0700529 throw new IllegalStateException("sOpDefaultMode length " + sOpDefaultMode.length
530 + " should be " + _NUM_OP);
531 }
532 if (sOpDisableReset.length != _NUM_OP) {
533 throw new IllegalStateException("sOpDisableReset length " + sOpDisableReset.length
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700534 + " should be " + _NUM_OP);
535 }
536 for (int i=0; i<_NUM_OP; i++) {
537 if (sOpToString[i] != null) {
538 sOpStrToOp.put(sOpToString[i], i);
539 }
540 }
541 }
542
David Braunf5d83192013-09-16 13:43:51 -0700543 /**
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800544 * Retrieve the op switch that controls the given operation.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700545 * @hide
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800546 */
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800547 public static int opToSwitch(int op) {
548 return sOpToSwitch[op];
549 }
550
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800551 /**
552 * Retrieve a non-localized name for the operation, for debugging output.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700553 * @hide
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800554 */
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800555 public static String opToName(int op) {
Dianne Hackbornc2293022013-02-06 23:14:49 -0800556 if (op == OP_NONE) return "NONE";
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800557 return op < sOpNames.length ? sOpNames[op] : ("Unknown(" + op + ")");
558 }
559
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800560 /**
561 * Retrieve the permission associated with an operation, or null if there is not one.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700562 * @hide
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800563 */
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800564 public static String opToPermission(int op) {
565 return sOpPerms[op];
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800566 }
567
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800568 /**
David Braunf5d83192013-09-16 13:43:51 -0700569 * Retrieve the default mode for the operation.
570 * @hide
571 */
572 public static int opToDefaultMode(int op) {
573 return sOpDefaultMode[op];
574 }
575
576 /**
Dianne Hackborn8828d3a2013-09-25 16:47:10 -0700577 * Retrieve whether the op allows itself to be reset.
578 * @hide
579 */
580 public static boolean opAllowsReset(int op) {
581 return !sOpDisableReset[op];
582 }
583
584 /**
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800585 * Class holding all of the operation information associated with an app.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700586 * @hide
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800587 */
Dianne Hackborn35654b62013-01-14 17:38:02 -0800588 public static class PackageOps implements Parcelable {
589 private final String mPackageName;
590 private final int mUid;
591 private final List<OpEntry> mEntries;
592
593 public PackageOps(String packageName, int uid, List<OpEntry> entries) {
594 mPackageName = packageName;
595 mUid = uid;
596 mEntries = entries;
597 }
598
599 public String getPackageName() {
600 return mPackageName;
601 }
602
603 public int getUid() {
604 return mUid;
605 }
606
607 public List<OpEntry> getOps() {
608 return mEntries;
609 }
610
611 @Override
612 public int describeContents() {
613 return 0;
614 }
615
616 @Override
617 public void writeToParcel(Parcel dest, int flags) {
618 dest.writeString(mPackageName);
619 dest.writeInt(mUid);
620 dest.writeInt(mEntries.size());
621 for (int i=0; i<mEntries.size(); i++) {
622 mEntries.get(i).writeToParcel(dest, flags);
623 }
624 }
625
626 PackageOps(Parcel source) {
627 mPackageName = source.readString();
628 mUid = source.readInt();
629 mEntries = new ArrayList<OpEntry>();
630 final int N = source.readInt();
631 for (int i=0; i<N; i++) {
632 mEntries.add(OpEntry.CREATOR.createFromParcel(source));
633 }
634 }
635
636 public static final Creator<PackageOps> CREATOR = new Creator<PackageOps>() {
637 @Override public PackageOps createFromParcel(Parcel source) {
638 return new PackageOps(source);
639 }
640
641 @Override public PackageOps[] newArray(int size) {
642 return new PackageOps[size];
643 }
644 };
645 }
646
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800647 /**
648 * Class holding the information about one unique operation of an application.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700649 * @hide
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800650 */
Dianne Hackborn35654b62013-01-14 17:38:02 -0800651 public static class OpEntry implements Parcelable {
652 private final int mOp;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800653 private final int mMode;
Dianne Hackborn35654b62013-01-14 17:38:02 -0800654 private final long mTime;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800655 private final long mRejectTime;
Dianne Hackborn35654b62013-01-14 17:38:02 -0800656 private final int mDuration;
657
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800658 public OpEntry(int op, int mode, long time, long rejectTime, int duration) {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800659 mOp = op;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800660 mMode = mode;
Dianne Hackborn35654b62013-01-14 17:38:02 -0800661 mTime = time;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800662 mRejectTime = rejectTime;
Dianne Hackborn35654b62013-01-14 17:38:02 -0800663 mDuration = duration;
664 }
665
666 public int getOp() {
667 return mOp;
668 }
669
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800670 public int getMode() {
671 return mMode;
672 }
673
Dianne Hackborn35654b62013-01-14 17:38:02 -0800674 public long getTime() {
675 return mTime;
676 }
677
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800678 public long getRejectTime() {
679 return mRejectTime;
680 }
681
Dianne Hackborn35654b62013-01-14 17:38:02 -0800682 public boolean isRunning() {
683 return mDuration == -1;
684 }
685
686 public int getDuration() {
687 return mDuration == -1 ? (int)(System.currentTimeMillis()-mTime) : mDuration;
688 }
689
690 @Override
691 public int describeContents() {
692 return 0;
693 }
694
695 @Override
696 public void writeToParcel(Parcel dest, int flags) {
697 dest.writeInt(mOp);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800698 dest.writeInt(mMode);
Dianne Hackborn35654b62013-01-14 17:38:02 -0800699 dest.writeLong(mTime);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800700 dest.writeLong(mRejectTime);
Dianne Hackborn35654b62013-01-14 17:38:02 -0800701 dest.writeInt(mDuration);
702 }
703
704 OpEntry(Parcel source) {
705 mOp = source.readInt();
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800706 mMode = source.readInt();
Dianne Hackborn35654b62013-01-14 17:38:02 -0800707 mTime = source.readLong();
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800708 mRejectTime = source.readLong();
Dianne Hackborn35654b62013-01-14 17:38:02 -0800709 mDuration = source.readInt();
710 }
711
712 public static final Creator<OpEntry> CREATOR = new Creator<OpEntry>() {
713 @Override public OpEntry createFromParcel(Parcel source) {
714 return new OpEntry(source);
715 }
716
717 @Override public OpEntry[] newArray(int size) {
718 return new OpEntry[size];
719 }
720 };
721 }
722
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800723 /**
724 * Callback for notification of changes to operation state.
725 */
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700726 public interface OnOpChangedListener {
727 public void onOpChanged(String op, String packageName);
728 }
729
730 /**
731 * Callback for notification of changes to operation state.
732 * This allows you to see the raw op codes instead of strings.
733 * @hide
734 */
735 public static class OnOpChangedInternalListener implements OnOpChangedListener {
736 public void onOpChanged(String op, String packageName) { }
737 public void onOpChanged(int op, String packageName) { }
Dianne Hackbornc2293022013-02-06 23:14:49 -0800738 }
739
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700740 AppOpsManager(Context context, IAppOpsService service) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800741 mContext = context;
742 mService = service;
743 }
744
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800745 /**
746 * Retrieve current operation state for all applications.
747 *
748 * @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 -0700749 * @hide
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800750 */
Dianne Hackborn35654b62013-01-14 17:38:02 -0800751 public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
752 try {
753 return mService.getPackagesForOps(ops);
754 } catch (RemoteException e) {
755 }
756 return null;
757 }
758
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800759 /**
760 * Retrieve current operation state for one application.
761 *
762 * @param uid The uid of the application of interest.
763 * @param packageName The name of the application of interest.
764 * @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 -0700765 * @hide
Dianne Hackbornd7d28e62013-02-12 14:59:53 -0800766 */
Dianne Hackborn72e39832013-01-18 18:36:09 -0800767 public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, int[] ops) {
768 try {
769 return mService.getOpsForPackage(uid, packageName, ops);
770 } catch (RemoteException e) {
771 }
772 return null;
773 }
774
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700775 /** @hide */
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800776 public void setMode(int code, int uid, String packageName, int mode) {
777 try {
778 mService.setMode(code, uid, packageName, mode);
779 } catch (RemoteException e) {
780 }
781 }
782
Dianne Hackborn607b4142013-08-02 18:10:10 -0700783 /** @hide */
784 public void resetAllModes() {
785 try {
786 mService.resetAllModes();
787 } catch (RemoteException e) {
788 }
789 }
790
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700791 /**
792 * Monitor for changes to the operating mode for the given op in the given app package.
Dianne Hackborne4cb66f2013-10-02 10:34:02 -0700793 * @param op The operation to monitor, one of OPSTR_*.
794 * @param packageName The name of the application to monitor.
795 * @param callback Where to report changes.
796 */
797 public void startWatchingMode(String op, String packageName,
798 final OnOpChangedListener callback) {
799 startWatchingMode(strOpToOp(op), packageName, callback);
800 }
801
802 /**
803 * Monitor for changes to the operating mode for the given op in the given app package.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700804 * @param op The operation to monitor, one of OP_*.
805 * @param packageName The name of the application to monitor.
806 * @param callback Where to report changes.
Dianne Hackborne4cb66f2013-10-02 10:34:02 -0700807 * @hide
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700808 */
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700809 public void startWatchingMode(int op, String packageName, final OnOpChangedListener callback) {
Dianne Hackbornc2293022013-02-06 23:14:49 -0800810 synchronized (mModeWatchers) {
811 IAppOpsCallback cb = mModeWatchers.get(callback);
812 if (cb == null) {
813 cb = new IAppOpsCallback.Stub() {
814 public void opChanged(int op, String packageName) {
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700815 if (callback instanceof OnOpChangedInternalListener) {
816 ((OnOpChangedInternalListener)callback).onOpChanged(op, packageName);
817 }
818 if (sOpToString[op] != null) {
819 callback.onOpChanged(sOpToString[op], packageName);
820 }
Dianne Hackbornc2293022013-02-06 23:14:49 -0800821 }
822 };
823 mModeWatchers.put(callback, cb);
824 }
825 try {
826 mService.startWatchingMode(op, packageName, cb);
827 } catch (RemoteException e) {
828 }
829 }
830 }
831
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700832 /**
833 * Stop monitoring that was previously started with {@link #startWatchingMode}. All
834 * monitoring associated with this callback will be removed.
835 */
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700836 public void stopWatchingMode(OnOpChangedListener callback) {
Dianne Hackbornc2293022013-02-06 23:14:49 -0800837 synchronized (mModeWatchers) {
838 IAppOpsCallback cb = mModeWatchers.get(callback);
839 if (cb != null) {
840 try {
841 mService.stopWatchingMode(cb);
842 } catch (RemoteException e) {
843 }
844 }
845 }
846 }
847
Dianne Hackborn95d78532013-09-11 09:51:14 -0700848 private String buildSecurityExceptionMsg(int op, int uid, String packageName) {
849 return packageName + " from uid " + uid + " not allowed to perform " + sOpNames[op];
850 }
851
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700852 private int strOpToOp(String op) {
853 Integer val = sOpStrToOp.get(op);
854 if (val == null) {
855 throw new IllegalArgumentException("Unknown operation string: " + op);
856 }
857 return val;
858 }
859
860 /**
861 * Do a quick check for whether an application might be able to perform an operation.
862 * This is <em>not</em> a security check; you must use {@link #noteOp(String, int, String)}
863 * or {@link #startOp(String, int, String)} for your actual security checks, which also
864 * ensure that the given uid and package name are consistent. This function can just be
865 * used for a quick check to see if an operation has been disabled for the application,
866 * as an early reject of some work. This does not modify the time stamp or other data
867 * about the operation.
868 * @param op The operation to check. One of the OPSTR_* constants.
869 * @param uid The user id of the application attempting to perform the operation.
870 * @param packageName The name of the application attempting to perform the operation.
871 * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
872 * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
873 * causing the app to crash).
874 * @throws SecurityException If the app has been configured to crash on this op.
875 */
876 public int checkOp(String op, int uid, String packageName) {
877 return checkOp(strOpToOp(op), uid, packageName);
878 }
879
880 /**
881 * Like {@link #checkOp but instead of throwing a {@link SecurityException} it
882 * returns {@link #MODE_ERRORED}.
883 */
884 public int checkOpNoThrow(String op, int uid, String packageName) {
885 return checkOpNoThrow(strOpToOp(op), uid, packageName);
886 }
887
888 /**
889 * Make note of an application performing an operation. Note that you must pass
890 * in both the uid and name of the application to be checked; this function will verify
891 * that these two match, and if not, return {@link #MODE_IGNORED}. If this call
892 * succeeds, the last execution time of the operation for this app will be updated to
893 * the current time.
894 * @param op The operation to note. One of the OPSTR_* constants.
895 * @param uid The user id of the application attempting to perform the operation.
896 * @param packageName The name of the application attempting to perform the operation.
897 * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
898 * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
899 * causing the app to crash).
900 * @throws SecurityException If the app has been configured to crash on this op.
901 */
902 public int noteOp(String op, int uid, String packageName) {
903 return noteOp(strOpToOp(op), uid, packageName);
904 }
905
906 /**
907 * Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
908 * returns {@link #MODE_ERRORED}.
909 */
910 public int noteOpNoThrow(String op, int uid, String packageName) {
911 return noteOpNoThrow(strOpToOp(op), uid, packageName);
912 }
913
914 /**
915 * Report that an application has started executing a long-running operation. Note that you
916 * must pass in both the uid and name of the application to be checked; this function will
917 * verify that these two match, and if not, return {@link #MODE_IGNORED}. If this call
918 * succeeds, the last execution time of the operation for this app will be updated to
919 * the current time and the operation will be marked as "running". In this case you must
920 * later call {@link #finishOp(String, int, String)} to report when the application is no
921 * longer performing the operation.
922 * @param op The operation to start. One of the OPSTR_* constants.
923 * @param uid The user id of the application attempting to perform the operation.
924 * @param packageName The name of the application attempting to perform the operation.
925 * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
926 * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
927 * causing the app to crash).
928 * @throws SecurityException If the app has been configured to crash on this op.
929 */
930 public int startOp(String op, int uid, String packageName) {
931 return startOp(strOpToOp(op), uid, packageName);
932 }
933
934 /**
935 * Like {@link #startOp} but instead of throwing a {@link SecurityException} it
936 * returns {@link #MODE_ERRORED}.
937 */
938 public int startOpNoThrow(String op, int uid, String packageName) {
939 return startOpNoThrow(strOpToOp(op), uid, packageName);
940 }
941
942 /**
943 * Report that an application is no longer performing an operation that had previously
944 * been started with {@link #startOp(String, int, String)}. There is no validation of input
945 * or result; the parameters supplied here must be the exact same ones previously passed
946 * in when starting the operation.
947 */
948 public void finishOp(String op, int uid, String packageName) {
949 finishOp(strOpToOp(op), uid, packageName);
950 }
951
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700952 /**
953 * Do a quick check for whether an application might be able to perform an operation.
954 * This is <em>not</em> a security check; you must use {@link #noteOp(int, int, String)}
955 * or {@link #startOp(int, int, String)} for your actual security checks, which also
956 * ensure that the given uid and package name are consistent. This function can just be
957 * used for a quick check to see if an operation has been disabled for the application,
958 * as an early reject of some work. This does not modify the time stamp or other data
959 * about the operation.
960 * @param op The operation to check. One of the OP_* constants.
961 * @param uid The user id of the application attempting to perform the operation.
962 * @param packageName The name of the application attempting to perform the operation.
963 * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
964 * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
965 * causing the app to crash).
966 * @throws SecurityException If the app has been configured to crash on this op.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700967 * @hide
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700968 */
Dianne Hackborn35654b62013-01-14 17:38:02 -0800969 public int checkOp(int op, int uid, String packageName) {
970 try {
971 int mode = mService.checkOperation(op, uid, packageName);
972 if (mode == MODE_ERRORED) {
Dianne Hackborn95d78532013-09-11 09:51:14 -0700973 throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
Dianne Hackborn35654b62013-01-14 17:38:02 -0800974 }
975 return mode;
976 } catch (RemoteException e) {
977 }
978 return MODE_IGNORED;
979 }
980
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700981 /**
982 * Like {@link #checkOp} but instead of throwing a {@link SecurityException} it
983 * returns {@link #MODE_ERRORED}.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700984 * @hide
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700985 */
Dianne Hackborn35654b62013-01-14 17:38:02 -0800986 public int checkOpNoThrow(int op, int uid, String packageName) {
987 try {
988 return mService.checkOperation(op, uid, packageName);
989 } catch (RemoteException e) {
990 }
991 return MODE_IGNORED;
992 }
993
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700994 /**
Jeff Sharkey911d7f42013-09-05 18:11:45 -0700995 * Do a quick check to validate if a package name belongs to a UID.
996 *
997 * @throws SecurityException if the package name doesn't belong to the given
998 * UID, or if ownership cannot be verified.
999 */
1000 public void checkPackage(int uid, String packageName) {
1001 try {
1002 if (mService.checkPackage(uid, packageName) != MODE_ALLOWED) {
1003 throw new SecurityException(
1004 "Package " + packageName + " does not belong to " + uid);
1005 }
1006 } catch (RemoteException e) {
1007 throw new SecurityException("Unable to verify package ownership", e);
1008 }
1009 }
1010
1011 /**
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001012 * Make note of an application performing an operation. Note that you must pass
1013 * in both the uid and name of the application to be checked; this function will verify
1014 * that these two match, and if not, return {@link #MODE_IGNORED}. If this call
1015 * succeeds, the last execution time of the operation for this app will be updated to
1016 * the current time.
1017 * @param op The operation to note. One of the OP_* constants.
1018 * @param uid The user id of the application attempting to perform the operation.
1019 * @param packageName The name of the application attempting to perform the operation.
1020 * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
1021 * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
1022 * causing the app to crash).
1023 * @throws SecurityException If the app has been configured to crash on this op.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -07001024 * @hide
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001025 */
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001026 public int noteOp(int op, int uid, String packageName) {
1027 try {
1028 int mode = mService.noteOperation(op, uid, packageName);
1029 if (mode == MODE_ERRORED) {
Dianne Hackborn95d78532013-09-11 09:51:14 -07001030 throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001031 }
1032 return mode;
1033 } catch (RemoteException e) {
1034 }
1035 return MODE_IGNORED;
1036 }
1037
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001038 /**
1039 * Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
1040 * returns {@link #MODE_ERRORED}.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -07001041 * @hide
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001042 */
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001043 public int noteOpNoThrow(int op, int uid, String packageName) {
1044 try {
1045 return mService.noteOperation(op, uid, packageName);
1046 } catch (RemoteException e) {
1047 }
1048 return MODE_IGNORED;
1049 }
1050
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001051 /** @hide */
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001052 public int noteOp(int op) {
Dianne Hackborn95d78532013-09-11 09:51:14 -07001053 return noteOp(op, Process.myUid(), mContext.getOpPackageName());
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001054 }
1055
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001056 /** @hide */
1057 public static IBinder getToken(IAppOpsService service) {
1058 synchronized (AppOpsManager.class) {
1059 if (sToken != null) {
1060 return sToken;
1061 }
1062 try {
1063 sToken = service.getToken(new Binder());
1064 } catch (RemoteException e) {
1065 // System is dead, whatevs.
1066 }
1067 return sToken;
1068 }
1069 }
1070
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001071 /**
1072 * Report that an application has started executing a long-running operation. Note that you
1073 * must pass in both the uid and name of the application to be checked; this function will
1074 * verify that these two match, and if not, return {@link #MODE_IGNORED}. If this call
1075 * succeeds, the last execution time of the operation for this app will be updated to
1076 * the current time and the operation will be marked as "running". In this case you must
1077 * later call {@link #finishOp(int, int, String)} to report when the application is no
1078 * longer performing the operation.
1079 * @param op The operation to start. One of the OP_* constants.
1080 * @param uid The user id of the application attempting to perform the operation.
1081 * @param packageName The name of the application attempting to perform the operation.
1082 * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
1083 * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
1084 * causing the app to crash).
1085 * @throws SecurityException If the app has been configured to crash on this op.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -07001086 * @hide
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001087 */
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001088 public int startOp(int op, int uid, String packageName) {
1089 try {
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001090 int mode = mService.startOperation(getToken(mService), op, uid, packageName);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001091 if (mode == MODE_ERRORED) {
Dianne Hackborn95d78532013-09-11 09:51:14 -07001092 throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001093 }
1094 return mode;
1095 } catch (RemoteException e) {
1096 }
1097 return MODE_IGNORED;
1098 }
1099
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001100 /**
1101 * Like {@link #startOp} but instead of throwing a {@link SecurityException} it
1102 * returns {@link #MODE_ERRORED}.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -07001103 * @hide
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001104 */
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001105 public int startOpNoThrow(int op, int uid, String packageName) {
1106 try {
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001107 return mService.startOperation(getToken(mService), op, uid, packageName);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001108 } catch (RemoteException e) {
1109 }
1110 return MODE_IGNORED;
1111 }
1112
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001113 /** @hide */
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001114 public int startOp(int op) {
Dianne Hackborn95d78532013-09-11 09:51:14 -07001115 return startOp(op, Process.myUid(), mContext.getOpPackageName());
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001116 }
1117
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001118 /**
1119 * Report that an application is no longer performing an operation that had previously
1120 * been started with {@link #startOp(int, int, String)}. There is no validation of input
1121 * or result; the parameters supplied here must be the exact same ones previously passed
1122 * in when starting the operation.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -07001123 * @hide
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001124 */
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001125 public void finishOp(int op, int uid, String packageName) {
1126 try {
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001127 mService.finishOperation(getToken(mService), op, uid, packageName);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001128 } catch (RemoteException e) {
1129 }
1130 }
1131
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -07001132 /** @hide */
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001133 public void finishOp(int op) {
Dianne Hackborn95d78532013-09-11 09:51:14 -07001134 finishOp(op, Process.myUid(), mContext.getOpPackageName());
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001135 }
1136}