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.Collections; 29 import java.util.HashMap; 30 import java.util.Iterator; 31 import java.util.List; 32 import java.util.Map; 33 34 import android.app.ActivityManager; 35 import android.app.ActivityThread; 36 import android.app.AppGlobals; 37 import android.app.AppOpsManager; 38 import android.content.Context; 39 import android.content.pm.ApplicationInfo; 40 import android.content.pm.IPackageManager; 41 import android.content.pm.PackageManager; 42 import android.content.pm.PackageManager.NameNotFoundException; 43 import android.media.AudioAttributes; 44 import android.os.AsyncTask; 45 import android.os.Binder; 46 import android.os.Bundle; 47 import android.os.Handler; 48 import android.os.IBinder; 49 import android.os.Process; 50 import android.os.RemoteException; 51 import android.os.ServiceManager; 52 import android.os.UserHandle; 53 import android.os.storage.MountServiceInternal; 54 import android.util.ArrayMap; 55 import android.util.ArraySet; 56 import android.util.AtomicFile; 57 import android.util.Log; 58 import android.util.Pair; 59 import android.util.Slog; 60 import android.util.SparseArray; 61 import android.util.SparseIntArray; 62 import android.util.TimeUtils; 63 import android.util.Xml; 64 65 import com.android.internal.app.IAppOpsService; 66 import com.android.internal.app.IAppOpsCallback; 67 import com.android.internal.os.Zygote; 68 import com.android.internal.util.ArrayUtils; 69 import com.android.internal.util.FastXmlSerializer; 70 import com.android.internal.util.XmlUtils; 71 72 import libcore.util.EmptyArray; 73 import org.xmlpull.v1.XmlPullParser; 74 import org.xmlpull.v1.XmlPullParserException; 75 import org.xmlpull.v1.XmlSerializer; 76 77 public class AppOpsService extends IAppOpsService.Stub { 78 static final String TAG = "AppOps"; 79 static final boolean DEBUG = false; 80 81 // Write at most every 30 minutes. 82 static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000; 83 84 Context mContext; 85 final AtomicFile mFile; 86 final Handler mHandler; 87 88 boolean mWriteScheduled; 89 boolean mFastWriteScheduled; 90 final Runnable mWriteRunner = new Runnable() { 91 public void run() { 92 synchronized (AppOpsService.this) { 93 mWriteScheduled = false; 94 mFastWriteScheduled = false; 95 AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() { 96 @Override protected Void doInBackground(Void... params) { 97 writeState(); 98 return null; 99 } 100 }; 101 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null); 102 } 103 } 104 }; 105 106 final SparseArray<UidState> mUidStates = new SparseArray<>(); 107 108 private final SparseArray<boolean[]> mOpRestrictions = new SparseArray<boolean[]>(); 109 110 private static final class UidState { 111 public final int uid; 112 public ArrayMap<String, Ops> pkgOps; 113 public SparseIntArray opModes; 114 115 public UidState(int uid) { 116 this.uid = uid; 117 } 118 119 public void clear() { 120 pkgOps = null; 121 opModes = null; 122 } 123 124 public boolean isDefault() { 125 return (pkgOps == null || pkgOps.isEmpty()) 126 && (opModes == null || opModes.size() <= 0); 127 } 128 } 129 130 public final static class Ops extends SparseArray<Op> { 131 public final String packageName; 132 public final UidState uidState; 133 public final boolean isPrivileged; 134 135 public Ops(String _packageName, UidState _uidState, boolean _isPrivileged) { 136 packageName = _packageName; 137 uidState = _uidState; 138 isPrivileged = _isPrivileged; 139 } 140 } 141 142 public final static class Op { 143 public final int uid; 144 public final String packageName; 145 public int proxyUid = -1; 146 public String proxyPackageName; 147 public final int op; 148 public int mode; 149 public int duration; 150 public long time; 151 public long rejectTime; 152 public int nesting; 153 154 public Op(int _uid, String _packageName, int _op) { 155 uid = _uid; 156 packageName = _packageName; 157 op = _op; 158 mode = AppOpsManager.opToDefaultMode(op); 159 } 160 } 161 162 final SparseArray<ArrayList<Callback>> mOpModeWatchers 163 = new SparseArray<ArrayList<Callback>>(); 164 final ArrayMap<String, ArrayList<Callback>> mPackageModeWatchers 165 = new ArrayMap<String, ArrayList<Callback>>(); 166 final ArrayMap<IBinder, Callback> mModeWatchers 167 = new ArrayMap<IBinder, Callback>(); 168 final SparseArray<SparseArray<Restriction>> mAudioRestrictions 169 = new SparseArray<SparseArray<Restriction>>(); 170 171 public final class Callback implements DeathRecipient { 172 final IAppOpsCallback mCallback; 173 174 public Callback(IAppOpsCallback callback) { 175 mCallback = callback; 176 try { 177 mCallback.asBinder().linkToDeath(this, 0); 178 } catch (RemoteException e) { 179 } 180 } 181 182 public void unlinkToDeath() { 183 mCallback.asBinder().unlinkToDeath(this, 0); 184 } 185 186 @Override 187 public void binderDied() { 188 stopWatchingMode(mCallback); 189 } 190 } 191 192 final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<IBinder, ClientState>(); 193 194 public final class ClientState extends Binder implements DeathRecipient { 195 final IBinder mAppToken; 196 final int mPid; 197 final ArrayList<Op> mStartedOps; 198 199 public ClientState(IBinder appToken) { 200 mAppToken = appToken; 201 mPid = Binder.getCallingPid(); 202 if (appToken instanceof Binder) { 203 // For local clients, there is no reason to track them. 204 mStartedOps = null; 205 } else { 206 mStartedOps = new ArrayList<Op>(); 207 try { 208 mAppToken.linkToDeath(this, 0); 209 } catch (RemoteException e) { 210 } 211 } 212 } 213 214 @Override 215 public String toString() { 216 return "ClientState{" + 217 "mAppToken=" + mAppToken + 218 ", " + (mStartedOps != null ? ("pid=" + mPid) : "local") + 219 '}'; 220 } 221 222 @Override 223 public void binderDied() { 224 synchronized (AppOpsService.this) { 225 for (int i=mStartedOps.size()-1; i>=0; i--) { 226 finishOperationLocked(mStartedOps.get(i)); 227 } 228 mClients.remove(mAppToken); 229 } 230 } 231 } 232 233 public AppOpsService(File storagePath, Handler handler) { 234 mFile = new AtomicFile(storagePath); 235 mHandler = handler; 236 readState(); 237 } 238 239 public void publish(Context context) { 240 mContext = context; 241 ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder()); 242 } 243 244 public void systemReady() { 245 synchronized (this) { 246 boolean changed = false; 247 for (int i = mUidStates.size() - 1; i >= 0; i--) { 248 UidState uidState = mUidStates.valueAt(i); 249 250 String[] packageNames = getPackagesForUid(uidState.uid); 251 if (ArrayUtils.isEmpty(packageNames)) { 252 uidState.clear(); 253 mUidStates.removeAt(i); 254 changed = true; 255 continue; 256 } 257 258 ArrayMap<String, Ops> pkgs = uidState.pkgOps; 259 if (pkgs == null) { 260 continue; 261 } 262 263 Iterator<Ops> it = pkgs.values().iterator(); 264 while (it.hasNext()) { 265 Ops ops = it.next(); 266 int curUid; 267 try { 268 curUid = mContext.getPackageManager().getPackageUid(ops.packageName, 269 UserHandle.getUserId(ops.uidState.uid)); 270 } catch (NameNotFoundException e) { 271 curUid = -1; 272 } 273 if (curUid != ops.uidState.uid) { 274 Slog.i(TAG, "Pruning old package " + ops.packageName 275 + "/" + ops.uidState + ": new uid=" + curUid); 276 it.remove(); 277 changed = true; 278 } 279 } 280 281 if (uidState.isDefault()) { 282 mUidStates.removeAt(i); 283 } 284 } 285 if (changed) { 286 scheduleFastWriteLocked(); 287 } 288 } 289 290 MountServiceInternal mountServiceInternal = LocalServices.getService( 291 MountServiceInternal.class); 292 mountServiceInternal.addExternalStoragePolicy( 293 new MountServiceInternal.ExternalStorageMountPolicy() { 294 @Override 295 public int getMountMode(int uid, String packageName) { 296 if (Process.isIsolated(uid)) { 297 return Zygote.MOUNT_EXTERNAL_NONE; 298 } 299 if (noteOperation(AppOpsManager.OP_READ_EXTERNAL_STORAGE, uid, 300 packageName) != AppOpsManager.MODE_ALLOWED) { 301 return Zygote.MOUNT_EXTERNAL_NONE; 302 } 303 if (noteOperation(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, uid, 304 packageName) != AppOpsManager.MODE_ALLOWED) { 305 return Zygote.MOUNT_EXTERNAL_READ; 306 } 307 return Zygote.MOUNT_EXTERNAL_WRITE; 308 } 309 310 @Override 311 public boolean hasExternalStorage(int uid, String packageName) { 312 final int mountMode = getMountMode(uid, packageName); 313 return mountMode == Zygote.MOUNT_EXTERNAL_READ 314 || mountMode == Zygote.MOUNT_EXTERNAL_WRITE; 315 } 316 }); 317 } 318 319 public void packageRemoved(int uid, String packageName) { 320 synchronized (this) { 321 UidState uidState = mUidStates.get(uid); 322 if (uidState == null) { 323 return; 324 } 325 326 boolean changed = false; 327 328 // Remove any package state if such. 329 if (uidState.pkgOps != null && uidState.pkgOps.remove(packageName) != null) { 330 changed = true; 331 } 332 333 // If we just nuked the last package state check if the UID is valid. 334 if (changed && uidState.pkgOps.isEmpty() 335 && getPackagesForUid(uid).length <= 0) { 336 mUidStates.remove(uid); 337 } 338 339 if (changed) { 340 scheduleFastWriteLocked(); 341 } 342 } 343 } 344 345 public void uidRemoved(int uid) { 346 synchronized (this) { 347 if (mUidStates.indexOfKey(uid) >= 0) { 348 mUidStates.remove(uid); 349 scheduleFastWriteLocked(); 350 } 351 } 352 } 353 354 public void shutdown() { 355 Slog.w(TAG, "Writing app ops before shutdown..."); 356 boolean doWrite = false; 357 synchronized (this) { 358 if (mWriteScheduled) { 359 mWriteScheduled = false; 360 doWrite = true; 361 } 362 } 363 if (doWrite) { 364 writeState(); 365 } 366 } 367 368 private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) { 369 ArrayList<AppOpsManager.OpEntry> resOps = null; 370 if (ops == null) { 371 resOps = new ArrayList<AppOpsManager.OpEntry>(); 372 for (int j=0; j<pkgOps.size(); j++) { 373 Op curOp = pkgOps.valueAt(j); 374 resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time, 375 curOp.rejectTime, curOp.duration, curOp.proxyUid, 376 curOp.proxyPackageName)); 377 } 378 } else { 379 for (int j=0; j<ops.length; j++) { 380 Op curOp = pkgOps.get(ops[j]); 381 if (curOp != null) { 382 if (resOps == null) { 383 resOps = new ArrayList<AppOpsManager.OpEntry>(); 384 } 385 resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time, 386 curOp.rejectTime, curOp.duration, curOp.proxyUid, 387 curOp.proxyPackageName)); 388 } 389 } 390 } 391 return resOps; 392 } 393 394 @Override 395 public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) { 396 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 397 Binder.getCallingPid(), Binder.getCallingUid(), null); 398 ArrayList<AppOpsManager.PackageOps> res = null; 399 synchronized (this) { 400 final int uidStateCount = mUidStates.size(); 401 for (int i = 0; i < uidStateCount; i++) { 402 UidState uidState = mUidStates.valueAt(i); 403 if (uidState.pkgOps == null || uidState.pkgOps.isEmpty()) { 404 continue; 405 } 406 ArrayMap<String, Ops> packages = uidState.pkgOps; 407 final int packageCount = packages.size(); 408 for (int j = 0; j < packageCount; j++) { 409 Ops pkgOps = packages.valueAt(j); 410 ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops); 411 if (resOps != null) { 412 if (res == null) { 413 res = new ArrayList<AppOpsManager.PackageOps>(); 414 } 415 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( 416 pkgOps.packageName, pkgOps.uidState.uid, resOps); 417 res.add(resPackage); 418 } 419 } 420 } 421 } 422 return res; 423 } 424 425 @Override 426 public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, 427 int[] ops) { 428 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 429 Binder.getCallingPid(), Binder.getCallingUid(), null); 430 synchronized (this) { 431 Ops pkgOps = getOpsLocked(uid, packageName, false); 432 if (pkgOps == null) { 433 return null; 434 } 435 ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops); 436 if (resOps == null) { 437 return null; 438 } 439 ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>(); 440 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( 441 pkgOps.packageName, pkgOps.uidState.uid, resOps); 442 res.add(resPackage); 443 return res; 444 } 445 } 446 447 private void pruneOp(Op op, int uid, String packageName) { 448 if (op.time == 0 && op.rejectTime == 0) { 449 Ops ops = getOpsLocked(uid, packageName, false); 450 if (ops != null) { 451 ops.remove(op.op); 452 if (ops.size() <= 0) { 453 UidState uidState = ops.uidState; 454 ArrayMap<String, Ops> pkgOps = uidState.pkgOps; 455 if (pkgOps != null) { 456 pkgOps.remove(ops.packageName); 457 if (pkgOps.isEmpty()) { 458 uidState.pkgOps = null; 459 } 460 if (uidState.isDefault()) { 461 mUidStates.remove(uid); 462 } 463 } 464 } 465 } 466 } 467 } 468 469 @Override 470 public void setUidMode(int code, int uid, int mode) { 471 if (Binder.getCallingPid() != Process.myPid()) { 472 mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 473 Binder.getCallingPid(), Binder.getCallingUid(), null); 474 } 475 verifyIncomingOp(code); 476 code = AppOpsManager.opToSwitch(code); 477 478 synchronized (this) { 479 final int defaultMode = AppOpsManager.opToDefaultMode(code); 480 481 UidState uidState = getUidStateLocked(uid, false); 482 if (uidState == null) { 483 if (mode == defaultMode) { 484 return; 485 } 486 uidState = new UidState(uid); 487 uidState.opModes = new SparseIntArray(); 488 uidState.opModes.put(code, mode); 489 mUidStates.put(uid, uidState); 490 scheduleWriteLocked(); 491 } else if (uidState.opModes == null) { 492 if (mode != defaultMode) { 493 uidState.opModes = new SparseIntArray(); 494 uidState.opModes.put(code, mode); 495 scheduleWriteLocked(); 496 } 497 } else { 498 if (uidState.opModes.get(code) == mode) { 499 return; 500 } 501 if (mode == defaultMode) { 502 uidState.opModes.delete(code); 503 if (uidState.opModes.size() <= 0) { 504 uidState.opModes = null; 505 } 506 } else { 507 uidState.opModes.put(code, mode); 508 } 509 scheduleWriteLocked(); 510 } 511 } 512 513 String[] uidPackageNames = getPackagesForUid(uid); 514 ArrayMap<Callback, ArraySet<String>> callbackSpecs = null; 515 516 ArrayList<Callback> callbacks = mOpModeWatchers.get(code); 517 if (callbacks != null) { 518 final int callbackCount = callbacks.size(); 519 for (int i = 0; i < callbackCount; i++) { 520 Callback callback = callbacks.get(i); 521 ArraySet<String> changedPackages = new ArraySet<>(); 522 Collections.addAll(changedPackages, uidPackageNames); 523 callbackSpecs = new ArrayMap<>(); 524 callbackSpecs.put(callback, changedPackages); 525 } 526 } 527 528 for (String uidPackageName : uidPackageNames) { 529 callbacks = mPackageModeWatchers.get(uidPackageName); 530 if (callbacks != null) { 531 if (callbackSpecs == null) { 532 callbackSpecs = new ArrayMap<>(); 533 } 534 final int callbackCount = callbacks.size(); 535 for (int i = 0; i < callbackCount; i++) { 536 Callback callback = callbacks.get(i); 537 ArraySet<String> changedPackages = callbackSpecs.get(callback); 538 if (changedPackages == null) { 539 changedPackages = new ArraySet<>(); 540 callbackSpecs.put(callback, changedPackages); 541 } 542 changedPackages.add(uidPackageName); 543 } 544 } 545 } 546 547 if (callbackSpecs == null) { 548 return; 549 } 550 551 // There are components watching for mode changes such as window manager 552 // and location manager which are in our process. The callbacks in these 553 // components may require permissions our remote caller does not have. 554 final long identity = Binder.clearCallingIdentity(); 555 try { 556 for (int i = 0; i < callbackSpecs.size(); i++) { 557 Callback callback = callbackSpecs.keyAt(i); 558 ArraySet<String> reportedPackageNames = callbackSpecs.valueAt(i); 559 try { 560 if (reportedPackageNames == null) { 561 callback.mCallback.opChanged(code, null); 562 } else { 563 final int reportedPackageCount = reportedPackageNames.size(); 564 for (int j = 0; j < reportedPackageCount; j++) { 565 String reportedPackageName = reportedPackageNames.valueAt(j); 566 callback.mCallback.opChanged(code, reportedPackageName); 567 } 568 } 569 } catch (RemoteException e) { 570 Log.w(TAG, "Error dispatching op op change", e); 571 } 572 } 573 } finally { 574 Binder.restoreCallingIdentity(identity); 575 } 576 } 577 578 @Override 579 public void setMode(int code, int uid, String packageName, int mode) { 580 if (Binder.getCallingPid() != Process.myPid()) { 581 mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 582 Binder.getCallingPid(), Binder.getCallingUid(), null); 583 } 584 verifyIncomingOp(code); 585 ArrayList<Callback> repCbs = null; 586 code = AppOpsManager.opToSwitch(code); 587 synchronized (this) { 588 UidState uidState = getUidStateLocked(uid, false); 589 Op op = getOpLocked(code, uid, packageName, true); 590 if (op != null) { 591 if (op.mode != mode) { 592 op.mode = mode; 593 ArrayList<Callback> cbs = mOpModeWatchers.get(code); 594 if (cbs != null) { 595 if (repCbs == null) { 596 repCbs = new ArrayList<Callback>(); 597 } 598 repCbs.addAll(cbs); 599 } 600 cbs = mPackageModeWatchers.get(packageName); 601 if (cbs != null) { 602 if (repCbs == null) { 603 repCbs = new ArrayList<Callback>(); 604 } 605 repCbs.addAll(cbs); 606 } 607 if (mode == AppOpsManager.opToDefaultMode(op.op)) { 608 // If going into the default mode, prune this op 609 // if there is nothing else interesting in it. 610 pruneOp(op, uid, packageName); 611 } 612 scheduleFastWriteLocked(); 613 } 614 } 615 } 616 if (repCbs != null) { 617 // There are components watching for mode changes such as window manager 618 // and location manager which are in our process. The callbacks in these 619 // components may require permissions our remote caller does not have. 620 final long identity = Binder.clearCallingIdentity(); 621 try { 622 for (int i = 0; i < repCbs.size(); i++) { 623 try { 624 repCbs.get(i).mCallback.opChanged(code, packageName); 625 } catch (RemoteException e) { 626 } 627 } 628 } finally { 629 Binder.restoreCallingIdentity(identity); 630 } 631 } 632 } 633 634 private static HashMap<Callback, ArrayList<Pair<String, Integer>>> addCallbacks( 635 HashMap<Callback, ArrayList<Pair<String, Integer>>> callbacks, 636 String packageName, int op, ArrayList<Callback> cbs) { 637 if (cbs == null) { 638 return callbacks; 639 } 640 if (callbacks == null) { 641 callbacks = new HashMap<Callback, ArrayList<Pair<String, Integer>>>(); 642 } 643 boolean duplicate = false; 644 for (int i=0; i<cbs.size(); i++) { 645 Callback cb = cbs.get(i); 646 ArrayList<Pair<String, Integer>> reports = callbacks.get(cb); 647 if (reports == null) { 648 reports = new ArrayList<Pair<String, Integer>>(); 649 callbacks.put(cb, reports); 650 } else { 651 final int reportCount = reports.size(); 652 for (int j = 0; j < reportCount; j++) { 653 Pair<String, Integer> report = reports.get(j); 654 if (report.second == op && report.first.equals(packageName)) { 655 duplicate = true; 656 break; 657 } 658 } 659 } 660 if (!duplicate) { 661 reports.add(new Pair<>(packageName, op)); 662 } 663 } 664 return callbacks; 665 } 666 667 @Override 668 public void resetAllModes(int reqUserId, String reqPackageName) { 669 final int callingPid = Binder.getCallingPid(); 670 final int callingUid = Binder.getCallingUid(); 671 mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 672 callingPid, callingUid, null); 673 reqUserId = ActivityManager.handleIncomingUser(callingPid, callingUid, reqUserId, 674 true, true, "resetAllModes", null); 675 676 int reqUid = -1; 677 if (reqPackageName != null) { 678 try { 679 reqUid = AppGlobals.getPackageManager().getPackageUid( 680 reqPackageName, reqUserId); 681 } catch (RemoteException e) { 682 /* ignore - local call */ 683 } 684 } 685 686 HashMap<Callback, ArrayList<Pair<String, Integer>>> callbacks = null; 687 synchronized (this) { 688 boolean changed = false; 689 for (int i = mUidStates.size() - 1; i >= 0; i--) { 690 UidState uidState = mUidStates.valueAt(i); 691 692 SparseIntArray opModes = uidState.opModes; 693 if (opModes != null && (uidState.uid == reqUid || reqUid == -1)) { 694 final int uidOpCount = opModes.size(); 695 for (int j = uidOpCount - 1; j >= 0; j--) { 696 final int code = opModes.keyAt(j); 697 if (AppOpsManager.opAllowsReset(code)) { 698 opModes.removeAt(j); 699 if (opModes.size() <= 0) { 700 uidState.opModes = null; 701 } 702 for (String packageName : getPackagesForUid(uidState.uid)) { 703 callbacks = addCallbacks(callbacks, packageName, code, 704 mOpModeWatchers.get(code)); 705 callbacks = addCallbacks(callbacks, packageName, code, 706 mPackageModeWatchers.get(packageName)); 707 } 708 } 709 } 710 } 711 712 if (uidState.pkgOps == null) { 713 continue; 714 } 715 716 if (reqUserId != UserHandle.USER_ALL 717 && reqUserId != UserHandle.getUserId(uidState.uid)) { 718 // Skip any ops for a different user 719 continue; 720 } 721 722 Map<String, Ops> packages = uidState.pkgOps; 723 Iterator<Map.Entry<String, Ops>> it = packages.entrySet().iterator(); 724 while (it.hasNext()) { 725 Map.Entry<String, Ops> ent = it.next(); 726 String packageName = ent.getKey(); 727 if (reqPackageName != null && !reqPackageName.equals(packageName)) { 728 // Skip any ops for a different package 729 continue; 730 } 731 Ops pkgOps = ent.getValue(); 732 for (int j=pkgOps.size()-1; j>=0; j--) { 733 Op curOp = pkgOps.valueAt(j); 734 if (AppOpsManager.opAllowsReset(curOp.op) 735 && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) { 736 curOp.mode = AppOpsManager.opToDefaultMode(curOp.op); 737 changed = true; 738 callbacks = addCallbacks(callbacks, packageName, curOp.op, 739 mOpModeWatchers.get(curOp.op)); 740 callbacks = addCallbacks(callbacks, packageName, curOp.op, 741 mPackageModeWatchers.get(packageName)); 742 if (curOp.time == 0 && curOp.rejectTime == 0) { 743 pkgOps.removeAt(j); 744 } 745 } 746 } 747 if (pkgOps.size() == 0) { 748 it.remove(); 749 } 750 } 751 if (uidState.isDefault()) { 752 mUidStates.remove(uidState.uid); 753 } 754 } 755 756 if (changed) { 757 scheduleFastWriteLocked(); 758 } 759 } 760 if (callbacks != null) { 761 for (Map.Entry<Callback, ArrayList<Pair<String, Integer>>> ent : callbacks.entrySet()) { 762 Callback cb = ent.getKey(); 763 ArrayList<Pair<String, Integer>> reports = ent.getValue(); 764 for (int i=0; i<reports.size(); i++) { 765 Pair<String, Integer> rep = reports.get(i); 766 try { 767 cb.mCallback.opChanged(rep.second, rep.first); 768 } catch (RemoteException e) { 769 } 770 } 771 } 772 } 773 } 774 775 @Override 776 public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) { 777 synchronized (this) { 778 op = (op != AppOpsManager.OP_NONE) ? AppOpsManager.opToSwitch(op) : op; 779 Callback cb = mModeWatchers.get(callback.asBinder()); 780 if (cb == null) { 781 cb = new Callback(callback); 782 mModeWatchers.put(callback.asBinder(), cb); 783 } 784 if (op != AppOpsManager.OP_NONE) { 785 ArrayList<Callback> cbs = mOpModeWatchers.get(op); 786 if (cbs == null) { 787 cbs = new ArrayList<Callback>(); 788 mOpModeWatchers.put(op, cbs); 789 } 790 cbs.add(cb); 791 } 792 if (packageName != null) { 793 ArrayList<Callback> cbs = mPackageModeWatchers.get(packageName); 794 if (cbs == null) { 795 cbs = new ArrayList<Callback>(); 796 mPackageModeWatchers.put(packageName, cbs); 797 } 798 cbs.add(cb); 799 } 800 } 801 } 802 803 @Override 804 public void stopWatchingMode(IAppOpsCallback callback) { 805 synchronized (this) { 806 Callback cb = mModeWatchers.remove(callback.asBinder()); 807 if (cb != null) { 808 cb.unlinkToDeath(); 809 for (int i=mOpModeWatchers.size()-1; i>=0; i--) { 810 ArrayList<Callback> cbs = mOpModeWatchers.valueAt(i); 811 cbs.remove(cb); 812 if (cbs.size() <= 0) { 813 mOpModeWatchers.removeAt(i); 814 } 815 } 816 for (int i=mPackageModeWatchers.size()-1; i>=0; i--) { 817 ArrayList<Callback> cbs = mPackageModeWatchers.valueAt(i); 818 cbs.remove(cb); 819 if (cbs.size() <= 0) { 820 mPackageModeWatchers.removeAt(i); 821 } 822 } 823 } 824 } 825 } 826 827 @Override 828 public IBinder getToken(IBinder clientToken) { 829 synchronized (this) { 830 ClientState cs = mClients.get(clientToken); 831 if (cs == null) { 832 cs = new ClientState(clientToken); 833 mClients.put(clientToken, cs); 834 } 835 return cs; 836 } 837 } 838 839 @Override 840 public int checkOperation(int code, int uid, String packageName) { 841 verifyIncomingUid(uid); 842 verifyIncomingOp(code); 843 synchronized (this) { 844 if (isOpRestricted(uid, code, packageName)) { 845 return AppOpsManager.MODE_IGNORED; 846 } 847 code = AppOpsManager.opToSwitch(code); 848 UidState uidState = getUidStateLocked(uid, false); 849 if (uidState != null && uidState.opModes != null) { 850 final int uidMode = uidState.opModes.get(code); 851 if (uidMode != AppOpsManager.MODE_ALLOWED) { 852 return uidMode; 853 } 854 } 855 Op op = getOpLocked(code, uid, packageName, false); 856 if (op == null) { 857 return AppOpsManager.opToDefaultMode(code); 858 } 859 return op.mode; 860 } 861 } 862 863 @Override 864 public int checkAudioOperation(int code, int usage, int uid, String packageName) { 865 synchronized (this) { 866 final int mode = checkRestrictionLocked(code, usage, uid, packageName); 867 if (mode != AppOpsManager.MODE_ALLOWED) { 868 return mode; 869 } 870 } 871 return checkOperation(code, uid, packageName); 872 } 873 874 private int checkRestrictionLocked(int code, int usage, int uid, String packageName) { 875 final SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code); 876 if (usageRestrictions != null) { 877 final Restriction r = usageRestrictions.get(usage); 878 if (r != null && !r.exceptionPackages.contains(packageName)) { 879 return r.mode; 880 } 881 } 882 return AppOpsManager.MODE_ALLOWED; 883 } 884 885 @Override 886 public void setAudioRestriction(int code, int usage, int uid, int mode, 887 String[] exceptionPackages) { 888 verifyIncomingUid(uid); 889 verifyIncomingOp(code); 890 synchronized (this) { 891 SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code); 892 if (usageRestrictions == null) { 893 usageRestrictions = new SparseArray<Restriction>(); 894 mAudioRestrictions.put(code, usageRestrictions); 895 } 896 usageRestrictions.remove(usage); 897 if (mode != AppOpsManager.MODE_ALLOWED) { 898 final Restriction r = new Restriction(); 899 r.mode = mode; 900 if (exceptionPackages != null) { 901 final int N = exceptionPackages.length; 902 r.exceptionPackages = new ArraySet<String>(N); 903 for (int i = 0; i < N; i++) { 904 final String pkg = exceptionPackages[i]; 905 if (pkg != null) { 906 r.exceptionPackages.add(pkg.trim()); 907 } 908 } 909 } 910 usageRestrictions.put(usage, r); 911 } 912 } 913 } 914 915 @Override 916 public int checkPackage(int uid, String packageName) { 917 synchronized (this) { 918 if (getOpsRawLocked(uid, packageName, true) != null) { 919 return AppOpsManager.MODE_ALLOWED; 920 } else { 921 return AppOpsManager.MODE_ERRORED; 922 } 923 } 924 } 925 926 @Override 927 public int noteProxyOperation(int code, String proxyPackageName, 928 int proxiedUid, String proxiedPackageName) { 929 verifyIncomingOp(code); 930 final int proxyMode = noteOperationUnchecked(code, Binder.getCallingUid(), 931 proxyPackageName, -1, null); 932 if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) { 933 return proxyMode; 934 } 935 return noteOperationUnchecked(code, proxiedUid, proxiedPackageName, 936 Binder.getCallingUid(), proxyPackageName); 937 } 938 939 @Override 940 public int noteOperation(int code, int uid, String packageName) { 941 verifyIncomingUid(uid); 942 verifyIncomingOp(code); 943 return noteOperationUnchecked(code, uid, packageName, 0, null); 944 } 945 946 private int noteOperationUnchecked(int code, int uid, String packageName, 947 int proxyUid, String proxyPackageName) { 948 synchronized (this) { 949 Ops ops = getOpsLocked(uid, packageName, true); 950 if (ops == null) { 951 if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid 952 + " package " + packageName); 953 return AppOpsManager.MODE_ERRORED; 954 } 955 Op op = getOpLocked(ops, code, true); 956 if (isOpRestricted(uid, code, packageName)) { 957 return AppOpsManager.MODE_IGNORED; 958 } 959 if (op.duration == -1) { 960 Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName 961 + " code " + code + " time=" + op.time + " duration=" + op.duration); 962 } 963 op.duration = 0; 964 final int switchCode = AppOpsManager.opToSwitch(code); 965 UidState uidState = ops.uidState; 966 if (uidState.opModes != null) { 967 final int uidMode = uidState.opModes.get(switchCode); 968 if (uidMode != AppOpsManager.MODE_ALLOWED) { 969 if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code " 970 + switchCode + " (" + code + ") uid " + uid + " package " 971 + packageName); 972 op.rejectTime = System.currentTimeMillis(); 973 return uidMode; 974 } 975 } 976 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op; 977 if (switchOp.mode != AppOpsManager.MODE_ALLOWED) { 978 if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code " 979 + switchCode + " (" + code + ") uid " + uid + " package " + packageName); 980 op.rejectTime = System.currentTimeMillis(); 981 return switchOp.mode; 982 } 983 if (DEBUG) Log.d(TAG, "noteOperation: allowing code " + code + " uid " + uid 984 + " package " + packageName); 985 op.time = System.currentTimeMillis(); 986 op.rejectTime = 0; 987 op.proxyUid = proxyUid; 988 op.proxyPackageName = proxyPackageName; 989 return AppOpsManager.MODE_ALLOWED; 990 } 991 } 992 993 @Override 994 public int startOperation(IBinder token, int code, int uid, String packageName) { 995 verifyIncomingUid(uid); 996 verifyIncomingOp(code); 997 ClientState client = (ClientState)token; 998 synchronized (this) { 999 Ops ops = getOpsLocked(uid, packageName, true); 1000 if (ops == null) { 1001 if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid 1002 + " package " + packageName); 1003 return AppOpsManager.MODE_ERRORED; 1004 } 1005 Op op = getOpLocked(ops, code, true); 1006 if (isOpRestricted(uid, code, packageName)) { 1007 return AppOpsManager.MODE_IGNORED; 1008 } 1009 final int switchCode = AppOpsManager.opToSwitch(code); 1010 UidState uidState = ops.uidState; 1011 if (uidState.opModes != null) { 1012 final int uidMode = uidState.opModes.get(switchCode); 1013 if (uidMode != AppOpsManager.MODE_ALLOWED) { 1014 if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code " 1015 + switchCode + " (" + code + ") uid " + uid + " package " 1016 + packageName); 1017 op.rejectTime = System.currentTimeMillis(); 1018 return uidMode; 1019 } 1020 } 1021 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op; 1022 if (switchOp.mode != AppOpsManager.MODE_ALLOWED) { 1023 if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code " 1024 + switchCode + " (" + code + ") uid " + uid + " package " + packageName); 1025 op.rejectTime = System.currentTimeMillis(); 1026 return switchOp.mode; 1027 } 1028 if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid 1029 + " package " + packageName); 1030 if (op.nesting == 0) { 1031 op.time = System.currentTimeMillis(); 1032 op.rejectTime = 0; 1033 op.duration = -1; 1034 } 1035 op.nesting++; 1036 if (client.mStartedOps != null) { 1037 client.mStartedOps.add(op); 1038 } 1039 return AppOpsManager.MODE_ALLOWED; 1040 } 1041 } 1042 1043 @Override 1044 public void finishOperation(IBinder token, int code, int uid, String packageName) { 1045 verifyIncomingUid(uid); 1046 verifyIncomingOp(code); 1047 ClientState client = (ClientState)token; 1048 synchronized (this) { 1049 Op op = getOpLocked(code, uid, packageName, true); 1050 if (op == null) { 1051 return; 1052 } 1053 if (client.mStartedOps != null) { 1054 if (!client.mStartedOps.remove(op)) { 1055 throw new IllegalStateException("Operation not started: uid" + op.uid 1056 + " pkg=" + op.packageName + " op=" + op.op); 1057 } 1058 } 1059 finishOperationLocked(op); 1060 } 1061 } 1062 1063 @Override 1064 public int permissionToOpCode(String permission) { 1065 return AppOpsManager.permissionToOpCode(permission); 1066 } 1067 1068 void finishOperationLocked(Op op) { 1069 if (op.nesting <= 1) { 1070 if (op.nesting == 1) { 1071 op.duration = (int)(System.currentTimeMillis() - op.time); 1072 op.time += op.duration; 1073 } else { 1074 Slog.w(TAG, "Finishing op nesting under-run: uid " + op.uid + " pkg " 1075 + op.packageName + " code " + op.op + " time=" + op.time 1076 + " duration=" + op.duration + " nesting=" + op.nesting); 1077 } 1078 op.nesting = 0; 1079 } else { 1080 op.nesting--; 1081 } 1082 } 1083 1084 private void verifyIncomingUid(int uid) { 1085 if (uid == Binder.getCallingUid()) { 1086 return; 1087 } 1088 if (Binder.getCallingPid() == Process.myPid()) { 1089 return; 1090 } 1091 mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 1092 Binder.getCallingPid(), Binder.getCallingUid(), null); 1093 } 1094 1095 private void verifyIncomingOp(int op) { 1096 if (op >= 0 && op < AppOpsManager._NUM_OP) { 1097 return; 1098 } 1099 throw new IllegalArgumentException("Bad operation #" + op); 1100 } 1101 1102 private UidState getUidStateLocked(int uid, boolean edit) { 1103 UidState uidState = mUidStates.get(uid); 1104 if (uidState == null) { 1105 if (!edit) { 1106 return null; 1107 } 1108 uidState = new UidState(uid); 1109 mUidStates.put(uid, uidState); 1110 } 1111 return uidState; 1112 } 1113 1114 private Ops getOpsLocked(int uid, String packageName, boolean edit) { 1115 if (uid == 0) { 1116 packageName = "root"; 1117 } else if (uid == Process.SHELL_UID) { 1118 packageName = "com.android.shell"; 1119 } 1120 return getOpsRawLocked(uid, packageName, edit); 1121 } 1122 1123 private Ops getOpsRawLocked(int uid, String packageName, boolean edit) { 1124 UidState uidState = getUidStateLocked(uid, edit); 1125 if (uidState == null) { 1126 return null; 1127 } 1128 1129 if (uidState.pkgOps == null) { 1130 if (!edit) { 1131 return null; 1132 } 1133 uidState.pkgOps = new ArrayMap<>(); 1134 } 1135 1136 Ops ops = uidState.pkgOps.get(packageName); 1137 if (ops == null) { 1138 if (!edit) { 1139 return null; 1140 } 1141 boolean isPrivileged = false; 1142 // This is the first time we have seen this package name under this uid, 1143 // so let's make sure it is valid. 1144 if (uid != 0) { 1145 final long ident = Binder.clearCallingIdentity(); 1146 try { 1147 int pkgUid = -1; 1148 try { 1149 ApplicationInfo appInfo = ActivityThread.getPackageManager() 1150 .getApplicationInfo(packageName, 0, UserHandle.getUserId(uid)); 1151 if (appInfo != null) { 1152 pkgUid = appInfo.uid; 1153 isPrivileged = (appInfo.privateFlags 1154 & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; 1155 } else { 1156 if ("media".equals(packageName)) { 1157 pkgUid = Process.MEDIA_UID; 1158 isPrivileged = false; 1159 } 1160 } 1161 } catch (RemoteException e) { 1162 Slog.w(TAG, "Could not contact PackageManager", e); 1163 } 1164 if (pkgUid != uid) { 1165 // Oops! The package name is not valid for the uid they are calling 1166 // under. Abort. 1167 Slog.w(TAG, "Bad call: specified package " + packageName 1168 + " under uid " + uid + " but it is really " + pkgUid); 1169 return null; 1170 } 1171 } finally { 1172 Binder.restoreCallingIdentity(ident); 1173 } 1174 } 1175 ops = new Ops(packageName, uidState, isPrivileged); 1176 uidState.pkgOps.put(packageName, ops); 1177 } 1178 return ops; 1179 } 1180 1181 private void scheduleWriteLocked() { 1182 if (!mWriteScheduled) { 1183 mWriteScheduled = true; 1184 mHandler.postDelayed(mWriteRunner, WRITE_DELAY); 1185 } 1186 } 1187 1188 private void scheduleFastWriteLocked() { 1189 if (!mFastWriteScheduled) { 1190 mWriteScheduled = true; 1191 mFastWriteScheduled = true; 1192 mHandler.removeCallbacks(mWriteRunner); 1193 mHandler.postDelayed(mWriteRunner, 10*1000); 1194 } 1195 } 1196 1197 private Op getOpLocked(int code, int uid, String packageName, boolean edit) { 1198 Ops ops = getOpsLocked(uid, packageName, edit); 1199 if (ops == null) { 1200 return null; 1201 } 1202 return getOpLocked(ops, code, edit); 1203 } 1204 1205 private Op getOpLocked(Ops ops, int code, boolean edit) { 1206 Op op = ops.get(code); 1207 if (op == null) { 1208 if (!edit) { 1209 return null; 1210 } 1211 op = new Op(ops.uidState.uid, ops.packageName, code); 1212 ops.put(code, op); 1213 } 1214 if (edit) { 1215 scheduleWriteLocked(); 1216 } 1217 return op; 1218 } 1219 1220 private boolean isOpRestricted(int uid, int code, String packageName) { 1221 int userHandle = UserHandle.getUserId(uid); 1222 boolean[] opRestrictions = mOpRestrictions.get(userHandle); 1223 if ((opRestrictions != null) && opRestrictions[code]) { 1224 if (AppOpsManager.opAllowSystemBypassRestriction(code)) { 1225 synchronized (this) { 1226 Ops ops = getOpsLocked(uid, packageName, true); 1227 if ((ops != null) && ops.isPrivileged) { 1228 return false; 1229 } 1230 } 1231 } 1232 return true; 1233 } 1234 return false; 1235 } 1236 1237 void readState() { 1238 synchronized (mFile) { 1239 synchronized (this) { 1240 FileInputStream stream; 1241 try { 1242 stream = mFile.openRead(); 1243 } catch (FileNotFoundException e) { 1244 Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty"); 1245 return; 1246 } 1247 boolean success = false; 1248 mUidStates.clear(); 1249 try { 1250 XmlPullParser parser = Xml.newPullParser(); 1251 parser.setInput(stream, StandardCharsets.UTF_8.name()); 1252 int type; 1253 while ((type = parser.next()) != XmlPullParser.START_TAG 1254 && type != XmlPullParser.END_DOCUMENT) { 1255 ; 1256 } 1257 1258 if (type != XmlPullParser.START_TAG) { 1259 throw new IllegalStateException("no start tag found"); 1260 } 1261 1262 int outerDepth = parser.getDepth(); 1263 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 1264 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 1265 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 1266 continue; 1267 } 1268 1269 String tagName = parser.getName(); 1270 if (tagName.equals("pkg")) { 1271 readPackage(parser); 1272 } else if (tagName.equals("uid")) { 1273 readUidOps(parser); 1274 } else { 1275 Slog.w(TAG, "Unknown element under <app-ops>: " 1276 + parser.getName()); 1277 XmlUtils.skipCurrentTag(parser); 1278 } 1279 } 1280 success = true; 1281 } catch (IllegalStateException e) { 1282 Slog.w(TAG, "Failed parsing " + e); 1283 } catch (NullPointerException e) { 1284 Slog.w(TAG, "Failed parsing " + e); 1285 } catch (NumberFormatException e) { 1286 Slog.w(TAG, "Failed parsing " + e); 1287 } catch (XmlPullParserException e) { 1288 Slog.w(TAG, "Failed parsing " + e); 1289 } catch (IOException e) { 1290 Slog.w(TAG, "Failed parsing " + e); 1291 } catch (IndexOutOfBoundsException e) { 1292 Slog.w(TAG, "Failed parsing " + e); 1293 } finally { 1294 if (!success) { 1295 mUidStates.clear(); 1296 } 1297 try { 1298 stream.close(); 1299 } catch (IOException e) { 1300 } 1301 } 1302 } 1303 } 1304 } 1305 1306 void readUidOps(XmlPullParser parser) throws NumberFormatException, 1307 XmlPullParserException, IOException { 1308 final int uid = Integer.parseInt(parser.getAttributeValue(null, "n")); 1309 int outerDepth = parser.getDepth(); 1310 int type; 1311 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 1312 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 1313 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 1314 continue; 1315 } 1316 1317 String tagName = parser.getName(); 1318 if (tagName.equals("op")) { 1319 final int code = Integer.parseInt(parser.getAttributeValue(null, "n")); 1320 final int mode = Integer.parseInt(parser.getAttributeValue(null, "m")); 1321 UidState uidState = getUidStateLocked(uid, true); 1322 if (uidState.opModes == null) { 1323 uidState.opModes = new SparseIntArray(); 1324 } 1325 uidState.opModes.put(code, mode); 1326 } else { 1327 Slog.w(TAG, "Unknown element under <uid-ops>: " 1328 + parser.getName()); 1329 XmlUtils.skipCurrentTag(parser); 1330 } 1331 } 1332 } 1333 1334 void readPackage(XmlPullParser parser) throws NumberFormatException, 1335 XmlPullParserException, IOException { 1336 String pkgName = parser.getAttributeValue(null, "n"); 1337 int outerDepth = parser.getDepth(); 1338 int type; 1339 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 1340 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 1341 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 1342 continue; 1343 } 1344 1345 String tagName = parser.getName(); 1346 if (tagName.equals("uid")) { 1347 readUid(parser, pkgName); 1348 } else { 1349 Slog.w(TAG, "Unknown element under <pkg>: " 1350 + parser.getName()); 1351 XmlUtils.skipCurrentTag(parser); 1352 } 1353 } 1354 } 1355 1356 void readUid(XmlPullParser parser, String pkgName) throws NumberFormatException, 1357 XmlPullParserException, IOException { 1358 int uid = Integer.parseInt(parser.getAttributeValue(null, "n")); 1359 String isPrivilegedString = parser.getAttributeValue(null, "p"); 1360 boolean isPrivileged = false; 1361 if (isPrivilegedString == null) { 1362 try { 1363 IPackageManager packageManager = ActivityThread.getPackageManager(); 1364 if (packageManager != null) { 1365 ApplicationInfo appInfo = ActivityThread.getPackageManager() 1366 .getApplicationInfo(pkgName, 0, UserHandle.getUserId(uid)); 1367 if (appInfo != null) { 1368 isPrivileged = (appInfo.privateFlags 1369 & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; 1370 } 1371 } else { 1372 // Could not load data, don't add to cache so it will be loaded later. 1373 return; 1374 } 1375 } catch (RemoteException e) { 1376 Slog.w(TAG, "Could not contact PackageManager", e); 1377 } 1378 } else { 1379 isPrivileged = Boolean.parseBoolean(isPrivilegedString); 1380 } 1381 int outerDepth = parser.getDepth(); 1382 int type; 1383 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 1384 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 1385 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 1386 continue; 1387 } 1388 1389 String tagName = parser.getName(); 1390 if (tagName.equals("op")) { 1391 Op op = new Op(uid, pkgName, Integer.parseInt(parser.getAttributeValue(null, "n"))); 1392 String mode = parser.getAttributeValue(null, "m"); 1393 if (mode != null) { 1394 op.mode = Integer.parseInt(mode); 1395 } 1396 String time = parser.getAttributeValue(null, "t"); 1397 if (time != null) { 1398 op.time = Long.parseLong(time); 1399 } 1400 time = parser.getAttributeValue(null, "r"); 1401 if (time != null) { 1402 op.rejectTime = Long.parseLong(time); 1403 } 1404 String dur = parser.getAttributeValue(null, "d"); 1405 if (dur != null) { 1406 op.duration = Integer.parseInt(dur); 1407 } 1408 String proxyUid = parser.getAttributeValue(null, "pu"); 1409 if (proxyUid != null) { 1410 op.proxyUid = Integer.parseInt(proxyUid); 1411 } 1412 String proxyPackageName = parser.getAttributeValue(null, "pp"); 1413 if (proxyPackageName != null) { 1414 op.proxyPackageName = proxyPackageName; 1415 } 1416 1417 UidState uidState = getUidStateLocked(uid, true); 1418 if (uidState.pkgOps == null) { 1419 uidState.pkgOps = new ArrayMap<>(); 1420 } 1421 1422 Ops ops = uidState.pkgOps.get(pkgName); 1423 if (ops == null) { 1424 ops = new Ops(pkgName, uidState, isPrivileged); 1425 uidState.pkgOps.put(pkgName, ops); 1426 } 1427 ops.put(op.op, op); 1428 } else { 1429 Slog.w(TAG, "Unknown element under <pkg>: " 1430 + parser.getName()); 1431 XmlUtils.skipCurrentTag(parser); 1432 } 1433 } 1434 } 1435 1436 void writeState() { 1437 synchronized (mFile) { 1438 List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null); 1439 1440 FileOutputStream stream; 1441 try { 1442 stream = mFile.startWrite(); 1443 } catch (IOException e) { 1444 Slog.w(TAG, "Failed to write state: " + e); 1445 return; 1446 } 1447 1448 try { 1449 XmlSerializer out = new FastXmlSerializer(); 1450 out.setOutput(stream, StandardCharsets.UTF_8.name()); 1451 out.startDocument(null, true); 1452 out.startTag(null, "app-ops"); 1453 1454 final int uidStateCount = mUidStates.size(); 1455 for (int i = 0; i < uidStateCount; i++) { 1456 UidState uidState = mUidStates.valueAt(i); 1457 if (uidState.opModes != null && uidState.opModes.size() > 0) { 1458 out.startTag(null, "uid"); 1459 out.attribute(null, "n", Integer.toString(uidState.uid)); 1460 SparseIntArray uidOpModes = uidState.opModes; 1461 final int opCount = uidOpModes.size(); 1462 for (int j = 0; j < opCount; j++) { 1463 final int op = uidOpModes.keyAt(j); 1464 final int mode = uidOpModes.valueAt(j); 1465 out.startTag(null, "op"); 1466 out.attribute(null, "n", Integer.toString(op)); 1467 out.attribute(null, "m", Integer.toString(mode)); 1468 out.endTag(null, "op"); 1469 } 1470 out.endTag(null, "uid"); 1471 } 1472 } 1473 1474 if (allOps != null) { 1475 String lastPkg = null; 1476 for (int i=0; i<allOps.size(); i++) { 1477 AppOpsManager.PackageOps pkg = allOps.get(i); 1478 if (!pkg.getPackageName().equals(lastPkg)) { 1479 if (lastPkg != null) { 1480 out.endTag(null, "pkg"); 1481 } 1482 lastPkg = pkg.getPackageName(); 1483 out.startTag(null, "pkg"); 1484 out.attribute(null, "n", lastPkg); 1485 } 1486 out.startTag(null, "uid"); 1487 out.attribute(null, "n", Integer.toString(pkg.getUid())); 1488 synchronized (this) { 1489 Ops ops = getOpsLocked(pkg.getUid(), pkg.getPackageName(), false); 1490 // Should always be present as the list of PackageOps is generated 1491 // from Ops. 1492 if (ops != null) { 1493 out.attribute(null, "p", Boolean.toString(ops.isPrivileged)); 1494 } else { 1495 out.attribute(null, "p", Boolean.toString(false)); 1496 } 1497 } 1498 List<AppOpsManager.OpEntry> ops = pkg.getOps(); 1499 for (int j=0; j<ops.size(); j++) { 1500 AppOpsManager.OpEntry op = ops.get(j); 1501 out.startTag(null, "op"); 1502 out.attribute(null, "n", Integer.toString(op.getOp())); 1503 if (op.getMode() != AppOpsManager.opToDefaultMode(op.getOp())) { 1504 out.attribute(null, "m", Integer.toString(op.getMode())); 1505 } 1506 long time = op.getTime(); 1507 if (time != 0) { 1508 out.attribute(null, "t", Long.toString(time)); 1509 } 1510 time = op.getRejectTime(); 1511 if (time != 0) { 1512 out.attribute(null, "r", Long.toString(time)); 1513 } 1514 int dur = op.getDuration(); 1515 if (dur != 0) { 1516 out.attribute(null, "d", Integer.toString(dur)); 1517 } 1518 int proxyUid = op.getProxyUid(); 1519 if (proxyUid != -1) { 1520 out.attribute(null, "pu", Integer.toString(proxyUid)); 1521 } 1522 String proxyPackageName = op.getProxyPackageName(); 1523 if (proxyPackageName != null) { 1524 out.attribute(null, "pp", proxyPackageName); 1525 } 1526 out.endTag(null, "op"); 1527 } 1528 out.endTag(null, "uid"); 1529 } 1530 if (lastPkg != null) { 1531 out.endTag(null, "pkg"); 1532 } 1533 } 1534 1535 out.endTag(null, "app-ops"); 1536 out.endDocument(); 1537 mFile.finishWrite(stream); 1538 } catch (IOException e) { 1539 Slog.w(TAG, "Failed to write state, restoring backup.", e); 1540 mFile.failWrite(stream); 1541 } 1542 } 1543 } 1544 1545 private void dumpHelp(PrintWriter pw) { 1546 pw.println("AppOps service (appops) dump options:"); 1547 pw.println(" [-h] [CMD]"); 1548 pw.println(" -h: print this help text."); 1549 pw.println("Commands:"); 1550 pw.println(" write-settings"); 1551 pw.println(" Immediately write pending changes to storage."); 1552 pw.println(" read-settings"); 1553 pw.println(" Read the last written settings, replacing current state in RAM."); 1554 } 1555 1556 @Override 1557 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1558 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1559 != PackageManager.PERMISSION_GRANTED) { 1560 pw.println("Permission Denial: can't dump ApOps service from from pid=" 1561 + Binder.getCallingPid() 1562 + ", uid=" + Binder.getCallingUid()); 1563 return; 1564 } 1565 1566 if (args != null) { 1567 for (int i=0; i<args.length; i++) { 1568 String arg = args[i]; 1569 if ("-h".equals(arg)) { 1570 dumpHelp(pw); 1571 return; 1572 } else if ("-a".equals(arg)) { 1573 // dump all data 1574 } else if ("write-settings".equals(arg)) { 1575 long token = Binder.clearCallingIdentity(); 1576 try { 1577 synchronized (this) { 1578 mHandler.removeCallbacks(mWriteRunner); 1579 } 1580 writeState(); 1581 pw.println("Current settings written."); 1582 } finally { 1583 Binder.restoreCallingIdentity(token); 1584 } 1585 return; 1586 } else if ("read-settings".equals(arg)) { 1587 long token = Binder.clearCallingIdentity(); 1588 try { 1589 readState(); 1590 pw.println("Last settings read."); 1591 } finally { 1592 Binder.restoreCallingIdentity(token); 1593 } 1594 return; 1595 } else if (arg.length() > 0 && arg.charAt(0) == '-'){ 1596 pw.println("Unknown option: " + arg); 1597 return; 1598 } else { 1599 pw.println("Unknown command: " + arg); 1600 return; 1601 } 1602 } 1603 } 1604 1605 synchronized (this) { 1606 pw.println("Current AppOps Service state:"); 1607 final long now = System.currentTimeMillis(); 1608 boolean needSep = false; 1609 if (mOpModeWatchers.size() > 0) { 1610 needSep = true; 1611 pw.println(" Op mode watchers:"); 1612 for (int i=0; i<mOpModeWatchers.size(); i++) { 1613 pw.print(" Op "); pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i))); 1614 pw.println(":"); 1615 ArrayList<Callback> callbacks = mOpModeWatchers.valueAt(i); 1616 for (int j=0; j<callbacks.size(); j++) { 1617 pw.print(" #"); pw.print(j); pw.print(": "); 1618 pw.println(callbacks.get(j)); 1619 } 1620 } 1621 } 1622 if (mPackageModeWatchers.size() > 0) { 1623 needSep = true; 1624 pw.println(" Package mode watchers:"); 1625 for (int i=0; i<mPackageModeWatchers.size(); i++) { 1626 pw.print(" Pkg "); pw.print(mPackageModeWatchers.keyAt(i)); 1627 pw.println(":"); 1628 ArrayList<Callback> callbacks = mPackageModeWatchers.valueAt(i); 1629 for (int j=0; j<callbacks.size(); j++) { 1630 pw.print(" #"); pw.print(j); pw.print(": "); 1631 pw.println(callbacks.get(j)); 1632 } 1633 } 1634 } 1635 if (mModeWatchers.size() > 0) { 1636 needSep = true; 1637 pw.println(" All mode watchers:"); 1638 for (int i=0; i<mModeWatchers.size(); i++) { 1639 pw.print(" "); pw.print(mModeWatchers.keyAt(i)); 1640 pw.print(" -> "); pw.println(mModeWatchers.valueAt(i)); 1641 } 1642 } 1643 if (mClients.size() > 0) { 1644 needSep = true; 1645 pw.println(" Clients:"); 1646 for (int i=0; i<mClients.size(); i++) { 1647 pw.print(" "); pw.print(mClients.keyAt(i)); pw.println(":"); 1648 ClientState cs = mClients.valueAt(i); 1649 pw.print(" "); pw.println(cs); 1650 if (cs.mStartedOps != null && cs.mStartedOps.size() > 0) { 1651 pw.println(" Started ops:"); 1652 for (int j=0; j<cs.mStartedOps.size(); j++) { 1653 Op op = cs.mStartedOps.get(j); 1654 pw.print(" "); pw.print("uid="); pw.print(op.uid); 1655 pw.print(" pkg="); pw.print(op.packageName); 1656 pw.print(" op="); pw.println(AppOpsManager.opToName(op.op)); 1657 } 1658 } 1659 } 1660 } 1661 if (mAudioRestrictions.size() > 0) { 1662 boolean printedHeader = false; 1663 for (int o=0; o<mAudioRestrictions.size(); o++) { 1664 final String op = AppOpsManager.opToName(mAudioRestrictions.keyAt(o)); 1665 final SparseArray<Restriction> restrictions = mAudioRestrictions.valueAt(o); 1666 for (int i=0; i<restrictions.size(); i++) { 1667 if (!printedHeader){ 1668 pw.println(" Audio Restrictions:"); 1669 printedHeader = true; 1670 needSep = true; 1671 } 1672 final int usage = restrictions.keyAt(i); 1673 pw.print(" "); pw.print(op); 1674 pw.print(" usage="); pw.print(AudioAttributes.usageToString(usage)); 1675 Restriction r = restrictions.valueAt(i); 1676 pw.print(": mode="); pw.println(r.mode); 1677 if (!r.exceptionPackages.isEmpty()) { 1678 pw.println(" Exceptions:"); 1679 for (int j=0; j<r.exceptionPackages.size(); j++) { 1680 pw.print(" "); pw.println(r.exceptionPackages.valueAt(j)); 1681 } 1682 } 1683 } 1684 } 1685 } 1686 if (needSep) { 1687 pw.println(); 1688 } 1689 for (int i=0; i<mUidStates.size(); i++) { 1690 UidState uidState = mUidStates.valueAt(i); 1691 1692 pw.print(" Uid "); UserHandle.formatUid(pw, uidState.uid); pw.println(":"); 1693 1694 SparseIntArray opModes = uidState.opModes; 1695 if (opModes != null) { 1696 final int opModeCount = opModes.size(); 1697 for (int j = 0; j < opModeCount; j++) { 1698 final int code = opModes.keyAt(j); 1699 final int mode = opModes.valueAt(j); 1700 pw.print(" "); pw.print(AppOpsManager.opToName(code)); 1701 pw.print(": mode="); pw.println(mode); 1702 } 1703 } 1704 1705 ArrayMap<String, Ops> pkgOps = uidState.pkgOps; 1706 if (pkgOps == null) { 1707 continue; 1708 } 1709 1710 for (Ops ops : pkgOps.values()) { 1711 pw.print(" Package "); pw.print(ops.packageName); pw.println(":"); 1712 for (int j=0; j<ops.size(); j++) { 1713 Op op = ops.valueAt(j); 1714 pw.print(" "); pw.print(AppOpsManager.opToName(op.op)); 1715 pw.print(": mode="); pw.print(op.mode); 1716 if (op.time != 0) { 1717 pw.print("; time="); TimeUtils.formatDuration(now-op.time, pw); 1718 pw.print(" ago"); 1719 } 1720 if (op.rejectTime != 0) { 1721 pw.print("; rejectTime="); TimeUtils.formatDuration(now-op.rejectTime, pw); 1722 pw.print(" ago"); 1723 } 1724 if (op.duration == -1) { 1725 pw.print(" (running)"); 1726 } else if (op.duration != 0) { 1727 pw.print("; duration="); TimeUtils.formatDuration(op.duration, pw); 1728 } 1729 pw.println(); 1730 } 1731 } 1732 } 1733 } 1734 } 1735 1736 private static final class Restriction { 1737 private static final ArraySet<String> NO_EXCEPTIONS = new ArraySet<String>(); 1738 int mode; 1739 ArraySet<String> exceptionPackages = NO_EXCEPTIONS; 1740 } 1741 1742 @Override 1743 public void setUserRestrictions(Bundle restrictions, int userHandle) throws RemoteException { 1744 checkSystemUid("setUserRestrictions"); 1745 boolean[] opRestrictions = mOpRestrictions.get(userHandle); 1746 if (opRestrictions == null) { 1747 opRestrictions = new boolean[AppOpsManager._NUM_OP]; 1748 mOpRestrictions.put(userHandle, opRestrictions); 1749 } 1750 for (int i = 0; i < opRestrictions.length; ++i) { 1751 String restriction = AppOpsManager.opToRestriction(i); 1752 if (restriction != null) { 1753 opRestrictions[i] = restrictions.getBoolean(restriction, false); 1754 } else { 1755 opRestrictions[i] = false; 1756 } 1757 } 1758 } 1759 1760 @Override 1761 public void removeUser(int userHandle) throws RemoteException { 1762 checkSystemUid("removeUser"); 1763 mOpRestrictions.remove(userHandle); 1764 } 1765 1766 private void checkSystemUid(String function) { 1767 int uid = Binder.getCallingUid(); 1768 if (uid != Process.SYSTEM_UID) { 1769 throw new SecurityException(function + " must by called by the system"); 1770 } 1771 } 1772 1773 private static String[] getPackagesForUid(int uid) { 1774 String[] packageNames = null; 1775 try { 1776 packageNames= AppGlobals.getPackageManager().getPackagesForUid(uid); 1777 } catch (RemoteException e) { 1778 /* ignore - local call */ 1779 } 1780 if (packageNames == null) { 1781 return EmptyArray.STRING; 1782 } 1783 return packageNames; 1784 } 1785 } 1786