AppOpsManager.java revision f5d831915dd11e77cdcf5669228c55fe17a21c5e
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.os.Binder; 20import android.os.IBinder; 21import android.util.ArrayMap; 22import com.android.internal.app.IAppOpsService; 23import com.android.internal.app.IAppOpsCallback; 24 25import java.util.ArrayList; 26import java.util.List; 27 28import android.content.Context; 29import android.os.Parcel; 30import android.os.Parcelable; 31import android.os.Process; 32import android.os.RemoteException; 33 34/** 35 * API for interacting with "application operation" tracking. Allows you to: 36 * 37 * <ul> 38 * <li> Note when operations are happening, and find out if they are allowed for the current 39 * caller.</li> 40 * <li> Disallow specific apps from doing specific operations.</li> 41 * <li> Collect all of the current information about operations that have been executed or are not 42 * being allowed.</li> 43 * <li> Monitor for changes in whether an operation is allowed.</li> 44 * </ul> 45 * 46 * <p>Each operation is identified by a single integer; these integers are a fixed set of 47 * operations, enumerated by the OP_* constants. 48 * 49 * <p></p>When checking operations, the result is a "mode" integer indicating the current setting 50 * for the operation under that caller: MODE_ALLOWED, MODE_IGNORED (don't execute the operation but 51 * fake its behavior enough so that the caller doesn't crash), MODE_ERRORED (through a 52 * SecurityException back to the caller; the normal operation calls will do this for you). 53 */ 54public class AppOpsManager { 55 final Context mContext; 56 final IAppOpsService mService; 57 final ArrayMap<Callback, IAppOpsCallback> mModeWatchers 58 = new ArrayMap<Callback, IAppOpsCallback>(); 59 60 static IBinder sToken; 61 62 public static final int MODE_ALLOWED = 0; 63 public static final int MODE_IGNORED = 1; 64 public static final int MODE_ERRORED = 2; 65 66 // when adding one of these: 67 // - increment _NUM_OP 68 // - add rows to sOpToSwitch, sOpNames, sOpPerms, sOpDefaultMode 69 // - add descriptive strings to Settings/res/values/arrays.xml 70 // - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app) 71 72 /** No operation specified. */ 73 public static final int OP_NONE = -1; 74 /** Access to coarse location information. */ 75 public static final int OP_COARSE_LOCATION = 0; 76 /** Access to fine location information. */ 77 public static final int OP_FINE_LOCATION = 1; 78 /** Causing GPS to run. */ 79 public static final int OP_GPS = 2; 80 /** @hide */ 81 public static final int OP_VIBRATE = 3; 82 /** @hide */ 83 public static final int OP_READ_CONTACTS = 4; 84 /** @hide */ 85 public static final int OP_WRITE_CONTACTS = 5; 86 /** @hide */ 87 public static final int OP_READ_CALL_LOG = 6; 88 /** @hide */ 89 public static final int OP_WRITE_CALL_LOG = 7; 90 /** @hide */ 91 public static final int OP_READ_CALENDAR = 8; 92 /** @hide */ 93 public static final int OP_WRITE_CALENDAR = 9; 94 /** @hide */ 95 public static final int OP_WIFI_SCAN = 10; 96 /** @hide */ 97 public static final int OP_POST_NOTIFICATION = 11; 98 /** @hide */ 99 public static final int OP_NEIGHBORING_CELLS = 12; 100 /** @hide */ 101 public static final int OP_CALL_PHONE = 13; 102 /** @hide */ 103 public static final int OP_READ_SMS = 14; 104 /** @hide */ 105 public static final int OP_WRITE_SMS = 15; 106 /** @hide */ 107 public static final int OP_RECEIVE_SMS = 16; 108 /** @hide */ 109 public static final int OP_RECEIVE_EMERGECY_SMS = 17; 110 /** @hide */ 111 public static final int OP_RECEIVE_MMS = 18; 112 /** @hide */ 113 public static final int OP_RECEIVE_WAP_PUSH = 19; 114 /** @hide */ 115 public static final int OP_SEND_SMS = 20; 116 /** @hide */ 117 public static final int OP_READ_ICC_SMS = 21; 118 /** @hide */ 119 public static final int OP_WRITE_ICC_SMS = 22; 120 /** @hide */ 121 public static final int OP_WRITE_SETTINGS = 23; 122 /** @hide */ 123 public static final int OP_SYSTEM_ALERT_WINDOW = 24; 124 /** @hide */ 125 public static final int OP_ACCESS_NOTIFICATIONS = 25; 126 /** @hide */ 127 public static final int OP_CAMERA = 26; 128 /** @hide */ 129 public static final int OP_RECORD_AUDIO = 27; 130 /** @hide */ 131 public static final int OP_PLAY_AUDIO = 28; 132 /** @hide */ 133 public static final int OP_READ_CLIPBOARD = 29; 134 /** @hide */ 135 public static final int OP_WRITE_CLIPBOARD = 30; 136 /** @hide */ 137 public static final int OP_TAKE_MEDIA_BUTTONS = 31; 138 /** @hide */ 139 public static final int OP_TAKE_AUDIO_FOCUS = 32; 140 /** @hide */ 141 public static final int OP_AUDIO_MASTER_VOLUME = 33; 142 /** @hide */ 143 public static final int OP_AUDIO_VOICE_VOLUME = 34; 144 /** @hide */ 145 public static final int OP_AUDIO_RING_VOLUME = 35; 146 /** @hide */ 147 public static final int OP_AUDIO_MEDIA_VOLUME = 36; 148 /** @hide */ 149 public static final int OP_AUDIO_ALARM_VOLUME = 37; 150 /** @hide */ 151 public static final int OP_AUDIO_NOTIFICATION_VOLUME = 38; 152 /** @hide */ 153 public static final int OP_AUDIO_BLUETOOTH_VOLUME = 39; 154 /** @hide */ 155 public static final int OP_WAKE_LOCK = 40; 156 /** Continually monitoring location data. */ 157 public static final int OP_MONITOR_LOCATION = 41; 158 /** Continually monitoring location data with a relatively high power request. */ 159 public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42; 160 /** @hide */ 161 public static final int _NUM_OP = 43; 162 163 /** 164 * This maps each operation to the operation that serves as the 165 * switch to determine whether it is allowed. Generally this is 166 * a 1:1 mapping, but for some things (like location) that have 167 * multiple low-level operations being tracked that should be 168 * presented to the user as one switch then this can be used to 169 * make them all controlled by the same single operation. 170 */ 171 private static int[] sOpToSwitch = new int[] { 172 OP_COARSE_LOCATION, 173 OP_COARSE_LOCATION, 174 OP_COARSE_LOCATION, 175 OP_VIBRATE, 176 OP_READ_CONTACTS, 177 OP_WRITE_CONTACTS, 178 OP_READ_CALL_LOG, 179 OP_WRITE_CALL_LOG, 180 OP_READ_CALENDAR, 181 OP_WRITE_CALENDAR, 182 OP_COARSE_LOCATION, 183 OP_POST_NOTIFICATION, 184 OP_COARSE_LOCATION, 185 OP_CALL_PHONE, 186 OP_READ_SMS, 187 OP_WRITE_SMS, 188 OP_RECEIVE_SMS, 189 OP_RECEIVE_SMS, 190 OP_RECEIVE_SMS, 191 OP_RECEIVE_SMS, 192 OP_SEND_SMS, 193 OP_READ_SMS, 194 OP_WRITE_SMS, 195 OP_WRITE_SETTINGS, 196 OP_SYSTEM_ALERT_WINDOW, 197 OP_ACCESS_NOTIFICATIONS, 198 OP_CAMERA, 199 OP_RECORD_AUDIO, 200 OP_PLAY_AUDIO, 201 OP_READ_CLIPBOARD, 202 OP_WRITE_CLIPBOARD, 203 OP_TAKE_MEDIA_BUTTONS, 204 OP_TAKE_AUDIO_FOCUS, 205 OP_AUDIO_MASTER_VOLUME, 206 OP_AUDIO_VOICE_VOLUME, 207 OP_AUDIO_RING_VOLUME, 208 OP_AUDIO_MEDIA_VOLUME, 209 OP_AUDIO_ALARM_VOLUME, 210 OP_AUDIO_NOTIFICATION_VOLUME, 211 OP_AUDIO_BLUETOOTH_VOLUME, 212 OP_WAKE_LOCK, 213 OP_COARSE_LOCATION, 214 OP_COARSE_LOCATION, 215 }; 216 217 /** 218 * This provides a simple name for each operation to be used 219 * in debug output. 220 */ 221 private static String[] sOpNames = new String[] { 222 "COARSE_LOCATION", 223 "FINE_LOCATION", 224 "GPS", 225 "VIBRATE", 226 "READ_CONTACTS", 227 "WRITE_CONTACTS", 228 "READ_CALL_LOG", 229 "WRITE_CALL_LOG", 230 "READ_CALENDAR", 231 "WRITE_CALENDAR", 232 "WIFI_SCAN", 233 "POST_NOTIFICATION", 234 "NEIGHBORING_CELLS", 235 "CALL_PHONE", 236 "READ_SMS", 237 "WRITE_SMS", 238 "RECEIVE_SMS", 239 "RECEIVE_EMERGECY_SMS", 240 "RECEIVE_MMS", 241 "RECEIVE_WAP_PUSH", 242 "SEND_SMS", 243 "READ_ICC_SMS", 244 "WRITE_ICC_SMS", 245 "WRITE_SETTINGS", 246 "SYSTEM_ALERT_WINDOW", 247 "ACCESS_NOTIFICATIONS", 248 "CAMERA", 249 "RECORD_AUDIO", 250 "PLAY_AUDIO", 251 "READ_CLIPBOARD", 252 "WRITE_CLIPBOARD", 253 "TAKE_MEDIA_BUTTONS", 254 "TAKE_AUDIO_FOCUS", 255 "AUDIO_MASTER_VOLUME", 256 "AUDIO_VOICE_VOLUME", 257 "AUDIO_RING_VOLUME", 258 "AUDIO_MEDIA_VOLUME", 259 "AUDIO_ALARM_VOLUME", 260 "AUDIO_NOTIFICATION_VOLUME", 261 "AUDIO_BLUETOOTH_VOLUME", 262 "WAKE_LOCK", 263 "MONITOR_LOCATION", 264 "MONITOR_HIGH_POWER_LOCATION", 265 }; 266 267 /** 268 * This optionally maps a permission to an operation. If there 269 * is no permission associated with an operation, it is null. 270 */ 271 private static String[] sOpPerms = new String[] { 272 android.Manifest.permission.ACCESS_COARSE_LOCATION, 273 android.Manifest.permission.ACCESS_FINE_LOCATION, 274 null, 275 android.Manifest.permission.VIBRATE, 276 android.Manifest.permission.READ_CONTACTS, 277 android.Manifest.permission.WRITE_CONTACTS, 278 android.Manifest.permission.READ_CALL_LOG, 279 android.Manifest.permission.WRITE_CALL_LOG, 280 android.Manifest.permission.READ_CALENDAR, 281 android.Manifest.permission.WRITE_CALENDAR, 282 null, // no permission required for notifications 283 android.Manifest.permission.ACCESS_WIFI_STATE, 284 null, // neighboring cells shares the coarse location perm 285 android.Manifest.permission.CALL_PHONE, 286 android.Manifest.permission.READ_SMS, 287 android.Manifest.permission.WRITE_SMS, 288 android.Manifest.permission.RECEIVE_SMS, 289 android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST, 290 android.Manifest.permission.RECEIVE_MMS, 291 android.Manifest.permission.RECEIVE_WAP_PUSH, 292 android.Manifest.permission.SEND_SMS, 293 android.Manifest.permission.READ_SMS, 294 android.Manifest.permission.WRITE_SMS, 295 android.Manifest.permission.WRITE_SETTINGS, 296 android.Manifest.permission.SYSTEM_ALERT_WINDOW, 297 android.Manifest.permission.ACCESS_NOTIFICATIONS, 298 android.Manifest.permission.CAMERA, 299 android.Manifest.permission.RECORD_AUDIO, 300 null, // no permission for playing audio 301 null, // no permission for reading clipboard 302 null, // no permission for writing clipboard 303 null, // no permission for taking media buttons 304 null, // no permission for taking audio focus 305 null, // no permission for changing master volume 306 null, // no permission for changing voice volume 307 null, // no permission for changing ring volume 308 null, // no permission for changing media volume 309 null, // no permission for changing alarm volume 310 null, // no permission for changing notification volume 311 null, // no permission for changing bluetooth volume 312 android.Manifest.permission.WAKE_LOCK, 313 null, // no permission for generic location monitoring 314 null, // no permission for high power location monitoring 315 }; 316 317 /** 318 * This specifies the default mode for each operation. 319 */ 320 private static int[] sOpDefaultMode = new int[] { 321 AppOpsManager.MODE_ALLOWED, 322 AppOpsManager.MODE_ALLOWED, 323 AppOpsManager.MODE_ALLOWED, 324 AppOpsManager.MODE_ALLOWED, 325 AppOpsManager.MODE_ALLOWED, 326 AppOpsManager.MODE_ALLOWED, 327 AppOpsManager.MODE_ALLOWED, 328 AppOpsManager.MODE_ALLOWED, 329 AppOpsManager.MODE_ALLOWED, 330 AppOpsManager.MODE_ALLOWED, 331 AppOpsManager.MODE_ALLOWED, 332 AppOpsManager.MODE_ALLOWED, 333 AppOpsManager.MODE_ALLOWED, 334 AppOpsManager.MODE_ALLOWED, 335 AppOpsManager.MODE_ALLOWED, 336 AppOpsManager.MODE_IGNORED, // OP_WRITE_SMS 337 AppOpsManager.MODE_ALLOWED, 338 AppOpsManager.MODE_ALLOWED, 339 AppOpsManager.MODE_ALLOWED, 340 AppOpsManager.MODE_ALLOWED, 341 AppOpsManager.MODE_ALLOWED, 342 AppOpsManager.MODE_ALLOWED, 343 AppOpsManager.MODE_ALLOWED, 344 AppOpsManager.MODE_ALLOWED, 345 AppOpsManager.MODE_ALLOWED, 346 AppOpsManager.MODE_ALLOWED, 347 AppOpsManager.MODE_ALLOWED, 348 AppOpsManager.MODE_ALLOWED, 349 AppOpsManager.MODE_ALLOWED, 350 AppOpsManager.MODE_ALLOWED, 351 AppOpsManager.MODE_ALLOWED, 352 AppOpsManager.MODE_ALLOWED, 353 AppOpsManager.MODE_ALLOWED, 354 AppOpsManager.MODE_ALLOWED, 355 AppOpsManager.MODE_ALLOWED, 356 AppOpsManager.MODE_ALLOWED, 357 AppOpsManager.MODE_ALLOWED, 358 AppOpsManager.MODE_ALLOWED, 359 AppOpsManager.MODE_ALLOWED, 360 AppOpsManager.MODE_ALLOWED, 361 AppOpsManager.MODE_ALLOWED, 362 AppOpsManager.MODE_ALLOWED, 363 AppOpsManager.MODE_ALLOWED, 364 }; 365 366 /** 367 * Retrieve the op switch that controls the given operation. 368 * @hide 369 */ 370 public static int opToSwitch(int op) { 371 return sOpToSwitch[op]; 372 } 373 374 /** 375 * Retrieve a non-localized name for the operation, for debugging output. 376 */ 377 public static String opToName(int op) { 378 if (op == OP_NONE) return "NONE"; 379 return op < sOpNames.length ? sOpNames[op] : ("Unknown(" + op + ")"); 380 } 381 382 /** 383 * Retrieve the permission associated with an operation, or null if there is not one. 384 * @hide 385 */ 386 public static String opToPermission(int op) { 387 return sOpPerms[op]; 388 } 389 390 /** 391 * Retrieve the default mode for the operation. 392 * @hide 393 */ 394 public static int opToDefaultMode(int op) { 395 return sOpDefaultMode[op]; 396 } 397 398 /** 399 * Class holding all of the operation information associated with an app. 400 * @hide 401 */ 402 public static class PackageOps implements Parcelable { 403 private final String mPackageName; 404 private final int mUid; 405 private final List<OpEntry> mEntries; 406 407 public PackageOps(String packageName, int uid, List<OpEntry> entries) { 408 mPackageName = packageName; 409 mUid = uid; 410 mEntries = entries; 411 } 412 413 public String getPackageName() { 414 return mPackageName; 415 } 416 417 public int getUid() { 418 return mUid; 419 } 420 421 public List<OpEntry> getOps() { 422 return mEntries; 423 } 424 425 @Override 426 public int describeContents() { 427 return 0; 428 } 429 430 @Override 431 public void writeToParcel(Parcel dest, int flags) { 432 dest.writeString(mPackageName); 433 dest.writeInt(mUid); 434 dest.writeInt(mEntries.size()); 435 for (int i=0; i<mEntries.size(); i++) { 436 mEntries.get(i).writeToParcel(dest, flags); 437 } 438 } 439 440 PackageOps(Parcel source) { 441 mPackageName = source.readString(); 442 mUid = source.readInt(); 443 mEntries = new ArrayList<OpEntry>(); 444 final int N = source.readInt(); 445 for (int i=0; i<N; i++) { 446 mEntries.add(OpEntry.CREATOR.createFromParcel(source)); 447 } 448 } 449 450 public static final Creator<PackageOps> CREATOR = new Creator<PackageOps>() { 451 @Override public PackageOps createFromParcel(Parcel source) { 452 return new PackageOps(source); 453 } 454 455 @Override public PackageOps[] newArray(int size) { 456 return new PackageOps[size]; 457 } 458 }; 459 } 460 461 /** 462 * Class holding the information about one unique operation of an application. 463 * @hide 464 */ 465 public static class OpEntry implements Parcelable { 466 private final int mOp; 467 private final int mMode; 468 private final long mTime; 469 private final long mRejectTime; 470 private final int mDuration; 471 472 public OpEntry(int op, int mode, long time, long rejectTime, int duration) { 473 mOp = op; 474 mMode = mode; 475 mTime = time; 476 mRejectTime = rejectTime; 477 mDuration = duration; 478 } 479 480 public int getOp() { 481 return mOp; 482 } 483 484 public int getMode() { 485 return mMode; 486 } 487 488 public long getTime() { 489 return mTime; 490 } 491 492 public long getRejectTime() { 493 return mRejectTime; 494 } 495 496 public boolean isRunning() { 497 return mDuration == -1; 498 } 499 500 public int getDuration() { 501 return mDuration == -1 ? (int)(System.currentTimeMillis()-mTime) : mDuration; 502 } 503 504 @Override 505 public int describeContents() { 506 return 0; 507 } 508 509 @Override 510 public void writeToParcel(Parcel dest, int flags) { 511 dest.writeInt(mOp); 512 dest.writeInt(mMode); 513 dest.writeLong(mTime); 514 dest.writeLong(mRejectTime); 515 dest.writeInt(mDuration); 516 } 517 518 OpEntry(Parcel source) { 519 mOp = source.readInt(); 520 mMode = source.readInt(); 521 mTime = source.readLong(); 522 mRejectTime = source.readLong(); 523 mDuration = source.readInt(); 524 } 525 526 public static final Creator<OpEntry> CREATOR = new Creator<OpEntry>() { 527 @Override public OpEntry createFromParcel(Parcel source) { 528 return new OpEntry(source); 529 } 530 531 @Override public OpEntry[] newArray(int size) { 532 return new OpEntry[size]; 533 } 534 }; 535 } 536 537 /** 538 * Callback for notification of changes to operation state. 539 */ 540 public interface Callback { 541 public void opChanged(int op, String packageName); 542 } 543 544 AppOpsManager(Context context, IAppOpsService service) { 545 mContext = context; 546 mService = service; 547 } 548 549 /** 550 * Retrieve current operation state for all applications. 551 * 552 * @param ops The set of operations you are interested in, or null if you want all of them. 553 * @hide 554 */ 555 public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) { 556 try { 557 return mService.getPackagesForOps(ops); 558 } catch (RemoteException e) { 559 } 560 return null; 561 } 562 563 /** 564 * Retrieve current operation state for one application. 565 * 566 * @param uid The uid of the application of interest. 567 * @param packageName The name of the application of interest. 568 * @param ops The set of operations you are interested in, or null if you want all of them. 569 * @hide 570 */ 571 public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, int[] ops) { 572 try { 573 return mService.getOpsForPackage(uid, packageName, ops); 574 } catch (RemoteException e) { 575 } 576 return null; 577 } 578 579 /** @hide */ 580 public void setMode(int code, int uid, String packageName, int mode) { 581 try { 582 mService.setMode(code, uid, packageName, mode); 583 } catch (RemoteException e) { 584 } 585 } 586 587 /** @hide */ 588 public void resetAllModes() { 589 try { 590 mService.resetAllModes(); 591 } catch (RemoteException e) { 592 } 593 } 594 595 /** 596 * Monitor for changes to the operating mode for the given op in the given app package. 597 * @param op The operation to monitor, one of OP_*. 598 * @param packageName The name of the application to monitor. 599 * @param callback Where to report changes. 600 */ 601 public void startWatchingMode(int op, String packageName, final Callback callback) { 602 synchronized (mModeWatchers) { 603 IAppOpsCallback cb = mModeWatchers.get(callback); 604 if (cb == null) { 605 cb = new IAppOpsCallback.Stub() { 606 public void opChanged(int op, String packageName) { 607 callback.opChanged(op, packageName); 608 } 609 }; 610 mModeWatchers.put(callback, cb); 611 } 612 try { 613 mService.startWatchingMode(op, packageName, cb); 614 } catch (RemoteException e) { 615 } 616 } 617 } 618 619 /** 620 * Stop monitoring that was previously started with {@link #startWatchingMode}. All 621 * monitoring associated with this callback will be removed. 622 */ 623 public void stopWatchingMode(Callback callback) { 624 synchronized (mModeWatchers) { 625 IAppOpsCallback cb = mModeWatchers.get(callback); 626 if (cb != null) { 627 try { 628 mService.stopWatchingMode(cb); 629 } catch (RemoteException e) { 630 } 631 } 632 } 633 } 634 635 private String buildSecurityExceptionMsg(int op, int uid, String packageName) { 636 return packageName + " from uid " + uid + " not allowed to perform " + sOpNames[op]; 637 } 638 639 /** 640 * Do a quick check for whether an application might be able to perform an operation. 641 * This is <em>not</em> a security check; you must use {@link #noteOp(int, int, String)} 642 * or {@link #startOp(int, int, String)} for your actual security checks, which also 643 * ensure that the given uid and package name are consistent. This function can just be 644 * used for a quick check to see if an operation has been disabled for the application, 645 * as an early reject of some work. This does not modify the time stamp or other data 646 * about the operation. 647 * @param op The operation to check. One of the OP_* constants. 648 * @param uid The user id of the application attempting to perform the operation. 649 * @param packageName The name of the application attempting to perform the operation. 650 * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or 651 * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without 652 * causing the app to crash). 653 * @throws SecurityException If the app has been configured to crash on this op. 654 */ 655 public int checkOp(int op, int uid, String packageName) { 656 try { 657 int mode = mService.checkOperation(op, uid, packageName); 658 if (mode == MODE_ERRORED) { 659 throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName)); 660 } 661 return mode; 662 } catch (RemoteException e) { 663 } 664 return MODE_IGNORED; 665 } 666 667 /** 668 * Like {@link #checkOp} but instead of throwing a {@link SecurityException} it 669 * returns {@link #MODE_ERRORED}. 670 */ 671 public int checkOpNoThrow(int op, int uid, String packageName) { 672 try { 673 return mService.checkOperation(op, uid, packageName); 674 } catch (RemoteException e) { 675 } 676 return MODE_IGNORED; 677 } 678 679 /** 680 * Do a quick check to validate if a package name belongs to a UID. 681 * 682 * @throws SecurityException if the package name doesn't belong to the given 683 * UID, or if ownership cannot be verified. 684 */ 685 public void checkPackage(int uid, String packageName) { 686 try { 687 if (mService.checkPackage(uid, packageName) != MODE_ALLOWED) { 688 throw new SecurityException( 689 "Package " + packageName + " does not belong to " + uid); 690 } 691 } catch (RemoteException e) { 692 throw new SecurityException("Unable to verify package ownership", e); 693 } 694 } 695 696 /** 697 * Make note of an application performing an operation. Note that you must pass 698 * in both the uid and name of the application to be checked; this function will verify 699 * that these two match, and if not, return {@link #MODE_IGNORED}. If this call 700 * succeeds, the last execution time of the operation for this app will be updated to 701 * the current time. 702 * @param op The operation to note. One of the OP_* constants. 703 * @param uid The user id of the application attempting to perform the operation. 704 * @param packageName The name of the application attempting to perform the operation. 705 * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or 706 * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without 707 * causing the app to crash). 708 * @throws SecurityException If the app has been configured to crash on this op. 709 */ 710 public int noteOp(int op, int uid, String packageName) { 711 try { 712 int mode = mService.noteOperation(op, uid, packageName); 713 if (mode == MODE_ERRORED) { 714 throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName)); 715 } 716 return mode; 717 } catch (RemoteException e) { 718 } 719 return MODE_IGNORED; 720 } 721 722 /** 723 * Like {@link #noteOp} but instead of throwing a {@link SecurityException} it 724 * returns {@link #MODE_ERRORED}. 725 */ 726 public int noteOpNoThrow(int op, int uid, String packageName) { 727 try { 728 return mService.noteOperation(op, uid, packageName); 729 } catch (RemoteException e) { 730 } 731 return MODE_IGNORED; 732 } 733 734 /** @hide */ 735 public int noteOp(int op) { 736 return noteOp(op, Process.myUid(), mContext.getOpPackageName()); 737 } 738 739 /** @hide */ 740 public static IBinder getToken(IAppOpsService service) { 741 synchronized (AppOpsManager.class) { 742 if (sToken != null) { 743 return sToken; 744 } 745 try { 746 sToken = service.getToken(new Binder()); 747 } catch (RemoteException e) { 748 // System is dead, whatevs. 749 } 750 return sToken; 751 } 752 } 753 754 /** 755 * Report that an application has started executing a long-running operation. Note that you 756 * must pass in both the uid and name of the application to be checked; this function will 757 * verify that these two match, and if not, return {@link #MODE_IGNORED}. If this call 758 * succeeds, the last execution time of the operation for this app will be updated to 759 * the current time and the operation will be marked as "running". In this case you must 760 * later call {@link #finishOp(int, int, String)} to report when the application is no 761 * longer performing the operation. 762 * @param op The operation to start. One of the OP_* constants. 763 * @param uid The user id of the application attempting to perform the operation. 764 * @param packageName The name of the application attempting to perform the operation. 765 * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or 766 * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without 767 * causing the app to crash). 768 * @throws SecurityException If the app has been configured to crash on this op. 769 */ 770 public int startOp(int op, int uid, String packageName) { 771 try { 772 int mode = mService.startOperation(getToken(mService), op, uid, packageName); 773 if (mode == MODE_ERRORED) { 774 throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName)); 775 } 776 return mode; 777 } catch (RemoteException e) { 778 } 779 return MODE_IGNORED; 780 } 781 782 /** 783 * Like {@link #startOp} but instead of throwing a {@link SecurityException} it 784 * returns {@link #MODE_ERRORED}. 785 */ 786 public int startOpNoThrow(int op, int uid, String packageName) { 787 try { 788 return mService.startOperation(getToken(mService), op, uid, packageName); 789 } catch (RemoteException e) { 790 } 791 return MODE_IGNORED; 792 } 793 794 /** @hide */ 795 public int startOp(int op) { 796 return startOp(op, Process.myUid(), mContext.getOpPackageName()); 797 } 798 799 /** 800 * Report that an application is no longer performing an operation that had previously 801 * been started with {@link #startOp(int, int, String)}. There is no validation of input 802 * or result; the parameters supplied here must be the exact same ones previously passed 803 * in when starting the operation. 804 */ 805 public void finishOp(int op, int uid, String packageName) { 806 try { 807 mService.finishOperation(getToken(mService), op, uid, packageName); 808 } catch (RemoteException e) { 809 } 810 } 811 812 public void finishOp(int op) { 813 finishOp(op, Process.myUid(), mContext.getOpPackageName()); 814 } 815} 816