1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.app; 18 19 import android.os.Binder; 20 import android.os.IBinder; 21 import android.util.ArrayMap; 22 import com.android.internal.app.IAppOpsService; 23 import com.android.internal.app.IAppOpsCallback; 24 25 import java.util.ArrayList; 26 import java.util.HashMap; 27 import java.util.List; 28 29 import android.content.Context; 30 import android.os.Parcel; 31 import android.os.Parcelable; 32 import android.os.Process; 33 import android.os.RemoteException; 34 35 /** 36 * API for interacting with "application operation" tracking. 37 * 38 * <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> 42 */ 43 public class AppOpsManager { 44 /** 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 66 final Context mContext; 67 final IAppOpsService mService; 68 final ArrayMap<OnOpChangedListener, IAppOpsCallback> mModeWatchers 69 = new ArrayMap<OnOpChangedListener, IAppOpsCallback>(); 70 71 static IBinder sToken; 72 73 /** 74 * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller is 75 * allowed to perform the given operation. 76 */ 77 public static final int MODE_ALLOWED = 0; 78 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 */ 84 public static final int MODE_IGNORED = 1; 85 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 */ 91 public static final int MODE_ERRORED = 2; 92 93 // when adding one of these: 94 // - increment _NUM_OP 95 // - add rows to sOpToSwitch, sOpToString, sOpNames, sOpPerms, sOpDefaultMode 96 // - add descriptive strings to Settings/res/values/arrays.xml 97 // - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app) 98 99 /** @hide No operation specified. */ 100 public static final int OP_NONE = -1; 101 /** @hide Access to coarse location information. */ 102 public static final int OP_COARSE_LOCATION = 0; 103 /** @hide Access to fine location information. */ 104 public static final int OP_FINE_LOCATION = 1; 105 /** @hide Causing GPS to run. */ 106 public static final int OP_GPS = 2; 107 /** @hide */ 108 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; 183 /** @hide Continually monitoring location data. */ 184 public static final int OP_MONITOR_LOCATION = 41; 185 /** @hide Continually monitoring location data with a relatively high power request. */ 186 public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42; 187 /** @hide */ 188 public static final int _NUM_OP = 43; 189 190 /** 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 203 /** 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 208 * presented to the user as one switch then this can be used to 209 * 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, 226 OP_READ_SMS, 227 OP_WRITE_SMS, 228 OP_RECEIVE_SMS, 229 OP_RECEIVE_SMS, 230 OP_RECEIVE_SMS, 231 OP_RECEIVE_SMS, 232 OP_SEND_SMS, 233 OP_READ_SMS, 234 OP_WRITE_SMS, 235 OP_WRITE_SETTINGS, 236 OP_SYSTEM_ALERT_WINDOW, 237 OP_ACCESS_NOTIFICATIONS, 238 OP_CAMERA, 239 OP_RECORD_AUDIO, 240 OP_PLAY_AUDIO, 241 OP_READ_CLIPBOARD, 242 OP_WRITE_CLIPBOARD, 243 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, 252 OP_WAKE_LOCK, 253 OP_COARSE_LOCATION, 254 OP_COARSE_LOCATION, 255 }; 256 257 /** 258 * 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 /** 308 * This provides a simple name for each operation to be used 309 * in debug output. 310 */ 311 private static String[] sOpNames = new String[] { 312 "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", 326 "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", 335 "WRITE_SETTINGS", 336 "SYSTEM_ALERT_WINDOW", 337 "ACCESS_NOTIFICATIONS", 338 "CAMERA", 339 "RECORD_AUDIO", 340 "PLAY_AUDIO", 341 "READ_CLIPBOARD", 342 "WRITE_CLIPBOARD", 343 "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", 352 "WAKE_LOCK", 353 "MONITOR_LOCATION", 354 "MONITOR_HIGH_POWER_LOCATION", 355 }; 356 357 /** 358 * This optionally maps a permission to an operation. If there 359 * is no permission associated with an operation, it is null. 360 */ 361 private static String[] sOpPerms = new String[] { 362 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, 372 null, // no permission required for notifications 373 android.Manifest.permission.ACCESS_WIFI_STATE, 374 null, // neighboring cells shares the coarse location perm 375 android.Manifest.permission.CALL_PHONE, 376 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, 385 android.Manifest.permission.WRITE_SETTINGS, 386 android.Manifest.permission.SYSTEM_ALERT_WINDOW, 387 android.Manifest.permission.ACCESS_NOTIFICATIONS, 388 android.Manifest.permission.CAMERA, 389 android.Manifest.permission.RECORD_AUDIO, 390 null, // no permission for playing audio 391 null, // no permission for reading clipboard 392 null, // no permission for writing clipboard 393 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 402 android.Manifest.permission.WAKE_LOCK, 403 null, // no permission for generic location monitoring 404 null, // no permission for high power location monitoring 405 }; 406 407 /** 408 * 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 456 /** 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 509 private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>(); 510 511 static { 512 if (sOpToSwitch.length != _NUM_OP) { 513 throw new IllegalStateException("sOpToSwitch length " + sOpToSwitch.length 514 + " should be " + _NUM_OP); 515 } 516 if (sOpToString.length != _NUM_OP) { 517 throw new IllegalStateException("sOpToString length " + sOpToString.length 518 + " should be " + _NUM_OP); 519 } 520 if (sOpNames.length != _NUM_OP) { 521 throw new IllegalStateException("sOpNames length " + sOpNames.length 522 + " should be " + _NUM_OP); 523 } 524 if (sOpPerms.length != _NUM_OP) { 525 throw new IllegalStateException("sOpPerms length " + sOpPerms.length 526 + " should be " + _NUM_OP); 527 } 528 if (sOpDefaultMode.length != _NUM_OP) { 529 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 534 + " 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 543 /** 544 * Retrieve the op switch that controls the given operation. 545 * @hide 546 */ 547 public static int opToSwitch(int op) { 548 return sOpToSwitch[op]; 549 } 550 551 /** 552 * Retrieve a non-localized name for the operation, for debugging output. 553 * @hide 554 */ 555 public static String opToName(int op) { 556 if (op == OP_NONE) return "NONE"; 557 return op < sOpNames.length ? sOpNames[op] : ("Unknown(" + op + ")"); 558 } 559 560 /** 561 * Retrieve the permission associated with an operation, or null if there is not one. 562 * @hide 563 */ 564 public static String opToPermission(int op) { 565 return sOpPerms[op]; 566 } 567 568 /** 569 * Retrieve the default mode for the operation. 570 * @hide 571 */ 572 public static int opToDefaultMode(int op) { 573 return sOpDefaultMode[op]; 574 } 575 576 /** 577 * 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 /** 585 * Class holding all of the operation information associated with an app. 586 * @hide 587 */ 588 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 647 /** 648 * Class holding the information about one unique operation of an application. 649 * @hide 650 */ 651 public static class OpEntry implements Parcelable { 652 private final int mOp; 653 private final int mMode; 654 private final long mTime; 655 private final long mRejectTime; 656 private final int mDuration; 657 658 public OpEntry(int op, int mode, long time, long rejectTime, int duration) { 659 mOp = op; 660 mMode = mode; 661 mTime = time; 662 mRejectTime = rejectTime; 663 mDuration = duration; 664 } 665 666 public int getOp() { 667 return mOp; 668 } 669 670 public int getMode() { 671 return mMode; 672 } 673 674 public long getTime() { 675 return mTime; 676 } 677 678 public long getRejectTime() { 679 return mRejectTime; 680 } 681 682 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); 698 dest.writeInt(mMode); 699 dest.writeLong(mTime); 700 dest.writeLong(mRejectTime); 701 dest.writeInt(mDuration); 702 } 703 704 OpEntry(Parcel source) { 705 mOp = source.readInt(); 706 mMode = source.readInt(); 707 mTime = source.readLong(); 708 mRejectTime = source.readLong(); 709 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 723 /** 724 * Callback for notification of changes to operation state. 725 */ 726 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) { } 738 } 739 740 AppOpsManager(Context context, IAppOpsService service) { 741 mContext = context; 742 mService = service; 743 } 744 745 /** 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. 749 * @hide 750 */ 751 public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) { 752 try { 753 return mService.getPackagesForOps(ops); 754 } catch (RemoteException e) { 755 } 756 return null; 757 } 758 759 /** 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. 765 * @hide 766 */ 767 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 775 /** @hide */ 776 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 783 /** @hide */ 784 public void resetAllModes() { 785 try { 786 mService.resetAllModes(); 787 } catch (RemoteException e) { 788 } 789 } 790 791 /** 792 * Monitor for changes to the operating mode for the given op in the given app package. 793 * @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. 804 * @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. 807 * @hide 808 */ 809 public void startWatchingMode(int op, String packageName, final OnOpChangedListener callback) { 810 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) { 815 if (callback instanceof OnOpChangedInternalListener) { 816 ((OnOpChangedInternalListener)callback).onOpChanged(op, packageName); 817 } 818 if (sOpToString[op] != null) { 819 callback.onOpChanged(sOpToString[op], packageName); 820 } 821 } 822 }; 823 mModeWatchers.put(callback, cb); 824 } 825 try { 826 mService.startWatchingMode(op, packageName, cb); 827 } catch (RemoteException e) { 828 } 829 } 830 } 831 832 /** 833 * Stop monitoring that was previously started with {@link #startWatchingMode}. All 834 * monitoring associated with this callback will be removed. 835 */ 836 public void stopWatchingMode(OnOpChangedListener callback) { 837 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 848 private String buildSecurityExceptionMsg(int op, int uid, String packageName) { 849 return packageName + " from uid " + uid + " not allowed to perform " + sOpNames[op]; 850 } 851 852 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 952 /** 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. 967 * @hide 968 */ 969 public int checkOp(int op, int uid, String packageName) { 970 try { 971 int mode = mService.checkOperation(op, uid, packageName); 972 if (mode == MODE_ERRORED) { 973 throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName)); 974 } 975 return mode; 976 } catch (RemoteException e) { 977 } 978 return MODE_IGNORED; 979 } 980 981 /** 982 * Like {@link #checkOp} but instead of throwing a {@link SecurityException} it 983 * returns {@link #MODE_ERRORED}. 984 * @hide 985 */ 986 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 994 /** 995 * 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 /** 1012 * 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. 1024 * @hide 1025 */ 1026 public int noteOp(int op, int uid, String packageName) { 1027 try { 1028 int mode = mService.noteOperation(op, uid, packageName); 1029 if (mode == MODE_ERRORED) { 1030 throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName)); 1031 } 1032 return mode; 1033 } catch (RemoteException e) { 1034 } 1035 return MODE_IGNORED; 1036 } 1037 1038 /** 1039 * Like {@link #noteOp} but instead of throwing a {@link SecurityException} it 1040 * returns {@link #MODE_ERRORED}. 1041 * @hide 1042 */ 1043 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 1051 /** @hide */ 1052 public int noteOp(int op) { 1053 return noteOp(op, Process.myUid(), mContext.getOpPackageName()); 1054 } 1055 1056 /** @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 1071 /** 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. 1086 * @hide 1087 */ 1088 public int startOp(int op, int uid, String packageName) { 1089 try { 1090 int mode = mService.startOperation(getToken(mService), op, uid, packageName); 1091 if (mode == MODE_ERRORED) { 1092 throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName)); 1093 } 1094 return mode; 1095 } catch (RemoteException e) { 1096 } 1097 return MODE_IGNORED; 1098 } 1099 1100 /** 1101 * Like {@link #startOp} but instead of throwing a {@link SecurityException} it 1102 * returns {@link #MODE_ERRORED}. 1103 * @hide 1104 */ 1105 public int startOpNoThrow(int op, int uid, String packageName) { 1106 try { 1107 return mService.startOperation(getToken(mService), op, uid, packageName); 1108 } catch (RemoteException e) { 1109 } 1110 return MODE_IGNORED; 1111 } 1112 1113 /** @hide */ 1114 public int startOp(int op) { 1115 return startOp(op, Process.myUid(), mContext.getOpPackageName()); 1116 } 1117 1118 /** 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. 1123 * @hide 1124 */ 1125 public void finishOp(int op, int uid, String packageName) { 1126 try { 1127 mService.finishOperation(getToken(mService), op, uid, packageName); 1128 } catch (RemoteException e) { 1129 } 1130 } 1131 1132 /** @hide */ 1133 public void finishOp(int op) { 1134 finishOp(op, Process.myUid(), mContext.getOpPackageName()); 1135 } 1136 } 1137