AppOpsManager.java revision 713df150b92a0a5eea877f99405e31eefbf93a09
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.app; 18 19import android.Manifest; 20import com.android.internal.app.IAppOpsService; 21import com.android.internal.app.IAppOpsCallback; 22 23import java.util.ArrayList; 24import java.util.HashMap; 25import java.util.List; 26 27import android.content.Context; 28import android.os.Parcel; 29import android.os.Parcelable; 30import android.os.Process; 31import 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 */ 52public 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 public static final int OP_TAKE_MEDIA_BUTTONS = 31; 99 public static final int OP_TAKE_AUDIO_FOCUS = 32; 100 public static final int OP_AUDIO_MASTER_VOLUME = 33; 101 public static final int OP_AUDIO_VOICE_VOLUME = 34; 102 public static final int OP_AUDIO_RING_VOLUME = 35; 103 public static final int OP_AUDIO_MEDIA_VOLUME = 36; 104 public static final int OP_AUDIO_ALARM_VOLUME = 37; 105 public static final int OP_AUDIO_NOTIFICATION_VOLUME = 38; 106 public static final int OP_AUDIO_BLUETOOTH_VOLUME = 39; 107 public static final int OP_WAKE_LOCK = 40; 108 /** @hide */ 109 public static final int _NUM_OP = 41; 110 111 /** 112 * This maps each operation to the operation that serves as the 113 * switch to determine whether it is allowed. Generally this is 114 * a 1:1 mapping, but for some things (like location) that have 115 * multiple low-level operations being tracked that should be 116 * presented to hte user as one switch then this can be used to 117 * make them all controlled by the same single operation. 118 */ 119 private static int[] sOpToSwitch = new int[] { 120 OP_COARSE_LOCATION, 121 OP_COARSE_LOCATION, 122 OP_COARSE_LOCATION, 123 OP_VIBRATE, 124 OP_READ_CONTACTS, 125 OP_WRITE_CONTACTS, 126 OP_READ_CALL_LOG, 127 OP_WRITE_CALL_LOG, 128 OP_READ_CALENDAR, 129 OP_WRITE_CALENDAR, 130 OP_COARSE_LOCATION, 131 OP_POST_NOTIFICATION, 132 OP_COARSE_LOCATION, 133 OP_CALL_PHONE, 134 OP_READ_SMS, 135 OP_WRITE_SMS, 136 OP_READ_SMS, 137 OP_READ_SMS, 138 OP_READ_SMS, 139 OP_READ_SMS, 140 OP_WRITE_SMS, 141 OP_READ_SMS, 142 OP_WRITE_SMS, 143 OP_WRITE_SETTINGS, 144 OP_SYSTEM_ALERT_WINDOW, 145 OP_ACCESS_NOTIFICATIONS, 146 OP_CAMERA, 147 OP_RECORD_AUDIO, 148 OP_PLAY_AUDIO, 149 OP_READ_CLIPBOARD, 150 OP_WRITE_CLIPBOARD, 151 OP_TAKE_MEDIA_BUTTONS, 152 OP_TAKE_AUDIO_FOCUS, 153 OP_AUDIO_MASTER_VOLUME, 154 OP_AUDIO_VOICE_VOLUME, 155 OP_AUDIO_RING_VOLUME, 156 OP_AUDIO_MEDIA_VOLUME, 157 OP_AUDIO_ALARM_VOLUME, 158 OP_AUDIO_NOTIFICATION_VOLUME, 159 OP_AUDIO_BLUETOOTH_VOLUME, 160 OP_WAKE_LOCK, 161 }; 162 163 /** 164 * This provides a simple name for each operation to be used 165 * in debug output. 166 */ 167 private static String[] sOpNames = new String[] { 168 "COARSE_LOCATION", 169 "FINE_LOCATION", 170 "GPS", 171 "VIBRATE", 172 "READ_CONTACTS", 173 "WRITE_CONTACTS", 174 "READ_CALL_LOG", 175 "WRITE_CALL_LOG", 176 "READ_CALENDAR", 177 "WRITE_CALENDAR", 178 "WIFI_SCAN", 179 "POST_NOTIFICATION", 180 "NEIGHBORING_CELLS", 181 "CALL_PHONE", 182 "READ_SMS", 183 "WRITE_SMS", 184 "RECEIVE_SMS", 185 "RECEIVE_EMERGECY_SMS", 186 "RECEIVE_MMS", 187 "RECEIVE_WAP_PUSH", 188 "SEND_SMS", 189 "READ_ICC_SMS", 190 "WRITE_ICC_SMS", 191 "WRITE_SETTINGS", 192 "SYSTEM_ALERT_WINDOW", 193 "ACCESS_NOTIFICATIONS", 194 "CAMERA", 195 "RECORD_AUDIO", 196 "PLAY_AUDIO", 197 "READ_CLIPBOARD", 198 "WRITE_CLIPBOARD", 199 "TAKE_MEDIA_BUTTONS", 200 "TAKE_AUDIO_FOCUS", 201 "AUDIO_MASTER_VOLUME", 202 "AUDIO_VOICE_VOLUME", 203 "AUDIO_RING_VOLUME", 204 "AUDIO_MEDIA_VOLUME", 205 "AUDIO_ALARM_VOLUME", 206 "AUDIO_NOTIFICATION_VOLUME", 207 "AUDIO_BLUETOOTH_VOLUME", 208 "WAKE_LOCK", 209 }; 210 211 /** 212 * This optionally maps a permission to an operation. If there 213 * is no permission associated with an operation, it is null. 214 */ 215 private static String[] sOpPerms = new String[] { 216 android.Manifest.permission.ACCESS_COARSE_LOCATION, 217 android.Manifest.permission.ACCESS_FINE_LOCATION, 218 null, 219 android.Manifest.permission.VIBRATE, 220 android.Manifest.permission.READ_CONTACTS, 221 android.Manifest.permission.WRITE_CONTACTS, 222 android.Manifest.permission.READ_CALL_LOG, 223 android.Manifest.permission.WRITE_CALL_LOG, 224 android.Manifest.permission.READ_CALENDAR, 225 android.Manifest.permission.WRITE_CALENDAR, 226 null, // no permission required for notifications 227 android.Manifest.permission.ACCESS_WIFI_STATE, 228 null, // neighboring cells shares the coarse location perm 229 android.Manifest.permission.CALL_PHONE, 230 android.Manifest.permission.READ_SMS, 231 android.Manifest.permission.WRITE_SMS, 232 android.Manifest.permission.RECEIVE_SMS, 233 android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST, 234 android.Manifest.permission.RECEIVE_MMS, 235 android.Manifest.permission.RECEIVE_WAP_PUSH, 236 android.Manifest.permission.SEND_SMS, 237 android.Manifest.permission.READ_SMS, 238 android.Manifest.permission.WRITE_SMS, 239 android.Manifest.permission.WRITE_SETTINGS, 240 android.Manifest.permission.SYSTEM_ALERT_WINDOW, 241 android.Manifest.permission.ACCESS_NOTIFICATIONS, 242 android.Manifest.permission.CAMERA, 243 android.Manifest.permission.RECORD_AUDIO, 244 null, // no permission for playing audio 245 null, // no permission for reading clipboard 246 null, // no permission for writing clipboard 247 null, // no permission for taking media buttons 248 null, // no permission for taking audio focus 249 null, // no permission for changing master volume 250 null, // no permission for changing voice volume 251 null, // no permission for changing ring volume 252 null, // no permission for changing media volume 253 null, // no permission for changing alarm volume 254 null, // no permission for changing notification volume 255 null, // no permission for changing bluetooth volume 256 android.Manifest.permission.WAKE_LOCK, 257 }; 258 259 /** 260 * Retrieve the op switch that controls the given operation. 261 */ 262 public static int opToSwitch(int op) { 263 return sOpToSwitch[op]; 264 } 265 266 /** 267 * Retrieve a non-localized name for the operation, for debugging output. 268 */ 269 public static String opToName(int op) { 270 if (op == OP_NONE) return "NONE"; 271 return op < sOpNames.length ? sOpNames[op] : ("Unknown(" + op + ")"); 272 } 273 274 /** 275 * Retrieve the permission associated with an operation, or null if there is not one. 276 */ 277 public static String opToPermission(int op) { 278 return sOpPerms[op]; 279 } 280 281 /** 282 * Class holding all of the operation information associated with an app. 283 */ 284 public static class PackageOps implements Parcelable { 285 private final String mPackageName; 286 private final int mUid; 287 private final List<OpEntry> mEntries; 288 289 public PackageOps(String packageName, int uid, List<OpEntry> entries) { 290 mPackageName = packageName; 291 mUid = uid; 292 mEntries = entries; 293 } 294 295 public String getPackageName() { 296 return mPackageName; 297 } 298 299 public int getUid() { 300 return mUid; 301 } 302 303 public List<OpEntry> getOps() { 304 return mEntries; 305 } 306 307 @Override 308 public int describeContents() { 309 return 0; 310 } 311 312 @Override 313 public void writeToParcel(Parcel dest, int flags) { 314 dest.writeString(mPackageName); 315 dest.writeInt(mUid); 316 dest.writeInt(mEntries.size()); 317 for (int i=0; i<mEntries.size(); i++) { 318 mEntries.get(i).writeToParcel(dest, flags); 319 } 320 } 321 322 PackageOps(Parcel source) { 323 mPackageName = source.readString(); 324 mUid = source.readInt(); 325 mEntries = new ArrayList<OpEntry>(); 326 final int N = source.readInt(); 327 for (int i=0; i<N; i++) { 328 mEntries.add(OpEntry.CREATOR.createFromParcel(source)); 329 } 330 } 331 332 public static final Creator<PackageOps> CREATOR = new Creator<PackageOps>() { 333 @Override public PackageOps createFromParcel(Parcel source) { 334 return new PackageOps(source); 335 } 336 337 @Override public PackageOps[] newArray(int size) { 338 return new PackageOps[size]; 339 } 340 }; 341 } 342 343 /** 344 * Class holding the information about one unique operation of an application. 345 */ 346 public static class OpEntry implements Parcelable { 347 private final int mOp; 348 private final int mMode; 349 private final long mTime; 350 private final long mRejectTime; 351 private final int mDuration; 352 353 public OpEntry(int op, int mode, long time, long rejectTime, int duration) { 354 mOp = op; 355 mMode = mode; 356 mTime = time; 357 mRejectTime = rejectTime; 358 mDuration = duration; 359 } 360 361 public int getOp() { 362 return mOp; 363 } 364 365 public int getMode() { 366 return mMode; 367 } 368 369 public long getTime() { 370 return mTime; 371 } 372 373 public long getRejectTime() { 374 return mRejectTime; 375 } 376 377 public boolean isRunning() { 378 return mDuration == -1; 379 } 380 381 public int getDuration() { 382 return mDuration == -1 ? (int)(System.currentTimeMillis()-mTime) : mDuration; 383 } 384 385 @Override 386 public int describeContents() { 387 return 0; 388 } 389 390 @Override 391 public void writeToParcel(Parcel dest, int flags) { 392 dest.writeInt(mOp); 393 dest.writeInt(mMode); 394 dest.writeLong(mTime); 395 dest.writeLong(mRejectTime); 396 dest.writeInt(mDuration); 397 } 398 399 OpEntry(Parcel source) { 400 mOp = source.readInt(); 401 mMode = source.readInt(); 402 mTime = source.readLong(); 403 mRejectTime = source.readLong(); 404 mDuration = source.readInt(); 405 } 406 407 public static final Creator<OpEntry> CREATOR = new Creator<OpEntry>() { 408 @Override public OpEntry createFromParcel(Parcel source) { 409 return new OpEntry(source); 410 } 411 412 @Override public OpEntry[] newArray(int size) { 413 return new OpEntry[size]; 414 } 415 }; 416 } 417 418 /** 419 * Callback for notification of changes to operation state. 420 */ 421 public interface Callback { 422 public void opChanged(int op, String packageName); 423 } 424 425 public AppOpsManager(Context context, IAppOpsService service) { 426 mContext = context; 427 mService = service; 428 } 429 430 /** 431 * Retrieve current operation state for all applications. 432 * 433 * @param ops The set of operations you are interested in, or null if you want all of them. 434 */ 435 public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) { 436 try { 437 return mService.getPackagesForOps(ops); 438 } catch (RemoteException e) { 439 } 440 return null; 441 } 442 443 /** 444 * Retrieve current operation state for one application. 445 * 446 * @param uid The uid of the application of interest. 447 * @param packageName The name of the application of interest. 448 * @param ops The set of operations you are interested in, or null if you want all of them. 449 */ 450 public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, int[] ops) { 451 try { 452 return mService.getOpsForPackage(uid, packageName, ops); 453 } catch (RemoteException e) { 454 } 455 return null; 456 } 457 458 public void setMode(int code, int uid, String packageName, int mode) { 459 try { 460 mService.setMode(code, uid, packageName, mode); 461 } catch (RemoteException e) { 462 } 463 } 464 465 public void startWatchingMode(int op, String packageName, final Callback callback) { 466 synchronized (mModeWatchers) { 467 IAppOpsCallback cb = mModeWatchers.get(callback); 468 if (cb == null) { 469 cb = new IAppOpsCallback.Stub() { 470 public void opChanged(int op, String packageName) { 471 callback.opChanged(op, packageName); 472 } 473 }; 474 mModeWatchers.put(callback, cb); 475 } 476 try { 477 mService.startWatchingMode(op, packageName, cb); 478 } catch (RemoteException e) { 479 } 480 } 481 } 482 483 public void stopWatchingMode(Callback callback) { 484 synchronized (mModeWatchers) { 485 IAppOpsCallback cb = mModeWatchers.get(callback); 486 if (cb != null) { 487 try { 488 mService.stopWatchingMode(cb); 489 } catch (RemoteException e) { 490 } 491 } 492 } 493 } 494 495 public int checkOp(int op, int uid, String packageName) { 496 try { 497 int mode = mService.checkOperation(op, uid, packageName); 498 if (mode == MODE_ERRORED) { 499 throw new SecurityException("Operation not allowed"); 500 } 501 return mode; 502 } catch (RemoteException e) { 503 } 504 return MODE_IGNORED; 505 } 506 507 public int checkOpNoThrow(int op, int uid, String packageName) { 508 try { 509 return mService.checkOperation(op, uid, packageName); 510 } catch (RemoteException e) { 511 } 512 return MODE_IGNORED; 513 } 514 515 public int noteOp(int op, int uid, String packageName) { 516 try { 517 int mode = mService.noteOperation(op, uid, packageName); 518 if (mode == MODE_ERRORED) { 519 throw new SecurityException("Operation not allowed"); 520 } 521 return mode; 522 } catch (RemoteException e) { 523 } 524 return MODE_IGNORED; 525 } 526 527 public int noteOpNoThrow(int op, int uid, String packageName) { 528 try { 529 return mService.noteOperation(op, uid, packageName); 530 } catch (RemoteException e) { 531 } 532 return MODE_IGNORED; 533 } 534 535 public int noteOp(int op) { 536 return noteOp(op, Process.myUid(), mContext.getBasePackageName()); 537 } 538 539 public int startOp(int op, int uid, String packageName) { 540 try { 541 int mode = mService.startOperation(op, uid, packageName); 542 if (mode == MODE_ERRORED) { 543 throw new SecurityException("Operation not allowed"); 544 } 545 return mode; 546 } catch (RemoteException e) { 547 } 548 return MODE_IGNORED; 549 } 550 551 public int startOpNoThrow(int op, int uid, String packageName) { 552 try { 553 return mService.startOperation(op, uid, packageName); 554 } catch (RemoteException e) { 555 } 556 return MODE_IGNORED; 557 } 558 559 public int startOp(int op) { 560 return startOp(op, Process.myUid(), mContext.getBasePackageName()); 561 } 562 563 public void finishOp(int op, int uid, String packageName) { 564 try { 565 mService.finishOperation(op, uid, packageName); 566 } catch (RemoteException e) { 567 } 568 } 569 570 public void finishOp(int op) { 571 finishOp(op, Process.myUid(), mContext.getBasePackageName()); 572 } 573} 574