Guest User

Untitled

a guest
Oct 19th, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 58.07 KB | None | 0 0
  1. diff --cc services/core/java/com/android/server/AppOpsService.java
  2. index 786d757557d,2a7c9d66a7c..00000000000
  3. --- a/services/core/java/com/android/server/AppOpsService.java
  4. +++ b/services/core/java/com/android/server/AppOpsService.java
  5. @@@ -17,13 -20,15 +20,18 @@@
  6. package com.android.server;
  7.  
  8. import android.Manifest;
  9. --import android.app.ActivityManager;
  10. import android.app.ActivityThread;
  11. import android.app.AppGlobals;
  12. import android.app.AppOpsManager;
  13. +import android.app.AppOpsManagerInternal;
  14. ++import android.app.Dialog;
  15. ++import android.content.BroadcastReceiver;
  16. +import android.content.ContentResolver;
  17. + import android.app.Dialog;
  18. + import android.content.BroadcastReceiver;
  19. import android.content.Context;
  20. + import android.content.Intent;
  21. + import android.content.IntentFilter;
  22. import android.content.pm.ApplicationInfo;
  23. import android.content.pm.IPackageManager;
  24. import android.content.pm.PackageManager;
  25. @@@ -69,7 -69,7 +79,8 @@@ import com.android.internal.util.DumpUt
  26. import com.android.internal.util.FastXmlSerializer;
  27. import com.android.internal.util.Preconditions;
  28. import com.android.internal.util.XmlUtils;
  29. +import com.android.internal.util.function.pooled.PooledLambda;
  30. + import com.android.server.PermissionDialogReqQueue.PermissionDialogReq;
  31.  
  32. import libcore.util.EmptyArray;
  33.  
  34. @@@ -116,67 -100,17 +127,73 @@@ public class AppOpsService extends IApp
  35. // Write at most every 30 minutes.
  36. static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000;
  37.  
  38. + // Constant meaning that any UID should be matched when dispatching callbacks
  39. + private static final int UID_ANY = -2;
  40. +
  41. + // Map from process states to the uid states we track.
  42. + private static final int[] PROCESS_STATE_TO_UID_STATE = new int[] {
  43. + UID_STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT
  44. + UID_STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
  45. + UID_STATE_TOP, // ActivityManager.PROCESS_STATE_TOP
  46. + UID_STATE_FOREGROUND_SERVICE, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
  47. + UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
  48. + UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
  49. + UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
  50. + UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
  51. + UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_BACKUP
  52. + UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_SERVICE
  53. + UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_RECEIVER
  54. + UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_TOP_SLEEPING
  55. + UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
  56. + UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_HOME
  57. + UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
  58. + UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
  59. + UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
  60. + UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_RECENT
  61. + UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_EMPTY
  62. + UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_NONEXISTENT
  63. + };
  64. +
  65. + static final String[] UID_STATE_NAMES = new String[] {
  66. + "pers ", // UID_STATE_PERSISTENT
  67. + "top ", // UID_STATE_TOP
  68. + "fgsvc", // UID_STATE_FOREGROUND_SERVICE
  69. + "fg ", // UID_STATE_FOREGROUND
  70. + "bg ", // UID_STATE_BACKGROUND
  71. + "cch ", // UID_STATE_CACHED
  72. + };
  73. +
  74. + static final String[] UID_STATE_TIME_ATTRS = new String[] {
  75. + "tp", // UID_STATE_PERSISTENT
  76. + "tt", // UID_STATE_TOP
  77. - "tfs", // UID_STATE_FOREGROUND_SERVICE
  78. - "tf", // UID_STATE_FOREGROUND
  79. ++ "tf", // UID_STATE_FOREGROUND
  80. + "tb", // UID_STATE_BACKGROUND
  81. + "tc", // UID_STATE_CACHED
  82. + };
  83. +
  84. + static final String[] UID_STATE_REJECT_ATTRS = new String[] {
  85. + "rp", // UID_STATE_PERSISTENT
  86. + "rt", // UID_STATE_TOP
  87. + "rfs", // UID_STATE_FOREGROUND_SERVICE
  88. + "rf", // UID_STATE_FOREGROUND
  89. + "rb", // UID_STATE_BACKGROUND
  90. + "rc", // UID_STATE_CACHED
  91. + };
  92. +
  93. + // Location of policy file.
  94. + static final String DEFAULT_POLICY_FILE = "/system/etc/appops_policy.xml";
  95. +
  96. Context mContext;
  97. final AtomicFile mFile;
  98. final Handler mHandler;
  99. + final Looper mLooper;
  100. + final boolean mStrictEnable;
  101. + AppOpsPolicy mPolicy;
  102. + private PowerManager mPowerManager;
  103.  
  104. + private final AppOpsManagerInternalImpl mAppOpsManagerInternal
  105. + = new AppOpsManagerInternalImpl();
  106. +
  107. boolean mWriteScheduled;
  108. boolean mFastWriteScheduled;
  109. final Runnable mWriteRunner = new Runnable() {
  110. @@@ -205,109 -136,17 +222,117 @@@
  111. */
  112. private final ArrayMap<IBinder, ClientRestrictionState> mOpUserRestrictions = new ArrayMap<>();
  113.  
  114. + SparseIntArray mProfileOwners;
  115. +
  116. + private Runnable mSuSessionChangedRunner = new Runnable() {
  117. + @Override
  118. + public void run() {
  119. + mContext.sendBroadcastAsUser(new Intent(AppOpsManager.ACTION_SU_SESSION_CHANGED),
  120. + UserHandle.ALL);
  121. + }
  122. + };
  123. +
  124. + /**
  125. + * All times are in milliseconds. These constants are kept synchronized with the system
  126. + * global Settings. Any access to this class or its fields should be done while
  127. + * holding the AppOpsService lock.
  128. + */
  129. + private final class Constants extends ContentObserver {
  130. + // Key names stored in the settings value.
  131. + private static final String KEY_TOP_STATE_SETTLE_TIME = "top_state_settle_time";
  132. + private static final String KEY_FG_SERVICE_STATE_SETTLE_TIME
  133. + = "fg_service_state_settle_time";
  134. + private static final String KEY_BG_STATE_SETTLE_TIME = "bg_state_settle_time";
  135. +
  136. + /**
  137. + * How long we want for a drop in uid state from top to settle before applying it.
  138. + * @see Settings.Global#APP_OPS_CONSTANTS
  139. + * @see #KEY_TOP_STATE_SETTLE_TIME
  140. + */
  141. + public long TOP_STATE_SETTLE_TIME;
  142. +
  143. + /**
  144. + * How long we want for a drop in uid state from foreground to settle before applying it.
  145. + * @see Settings.Global#APP_OPS_CONSTANTS
  146. + * @see #KEY_FG_SERVICE_STATE_SETTLE_TIME
  147. + */
  148. + public long FG_SERVICE_STATE_SETTLE_TIME;
  149. +
  150. + /**
  151. + * How long we want for a drop in uid state from background to settle before applying it.
  152. + * @see Settings.Global#APP_OPS_CONSTANTS
  153. + * @see #KEY_BG_STATE_SETTLE_TIME
  154. + */
  155. + public long BG_STATE_SETTLE_TIME;
  156. +
  157. + private final KeyValueListParser mParser = new KeyValueListParser(',');
  158. + private ContentResolver mResolver;
  159. +
  160. + public Constants(Handler handler) {
  161. + super(handler);
  162. + updateConstants();
  163. + }
  164. +
  165. + public void startMonitoring(ContentResolver resolver) {
  166. + mResolver = resolver;
  167. + mResolver.registerContentObserver(
  168. + Settings.Global.getUriFor(Settings.Global.APP_OPS_CONSTANTS),
  169. + false, this);
  170. + updateConstants();
  171. + }
  172. +
  173. + @Override
  174. + public void onChange(boolean selfChange, Uri uri) {
  175. + updateConstants();
  176. + }
  177.  
  178. - private static final class UidState {
  179. + private void updateConstants() {
  180. + String value = mResolver != null ? Settings.Global.getString(mResolver,
  181. + Settings.Global.APP_OPS_CONSTANTS) : "";
  182. +
  183. + synchronized (AppOpsService.this) {
  184. + try {
  185. + mParser.setString(value);
  186. + } catch (IllegalArgumentException e) {
  187. + // Failed to parse the settings string, log this and move on
  188. + // with defaults.
  189. + Slog.e(TAG, "Bad app ops settings", e);
  190. + }
  191. + TOP_STATE_SETTLE_TIME = mParser.getDurationMillis(
  192. + KEY_TOP_STATE_SETTLE_TIME, 30 * 1000L);
  193. + FG_SERVICE_STATE_SETTLE_TIME = mParser.getDurationMillis(
  194. + KEY_FG_SERVICE_STATE_SETTLE_TIME, 10 * 1000L);
  195. + BG_STATE_SETTLE_TIME = mParser.getDurationMillis(
  196. + KEY_BG_STATE_SETTLE_TIME, 1 * 1000L);
  197. + }
  198. + }
  199. +
  200. + void dump(PrintWriter pw) {
  201. + pw.println(" Settings:");
  202. +
  203. + pw.print(" "); pw.print(KEY_TOP_STATE_SETTLE_TIME); pw.print("=");
  204. + TimeUtils.formatDuration(TOP_STATE_SETTLE_TIME, pw);
  205. + pw.println();
  206. + pw.print(" "); pw.print(KEY_FG_SERVICE_STATE_SETTLE_TIME); pw.print("=");
  207. + TimeUtils.formatDuration(FG_SERVICE_STATE_SETTLE_TIME, pw);
  208. + pw.println();
  209. + pw.print(" "); pw.print(KEY_BG_STATE_SETTLE_TIME); pw.print("=");
  210. + TimeUtils.formatDuration(BG_STATE_SETTLE_TIME, pw);
  211. + pw.println();
  212. + }
  213. + }
  214. +
  215. + private final Constants mConstants;
  216. +
  217. + @VisibleForTesting
  218. + static final class UidState {
  219. public final int uid;
  220. +
  221. + public int state = UID_STATE_CACHED;
  222. + public int pendingState = UID_STATE_CACHED;
  223. + public long pendingStateCommitTime;
  224. +
  225. + public int startNesting;
  226. public ArrayMap<String, Ops> pkgOps;
  227. public SparseIntArray opModes;
  228.  
  229. @@@ -395,65 -177,45 +420,74 @@@
  230. }
  231. }
  232.  
  233. - public final static class Op {
  234. - public final int uid;
  235. - public final String packageName;
  236. - public int proxyUid = -1;
  237. - public String proxyPackageName;
  238. - public final int op;
  239. - public int mode;
  240. - public int duration;
  241. - public long time;
  242. - public long rejectTime;
  243. - public int nesting;
  244. + final static class Op {
  245. + final UidState uidState;
  246. + final int uid;
  247. + final String packageName;
  248. + final int op;
  249. + int proxyUid = -1;
  250. + String proxyPackageName;
  251. + int mode;
  252. + int duration;
  253. + long time[] = new long[_NUM_UID_STATE];
  254. + long rejectTime[] = new long[_NUM_UID_STATE];
  255. + int startNesting;
  256. + long startRealtime;
  257. -
  258. - Op(UidState _uidState, String _packageName, int _op) {
  259. + public int noteOpCount;
  260. + public int startOpCount;
  261. + public PermissionDialogReqQueue dialogReqQueue;
  262. + final ArrayList<IBinder> clientTokens;
  263. + public int allowedCount;
  264. + public int ignoredCount;
  265. + public int delayedCount;
  266. +
  267. - public Op(int _uid, String _packageName, int _op, int _mode) {
  268. - uid = _uid;
  269. ++ Op(UidState _uidState, String _packageName, int _op, int _mode) {
  270. + uidState = _uidState;
  271. + uid = _uidState.uid;
  272. packageName = _packageName;
  273. op = _op;
  274. - mode = AppOpsManager.opToDefaultMode(op);
  275. + mode = _mode;
  276. + dialogReqQueue = new PermissionDialogReqQueue();
  277. + clientTokens = new ArrayList<IBinder>();
  278. }
  279. +
  280. + boolean hasAnyTime() {
  281. + for (int i = 0; i < AppOpsManager._NUM_UID_STATE; i++) {
  282. + if (time[i] != 0) {
  283. + return true;
  284. + }
  285. + if (rejectTime[i] != 0) {
  286. + return true;
  287. + }
  288. + }
  289. + return false;
  290. + }
  291. +
  292. + int getMode() {
  293. + return uidState.evalMode(mode);
  294. + }
  295. }
  296.  
  297. - final SparseArray<ArraySet<Callback>> mOpModeWatchers = new SparseArray<>();
  298. - final ArrayMap<String, ArraySet<Callback>> mPackageModeWatchers = new ArrayMap<>();
  299. - final ArrayMap<IBinder, Callback> mModeWatchers = new ArrayMap<>();
  300. + final SparseArray<ArraySet<ModeCallback>> mOpModeWatchers = new SparseArray<>();
  301. + final ArrayMap<String, ArraySet<ModeCallback>> mPackageModeWatchers = new ArrayMap<>();
  302. + final ArrayMap<IBinder, ModeCallback> mModeWatchers = new ArrayMap<>();
  303. + final ArrayMap<IBinder, SparseArray<ActiveCallback>> mActiveWatchers = new ArrayMap<>();
  304. final SparseArray<SparseArray<Restriction>> mAudioRestrictions = new SparseArray<>();
  305.  
  306. - public final class Callback implements DeathRecipient {
  307. + final class ModeCallback implements DeathRecipient {
  308. final IAppOpsCallback mCallback;
  309. + final int mWatchingUid;
  310. + final int mFlags;
  311. + final int mCallingUid;
  312. + final int mCallingPid;
  313.  
  314. - public Callback(IAppOpsCallback callback) {
  315. + ModeCallback(IAppOpsCallback callback, int watchingUid, int flags, int callingUid,
  316. + int callingPid) {
  317. mCallback = callback;
  318. + mWatchingUid = watchingUid;
  319. + mFlags = flags;
  320. + mCallingUid = callingUid;
  321. + mCallingPid = callingPid;
  322. try {
  323. mCallback.asBinder().linkToDeath(this, 0);
  324. } catch (RemoteException e) {
  325. @@@ -575,16 -282,17 +616,19 @@@
  326.  
  327. public AppOpsService(File storagePath, Handler handler) {
  328. LockGuard.installLock(this, LockGuard.INDEX_APP_OPS);
  329. - mFile = new AtomicFile(storagePath);
  330. + mFile = new AtomicFile(storagePath, "appops");
  331. mHandler = handler;
  332. + mConstants = new Constants(mHandler);
  333. + mLooper = Looper.myLooper();
  334. + mStrictEnable = AppOpsManager.isStrictEnable();
  335. readState();
  336. }
  337.  
  338. public void publish(Context context) {
  339. mContext = context;
  340. + readPolicy();
  341. ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder());
  342. + LocalServices.addService(AppOpsManagerInternal.class, mAppOpsManagerInternal);
  343. }
  344.  
  345. public void systemReady() {
  346. @@@ -807,33 -483,24 +887,33 @@@
  347.  
  348. private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) {
  349. ArrayList<AppOpsManager.OpEntry> resOps = null;
  350. + final long elapsedNow = SystemClock.elapsedRealtime();
  351. if (ops == null) {
  352. - resOps = new ArrayList<AppOpsManager.OpEntry>();
  353. + resOps = new ArrayList<>();
  354. for (int j=0; j<pkgOps.size(); j++) {
  355. Op curOp = pkgOps.valueAt(j);
  356. + final boolean running = curOp.duration == -1;
  357. + long duration = running
  358. + ? (elapsedNow - curOp.startRealtime)
  359. + : curOp.duration;
  360. resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
  361. - curOp.rejectTime, curOp.duration, curOp.proxyUid,
  362. + curOp.rejectTime, (int) duration, running, curOp.proxyUid,
  363. - curOp.proxyPackageName));
  364. + curOp.proxyPackageName, curOp.allowedCount, curOp.ignoredCount));
  365. }
  366. } else {
  367. for (int j=0; j<ops.length; j++) {
  368. Op curOp = pkgOps.get(ops[j]);
  369. if (curOp != null) {
  370. if (resOps == null) {
  371. - resOps = new ArrayList<AppOpsManager.OpEntry>();
  372. + resOps = new ArrayList<>();
  373. }
  374. + final boolean running = curOp.duration == -1;
  375. + final long duration = running
  376. + ? (elapsedNow - curOp.startRealtime)
  377. + : curOp.duration;
  378. resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
  379. - curOp.rejectTime, curOp.duration, curOp.proxyUid,
  380. - curOp.proxyPackageName, curOp.allowedCount, curOp.ignoredCount));
  381. + curOp.rejectTime, (int) duration, running, curOp.proxyUid,
  382. - curOp.proxyPackageName));
  383. ++ curOp.proxyPackageName), curOp.allowedCount, curOp.ignoredCount);
  384. }
  385. }
  386. }
  387. @@@ -1271,11 -911,12 +1352,13 @@@
  388. Ops pkgOps = ent.getValue();
  389. for (int j=pkgOps.size()-1; j>=0; j--) {
  390. Op curOp = pkgOps.valueAt(j);
  391. + int defaultMode = getDefaultMode(curOp.op, curOp.uid,
  392. + curOp.packageName);
  393. if (AppOpsManager.opAllowsReset(curOp.op)
  394. - && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) {
  395. - curOp.mode = AppOpsManager.opToDefaultMode(curOp.op);
  396. + && curOp.mode != defaultMode) {
  397. + curOp.mode = defaultMode;
  398. changed = true;
  399. + uidChanged = true;
  400. callbacks = addCallbacks(callbacks, curOp.op, curOp.uid, packageName,
  401. mOpModeWatchers.get(curOp.op));
  402. callbacks = addCallbacks(callbacks, curOp.op, curOp.uid, packageName,
  403. @@@ -1564,23 -1172,22 +1647,25 @@@
  404.  
  405. private int noteOperationUnchecked(int code, int uid, String packageName,
  406. int proxyUid, String proxyPackageName) {
  407. + PermissionDialogReq req = null;
  408. synchronized (this) {
  409. - Ops ops = getOpsRawLocked(uid, packageName, true);
  410. + final Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
  411. + false /* uidMismatchExpected */);
  412. if (ops == null) {
  413. - if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
  414. + if (DEBUG) Slog.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
  415. + " package " + packageName);
  416. return AppOpsManager.MODE_ERRORED;
  417. }
  418. - Op op = getOpLocked(ops, code, true);
  419. + final Op op = getOpLocked(ops, code, true);
  420. if (isOpRestrictedLocked(uid, code, packageName)) {
  421. + op.ignoredCount++;
  422. return AppOpsManager.MODE_IGNORED;
  423. }
  424. + final UidState uidState = ops.uidState;
  425. if (op.duration == -1) {
  426. Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
  427. - + " code " + code + " time=" + op.time + " duration=" + op.duration);
  428. + + " code " + code + " time=" + op.time[uidState.state]
  429. + + " duration=" + op.duration);
  430. }
  431. op.duration = 0;
  432. final int switchCode = AppOpsManager.opToSwitch(code);
  433. @@@ -1597,79 -1205,92 +1682,144 @@@
  434. }
  435. } else {
  436. final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
  437. - if (switchOp.mode != AppOpsManager.MODE_ALLOWED
  438. - && switchOp.mode != AppOpsManager.MODE_ASK) {
  439. - if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
  440. - + switchCode + " (" + code + ") uid " + uid + " package "
  441. - + packageName);
  442. - op.rejectTime = System.currentTimeMillis();
  443. + final int mode = switchOp.getMode();
  444. - if (mode != AppOpsManager.MODE_ALLOWED) {
  445. ++ if (mode != AppOpsManager.MODE_ALLOWED && mode != AppOpsManager.MODE_ASK) {
  446. + if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + mode + " for code "
  447. + + switchCode + " (" + code + ") uid " + uid + " package "
  448. + + packageName);
  449. + op.rejectTime[uidState.state] = System.currentTimeMillis();
  450. + op.ignoredCount++;
  451. - return switchOp.mode;
  452. - } else if (switchOp.mode == AppOpsManager.MODE_ASK) {
  453. + return mode;
  454. ++ } else if (mode == AppOpsManager.MODE_ASK) {
  455. + if (Looper.myLooper() == mLooper) {
  456. + Log.e(TAG,
  457. + "noteOperation: This method will deadlock if called from the main thread. (Code: "
  458. + + code
  459. + + " uid: "
  460. + + uid
  461. + + " package: "
  462. + + packageName + ")");
  463. - return switchOp.mode;
  464. ++ return mode;
  465. + }
  466. +
  467. + if (DEBUG) {
  468. + Log.d(TAG, "Package " + op.packageName + " has " + op.noteOpCount
  469. + + " requests and " + op.startOpCount + " start requests with "
  470. + + op.ignoredCount + " ignored at " + op.time +
  471. + " with a duration of "
  472. + + op.duration + " while being delayed " + op.delayedCount +
  473. + " times");
  474. + Log.d(TAG, "Total pkops for " + ops.packageName + " "
  475. + + ops.uidState.pkgOps.size());
  476. + }
  477. +
  478. + // First drop all request events if the device is not interactive, next
  479. + // check what the global pkg ops count for the package,
  480. + // then check op scoped count. High frequency request ops will be delayed until
  481. + // their delay count ceiling is met. This is to mitigate the overloading the
  482. + // main activity manager service handler and having watchdog kill our service.
  483. + // Google play services likes to share its uid with numerous packages to avoid
  484. + // having to grant permissions from the users perspective and thus is the worst
  485. + // example of overloading this queue -- so, to not encourage bad behavior,
  486. + // we move them to the back of the line. NOTE: these values are magic, and may need
  487. + // tuning. Ideally we'd want a ringbuffer or token bucket here to do proper rate
  488. + // limiting.
  489. + final boolean isInteractive = mPowerManager.isInteractive();
  490. + if (isInteractive &&
  491. + (ops.uidState.pkgOps.size() < AppOpsPolicy.RATE_LIMIT_OPS_TOTAL_PKG_COUNT
  492. + && op.noteOpCount < AppOpsPolicy.RATE_LIMIT_OP_COUNT
  493. + || op.delayedCount > AppOpsPolicy.RATE_LIMIT_OP_DELAY_CEILING)) {
  494. +
  495. + // Reset delayed count, most ops will never need this
  496. + if (op.delayedCount > 0) {
  497. + if (DEBUG) Log.d(TAG, "Resetting delayed count for " + op.packageName);
  498. + op.delayedCount = 0;
  499. + }
  500. +
  501. + op.noteOpCount++;
  502. + req = askOperationLocked(code, uid, packageName, switchOp);
  503. + } else {
  504. + if (isInteractive) {
  505. + op.delayedCount++;
  506. + }
  507. + op.ignoredCount++;
  508. + return AppOpsManager.MODE_IGNORED;
  509. + }
  510. }
  511. }
  512. - if (DEBUG) Slog.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
  513. - + " package " + packageName);
  514. - op.time[uidState.state] = System.currentTimeMillis();
  515. - op.rejectTime[uidState.state] = 0;
  516. - op.proxyUid = proxyUid;
  517. - op.proxyPackageName = proxyPackageName;
  518. - return AppOpsManager.MODE_ALLOWED;
  519. + if (req == null) {
  520. - if (DEBUG) Log.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
  521. ++ if (DEBUG) Slog.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
  522. + + " package " + packageName);
  523. - op.time = System.currentTimeMillis();
  524. - op.rejectTime = 0;
  525. ++ op.time[uidState.state] = System.currentTimeMillis();
  526. ++ op.rejectTime[uidState.state] = 0;
  527. + op.proxyUid = proxyUid;
  528. + op.proxyPackageName = proxyPackageName;
  529. + broadcastOpIfNeeded(code);
  530. + op.allowedCount++;
  531. + return AppOpsManager.MODE_ALLOWED;
  532. + }
  533. }
  534. +
  535. + int result = req.get();
  536. + broadcastOpIfNeeded(code);
  537. + return result;
  538. }
  539.  
  540. @Override
  541. - public int startOperation(IBinder token, int code, int uid, String packageName) {
  542. + public void startWatchingActive(int[] ops, IAppOpsActiveCallback callback) {
  543. + int watchedUid = -1;
  544. + final int callingUid = Binder.getCallingUid();
  545. + final int callingPid = Binder.getCallingPid();
  546. + if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS)
  547. + != PackageManager.PERMISSION_GRANTED) {
  548. + watchedUid = callingUid;
  549. + }
  550. + if (ops != null) {
  551. + Preconditions.checkArrayElementsInRange(ops, 0,
  552. + AppOpsManager._NUM_OP - 1, "Invalid op code in: " + Arrays.toString(ops));
  553. + }
  554. + if (callback == null) {
  555. + return;
  556. + }
  557. + synchronized (this) {
  558. + SparseArray<ActiveCallback> callbacks = mActiveWatchers.get(callback.asBinder());
  559. + if (callbacks == null) {
  560. + callbacks = new SparseArray<>();
  561. + mActiveWatchers.put(callback.asBinder(), callbacks);
  562. + }
  563. + final ActiveCallback activeCallback = new ActiveCallback(callback, watchedUid,
  564. + callingUid, callingPid);
  565. + for (int op : ops) {
  566. + callbacks.put(op, activeCallback);
  567. + }
  568. + }
  569. + }
  570. +
  571. + @Override
  572. + public void stopWatchingActive(IAppOpsActiveCallback callback) {
  573. + if (callback == null) {
  574. + return;
  575. + }
  576. + synchronized (this) {
  577. + final SparseArray<ActiveCallback> activeCallbacks =
  578. + mActiveWatchers.remove(callback.asBinder());
  579. + if (activeCallbacks == null) {
  580. + return;
  581. + }
  582. + final int callbackCount = activeCallbacks.size();
  583. + for (int i = 0; i < callbackCount; i++) {
  584. + // Apps ops are mapped to a singleton
  585. + if (i == 0) {
  586. + activeCallbacks.valueAt(i).destroy();
  587. + }
  588. + }
  589. + }
  590. + }
  591. +
  592. + @Override
  593. + public int startOperation(IBinder token, int code, int uid, String packageName,
  594. + boolean startIfModeDefault) {
  595. + final PermissionDialogReq req;
  596. verifyIncomingUid(uid);
  597. verifyIncomingOp(code);
  598. String resolvedPackageName = resolvePackageName(uid, packageName);
  599. @@@ -1685,53 -1305,67 +1835,78 @@@
  600. + " package " + resolvedPackageName);
  601. return AppOpsManager.MODE_ERRORED;
  602. }
  603. - Op op = getOpLocked(ops, code, true);
  604. + final Op op = getOpLocked(ops, code, true);
  605. if (isOpRestrictedLocked(uid, code, resolvedPackageName)) {
  606. + op.ignoredCount++;
  607. return AppOpsManager.MODE_IGNORED;
  608. }
  609. final int switchCode = AppOpsManager.opToSwitch(code);
  610. - UidState uidState = ops.uidState;
  611. - if (uidState.opModes != null) {
  612. - final int uidMode = uidState.opModes.get(switchCode);
  613. - if (uidMode != AppOpsManager.MODE_ALLOWED) {
  614. - if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
  615. + final UidState uidState = ops.uidState;
  616. + // If there is a non-default per UID policy (we set UID op mode only if
  617. + // non-default) it takes over, otherwise use the per package policy.
  618. + if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
  619. + final int uidMode = uidState.evalMode(uidState.opModes.get(switchCode));
  620. - if (uidMode != AppOpsManager.MODE_ALLOWED
  621. ++ if (uidMode != AppOpsManager.MODE_ALLOWED && mode != AppOpsManager.MODE_ASK
  622. + && (!startIfModeDefault || uidMode != AppOpsManager.MODE_DEFAULT)) {
  623. + if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
  624. + switchCode + " (" + code + ") uid " + uid + " package "
  625. + resolvedPackageName);
  626. - op.rejectTime = System.currentTimeMillis();
  627. + op.rejectTime[uidState.state] = System.currentTimeMillis();
  628. ++ op.ignoredCount++;
  629. return uidMode;
  630. }
  631. + } else {
  632. + final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
  633. + final int mode = switchOp.getMode();
  634. - if (mode != AppOpsManager.MODE_ALLOWED
  635. ++ if (mode != AppOpsManager.MODE_ALLOWED && mode != AppOpsManager.MODE_ASK
  636. + && (!startIfModeDefault || mode != AppOpsManager.MODE_DEFAULT)) {
  637. + if (DEBUG) Slog.d(TAG, "startOperation: reject #" + mode + " for code "
  638. + + switchCode + " (" + code + ") uid " + uid + " package "
  639. + + resolvedPackageName);
  640. + op.rejectTime[uidState.state] = System.currentTimeMillis();
  641. ++ op.ignoredCount++;
  642. + return mode;
  643. + }
  644. }
  645. - if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
  646. - + " package " + resolvedPackageName);
  647. - if (op.startNesting == 0) {
  648. - op.startRealtime = SystemClock.elapsedRealtime();
  649. - op.time[uidState.state] = System.currentTimeMillis();
  650. - op.rejectTime[uidState.state] = 0;
  651. - op.duration = -1;
  652. - scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, true);
  653. - }
  654. - op.startNesting++;
  655. - uidState.startNesting++;
  656. - if (client.mStartedOps != null) {
  657. - client.mStartedOps.add(op);
  658. - final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
  659. - if (switchOp.mode != AppOpsManager.MODE_ALLOWED
  660. - && switchOp.mode != AppOpsManager.MODE_ASK) {
  661. - if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code "
  662. - + switchCode + " (" + code + ") uid " + uid + " package "
  663. - + resolvedPackageName);
  664. - op.rejectTime = System.currentTimeMillis();
  665. - op.ignoredCount++;
  666. - return switchOp.mode;
  667. - } else if (switchOp.mode == AppOpsManager.MODE_ALLOWED) {
  668. - if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code
  669. - + " uid " + uid + " package " + resolvedPackageName);
  670. - if (op.nesting == 0) {
  671. - op.time = System.currentTimeMillis();
  672. - op.rejectTime = 0;
  673. ++ if (mode == AppOpsManager.MODE_ALLOWED) {
  674. ++ if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
  675. ++ + " package " + resolvedPackageName);
  676. ++ if (op.startNesting == 0) {
  677. ++ op.startRealtime = SystemClock.elapsedRealtime();
  678. ++ op.time[uidState.state] = System.currentTimeMillis();
  679. ++ op.rejectTime[uidState.state] = 0;
  680. + op.duration = -1;
  681. + op.allowedCount++;
  682. ++ scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, true);
  683. + }
  684. - op.nesting++;
  685. ++ op.startNesting++;
  686. ++ uidState.startNesting++;
  687. + if (client.mStartedOps != null) {
  688. + client.mStartedOps.add(op);
  689. + }
  690. + broadcastOpIfNeeded(code);
  691. + return AppOpsManager.MODE_ALLOWED;
  692. + } else {
  693. + if (Looper.myLooper() == mLooper) {
  694. + Log.e(TAG,
  695. + "startOperation: This method will deadlock if called from the main thread. (Code: "
  696. + + code
  697. + + " uid: "
  698. + + uid
  699. + + " package: "
  700. + + resolvedPackageName + ")");
  701. + return switchOp.mode;
  702. + }
  703. + op.startOpCount++;
  704. + IBinder clientToken = client.mAppToken;
  705. + op.clientTokens.add(clientToken);
  706. + req = askOperationLocked(code, uid, resolvedPackageName, switchOp);
  707. }
  708. }
  709. +
  710. - return AppOpsManager.MODE_ALLOWED;
  711. + int result = req.get();
  712. + broadcastOpIfNeeded(code);
  713. + return result;
  714. }
  715.  
  716. @Override
  717. @@@ -1751,78 -1385,15 +1926,79 @@@
  718. if (op == null) {
  719. return;
  720. }
  721. - if (client.mStartedOps != null) {
  722. - if (!client.mStartedOps.remove(op)) {
  723. - throw new IllegalStateException("Operation not started: uid" + op.uid
  724. - + " pkg=" + op.packageName + " op=" + op.op);
  725. + if (!client.mStartedOps.remove(op)) {
  726. + // We finish ops when packages get removed to guarantee no dangling
  727. + // started ops. However, some part of the system may asynchronously
  728. + // finish ops for an already gone package. Hence, finishing an op
  729. + // for a non existing package is fine and we don't log as a wtf.
  730. + final long identity = Binder.clearCallingIdentity();
  731. + try {
  732. + if (LocalServices.getService(PackageManagerInternal.class).getPackageUid(
  733. + resolvedPackageName, 0, UserHandle.getUserId(uid)) < 0) {
  734. + Slog.i(TAG, "Finishing op=" + AppOpsManager.opToName(code)
  735. + + " for non-existing package=" + resolvedPackageName
  736. + + " in uid=" + uid);
  737. + return;
  738. + }
  739. + } finally {
  740. + Binder.restoreCallingIdentity(identity);
  741. + }
  742. + Slog.wtf(TAG, "Operation not started: uid=" + op.uid + " pkg="
  743. + + op.packageName + " op=" + AppOpsManager.opToName(op.op));
  744. + return;
  745. + }
  746. + finishOperationLocked(op, /*finishNested*/ false);
  747. + if (op.startNesting <= 0) {
  748. + scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, false);
  749. + }
  750. + }
  751. + }
  752. +
  753. + private void scheduleOpActiveChangedIfNeededLocked(int code, int uid, String packageName,
  754. + boolean active) {
  755. + ArraySet<ActiveCallback> dispatchedCallbacks = null;
  756. + final int callbackListCount = mActiveWatchers.size();
  757. + for (int i = 0; i < callbackListCount; i++) {
  758. + final SparseArray<ActiveCallback> callbacks = mActiveWatchers.valueAt(i);
  759. + ActiveCallback callback = callbacks.get(code);
  760. + if (callback != null) {
  761. + if (callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) {
  762. + continue;
  763. + }
  764. + if (dispatchedCallbacks == null) {
  765. + dispatchedCallbacks = new ArraySet<>();
  766. + }
  767. + dispatchedCallbacks.add(callback);
  768. + }
  769. + }
  770. + if (dispatchedCallbacks == null) {
  771. + return;
  772. + }
  773. + mHandler.sendMessage(PooledLambda.obtainMessage(
  774. + AppOpsService::notifyOpActiveChanged,
  775. + this, dispatchedCallbacks, code, uid, packageName, active));
  776. + }
  777. +
  778. + private void notifyOpActiveChanged(ArraySet<ActiveCallback> callbacks,
  779. + int code, int uid, String packageName, boolean active) {
  780. + // There are components watching for mode changes such as window manager
  781. + // and location manager which are in our process. The callbacks in these
  782. + // components may require permissions our remote caller does not have.
  783. + final long identity = Binder.clearCallingIdentity();
  784. + try {
  785. + final int callbackCount = callbacks.size();
  786. + for (int i = 0; i < callbackCount; i++) {
  787. + final ActiveCallback callback = callbacks.valueAt(i);
  788. + try {
  789. + callback.mCallback.opActiveChanged(code, uid, packageName, active);
  790. + } catch (RemoteException e) {
  791. + /* do nothing */
  792. }
  793. }
  794. - finishOperationLocked(op);
  795. + } finally {
  796. + Binder.restoreCallingIdentity(identity);
  797. }
  798. + broadcastOpIfNeeded(code);
  799. }
  800.  
  801. @Override
  802. @@@ -2030,7 -1553,8 +2211,8 @@@
  803. if (!edit) {
  804. return null;
  805. }
  806. - op = new Op(ops.uidState, ops.packageName, code);
  807. + mode = getDefaultMode(code, ops.uidState.uid, ops.packageName);
  808. - op = new Op(ops.uidState.uid, ops.packageName, code, mode);
  809. ++ op = new Op(ops.uidState, ops.packageName, code, mode);
  810. ops.put(code, op);
  811. }
  812. if (edit) {
  813. @@@ -2278,86 -1741,66 +2460,111 @@@
  814.  
  815. String tagName = parser.getName();
  816. if (tagName.equals("op")) {
  817. + int code = Integer
  818. + .parseInt(parser.getAttributeValue(null, "n"));
  819. + // use op name string if it exists
  820. + String codeNameStr = parser.getAttributeValue(null, "ns");
  821. + if (codeNameStr != null) {
  822. + // returns OP_NONE if it could not be mapped
  823. + code = AppOpsManager.nameToOp(codeNameStr);
  824. + }
  825. + // skip op codes that are out of bounds
  826. + if (code == AppOpsManager.OP_NONE
  827. + || code >= AppOpsManager._NUM_OP) {
  828. + continue;
  829. + }
  830. - Op op = new Op(uid, pkgName, code, AppOpsManager.MODE_ERRORED);
  831. - String mode = parser.getAttributeValue(null, "m");
  832. - if (mode != null) {
  833. - op.mode = Integer.parseInt(mode);
  834. - } else {
  835. - String sDefualtMode = parser.getAttributeValue(null, "dm");
  836. - int defaultMode;
  837. - if (sDefualtMode != null) {
  838. - defaultMode = Integer.parseInt(sDefualtMode);
  839. - } else {
  840. - defaultMode = getDefaultMode(code, uid, pkgName);
  841. - }
  842. - op.mode = defaultMode;
  843. - }
  844. - String time = parser.getAttributeValue(null, "t");
  845. - if (time != null) {
  846. - op.time = Long.parseLong(time);
  847. - }
  848. - time = parser.getAttributeValue(null, "r");
  849. - if (time != null) {
  850. - op.rejectTime = Long.parseLong(time);
  851. - }
  852. - String dur = parser.getAttributeValue(null, "d");
  853. - if (dur != null) {
  854. - op.duration = Integer.parseInt(dur);
  855. - }
  856. - String proxyUid = parser.getAttributeValue(null, "pu");
  857. - if (proxyUid != null) {
  858. - op.proxyUid = Integer.parseInt(proxyUid);
  859. - }
  860. - String proxyPackageName = parser.getAttributeValue(null, "pp");
  861. - if (proxyPackageName != null) {
  862. - op.proxyPackageName = proxyPackageName;
  863. - }
  864. - String allowed = parser.getAttributeValue(null, "ac");
  865. - if (allowed != null) {
  866. - op.allowedCount = Integer.parseInt(allowed);
  867. - }
  868. - String ignored = parser.getAttributeValue(null, "ic");
  869. - if (ignored != null) {
  870. - op.ignoredCount = Integer.parseInt(ignored);
  871. - }
  872. UidState uidState = getUidStateLocked(uid, true);
  873. if (uidState.pkgOps == null) {
  874. uidState.pkgOps = new ArrayMap<>();
  875. }
  876.  
  877. - Op op = new Op(uidState, pkgName,
  878. - Integer.parseInt(parser.getAttributeValue(null, "n")));
  879. ++ Op op = new Op(uidState, pkgName, code, AppOpsManager.MODE_ERRORED);
  880. +
  881. + for (int i = parser.getAttributeCount()-1; i >= 0; i--) {
  882. + final String name = parser.getAttributeName(i);
  883. + final String value = parser.getAttributeValue(i);
  884. + switch (name) {
  885. ++ case "ac":
  886. ++ op.allowedCount = Integer.parseInt(value);
  887. ++ break;
  888. + case "m":
  889. + op.mode = Integer.parseInt(value);
  890. + break;
  891. ++ case "dm":
  892. ++ if (value != null) {
  893. ++ op.mode = Integer.parseInt(value);
  894. ++ } else {
  895. ++ op.mode = getDefaultMode(code, uidState.uid, pkgName);
  896. ++ }
  897. ++ break;
  898. + case "d":
  899. + op.duration = Integer.parseInt(value);
  900. + break;
  901. ++ case "ic":
  902. ++ op.ignoredCount = Integer.parseInt(value);
  903. ++ break;
  904. + case "pu":
  905. + op.proxyUid = Integer.parseInt(value);
  906. + break;
  907. + case "pp":
  908. + op.proxyPackageName = value;
  909. + break;
  910. + case "tp":
  911. + op.time[AppOpsManager.UID_STATE_PERSISTENT] = Long.parseLong(value);
  912. + break;
  913. + case "tt":
  914. + op.time[AppOpsManager.UID_STATE_TOP] = Long.parseLong(value);
  915. + break;
  916. + case "tfs":
  917. + op.time[AppOpsManager.UID_STATE_FOREGROUND_SERVICE]
  918. + = Long.parseLong(value);
  919. + break;
  920. + case "tf":
  921. + op.time[AppOpsManager.UID_STATE_FOREGROUND] = Long.parseLong(value);
  922. + break;
  923. + case "tb":
  924. + op.time[AppOpsManager.UID_STATE_BACKGROUND] = Long.parseLong(value);
  925. + break;
  926. + case "tc":
  927. + op.time[AppOpsManager.UID_STATE_CACHED] = Long.parseLong(value);
  928. + break;
  929. + case "rp":
  930. + op.rejectTime[AppOpsManager.UID_STATE_PERSISTENT]
  931. + = Long.parseLong(value);
  932. + break;
  933. + case "rt":
  934. + op.rejectTime[AppOpsManager.UID_STATE_TOP] = Long.parseLong(value);
  935. + break;
  936. + case "rfs":
  937. + op.rejectTime[AppOpsManager.UID_STATE_FOREGROUND_SERVICE]
  938. + = Long.parseLong(value);
  939. + break;
  940. + case "rf":
  941. + op.rejectTime[AppOpsManager.UID_STATE_FOREGROUND]
  942. + = Long.parseLong(value);
  943. + break;
  944. + case "rb":
  945. + op.rejectTime[AppOpsManager.UID_STATE_BACKGROUND]
  946. + = Long.parseLong(value);
  947. + break;
  948. + case "rc":
  949. + op.rejectTime[AppOpsManager.UID_STATE_CACHED]
  950. + = Long.parseLong(value);
  951. + break;
  952. + case "t":
  953. + // Backwards compat.
  954. + op.time[AppOpsManager.UID_STATE_TOP] = Long.parseLong(value);
  955. + break;
  956. + case "r":
  957. + // Backwards compat.
  958. + op.rejectTime[AppOpsManager.UID_STATE_TOP] = Long.parseLong(value);
  959. + break;
  960. + default:
  961. + Slog.w(TAG, "Unknown attribute in 'op' tag: " + name);
  962. + break;
  963. + }
  964. + }
  965. +
  966. Ops ops = uidState.pkgOps.get(pkgName);
  967. if (ops == null) {
  968. ops = new Ops(pkgName, uidState, isPrivileged);
  969. @@@ -2445,20 -1882,21 +2652,25 @@@
  970. AppOpsManager.OpEntry op = ops.get(j);
  971. out.startTag(null, "op");
  972. out.attribute(null, "n", Integer.toString(op.getOp()));
  973. - if (op.getMode() != AppOpsManager.opToDefaultMode(op.getOp())) {
  974. + out.attribute(null, "ns", AppOpsManager.opToName(op.getOp()));
  975. + int defaultMode = getDefaultMode(op.getOp(),
  976. + pkg.getUid(), pkg.getPackageName());
  977. + if (op.getMode() != defaultMode) {
  978. out.attribute(null, "m", Integer.toString(op.getMode()));
  979. + } else {
  980. + out.attribute(null, "dm", Integer.toString(defaultMode));
  981. }
  982. - long time = op.getTime();
  983. - if (time != 0) {
  984. - out.attribute(null, "t", Long.toString(time));
  985. - }
  986. - time = op.getRejectTime();
  987. - if (time != 0) {
  988. - out.attribute(null, "r", Long.toString(time));
  989. + for (int k = 0; k < _NUM_UID_STATE; k++) {
  990. + final long time = op.getLastTimeFor(k);
  991. + if (time != 0) {
  992. + out.attribute(null, UID_STATE_TIME_ATTRS[k],
  993. + Long.toString(time));
  994. + }
  995. + final long rejectTime = op.getLastRejectTimeFor(k);
  996. + if (rejectTime != 0) {
  997. + out.attribute(null, UID_STATE_REJECT_ATTRS[k],
  998. + Long.toString(rejectTime));
  999. + }
  1000. }
  1001. int dur = op.getDuration();
  1002. if (dur != 0) {
  1003. @@@ -3566,8 -2718,176 +3786,176 @@@
  1004. }
  1005. }
  1006.  
  1007. + final class AskRunnable implements Runnable {
  1008. + final int code;
  1009. + final int uid;
  1010. + final String packageName;
  1011. + final Op op;
  1012. + final PermissionDialogReq request;
  1013. +
  1014. + public AskRunnable(int code, int uid, String packageName, Op op,
  1015. + PermissionDialogReq request) {
  1016. + super();
  1017. + this.code = code;
  1018. + this.uid = uid;
  1019. + this.packageName = packageName;
  1020. + this.op = op;
  1021. + this.request = request;
  1022. + }
  1023. +
  1024. + @Override
  1025. + public void run() {
  1026. + PermissionDialog permDialog = null;
  1027. + synchronized (AppOpsService.this) {
  1028. + Log.e(TAG, "Creating dialog box");
  1029. + op.dialogReqQueue.register(request);
  1030. + if (op.dialogReqQueue.getDialog() == null) {
  1031. + permDialog = new PermissionDialog(mContext,
  1032. + AppOpsService.this, code, uid, packageName);
  1033. + op.dialogReqQueue.setDialog(permDialog);
  1034. + }
  1035. + }
  1036. + if (permDialog != null) {
  1037. + permDialog.show();
  1038. + }
  1039. + }
  1040. + }
  1041. +
  1042. + private PermissionDialogReq askOperationLocked(int code, int uid,
  1043. + String packageName, Op op) {
  1044. + PermissionDialogReq request = new PermissionDialogReq();
  1045. + mHandler.post(new AskRunnable(code, uid, packageName, op, request));
  1046. + return request;
  1047. + }
  1048. +
  1049. + private int getDefaultMode(int code, int uid, String packageName) {
  1050. + int mode = AppOpsManager.opToDefaultMode(code,
  1051. + isStrict(code, uid, packageName));
  1052. + if (AppOpsManager.isStrictOp(code) && mPolicy != null) {
  1053. + int policyMode = mPolicy.getDefualtMode(code, packageName);
  1054. + if (policyMode != AppOpsManager.MODE_ERRORED) {
  1055. + mode = policyMode;
  1056. + }
  1057. + }
  1058. + return mode;
  1059. + }
  1060. +
  1061. + private boolean isStrict(int code, int uid, String packageName) {
  1062. + if (!mStrictEnable)
  1063. + return false;
  1064. +
  1065. + return UserHandle.isApp(uid);
  1066. + }
  1067. +
  1068. + private void printOperationLocked(Op op, int mode, String operation) {
  1069. + if(op != null) {
  1070. + int switchCode = AppOpsManager.opToSwitch(op.op);
  1071. + if (mode == AppOpsManager.MODE_IGNORED) {
  1072. + if (DEBUG) Log.d(TAG, operation + ": reject #" + mode + " for code "
  1073. + + switchCode + " (" + op.op + ") uid " + op.uid + " package "
  1074. + + op.packageName);
  1075. + } else if (mode == AppOpsManager.MODE_ALLOWED) {
  1076. + if (DEBUG) Log.d(TAG, operation + ": allowing code " + op.op + " uid "
  1077. + + op.uid
  1078. + + " package " + op.packageName);
  1079. + }
  1080. + }
  1081. + }
  1082. +
  1083. + private void recordOperationLocked(int code, int uid, String packageName,
  1084. + int mode) {
  1085. + Op op = getOpLocked(code, uid, packageName, false);
  1086. + if (op != null) {
  1087. + if (op.noteOpCount != 0) {
  1088. + printOperationLocked(op, mode, "noteOperartion");
  1089. + }
  1090. + if (op.startOpCount != 0) {
  1091. + printOperationLocked(op, mode, "startOperation");
  1092. + }
  1093. + if (mode == AppOpsManager.MODE_IGNORED) {
  1094. + op.rejectTime = System.currentTimeMillis();
  1095. + } else if (mode == AppOpsManager.MODE_ALLOWED) {
  1096. + if (op.noteOpCount != 0) {
  1097. + op.time = System.currentTimeMillis();
  1098. + op.rejectTime = 0;
  1099. + }
  1100. + if (op.startOpCount != 0) {
  1101. + if (op.nesting == 0) {
  1102. + op.time = System.currentTimeMillis();
  1103. + op.rejectTime = 0;
  1104. + op.duration = -1;
  1105. + }
  1106. + op.nesting = op.nesting + op.startOpCount;
  1107. + while (op.clientTokens.size() != 0) {
  1108. + IBinder clientToken = op.clientTokens.get(0);
  1109. + ClientState client = mClients.get(clientToken);
  1110. + if (client != null) {
  1111. + if (client.mStartedOps != null) {
  1112. + client.mStartedOps.add(op);
  1113. + }
  1114. + }
  1115. + op.clientTokens.remove(0);
  1116. + }
  1117. + }
  1118. + }
  1119. + op.clientTokens.clear();
  1120. + op.startOpCount = 0;
  1121. + op.noteOpCount = 0;
  1122. + }
  1123. + }
  1124. +
  1125. + public void notifyOperation(int code, int uid, String packageName,
  1126. + int mode, boolean remember) {
  1127. + verifyIncomingUid(uid);
  1128. + verifyIncomingOp(code);
  1129. + ArrayList<Callback> repCbs = null;
  1130. + int switchCode = AppOpsManager.opToSwitch(code);
  1131. + synchronized (this) {
  1132. + recordOperationLocked(code, uid, packageName, mode);
  1133. + Op op = getOpLocked(switchCode, uid, packageName, true);
  1134. + if (op != null) {
  1135. + // Send result to all waiting client
  1136. + if (op.dialogReqQueue.getDialog() != null) {
  1137. + op.dialogReqQueue.notifyAll(mode);
  1138. + op.dialogReqQueue.setDialog(null);
  1139. + }
  1140. + if (remember && op.mode != mode) {
  1141. + op.mode = mode;
  1142. + ArraySet<Callback> cbs = mOpModeWatchers.get(switchCode);
  1143. + if (cbs != null) {
  1144. + if (repCbs == null) {
  1145. + repCbs = new ArrayList<Callback>();
  1146. + }
  1147. + repCbs.addAll(cbs);
  1148. + }
  1149. + cbs = mPackageModeWatchers.get(packageName);
  1150. + if (cbs != null) {
  1151. + if (repCbs == null) {
  1152. + repCbs = new ArrayList<Callback>();
  1153. + }
  1154. + repCbs.addAll(cbs);
  1155. + }
  1156. + if (mode == getDefaultMode(op.op, op.uid, op.packageName)) {
  1157. + // If going into the default mode, prune this op
  1158. + // if there is nothing else interesting in it.
  1159. + pruneOp(op, uid, packageName);
  1160. + }
  1161. + scheduleWriteLocked();
  1162. + }
  1163. + }
  1164. + }
  1165. + if (repCbs != null) {
  1166. + for (int i = 0; i < repCbs.size(); i++) {
  1167. + try {
  1168. + repCbs.get(i).mCallback.opChanged(switchCode, uid, packageName);
  1169. + } catch (RemoteException e) {
  1170. + }
  1171. + }
  1172. + }
  1173. + }
  1174. +
  1175. private static String resolvePackageName(int uid, String packageName) {
  1176. - if (uid == 0) {
  1177. + if (uid == Process.ROOT_UID) {
  1178. return "root";
  1179. } else if (uid == Process.SHELL_UID) {
  1180. return "com.android.shell";
  1181. @@@ -3769,11 -3064,74 +4157,82 @@@
  1182. }
  1183. }
  1184.  
  1185. + private final class AppOpsManagerInternalImpl extends AppOpsManagerInternal {
  1186. + @Override public void setDeviceAndProfileOwners(SparseIntArray owners) {
  1187. + synchronized (AppOpsService.this) {
  1188. + mProfileOwners = owners;
  1189. + }
  1190. + }
  1191. + }
  1192. ++
  1193. + private void broadcastOpIfNeeded(int op) {
  1194. + switch (op) {
  1195. + case AppOpsManager.OP_SU:
  1196. + mHandler.post(mSuSessionChangedRunner);
  1197. + break;
  1198. + default:
  1199. + break;
  1200. + }
  1201. + }
  1202. +
  1203. + private void readPolicy() {
  1204. + if (mStrictEnable) {
  1205. + mPolicy = new AppOpsPolicy(new File(DEFAULT_POLICY_FILE), mContext);
  1206. + mPolicy.readPolicy();
  1207. + mPolicy.debugPoilcy();
  1208. + } else {
  1209. + mPolicy = null;
  1210. + }
  1211. + }
  1212. +
  1213. + public boolean isControlAllowed(int code, String packageName) {
  1214. + boolean isShow = true;
  1215. + if (mPolicy != null) {
  1216. + isShow = mPolicy.isControlAllowed(code, packageName);
  1217. + }
  1218. + return isShow;
  1219. + }
  1220. +
  1221. + @Override
  1222. + public boolean getPrivacyGuardSettingForPackage(int uid, String packageName) {
  1223. + for (int op : AppOpsManager.PRIVACY_GUARD_OP_STATES) {
  1224. + int switchOp = AppOpsManager.opToSwitch(op);
  1225. + int mode = checkOperation(op, uid, packageName);
  1226. + if (mode != AppOpsManager.MODE_ALLOWED && mode != AppOpsManager.MODE_IGNORED) {
  1227. + return true;
  1228. + }
  1229. + }
  1230. + return false;
  1231. + }
  1232. +
  1233. + @Override
  1234. + public void setPrivacyGuardSettingForPackage(int uid, String packageName, boolean state) {
  1235. + for (int op : AppOpsManager.PRIVACY_GUARD_OP_STATES) {
  1236. + int switchOp = AppOpsManager.opToSwitch(op);
  1237. + setMode(switchOp, uid, packageName, state
  1238. + ? AppOpsManager.MODE_ASK : AppOpsManager.MODE_ALLOWED);
  1239. + }
  1240. + }
  1241. +
  1242. + @Override
  1243. + public void resetCounters() {
  1244. + mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
  1245. + Binder.getCallingPid(), Binder.getCallingUid(), null);
  1246. + synchronized (this) {
  1247. + for (int i = 0; i < mUidStates.size(); i++) {
  1248. + final UidState uidState = mUidStates.valueAt(i);
  1249. + for (Map.Entry<String, Ops> ent : uidState.pkgOps.entrySet()) {
  1250. + String packageName = ent.getKey();
  1251. + Ops pkgOps = ent.getValue();
  1252. + for (int j = 0; j < pkgOps.size(); j++) {
  1253. + Op curOp = pkgOps.valueAt(j);
  1254. + curOp.allowedCount = 0;
  1255. + curOp.ignoredCount = 0;
  1256. + }
  1257. + }
  1258. + }
  1259. + // ensure the counter reset persists
  1260. + scheduleWriteLocked();
  1261. + }
  1262. + }
  1263. }
Add Comment
Please, Sign In to add comment