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 com.android.server; 18 19 import java.io.File; 20 import java.io.FileDescriptor; 21 import java.io.FileInputStream; 22 import java.io.FileNotFoundException; 23 import java.io.FileOutputStream; 24 import java.io.IOException; 25 import java.io.PrintWriter; 26 import java.nio.charset.StandardCharsets; 27 import java.util.ArrayList; 28 import java.util.Arrays; 29 import java.util.Collections; 30 import java.util.HashMap; 31 import java.util.Iterator; 32 import java.util.List; 33 import java.util.Map; 34 35 import android.Manifest; 36 import android.app.ActivityManager; 37 import android.app.ActivityThread; 38 import android.app.AppGlobals; 39 import android.app.AppOpsManager; 40 import android.content.Context; 41 import android.content.pm.ApplicationInfo; 42 import android.content.pm.IPackageManager; 43 import android.content.pm.PackageManager; 44 import android.media.AudioAttributes; 45 import android.os.AsyncTask; 46 import android.os.Binder; 47 import android.os.Bundle; 48 import android.os.Handler; 49 import android.os.IBinder; 50 import android.os.Process; 51 import android.os.RemoteException; 52 import android.os.ResultReceiver; 53 import android.os.ServiceManager; 54 import android.os.ShellCommand; 55 import android.os.UserHandle; 56 import android.os.storage.MountServiceInternal; 57 import android.util.ArrayMap; 58 import android.util.ArraySet; 59 import android.util.AtomicFile; 60 import android.util.Log; 61 import android.util.Slog; 62 import android.util.SparseArray; 63 import android.util.SparseIntArray; 64 import android.util.TimeUtils; 65 import android.util.Xml; 66 67 import com.android.internal.app.IAppOpsService; 68 import com.android.internal.app.IAppOpsCallback; 69 import com.android.internal.os.Zygote; 70 import com.android.internal.util.ArrayUtils; 71 import com.android.internal.util.FastXmlSerializer; 72 import com.android.internal.util.Preconditions; 73 import com.android.internal.util.XmlUtils; 74 75 import libcore.util.EmptyArray; 76 import org.xmlpull.v1.XmlPullParser; 77 import org.xmlpull.v1.XmlPullParserException; 78 import org.xmlpull.v1.XmlSerializer; 79 80 public class AppOpsService extends IAppOpsService.Stub { 81 static final String TAG = "AppOps"; 82 static final boolean DEBUG = false; 83 84 // Write at most every 30 minutes. 85 static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000; 86 87 Context mContext; 88 final AtomicFile mFile; 89 final Handler mHandler; 90 91 boolean mWriteScheduled; 92 boolean mFastWriteScheduled; 93 final Runnable mWriteRunner = new Runnable() { 94 public void run() { 95 synchronized (AppOpsService.this) { 96 mWriteScheduled = false; 97 mFastWriteScheduled = false; 98 AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() { 99 @Override protected Void doInBackground(Void... params) { 100 writeState(); 101 return null; 102 } 103 }; 104 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null); 105 } 106 } 107 }; 108 109 private final SparseArray<UidState> mUidStates = new SparseArray<>(); 110 111 /* 112 * These are app op restrictions imposed per user from various parties. 113 */ 114 private final ArrayMap<IBinder, ClientRestrictionState> mOpUserRestrictions = new ArrayMap<>(); 115 116 private static final class UidState { 117 public final int uid; 118 public ArrayMap<String, Ops> pkgOps; 119 public SparseIntArray opModes; 120 121 public UidState(int uid) { 122 this.uid = uid; 123 } 124 125 public void clear() { 126 pkgOps = null; 127 opModes = null; 128 } 129 130 public boolean isDefault() { 131 return (pkgOps == null || pkgOps.isEmpty()) 132 && (opModes == null || opModes.size() <= 0); 133 } 134 } 135 136 public final static class Ops extends SparseArray<Op> { 137 public final String packageName; 138 public final UidState uidState; 139 public final boolean isPrivileged; 140 141 public Ops(String _packageName, UidState _uidState, boolean _isPrivileged) { 142 packageName = _packageName; 143 uidState = _uidState; 144 isPrivileged = _isPrivileged; 145 } 146 } 147 148 public final static class Op { 149 public final int uid; 150 public final String packageName; 151 public int proxyUid = -1; 152 public String proxyPackageName; 153 public final int op; 154 public int mode; 155 public int duration; 156 public long time; 157 public long rejectTime; 158 public int nesting; 159 160 public Op(int _uid, String _packageName, int _op) { 161 uid = _uid; 162 packageName = _packageName; 163 op = _op; 164 mode = AppOpsManager.opToDefaultMode(op); 165 } 166 } 167 168 final SparseArray<ArrayList<Callback>> mOpModeWatchers 169 = new SparseArray<ArrayList<Callback>>(); 170 final ArrayMap<String, ArrayList<Callback>> mPackageModeWatchers 171 = new ArrayMap<String, ArrayList<Callback>>(); 172 final ArrayMap<IBinder, Callback> mModeWatchers 173 = new ArrayMap<IBinder, Callback>(); 174 final SparseArray<SparseArray<Restriction>> mAudioRestrictions 175 = new SparseArray<SparseArray<Restriction>>(); 176 177 public final class Callback implements DeathRecipient { 178 final IAppOpsCallback mCallback; 179 180 public Callback(IAppOpsCallback callback) { 181 mCallback = callback; 182 try { 183 mCallback.asBinder().linkToDeath(this, 0); 184 } catch (RemoteException e) { 185 } 186 } 187 188 public void unlinkToDeath() { 189 mCallback.asBinder().unlinkToDeath(this, 0); 190 } 191 192 @Override 193 public void binderDied() { 194 stopWatchingMode(mCallback); 195 } 196 } 197 198 final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<IBinder, ClientState>(); 199 200 public final class ClientState extends Binder implements DeathRecipient { 201 final IBinder mAppToken; 202 final int mPid; 203 final ArrayList<Op> mStartedOps; 204 205 public ClientState(IBinder appToken) { 206 mAppToken = appToken; 207 mPid = Binder.getCallingPid(); 208 if (appToken instanceof Binder) { 209 // For local clients, there is no reason to track them. 210 mStartedOps = null; 211 } else { 212 mStartedOps = new ArrayList<Op>(); 213 try { 214 mAppToken.linkToDeath(this, 0); 215 } catch (RemoteException e) { 216 } 217 } 218 } 219 220 @Override 221 public String toString() { 222 return "ClientState{" + 223 "mAppToken=" + mAppToken + 224 ", " + (mStartedOps != null ? ("pid=" + mPid) : "local") + 225 '}'; 226 } 227 228 @Override 229 public void binderDied() { 230 synchronized (AppOpsService.this) { 231 for (int i=mStartedOps.size()-1; i>=0; i--) { 232 finishOperationLocked(mStartedOps.get(i)); 233 } 234 mClients.remove(mAppToken); 235 } 236 } 237 } 238 239 public AppOpsService(File storagePath, Handler handler) { 240 mFile = new AtomicFile(storagePath); 241 mHandler = handler; 242 readState(); 243 } 244 245 public void publish(Context context) { 246 mContext = context; 247 ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder()); 248 } 249 250 public void systemReady() { 251 synchronized (this) { 252 boolean changed = false; 253 for (int i = mUidStates.size() - 1; i >= 0; i--) { 254 UidState uidState = mUidStates.valueAt(i); 255 256 String[] packageNames = getPackagesForUid(uidState.uid); 257 if (ArrayUtils.isEmpty(packageNames)) { 258 uidState.clear(); 259 mUidStates.removeAt(i); 260 changed = true; 261 continue; 262 } 263 264 ArrayMap<String, Ops> pkgs = uidState.pkgOps; 265 if (pkgs == null) { 266 continue; 267 } 268 269 Iterator<Ops> it = pkgs.values().iterator(); 270 while (it.hasNext()) { 271 Ops ops = it.next(); 272 int curUid = -1; 273 try { 274 curUid = AppGlobals.getPackageManager().getPackageUid(ops.packageName, 275 PackageManager.MATCH_UNINSTALLED_PACKAGES, 276 UserHandle.getUserId(ops.uidState.uid)); 277 } catch (RemoteException ignored) { 278 } 279 if (curUid != ops.uidState.uid) { 280 Slog.i(TAG, "Pruning old package " + ops.packageName 281 + "/" + ops.uidState + ": new uid=" + curUid); 282 it.remove(); 283 changed = true; 284 } 285 } 286 287 if (uidState.isDefault()) { 288 mUidStates.removeAt(i); 289 } 290 } 291 if (changed) { 292 scheduleFastWriteLocked(); 293 } 294 } 295 296 MountServiceInternal mountServiceInternal = LocalServices.getService( 297 MountServiceInternal.class); 298 mountServiceInternal.addExternalStoragePolicy( 299 new MountServiceInternal.ExternalStorageMountPolicy() { 300 @Override 301 public int getMountMode(int uid, String packageName) { 302 if (Process.isIsolated(uid)) { 303 return Zygote.MOUNT_EXTERNAL_NONE; 304 } 305 if (noteOperation(AppOpsManager.OP_READ_EXTERNAL_STORAGE, uid, 306 packageName) != AppOpsManager.MODE_ALLOWED) { 307 return Zygote.MOUNT_EXTERNAL_NONE; 308 } 309 if (noteOperation(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, uid, 310 packageName) != AppOpsManager.MODE_ALLOWED) { 311 return Zygote.MOUNT_EXTERNAL_READ; 312 } 313 return Zygote.MOUNT_EXTERNAL_WRITE; 314 } 315 316 @Override 317 public boolean hasExternalStorage(int uid, String packageName) { 318 final int mountMode = getMountMode(uid, packageName); 319 return mountMode == Zygote.MOUNT_EXTERNAL_READ 320 || mountMode == Zygote.MOUNT_EXTERNAL_WRITE; 321 } 322 }); 323 } 324 325 public void packageRemoved(int uid, String packageName) { 326 synchronized (this) { 327 UidState uidState = mUidStates.get(uid); 328 if (uidState == null) { 329 return; 330 } 331 332 boolean changed = false; 333 334 // Remove any package state if such. 335 if (uidState.pkgOps != null && uidState.pkgOps.remove(packageName) != null) { 336 changed = true; 337 } 338 339 // If we just nuked the last package state check if the UID is valid. 340 if (changed && uidState.pkgOps.isEmpty() 341 && getPackagesForUid(uid).length <= 0) { 342 mUidStates.remove(uid); 343 } 344 345 if (changed) { 346 scheduleFastWriteLocked(); 347 } 348 } 349 } 350 351 public void uidRemoved(int uid) { 352 synchronized (this) { 353 if (mUidStates.indexOfKey(uid) >= 0) { 354 mUidStates.remove(uid); 355 scheduleFastWriteLocked(); 356 } 357 } 358 } 359 360 public void shutdown() { 361 Slog.w(TAG, "Writing app ops before shutdown..."); 362 boolean doWrite = false; 363 synchronized (this) { 364 if (mWriteScheduled) { 365 mWriteScheduled = false; 366 doWrite = true; 367 } 368 } 369 if (doWrite) { 370 writeState(); 371 } 372 } 373 374 private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) { 375 ArrayList<AppOpsManager.OpEntry> resOps = null; 376 if (ops == null) { 377 resOps = new ArrayList<AppOpsManager.OpEntry>(); 378 for (int j=0; j<pkgOps.size(); j++) { 379 Op curOp = pkgOps.valueAt(j); 380 resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time, 381 curOp.rejectTime, curOp.duration, curOp.proxyUid, 382 curOp.proxyPackageName)); 383 } 384 } else { 385 for (int j=0; j<ops.length; j++) { 386 Op curOp = pkgOps.get(ops[j]); 387 if (curOp != null) { 388 if (resOps == null) { 389 resOps = new ArrayList<AppOpsManager.OpEntry>(); 390 } 391 resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time, 392 curOp.rejectTime, curOp.duration, curOp.proxyUid, 393 curOp.proxyPackageName)); 394 } 395 } 396 } 397 return resOps; 398 } 399 400 @Override 401 public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) { 402 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 403 Binder.getCallingPid(), Binder.getCallingUid(), null); 404 ArrayList<AppOpsManager.PackageOps> res = null; 405 synchronized (this) { 406 final int uidStateCount = mUidStates.size(); 407 for (int i = 0; i < uidStateCount; i++) { 408 UidState uidState = mUidStates.valueAt(i); 409 if (uidState.pkgOps == null || uidState.pkgOps.isEmpty()) { 410 continue; 411 } 412 ArrayMap<String, Ops> packages = uidState.pkgOps; 413 final int packageCount = packages.size(); 414 for (int j = 0; j < packageCount; j++) { 415 Ops pkgOps = packages.valueAt(j); 416 ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops); 417 if (resOps != null) { 418 if (res == null) { 419 res = new ArrayList<AppOpsManager.PackageOps>(); 420 } 421 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( 422 pkgOps.packageName, pkgOps.uidState.uid, resOps); 423 res.add(resPackage); 424 } 425 } 426 } 427 } 428 return res; 429 } 430 431 @Override 432 public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, 433 int[] ops) { 434 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 435 Binder.getCallingPid(), Binder.getCallingUid(), null); 436 String resolvedPackageName = resolvePackageName(uid, packageName); 437 if (resolvedPackageName == null) { 438 return Collections.emptyList(); 439 } 440 synchronized (this) { 441 Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false); 442 if (pkgOps == null) { 443 return null; 444 } 445 ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops); 446 if (resOps == null) { 447 return null; 448 } 449 ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>(); 450 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( 451 pkgOps.packageName, pkgOps.uidState.uid, resOps); 452 res.add(resPackage); 453 return res; 454 } 455 } 456 457 private void pruneOp(Op op, int uid, String packageName) { 458 if (op.time == 0 && op.rejectTime == 0) { 459 Ops ops = getOpsRawLocked(uid, packageName, false); 460 if (ops != null) { 461 ops.remove(op.op); 462 if (ops.size() <= 0) { 463 UidState uidState = ops.uidState; 464 ArrayMap<String, Ops> pkgOps = uidState.pkgOps; 465 if (pkgOps != null) { 466 pkgOps.remove(ops.packageName); 467 if (pkgOps.isEmpty()) { 468 uidState.pkgOps = null; 469 } 470 if (uidState.isDefault()) { 471 mUidStates.remove(uid); 472 } 473 } 474 } 475 } 476 } 477 } 478 479 @Override 480 public void setUidMode(int code, int uid, int mode) { 481 if (Binder.getCallingPid() != Process.myPid()) { 482 mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 483 Binder.getCallingPid(), Binder.getCallingUid(), null); 484 } 485 verifyIncomingOp(code); 486 code = AppOpsManager.opToSwitch(code); 487 488 synchronized (this) { 489 final int defaultMode = AppOpsManager.opToDefaultMode(code); 490 491 UidState uidState = getUidStateLocked(uid, false); 492 if (uidState == null) { 493 if (mode == defaultMode) { 494 return; 495 } 496 uidState = new UidState(uid); 497 uidState.opModes = new SparseIntArray(); 498 uidState.opModes.put(code, mode); 499 mUidStates.put(uid, uidState); 500 scheduleWriteLocked(); 501 } else if (uidState.opModes == null) { 502 if (mode != defaultMode) { 503 uidState.opModes = new SparseIntArray(); 504 uidState.opModes.put(code, mode); 505 scheduleWriteLocked(); 506 } 507 } else { 508 if (uidState.opModes.get(code) == mode) { 509 return; 510 } 511 if (mode == defaultMode) { 512 uidState.opModes.delete(code); 513 if (uidState.opModes.size() <= 0) { 514 uidState.opModes = null; 515 } 516 } else { 517 uidState.opModes.put(code, mode); 518 } 519 scheduleWriteLocked(); 520 } 521 } 522 523 String[] uidPackageNames = getPackagesForUid(uid); 524 ArrayMap<Callback, ArraySet<String>> callbackSpecs = null; 525 526 synchronized (this) { 527 ArrayList<Callback> callbacks = mOpModeWatchers.get(code); 528 if (callbacks != null) { 529 final int callbackCount = callbacks.size(); 530 for (int i = 0; i < callbackCount; i++) { 531 Callback callback = callbacks.get(i); 532 ArraySet<String> changedPackages = new ArraySet<>(); 533 Collections.addAll(changedPackages, uidPackageNames); 534 callbackSpecs = new ArrayMap<>(); 535 callbackSpecs.put(callback, changedPackages); 536 } 537 } 538 539 for (String uidPackageName : uidPackageNames) { 540 callbacks = mPackageModeWatchers.get(uidPackageName); 541 if (callbacks != null) { 542 if (callbackSpecs == null) { 543 callbackSpecs = new ArrayMap<>(); 544 } 545 final int callbackCount = callbacks.size(); 546 for (int i = 0; i < callbackCount; i++) { 547 Callback callback = callbacks.get(i); 548 ArraySet<String> changedPackages = callbackSpecs.get(callback); 549 if (changedPackages == null) { 550 changedPackages = new ArraySet<>(); 551 callbackSpecs.put(callback, changedPackages); 552 } 553 changedPackages.add(uidPackageName); 554 } 555 } 556 } 557 } 558 559 if (callbackSpecs == null) { 560 return; 561 } 562 563 // There are components watching for mode changes such as window manager 564 // and location manager which are in our process. The callbacks in these 565 // components may require permissions our remote caller does not have. 566 final long identity = Binder.clearCallingIdentity(); 567 try { 568 for (int i = 0; i < callbackSpecs.size(); i++) { 569 Callback callback = callbackSpecs.keyAt(i); 570 ArraySet<String> reportedPackageNames = callbackSpecs.valueAt(i); 571 try { 572 if (reportedPackageNames == null) { 573 callback.mCallback.opChanged(code, uid, null); 574 } else { 575 final int reportedPackageCount = reportedPackageNames.size(); 576 for (int j = 0; j < reportedPackageCount; j++) { 577 String reportedPackageName = reportedPackageNames.valueAt(j); 578 callback.mCallback.opChanged(code, uid, reportedPackageName); 579 } 580 } 581 } catch (RemoteException e) { 582 Log.w(TAG, "Error dispatching op op change", e); 583 } 584 } 585 } finally { 586 Binder.restoreCallingIdentity(identity); 587 } 588 } 589 590 @Override 591 public void setMode(int code, int uid, String packageName, int mode) { 592 if (Binder.getCallingPid() != Process.myPid()) { 593 mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 594 Binder.getCallingPid(), Binder.getCallingUid(), null); 595 } 596 verifyIncomingOp(code); 597 ArrayList<Callback> repCbs = null; 598 code = AppOpsManager.opToSwitch(code); 599 synchronized (this) { 600 UidState uidState = getUidStateLocked(uid, false); 601 Op op = getOpLocked(code, uid, packageName, true); 602 if (op != null) { 603 if (op.mode != mode) { 604 op.mode = mode; 605 ArrayList<Callback> cbs = mOpModeWatchers.get(code); 606 if (cbs != null) { 607 if (repCbs == null) { 608 repCbs = new ArrayList<Callback>(); 609 } 610 repCbs.addAll(cbs); 611 } 612 cbs = mPackageModeWatchers.get(packageName); 613 if (cbs != null) { 614 if (repCbs == null) { 615 repCbs = new ArrayList<Callback>(); 616 } 617 repCbs.addAll(cbs); 618 } 619 if (mode == AppOpsManager.opToDefaultMode(op.op)) { 620 // If going into the default mode, prune this op 621 // if there is nothing else interesting in it. 622 pruneOp(op, uid, packageName); 623 } 624 scheduleFastWriteLocked(); 625 } 626 } 627 } 628 if (repCbs != null) { 629 // There are components watching for mode changes such as window manager 630 // and location manager which are in our process. The callbacks in these 631 // components may require permissions our remote caller does not have. 632 final long identity = Binder.clearCallingIdentity(); 633 try { 634 for (int i = 0; i < repCbs.size(); i++) { 635 try { 636 repCbs.get(i).mCallback.opChanged(code, uid, packageName); 637 } catch (RemoteException e) { 638 } 639 } 640 } finally { 641 Binder.restoreCallingIdentity(identity); 642 } 643 } 644 } 645 646 private static HashMap<Callback, ArrayList<ChangeRec>> addCallbacks( 647 HashMap<Callback, ArrayList<ChangeRec>> callbacks, 648 int op, int uid, String packageName, ArrayList<Callback> cbs) { 649 if (cbs == null) { 650 return callbacks; 651 } 652 if (callbacks == null) { 653 callbacks = new HashMap<>(); 654 } 655 boolean duplicate = false; 656 for (int i=0; i<cbs.size(); i++) { 657 Callback cb = cbs.get(i); 658 ArrayList<ChangeRec> reports = callbacks.get(cb); 659 if (reports == null) { 660 reports = new ArrayList<>(); 661 callbacks.put(cb, reports); 662 } else { 663 final int reportCount = reports.size(); 664 for (int j = 0; j < reportCount; j++) { 665 ChangeRec report = reports.get(j); 666 if (report.op == op && report.pkg.equals(packageName)) { 667 duplicate = true; 668 break; 669 } 670 } 671 } 672 if (!duplicate) { 673 reports.add(new ChangeRec(op, uid, packageName)); 674 } 675 } 676 return callbacks; 677 } 678 679 static final class ChangeRec { 680 final int op; 681 final int uid; 682 final String pkg; 683 684 ChangeRec(int _op, int _uid, String _pkg) { 685 op = _op; 686 uid = _uid; 687 pkg = _pkg; 688 } 689 } 690 691 @Override 692 public void resetAllModes(int reqUserId, String reqPackageName) { 693 final int callingPid = Binder.getCallingPid(); 694 final int callingUid = Binder.getCallingUid(); 695 mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 696 callingPid, callingUid, null); 697 reqUserId = ActivityManager.handleIncomingUser(callingPid, callingUid, reqUserId, 698 true, true, "resetAllModes", null); 699 700 int reqUid = -1; 701 if (reqPackageName != null) { 702 try { 703 reqUid = AppGlobals.getPackageManager().getPackageUid( 704 reqPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, reqUserId); 705 } catch (RemoteException e) { 706 /* ignore - local call */ 707 } 708 } 709 710 HashMap<Callback, ArrayList<ChangeRec>> callbacks = null; 711 synchronized (this) { 712 boolean changed = false; 713 for (int i = mUidStates.size() - 1; i >= 0; i--) { 714 UidState uidState = mUidStates.valueAt(i); 715 716 SparseIntArray opModes = uidState.opModes; 717 if (opModes != null && (uidState.uid == reqUid || reqUid == -1)) { 718 final int uidOpCount = opModes.size(); 719 for (int j = uidOpCount - 1; j >= 0; j--) { 720 final int code = opModes.keyAt(j); 721 if (AppOpsManager.opAllowsReset(code)) { 722 opModes.removeAt(j); 723 if (opModes.size() <= 0) { 724 uidState.opModes = null; 725 } 726 for (String packageName : getPackagesForUid(uidState.uid)) { 727 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName, 728 mOpModeWatchers.get(code)); 729 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName, 730 mPackageModeWatchers.get(packageName)); 731 } 732 } 733 } 734 } 735 736 if (uidState.pkgOps == null) { 737 continue; 738 } 739 740 if (reqUserId != UserHandle.USER_ALL 741 && reqUserId != UserHandle.getUserId(uidState.uid)) { 742 // Skip any ops for a different user 743 continue; 744 } 745 746 Map<String, Ops> packages = uidState.pkgOps; 747 Iterator<Map.Entry<String, Ops>> it = packages.entrySet().iterator(); 748 while (it.hasNext()) { 749 Map.Entry<String, Ops> ent = it.next(); 750 String packageName = ent.getKey(); 751 if (reqPackageName != null && !reqPackageName.equals(packageName)) { 752 // Skip any ops for a different package 753 continue; 754 } 755 Ops pkgOps = ent.getValue(); 756 for (int j=pkgOps.size()-1; j>=0; j--) { 757 Op curOp = pkgOps.valueAt(j); 758 if (AppOpsManager.opAllowsReset(curOp.op) 759 && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) { 760 curOp.mode = AppOpsManager.opToDefaultMode(curOp.op); 761 changed = true; 762 callbacks = addCallbacks(callbacks, curOp.op, curOp.uid, packageName, 763 mOpModeWatchers.get(curOp.op)); 764 callbacks = addCallbacks(callbacks, curOp.op, curOp.uid, packageName, 765 mPackageModeWatchers.get(packageName)); 766 if (curOp.time == 0 && curOp.rejectTime == 0) { 767 pkgOps.removeAt(j); 768 } 769 } 770 } 771 if (pkgOps.size() == 0) { 772 it.remove(); 773 } 774 } 775 if (uidState.isDefault()) { 776 mUidStates.remove(uidState.uid); 777 } 778 } 779 780 if (changed) { 781 scheduleFastWriteLocked(); 782 } 783 } 784 if (callbacks != null) { 785 for (Map.Entry<Callback, ArrayList<ChangeRec>> ent : callbacks.entrySet()) { 786 Callback cb = ent.getKey(); 787 ArrayList<ChangeRec> reports = ent.getValue(); 788 for (int i=0; i<reports.size(); i++) { 789 ChangeRec rep = reports.get(i); 790 try { 791 cb.mCallback.opChanged(rep.op, rep.uid, rep.pkg); 792 } catch (RemoteException e) { 793 } 794 } 795 } 796 } 797 } 798 799 @Override 800 public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) { 801 if (callback == null) { 802 return; 803 } 804 synchronized (this) { 805 op = (op != AppOpsManager.OP_NONE) ? AppOpsManager.opToSwitch(op) : op; 806 Callback cb = mModeWatchers.get(callback.asBinder()); 807 if (cb == null) { 808 cb = new Callback(callback); 809 mModeWatchers.put(callback.asBinder(), cb); 810 } 811 if (op != AppOpsManager.OP_NONE) { 812 ArrayList<Callback> cbs = mOpModeWatchers.get(op); 813 if (cbs == null) { 814 cbs = new ArrayList<Callback>(); 815 mOpModeWatchers.put(op, cbs); 816 } 817 cbs.add(cb); 818 } 819 if (packageName != null) { 820 ArrayList<Callback> cbs = mPackageModeWatchers.get(packageName); 821 if (cbs == null) { 822 cbs = new ArrayList<Callback>(); 823 mPackageModeWatchers.put(packageName, cbs); 824 } 825 cbs.add(cb); 826 } 827 } 828 } 829 830 @Override 831 public void stopWatchingMode(IAppOpsCallback callback) { 832 if (callback == null) { 833 return; 834 } 835 synchronized (this) { 836 Callback cb = mModeWatchers.remove(callback.asBinder()); 837 if (cb != null) { 838 cb.unlinkToDeath(); 839 for (int i=mOpModeWatchers.size()-1; i>=0; i--) { 840 ArrayList<Callback> cbs = mOpModeWatchers.valueAt(i); 841 cbs.remove(cb); 842 if (cbs.size() <= 0) { 843 mOpModeWatchers.removeAt(i); 844 } 845 } 846 for (int i=mPackageModeWatchers.size()-1; i>=0; i--) { 847 ArrayList<Callback> cbs = mPackageModeWatchers.valueAt(i); 848 cbs.remove(cb); 849 if (cbs.size() <= 0) { 850 mPackageModeWatchers.removeAt(i); 851 } 852 } 853 } 854 } 855 } 856 857 @Override 858 public IBinder getToken(IBinder clientToken) { 859 synchronized (this) { 860 ClientState cs = mClients.get(clientToken); 861 if (cs == null) { 862 cs = new ClientState(clientToken); 863 mClients.put(clientToken, cs); 864 } 865 return cs; 866 } 867 } 868 869 @Override 870 public int checkOperation(int code, int uid, String packageName) { 871 verifyIncomingUid(uid); 872 verifyIncomingOp(code); 873 String resolvedPackageName = resolvePackageName(uid, packageName); 874 if (resolvedPackageName == null) { 875 return AppOpsManager.MODE_IGNORED; 876 } 877 synchronized (this) { 878 if (isOpRestricted(uid, code, resolvedPackageName)) { 879 return AppOpsManager.MODE_IGNORED; 880 } 881 code = AppOpsManager.opToSwitch(code); 882 UidState uidState = getUidStateLocked(uid, false); 883 if (uidState != null && uidState.opModes != null) { 884 final int uidMode = uidState.opModes.get(code); 885 if (uidMode != AppOpsManager.MODE_ALLOWED) { 886 return uidMode; 887 } 888 } 889 Op op = getOpLocked(code, uid, resolvedPackageName, false); 890 if (op == null) { 891 return AppOpsManager.opToDefaultMode(code); 892 } 893 return op.mode; 894 } 895 } 896 897 @Override 898 public int checkAudioOperation(int code, int usage, int uid, String packageName) { 899 boolean suspended; 900 try { 901 suspended = isPackageSuspendedForUser(packageName, uid); 902 } catch (IllegalArgumentException ex) { 903 // Package not found. 904 suspended = false; 905 } 906 907 if (suspended) { 908 Log.i(TAG, "Audio disabled for suspended package=" + packageName + " for uid=" + uid); 909 return AppOpsManager.MODE_IGNORED; 910 } 911 912 synchronized (this) { 913 final int mode = checkRestrictionLocked(code, usage, uid, packageName); 914 if (mode != AppOpsManager.MODE_ALLOWED) { 915 return mode; 916 } 917 } 918 return checkOperation(code, uid, packageName); 919 } 920 921 private boolean isPackageSuspendedForUser(String pkg, int uid) { 922 try { 923 return AppGlobals.getPackageManager().isPackageSuspendedForUser( 924 pkg, UserHandle.getUserId(uid)); 925 } catch (RemoteException re) { 926 throw new SecurityException("Could not talk to package manager service"); 927 } 928 } 929 930 private int checkRestrictionLocked(int code, int usage, int uid, String packageName) { 931 final SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code); 932 if (usageRestrictions != null) { 933 final Restriction r = usageRestrictions.get(usage); 934 if (r != null && !r.exceptionPackages.contains(packageName)) { 935 return r.mode; 936 } 937 } 938 return AppOpsManager.MODE_ALLOWED; 939 } 940 941 @Override 942 public void setAudioRestriction(int code, int usage, int uid, int mode, 943 String[] exceptionPackages) { 944 verifyIncomingUid(uid); 945 verifyIncomingOp(code); 946 synchronized (this) { 947 SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code); 948 if (usageRestrictions == null) { 949 usageRestrictions = new SparseArray<Restriction>(); 950 mAudioRestrictions.put(code, usageRestrictions); 951 } 952 usageRestrictions.remove(usage); 953 if (mode != AppOpsManager.MODE_ALLOWED) { 954 final Restriction r = new Restriction(); 955 r.mode = mode; 956 if (exceptionPackages != null) { 957 final int N = exceptionPackages.length; 958 r.exceptionPackages = new ArraySet<String>(N); 959 for (int i = 0; i < N; i++) { 960 final String pkg = exceptionPackages[i]; 961 if (pkg != null) { 962 r.exceptionPackages.add(pkg.trim()); 963 } 964 } 965 } 966 usageRestrictions.put(usage, r); 967 } 968 } 969 notifyWatchersOfChange(code); 970 } 971 972 @Override 973 public int checkPackage(int uid, String packageName) { 974 Preconditions.checkNotNull(packageName); 975 synchronized (this) { 976 if (getOpsRawLocked(uid, packageName, true) != null) { 977 return AppOpsManager.MODE_ALLOWED; 978 } else { 979 return AppOpsManager.MODE_ERRORED; 980 } 981 } 982 } 983 984 @Override 985 public int noteProxyOperation(int code, String proxyPackageName, 986 int proxiedUid, String proxiedPackageName) { 987 verifyIncomingOp(code); 988 final int proxyUid = Binder.getCallingUid(); 989 String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName); 990 if (resolveProxyPackageName == null) { 991 return AppOpsManager.MODE_IGNORED; 992 } 993 final int proxyMode = noteOperationUnchecked(code, proxyUid, 994 resolveProxyPackageName, -1, null); 995 if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) { 996 return proxyMode; 997 } 998 String resolveProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName); 999 if (resolveProxiedPackageName == null) { 1000 return AppOpsManager.MODE_IGNORED; 1001 } 1002 return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName, 1003 proxyMode, resolveProxyPackageName); 1004 } 1005 1006 @Override 1007 public int noteOperation(int code, int uid, String packageName) { 1008 verifyIncomingUid(uid); 1009 verifyIncomingOp(code); 1010 String resolvedPackageName = resolvePackageName(uid, packageName); 1011 if (resolvedPackageName == null) { 1012 return AppOpsManager.MODE_IGNORED; 1013 } 1014 return noteOperationUnchecked(code, uid, resolvedPackageName, 0, null); 1015 } 1016 1017 private int noteOperationUnchecked(int code, int uid, String packageName, 1018 int proxyUid, String proxyPackageName) { 1019 synchronized (this) { 1020 Ops ops = getOpsRawLocked(uid, packageName, true); 1021 if (ops == null) { 1022 if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid 1023 + " package " + packageName); 1024 return AppOpsManager.MODE_ERRORED; 1025 } 1026 Op op = getOpLocked(ops, code, true); 1027 if (isOpRestricted(uid, code, packageName)) { 1028 return AppOpsManager.MODE_IGNORED; 1029 } 1030 if (op.duration == -1) { 1031 Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName 1032 + " code " + code + " time=" + op.time + " duration=" + op.duration); 1033 } 1034 op.duration = 0; 1035 final int switchCode = AppOpsManager.opToSwitch(code); 1036 UidState uidState = ops.uidState; 1037 // If there is a non-default per UID policy (we set UID op mode only if 1038 // non-default) it takes over, otherwise use the per package policy. 1039 if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) { 1040 final int uidMode = uidState.opModes.get(switchCode); 1041 if (uidMode != AppOpsManager.MODE_ALLOWED) { 1042 if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code " 1043 + switchCode + " (" + code + ") uid " + uid + " package " 1044 + packageName); 1045 op.rejectTime = System.currentTimeMillis(); 1046 return uidMode; 1047 } 1048 } else { 1049 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op; 1050 if (switchOp.mode != AppOpsManager.MODE_ALLOWED) { 1051 if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code " 1052 + switchCode + " (" + code + ") uid " + uid + " package " 1053 + packageName); 1054 op.rejectTime = System.currentTimeMillis(); 1055 return switchOp.mode; 1056 } 1057 } 1058 if (DEBUG) Log.d(TAG, "noteOperation: allowing code " + code + " uid " + uid 1059 + " package " + packageName); 1060 op.time = System.currentTimeMillis(); 1061 op.rejectTime = 0; 1062 op.proxyUid = proxyUid; 1063 op.proxyPackageName = proxyPackageName; 1064 return AppOpsManager.MODE_ALLOWED; 1065 } 1066 } 1067 1068 @Override 1069 public int startOperation(IBinder token, int code, int uid, String packageName) { 1070 verifyIncomingUid(uid); 1071 verifyIncomingOp(code); 1072 String resolvedPackageName = resolvePackageName(uid, packageName); 1073 if (resolvedPackageName == null) { 1074 return AppOpsManager.MODE_IGNORED; 1075 } 1076 ClientState client = (ClientState)token; 1077 synchronized (this) { 1078 Ops ops = getOpsRawLocked(uid, resolvedPackageName, true); 1079 if (ops == null) { 1080 if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid 1081 + " package " + resolvedPackageName); 1082 return AppOpsManager.MODE_ERRORED; 1083 } 1084 Op op = getOpLocked(ops, code, true); 1085 if (isOpRestricted(uid, code, resolvedPackageName)) { 1086 return AppOpsManager.MODE_IGNORED; 1087 } 1088 final int switchCode = AppOpsManager.opToSwitch(code); 1089 UidState uidState = ops.uidState; 1090 if (uidState.opModes != null) { 1091 final int uidMode = uidState.opModes.get(switchCode); 1092 if (uidMode != AppOpsManager.MODE_ALLOWED) { 1093 if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code " 1094 + switchCode + " (" + code + ") uid " + uid + " package " 1095 + resolvedPackageName); 1096 op.rejectTime = System.currentTimeMillis(); 1097 return uidMode; 1098 } 1099 } 1100 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op; 1101 if (switchOp.mode != AppOpsManager.MODE_ALLOWED) { 1102 if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code " 1103 + switchCode + " (" + code + ") uid " + uid + " package " 1104 + resolvedPackageName); 1105 op.rejectTime = System.currentTimeMillis(); 1106 return switchOp.mode; 1107 } 1108 if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid 1109 + " package " + resolvedPackageName); 1110 if (op.nesting == 0) { 1111 op.time = System.currentTimeMillis(); 1112 op.rejectTime = 0; 1113 op.duration = -1; 1114 } 1115 op.nesting++; 1116 if (client.mStartedOps != null) { 1117 client.mStartedOps.add(op); 1118 } 1119 return AppOpsManager.MODE_ALLOWED; 1120 } 1121 } 1122 1123 @Override 1124 public void finishOperation(IBinder token, int code, int uid, String packageName) { 1125 verifyIncomingUid(uid); 1126 verifyIncomingOp(code); 1127 String resolvedPackageName = resolvePackageName(uid, packageName); 1128 if (resolvedPackageName == null) { 1129 return; 1130 } 1131 if (!(token instanceof ClientState)) { 1132 return; 1133 } 1134 ClientState client = (ClientState) token; 1135 synchronized (this) { 1136 Op op = getOpLocked(code, uid, resolvedPackageName, true); 1137 if (op == null) { 1138 return; 1139 } 1140 if (client.mStartedOps != null) { 1141 if (!client.mStartedOps.remove(op)) { 1142 throw new IllegalStateException("Operation not started: uid" + op.uid 1143 + " pkg=" + op.packageName + " op=" + op.op); 1144 } 1145 } 1146 finishOperationLocked(op); 1147 } 1148 } 1149 1150 @Override 1151 public int permissionToOpCode(String permission) { 1152 if (permission == null) { 1153 return AppOpsManager.OP_NONE; 1154 } 1155 return AppOpsManager.permissionToOpCode(permission); 1156 } 1157 1158 void finishOperationLocked(Op op) { 1159 if (op.nesting <= 1) { 1160 if (op.nesting == 1) { 1161 op.duration = (int)(System.currentTimeMillis() - op.time); 1162 op.time += op.duration; 1163 } else { 1164 Slog.w(TAG, "Finishing op nesting under-run: uid " + op.uid + " pkg " 1165 + op.packageName + " code " + op.op + " time=" + op.time 1166 + " duration=" + op.duration + " nesting=" + op.nesting); 1167 } 1168 op.nesting = 0; 1169 } else { 1170 op.nesting--; 1171 } 1172 } 1173 1174 private void verifyIncomingUid(int uid) { 1175 if (uid == Binder.getCallingUid()) { 1176 return; 1177 } 1178 if (Binder.getCallingPid() == Process.myPid()) { 1179 return; 1180 } 1181 mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 1182 Binder.getCallingPid(), Binder.getCallingUid(), null); 1183 } 1184 1185 private void verifyIncomingOp(int op) { 1186 if (op >= 0 && op < AppOpsManager._NUM_OP) { 1187 return; 1188 } 1189 throw new IllegalArgumentException("Bad operation #" + op); 1190 } 1191 1192 private UidState getUidStateLocked(int uid, boolean edit) { 1193 UidState uidState = mUidStates.get(uid); 1194 if (uidState == null) { 1195 if (!edit) { 1196 return null; 1197 } 1198 uidState = new UidState(uid); 1199 mUidStates.put(uid, uidState); 1200 } 1201 return uidState; 1202 } 1203 1204 private Ops getOpsRawLocked(int uid, String packageName, boolean edit) { 1205 UidState uidState = getUidStateLocked(uid, edit); 1206 if (uidState == null) { 1207 return null; 1208 } 1209 1210 if (uidState.pkgOps == null) { 1211 if (!edit) { 1212 return null; 1213 } 1214 uidState.pkgOps = new ArrayMap<>(); 1215 } 1216 1217 Ops ops = uidState.pkgOps.get(packageName); 1218 if (ops == null) { 1219 if (!edit) { 1220 return null; 1221 } 1222 boolean isPrivileged = false; 1223 // This is the first time we have seen this package name under this uid, 1224 // so let's make sure it is valid. 1225 if (uid != 0) { 1226 final long ident = Binder.clearCallingIdentity(); 1227 try { 1228 int pkgUid = -1; 1229 try { 1230 ApplicationInfo appInfo = ActivityThread.getPackageManager() 1231 .getApplicationInfo(packageName, 1232 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, 1233 UserHandle.getUserId(uid)); 1234 if (appInfo != null) { 1235 pkgUid = appInfo.uid; 1236 isPrivileged = (appInfo.privateFlags 1237 & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; 1238 } else { 1239 if ("media".equals(packageName)) { 1240 pkgUid = Process.MEDIA_UID; 1241 isPrivileged = false; 1242 } else if ("audioserver".equals(packageName)) { 1243 pkgUid = Process.AUDIOSERVER_UID; 1244 isPrivileged = false; 1245 } else if ("cameraserver".equals(packageName)) { 1246 pkgUid = Process.CAMERASERVER_UID; 1247 isPrivileged = false; 1248 } 1249 } 1250 } catch (RemoteException e) { 1251 Slog.w(TAG, "Could not contact PackageManager", e); 1252 } 1253 if (pkgUid != uid) { 1254 // Oops! The package name is not valid for the uid they are calling 1255 // under. Abort. 1256 RuntimeException ex = new RuntimeException("here"); 1257 ex.fillInStackTrace(); 1258 Slog.w(TAG, "Bad call: specified package " + packageName 1259 + " under uid " + uid + " but it is really " + pkgUid, ex); 1260 return null; 1261 } 1262 } finally { 1263 Binder.restoreCallingIdentity(ident); 1264 } 1265 } 1266 ops = new Ops(packageName, uidState, isPrivileged); 1267 uidState.pkgOps.put(packageName, ops); 1268 } 1269 return ops; 1270 } 1271 1272 private void scheduleWriteLocked() { 1273 if (!mWriteScheduled) { 1274 mWriteScheduled = true; 1275 mHandler.postDelayed(mWriteRunner, WRITE_DELAY); 1276 } 1277 } 1278 1279 private void scheduleFastWriteLocked() { 1280 if (!mFastWriteScheduled) { 1281 mWriteScheduled = true; 1282 mFastWriteScheduled = true; 1283 mHandler.removeCallbacks(mWriteRunner); 1284 mHandler.postDelayed(mWriteRunner, 10*1000); 1285 } 1286 } 1287 1288 private Op getOpLocked(int code, int uid, String packageName, boolean edit) { 1289 Ops ops = getOpsRawLocked(uid, packageName, edit); 1290 if (ops == null) { 1291 return null; 1292 } 1293 return getOpLocked(ops, code, edit); 1294 } 1295 1296 private Op getOpLocked(Ops ops, int code, boolean edit) { 1297 Op op = ops.get(code); 1298 if (op == null) { 1299 if (!edit) { 1300 return null; 1301 } 1302 op = new Op(ops.uidState.uid, ops.packageName, code); 1303 ops.put(code, op); 1304 } 1305 if (edit) { 1306 scheduleWriteLocked(); 1307 } 1308 return op; 1309 } 1310 1311 private boolean isOpRestricted(int uid, int code, String packageName) { 1312 int userHandle = UserHandle.getUserId(uid); 1313 final int restrictionSetCount = mOpUserRestrictions.size(); 1314 1315 for (int i = 0; i < restrictionSetCount; i++) { 1316 // For each client, check that the given op is not restricted, or that the given 1317 // package is exempt from the restriction. 1318 ClientRestrictionState restrictionState = mOpUserRestrictions.valueAt(i); 1319 if (restrictionState.hasRestriction(code, packageName, userHandle)) { 1320 if (AppOpsManager.opAllowSystemBypassRestriction(code)) { 1321 // If we are the system, bypass user restrictions for certain codes 1322 synchronized (this) { 1323 Ops ops = getOpsRawLocked(uid, packageName, true); 1324 if ((ops != null) && ops.isPrivileged) { 1325 return false; 1326 } 1327 } 1328 } 1329 return true; 1330 } 1331 } 1332 return false; 1333 } 1334 1335 void readState() { 1336 synchronized (mFile) { 1337 synchronized (this) { 1338 FileInputStream stream; 1339 try { 1340 stream = mFile.openRead(); 1341 } catch (FileNotFoundException e) { 1342 Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty"); 1343 return; 1344 } 1345 boolean success = false; 1346 mUidStates.clear(); 1347 try { 1348 XmlPullParser parser = Xml.newPullParser(); 1349 parser.setInput(stream, StandardCharsets.UTF_8.name()); 1350 int type; 1351 while ((type = parser.next()) != XmlPullParser.START_TAG 1352 && type != XmlPullParser.END_DOCUMENT) { 1353 ; 1354 } 1355 1356 if (type != XmlPullParser.START_TAG) { 1357 throw new IllegalStateException("no start tag found"); 1358 } 1359 1360 int outerDepth = parser.getDepth(); 1361 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 1362 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 1363 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 1364 continue; 1365 } 1366 1367 String tagName = parser.getName(); 1368 if (tagName.equals("pkg")) { 1369 readPackage(parser); 1370 } else if (tagName.equals("uid")) { 1371 readUidOps(parser); 1372 } else { 1373 Slog.w(TAG, "Unknown element under <app-ops>: " 1374 + parser.getName()); 1375 XmlUtils.skipCurrentTag(parser); 1376 } 1377 } 1378 success = true; 1379 } catch (IllegalStateException e) { 1380 Slog.w(TAG, "Failed parsing " + e); 1381 } catch (NullPointerException e) { 1382 Slog.w(TAG, "Failed parsing " + e); 1383 } catch (NumberFormatException e) { 1384 Slog.w(TAG, "Failed parsing " + e); 1385 } catch (XmlPullParserException e) { 1386 Slog.w(TAG, "Failed parsing " + e); 1387 } catch (IOException e) { 1388 Slog.w(TAG, "Failed parsing " + e); 1389 } catch (IndexOutOfBoundsException e) { 1390 Slog.w(TAG, "Failed parsing " + e); 1391 } finally { 1392 if (!success) { 1393 mUidStates.clear(); 1394 } 1395 try { 1396 stream.close(); 1397 } catch (IOException e) { 1398 } 1399 } 1400 } 1401 } 1402 } 1403 1404 void readUidOps(XmlPullParser parser) throws NumberFormatException, 1405 XmlPullParserException, IOException { 1406 final int uid = Integer.parseInt(parser.getAttributeValue(null, "n")); 1407 int outerDepth = parser.getDepth(); 1408 int type; 1409 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 1410 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 1411 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 1412 continue; 1413 } 1414 1415 String tagName = parser.getName(); 1416 if (tagName.equals("op")) { 1417 final int code = Integer.parseInt(parser.getAttributeValue(null, "n")); 1418 final int mode = Integer.parseInt(parser.getAttributeValue(null, "m")); 1419 UidState uidState = getUidStateLocked(uid, true); 1420 if (uidState.opModes == null) { 1421 uidState.opModes = new SparseIntArray(); 1422 } 1423 uidState.opModes.put(code, mode); 1424 } else { 1425 Slog.w(TAG, "Unknown element under <uid-ops>: " 1426 + parser.getName()); 1427 XmlUtils.skipCurrentTag(parser); 1428 } 1429 } 1430 } 1431 1432 void readPackage(XmlPullParser parser) throws NumberFormatException, 1433 XmlPullParserException, IOException { 1434 String pkgName = parser.getAttributeValue(null, "n"); 1435 int outerDepth = parser.getDepth(); 1436 int type; 1437 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 1438 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 1439 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 1440 continue; 1441 } 1442 1443 String tagName = parser.getName(); 1444 if (tagName.equals("uid")) { 1445 readUid(parser, pkgName); 1446 } else { 1447 Slog.w(TAG, "Unknown element under <pkg>: " 1448 + parser.getName()); 1449 XmlUtils.skipCurrentTag(parser); 1450 } 1451 } 1452 } 1453 1454 void readUid(XmlPullParser parser, String pkgName) throws NumberFormatException, 1455 XmlPullParserException, IOException { 1456 int uid = Integer.parseInt(parser.getAttributeValue(null, "n")); 1457 String isPrivilegedString = parser.getAttributeValue(null, "p"); 1458 boolean isPrivileged = false; 1459 if (isPrivilegedString == null) { 1460 try { 1461 IPackageManager packageManager = ActivityThread.getPackageManager(); 1462 if (packageManager != null) { 1463 ApplicationInfo appInfo = ActivityThread.getPackageManager() 1464 .getApplicationInfo(pkgName, 0, UserHandle.getUserId(uid)); 1465 if (appInfo != null) { 1466 isPrivileged = (appInfo.privateFlags 1467 & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; 1468 } 1469 } else { 1470 // Could not load data, don't add to cache so it will be loaded later. 1471 return; 1472 } 1473 } catch (RemoteException e) { 1474 Slog.w(TAG, "Could not contact PackageManager", e); 1475 } 1476 } else { 1477 isPrivileged = Boolean.parseBoolean(isPrivilegedString); 1478 } 1479 int outerDepth = parser.getDepth(); 1480 int type; 1481 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 1482 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 1483 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 1484 continue; 1485 } 1486 1487 String tagName = parser.getName(); 1488 if (tagName.equals("op")) { 1489 Op op = new Op(uid, pkgName, Integer.parseInt(parser.getAttributeValue(null, "n"))); 1490 String mode = parser.getAttributeValue(null, "m"); 1491 if (mode != null) { 1492 op.mode = Integer.parseInt(mode); 1493 } 1494 String time = parser.getAttributeValue(null, "t"); 1495 if (time != null) { 1496 op.time = Long.parseLong(time); 1497 } 1498 time = parser.getAttributeValue(null, "r"); 1499 if (time != null) { 1500 op.rejectTime = Long.parseLong(time); 1501 } 1502 String dur = parser.getAttributeValue(null, "d"); 1503 if (dur != null) { 1504 op.duration = Integer.parseInt(dur); 1505 } 1506 String proxyUid = parser.getAttributeValue(null, "pu"); 1507 if (proxyUid != null) { 1508 op.proxyUid = Integer.parseInt(proxyUid); 1509 } 1510 String proxyPackageName = parser.getAttributeValue(null, "pp"); 1511 if (proxyPackageName != null) { 1512 op.proxyPackageName = proxyPackageName; 1513 } 1514 1515 UidState uidState = getUidStateLocked(uid, true); 1516 if (uidState.pkgOps == null) { 1517 uidState.pkgOps = new ArrayMap<>(); 1518 } 1519 1520 Ops ops = uidState.pkgOps.get(pkgName); 1521 if (ops == null) { 1522 ops = new Ops(pkgName, uidState, isPrivileged); 1523 uidState.pkgOps.put(pkgName, ops); 1524 } 1525 ops.put(op.op, op); 1526 } else { 1527 Slog.w(TAG, "Unknown element under <pkg>: " 1528 + parser.getName()); 1529 XmlUtils.skipCurrentTag(parser); 1530 } 1531 } 1532 } 1533 1534 void writeState() { 1535 synchronized (mFile) { 1536 List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null); 1537 1538 FileOutputStream stream; 1539 try { 1540 stream = mFile.startWrite(); 1541 } catch (IOException e) { 1542 Slog.w(TAG, "Failed to write state: " + e); 1543 return; 1544 } 1545 1546 try { 1547 XmlSerializer out = new FastXmlSerializer(); 1548 out.setOutput(stream, StandardCharsets.UTF_8.name()); 1549 out.startDocument(null, true); 1550 out.startTag(null, "app-ops"); 1551 1552 final int uidStateCount = mUidStates.size(); 1553 for (int i = 0; i < uidStateCount; i++) { 1554 UidState uidState = mUidStates.valueAt(i); 1555 if (uidState.opModes != null && uidState.opModes.size() > 0) { 1556 out.startTag(null, "uid"); 1557 out.attribute(null, "n", Integer.toString(uidState.uid)); 1558 SparseIntArray uidOpModes = uidState.opModes; 1559 final int opCount = uidOpModes.size(); 1560 for (int j = 0; j < opCount; j++) { 1561 final int op = uidOpModes.keyAt(j); 1562 final int mode = uidOpModes.valueAt(j); 1563 out.startTag(null, "op"); 1564 out.attribute(null, "n", Integer.toString(op)); 1565 out.attribute(null, "m", Integer.toString(mode)); 1566 out.endTag(null, "op"); 1567 } 1568 out.endTag(null, "uid"); 1569 } 1570 } 1571 1572 if (allOps != null) { 1573 String lastPkg = null; 1574 for (int i=0; i<allOps.size(); i++) { 1575 AppOpsManager.PackageOps pkg = allOps.get(i); 1576 if (!pkg.getPackageName().equals(lastPkg)) { 1577 if (lastPkg != null) { 1578 out.endTag(null, "pkg"); 1579 } 1580 lastPkg = pkg.getPackageName(); 1581 out.startTag(null, "pkg"); 1582 out.attribute(null, "n", lastPkg); 1583 } 1584 out.startTag(null, "uid"); 1585 out.attribute(null, "n", Integer.toString(pkg.getUid())); 1586 synchronized (this) { 1587 Ops ops = getOpsRawLocked(pkg.getUid(), pkg.getPackageName(), false); 1588 // Should always be present as the list of PackageOps is generated 1589 // from Ops. 1590 if (ops != null) { 1591 out.attribute(null, "p", Boolean.toString(ops.isPrivileged)); 1592 } else { 1593 out.attribute(null, "p", Boolean.toString(false)); 1594 } 1595 } 1596 List<AppOpsManager.OpEntry> ops = pkg.getOps(); 1597 for (int j=0; j<ops.size(); j++) { 1598 AppOpsManager.OpEntry op = ops.get(j); 1599 out.startTag(null, "op"); 1600 out.attribute(null, "n", Integer.toString(op.getOp())); 1601 if (op.getMode() != AppOpsManager.opToDefaultMode(op.getOp())) { 1602 out.attribute(null, "m", Integer.toString(op.getMode())); 1603 } 1604 long time = op.getTime(); 1605 if (time != 0) { 1606 out.attribute(null, "t", Long.toString(time)); 1607 } 1608 time = op.getRejectTime(); 1609 if (time != 0) { 1610 out.attribute(null, "r", Long.toString(time)); 1611 } 1612 int dur = op.getDuration(); 1613 if (dur != 0) { 1614 out.attribute(null, "d", Integer.toString(dur)); 1615 } 1616 int proxyUid = op.getProxyUid(); 1617 if (proxyUid != -1) { 1618 out.attribute(null, "pu", Integer.toString(proxyUid)); 1619 } 1620 String proxyPackageName = op.getProxyPackageName(); 1621 if (proxyPackageName != null) { 1622 out.attribute(null, "pp", proxyPackageName); 1623 } 1624 out.endTag(null, "op"); 1625 } 1626 out.endTag(null, "uid"); 1627 } 1628 if (lastPkg != null) { 1629 out.endTag(null, "pkg"); 1630 } 1631 } 1632 1633 out.endTag(null, "app-ops"); 1634 out.endDocument(); 1635 mFile.finishWrite(stream); 1636 } catch (IOException e) { 1637 Slog.w(TAG, "Failed to write state, restoring backup.", e); 1638 mFile.failWrite(stream); 1639 } 1640 } 1641 } 1642 1643 static class Shell extends ShellCommand { 1644 final IAppOpsService mInterface; 1645 final AppOpsService mInternal; 1646 1647 int userId = UserHandle.USER_SYSTEM; 1648 String packageName; 1649 String opStr; 1650 String modeStr; 1651 int op; 1652 int mode; 1653 int packageUid; 1654 1655 Shell(IAppOpsService iface, AppOpsService internal) { 1656 mInterface = iface; 1657 mInternal = internal; 1658 } 1659 1660 @Override 1661 public int onCommand(String cmd) { 1662 return onShellCommand(this, cmd); 1663 } 1664 1665 @Override 1666 public void onHelp() { 1667 PrintWriter pw = getOutPrintWriter(); 1668 dumpCommandHelp(pw); 1669 } 1670 1671 private int strOpToOp(String op, PrintWriter err) { 1672 try { 1673 return AppOpsManager.strOpToOp(op); 1674 } catch (IllegalArgumentException e) { 1675 } 1676 try { 1677 return Integer.parseInt(op); 1678 } catch (NumberFormatException e) { 1679 } 1680 try { 1681 return AppOpsManager.strDebugOpToOp(op); 1682 } catch (IllegalArgumentException e) { 1683 err.println("Error: " + e.getMessage()); 1684 return -1; 1685 } 1686 } 1687 1688 int strModeToMode(String modeStr, PrintWriter err) { 1689 switch (modeStr) { 1690 case "allow": 1691 return AppOpsManager.MODE_ALLOWED; 1692 case "deny": 1693 return AppOpsManager.MODE_ERRORED; 1694 case "ignore": 1695 return AppOpsManager.MODE_IGNORED; 1696 case "default": 1697 return AppOpsManager.MODE_DEFAULT; 1698 } 1699 try { 1700 return Integer.parseInt(modeStr); 1701 } catch (NumberFormatException e) { 1702 } 1703 err.println("Error: Mode " + modeStr + " is not valid"); 1704 return -1; 1705 } 1706 1707 int parseUserOpMode(int defMode, PrintWriter err) throws RemoteException { 1708 userId = UserHandle.USER_CURRENT; 1709 opStr = null; 1710 modeStr = null; 1711 for (String argument; (argument = getNextArg()) != null;) { 1712 if ("--user".equals(argument)) { 1713 userId = UserHandle.parseUserArg(getNextArgRequired()); 1714 } else { 1715 if (opStr == null) { 1716 opStr = argument; 1717 } else if (modeStr == null) { 1718 modeStr = argument; 1719 break; 1720 } 1721 } 1722 } 1723 if (opStr == null) { 1724 err.println("Error: Operation not specified."); 1725 return -1; 1726 } 1727 op = strOpToOp(opStr, err); 1728 if (op < 0) { 1729 return -1; 1730 } 1731 if (modeStr != null) { 1732 if ((mode=strModeToMode(modeStr, err)) < 0) { 1733 return -1; 1734 } 1735 } else { 1736 mode = defMode; 1737 } 1738 return 0; 1739 } 1740 1741 int parseUserPackageOp(boolean reqOp, PrintWriter err) throws RemoteException { 1742 userId = UserHandle.USER_CURRENT; 1743 packageName = null; 1744 opStr = null; 1745 for (String argument; (argument = getNextArg()) != null;) { 1746 if ("--user".equals(argument)) { 1747 userId = UserHandle.parseUserArg(getNextArgRequired()); 1748 } else { 1749 if (packageName == null) { 1750 packageName = argument; 1751 } else if (opStr == null) { 1752 opStr = argument; 1753 break; 1754 } 1755 } 1756 } 1757 if (packageName == null) { 1758 err.println("Error: Package name not specified."); 1759 return -1; 1760 } else if (opStr == null && reqOp) { 1761 err.println("Error: Operation not specified."); 1762 return -1; 1763 } 1764 if (opStr != null) { 1765 op = strOpToOp(opStr, err); 1766 if (op < 0) { 1767 return -1; 1768 } 1769 } else { 1770 op = AppOpsManager.OP_NONE; 1771 } 1772 if (userId == UserHandle.USER_CURRENT) { 1773 userId = ActivityManager.getCurrentUser(); 1774 } 1775 if ("root".equals(packageName)) { 1776 packageUid = 0; 1777 } else { 1778 packageUid = AppGlobals.getPackageManager().getPackageUid(packageName, 1779 PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); 1780 } 1781 if (packageUid < 0) { 1782 err.println("Error: No UID for " + packageName + " in user " + userId); 1783 return -1; 1784 } 1785 return 0; 1786 } 1787 } 1788 1789 @Override public void onShellCommand(FileDescriptor in, FileDescriptor out, 1790 FileDescriptor err, String[] args, ResultReceiver resultReceiver) { 1791 (new Shell(this, this)).exec(this, in, out, err, args, resultReceiver); 1792 } 1793 1794 static void dumpCommandHelp(PrintWriter pw) { 1795 pw.println("AppOps service (appops) commands:"); 1796 pw.println(" help"); 1797 pw.println(" Print this help text."); 1798 pw.println(" set [--user <USER_ID>] <PACKAGE> <OP> <MODE>"); 1799 pw.println(" Set the mode for a particular application and operation."); 1800 pw.println(" get [--user <USER_ID>] <PACKAGE> [<OP>]"); 1801 pw.println(" Return the mode for a particular application and optional operation."); 1802 pw.println(" query-op [--user <USER_ID>] <OP> [<MODE>]"); 1803 pw.println(" Print all packages that currently have the given op in the given mode."); 1804 pw.println(" reset [--user <USER_ID>] [<PACKAGE>]"); 1805 pw.println(" Reset the given application or all applications to default modes."); 1806 pw.println(" write-settings"); 1807 pw.println(" Immediately write pending changes to storage."); 1808 pw.println(" read-settings"); 1809 pw.println(" Read the last written settings, replacing current state in RAM."); 1810 pw.println(" options:"); 1811 pw.println(" <PACKAGE> an Android package name."); 1812 pw.println(" <OP> an AppOps operation."); 1813 pw.println(" <MODE> one of allow, ignore, deny, or default"); 1814 pw.println(" <USER_ID> the user id under which the package is installed. If --user is not"); 1815 pw.println(" specified, the current user is assumed."); 1816 } 1817 1818 static int onShellCommand(Shell shell, String cmd) { 1819 if (cmd == null) { 1820 return shell.handleDefaultCommands(cmd); 1821 } 1822 PrintWriter pw = shell.getOutPrintWriter(); 1823 PrintWriter err = shell.getErrPrintWriter(); 1824 try { 1825 switch (cmd) { 1826 case "set": { 1827 int res = shell.parseUserPackageOp(true, err); 1828 if (res < 0) { 1829 return res; 1830 } 1831 String modeStr = shell.getNextArg(); 1832 if (modeStr == null) { 1833 err.println("Error: Mode not specified."); 1834 return -1; 1835 } 1836 1837 final int mode = shell.strModeToMode(modeStr, err); 1838 if (mode < 0) { 1839 return -1; 1840 } 1841 1842 shell.mInterface.setMode(shell.op, shell.packageUid, shell.packageName, mode); 1843 return 0; 1844 } 1845 case "get": { 1846 int res = shell.parseUserPackageOp(false, err); 1847 if (res < 0) { 1848 return res; 1849 } 1850 1851 List<AppOpsManager.PackageOps> ops = shell.mInterface.getOpsForPackage( 1852 shell.packageUid, shell.packageName, 1853 shell.op != AppOpsManager.OP_NONE ? new int[] {shell.op} : null); 1854 if (ops == null || ops.size() <= 0) { 1855 pw.println("No operations."); 1856 return 0; 1857 } 1858 final long now = System.currentTimeMillis(); 1859 for (int i=0; i<ops.size(); i++) { 1860 List<AppOpsManager.OpEntry> entries = ops.get(i).getOps(); 1861 for (int j=0; j<entries.size(); j++) { 1862 AppOpsManager.OpEntry ent = entries.get(j); 1863 pw.print(AppOpsManager.opToName(ent.getOp())); 1864 pw.print(": "); 1865 switch (ent.getMode()) { 1866 case AppOpsManager.MODE_ALLOWED: 1867 pw.print("allow"); 1868 break; 1869 case AppOpsManager.MODE_IGNORED: 1870 pw.print("ignore"); 1871 break; 1872 case AppOpsManager.MODE_ERRORED: 1873 pw.print("deny"); 1874 break; 1875 case AppOpsManager.MODE_DEFAULT: 1876 pw.print("default"); 1877 break; 1878 default: 1879 pw.print("mode="); 1880 pw.print(ent.getMode()); 1881 break; 1882 } 1883 if (ent.getTime() != 0) { 1884 pw.print("; time="); 1885 TimeUtils.formatDuration(now - ent.getTime(), pw); 1886 pw.print(" ago"); 1887 } 1888 if (ent.getRejectTime() != 0) { 1889 pw.print("; rejectTime="); 1890 TimeUtils.formatDuration(now - ent.getRejectTime(), pw); 1891 pw.print(" ago"); 1892 } 1893 if (ent.getDuration() == -1) { 1894 pw.print(" (running)"); 1895 } else if (ent.getDuration() != 0) { 1896 pw.print("; duration="); 1897 TimeUtils.formatDuration(ent.getDuration(), pw); 1898 } 1899 pw.println(); 1900 } 1901 } 1902 return 0; 1903 } 1904 case "query-op": { 1905 int res = shell.parseUserOpMode(AppOpsManager.MODE_IGNORED, err); 1906 if (res < 0) { 1907 return res; 1908 } 1909 List<AppOpsManager.PackageOps> ops = shell.mInterface.getPackagesForOps( 1910 new int[] {shell.op}); 1911 if (ops == null || ops.size() <= 0) { 1912 pw.println("No operations."); 1913 return 0; 1914 } 1915 for (int i=0; i<ops.size(); i++) { 1916 final AppOpsManager.PackageOps pkg = ops.get(i); 1917 boolean hasMatch = false; 1918 final List<AppOpsManager.OpEntry> entries = ops.get(i).getOps(); 1919 for (int j=0; j<entries.size(); j++) { 1920 AppOpsManager.OpEntry ent = entries.get(j); 1921 if (ent.getOp() == shell.op && ent.getMode() == shell.mode) { 1922 hasMatch = true; 1923 break; 1924 } 1925 } 1926 if (hasMatch) { 1927 pw.println(pkg.getPackageName()); 1928 } 1929 } 1930 return 0; 1931 } 1932 case "reset": { 1933 String packageName = null; 1934 int userId = UserHandle.USER_CURRENT; 1935 for (String argument; (argument = shell.getNextArg()) != null;) { 1936 if ("--user".equals(argument)) { 1937 String userStr = shell.getNextArgRequired(); 1938 userId = UserHandle.parseUserArg(userStr); 1939 } else { 1940 if (packageName == null) { 1941 packageName = argument; 1942 } else { 1943 err.println("Error: Unsupported argument: " + argument); 1944 return -1; 1945 } 1946 } 1947 } 1948 1949 if (userId == UserHandle.USER_CURRENT) { 1950 userId = ActivityManager.getCurrentUser(); 1951 } 1952 1953 shell.mInterface.resetAllModes(userId, packageName); 1954 pw.print("Reset all modes for: "); 1955 if (userId == UserHandle.USER_ALL) { 1956 pw.print("all users"); 1957 } else { 1958 pw.print("user "); pw.print(userId); 1959 } 1960 pw.print(", "); 1961 if (packageName == null) { 1962 pw.println("all packages"); 1963 } else { 1964 pw.print("package "); pw.println(packageName); 1965 } 1966 return 0; 1967 } 1968 case "write-settings": { 1969 shell.mInternal.mContext.enforcePermission( 1970 android.Manifest.permission.UPDATE_APP_OPS_STATS, 1971 Binder.getCallingPid(), Binder.getCallingUid(), null); 1972 long token = Binder.clearCallingIdentity(); 1973 try { 1974 synchronized (shell.mInternal) { 1975 shell.mInternal.mHandler.removeCallbacks(shell.mInternal.mWriteRunner); 1976 } 1977 shell.mInternal.writeState(); 1978 pw.println("Current settings written."); 1979 } finally { 1980 Binder.restoreCallingIdentity(token); 1981 } 1982 return 0; 1983 } 1984 case "read-settings": { 1985 shell.mInternal.mContext.enforcePermission( 1986 android.Manifest.permission.UPDATE_APP_OPS_STATS, 1987 Binder.getCallingPid(), Binder.getCallingUid(), null); 1988 long token = Binder.clearCallingIdentity(); 1989 try { 1990 shell.mInternal.readState(); 1991 pw.println("Last settings read."); 1992 } finally { 1993 Binder.restoreCallingIdentity(token); 1994 } 1995 return 0; 1996 } 1997 default: 1998 return shell.handleDefaultCommands(cmd); 1999 } 2000 } catch (RemoteException e) { 2001 pw.println("Remote exception: " + e); 2002 } 2003 return -1; 2004 } 2005 2006 private void dumpHelp(PrintWriter pw) { 2007 pw.println("AppOps service (appops) dump options:"); 2008 pw.println(" none"); 2009 } 2010 2011 @Override 2012 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2013 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 2014 != PackageManager.PERMISSION_GRANTED) { 2015 pw.println("Permission Denial: can't dump ApOps service from from pid=" 2016 + Binder.getCallingPid() 2017 + ", uid=" + Binder.getCallingUid()); 2018 return; 2019 } 2020 2021 if (args != null) { 2022 for (int i=0; i<args.length; i++) { 2023 String arg = args[i]; 2024 if ("-h".equals(arg)) { 2025 dumpHelp(pw); 2026 return; 2027 } else if ("-a".equals(arg)) { 2028 // dump all data 2029 } else if (arg.length() > 0 && arg.charAt(0) == '-'){ 2030 pw.println("Unknown option: " + arg); 2031 return; 2032 } else { 2033 pw.println("Unknown command: " + arg); 2034 return; 2035 } 2036 } 2037 } 2038 2039 synchronized (this) { 2040 pw.println("Current AppOps Service state:"); 2041 final long now = System.currentTimeMillis(); 2042 boolean needSep = false; 2043 if (mOpModeWatchers.size() > 0) { 2044 needSep = true; 2045 pw.println(" Op mode watchers:"); 2046 for (int i=0; i<mOpModeWatchers.size(); i++) { 2047 pw.print(" Op "); pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i))); 2048 pw.println(":"); 2049 ArrayList<Callback> callbacks = mOpModeWatchers.valueAt(i); 2050 for (int j=0; j<callbacks.size(); j++) { 2051 pw.print(" #"); pw.print(j); pw.print(": "); 2052 pw.println(callbacks.get(j)); 2053 } 2054 } 2055 } 2056 if (mPackageModeWatchers.size() > 0) { 2057 needSep = true; 2058 pw.println(" Package mode watchers:"); 2059 for (int i=0; i<mPackageModeWatchers.size(); i++) { 2060 pw.print(" Pkg "); pw.print(mPackageModeWatchers.keyAt(i)); 2061 pw.println(":"); 2062 ArrayList<Callback> callbacks = mPackageModeWatchers.valueAt(i); 2063 for (int j=0; j<callbacks.size(); j++) { 2064 pw.print(" #"); pw.print(j); pw.print(": "); 2065 pw.println(callbacks.get(j)); 2066 } 2067 } 2068 } 2069 if (mModeWatchers.size() > 0) { 2070 needSep = true; 2071 pw.println(" All mode watchers:"); 2072 for (int i=0; i<mModeWatchers.size(); i++) { 2073 pw.print(" "); pw.print(mModeWatchers.keyAt(i)); 2074 pw.print(" -> "); pw.println(mModeWatchers.valueAt(i)); 2075 } 2076 } 2077 if (mClients.size() > 0) { 2078 needSep = true; 2079 pw.println(" Clients:"); 2080 for (int i=0; i<mClients.size(); i++) { 2081 pw.print(" "); pw.print(mClients.keyAt(i)); pw.println(":"); 2082 ClientState cs = mClients.valueAt(i); 2083 pw.print(" "); pw.println(cs); 2084 if (cs.mStartedOps != null && cs.mStartedOps.size() > 0) { 2085 pw.println(" Started ops:"); 2086 for (int j=0; j<cs.mStartedOps.size(); j++) { 2087 Op op = cs.mStartedOps.get(j); 2088 pw.print(" "); pw.print("uid="); pw.print(op.uid); 2089 pw.print(" pkg="); pw.print(op.packageName); 2090 pw.print(" op="); pw.println(AppOpsManager.opToName(op.op)); 2091 } 2092 } 2093 } 2094 } 2095 if (mAudioRestrictions.size() > 0) { 2096 boolean printedHeader = false; 2097 for (int o=0; o<mAudioRestrictions.size(); o++) { 2098 final String op = AppOpsManager.opToName(mAudioRestrictions.keyAt(o)); 2099 final SparseArray<Restriction> restrictions = mAudioRestrictions.valueAt(o); 2100 for (int i=0; i<restrictions.size(); i++) { 2101 if (!printedHeader){ 2102 pw.println(" Audio Restrictions:"); 2103 printedHeader = true; 2104 needSep = true; 2105 } 2106 final int usage = restrictions.keyAt(i); 2107 pw.print(" "); pw.print(op); 2108 pw.print(" usage="); pw.print(AudioAttributes.usageToString(usage)); 2109 Restriction r = restrictions.valueAt(i); 2110 pw.print(": mode="); pw.println(r.mode); 2111 if (!r.exceptionPackages.isEmpty()) { 2112 pw.println(" Exceptions:"); 2113 for (int j=0; j<r.exceptionPackages.size(); j++) { 2114 pw.print(" "); pw.println(r.exceptionPackages.valueAt(j)); 2115 } 2116 } 2117 } 2118 } 2119 } 2120 if (needSep) { 2121 pw.println(); 2122 } 2123 for (int i=0; i<mUidStates.size(); i++) { 2124 UidState uidState = mUidStates.valueAt(i); 2125 2126 pw.print(" Uid "); UserHandle.formatUid(pw, uidState.uid); pw.println(":"); 2127 2128 SparseIntArray opModes = uidState.opModes; 2129 if (opModes != null) { 2130 final int opModeCount = opModes.size(); 2131 for (int j = 0; j < opModeCount; j++) { 2132 final int code = opModes.keyAt(j); 2133 final int mode = opModes.valueAt(j); 2134 pw.print(" "); pw.print(AppOpsManager.opToName(code)); 2135 pw.print(": mode="); pw.println(mode); 2136 } 2137 } 2138 2139 ArrayMap<String, Ops> pkgOps = uidState.pkgOps; 2140 if (pkgOps == null) { 2141 continue; 2142 } 2143 2144 for (Ops ops : pkgOps.values()) { 2145 pw.print(" Package "); pw.print(ops.packageName); pw.println(":"); 2146 for (int j=0; j<ops.size(); j++) { 2147 Op op = ops.valueAt(j); 2148 pw.print(" "); pw.print(AppOpsManager.opToName(op.op)); 2149 pw.print(": mode="); pw.print(op.mode); 2150 if (op.time != 0) { 2151 pw.print("; time="); TimeUtils.formatDuration(now-op.time, pw); 2152 pw.print(" ago"); 2153 } 2154 if (op.rejectTime != 0) { 2155 pw.print("; rejectTime="); TimeUtils.formatDuration(now-op.rejectTime, pw); 2156 pw.print(" ago"); 2157 } 2158 if (op.duration == -1) { 2159 pw.print(" (running)"); 2160 } else if (op.duration != 0) { 2161 pw.print("; duration="); TimeUtils.formatDuration(op.duration, pw); 2162 } 2163 pw.println(); 2164 } 2165 } 2166 } 2167 } 2168 } 2169 2170 private static final class Restriction { 2171 private static final ArraySet<String> NO_EXCEPTIONS = new ArraySet<String>(); 2172 int mode; 2173 ArraySet<String> exceptionPackages = NO_EXCEPTIONS; 2174 } 2175 2176 @Override 2177 public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) { 2178 checkSystemUid("setUserRestrictions"); 2179 Preconditions.checkNotNull(restrictions); 2180 Preconditions.checkNotNull(token); 2181 for (int i = 0; i < AppOpsManager._NUM_OP; i++) { 2182 String restriction = AppOpsManager.opToRestriction(i); 2183 if (restriction != null) { 2184 setUserRestrictionNoCheck(i, restrictions.getBoolean(restriction, false), token, 2185 userHandle, null); 2186 } 2187 } 2188 } 2189 2190 @Override 2191 public void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle, 2192 String[] exceptionPackages) { 2193 if (Binder.getCallingPid() != Process.myPid()) { 2194 mContext.enforcePermission(Manifest.permission.MANAGE_APP_OPS_RESTRICTIONS, 2195 Binder.getCallingPid(), Binder.getCallingUid(), null); 2196 } 2197 if (userHandle != UserHandle.getCallingUserId()) { 2198 if (mContext.checkCallingOrSelfPermission(Manifest.permission 2199 .INTERACT_ACROSS_USERS_FULL) != PackageManager.PERMISSION_GRANTED 2200 && mContext.checkCallingOrSelfPermission(Manifest.permission 2201 .INTERACT_ACROSS_USERS) != PackageManager.PERMISSION_GRANTED) { 2202 throw new SecurityException("Need INTERACT_ACROSS_USERS_FULL or" 2203 + " INTERACT_ACROSS_USERS to interact cross user "); 2204 } 2205 } 2206 verifyIncomingOp(code); 2207 Preconditions.checkNotNull(token); 2208 setUserRestrictionNoCheck(code, restricted, token, userHandle, exceptionPackages); 2209 } 2210 2211 private void setUserRestrictionNoCheck(int code, boolean restricted, IBinder token, 2212 int userHandle, String[] exceptionPackages) { 2213 ClientRestrictionState restrictionState = mOpUserRestrictions.get(token); 2214 2215 if (restrictionState == null) { 2216 try { 2217 restrictionState = new ClientRestrictionState(token); 2218 } catch (RemoteException e) { 2219 return; 2220 } 2221 mOpUserRestrictions.put(token, restrictionState); 2222 } 2223 2224 if (restrictionState.setRestriction(code, restricted, exceptionPackages, userHandle)) { 2225 notifyWatchersOfChange(code); 2226 } 2227 2228 if (restrictionState.isDefault()) { 2229 mOpUserRestrictions.remove(token); 2230 restrictionState.destroy(); 2231 } 2232 } 2233 2234 private void notifyWatchersOfChange(int code) { 2235 final ArrayList<Callback> clonedCallbacks; 2236 synchronized (this) { 2237 ArrayList<Callback> callbacks = mOpModeWatchers.get(code); 2238 if (callbacks == null) { 2239 return; 2240 } 2241 clonedCallbacks = new ArrayList<>(callbacks); 2242 } 2243 2244 // There are components watching for mode changes such as window manager 2245 // and location manager which are in our process. The callbacks in these 2246 // components may require permissions our remote caller does not have.s 2247 final long identity = Binder.clearCallingIdentity(); 2248 try { 2249 final int callbackCount = clonedCallbacks.size(); 2250 for (int i = 0; i < callbackCount; i++) { 2251 Callback callback = clonedCallbacks.get(i); 2252 try { 2253 callback.mCallback.opChanged(code, -1, null); 2254 } catch (RemoteException e) { 2255 Log.w(TAG, "Error dispatching op op change", e); 2256 } 2257 } 2258 } finally { 2259 Binder.restoreCallingIdentity(identity); 2260 } 2261 } 2262 2263 @Override 2264 public void removeUser(int userHandle) throws RemoteException { 2265 checkSystemUid("removeUser"); 2266 final int tokenCount = mOpUserRestrictions.size(); 2267 for (int i = tokenCount - 1; i >= 0; i--) { 2268 ClientRestrictionState opRestrictions = mOpUserRestrictions.valueAt(i); 2269 opRestrictions.removeUser(userHandle); 2270 } 2271 } 2272 2273 private void checkSystemUid(String function) { 2274 int uid = Binder.getCallingUid(); 2275 if (uid != Process.SYSTEM_UID) { 2276 throw new SecurityException(function + " must by called by the system"); 2277 } 2278 } 2279 2280 private static String resolvePackageName(int uid, String packageName) { 2281 if (uid == 0) { 2282 return "root"; 2283 } else if (uid == Process.SHELL_UID) { 2284 return "com.android.shell"; 2285 } else if (uid == Process.SYSTEM_UID && packageName == null) { 2286 return "android"; 2287 } 2288 return packageName; 2289 } 2290 2291 private static String[] getPackagesForUid(int uid) { 2292 String[] packageNames = null; 2293 try { 2294 packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid); 2295 } catch (RemoteException e) { 2296 /* ignore - local call */ 2297 } 2298 if (packageNames == null) { 2299 return EmptyArray.STRING; 2300 } 2301 return packageNames; 2302 } 2303 2304 private final class ClientRestrictionState implements DeathRecipient { 2305 private final IBinder token; 2306 SparseArray<boolean[]> perUserRestrictions; 2307 SparseArray<String[]> perUserExcludedPackages; 2308 2309 public ClientRestrictionState(IBinder token) 2310 throws RemoteException { 2311 token.linkToDeath(this, 0); 2312 this.token = token; 2313 } 2314 2315 public boolean setRestriction(int code, boolean restricted, 2316 String[] excludedPackages, int userId) { 2317 boolean changed = false; 2318 2319 if (perUserRestrictions == null && restricted) { 2320 perUserRestrictions = new SparseArray<>(); 2321 } 2322 2323 if (perUserRestrictions != null) { 2324 boolean[] userRestrictions = perUserRestrictions.get(userId); 2325 if (userRestrictions == null && restricted) { 2326 userRestrictions = new boolean[AppOpsManager._NUM_OP]; 2327 perUserRestrictions.put(userId, userRestrictions); 2328 } 2329 if (userRestrictions != null && userRestrictions[code] != restricted) { 2330 userRestrictions[code] = restricted; 2331 if (!restricted && isDefault(userRestrictions)) { 2332 perUserRestrictions.remove(userId); 2333 userRestrictions = null; 2334 } 2335 changed = true; 2336 } 2337 2338 if (userRestrictions != null) { 2339 final boolean noExcludedPackages = ArrayUtils.isEmpty(excludedPackages); 2340 if (perUserExcludedPackages == null && !noExcludedPackages) { 2341 perUserExcludedPackages = new SparseArray<>(); 2342 } 2343 if (perUserExcludedPackages != null && !Arrays.equals(excludedPackages, 2344 perUserExcludedPackages.get(userId))) { 2345 if (noExcludedPackages) { 2346 perUserExcludedPackages.remove(userId); 2347 if (perUserExcludedPackages.size() <= 0) { 2348 perUserExcludedPackages = null; 2349 } 2350 } else { 2351 perUserExcludedPackages.put(userId, excludedPackages); 2352 } 2353 changed = true; 2354 } 2355 } 2356 } 2357 2358 return changed; 2359 } 2360 2361 public boolean hasRestriction(int restriction, String packageName, int userId) { 2362 if (perUserRestrictions == null) { 2363 return false; 2364 } 2365 boolean[] restrictions = perUserRestrictions.get(userId); 2366 if (restrictions == null) { 2367 return false; 2368 } 2369 if (!restrictions[restriction]) { 2370 return false; 2371 } 2372 if (perUserExcludedPackages == null) { 2373 return true; 2374 } 2375 String[] perUserExclusions = perUserExcludedPackages.get(userId); 2376 if (perUserExclusions == null) { 2377 return true; 2378 } 2379 return !ArrayUtils.contains(perUserExclusions, packageName); 2380 } 2381 2382 public void removeUser(int userId) { 2383 if (perUserExcludedPackages != null) { 2384 perUserExcludedPackages.remove(userId); 2385 if (perUserExcludedPackages.size() <= 0) { 2386 perUserExcludedPackages = null; 2387 } 2388 } 2389 } 2390 2391 public boolean isDefault() { 2392 return perUserRestrictions == null || perUserRestrictions.size() <= 0; 2393 } 2394 2395 @Override 2396 public void binderDied() { 2397 synchronized (AppOpsService.this) { 2398 mOpUserRestrictions.remove(token); 2399 if (perUserRestrictions == null) { 2400 return; 2401 } 2402 final int userCount = perUserRestrictions.size(); 2403 for (int i = 0; i < userCount; i++) { 2404 final boolean[] restrictions = perUserRestrictions.valueAt(i); 2405 final int restrictionCount = restrictions.length; 2406 for (int j = 0; j < restrictionCount; j++) { 2407 if (restrictions[j]) { 2408 final int changedCode = j; 2409 mHandler.post(() -> notifyWatchersOfChange(changedCode)); 2410 } 2411 } 2412 } 2413 destroy(); 2414 } 2415 } 2416 2417 public void destroy() { 2418 token.unlinkToDeath(this, 0); 2419 } 2420 2421 private boolean isDefault(boolean[] array) { 2422 if (ArrayUtils.isEmpty(array)) { 2423 return true; 2424 } 2425 for (boolean value : array) { 2426 if (value) { 2427 return false; 2428 } 2429 } 2430 return true; 2431 } 2432 } 2433 } 2434