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.appop;
18 
19 import static android.app.AppOpsManager.MAX_PRIORITY_UID_STATE;
20 import static android.app.AppOpsManager.MIN_PRIORITY_UID_STATE;
21 import static android.app.AppOpsManager.OP_FLAGS_ALL;
22 import static android.app.AppOpsManager.OP_NONE;
23 import static android.app.AppOpsManager.OP_PLAY_AUDIO;
24 import static android.app.AppOpsManager.UID_STATE_BACKGROUND;
25 import static android.app.AppOpsManager.UID_STATE_CACHED;
26 import static android.app.AppOpsManager.UID_STATE_FOREGROUND;
27 import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE;
28 import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE_LOCATION;
29 import static android.app.AppOpsManager.UID_STATE_MAX_LAST_NON_RESTRICTED;
30 import static android.app.AppOpsManager.UID_STATE_PERSISTENT;
31 import static android.app.AppOpsManager.UID_STATE_TOP;
32 import static android.app.AppOpsManager.modeToName;
33 import static android.app.AppOpsManager.opToName;
34 import static android.app.AppOpsManager.resolveFirstUnrestrictedUidState;
35 
36 import android.Manifest;
37 import android.annotation.NonNull;
38 import android.annotation.Nullable;
39 import android.app.ActivityManager;
40 import android.app.ActivityThread;
41 import android.app.AppGlobals;
42 import android.app.AppOpsManager;
43 import android.app.AppOpsManager.HistoricalOps;
44 import android.app.AppOpsManager.HistoricalOpsRequest;
45 import android.app.AppOpsManager.Mode;
46 import android.app.AppOpsManager.OpEntry;
47 import android.app.AppOpsManager.OpFlags;
48 import android.app.AppOpsManagerInternal;
49 import android.app.AppOpsManagerInternal.CheckOpsDelegate;
50 import android.content.BroadcastReceiver;
51 import android.content.ContentResolver;
52 import android.content.Context;
53 import android.content.Intent;
54 import android.content.IntentFilter;
55 import android.content.pm.ApplicationInfo;
56 import android.content.pm.IPackageManager;
57 import android.content.pm.PackageManager;
58 import android.content.pm.PackageManagerInternal;
59 import android.content.pm.UserInfo;
60 import android.database.ContentObserver;
61 import android.media.AudioAttributes;
62 import android.net.Uri;
63 import android.os.AsyncTask;
64 import android.os.Binder;
65 import android.os.Bundle;
66 import android.os.Handler;
67 import android.os.IBinder;
68 import android.os.Process;
69 import android.os.RemoteCallback;
70 import android.os.RemoteException;
71 import android.os.ResultReceiver;
72 import android.os.ServiceManager;
73 import android.os.ShellCallback;
74 import android.os.ShellCommand;
75 import android.os.SystemClock;
76 import android.os.UserHandle;
77 import android.os.UserManager;
78 import android.os.storage.StorageManager;
79 import android.os.storage.StorageManagerInternal;
80 import android.provider.Settings;
81 import android.util.ArrayMap;
82 import android.util.ArraySet;
83 import android.util.AtomicFile;
84 import android.util.KeyValueListParser;
85 import android.util.LongSparseArray;
86 import android.util.LongSparseLongArray;
87 import android.util.Slog;
88 import android.util.SparseArray;
89 import android.util.SparseBooleanArray;
90 import android.util.SparseIntArray;
91 import android.util.TimeUtils;
92 import android.util.Xml;
93 
94 import com.android.internal.annotations.GuardedBy;
95 import com.android.internal.annotations.VisibleForTesting;
96 import com.android.internal.app.IAppOpsActiveCallback;
97 import com.android.internal.app.IAppOpsCallback;
98 import com.android.internal.app.IAppOpsNotedCallback;
99 import com.android.internal.app.IAppOpsService;
100 import com.android.internal.os.Zygote;
101 import com.android.internal.util.ArrayUtils;
102 import com.android.internal.util.DumpUtils;
103 import com.android.internal.util.FastXmlSerializer;
104 import com.android.internal.util.Preconditions;
105 import com.android.internal.util.XmlUtils;
106 import com.android.internal.util.function.pooled.PooledLambda;
107 import com.android.server.LocalServices;
108 import com.android.server.LockGuard;
109 
110 import libcore.util.EmptyArray;
111 
112 import org.xmlpull.v1.XmlPullParser;
113 import org.xmlpull.v1.XmlPullParserException;
114 import org.xmlpull.v1.XmlSerializer;
115 
116 import java.io.File;
117 import java.io.FileDescriptor;
118 import java.io.FileInputStream;
119 import java.io.FileNotFoundException;
120 import java.io.FileOutputStream;
121 import java.io.IOException;
122 import java.io.PrintWriter;
123 import java.nio.charset.StandardCharsets;
124 import java.text.SimpleDateFormat;
125 import java.util.ArrayList;
126 import java.util.Arrays;
127 import java.util.Collections;
128 import java.util.Date;
129 import java.util.HashMap;
130 import java.util.Iterator;
131 import java.util.List;
132 import java.util.Map;
133 
134 public class AppOpsService extends IAppOpsService.Stub {
135     static final String TAG = "AppOps";
136     static final boolean DEBUG = false;
137 
138     private static final int NO_VERSION = -1;
139     /** Increment by one every time and add the corresponding upgrade logic in
140      *  {@link #upgradeLocked(int)} below. The first version was 1 */
141     private static final int CURRENT_VERSION = 1;
142 
143     // Write at most every 30 minutes.
144     static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000;
145 
146     // Constant meaning that any UID should be matched when dispatching callbacks
147     private static final int UID_ANY = -2;
148 
149     // Map from process states to the uid states we track.
150     private static final int[] PROCESS_STATE_TO_UID_STATE = new int[] {
151         UID_STATE_PERSISTENT,           // ActivityManager.PROCESS_STATE_PERSISTENT
152         UID_STATE_PERSISTENT,           // ActivityManager.PROCESS_STATE_PERSISTENT_UI
153         UID_STATE_TOP,                  // ActivityManager.PROCESS_STATE_TOP
154         UID_STATE_FOREGROUND_SERVICE_LOCATION,
155                                         // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION
156         UID_STATE_FOREGROUND,           // ActivityManager.PROCESS_STATE_BOUND_TOP
157         UID_STATE_FOREGROUND_SERVICE,   // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
158         UID_STATE_FOREGROUND,           // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
159         UID_STATE_FOREGROUND,           // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
160         UID_STATE_BACKGROUND,           // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
161         UID_STATE_BACKGROUND,           // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
162         UID_STATE_BACKGROUND,           // ActivityManager.PROCESS_STATE_BACKUP
163         UID_STATE_BACKGROUND,           // ActivityManager.PROCESS_STATE_SERVICE
164         UID_STATE_BACKGROUND,           // ActivityManager.PROCESS_STATE_RECEIVER
165         UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_TOP_SLEEPING
166         UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
167         UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_HOME
168         UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
169         UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
170         UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
171         UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_CACHED_RECENT
172         UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_CACHED_EMPTY
173         UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_NONEXISTENT
174     };
175 
176     Context mContext;
177     final AtomicFile mFile;
178     final Handler mHandler;
179 
180     private final AppOpsManagerInternalImpl mAppOpsManagerInternal
181             = new AppOpsManagerInternalImpl();
182 
183     boolean mWriteScheduled;
184     boolean mFastWriteScheduled;
185     final Runnable mWriteRunner = new Runnable() {
186         public void run() {
187             synchronized (AppOpsService.this) {
188                 mWriteScheduled = false;
189                 mFastWriteScheduled = false;
190                 AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
191                     @Override protected Void doInBackground(Void... params) {
192                         writeState();
193                         return null;
194                     }
195                 };
196                 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null);
197             }
198         }
199     };
200 
201     @VisibleForTesting
202     final SparseArray<UidState> mUidStates = new SparseArray<>();
203 
204     final HistoricalRegistry mHistoricalRegistry = new HistoricalRegistry(this);
205 
206     long mLastRealtime;
207 
208     /*
209      * These are app op restrictions imposed per user from various parties.
210      */
211     private final ArrayMap<IBinder, ClientRestrictionState> mOpUserRestrictions = new ArrayMap<>();
212 
213     SparseIntArray mProfileOwners;
214 
215     @GuardedBy("this")
216     private CheckOpsDelegate mCheckOpsDelegate;
217 
218     /**
219      * All times are in milliseconds. These constants are kept synchronized with the system
220      * global Settings. Any access to this class or its fields should be done while
221      * holding the AppOpsService lock.
222      */
223     @VisibleForTesting
224     final class Constants extends ContentObserver {
225         // Key names stored in the settings value.
226         private static final String KEY_TOP_STATE_SETTLE_TIME = "top_state_settle_time";
227         private static final String KEY_FG_SERVICE_STATE_SETTLE_TIME
228                 = "fg_service_state_settle_time";
229         private static final String KEY_BG_STATE_SETTLE_TIME = "bg_state_settle_time";
230 
231         /**
232          * How long we want for a drop in uid state from top to settle before applying it.
233          * @see Settings.Global#APP_OPS_CONSTANTS
234          * @see #KEY_TOP_STATE_SETTLE_TIME
235          */
236         public long TOP_STATE_SETTLE_TIME;
237 
238         /**
239          * How long we want for a drop in uid state from foreground to settle before applying it.
240          * @see Settings.Global#APP_OPS_CONSTANTS
241          * @see #KEY_FG_SERVICE_STATE_SETTLE_TIME
242          */
243         public long FG_SERVICE_STATE_SETTLE_TIME;
244 
245         /**
246          * How long we want for a drop in uid state from background to settle before applying it.
247          * @see Settings.Global#APP_OPS_CONSTANTS
248          * @see #KEY_BG_STATE_SETTLE_TIME
249          */
250         public long BG_STATE_SETTLE_TIME;
251 
252         private final KeyValueListParser mParser = new KeyValueListParser(',');
253         private ContentResolver mResolver;
254 
Constants(Handler handler)255         public Constants(Handler handler) {
256             super(handler);
257             updateConstants();
258         }
259 
startMonitoring(ContentResolver resolver)260         public void startMonitoring(ContentResolver resolver) {
261             mResolver = resolver;
262             mResolver.registerContentObserver(
263                     Settings.Global.getUriFor(Settings.Global.APP_OPS_CONSTANTS),
264                     false, this);
265             updateConstants();
266         }
267 
268         @Override
onChange(boolean selfChange, Uri uri)269         public void onChange(boolean selfChange, Uri uri) {
270             updateConstants();
271         }
272 
updateConstants()273         private void updateConstants() {
274             String value = mResolver != null ? Settings.Global.getString(mResolver,
275                     Settings.Global.APP_OPS_CONSTANTS) : "";
276 
277             synchronized (AppOpsService.this) {
278                 try {
279                     mParser.setString(value);
280                 } catch (IllegalArgumentException e) {
281                     // Failed to parse the settings string, log this and move on
282                     // with defaults.
283                     Slog.e(TAG, "Bad app ops settings", e);
284                 }
285                 TOP_STATE_SETTLE_TIME = mParser.getDurationMillis(
286                         KEY_TOP_STATE_SETTLE_TIME, 30 * 1000L);
287                 FG_SERVICE_STATE_SETTLE_TIME = mParser.getDurationMillis(
288                         KEY_FG_SERVICE_STATE_SETTLE_TIME, 10 * 1000L);
289                 BG_STATE_SETTLE_TIME = mParser.getDurationMillis(
290                         KEY_BG_STATE_SETTLE_TIME, 1 * 1000L);
291             }
292         }
293 
dump(PrintWriter pw)294         void dump(PrintWriter pw) {
295             pw.println("  Settings:");
296 
297             pw.print("    "); pw.print(KEY_TOP_STATE_SETTLE_TIME); pw.print("=");
298             TimeUtils.formatDuration(TOP_STATE_SETTLE_TIME, pw);
299             pw.println();
300             pw.print("    "); pw.print(KEY_FG_SERVICE_STATE_SETTLE_TIME); pw.print("=");
301             TimeUtils.formatDuration(FG_SERVICE_STATE_SETTLE_TIME, pw);
302             pw.println();
303             pw.print("    "); pw.print(KEY_BG_STATE_SETTLE_TIME); pw.print("=");
304             TimeUtils.formatDuration(BG_STATE_SETTLE_TIME, pw);
305             pw.println();
306         }
307     }
308 
309     @VisibleForTesting
310     final Constants mConstants;
311 
312     @VisibleForTesting
313     static final class UidState {
314         public final int uid;
315 
316         public int state = UID_STATE_CACHED;
317         public int pendingState = UID_STATE_CACHED;
318         public long pendingStateCommitTime;
319 
320         public int startNesting;
321         public ArrayMap<String, Ops> pkgOps;
322         public SparseIntArray opModes;
323 
324         // true indicates there is an interested observer, false there isn't but it has such an op
325         public SparseBooleanArray foregroundOps;
326         public boolean hasForegroundWatchers;
327 
UidState(int uid)328         public UidState(int uid) {
329             this.uid = uid;
330         }
331 
clear()332         public void clear() {
333             pkgOps = null;
334             opModes = null;
335         }
336 
isDefault()337         public boolean isDefault() {
338             return (pkgOps == null || pkgOps.isEmpty())
339                     && (opModes == null || opModes.size() <= 0)
340                     && (state == UID_STATE_CACHED
341                     && (pendingState == UID_STATE_CACHED));
342         }
343 
evalMode(int op, int mode)344         int evalMode(int op, int mode) {
345             if (mode == AppOpsManager.MODE_FOREGROUND) {
346                 return state <= AppOpsManager.resolveFirstUnrestrictedUidState(op)
347                         ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED;
348             }
349             return mode;
350         }
351 
evalForegroundWatchers(int op, SparseArray<ArraySet<ModeCallback>> watchers, SparseBooleanArray which)352         private void evalForegroundWatchers(int op, SparseArray<ArraySet<ModeCallback>> watchers,
353                 SparseBooleanArray which) {
354             boolean curValue = which.get(op, false);
355             ArraySet<ModeCallback> callbacks = watchers.get(op);
356             if (callbacks != null) {
357                 for (int cbi = callbacks.size() - 1; !curValue && cbi >= 0; cbi--) {
358                     if ((callbacks.valueAt(cbi).mFlags
359                             & AppOpsManager.WATCH_FOREGROUND_CHANGES) != 0) {
360                         hasForegroundWatchers = true;
361                         curValue = true;
362                     }
363                 }
364             }
365             which.put(op, curValue);
366         }
367 
evalForegroundOps(SparseArray<ArraySet<ModeCallback>> watchers)368         public void evalForegroundOps(SparseArray<ArraySet<ModeCallback>> watchers) {
369             SparseBooleanArray which = null;
370             hasForegroundWatchers = false;
371             if (opModes != null) {
372                 for (int i = opModes.size() - 1; i >= 0; i--) {
373                     if (opModes.valueAt(i) == AppOpsManager.MODE_FOREGROUND) {
374                         if (which == null) {
375                             which = new SparseBooleanArray();
376                         }
377                         evalForegroundWatchers(opModes.keyAt(i), watchers, which);
378                     }
379                 }
380             }
381             if (pkgOps != null) {
382                 for (int i = pkgOps.size() - 1; i >= 0; i--) {
383                     Ops ops = pkgOps.valueAt(i);
384                     for (int j = ops.size() - 1; j >= 0; j--) {
385                         if (ops.valueAt(j).mode == AppOpsManager.MODE_FOREGROUND) {
386                             if (which == null) {
387                                 which = new SparseBooleanArray();
388                             }
389                             evalForegroundWatchers(ops.keyAt(j), watchers, which);
390                         }
391                     }
392                 }
393             }
394             foregroundOps = which;
395         }
396     }
397 
398     final static class Ops extends SparseArray<Op> {
399         final String packageName;
400         final UidState uidState;
401         final boolean isPrivileged;
402 
Ops(String _packageName, UidState _uidState, boolean _isPrivileged)403         Ops(String _packageName, UidState _uidState, boolean _isPrivileged) {
404             packageName = _packageName;
405             uidState = _uidState;
406             isPrivileged = _isPrivileged;
407         }
408     }
409 
410     final static class Op {
411         int op;
412         boolean running;
413         final UidState uidState;
414         final @NonNull String packageName;
415 
416         private @Mode int mode;
417         private @Nullable LongSparseLongArray mAccessTimes;
418         private @Nullable LongSparseLongArray mRejectTimes;
419         private @Nullable LongSparseLongArray mDurations;
420         private @Nullable LongSparseLongArray mProxyUids;
421         private @Nullable LongSparseArray<String> mProxyPackageNames;
422 
423         int startNesting;
424         long startRealtime;
425 
Op(UidState uidState, String packageName, int op)426         Op(UidState uidState, String packageName, int op) {
427             this.op = op;
428             this.uidState = uidState;
429             this.packageName = packageName;
430             this.mode = AppOpsManager.opToDefaultMode(op);
431         }
432 
getMode()433         int getMode() {
434             return mode;
435         }
436 
evalMode()437         int evalMode() {
438             return uidState.evalMode(op, mode);
439         }
440 
441         /** @hide */
accessed(long time, int proxyUid, @Nullable String proxyPackageName, @AppOpsManager.UidState int uidState, @OpFlags int flags)442         public void accessed(long time, int proxyUid, @Nullable String proxyPackageName,
443             @AppOpsManager.UidState int uidState, @OpFlags int flags) {
444             final long key = AppOpsManager.makeKey(uidState, flags);
445             if (mAccessTimes == null) {
446                 mAccessTimes = new LongSparseLongArray();
447             }
448             mAccessTimes.put(key, time);
449             updateProxyState(key, proxyUid, proxyPackageName);
450             if (mDurations != null) {
451                 mDurations.delete(key);
452             }
453         }
454 
455         /** @hide */
rejected(long time, int proxyUid, @Nullable String proxyPackageName, @AppOpsManager.UidState int uidState, @OpFlags int flags)456         public void rejected(long time, int proxyUid, @Nullable String proxyPackageName,
457             @AppOpsManager.UidState int uidState, @OpFlags int flags) {
458             final long key = AppOpsManager.makeKey(uidState, flags);
459             if (mRejectTimes == null) {
460                 mRejectTimes = new LongSparseLongArray();
461             }
462             mRejectTimes.put(key, time);
463             updateProxyState(key, proxyUid, proxyPackageName);
464             if (mDurations != null) {
465                 mDurations.delete(key);
466             }
467         }
468 
469         /** @hide */
started(long time, @AppOpsManager.UidState int uidState, @OpFlags int flags)470         public void started(long time, @AppOpsManager.UidState int uidState, @OpFlags int flags) {
471             updateAccessTimeAndDuration(time, -1 /*duration*/, uidState, flags);
472             running = true;
473         }
474 
475         /** @hide */
finished(long time, long duration, @AppOpsManager.UidState int uidState, @OpFlags int flags)476         public void finished(long time, long duration, @AppOpsManager.UidState int uidState,
477             @OpFlags int flags) {
478             updateAccessTimeAndDuration(time, duration, uidState, flags);
479             running = false;
480         }
481 
482         /** @hide */
running(long time, long duration, @AppOpsManager.UidState int uidState, @OpFlags int flags)483         public void running(long time, long duration, @AppOpsManager.UidState int uidState,
484             @OpFlags int flags) {
485             updateAccessTimeAndDuration(time, duration, uidState, flags);
486         }
487 
488         /** @hide */
continuing(long duration, @AppOpsManager.UidState int uidState, @OpFlags int flags)489         public void continuing(long duration, @AppOpsManager.UidState int uidState,
490             @OpFlags int flags) {
491             final long key = AppOpsManager.makeKey(uidState, flags);
492             if (mDurations == null) {
493                 mDurations = new LongSparseLongArray();
494             }
495             mDurations.put(key, duration);
496         }
497 
updateAccessTimeAndDuration(long time, long duration, @AppOpsManager.UidState int uidState, @OpFlags int flags)498         private void updateAccessTimeAndDuration(long time, long duration,
499             @AppOpsManager.UidState int uidState, @OpFlags int flags) {
500             final long key = AppOpsManager.makeKey(uidState, flags);
501             if (mAccessTimes == null) {
502                 mAccessTimes = new LongSparseLongArray();
503             }
504             mAccessTimes.put(key, time);
505             if (mDurations == null) {
506                 mDurations = new LongSparseLongArray();
507             }
508             mDurations.put(key, duration);
509         }
510 
updateProxyState(long key, int proxyUid, @Nullable String proxyPackageName)511         private void updateProxyState(long key, int proxyUid,
512             @Nullable String proxyPackageName) {
513             if (mProxyUids == null) {
514                 mProxyUids = new LongSparseLongArray();
515             }
516             mProxyUids.put(key, proxyUid);
517             if (mProxyPackageNames == null) {
518                 mProxyPackageNames = new LongSparseArray<>();
519             }
520             mProxyPackageNames.put(key, proxyPackageName);
521         }
522 
hasAnyTime()523         boolean hasAnyTime() {
524             return (mAccessTimes != null && mAccessTimes.size() > 0)
525                 || (mRejectTimes != null && mRejectTimes.size() > 0);
526         }
527     }
528 
529     final SparseArray<ArraySet<ModeCallback>> mOpModeWatchers = new SparseArray<>();
530     final ArrayMap<String, ArraySet<ModeCallback>> mPackageModeWatchers = new ArrayMap<>();
531     final ArrayMap<IBinder, ModeCallback> mModeWatchers = new ArrayMap<>();
532     final ArrayMap<IBinder, SparseArray<ActiveCallback>> mActiveWatchers = new ArrayMap<>();
533     final ArrayMap<IBinder, SparseArray<NotedCallback>> mNotedWatchers = new ArrayMap<>();
534     final SparseArray<SparseArray<Restriction>> mAudioRestrictions = new SparseArray<>();
535 
536     final class ModeCallback implements DeathRecipient {
537         final IAppOpsCallback mCallback;
538         final int mWatchingUid;
539         final int mFlags;
540         final int mCallingUid;
541         final int mCallingPid;
542 
ModeCallback(IAppOpsCallback callback, int watchingUid, int flags, int callingUid, int callingPid)543         ModeCallback(IAppOpsCallback callback, int watchingUid, int flags, int callingUid,
544                 int callingPid) {
545             mCallback = callback;
546             mWatchingUid = watchingUid;
547             mFlags = flags;
548             mCallingUid = callingUid;
549             mCallingPid = callingPid;
550             try {
551                 mCallback.asBinder().linkToDeath(this, 0);
552             } catch (RemoteException e) {
553                 /*ignored*/
554             }
555         }
556 
isWatchingUid(int uid)557         public boolean isWatchingUid(int uid) {
558             return uid == UID_ANY || mWatchingUid < 0 || mWatchingUid == uid;
559         }
560 
561         @Override
toString()562         public String toString() {
563             StringBuilder sb = new StringBuilder(128);
564             sb.append("ModeCallback{");
565             sb.append(Integer.toHexString(System.identityHashCode(this)));
566             sb.append(" watchinguid=");
567             UserHandle.formatUid(sb, mWatchingUid);
568             sb.append(" flags=0x");
569             sb.append(Integer.toHexString(mFlags));
570             sb.append(" from uid=");
571             UserHandle.formatUid(sb, mCallingUid);
572             sb.append(" pid=");
573             sb.append(mCallingPid);
574             sb.append('}');
575             return sb.toString();
576         }
577 
unlinkToDeath()578         void unlinkToDeath() {
579             mCallback.asBinder().unlinkToDeath(this, 0);
580         }
581 
582         @Override
binderDied()583         public void binderDied() {
584             stopWatchingMode(mCallback);
585         }
586     }
587 
588     final class ActiveCallback implements DeathRecipient {
589         final IAppOpsActiveCallback mCallback;
590         final int mWatchingUid;
591         final int mCallingUid;
592         final int mCallingPid;
593 
ActiveCallback(IAppOpsActiveCallback callback, int watchingUid, int callingUid, int callingPid)594         ActiveCallback(IAppOpsActiveCallback callback, int watchingUid, int callingUid,
595                 int callingPid) {
596             mCallback = callback;
597             mWatchingUid = watchingUid;
598             mCallingUid = callingUid;
599             mCallingPid = callingPid;
600             try {
601                 mCallback.asBinder().linkToDeath(this, 0);
602             } catch (RemoteException e) {
603                 /*ignored*/
604             }
605         }
606 
607         @Override
toString()608         public String toString() {
609             StringBuilder sb = new StringBuilder(128);
610             sb.append("ActiveCallback{");
611             sb.append(Integer.toHexString(System.identityHashCode(this)));
612             sb.append(" watchinguid=");
613             UserHandle.formatUid(sb, mWatchingUid);
614             sb.append(" from uid=");
615             UserHandle.formatUid(sb, mCallingUid);
616             sb.append(" pid=");
617             sb.append(mCallingPid);
618             sb.append('}');
619             return sb.toString();
620         }
621 
destroy()622         void destroy() {
623             mCallback.asBinder().unlinkToDeath(this, 0);
624         }
625 
626         @Override
binderDied()627         public void binderDied() {
628             stopWatchingActive(mCallback);
629         }
630     }
631 
632     final class NotedCallback implements DeathRecipient {
633         final IAppOpsNotedCallback mCallback;
634         final int mWatchingUid;
635         final int mCallingUid;
636         final int mCallingPid;
637 
NotedCallback(IAppOpsNotedCallback callback, int watchingUid, int callingUid, int callingPid)638         NotedCallback(IAppOpsNotedCallback callback, int watchingUid, int callingUid,
639                 int callingPid) {
640             mCallback = callback;
641             mWatchingUid = watchingUid;
642             mCallingUid = callingUid;
643             mCallingPid = callingPid;
644             try {
645                 mCallback.asBinder().linkToDeath(this, 0);
646             } catch (RemoteException e) {
647                 /*ignored*/
648             }
649         }
650 
651         @Override
toString()652         public String toString() {
653             StringBuilder sb = new StringBuilder(128);
654             sb.append("NotedCallback{");
655             sb.append(Integer.toHexString(System.identityHashCode(this)));
656             sb.append(" watchinguid=");
657             UserHandle.formatUid(sb, mWatchingUid);
658             sb.append(" from uid=");
659             UserHandle.formatUid(sb, mCallingUid);
660             sb.append(" pid=");
661             sb.append(mCallingPid);
662             sb.append('}');
663             return sb.toString();
664         }
665 
destroy()666         void destroy() {
667             mCallback.asBinder().unlinkToDeath(this, 0);
668         }
669 
670         @Override
binderDied()671         public void binderDied() {
672             stopWatchingNoted(mCallback);
673         }
674     }
675 
676     final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<>();
677 
678     final class ClientState extends Binder implements DeathRecipient {
679         final ArrayList<Op> mStartedOps = new ArrayList<>();
680         final IBinder mAppToken;
681         final int mPid;
682 
ClientState(IBinder appToken)683         ClientState(IBinder appToken) {
684             mAppToken = appToken;
685             mPid = Binder.getCallingPid();
686             // Watch only for remote processes dying
687             if (!(appToken instanceof Binder)) {
688                 try {
689                     mAppToken.linkToDeath(this, 0);
690                 } catch (RemoteException e) {
691                     /* do nothing */
692                 }
693             }
694         }
695 
696         @Override
toString()697         public String toString() {
698             return "ClientState{" +
699                     "mAppToken=" + mAppToken +
700                     ", " + "pid=" + mPid +
701                     '}';
702         }
703 
704         @Override
binderDied()705         public void binderDied() {
706             synchronized (AppOpsService.this) {
707                 for (int i=mStartedOps.size()-1; i>=0; i--) {
708                     finishOperationLocked(mStartedOps.get(i), /*finishNested*/ true);
709                 }
710                 mClients.remove(mAppToken);
711             }
712         }
713     }
714 
AppOpsService(File storagePath, Handler handler)715     public AppOpsService(File storagePath, Handler handler) {
716         LockGuard.installLock(this, LockGuard.INDEX_APP_OPS);
717         mFile = new AtomicFile(storagePath, "appops");
718         mHandler = handler;
719         mConstants = new Constants(mHandler);
720         readState();
721     }
722 
publish(Context context)723     public void publish(Context context) {
724         mContext = context;
725         ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder());
726         LocalServices.addService(AppOpsManagerInternal.class, mAppOpsManagerInternal);
727     }
728 
systemReady()729     public void systemReady() {
730         mConstants.startMonitoring(mContext.getContentResolver());
731         mHistoricalRegistry.systemReady(mContext.getContentResolver());
732 
733         synchronized (this) {
734             boolean changed = false;
735             for (int i = mUidStates.size() - 1; i >= 0; i--) {
736                 UidState uidState = mUidStates.valueAt(i);
737 
738                 String[] packageNames = getPackagesForUid(uidState.uid);
739                 if (ArrayUtils.isEmpty(packageNames)) {
740                     uidState.clear();
741                     mUidStates.removeAt(i);
742                     changed = true;
743                     continue;
744                 }
745 
746                 ArrayMap<String, Ops> pkgs = uidState.pkgOps;
747                 if (pkgs == null) {
748                     continue;
749                 }
750 
751                 Iterator<Ops> it = pkgs.values().iterator();
752                 while (it.hasNext()) {
753                     Ops ops = it.next();
754                     int curUid = -1;
755                     try {
756                         curUid = AppGlobals.getPackageManager().getPackageUid(ops.packageName,
757                                 PackageManager.MATCH_UNINSTALLED_PACKAGES,
758                                 UserHandle.getUserId(ops.uidState.uid));
759                     } catch (RemoteException ignored) {
760                     }
761                     if (curUid != ops.uidState.uid) {
762                         Slog.i(TAG, "Pruning old package " + ops.packageName
763                                 + "/" + ops.uidState + ": new uid=" + curUid);
764                         it.remove();
765                         changed = true;
766                     }
767                 }
768 
769                 if (uidState.isDefault()) {
770                     mUidStates.removeAt(i);
771                 }
772             }
773             if (changed) {
774                 scheduleFastWriteLocked();
775             }
776         }
777 
778         final IntentFilter packageSuspendFilter = new IntentFilter();
779         packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
780         packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
781         mContext.registerReceiver(new BroadcastReceiver() {
782             @Override
783             public void onReceive(Context context, Intent intent) {
784                 final int[] changedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
785                 final String[] changedPkgs = intent.getStringArrayExtra(
786                         Intent.EXTRA_CHANGED_PACKAGE_LIST);
787                 ArraySet<ModeCallback> callbacks;
788                 synchronized (AppOpsService.this) {
789                     callbacks = mOpModeWatchers.get(OP_PLAY_AUDIO);
790                     if (callbacks == null) {
791                         return;
792                     }
793                     callbacks = new ArraySet<>(callbacks);
794                 }
795                 for (int i = 0; i < changedUids.length; i++) {
796                     final int changedUid = changedUids[i];
797                     final String changedPkg = changedPkgs[i];
798                     // We trust packagemanager to insert matching uid and packageNames in the
799                     // extras
800                     notifyOpChanged(callbacks, OP_PLAY_AUDIO, changedUid, changedPkg);
801                 }
802             }
803         }, packageSuspendFilter);
804 
805         PackageManagerInternal packageManagerInternal = LocalServices.getService(
806                 PackageManagerInternal.class);
807         packageManagerInternal.setExternalSourcesPolicy(
808                 new PackageManagerInternal.ExternalSourcesPolicy() {
809                     @Override
810                     public int getPackageTrustedToInstallApps(String packageName, int uid) {
811                         int appOpMode = checkOperation(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES,
812                                 uid, packageName);
813                         switch (appOpMode) {
814                             case AppOpsManager.MODE_ALLOWED:
815                                 return PackageManagerInternal.ExternalSourcesPolicy.USER_TRUSTED;
816                             case AppOpsManager.MODE_ERRORED:
817                                 return PackageManagerInternal.ExternalSourcesPolicy.USER_BLOCKED;
818                             default:
819                                 return PackageManagerInternal.ExternalSourcesPolicy.USER_DEFAULT;
820                         }
821                     }
822                 });
823 
824         if (!StorageManager.hasIsolatedStorage()) {
825             StorageManagerInternal storageManagerInternal = LocalServices.getService(
826                     StorageManagerInternal.class);
827             storageManagerInternal.addExternalStoragePolicy(
828                     new StorageManagerInternal.ExternalStorageMountPolicy() {
829                         @Override
830                         public int getMountMode(int uid, String packageName) {
831                             if (Process.isIsolated(uid)) {
832                                 return Zygote.MOUNT_EXTERNAL_NONE;
833                             }
834                             if (noteOperation(AppOpsManager.OP_READ_EXTERNAL_STORAGE, uid,
835                                     packageName) != AppOpsManager.MODE_ALLOWED) {
836                                 return Zygote.MOUNT_EXTERNAL_NONE;
837                             }
838                             if (noteOperation(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, uid,
839                                     packageName) != AppOpsManager.MODE_ALLOWED) {
840                                 return Zygote.MOUNT_EXTERNAL_READ;
841                             }
842                             return Zygote.MOUNT_EXTERNAL_WRITE;
843                         }
844 
845                         @Override
846                         public boolean hasExternalStorage(int uid, String packageName) {
847                             final int mountMode = getMountMode(uid, packageName);
848                             return mountMode == Zygote.MOUNT_EXTERNAL_READ
849                                     || mountMode == Zygote.MOUNT_EXTERNAL_WRITE;
850                         }
851                     });
852         }
853     }
854 
packageRemoved(int uid, String packageName)855     public void packageRemoved(int uid, String packageName) {
856         synchronized (this) {
857             UidState uidState = mUidStates.get(uid);
858             if (uidState == null) {
859                 return;
860             }
861 
862             Ops ops = null;
863 
864             // Remove any package state if such.
865             if (uidState.pkgOps != null) {
866                 ops = uidState.pkgOps.remove(packageName);
867             }
868 
869             // If we just nuked the last package state check if the UID is valid.
870             if (ops != null && uidState.pkgOps.isEmpty()
871                     && getPackagesForUid(uid).length <= 0) {
872                 mUidStates.remove(uid);
873             }
874 
875             // Finish ops other packages started on behalf of the package.
876             final int clientCount = mClients.size();
877             for (int i = 0; i < clientCount; i++) {
878                 final ClientState client = mClients.valueAt(i);
879                 if (client.mStartedOps == null) {
880                     continue;
881                 }
882                 final int opCount = client.mStartedOps.size();
883                 for (int j = opCount - 1; j >= 0; j--) {
884                     final Op op = client.mStartedOps.get(j);
885                     if (uid == op.uidState.uid && packageName.equals(op.packageName)) {
886                         finishOperationLocked(op, /*finishNested*/ true);
887                         client.mStartedOps.remove(j);
888                         if (op.startNesting <= 0) {
889                             scheduleOpActiveChangedIfNeededLocked(op.op,
890                                     uid, packageName, false);
891                         }
892                     }
893                 }
894             }
895 
896             if (ops != null) {
897                 scheduleFastWriteLocked();
898 
899                 final int opCount = ops.size();
900                 for (int i = 0; i < opCount; i++) {
901                     final Op op = ops.valueAt(i);
902                     if (op.running) {
903                         scheduleOpActiveChangedIfNeededLocked(
904                                 op.op, op.uidState.uid, op.packageName, false);
905                     }
906                 }
907             }
908 
909             mHistoricalRegistry.clearHistory(uid, packageName);
910         }
911     }
912 
uidRemoved(int uid)913     public void uidRemoved(int uid) {
914         synchronized (this) {
915             if (mUidStates.indexOfKey(uid) >= 0) {
916                 mUidStates.remove(uid);
917                 scheduleFastWriteLocked();
918             }
919         }
920     }
921 
updateUidProcState(int uid, int procState)922     public void updateUidProcState(int uid, int procState) {
923         synchronized (this) {
924             final UidState uidState = getUidStateLocked(uid, true);
925             int newState = PROCESS_STATE_TO_UID_STATE[procState];
926             if (uidState != null && uidState.pendingState != newState) {
927                 final int oldPendingState = uidState.pendingState;
928                 uidState.pendingState = newState;
929                 if (newState < uidState.state
930                         || (newState <= UID_STATE_MAX_LAST_NON_RESTRICTED
931                                 && uidState.state > UID_STATE_MAX_LAST_NON_RESTRICTED)) {
932                     // We are moving to a more important state, or the new state may be in the
933                     // foreground and the old state is in the background, then always do it
934                     // immediately.
935                     commitUidPendingStateLocked(uidState);
936                 } else if (uidState.pendingStateCommitTime == 0) {
937                     // We are moving to a less important state for the first time,
938                     // delay the application for a bit.
939                     final long settleTime;
940                     if (uidState.state <= UID_STATE_TOP) {
941                         settleTime = mConstants.TOP_STATE_SETTLE_TIME;
942                     } else if (uidState.state <= UID_STATE_FOREGROUND_SERVICE) {
943                         settleTime = mConstants.FG_SERVICE_STATE_SETTLE_TIME;
944                     } else {
945                         settleTime = mConstants.BG_STATE_SETTLE_TIME;
946                     }
947                     uidState.pendingStateCommitTime = SystemClock.elapsedRealtime() + settleTime;
948                 }
949                 if (uidState.startNesting != 0) {
950                     // There is some actively running operation...  need to find it
951                     // and appropriately update its state.
952                     final long now = System.currentTimeMillis();
953                     for (int i = uidState.pkgOps.size() - 1; i >= 0; i--) {
954                         final Ops ops = uidState.pkgOps.valueAt(i);
955                         for (int j = ops.size() - 1; j >= 0; j--) {
956                             final Op op = ops.valueAt(j);
957                             if (op.startNesting > 0) {
958                                 final long duration = SystemClock.elapsedRealtime()
959                                         - op.startRealtime;
960                                 // We don't support proxy long running ops (start/stop)
961                                 mHistoricalRegistry.increaseOpAccessDuration(op.op,
962                                         op.uidState.uid, op.packageName, oldPendingState,
963                                         AppOpsManager.OP_FLAG_SELF, duration);
964                                 // Finish the op in the old state
965                                 op.finished(now, duration, oldPendingState,
966                                         AppOpsManager.OP_FLAG_SELF);
967                                 // Start the op in the new state
968                                 op.startRealtime = now;
969                                 op.started(now, newState, AppOpsManager.OP_FLAG_SELF);
970                             }
971                         }
972                     }
973                 }
974             }
975         }
976     }
977 
shutdown()978     public void shutdown() {
979         Slog.w(TAG, "Writing app ops before shutdown...");
980         boolean doWrite = false;
981         synchronized (this) {
982             if (mWriteScheduled) {
983                 mWriteScheduled = false;
984                 doWrite = true;
985             }
986         }
987         if (doWrite) {
988             writeState();
989         }
990     }
991 
collectOps(Ops pkgOps, int[] ops)992     private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) {
993         ArrayList<AppOpsManager.OpEntry> resOps = null;
994         final long elapsedNow = SystemClock.elapsedRealtime();
995         if (ops == null) {
996             resOps = new ArrayList<>();
997             for (int j=0; j<pkgOps.size(); j++) {
998                 Op curOp = pkgOps.valueAt(j);
999                 resOps.add(getOpEntryForResult(curOp, elapsedNow));
1000             }
1001         } else {
1002             for (int j=0; j<ops.length; j++) {
1003                 Op curOp = pkgOps.get(ops[j]);
1004                 if (curOp != null) {
1005                     if (resOps == null) {
1006                         resOps = new ArrayList<>();
1007                     }
1008                     resOps.add(getOpEntryForResult(curOp, elapsedNow));
1009                 }
1010             }
1011         }
1012         return resOps;
1013     }
1014 
collectOps(SparseIntArray uidOps, int[] ops)1015     private ArrayList<AppOpsManager.OpEntry> collectOps(SparseIntArray uidOps, int[] ops) {
1016         if (uidOps == null) {
1017             return null;
1018         }
1019         ArrayList<AppOpsManager.OpEntry> resOps = null;
1020         if (ops == null) {
1021             resOps = new ArrayList<>();
1022             for (int j=0; j<uidOps.size(); j++) {
1023                 resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j)));
1024             }
1025         } else {
1026             for (int j=0; j<ops.length; j++) {
1027                 int index = uidOps.indexOfKey(ops[j]);
1028                 if (index >= 0) {
1029                     if (resOps == null) {
1030                         resOps = new ArrayList<>();
1031                     }
1032                     resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j)));
1033                 }
1034             }
1035         }
1036         return resOps;
1037     }
1038 
getOpEntryForResult(@onNull Op op, long elapsedNow)1039     private static @NonNull OpEntry getOpEntryForResult(@NonNull Op op, long elapsedNow) {
1040         if (op.running) {
1041             op.continuing(elapsedNow - op.startRealtime,
1042                 op.uidState.state, AppOpsManager.OP_FLAG_SELF);
1043         }
1044         final OpEntry entry = new OpEntry(op.op, op.running, op.mode,
1045             op.mAccessTimes != null ? op.mAccessTimes.clone() : null,
1046             op.mRejectTimes != null ? op.mRejectTimes.clone() : null,
1047             op.mDurations != null ? op.mDurations.clone() : null,
1048             op.mProxyUids != null ? op.mProxyUids.clone() : null,
1049             op.mProxyPackageNames != null ? op.mProxyPackageNames.clone() : null);
1050         return entry;
1051     }
1052 
1053     @Override
getPackagesForOps(int[] ops)1054     public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
1055         mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
1056                 Binder.getCallingPid(), Binder.getCallingUid(), null);
1057         ArrayList<AppOpsManager.PackageOps> res = null;
1058         synchronized (this) {
1059             final int uidStateCount = mUidStates.size();
1060             for (int i = 0; i < uidStateCount; i++) {
1061                 UidState uidState = mUidStates.valueAt(i);
1062                 if (uidState.pkgOps == null || uidState.pkgOps.isEmpty()) {
1063                     continue;
1064                 }
1065                 ArrayMap<String, Ops> packages = uidState.pkgOps;
1066                 final int packageCount = packages.size();
1067                 for (int j = 0; j < packageCount; j++) {
1068                     Ops pkgOps = packages.valueAt(j);
1069                     ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
1070                     if (resOps != null) {
1071                         if (res == null) {
1072                             res = new ArrayList<AppOpsManager.PackageOps>();
1073                         }
1074                         AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
1075                                 pkgOps.packageName, pkgOps.uidState.uid, resOps);
1076                         res.add(resPackage);
1077                     }
1078                 }
1079             }
1080         }
1081         return res;
1082     }
1083 
1084     @Override
getOpsForPackage(int uid, String packageName, int[] ops)1085     public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName,
1086             int[] ops) {
1087         mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
1088                 Binder.getCallingPid(), Binder.getCallingUid(), null);
1089         String resolvedPackageName = resolvePackageName(uid, packageName);
1090         if (resolvedPackageName == null) {
1091             return Collections.emptyList();
1092         }
1093         synchronized (this) {
1094             Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false /* edit */,
1095                     false /* uidMismatchExpected */);
1096             if (pkgOps == null) {
1097                 return null;
1098             }
1099             ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
1100             if (resOps == null) {
1101                 return null;
1102             }
1103             ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>();
1104             AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
1105                     pkgOps.packageName, pkgOps.uidState.uid, resOps);
1106             res.add(resPackage);
1107             return res;
1108         }
1109     }
1110 
1111     @Override
getHistoricalOps(int uid, @NonNull String packageName, @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis, @OpFlags int flags, @NonNull RemoteCallback callback)1112     public void getHistoricalOps(int uid, @NonNull String packageName,
1113             @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis,
1114             @OpFlags int flags, @NonNull RemoteCallback callback) {
1115         // Use the builder to validate arguments.
1116         new HistoricalOpsRequest.Builder(
1117                 beginTimeMillis, endTimeMillis)
1118                 .setUid(uid)
1119                 .setPackageName(packageName)
1120                 .setOpNames(opNames)
1121                 .setFlags(flags)
1122                 .build();
1123         Preconditions.checkNotNull(callback, "callback cannot be null");
1124 
1125         mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
1126                 Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");
1127 
1128         final String[] opNamesArray = (opNames != null)
1129                 ? opNames.toArray(new String[opNames.size()]) : null;
1130 
1131         // Must not hold the appops lock
1132         mHistoricalRegistry.getHistoricalOps(uid, packageName, opNamesArray,
1133                 beginTimeMillis, endTimeMillis, flags, callback);
1134     }
1135 
1136     @Override
getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName, @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis, @OpFlags int flags, @NonNull RemoteCallback callback)1137     public void getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName,
1138             @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis,
1139             @OpFlags int flags, @NonNull RemoteCallback callback) {
1140         // Use the builder to validate arguments.
1141         new HistoricalOpsRequest.Builder(
1142                 beginTimeMillis, endTimeMillis)
1143                 .setUid(uid)
1144                 .setPackageName(packageName)
1145                 .setOpNames(opNames)
1146                 .setFlags(flags)
1147                 .build();
1148         Preconditions.checkNotNull(callback, "callback cannot be null");
1149 
1150         mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS,
1151                 Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");
1152 
1153         final String[] opNamesArray = (opNames != null)
1154                 ? opNames.toArray(new String[opNames.size()]) : null;
1155 
1156         // Must not hold the appops lock
1157         mHistoricalRegistry.getHistoricalOpsFromDiskRaw(uid, packageName, opNamesArray,
1158                 beginTimeMillis, endTimeMillis, flags, callback);
1159     }
1160 
1161     @Override
reloadNonHistoricalState()1162     public void reloadNonHistoricalState() {
1163         mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS,
1164                 Binder.getCallingPid(), Binder.getCallingUid(), "reloadNonHistoricalState");
1165         writeState();
1166         readState();
1167     }
1168 
1169     @Override
getUidOps(int uid, int[] ops)1170     public List<AppOpsManager.PackageOps> getUidOps(int uid, int[] ops) {
1171         mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
1172                 Binder.getCallingPid(), Binder.getCallingUid(), null);
1173         synchronized (this) {
1174             UidState uidState = getUidStateLocked(uid, false);
1175             if (uidState == null) {
1176                 return null;
1177             }
1178             ArrayList<AppOpsManager.OpEntry> resOps = collectOps(uidState.opModes, ops);
1179             if (resOps == null) {
1180                 return null;
1181             }
1182             ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>();
1183             AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
1184                     null, uidState.uid, resOps);
1185             res.add(resPackage);
1186             return res;
1187         }
1188     }
1189 
pruneOp(Op op, int uid, String packageName)1190     private void pruneOp(Op op, int uid, String packageName) {
1191         if (!op.hasAnyTime()) {
1192             Ops ops = getOpsRawLocked(uid, packageName, false /* edit */,
1193                     false /* uidMismatchExpected */);
1194             if (ops != null) {
1195                 ops.remove(op.op);
1196                 if (ops.size() <= 0) {
1197                     UidState uidState = ops.uidState;
1198                     ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
1199                     if (pkgOps != null) {
1200                         pkgOps.remove(ops.packageName);
1201                         if (pkgOps.isEmpty()) {
1202                             uidState.pkgOps = null;
1203                         }
1204                         if (uidState.isDefault()) {
1205                             mUidStates.remove(uid);
1206                         }
1207                     }
1208                 }
1209             }
1210         }
1211     }
1212 
enforceManageAppOpsModes(int callingPid, int callingUid, int targetUid)1213     private void enforceManageAppOpsModes(int callingPid, int callingUid, int targetUid) {
1214         if (callingPid == Process.myPid()) {
1215             return;
1216         }
1217         final int callingUser = UserHandle.getUserId(callingUid);
1218         synchronized (this) {
1219             if (mProfileOwners != null && mProfileOwners.get(callingUser, -1) == callingUid) {
1220                 if (targetUid >= 0 && callingUser == UserHandle.getUserId(targetUid)) {
1221                     // Profile owners are allowed to change modes but only for apps
1222                     // within their user.
1223                     return;
1224                 }
1225             }
1226         }
1227         mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
1228                 Binder.getCallingPid(), Binder.getCallingUid(), null);
1229     }
1230 
1231     @Override
setUidMode(int code, int uid, int mode)1232     public void setUidMode(int code, int uid, int mode) {
1233         if (DEBUG) {
1234             Slog.i(TAG, "uid " + uid + " OP_" + opToName(code) + " := " + modeToName(mode)
1235                     + " by uid " + Binder.getCallingUid());
1236         }
1237 
1238         enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
1239         verifyIncomingOp(code);
1240         code = AppOpsManager.opToSwitch(code);
1241 
1242         synchronized (this) {
1243             final int defaultMode = AppOpsManager.opToDefaultMode(code);
1244 
1245             UidState uidState = getUidStateLocked(uid, false);
1246             if (uidState == null) {
1247                 if (mode == defaultMode) {
1248                     return;
1249                 }
1250                 uidState = new UidState(uid);
1251                 uidState.opModes = new SparseIntArray();
1252                 uidState.opModes.put(code, mode);
1253                 mUidStates.put(uid, uidState);
1254                 scheduleWriteLocked();
1255             } else if (uidState.opModes == null) {
1256                 if (mode != defaultMode) {
1257                     uidState.opModes = new SparseIntArray();
1258                     uidState.opModes.put(code, mode);
1259                     scheduleWriteLocked();
1260                 }
1261             } else {
1262                 if (uidState.opModes.indexOfKey(code) >= 0 && uidState.opModes.get(code) == mode) {
1263                     return;
1264                 }
1265                 if (mode == defaultMode) {
1266                     uidState.opModes.delete(code);
1267                     if (uidState.opModes.size() <= 0) {
1268                         uidState.opModes = null;
1269                     }
1270                 } else {
1271                     uidState.opModes.put(code, mode);
1272                 }
1273                 scheduleWriteLocked();
1274             }
1275             uidState.evalForegroundOps(mOpModeWatchers);
1276         }
1277 
1278         String[] uidPackageNames = getPackagesForUid(uid);
1279         ArrayMap<ModeCallback, ArraySet<String>> callbackSpecs = null;
1280 
1281         synchronized (this) {
1282             ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code);
1283             if (callbacks != null) {
1284                 final int callbackCount = callbacks.size();
1285                 for (int i = 0; i < callbackCount; i++) {
1286                     ModeCallback callback = callbacks.valueAt(i);
1287                     ArraySet<String> changedPackages = new ArraySet<>();
1288                     Collections.addAll(changedPackages, uidPackageNames);
1289                     if (callbackSpecs == null) {
1290                         callbackSpecs = new ArrayMap<>();
1291                     }
1292                     callbackSpecs.put(callback, changedPackages);
1293                 }
1294             }
1295 
1296             for (String uidPackageName : uidPackageNames) {
1297                 callbacks = mPackageModeWatchers.get(uidPackageName);
1298                 if (callbacks != null) {
1299                     if (callbackSpecs == null) {
1300                         callbackSpecs = new ArrayMap<>();
1301                     }
1302                     final int callbackCount = callbacks.size();
1303                     for (int i = 0; i < callbackCount; i++) {
1304                         ModeCallback callback = callbacks.valueAt(i);
1305                         ArraySet<String> changedPackages = callbackSpecs.get(callback);
1306                         if (changedPackages == null) {
1307                             changedPackages = new ArraySet<>();
1308                             callbackSpecs.put(callback, changedPackages);
1309                         }
1310                         changedPackages.add(uidPackageName);
1311                     }
1312                 }
1313             }
1314         }
1315 
1316         if (callbackSpecs == null) {
1317             notifyOpChangedSync(code, uid, null, mode);
1318             return;
1319         }
1320 
1321         for (int i = 0; i < callbackSpecs.size(); i++) {
1322             final ModeCallback callback = callbackSpecs.keyAt(i);
1323             final ArraySet<String> reportedPackageNames = callbackSpecs.valueAt(i);
1324             if (reportedPackageNames == null) {
1325                 mHandler.sendMessage(PooledLambda.obtainMessage(
1326                         AppOpsService::notifyOpChanged,
1327                         this, callback, code, uid, (String) null));
1328 
1329             } else {
1330                 final int reportedPackageCount = reportedPackageNames.size();
1331                 for (int j = 0; j < reportedPackageCount; j++) {
1332                     final String reportedPackageName = reportedPackageNames.valueAt(j);
1333                     mHandler.sendMessage(PooledLambda.obtainMessage(
1334                             AppOpsService::notifyOpChanged,
1335                             this, callback, code, uid, reportedPackageName));
1336                 }
1337             }
1338         }
1339 
1340         notifyOpChangedSync(code, uid, null, mode);
1341     }
1342 
notifyOpChangedSync(int code, int uid, @NonNull String packageName, int mode)1343     private void notifyOpChangedSync(int code, int uid, @NonNull String packageName, int mode) {
1344         final StorageManagerInternal storageManagerInternal =
1345                 LocalServices.getService(StorageManagerInternal.class);
1346         if (storageManagerInternal != null) {
1347             storageManagerInternal.onAppOpsChanged(code, uid, packageName, mode);
1348         }
1349     }
1350 
1351     /**
1352      * Set all {@link #setMode (package) modes} for this uid to the default value.
1353      *
1354      * @param code The app-op
1355      * @param uid The uid
1356      */
setAllPkgModesToDefault(int code, int uid)1357     private void setAllPkgModesToDefault(int code, int uid) {
1358         synchronized (this) {
1359             UidState uidState = getUidStateLocked(uid, false);
1360             if (uidState == null) {
1361                 return;
1362             }
1363 
1364             ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
1365             if (pkgOps == null) {
1366                 return;
1367             }
1368 
1369             boolean scheduleWrite = false;
1370 
1371             int numPkgs = pkgOps.size();
1372             for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) {
1373                 Ops ops = pkgOps.valueAt(pkgNum);
1374 
1375                 Op op = ops.get(code);
1376                 if (op == null) {
1377                     continue;
1378                 }
1379 
1380                 int defaultMode = AppOpsManager.opToDefaultMode(code);
1381                 if (op.mode != defaultMode) {
1382                     op.mode = defaultMode;
1383                     scheduleWrite = true;
1384                 }
1385             }
1386 
1387             if (scheduleWrite) {
1388                 scheduleWriteLocked();
1389             }
1390         }
1391     }
1392 
1393     @Override
setMode(int code, int uid, String packageName, int mode)1394     public void setMode(int code, int uid, String packageName, int mode) {
1395         setMode(code, uid, packageName, mode, true, false);
1396     }
1397 
1398     /**
1399      * Sets the mode for a certain op and uid.
1400      *
1401      * @param code The op code to set
1402      * @param uid The UID for which to set
1403      * @param packageName The package for which to set
1404      * @param mode The new mode to set
1405      * @param verifyUid Iff {@code true}, check that the package name belongs to the uid
1406      * @param isPrivileged Whether the package is privileged. (Only used if {@code verifyUid ==
1407      *                     false})
1408      */
setMode(int code, int uid, @NonNull String packageName, int mode, boolean verifyUid, boolean isPrivileged)1409     private void setMode(int code, int uid, @NonNull String packageName, int mode,
1410             boolean verifyUid, boolean isPrivileged) {
1411         enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
1412         verifyIncomingOp(code);
1413         ArraySet<ModeCallback> repCbs = null;
1414         code = AppOpsManager.opToSwitch(code);
1415         synchronized (this) {
1416             UidState uidState = getUidStateLocked(uid, false);
1417             Op op = getOpLocked(code, uid, packageName, true, verifyUid, isPrivileged);
1418             if (op != null) {
1419                 if (op.mode != mode) {
1420                     op.mode = mode;
1421                     if (uidState != null) {
1422                         uidState.evalForegroundOps(mOpModeWatchers);
1423                     }
1424                     ArraySet<ModeCallback> cbs = mOpModeWatchers.get(code);
1425                     if (cbs != null) {
1426                         if (repCbs == null) {
1427                             repCbs = new ArraySet<>();
1428                         }
1429                         repCbs.addAll(cbs);
1430                     }
1431                     cbs = mPackageModeWatchers.get(packageName);
1432                     if (cbs != null) {
1433                         if (repCbs == null) {
1434                             repCbs = new ArraySet<>();
1435                         }
1436                         repCbs.addAll(cbs);
1437                     }
1438                     if (mode == AppOpsManager.opToDefaultMode(op.op)) {
1439                         // If going into the default mode, prune this op
1440                         // if there is nothing else interesting in it.
1441                         pruneOp(op, uid, packageName);
1442                     }
1443                     scheduleFastWriteLocked();
1444                 }
1445             }
1446         }
1447         if (repCbs != null) {
1448             mHandler.sendMessage(PooledLambda.obtainMessage(
1449                     AppOpsService::notifyOpChanged,
1450                     this, repCbs, code, uid, packageName));
1451         }
1452 
1453         notifyOpChangedSync(code, uid, packageName, mode);
1454     }
1455 
notifyOpChanged(ArraySet<ModeCallback> callbacks, int code, int uid, String packageName)1456     private void notifyOpChanged(ArraySet<ModeCallback> callbacks, int code,
1457             int uid, String packageName) {
1458         for (int i = 0; i < callbacks.size(); i++) {
1459             final ModeCallback callback = callbacks.valueAt(i);
1460             notifyOpChanged(callback, code, uid, packageName);
1461         }
1462     }
1463 
notifyOpChanged(ModeCallback callback, int code, int uid, String packageName)1464     private void notifyOpChanged(ModeCallback callback, int code,
1465             int uid, String packageName) {
1466         if (uid != UID_ANY && callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) {
1467             return;
1468         }
1469         // There are components watching for mode changes such as window manager
1470         // and location manager which are in our process. The callbacks in these
1471         // components may require permissions our remote caller does not have.
1472         final long identity = Binder.clearCallingIdentity();
1473         try {
1474             callback.mCallback.opChanged(code, uid, packageName);
1475         } catch (RemoteException e) {
1476             /* ignore */
1477         } finally {
1478             Binder.restoreCallingIdentity(identity);
1479         }
1480     }
1481 
addCallbacks( HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks, int op, int uid, String packageName, ArraySet<ModeCallback> cbs)1482     private static HashMap<ModeCallback, ArrayList<ChangeRec>> addCallbacks(
1483             HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks,
1484             int op, int uid, String packageName, ArraySet<ModeCallback> cbs) {
1485         if (cbs == null) {
1486             return callbacks;
1487         }
1488         if (callbacks == null) {
1489             callbacks = new HashMap<>();
1490         }
1491         boolean duplicate = false;
1492         final int N = cbs.size();
1493         for (int i=0; i<N; i++) {
1494             ModeCallback cb = cbs.valueAt(i);
1495             ArrayList<ChangeRec> reports = callbacks.get(cb);
1496             if (reports == null) {
1497                 reports = new ArrayList<>();
1498                 callbacks.put(cb, reports);
1499             } else {
1500                 final int reportCount = reports.size();
1501                 for (int j = 0; j < reportCount; j++) {
1502                     ChangeRec report = reports.get(j);
1503                     if (report.op == op && report.pkg.equals(packageName)) {
1504                         duplicate = true;
1505                         break;
1506                     }
1507                 }
1508             }
1509             if (!duplicate) {
1510                 reports.add(new ChangeRec(op, uid, packageName));
1511             }
1512         }
1513         return callbacks;
1514     }
1515 
1516     static final class ChangeRec {
1517         final int op;
1518         final int uid;
1519         final String pkg;
1520 
ChangeRec(int _op, int _uid, String _pkg)1521         ChangeRec(int _op, int _uid, String _pkg) {
1522             op = _op;
1523             uid = _uid;
1524             pkg = _pkg;
1525         }
1526     }
1527 
1528     @Override
resetAllModes(int reqUserId, String reqPackageName)1529     public void resetAllModes(int reqUserId, String reqPackageName) {
1530         final int callingPid = Binder.getCallingPid();
1531         final int callingUid = Binder.getCallingUid();
1532         reqUserId = ActivityManager.handleIncomingUser(callingPid, callingUid, reqUserId,
1533                 true, true, "resetAllModes", null);
1534 
1535         int reqUid = -1;
1536         if (reqPackageName != null) {
1537             try {
1538                 reqUid = AppGlobals.getPackageManager().getPackageUid(
1539                         reqPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, reqUserId);
1540             } catch (RemoteException e) {
1541                 /* ignore - local call */
1542             }
1543         }
1544 
1545         enforceManageAppOpsModes(callingPid, callingUid, reqUid);
1546 
1547         HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks = null;
1548         synchronized (this) {
1549             boolean changed = false;
1550             for (int i = mUidStates.size() - 1; i >= 0; i--) {
1551                 UidState uidState = mUidStates.valueAt(i);
1552 
1553                 SparseIntArray opModes = uidState.opModes;
1554                 if (opModes != null && (uidState.uid == reqUid || reqUid == -1)) {
1555                     final int uidOpCount = opModes.size();
1556                     for (int j = uidOpCount - 1; j >= 0; j--) {
1557                         final int code = opModes.keyAt(j);
1558                         if (AppOpsManager.opAllowsReset(code)) {
1559                             opModes.removeAt(j);
1560                             if (opModes.size() <= 0) {
1561                                 uidState.opModes = null;
1562                             }
1563                             for (String packageName : getPackagesForUid(uidState.uid)) {
1564                                 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
1565                                         mOpModeWatchers.get(code));
1566                                 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
1567                                         mPackageModeWatchers.get(packageName));
1568                             }
1569                         }
1570                     }
1571                 }
1572 
1573                 if (uidState.pkgOps == null) {
1574                     continue;
1575                 }
1576 
1577                 if (reqUserId != UserHandle.USER_ALL
1578                         && reqUserId != UserHandle.getUserId(uidState.uid)) {
1579                     // Skip any ops for a different user
1580                     continue;
1581                 }
1582 
1583                 Map<String, Ops> packages = uidState.pkgOps;
1584                 Iterator<Map.Entry<String, Ops>> it = packages.entrySet().iterator();
1585                 boolean uidChanged = false;
1586                 while (it.hasNext()) {
1587                     Map.Entry<String, Ops> ent = it.next();
1588                     String packageName = ent.getKey();
1589                     if (reqPackageName != null && !reqPackageName.equals(packageName)) {
1590                         // Skip any ops for a different package
1591                         continue;
1592                     }
1593                     Ops pkgOps = ent.getValue();
1594                     for (int j=pkgOps.size()-1; j>=0; j--) {
1595                         Op curOp = pkgOps.valueAt(j);
1596                         if (AppOpsManager.opAllowsReset(curOp.op)
1597                                 && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) {
1598                             curOp.mode = AppOpsManager.opToDefaultMode(curOp.op);
1599                             changed = true;
1600                             uidChanged = true;
1601                             final int uid = curOp.uidState.uid;
1602                             callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
1603                                     mOpModeWatchers.get(curOp.op));
1604                             callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
1605                                     mPackageModeWatchers.get(packageName));
1606                             if (!curOp.hasAnyTime()) {
1607                                 pkgOps.removeAt(j);
1608                             }
1609                         }
1610                     }
1611                     if (pkgOps.size() == 0) {
1612                         it.remove();
1613                     }
1614                 }
1615                 if (uidState.isDefault()) {
1616                     mUidStates.remove(uidState.uid);
1617                 }
1618                 if (uidChanged) {
1619                     uidState.evalForegroundOps(mOpModeWatchers);
1620                 }
1621             }
1622 
1623             if (changed) {
1624                 scheduleFastWriteLocked();
1625             }
1626         }
1627         if (callbacks != null) {
1628             for (Map.Entry<ModeCallback, ArrayList<ChangeRec>> ent : callbacks.entrySet()) {
1629                 ModeCallback cb = ent.getKey();
1630                 ArrayList<ChangeRec> reports = ent.getValue();
1631                 for (int i=0; i<reports.size(); i++) {
1632                     ChangeRec rep = reports.get(i);
1633                     mHandler.sendMessage(PooledLambda.obtainMessage(
1634                             AppOpsService::notifyOpChanged,
1635                             this, cb, rep.op, rep.uid, rep.pkg));
1636                 }
1637             }
1638         }
1639     }
1640 
evalAllForegroundOpsLocked()1641     private void evalAllForegroundOpsLocked() {
1642         for (int uidi = mUidStates.size() - 1; uidi >= 0; uidi--) {
1643             final UidState uidState = mUidStates.valueAt(uidi);
1644             if (uidState.foregroundOps != null) {
1645                 uidState.evalForegroundOps(mOpModeWatchers);
1646             }
1647         }
1648     }
1649 
1650     @Override
startWatchingMode(int op, String packageName, IAppOpsCallback callback)1651     public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) {
1652         startWatchingModeWithFlags(op, packageName, 0, callback);
1653     }
1654 
1655     @Override
startWatchingModeWithFlags(int op, String packageName, int flags, IAppOpsCallback callback)1656     public void startWatchingModeWithFlags(int op, String packageName, int flags,
1657             IAppOpsCallback callback) {
1658         int watchedUid = -1;
1659         final int callingUid = Binder.getCallingUid();
1660         final int callingPid = Binder.getCallingPid();
1661         // TODO: should have a privileged permission to protect this.
1662         // Also, if the caller has requested WATCH_FOREGROUND_CHANGES, should we require
1663         // the USAGE_STATS permission since this can provide information about when an
1664         // app is in the foreground?
1665         Preconditions.checkArgumentInRange(op, AppOpsManager.OP_NONE,
1666                 AppOpsManager._NUM_OP - 1, "Invalid op code: " + op);
1667         if (callback == null) {
1668             return;
1669         }
1670         synchronized (this) {
1671             op = (op != AppOpsManager.OP_NONE) ? AppOpsManager.opToSwitch(op) : op;
1672             ModeCallback cb = mModeWatchers.get(callback.asBinder());
1673             if (cb == null) {
1674                 cb = new ModeCallback(callback, watchedUid, flags, callingUid, callingPid);
1675                 mModeWatchers.put(callback.asBinder(), cb);
1676             }
1677             if (op != AppOpsManager.OP_NONE) {
1678                 ArraySet<ModeCallback> cbs = mOpModeWatchers.get(op);
1679                 if (cbs == null) {
1680                     cbs = new ArraySet<>();
1681                     mOpModeWatchers.put(op, cbs);
1682                 }
1683                 cbs.add(cb);
1684             }
1685             if (packageName != null) {
1686                 ArraySet<ModeCallback> cbs = mPackageModeWatchers.get(packageName);
1687                 if (cbs == null) {
1688                     cbs = new ArraySet<>();
1689                     mPackageModeWatchers.put(packageName, cbs);
1690                 }
1691                 cbs.add(cb);
1692             }
1693             evalAllForegroundOpsLocked();
1694         }
1695     }
1696 
1697     @Override
stopWatchingMode(IAppOpsCallback callback)1698     public void stopWatchingMode(IAppOpsCallback callback) {
1699         if (callback == null) {
1700             return;
1701         }
1702         synchronized (this) {
1703             ModeCallback cb = mModeWatchers.remove(callback.asBinder());
1704             if (cb != null) {
1705                 cb.unlinkToDeath();
1706                 for (int i=mOpModeWatchers.size()-1; i>=0; i--) {
1707                     ArraySet<ModeCallback> cbs = mOpModeWatchers.valueAt(i);
1708                     cbs.remove(cb);
1709                     if (cbs.size() <= 0) {
1710                         mOpModeWatchers.removeAt(i);
1711                     }
1712                 }
1713                 for (int i=mPackageModeWatchers.size()-1; i>=0; i--) {
1714                     ArraySet<ModeCallback> cbs = mPackageModeWatchers.valueAt(i);
1715                     cbs.remove(cb);
1716                     if (cbs.size() <= 0) {
1717                         mPackageModeWatchers.removeAt(i);
1718                     }
1719                 }
1720             }
1721             evalAllForegroundOpsLocked();
1722         }
1723     }
1724 
1725     @Override
getToken(IBinder clientToken)1726     public IBinder getToken(IBinder clientToken) {
1727         synchronized (this) {
1728             ClientState cs = mClients.get(clientToken);
1729             if (cs == null) {
1730                 cs = new ClientState(clientToken);
1731                 mClients.put(clientToken, cs);
1732             }
1733             return cs;
1734         }
1735     }
1736 
getAppOpsServiceDelegate()1737     public CheckOpsDelegate getAppOpsServiceDelegate() {
1738         synchronized (this) {
1739             return mCheckOpsDelegate;
1740         }
1741     }
1742 
setAppOpsServiceDelegate(CheckOpsDelegate delegate)1743     public void setAppOpsServiceDelegate(CheckOpsDelegate delegate) {
1744         synchronized (this) {
1745             mCheckOpsDelegate = delegate;
1746         }
1747     }
1748 
1749     @Override
checkOperationRaw(int code, int uid, String packageName)1750     public int checkOperationRaw(int code, int uid, String packageName) {
1751         return checkOperationInternal(code, uid, packageName, true /*raw*/);
1752     }
1753 
1754     @Override
checkOperation(int code, int uid, String packageName)1755     public int checkOperation(int code, int uid, String packageName) {
1756         return checkOperationInternal(code, uid, packageName, false /*raw*/);
1757     }
1758 
checkOperationInternal(int code, int uid, String packageName, boolean raw)1759     private int checkOperationInternal(int code, int uid, String packageName, boolean raw) {
1760         final CheckOpsDelegate delegate;
1761         synchronized (this) {
1762             delegate = mCheckOpsDelegate;
1763         }
1764         if (delegate == null) {
1765             return checkOperationImpl(code, uid, packageName, raw);
1766         }
1767         return delegate.checkOperation(code, uid, packageName, raw,
1768                     AppOpsService.this::checkOperationImpl);
1769     }
1770 
checkOperationImpl(int code, int uid, String packageName, boolean raw)1771     private int checkOperationImpl(int code, int uid, String packageName,
1772                 boolean raw) {
1773         verifyIncomingUid(uid);
1774         verifyIncomingOp(code);
1775         String resolvedPackageName = resolvePackageName(uid, packageName);
1776         if (resolvedPackageName == null) {
1777             return AppOpsManager.MODE_IGNORED;
1778         }
1779         return checkOperationUnchecked(code, uid, resolvedPackageName, raw);
1780     }
1781 
1782     /**
1783      * @see #checkOperationUnchecked(int, int, String, boolean, boolean)
1784      */
checkOperationUnchecked(int code, int uid, @NonNull String packageName, boolean raw)1785     private @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName,
1786             boolean raw) {
1787         return checkOperationUnchecked(code, uid, packageName, raw, true);
1788     }
1789 
1790     /**
1791      * Get the mode of an app-op.
1792      *
1793      * @param code The code of the op
1794      * @param uid The uid of the package the op belongs to
1795      * @param packageName The package the op belongs to
1796      * @param raw If the raw state of eval-ed state should be checked.
1797      * @param verify If the code should check the package belongs to the uid
1798      *
1799      * @return The mode of the op
1800      */
checkOperationUnchecked(int code, int uid, @NonNull String packageName, boolean raw, boolean verify)1801     private @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName,
1802                 boolean raw, boolean verify) {
1803         synchronized (this) {
1804             if (verify) {
1805                 checkPackage(uid, packageName);
1806             }
1807             if (isOpRestrictedLocked(uid, code, packageName)) {
1808                 return AppOpsManager.MODE_IGNORED;
1809             }
1810             code = AppOpsManager.opToSwitch(code);
1811             UidState uidState = getUidStateLocked(uid, false);
1812             if (uidState != null && uidState.opModes != null
1813                     && uidState.opModes.indexOfKey(code) >= 0) {
1814                 final int rawMode = uidState.opModes.get(code);
1815                 return raw ? rawMode : uidState.evalMode(code, rawMode);
1816             }
1817             Op op = getOpLocked(code, uid, packageName, false, verify, false);
1818             if (op == null) {
1819                 return AppOpsManager.opToDefaultMode(code);
1820             }
1821             return raw ? op.mode : op.evalMode();
1822         }
1823     }
1824 
1825     @Override
checkAudioOperation(int code, int usage, int uid, String packageName)1826     public int checkAudioOperation(int code, int usage, int uid, String packageName) {
1827         final CheckOpsDelegate delegate;
1828         synchronized (this) {
1829             delegate = mCheckOpsDelegate;
1830         }
1831         if (delegate == null) {
1832             return checkAudioOperationImpl(code, usage, uid, packageName);
1833         }
1834         return delegate.checkAudioOperation(code, usage, uid, packageName,
1835                 AppOpsService.this::checkAudioOperationImpl);
1836     }
1837 
checkAudioOperationImpl(int code, int usage, int uid, String packageName)1838     private int checkAudioOperationImpl(int code, int usage, int uid, String packageName) {
1839         boolean suspended;
1840         try {
1841             suspended = isPackageSuspendedForUser(packageName, uid);
1842         } catch (IllegalArgumentException ex) {
1843             // Package not found.
1844             suspended = false;
1845         }
1846 
1847         if (suspended) {
1848             Slog.i(TAG, "Audio disabled for suspended package=" + packageName
1849                     + " for uid=" + uid);
1850             return AppOpsManager.MODE_IGNORED;
1851         }
1852 
1853         synchronized (this) {
1854             final int mode = checkRestrictionLocked(code, usage, uid, packageName);
1855             if (mode != AppOpsManager.MODE_ALLOWED) {
1856                 return mode;
1857             }
1858         }
1859         return checkOperation(code, uid, packageName);
1860     }
1861 
isPackageSuspendedForUser(String pkg, int uid)1862     private boolean isPackageSuspendedForUser(String pkg, int uid) {
1863         final long identity = Binder.clearCallingIdentity();
1864         try {
1865             return AppGlobals.getPackageManager().isPackageSuspendedForUser(
1866                     pkg, UserHandle.getUserId(uid));
1867         } catch (RemoteException re) {
1868             throw new SecurityException("Could not talk to package manager service");
1869         } finally {
1870             Binder.restoreCallingIdentity(identity);
1871         }
1872     }
1873 
checkRestrictionLocked(int code, int usage, int uid, String packageName)1874     private int checkRestrictionLocked(int code, int usage, int uid, String packageName) {
1875         final SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code);
1876         if (usageRestrictions != null) {
1877             final Restriction r = usageRestrictions.get(usage);
1878             if (r != null && !r.exceptionPackages.contains(packageName)) {
1879                 return r.mode;
1880             }
1881         }
1882         return AppOpsManager.MODE_ALLOWED;
1883     }
1884 
1885     @Override
setAudioRestriction(int code, int usage, int uid, int mode, String[] exceptionPackages)1886     public void setAudioRestriction(int code, int usage, int uid, int mode,
1887             String[] exceptionPackages) {
1888         enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
1889         verifyIncomingUid(uid);
1890         verifyIncomingOp(code);
1891         synchronized (this) {
1892             SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code);
1893             if (usageRestrictions == null) {
1894                 usageRestrictions = new SparseArray<Restriction>();
1895                 mAudioRestrictions.put(code, usageRestrictions);
1896             }
1897             usageRestrictions.remove(usage);
1898             if (mode != AppOpsManager.MODE_ALLOWED) {
1899                 final Restriction r = new Restriction();
1900                 r.mode = mode;
1901                 if (exceptionPackages != null) {
1902                     final int N = exceptionPackages.length;
1903                     r.exceptionPackages = new ArraySet<String>(N);
1904                     for (int i = 0; i < N; i++) {
1905                         final String pkg = exceptionPackages[i];
1906                         if (pkg != null) {
1907                             r.exceptionPackages.add(pkg.trim());
1908                         }
1909                     }
1910                 }
1911                 usageRestrictions.put(usage, r);
1912             }
1913         }
1914 
1915         mHandler.sendMessage(PooledLambda.obtainMessage(
1916                 AppOpsService::notifyWatchersOfChange, this, code, UID_ANY));
1917     }
1918 
1919     @Override
checkPackage(int uid, String packageName)1920     public int checkPackage(int uid, String packageName) {
1921         Preconditions.checkNotNull(packageName);
1922         synchronized (this) {
1923             Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
1924                     true /* uidMismatchExpected */);
1925             if (ops != null) {
1926                 return AppOpsManager.MODE_ALLOWED;
1927             } else {
1928                 return AppOpsManager.MODE_ERRORED;
1929             }
1930         }
1931     }
1932 
1933     @Override
noteProxyOperation(int code, int proxyUid, String proxyPackageName, int proxiedUid, String proxiedPackageName)1934     public int noteProxyOperation(int code, int proxyUid,
1935             String proxyPackageName, int proxiedUid, String proxiedPackageName) {
1936         verifyIncomingUid(proxyUid);
1937         verifyIncomingOp(code);
1938 
1939         String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
1940         if (resolveProxyPackageName == null) {
1941             return AppOpsManager.MODE_IGNORED;
1942         }
1943 
1944         final boolean isProxyTrusted = mContext.checkPermission(
1945                 Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
1946                 == PackageManager.PERMISSION_GRANTED;
1947 
1948         final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
1949                 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
1950         final int proxyMode = noteOperationUnchecked(code, proxyUid,
1951                 resolveProxyPackageName, Process.INVALID_UID, null, proxyFlags);
1952         if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) {
1953             return proxyMode;
1954         }
1955 
1956         String resolveProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName);
1957         if (resolveProxiedPackageName == null) {
1958             return AppOpsManager.MODE_IGNORED;
1959         }
1960         final int proxiedFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXIED
1961                 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED;
1962         return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName,
1963                 proxyUid, resolveProxyPackageName, proxiedFlags);
1964     }
1965 
1966     @Override
noteOperation(int code, int uid, String packageName)1967     public int noteOperation(int code, int uid, String packageName) {
1968         final CheckOpsDelegate delegate;
1969         synchronized (this) {
1970             delegate = mCheckOpsDelegate;
1971         }
1972         if (delegate == null) {
1973             return noteOperationImpl(code, uid, packageName);
1974         }
1975         return delegate.noteOperation(code, uid, packageName,
1976                 AppOpsService.this::noteOperationImpl);
1977     }
1978 
noteOperationImpl(int code, int uid, String packageName)1979     private int noteOperationImpl(int code, int uid, String packageName) {
1980         verifyIncomingUid(uid);
1981         verifyIncomingOp(code);
1982         String resolvedPackageName = resolvePackageName(uid, packageName);
1983         if (resolvedPackageName == null) {
1984             return AppOpsManager.MODE_IGNORED;
1985         }
1986         return noteOperationUnchecked(code, uid, resolvedPackageName, Process.INVALID_UID, null,
1987                 AppOpsManager.OP_FLAG_SELF);
1988     }
1989 
noteOperationUnchecked(int code, int uid, String packageName, int proxyUid, String proxyPackageName, @OpFlags int flags)1990     private int noteOperationUnchecked(int code, int uid, String packageName,
1991             int proxyUid, String proxyPackageName, @OpFlags int flags) {
1992         synchronized (this) {
1993             final Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
1994                     false /* uidMismatchExpected */);
1995             if (ops == null) {
1996                 scheduleOpNotedIfNeededLocked(code, uid, packageName,
1997                         AppOpsManager.MODE_IGNORED);
1998                 if (DEBUG) Slog.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
1999                         + " package " + packageName);
2000                 return AppOpsManager.MODE_ERRORED;
2001             }
2002             final Op op = getOpLocked(ops, code, true);
2003             if (isOpRestrictedLocked(uid, code, packageName)) {
2004                 scheduleOpNotedIfNeededLocked(code, uid, packageName,
2005                         AppOpsManager.MODE_IGNORED);
2006                 return AppOpsManager.MODE_IGNORED;
2007             }
2008             final UidState uidState = ops.uidState;
2009             if (op.running) {
2010                 final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes,
2011                     op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames);
2012                 Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
2013                         + " code " + code + " time=" + entry.getLastAccessTime(uidState.state,
2014                         uidState.state, flags) + " duration=" + entry.getLastDuration(
2015                                 uidState.state, uidState.state, flags));
2016             }
2017 
2018             final int switchCode = AppOpsManager.opToSwitch(code);
2019             // If there is a non-default per UID policy (we set UID op mode only if
2020             // non-default) it takes over, otherwise use the per package policy.
2021             if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
2022                 final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode));
2023                 if (uidMode != AppOpsManager.MODE_ALLOWED) {
2024                     if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
2025                             + switchCode + " (" + code + ") uid " + uid + " package "
2026                             + packageName);
2027                     op.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName,
2028                             uidState.state, flags);
2029                     mHistoricalRegistry.incrementOpRejected(code, uid, packageName,
2030                             uidState.state, flags);
2031                     scheduleOpNotedIfNeededLocked(code, uid, packageName, uidMode);
2032                     return uidMode;
2033                 }
2034             } else {
2035                 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
2036                 final int mode = switchOp.evalMode();
2037                 if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
2038                     if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + mode + " for code "
2039                             + switchCode + " (" + code + ") uid " + uid + " package "
2040                             + packageName);
2041                     op.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName,
2042                             uidState.state, flags);
2043                     mHistoricalRegistry.incrementOpRejected(code, uid, packageName,
2044                             uidState.state, flags);
2045                     scheduleOpNotedIfNeededLocked(code, uid, packageName, mode);
2046                     return mode;
2047                 }
2048             }
2049             if (DEBUG) Slog.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
2050                     + " package " + packageName);
2051             op.accessed(System.currentTimeMillis(), proxyUid, proxyPackageName,
2052                     uidState.state, flags);
2053             mHistoricalRegistry.incrementOpAccessedCount(op.op, uid, packageName,
2054                     uidState.state, flags);
2055             scheduleOpNotedIfNeededLocked(code, uid, packageName,
2056                     AppOpsManager.MODE_ALLOWED);
2057             return AppOpsManager.MODE_ALLOWED;
2058         }
2059     }
2060 
2061     @Override
startWatchingActive(int[] ops, IAppOpsActiveCallback callback)2062     public void startWatchingActive(int[] ops, IAppOpsActiveCallback callback) {
2063         int watchedUid = -1;
2064         final int callingUid = Binder.getCallingUid();
2065         final int callingPid = Binder.getCallingPid();
2066         if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS)
2067                 != PackageManager.PERMISSION_GRANTED) {
2068             watchedUid = callingUid;
2069         }
2070         if (ops != null) {
2071             Preconditions.checkArrayElementsInRange(ops, 0,
2072                     AppOpsManager._NUM_OP - 1, "Invalid op code in: " + Arrays.toString(ops));
2073         }
2074         if (callback == null) {
2075             return;
2076         }
2077         synchronized (this) {
2078             SparseArray<ActiveCallback> callbacks = mActiveWatchers.get(callback.asBinder());
2079             if (callbacks == null) {
2080                 callbacks = new SparseArray<>();
2081                 mActiveWatchers.put(callback.asBinder(), callbacks);
2082             }
2083             final ActiveCallback activeCallback = new ActiveCallback(callback, watchedUid,
2084                     callingUid, callingPid);
2085             for (int op : ops) {
2086                 callbacks.put(op, activeCallback);
2087             }
2088         }
2089     }
2090 
2091     @Override
stopWatchingActive(IAppOpsActiveCallback callback)2092     public void stopWatchingActive(IAppOpsActiveCallback callback) {
2093         if (callback == null) {
2094             return;
2095         }
2096         synchronized (this) {
2097             final SparseArray<ActiveCallback> activeCallbacks =
2098                     mActiveWatchers.remove(callback.asBinder());
2099             if (activeCallbacks == null) {
2100                 return;
2101             }
2102             final int callbackCount = activeCallbacks.size();
2103             for (int i = 0; i < callbackCount; i++) {
2104                 activeCallbacks.valueAt(i).destroy();
2105             }
2106         }
2107     }
2108 
2109     @Override
startWatchingNoted(@onNull int[] ops, @NonNull IAppOpsNotedCallback callback)2110     public void startWatchingNoted(@NonNull int[] ops, @NonNull IAppOpsNotedCallback callback) {
2111         int watchedUid = Process.INVALID_UID;
2112         final int callingUid = Binder.getCallingUid();
2113         final int callingPid = Binder.getCallingPid();
2114         if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS)
2115                 != PackageManager.PERMISSION_GRANTED) {
2116             watchedUid = callingUid;
2117         }
2118         Preconditions.checkArgument(!ArrayUtils.isEmpty(ops), "Ops cannot be null or empty");
2119         Preconditions.checkArrayElementsInRange(ops, 0, AppOpsManager._NUM_OP - 1,
2120                 "Invalid op code in: " + Arrays.toString(ops));
2121         Preconditions.checkNotNull(callback, "Callback cannot be null");
2122         synchronized (this) {
2123             SparseArray<NotedCallback> callbacks = mNotedWatchers.get(callback.asBinder());
2124             if (callbacks == null) {
2125                 callbacks = new SparseArray<>();
2126                 mNotedWatchers.put(callback.asBinder(), callbacks);
2127             }
2128             final NotedCallback notedCallback = new NotedCallback(callback, watchedUid,
2129                     callingUid, callingPid);
2130             for (int op : ops) {
2131                 callbacks.put(op, notedCallback);
2132             }
2133         }
2134     }
2135 
2136     @Override
stopWatchingNoted(IAppOpsNotedCallback callback)2137     public void stopWatchingNoted(IAppOpsNotedCallback callback) {
2138         Preconditions.checkNotNull(callback, "Callback cannot be null");
2139         synchronized (this) {
2140             final SparseArray<NotedCallback> notedCallbacks =
2141                     mNotedWatchers.remove(callback.asBinder());
2142             if (notedCallbacks == null) {
2143                 return;
2144             }
2145             final int callbackCount = notedCallbacks.size();
2146             for (int i = 0; i < callbackCount; i++) {
2147                 notedCallbacks.valueAt(i).destroy();
2148             }
2149         }
2150     }
2151 
2152     @Override
startOperation(IBinder token, int code, int uid, String packageName, boolean startIfModeDefault)2153     public int startOperation(IBinder token, int code, int uid, String packageName,
2154             boolean startIfModeDefault) {
2155         verifyIncomingUid(uid);
2156         verifyIncomingOp(code);
2157         String resolvedPackageName = resolvePackageName(uid, packageName);
2158         if (resolvedPackageName == null) {
2159             return  AppOpsManager.MODE_IGNORED;
2160         }
2161         ClientState client = (ClientState)token;
2162         synchronized (this) {
2163             final Ops ops = getOpsRawLocked(uid, resolvedPackageName, true /* edit */,
2164                     false /* uidMismatchExpected */);
2165             if (ops == null) {
2166                 if (DEBUG) Slog.d(TAG, "startOperation: no op for code " + code + " uid " + uid
2167                         + " package " + resolvedPackageName);
2168                 return AppOpsManager.MODE_ERRORED;
2169             }
2170             final Op op = getOpLocked(ops, code, true);
2171             if (isOpRestrictedLocked(uid, code, resolvedPackageName)) {
2172                 return AppOpsManager.MODE_IGNORED;
2173             }
2174             final int switchCode = AppOpsManager.opToSwitch(code);
2175             final UidState uidState = ops.uidState;
2176             // If there is a non-default per UID policy (we set UID op mode only if
2177             // non-default) it takes over, otherwise use the per package policy.
2178             final int opCode = op.op;
2179             if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
2180                 final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode));
2181                 if (uidMode != AppOpsManager.MODE_ALLOWED
2182                         && (!startIfModeDefault || uidMode != AppOpsManager.MODE_DEFAULT)) {
2183                     if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
2184                             + switchCode + " (" + code + ") uid " + uid + " package "
2185                             + resolvedPackageName);
2186                     // We don't support proxy long running ops (start/stop)
2187                     op.rejected(System.currentTimeMillis(), -1 /*proxyUid*/,
2188                             null /*proxyPackage*/, uidState.state, AppOpsManager.OP_FLAG_SELF);
2189                     mHistoricalRegistry.incrementOpRejected(opCode, uid, packageName,
2190                             uidState.state, AppOpsManager.OP_FLAG_SELF);
2191                     return uidMode;
2192                 }
2193             } else {
2194                 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
2195                 final int mode = switchOp.evalMode();
2196                 if (mode != AppOpsManager.MODE_ALLOWED
2197                         && (!startIfModeDefault || mode != AppOpsManager.MODE_DEFAULT)) {
2198                     if (DEBUG) Slog.d(TAG, "startOperation: reject #" + mode + " for code "
2199                             + switchCode + " (" + code + ") uid " + uid + " package "
2200                             + resolvedPackageName);
2201                     // We don't support proxy long running ops (start/stop)
2202                     op.rejected(System.currentTimeMillis(), -1 /*proxyUid*/,
2203                             null /*proxyPackage*/, uidState.state, AppOpsManager.OP_FLAG_SELF);
2204                     mHistoricalRegistry.incrementOpRejected(opCode, uid, packageName,
2205                             uidState.state, AppOpsManager.OP_FLAG_SELF);
2206                     return mode;
2207                 }
2208             }
2209             if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
2210                     + " package " + resolvedPackageName);
2211             if (op.startNesting == 0) {
2212                 op.startRealtime = SystemClock.elapsedRealtime();
2213                 // We don't support proxy long running ops (start/stop)
2214                 op.started(System.currentTimeMillis(), uidState.state,
2215                         AppOpsManager.OP_FLAG_SELF);
2216                 mHistoricalRegistry.incrementOpAccessedCount(opCode, uid, packageName,
2217                         uidState.state, AppOpsManager.OP_FLAG_SELF);
2218 
2219                 scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, true);
2220             }
2221             op.startNesting++;
2222             uidState.startNesting++;
2223             if (client.mStartedOps != null) {
2224                 client.mStartedOps.add(op);
2225             }
2226         }
2227 
2228         return AppOpsManager.MODE_ALLOWED;
2229     }
2230 
2231     @Override
finishOperation(IBinder token, int code, int uid, String packageName)2232     public void finishOperation(IBinder token, int code, int uid, String packageName) {
2233         verifyIncomingUid(uid);
2234         verifyIncomingOp(code);
2235         String resolvedPackageName = resolvePackageName(uid, packageName);
2236         if (resolvedPackageName == null) {
2237             return;
2238         }
2239         if (!(token instanceof ClientState)) {
2240             return;
2241         }
2242         ClientState client = (ClientState) token;
2243         synchronized (this) {
2244             Op op = getOpLocked(code, uid, resolvedPackageName, true, true, false);
2245             if (op == null) {
2246                 return;
2247             }
2248             if (!client.mStartedOps.remove(op)) {
2249                 // We finish ops when packages get removed to guarantee no dangling
2250                 // started ops. However, some part of the system may asynchronously
2251                 // finish ops for an already gone package. Hence, finishing an op
2252                 // for a non existing package is fine and we don't log as a wtf.
2253                 final long identity = Binder.clearCallingIdentity();
2254                 try {
2255                     if (LocalServices.getService(PackageManagerInternal.class).getPackageUid(
2256                             resolvedPackageName, 0, UserHandle.getUserId(uid)) < 0) {
2257                         Slog.i(TAG, "Finishing op=" + AppOpsManager.opToName(code)
2258                                 + " for non-existing package=" + resolvedPackageName
2259                                 + " in uid=" + uid);
2260                         return;
2261                     }
2262                 } finally {
2263                     Binder.restoreCallingIdentity(identity);
2264                 }
2265                 Slog.wtf(TAG, "Operation not started: uid=" + op.uidState.uid + " pkg="
2266                         + op.packageName + " op=" + AppOpsManager.opToName(op.op));
2267                 return;
2268             }
2269             finishOperationLocked(op, /*finishNested*/ false);
2270             if (op.startNesting <= 0) {
2271                 scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, false);
2272             }
2273         }
2274     }
2275 
scheduleOpActiveChangedIfNeededLocked(int code, int uid, String packageName, boolean active)2276     private void scheduleOpActiveChangedIfNeededLocked(int code, int uid, String packageName,
2277             boolean active) {
2278         ArraySet<ActiveCallback> dispatchedCallbacks = null;
2279         final int callbackListCount = mActiveWatchers.size();
2280         for (int i = 0; i < callbackListCount; i++) {
2281             final SparseArray<ActiveCallback> callbacks = mActiveWatchers.valueAt(i);
2282             ActiveCallback callback = callbacks.get(code);
2283             if (callback != null) {
2284                 if (callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) {
2285                     continue;
2286                 }
2287                 if (dispatchedCallbacks == null) {
2288                     dispatchedCallbacks = new ArraySet<>();
2289                 }
2290                 dispatchedCallbacks.add(callback);
2291             }
2292         }
2293         if (dispatchedCallbacks == null) {
2294             return;
2295         }
2296         mHandler.sendMessage(PooledLambda.obtainMessage(
2297                 AppOpsService::notifyOpActiveChanged,
2298                 this, dispatchedCallbacks, code, uid, packageName, active));
2299     }
2300 
notifyOpActiveChanged(ArraySet<ActiveCallback> callbacks, int code, int uid, String packageName, boolean active)2301     private void notifyOpActiveChanged(ArraySet<ActiveCallback> callbacks,
2302             int code, int uid, String packageName, boolean active) {
2303         // There are components watching for mode changes such as window manager
2304         // and location manager which are in our process. The callbacks in these
2305         // components may require permissions our remote caller does not have.
2306         final long identity = Binder.clearCallingIdentity();
2307         try {
2308             final int callbackCount = callbacks.size();
2309             for (int i = 0; i < callbackCount; i++) {
2310                 final ActiveCallback callback = callbacks.valueAt(i);
2311                 try {
2312                     callback.mCallback.opActiveChanged(code, uid, packageName, active);
2313                 } catch (RemoteException e) {
2314                     /* do nothing */
2315                 }
2316             }
2317         } finally {
2318             Binder.restoreCallingIdentity(identity);
2319         }
2320     }
2321 
scheduleOpNotedIfNeededLocked(int code, int uid, String packageName, int result)2322     private void scheduleOpNotedIfNeededLocked(int code, int uid, String packageName,
2323             int result) {
2324         ArraySet<NotedCallback> dispatchedCallbacks = null;
2325         final int callbackListCount = mNotedWatchers.size();
2326         for (int i = 0; i < callbackListCount; i++) {
2327             final SparseArray<NotedCallback> callbacks = mNotedWatchers.valueAt(i);
2328             final NotedCallback callback = callbacks.get(code);
2329             if (callback != null) {
2330                 if (callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) {
2331                     continue;
2332                 }
2333                 if (dispatchedCallbacks == null) {
2334                     dispatchedCallbacks = new ArraySet<>();
2335                 }
2336                 dispatchedCallbacks.add(callback);
2337             }
2338         }
2339         if (dispatchedCallbacks == null) {
2340             return;
2341         }
2342         mHandler.sendMessage(PooledLambda.obtainMessage(
2343                 AppOpsService::notifyOpChecked,
2344                 this, dispatchedCallbacks, code, uid, packageName, result));
2345     }
2346 
notifyOpChecked(ArraySet<NotedCallback> callbacks, int code, int uid, String packageName, int result)2347     private void notifyOpChecked(ArraySet<NotedCallback> callbacks,
2348             int code, int uid, String packageName, int result) {
2349         // There are components watching for checks in our process. The callbacks in
2350         // these components may require permissions our remote caller does not have.
2351         final long identity = Binder.clearCallingIdentity();
2352         try {
2353             final int callbackCount = callbacks.size();
2354             for (int i = 0; i < callbackCount; i++) {
2355                 final NotedCallback callback = callbacks.valueAt(i);
2356                 try {
2357                     callback.mCallback.opNoted(code, uid, packageName, result);
2358                 } catch (RemoteException e) {
2359                     /* do nothing */
2360                 }
2361             }
2362         } finally {
2363             Binder.restoreCallingIdentity(identity);
2364         }
2365     }
2366 
2367     @Override
permissionToOpCode(String permission)2368     public int permissionToOpCode(String permission) {
2369         if (permission == null) {
2370             return AppOpsManager.OP_NONE;
2371         }
2372         return AppOpsManager.permissionToOpCode(permission);
2373     }
2374 
finishOperationLocked(Op op, boolean finishNested)2375     void finishOperationLocked(Op op, boolean finishNested) {
2376         final int opCode = op.op;
2377         final int uid = op.uidState.uid;
2378         if (op.startNesting <= 1 || finishNested) {
2379             if (op.startNesting == 1 || finishNested) {
2380                 // We don't support proxy long running ops (start/stop)
2381                 final long duration = SystemClock.elapsedRealtime() - op.startRealtime;
2382                 op.finished(System.currentTimeMillis(), duration, op.uidState.state,
2383                         AppOpsManager.OP_FLAG_SELF);
2384                 mHistoricalRegistry.increaseOpAccessDuration(opCode, uid, op.packageName,
2385                         op.uidState.state, AppOpsManager.OP_FLAG_SELF, duration);
2386             } else {
2387                 final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes,
2388                     op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames);
2389                 Slog.w(TAG, "Finishing op nesting under-run: uid " + uid + " pkg "
2390                         + op.packageName + " code " + opCode + " time="
2391                         + entry.getLastAccessTime(OP_FLAGS_ALL)
2392                         + " duration=" + entry.getLastDuration(MAX_PRIORITY_UID_STATE,
2393                         MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL) + " nesting=" + op.startNesting);
2394             }
2395             if (op.startNesting >= 1) {
2396                 op.uidState.startNesting -= op.startNesting;
2397             }
2398             op.startNesting = 0;
2399         } else {
2400             op.startNesting--;
2401             op.uidState.startNesting--;
2402         }
2403     }
2404 
verifyIncomingUid(int uid)2405     private void verifyIncomingUid(int uid) {
2406         if (uid == Binder.getCallingUid()) {
2407             return;
2408         }
2409         if (Binder.getCallingPid() == Process.myPid()) {
2410             return;
2411         }
2412         mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
2413                 Binder.getCallingPid(), Binder.getCallingUid(), null);
2414     }
2415 
verifyIncomingOp(int op)2416     private void verifyIncomingOp(int op) {
2417         if (op >= 0 && op < AppOpsManager._NUM_OP) {
2418             return;
2419         }
2420         throw new IllegalArgumentException("Bad operation #" + op);
2421     }
2422 
getUidStateLocked(int uid, boolean edit)2423     private @Nullable UidState getUidStateLocked(int uid, boolean edit) {
2424         UidState uidState = mUidStates.get(uid);
2425         if (uidState == null) {
2426             if (!edit) {
2427                 return null;
2428             }
2429             uidState = new UidState(uid);
2430             mUidStates.put(uid, uidState);
2431         } else {
2432             if (uidState.pendingStateCommitTime != 0) {
2433                 if (uidState.pendingStateCommitTime < mLastRealtime) {
2434                     commitUidPendingStateLocked(uidState);
2435                 } else {
2436                     mLastRealtime = SystemClock.elapsedRealtime();
2437                     if (uidState.pendingStateCommitTime < mLastRealtime) {
2438                         commitUidPendingStateLocked(uidState);
2439                     }
2440                 }
2441             }
2442         }
2443         return uidState;
2444     }
2445 
commitUidPendingStateLocked(UidState uidState)2446     private void commitUidPendingStateLocked(UidState uidState) {
2447         if (uidState.hasForegroundWatchers) {
2448             for (int fgi = uidState.foregroundOps.size() - 1; fgi >= 0; fgi--) {
2449                 if (!uidState.foregroundOps.valueAt(fgi)) {
2450                     continue;
2451                 }
2452                 final int code = uidState.foregroundOps.keyAt(fgi);
2453                 // For location ops we consider fg state only if the fg service
2454                 // is of location type, for all other ops any fg service will do.
2455                 final long firstUnrestrictedUidState = resolveFirstUnrestrictedUidState(code);
2456                 final boolean resolvedLastFg = uidState.state <= firstUnrestrictedUidState;
2457                 final boolean resolvedNowFg = uidState.pendingState <= firstUnrestrictedUidState;
2458                 if (resolvedLastFg == resolvedNowFg) {
2459                     continue;
2460                 }
2461                 final ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code);
2462                 if (callbacks != null) {
2463                     for (int cbi = callbacks.size() - 1; cbi >= 0; cbi--) {
2464                         final ModeCallback callback = callbacks.valueAt(cbi);
2465                         if ((callback.mFlags & AppOpsManager.WATCH_FOREGROUND_CHANGES) == 0
2466                                 || !callback.isWatchingUid(uidState.uid)) {
2467                             continue;
2468                         }
2469                         boolean doAllPackages = uidState.opModes != null
2470                                 && uidState.opModes.indexOfKey(code) >= 0
2471                                 && uidState.opModes.get(code) == AppOpsManager.MODE_FOREGROUND;
2472                         if (uidState.pkgOps != null) {
2473                             for (int pkgi = uidState.pkgOps.size() - 1; pkgi >= 0; pkgi--) {
2474                                 final Op op = uidState.pkgOps.valueAt(pkgi).get(code);
2475                                 if (op == null) {
2476                                     continue;
2477                                 }
2478                                 if (doAllPackages || op.mode == AppOpsManager.MODE_FOREGROUND) {
2479                                     mHandler.sendMessage(PooledLambda.obtainMessage(
2480                                             AppOpsService::notifyOpChanged,
2481                                             this, callback, code, uidState.uid,
2482                                             uidState.pkgOps.keyAt(pkgi)));
2483                                 }
2484                             }
2485                         }
2486                     }
2487                 }
2488             }
2489         }
2490         uidState.state = uidState.pendingState;
2491         uidState.pendingStateCommitTime = 0;
2492     }
2493 
getOpsRawLocked(int uid, String packageName, boolean edit, boolean uidMismatchExpected)2494     private Ops getOpsRawLocked(int uid, String packageName, boolean edit,
2495             boolean uidMismatchExpected) {
2496         UidState uidState = getUidStateLocked(uid, edit);
2497         if (uidState == null) {
2498             return null;
2499         }
2500 
2501         if (uidState.pkgOps == null) {
2502             if (!edit) {
2503                 return null;
2504             }
2505             uidState.pkgOps = new ArrayMap<>();
2506         }
2507 
2508         Ops ops = uidState.pkgOps.get(packageName);
2509         if (ops == null) {
2510             if (!edit) {
2511                 return null;
2512             }
2513             boolean isPrivileged = false;
2514             // This is the first time we have seen this package name under this uid,
2515             // so let's make sure it is valid.
2516             if (uid != 0) {
2517                 final long ident = Binder.clearCallingIdentity();
2518                 try {
2519                     int pkgUid = -1;
2520                     try {
2521                         ApplicationInfo appInfo = ActivityThread.getPackageManager()
2522                                 .getApplicationInfo(packageName,
2523                                         PackageManager.MATCH_DIRECT_BOOT_AWARE
2524                                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
2525                                         UserHandle.getUserId(uid));
2526                         if (appInfo != null) {
2527                             pkgUid = appInfo.uid;
2528                             isPrivileged = (appInfo.privateFlags
2529                                     & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
2530                         } else {
2531                             pkgUid = resolveUid(packageName);
2532                             if (pkgUid >= 0) {
2533                                 isPrivileged = false;
2534                             }
2535                         }
2536                     } catch (RemoteException e) {
2537                         Slog.w(TAG, "Could not contact PackageManager", e);
2538                     }
2539                     if (pkgUid != uid) {
2540                         // Oops!  The package name is not valid for the uid they are calling
2541                         // under.  Abort.
2542                         if (!uidMismatchExpected) {
2543                             RuntimeException ex = new RuntimeException("here");
2544                             ex.fillInStackTrace();
2545                             Slog.w(TAG, "Bad call: specified package " + packageName
2546                                     + " under uid " + uid + " but it is really " + pkgUid, ex);
2547                         }
2548                         return null;
2549                     }
2550                 } finally {
2551                     Binder.restoreCallingIdentity(ident);
2552                 }
2553             }
2554             ops = new Ops(packageName, uidState, isPrivileged);
2555             uidState.pkgOps.put(packageName, ops);
2556         }
2557         return ops;
2558     }
2559 
2560     /**
2561      * Get the state of all ops for a package, <b>don't verify that package belongs to uid</b>.
2562      *
2563      * <p>Usually callers should use {@link #getOpLocked} and not call this directly.
2564      *
2565      * @param uid The uid the of the package
2566      * @param packageName The package name for which to get the state for
2567      * @param edit Iff {@code true} create the {@link Ops} object if not yet created
2568      * @param isPrivileged Whether the package is privileged or not
2569      *
2570      * @return The {@link Ops state} of all ops for the package
2571      */
getOpsRawNoVerifyLocked(int uid, @NonNull String packageName, boolean edit, boolean isPrivileged)2572     private @Nullable Ops getOpsRawNoVerifyLocked(int uid, @NonNull String packageName,
2573             boolean edit, boolean isPrivileged) {
2574         UidState uidState = getUidStateLocked(uid, edit);
2575         if (uidState == null) {
2576             return null;
2577         }
2578 
2579         if (uidState.pkgOps == null) {
2580             if (!edit) {
2581                 return null;
2582             }
2583             uidState.pkgOps = new ArrayMap<>();
2584         }
2585 
2586         Ops ops = uidState.pkgOps.get(packageName);
2587         if (ops == null) {
2588             if (!edit) {
2589                 return null;
2590             }
2591             ops = new Ops(packageName, uidState, isPrivileged);
2592             uidState.pkgOps.put(packageName, ops);
2593         }
2594         return ops;
2595     }
2596 
scheduleWriteLocked()2597     private void scheduleWriteLocked() {
2598         if (!mWriteScheduled) {
2599             mWriteScheduled = true;
2600             mHandler.postDelayed(mWriteRunner, WRITE_DELAY);
2601         }
2602     }
2603 
scheduleFastWriteLocked()2604     private void scheduleFastWriteLocked() {
2605         if (!mFastWriteScheduled) {
2606             mWriteScheduled = true;
2607             mFastWriteScheduled = true;
2608             mHandler.removeCallbacks(mWriteRunner);
2609             mHandler.postDelayed(mWriteRunner, 10*1000);
2610         }
2611     }
2612 
2613     /**
2614      * Get the state of an op for a uid.
2615      *
2616      * @param code The code of the op
2617      * @param uid The uid the of the package
2618      * @param packageName The package name for which to get the state for
2619      * @param edit Iff {@code true} create the {@link Op} object if not yet created
2620      * @param verifyUid Iff {@code true} check that the package belongs to the uid
2621      * @param isPrivileged Whether the package is privileged or not (only used if {@code verifyUid
2622      *                     == false})
2623      *
2624      * @return The {@link Op state} of the op
2625      */
getOpLocked(int code, int uid, @NonNull String packageName, boolean edit, boolean verifyUid, boolean isPrivileged)2626     private @Nullable Op getOpLocked(int code, int uid, @NonNull String packageName, boolean edit,
2627             boolean verifyUid, boolean isPrivileged) {
2628         Ops ops;
2629 
2630         if (verifyUid) {
2631             ops = getOpsRawLocked(uid, packageName, edit, false /* uidMismatchExpected */);
2632         }  else {
2633             ops = getOpsRawNoVerifyLocked(uid, packageName, edit, isPrivileged);
2634         }
2635 
2636         if (ops == null) {
2637             return null;
2638         }
2639         return getOpLocked(ops, code, edit);
2640     }
2641 
getOpLocked(Ops ops, int code, boolean edit)2642     private Op getOpLocked(Ops ops, int code, boolean edit) {
2643         Op op = ops.get(code);
2644         if (op == null) {
2645             if (!edit) {
2646                 return null;
2647             }
2648             op = new Op(ops.uidState, ops.packageName, code);
2649             ops.put(code, op);
2650         }
2651         if (edit) {
2652             scheduleWriteLocked();
2653         }
2654         return op;
2655     }
2656 
isOpRestrictedLocked(int uid, int code, String packageName)2657     private boolean isOpRestrictedLocked(int uid, int code, String packageName) {
2658         int userHandle = UserHandle.getUserId(uid);
2659         final int restrictionSetCount = mOpUserRestrictions.size();
2660 
2661         for (int i = 0; i < restrictionSetCount; i++) {
2662             // For each client, check that the given op is not restricted, or that the given
2663             // package is exempt from the restriction.
2664             ClientRestrictionState restrictionState = mOpUserRestrictions.valueAt(i);
2665             if (restrictionState.hasRestriction(code, packageName, userHandle)) {
2666                 if (AppOpsManager.opAllowSystemBypassRestriction(code)) {
2667                     // If we are the system, bypass user restrictions for certain codes
2668                     synchronized (this) {
2669                         Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
2670                                 false /* uidMismatchExpected */);
2671                         if ((ops != null) && ops.isPrivileged) {
2672                             return false;
2673                         }
2674                     }
2675                 }
2676                 return true;
2677             }
2678         }
2679         return false;
2680     }
2681 
readState()2682     void readState() {
2683         int oldVersion = NO_VERSION;
2684         synchronized (mFile) {
2685             synchronized (this) {
2686                 FileInputStream stream;
2687                 try {
2688                     stream = mFile.openRead();
2689                 } catch (FileNotFoundException e) {
2690                     Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty");
2691                     return;
2692                 }
2693                 boolean success = false;
2694                 mUidStates.clear();
2695                 try {
2696                     XmlPullParser parser = Xml.newPullParser();
2697                     parser.setInput(stream, StandardCharsets.UTF_8.name());
2698                     int type;
2699                     while ((type = parser.next()) != XmlPullParser.START_TAG
2700                             && type != XmlPullParser.END_DOCUMENT) {
2701                         ;
2702                     }
2703 
2704                     if (type != XmlPullParser.START_TAG) {
2705                         throw new IllegalStateException("no start tag found");
2706                     }
2707 
2708                     final String versionString = parser.getAttributeValue(null, "v");
2709                     if (versionString != null) {
2710                         oldVersion = Integer.parseInt(versionString);
2711                     }
2712 
2713                     int outerDepth = parser.getDepth();
2714                     while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2715                             && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2716                         if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2717                             continue;
2718                         }
2719 
2720                         String tagName = parser.getName();
2721                         if (tagName.equals("pkg")) {
2722                             readPackage(parser);
2723                         } else if (tagName.equals("uid")) {
2724                             readUidOps(parser);
2725                         } else {
2726                             Slog.w(TAG, "Unknown element under <app-ops>: "
2727                                     + parser.getName());
2728                             XmlUtils.skipCurrentTag(parser);
2729                         }
2730                     }
2731                     success = true;
2732                 } catch (IllegalStateException e) {
2733                     Slog.w(TAG, "Failed parsing " + e);
2734                 } catch (NullPointerException e) {
2735                     Slog.w(TAG, "Failed parsing " + e);
2736                 } catch (NumberFormatException e) {
2737                     Slog.w(TAG, "Failed parsing " + e);
2738                 } catch (XmlPullParserException e) {
2739                     Slog.w(TAG, "Failed parsing " + e);
2740                 } catch (IOException e) {
2741                     Slog.w(TAG, "Failed parsing " + e);
2742                 } catch (IndexOutOfBoundsException e) {
2743                     Slog.w(TAG, "Failed parsing " + e);
2744                 } finally {
2745                     if (!success) {
2746                         mUidStates.clear();
2747                     }
2748                     try {
2749                         stream.close();
2750                     } catch (IOException e) {
2751                     }
2752                 }
2753             }
2754         }
2755         synchronized (this) {
2756             upgradeLocked(oldVersion);
2757         }
2758     }
2759 
upgradeRunAnyInBackgroundLocked()2760     private void upgradeRunAnyInBackgroundLocked() {
2761         for (int i = 0; i < mUidStates.size(); i++) {
2762             final UidState uidState = mUidStates.valueAt(i);
2763             if (uidState == null) {
2764                 continue;
2765             }
2766             if (uidState.opModes != null) {
2767                 final int idx = uidState.opModes.indexOfKey(AppOpsManager.OP_RUN_IN_BACKGROUND);
2768                 if (idx >= 0) {
2769                     uidState.opModes.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
2770                         uidState.opModes.valueAt(idx));
2771                 }
2772             }
2773             if (uidState.pkgOps == null) {
2774                 continue;
2775             }
2776             boolean changed = false;
2777             for (int j = 0; j < uidState.pkgOps.size(); j++) {
2778                 Ops ops = uidState.pkgOps.valueAt(j);
2779                 if (ops != null) {
2780                     final Op op = ops.get(AppOpsManager.OP_RUN_IN_BACKGROUND);
2781                     if (op != null && op.mode != AppOpsManager.opToDefaultMode(op.op)) {
2782                         final Op copy = new Op(op.uidState, op.packageName,
2783                             AppOpsManager.OP_RUN_ANY_IN_BACKGROUND);
2784                         copy.mode = op.mode;
2785                         ops.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, copy);
2786                         changed = true;
2787                     }
2788                 }
2789             }
2790             if (changed) {
2791                 uidState.evalForegroundOps(mOpModeWatchers);
2792             }
2793         }
2794     }
2795 
upgradeLocked(int oldVersion)2796     private void upgradeLocked(int oldVersion) {
2797         if (oldVersion >= CURRENT_VERSION) {
2798             return;
2799         }
2800         Slog.d(TAG, "Upgrading app-ops xml from version " + oldVersion + " to " + CURRENT_VERSION);
2801         switch (oldVersion) {
2802             case NO_VERSION:
2803                 upgradeRunAnyInBackgroundLocked();
2804                 // fall through
2805             case 1:
2806                 // for future upgrades
2807         }
2808         scheduleFastWriteLocked();
2809     }
2810 
readUidOps(XmlPullParser parser)2811     private void readUidOps(XmlPullParser parser) throws NumberFormatException,
2812             XmlPullParserException, IOException {
2813         final int uid = Integer.parseInt(parser.getAttributeValue(null, "n"));
2814         int outerDepth = parser.getDepth();
2815         int type;
2816         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2817                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2818             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2819                 continue;
2820             }
2821 
2822             String tagName = parser.getName();
2823             if (tagName.equals("op")) {
2824                 final int code = Integer.parseInt(parser.getAttributeValue(null, "n"));
2825                 final int mode = Integer.parseInt(parser.getAttributeValue(null, "m"));
2826                 UidState uidState = getUidStateLocked(uid, true);
2827                 if (uidState.opModes == null) {
2828                     uidState.opModes = new SparseIntArray();
2829                 }
2830                 uidState.opModes.put(code, mode);
2831             } else {
2832                 Slog.w(TAG, "Unknown element under <uid-ops>: "
2833                         + parser.getName());
2834                 XmlUtils.skipCurrentTag(parser);
2835             }
2836         }
2837     }
2838 
readPackage(XmlPullParser parser)2839     private void readPackage(XmlPullParser parser)
2840             throws NumberFormatException, XmlPullParserException, IOException {
2841         String pkgName = parser.getAttributeValue(null, "n");
2842         int outerDepth = parser.getDepth();
2843         int type;
2844         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2845                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2846             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2847                 continue;
2848             }
2849 
2850             String tagName = parser.getName();
2851             if (tagName.equals("uid")) {
2852                 readUid(parser, pkgName);
2853             } else {
2854                 Slog.w(TAG, "Unknown element under <pkg>: "
2855                         + parser.getName());
2856                 XmlUtils.skipCurrentTag(parser);
2857             }
2858         }
2859     }
2860 
readUid(XmlPullParser parser, String pkgName)2861     private void readUid(XmlPullParser parser, String pkgName)
2862             throws NumberFormatException, XmlPullParserException, IOException {
2863         int uid = Integer.parseInt(parser.getAttributeValue(null, "n"));
2864         final UidState uidState = getUidStateLocked(uid, true);
2865         String isPrivilegedString = parser.getAttributeValue(null, "p");
2866         boolean isPrivileged = false;
2867         if (isPrivilegedString == null) {
2868             try {
2869                 IPackageManager packageManager = ActivityThread.getPackageManager();
2870                 if (packageManager != null) {
2871                     ApplicationInfo appInfo = ActivityThread.getPackageManager()
2872                             .getApplicationInfo(pkgName, 0, UserHandle.getUserId(uid));
2873                     if (appInfo != null) {
2874                         isPrivileged = (appInfo.privateFlags
2875                                 & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
2876                     }
2877                 } else {
2878                     // Could not load data, don't add to cache so it will be loaded later.
2879                     return;
2880                 }
2881             } catch (RemoteException e) {
2882                 Slog.w(TAG, "Could not contact PackageManager", e);
2883             }
2884         } else {
2885             isPrivileged = Boolean.parseBoolean(isPrivilegedString);
2886         }
2887         int outerDepth = parser.getDepth();
2888         int type;
2889         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2890                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2891             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2892                 continue;
2893             }
2894             String tagName = parser.getName();
2895             if (tagName.equals("op")) {
2896                 readOp(parser, uidState, pkgName, isPrivileged);
2897             } else {
2898                 Slog.w(TAG, "Unknown element under <pkg>: "
2899                         + parser.getName());
2900                 XmlUtils.skipCurrentTag(parser);
2901             }
2902         }
2903         uidState.evalForegroundOps(mOpModeWatchers);
2904     }
2905 
readOp(XmlPullParser parser, @NonNull UidState uidState, @NonNull String pkgName, boolean isPrivileged)2906     private void readOp(XmlPullParser parser, @NonNull UidState uidState,
2907             @NonNull String pkgName, boolean isPrivileged) throws NumberFormatException,
2908             XmlPullParserException, IOException {
2909         Op op = new Op(uidState, pkgName,
2910                 Integer.parseInt(parser.getAttributeValue(null, "n")));
2911 
2912         final int mode = XmlUtils.readIntAttribute(parser, "m",
2913                 AppOpsManager.opToDefaultMode(op.op));
2914         op.mode = mode;
2915 
2916         int outerDepth = parser.getDepth();
2917         int type;
2918         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2919                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2920             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2921                 continue;
2922             }
2923             String tagName = parser.getName();
2924             if (tagName.equals("st")) {
2925                 final long key = XmlUtils.readLongAttribute(parser, "n");
2926 
2927                 final int flags = AppOpsManager.extractFlagsFromKey(key);
2928                 final int state = AppOpsManager.extractUidStateFromKey(key);
2929 
2930                 final long accessTime = XmlUtils.readLongAttribute(parser, "t", 0);
2931                 final long rejectTime = XmlUtils.readLongAttribute(parser, "r", 0);
2932                 final long accessDuration = XmlUtils.readLongAttribute(parser, "d", 0);
2933                 final String proxyPkg = XmlUtils.readStringAttribute(parser, "pp");
2934                 final int proxyUid = XmlUtils.readIntAttribute(parser, "pu", 0);
2935 
2936                 if (accessTime > 0) {
2937                     op.accessed(accessTime, proxyUid, proxyPkg, state, flags);
2938                 }
2939                 if (rejectTime > 0) {
2940                     op.rejected(rejectTime, proxyUid, proxyPkg, state, flags);
2941                 }
2942                 if (accessDuration > 0) {
2943                     op.running(accessTime, accessDuration, state, flags);
2944                 }
2945             } else {
2946                 Slog.w(TAG, "Unknown element under <op>: "
2947                         + parser.getName());
2948                 XmlUtils.skipCurrentTag(parser);
2949             }
2950         }
2951 
2952         if (uidState.pkgOps == null) {
2953             uidState.pkgOps = new ArrayMap<>();
2954         }
2955         Ops ops = uidState.pkgOps.get(pkgName);
2956         if (ops == null) {
2957             ops = new Ops(pkgName, uidState, isPrivileged);
2958             uidState.pkgOps.put(pkgName, ops);
2959         }
2960         ops.put(op.op, op);
2961     }
2962 
writeState()2963     void writeState() {
2964         synchronized (mFile) {
2965             FileOutputStream stream;
2966             try {
2967                 stream = mFile.startWrite();
2968             } catch (IOException e) {
2969                 Slog.w(TAG, "Failed to write state: " + e);
2970                 return;
2971             }
2972 
2973             List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null);
2974 
2975             try {
2976                 XmlSerializer out = new FastXmlSerializer();
2977                 out.setOutput(stream, StandardCharsets.UTF_8.name());
2978                 out.startDocument(null, true);
2979                 out.startTag(null, "app-ops");
2980                 out.attribute(null, "v", String.valueOf(CURRENT_VERSION));
2981 
2982                 final int uidStateCount = mUidStates.size();
2983                 for (int i = 0; i < uidStateCount; i++) {
2984                     UidState uidState = mUidStates.valueAt(i);
2985                     if (uidState.opModes != null && uidState.opModes.size() > 0) {
2986                         out.startTag(null, "uid");
2987                         out.attribute(null, "n", Integer.toString(uidState.uid));
2988                         SparseIntArray uidOpModes = uidState.opModes;
2989                         final int opCount = uidOpModes.size();
2990                         for (int j = 0; j < opCount; j++) {
2991                             final int op = uidOpModes.keyAt(j);
2992                             final int mode = uidOpModes.valueAt(j);
2993                             out.startTag(null, "op");
2994                             out.attribute(null, "n", Integer.toString(op));
2995                             out.attribute(null, "m", Integer.toString(mode));
2996                             out.endTag(null, "op");
2997                         }
2998                         out.endTag(null, "uid");
2999                     }
3000                 }
3001 
3002                 if (allOps != null) {
3003                     String lastPkg = null;
3004                     for (int i=0; i<allOps.size(); i++) {
3005                         AppOpsManager.PackageOps pkg = allOps.get(i);
3006                         if (!pkg.getPackageName().equals(lastPkg)) {
3007                             if (lastPkg != null) {
3008                                 out.endTag(null, "pkg");
3009                             }
3010                             lastPkg = pkg.getPackageName();
3011                             out.startTag(null, "pkg");
3012                             out.attribute(null, "n", lastPkg);
3013                         }
3014                         out.startTag(null, "uid");
3015                         out.attribute(null, "n", Integer.toString(pkg.getUid()));
3016                         synchronized (this) {
3017                             Ops ops = getOpsRawLocked(pkg.getUid(), pkg.getPackageName(),
3018                                     false /* edit */, false /* uidMismatchExpected */);
3019                             // Should always be present as the list of PackageOps is generated
3020                             // from Ops.
3021                             if (ops != null) {
3022                                 out.attribute(null, "p", Boolean.toString(ops.isPrivileged));
3023                             } else {
3024                                 out.attribute(null, "p", Boolean.toString(false));
3025                             }
3026                         }
3027                         List<AppOpsManager.OpEntry> ops = pkg.getOps();
3028                         for (int j=0; j<ops.size(); j++) {
3029                             AppOpsManager.OpEntry op = ops.get(j);
3030                             out.startTag(null, "op");
3031                             out.attribute(null, "n", Integer.toString(op.getOp()));
3032                             if (op.getMode() != AppOpsManager.opToDefaultMode(op.getOp())) {
3033                                 out.attribute(null, "m", Integer.toString(op.getMode()));
3034                             }
3035 
3036                             final LongSparseArray keys = op.collectKeys();
3037                             if (keys == null || keys.size() <= 0) {
3038                                 out.endTag(null, "op");
3039                                 continue;
3040                             }
3041 
3042                             final int keyCount = keys.size();
3043                             for (int k = 0; k < keyCount; k++) {
3044                                 final long key = keys.keyAt(k);
3045 
3046                                 final int uidState = AppOpsManager.extractUidStateFromKey(key);
3047                                 final int flags = AppOpsManager.extractFlagsFromKey(key);
3048 
3049                                 final long accessTime = op.getLastAccessTime(
3050                                         uidState, uidState, flags);
3051                                 final long rejectTime = op.getLastRejectTime(
3052                                         uidState, uidState, flags);
3053                                 final long accessDuration = op.getLastDuration(
3054                                         uidState, uidState, flags);
3055                                 final String proxyPkg = op.getProxyPackageName(uidState, flags);
3056                                 final int proxyUid = op.getProxyUid(uidState, flags);
3057 
3058                                 if (accessTime <= 0 && rejectTime <= 0 && accessDuration <= 0
3059                                         && proxyPkg == null && proxyUid < 0) {
3060                                     continue;
3061                                 }
3062 
3063                                 out.startTag(null, "st");
3064                                 out.attribute(null, "n", Long.toString(key));
3065                                 if (accessTime > 0) {
3066                                     out.attribute(null, "t", Long.toString(accessTime));
3067                                 }
3068                                 if (rejectTime > 0) {
3069                                     out.attribute(null, "r", Long.toString(rejectTime));
3070                                 }
3071                                 if (accessDuration > 0) {
3072                                     out.attribute(null, "d", Long.toString(accessDuration));
3073                                 }
3074                                 if (proxyPkg != null) {
3075                                     out.attribute(null, "pp", proxyPkg);
3076                                 }
3077                                 if (proxyUid >= 0) {
3078                                     out.attribute(null, "pu", Integer.toString(proxyUid));
3079                                 }
3080                                 out.endTag(null, "st");
3081                             }
3082 
3083                             out.endTag(null, "op");
3084                         }
3085                         out.endTag(null, "uid");
3086                     }
3087                     if (lastPkg != null) {
3088                         out.endTag(null, "pkg");
3089                     }
3090                 }
3091 
3092                 out.endTag(null, "app-ops");
3093                 out.endDocument();
3094                 mFile.finishWrite(stream);
3095             } catch (IOException e) {
3096                 Slog.w(TAG, "Failed to write state, restoring backup.", e);
3097                 mFile.failWrite(stream);
3098             }
3099         }
3100     }
3101 
3102     static class Shell extends ShellCommand {
3103         final IAppOpsService mInterface;
3104         final AppOpsService mInternal;
3105 
3106         int userId = UserHandle.USER_SYSTEM;
3107         String packageName;
3108         String opStr;
3109         String modeStr;
3110         int op;
3111         int mode;
3112         int packageUid;
3113         int nonpackageUid;
3114         final static Binder sBinder = new Binder();
3115         IBinder mToken;
3116         boolean targetsUid;
3117 
Shell(IAppOpsService iface, AppOpsService internal)3118         Shell(IAppOpsService iface, AppOpsService internal) {
3119             mInterface = iface;
3120             mInternal = internal;
3121             try {
3122                 mToken = mInterface.getToken(sBinder);
3123             } catch (RemoteException e) {
3124             }
3125         }
3126 
3127         @Override
onCommand(String cmd)3128         public int onCommand(String cmd) {
3129             return onShellCommand(this, cmd);
3130         }
3131 
3132         @Override
onHelp()3133         public void onHelp() {
3134             PrintWriter pw = getOutPrintWriter();
3135             dumpCommandHelp(pw);
3136         }
3137 
strOpToOp(String op, PrintWriter err)3138         static private int strOpToOp(String op, PrintWriter err) {
3139             try {
3140                 return AppOpsManager.strOpToOp(op);
3141             } catch (IllegalArgumentException e) {
3142             }
3143             try {
3144                 return Integer.parseInt(op);
3145             } catch (NumberFormatException e) {
3146             }
3147             try {
3148                 return AppOpsManager.strDebugOpToOp(op);
3149             } catch (IllegalArgumentException e) {
3150                 err.println("Error: " + e.getMessage());
3151                 return -1;
3152             }
3153         }
3154 
strModeToMode(String modeStr, PrintWriter err)3155         static int strModeToMode(String modeStr, PrintWriter err) {
3156             for (int i = AppOpsManager.MODE_NAMES.length - 1; i >= 0; i--) {
3157                 if (AppOpsManager.MODE_NAMES[i].equals(modeStr)) {
3158                     return i;
3159                 }
3160             }
3161             try {
3162                 return Integer.parseInt(modeStr);
3163             } catch (NumberFormatException e) {
3164             }
3165             err.println("Error: Mode " + modeStr + " is not valid");
3166             return -1;
3167         }
3168 
parseUserOpMode(int defMode, PrintWriter err)3169         int parseUserOpMode(int defMode, PrintWriter err) throws RemoteException {
3170             userId = UserHandle.USER_CURRENT;
3171             opStr = null;
3172             modeStr = null;
3173             for (String argument; (argument = getNextArg()) != null;) {
3174                 if ("--user".equals(argument)) {
3175                     userId = UserHandle.parseUserArg(getNextArgRequired());
3176                 } else {
3177                     if (opStr == null) {
3178                         opStr = argument;
3179                     } else if (modeStr == null) {
3180                         modeStr = argument;
3181                         break;
3182                     }
3183                 }
3184             }
3185             if (opStr == null) {
3186                 err.println("Error: Operation not specified.");
3187                 return -1;
3188             }
3189             op = strOpToOp(opStr, err);
3190             if (op < 0) {
3191                 return -1;
3192             }
3193             if (modeStr != null) {
3194                 if ((mode=strModeToMode(modeStr, err)) < 0) {
3195                     return -1;
3196                 }
3197             } else {
3198                 mode = defMode;
3199             }
3200             return 0;
3201         }
3202 
parseUserPackageOp(boolean reqOp, PrintWriter err)3203         int parseUserPackageOp(boolean reqOp, PrintWriter err) throws RemoteException {
3204             userId = UserHandle.USER_CURRENT;
3205             packageName = null;
3206             opStr = null;
3207             for (String argument; (argument = getNextArg()) != null;) {
3208                 if ("--user".equals(argument)) {
3209                     userId = UserHandle.parseUserArg(getNextArgRequired());
3210                 } else if ("--uid".equals(argument)) {
3211                     targetsUid = true;
3212                 } else {
3213                     if (packageName == null) {
3214                         packageName = argument;
3215                     } else if (opStr == null) {
3216                         opStr = argument;
3217                         break;
3218                     }
3219                 }
3220             }
3221             if (packageName == null) {
3222                 err.println("Error: Package name not specified.");
3223                 return -1;
3224             } else if (opStr == null && reqOp) {
3225                 err.println("Error: Operation not specified.");
3226                 return -1;
3227             }
3228             if (opStr != null) {
3229                 op = strOpToOp(opStr, err);
3230                 if (op < 0) {
3231                     return -1;
3232                 }
3233             } else {
3234                 op = AppOpsManager.OP_NONE;
3235             }
3236             if (userId == UserHandle.USER_CURRENT) {
3237                 userId = ActivityManager.getCurrentUser();
3238             }
3239             nonpackageUid = -1;
3240             try {
3241                 nonpackageUid = Integer.parseInt(packageName);
3242             } catch (NumberFormatException e) {
3243             }
3244             if (nonpackageUid == -1 && packageName.length() > 1 && packageName.charAt(0) == 'u'
3245                     && packageName.indexOf('.') < 0) {
3246                 int i = 1;
3247                 while (i < packageName.length() && packageName.charAt(i) >= '0'
3248                         && packageName.charAt(i) <= '9') {
3249                     i++;
3250                 }
3251                 if (i > 1 && i < packageName.length()) {
3252                     String userStr = packageName.substring(1, i);
3253                     try {
3254                         int user = Integer.parseInt(userStr);
3255                         char type = packageName.charAt(i);
3256                         i++;
3257                         int startTypeVal = i;
3258                         while (i < packageName.length() && packageName.charAt(i) >= '0'
3259                                 && packageName.charAt(i) <= '9') {
3260                             i++;
3261                         }
3262                         if (i > startTypeVal) {
3263                             String typeValStr = packageName.substring(startTypeVal, i);
3264                             try {
3265                                 int typeVal = Integer.parseInt(typeValStr);
3266                                 if (type == 'a') {
3267                                     nonpackageUid = UserHandle.getUid(user,
3268                                             typeVal + Process.FIRST_APPLICATION_UID);
3269                                 } else if (type == 's') {
3270                                     nonpackageUid = UserHandle.getUid(user, typeVal);
3271                                 }
3272                             } catch (NumberFormatException e) {
3273                             }
3274                         }
3275                     } catch (NumberFormatException e) {
3276                     }
3277                 }
3278             }
3279             if (nonpackageUid != -1) {
3280                 packageName = null;
3281             } else {
3282                 packageUid = resolveUid(packageName);
3283                 if (packageUid < 0) {
3284                     packageUid = AppGlobals.getPackageManager().getPackageUid(packageName,
3285                             PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
3286                 }
3287                 if (packageUid < 0) {
3288                     err.println("Error: No UID for " + packageName + " in user " + userId);
3289                     return -1;
3290                 }
3291             }
3292             return 0;
3293         }
3294     }
3295 
onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)3296     @Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
3297             FileDescriptor err, String[] args, ShellCallback callback,
3298             ResultReceiver resultReceiver) {
3299         (new Shell(this, this)).exec(this, in, out, err, args, callback, resultReceiver);
3300     }
3301 
dumpCommandHelp(PrintWriter pw)3302     static void dumpCommandHelp(PrintWriter pw) {
3303         pw.println("AppOps service (appops) commands:");
3304         pw.println("  help");
3305         pw.println("    Print this help text.");
3306         pw.println("  start [--user <USER_ID>] <PACKAGE | UID> <OP> ");
3307         pw.println("    Starts a given operation for a particular application.");
3308         pw.println("  stop [--user <USER_ID>] <PACKAGE | UID> <OP> ");
3309         pw.println("    Stops a given operation for a particular application.");
3310         pw.println("  set [--user <USER_ID>] <[--uid] PACKAGE | UID> <OP> <MODE>");
3311         pw.println("    Set the mode for a particular application and operation.");
3312         pw.println("  get [--user <USER_ID>] <PACKAGE | UID> [<OP>]");
3313         pw.println("    Return the mode for a particular application and optional operation.");
3314         pw.println("  query-op [--user <USER_ID>] <OP> [<MODE>]");
3315         pw.println("    Print all packages that currently have the given op in the given mode.");
3316         pw.println("  reset [--user <USER_ID>] [<PACKAGE>]");
3317         pw.println("    Reset the given application or all applications to default modes.");
3318         pw.println("  write-settings");
3319         pw.println("    Immediately write pending changes to storage.");
3320         pw.println("  read-settings");
3321         pw.println("    Read the last written settings, replacing current state in RAM.");
3322         pw.println("  options:");
3323         pw.println("    <PACKAGE> an Android package name or its UID if prefixed by --uid");
3324         pw.println("    <OP>      an AppOps operation.");
3325         pw.println("    <MODE>    one of allow, ignore, deny, or default");
3326         pw.println("    <USER_ID> the user id under which the package is installed. If --user is not");
3327         pw.println("              specified, the current user is assumed.");
3328     }
3329 
onShellCommand(Shell shell, String cmd)3330     static int onShellCommand(Shell shell, String cmd) {
3331         if (cmd == null) {
3332             return shell.handleDefaultCommands(cmd);
3333         }
3334         PrintWriter pw = shell.getOutPrintWriter();
3335         PrintWriter err = shell.getErrPrintWriter();
3336         try {
3337             switch (cmd) {
3338                 case "set": {
3339                     int res = shell.parseUserPackageOp(true, err);
3340                     if (res < 0) {
3341                         return res;
3342                     }
3343                     String modeStr = shell.getNextArg();
3344                     if (modeStr == null) {
3345                         err.println("Error: Mode not specified.");
3346                         return -1;
3347                     }
3348 
3349                     final int mode = shell.strModeToMode(modeStr, err);
3350                     if (mode < 0) {
3351                         return -1;
3352                     }
3353 
3354                     if (!shell.targetsUid && shell.packageName != null) {
3355                         shell.mInterface.setMode(shell.op, shell.packageUid, shell.packageName,
3356                                 mode);
3357                     } else if (shell.targetsUid && shell.packageName != null) {
3358                         try {
3359                             final int uid = shell.mInternal.mContext.getPackageManager()
3360                                     .getPackageUid(shell.packageName, shell.userId);
3361                             shell.mInterface.setUidMode(shell.op, uid, mode);
3362                         } catch (PackageManager.NameNotFoundException e) {
3363                             return -1;
3364                         }
3365                     } else {
3366                         shell.mInterface.setUidMode(shell.op, shell.nonpackageUid, mode);
3367                     }
3368                     return 0;
3369                 }
3370                 case "get": {
3371                     int res = shell.parseUserPackageOp(false, err);
3372                     if (res < 0) {
3373                         return res;
3374                     }
3375 
3376                     List<AppOpsManager.PackageOps> ops = new ArrayList<>();
3377                     if (shell.packageName != null) {
3378                         // Uid mode overrides package mode, so make sure it's also reported
3379                         List<AppOpsManager.PackageOps> r = shell.mInterface.getUidOps(
3380                                 shell.packageUid,
3381                                 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null);
3382                         if (r != null) {
3383                             ops.addAll(r);
3384                         }
3385                         r = shell.mInterface.getOpsForPackage(
3386                                 shell.packageUid, shell.packageName,
3387                                 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null);
3388                         if (r != null) {
3389                             ops.addAll(r);
3390                         }
3391                     } else {
3392                         ops = shell.mInterface.getUidOps(
3393                                 shell.nonpackageUid,
3394                                 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null);
3395                     }
3396                     if (ops == null || ops.size() <= 0) {
3397                         pw.println("No operations.");
3398                         if (shell.op > AppOpsManager.OP_NONE && shell.op < AppOpsManager._NUM_OP) {
3399                             pw.println("Default mode: " + AppOpsManager.modeToName(
3400                                     AppOpsManager.opToDefaultMode(shell.op)));
3401                         }
3402                         return 0;
3403                     }
3404                     final long now = System.currentTimeMillis();
3405                     for (int i=0; i<ops.size(); i++) {
3406                         AppOpsManager.PackageOps packageOps = ops.get(i);
3407                         if (packageOps.getPackageName() == null) {
3408                             pw.print("Uid mode: ");
3409                         }
3410                         List<AppOpsManager.OpEntry> entries = packageOps.getOps();
3411                         for (int j=0; j<entries.size(); j++) {
3412                             AppOpsManager.OpEntry ent = entries.get(j);
3413                             pw.print(AppOpsManager.opToName(ent.getOp()));
3414                             pw.print(": ");
3415                             pw.print(AppOpsManager.modeToName(ent.getMode()));
3416                             if (ent.getTime() != 0) {
3417                                 pw.print("; time=");
3418                                 TimeUtils.formatDuration(now - ent.getTime(), pw);
3419                                 pw.print(" ago");
3420                             }
3421                             if (ent.getRejectTime() != 0) {
3422                                 pw.print("; rejectTime=");
3423                                 TimeUtils.formatDuration(now - ent.getRejectTime(), pw);
3424                                 pw.print(" ago");
3425                             }
3426                             if (ent.getDuration() == -1) {
3427                                 pw.print(" (running)");
3428                             } else if (ent.getDuration() != 0) {
3429                                 pw.print("; duration=");
3430                                 TimeUtils.formatDuration(ent.getDuration(), pw);
3431                             }
3432                             pw.println();
3433                         }
3434                     }
3435                     return 0;
3436                 }
3437                 case "query-op": {
3438                     int res = shell.parseUserOpMode(AppOpsManager.MODE_IGNORED, err);
3439                     if (res < 0) {
3440                         return res;
3441                     }
3442                     List<AppOpsManager.PackageOps> ops = shell.mInterface.getPackagesForOps(
3443                             new int[] {shell.op});
3444                     if (ops == null || ops.size() <= 0) {
3445                         pw.println("No operations.");
3446                         return 0;
3447                     }
3448                     for (int i=0; i<ops.size(); i++) {
3449                         final AppOpsManager.PackageOps pkg = ops.get(i);
3450                         boolean hasMatch = false;
3451                         final List<AppOpsManager.OpEntry> entries = ops.get(i).getOps();
3452                         for (int j=0; j<entries.size(); j++) {
3453                             AppOpsManager.OpEntry ent = entries.get(j);
3454                             if (ent.getOp() == shell.op && ent.getMode() == shell.mode) {
3455                                 hasMatch = true;
3456                                 break;
3457                             }
3458                         }
3459                         if (hasMatch) {
3460                             pw.println(pkg.getPackageName());
3461                         }
3462                     }
3463                     return 0;
3464                 }
3465                 case "reset": {
3466                     String packageName = null;
3467                     int userId = UserHandle.USER_CURRENT;
3468                     for (String argument; (argument = shell.getNextArg()) != null;) {
3469                         if ("--user".equals(argument)) {
3470                             String userStr = shell.getNextArgRequired();
3471                             userId = UserHandle.parseUserArg(userStr);
3472                         } else {
3473                             if (packageName == null) {
3474                                 packageName = argument;
3475                             } else {
3476                                 err.println("Error: Unsupported argument: " + argument);
3477                                 return -1;
3478                             }
3479                         }
3480                     }
3481 
3482                     if (userId == UserHandle.USER_CURRENT) {
3483                         userId = ActivityManager.getCurrentUser();
3484                     }
3485 
3486                     shell.mInterface.resetAllModes(userId, packageName);
3487                     pw.print("Reset all modes for: ");
3488                     if (userId == UserHandle.USER_ALL) {
3489                         pw.print("all users");
3490                     } else {
3491                         pw.print("user "); pw.print(userId);
3492                     }
3493                     pw.print(", ");
3494                     if (packageName == null) {
3495                         pw.println("all packages");
3496                     } else {
3497                         pw.print("package "); pw.println(packageName);
3498                     }
3499                     return 0;
3500                 }
3501                 case "write-settings": {
3502                     shell.mInternal.enforceManageAppOpsModes(Binder.getCallingPid(),
3503                             Binder.getCallingUid(), -1);
3504                     long token = Binder.clearCallingIdentity();
3505                     try {
3506                         synchronized (shell.mInternal) {
3507                             shell.mInternal.mHandler.removeCallbacks(shell.mInternal.mWriteRunner);
3508                         }
3509                         shell.mInternal.writeState();
3510                         pw.println("Current settings written.");
3511                     } finally {
3512                         Binder.restoreCallingIdentity(token);
3513                     }
3514                     return 0;
3515                 }
3516                 case "read-settings": {
3517                     shell.mInternal.enforceManageAppOpsModes(Binder.getCallingPid(),
3518                             Binder.getCallingUid(), -1);
3519                     long token = Binder.clearCallingIdentity();
3520                     try {
3521                         shell.mInternal.readState();
3522                         pw.println("Last settings read.");
3523                     } finally {
3524                         Binder.restoreCallingIdentity(token);
3525                     }
3526                     return 0;
3527                 }
3528                 case "start": {
3529                     int res = shell.parseUserPackageOp(true, err);
3530                     if (res < 0) {
3531                         return res;
3532                     }
3533 
3534                     if (shell.packageName != null) {
3535                         shell.mInterface.startOperation(shell.mToken,
3536                                 shell.op, shell.packageUid, shell.packageName, true);
3537                     } else {
3538                         return -1;
3539                     }
3540                     return 0;
3541                 }
3542                 case "stop": {
3543                     int res = shell.parseUserPackageOp(true, err);
3544                     if (res < 0) {
3545                         return res;
3546                     }
3547 
3548                     if (shell.packageName != null) {
3549                         shell.mInterface.finishOperation(shell.mToken,
3550                                 shell.op, shell.packageUid, shell.packageName);
3551                     } else {
3552                         return -1;
3553                     }
3554                     return 0;
3555                 }
3556                 default:
3557                     return shell.handleDefaultCommands(cmd);
3558             }
3559         } catch (RemoteException e) {
3560             pw.println("Remote exception: " + e);
3561         }
3562         return -1;
3563     }
3564 
dumpHelp(PrintWriter pw)3565     private void dumpHelp(PrintWriter pw) {
3566         pw.println("AppOps service (appops) dump options:");
3567         pw.println("  -h");
3568         pw.println("    Print this help text.");
3569         pw.println("  --op [OP]");
3570         pw.println("    Limit output to data associated with the given app op code.");
3571         pw.println("  --mode [MODE]");
3572         pw.println("    Limit output to data associated with the given app op mode.");
3573         pw.println("  --package [PACKAGE]");
3574         pw.println("    Limit output to data associated with the given package name.");
3575         pw.println("  --watchers");
3576         pw.println("    Only output the watcher sections.");
3577     }
3578 
dumpStatesLocked(@onNull PrintWriter pw, @NonNull Op op, long now, @NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix)3579     private void dumpStatesLocked(@NonNull PrintWriter pw, @NonNull Op op,
3580             long now, @NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix) {
3581 
3582         final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes,
3583             op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames);
3584 
3585         final LongSparseArray keys = entry.collectKeys();
3586         if (keys == null || keys.size() <= 0) {
3587             return;
3588         }
3589 
3590         final int keyCount = keys.size();
3591         for (int k = 0; k < keyCount; k++) {
3592             final long key = keys.keyAt(k);
3593 
3594             final int uidState = AppOpsManager.extractUidStateFromKey(key);
3595             final int flags = AppOpsManager.extractFlagsFromKey(key);
3596 
3597             final long accessTime = entry.getLastAccessTime(
3598                     uidState, uidState, flags);
3599             final long rejectTime = entry.getLastRejectTime(
3600                     uidState, uidState, flags);
3601             final long accessDuration = entry.getLastDuration(
3602                     uidState, uidState, flags);
3603             final String proxyPkg = entry.getProxyPackageName(uidState, flags);
3604             final int proxyUid = entry.getProxyUid(uidState, flags);
3605 
3606             if (accessTime > 0) {
3607                 pw.print(prefix);
3608                 pw.print("Access: ");
3609                 pw.print(AppOpsManager.keyToString(key));
3610                 pw.print(" ");
3611                 date.setTime(accessTime);
3612                 pw.print(sdf.format(date));
3613                 pw.print(" (");
3614                 TimeUtils.formatDuration(accessTime - now, pw);
3615                 pw.print(")");
3616                 if (accessDuration > 0) {
3617                     pw.print(" duration=");
3618                     TimeUtils.formatDuration(accessDuration, pw);
3619                 }
3620                 if (proxyUid >= 0) {
3621                     pw.print(" proxy[");
3622                     pw.print("uid=");
3623                     pw.print(proxyUid);
3624                     pw.print(", pkg=");
3625                     pw.print(proxyPkg);
3626                     pw.print("]");
3627                 }
3628                 pw.println();
3629             }
3630 
3631             if (rejectTime > 0) {
3632                 pw.print(prefix);
3633                 pw.print("Reject: ");
3634                 pw.print(AppOpsManager.keyToString(key));
3635                 date.setTime(rejectTime);
3636                 pw.print(sdf.format(date));
3637                 pw.print(" (");
3638                 TimeUtils.formatDuration(rejectTime - now, pw);
3639                 pw.print(")");
3640                 if (proxyUid >= 0) {
3641                     pw.print(" proxy[");
3642                     pw.print("uid=");
3643                     pw.print(proxyUid);
3644                     pw.print(", pkg=");
3645                     pw.print(proxyPkg);
3646                     pw.print("]");
3647                 }
3648                 pw.println();
3649             }
3650         }
3651     }
3652 
3653     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)3654     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
3655         if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
3656 
3657         int dumpOp = OP_NONE;
3658         String dumpPackage = null;
3659         int dumpUid = Process.INVALID_UID;
3660         int dumpMode = -1;
3661         boolean dumpWatchers = false;
3662         boolean dumpHistory = false;
3663 
3664         if (args != null) {
3665             for (int i=0; i<args.length; i++) {
3666                 String arg = args[i];
3667                 if ("-h".equals(arg)) {
3668                     dumpHelp(pw);
3669                     return;
3670                 } else if ("-a".equals(arg)) {
3671                     // dump all data
3672                 } else if ("--op".equals(arg)) {
3673                     i++;
3674                     if (i >= args.length) {
3675                         pw.println("No argument for --op option");
3676                         return;
3677                     }
3678                     dumpOp = Shell.strOpToOp(args[i], pw);
3679                     if (dumpOp < 0) {
3680                         return;
3681                     }
3682                 } else if ("--package".equals(arg)) {
3683                     i++;
3684                     if (i >= args.length) {
3685                         pw.println("No argument for --package option");
3686                         return;
3687                     }
3688                     dumpPackage = args[i];
3689                     try {
3690                         dumpUid = AppGlobals.getPackageManager().getPackageUid(dumpPackage,
3691                                 PackageManager.MATCH_KNOWN_PACKAGES | PackageManager.MATCH_INSTANT,
3692                                 0);
3693                     } catch (RemoteException e) {
3694                     }
3695                     if (dumpUid < 0) {
3696                         pw.println("Unknown package: " + dumpPackage);
3697                         return;
3698                     }
3699                     dumpUid = UserHandle.getAppId(dumpUid);
3700                 } else if ("--mode".equals(arg)) {
3701                     i++;
3702                     if (i >= args.length) {
3703                         pw.println("No argument for --mode option");
3704                         return;
3705                     }
3706                     dumpMode = Shell.strModeToMode(args[i], pw);
3707                     if (dumpMode < 0) {
3708                         return;
3709                     }
3710                 } else if ("--watchers".equals(arg)) {
3711                     dumpWatchers = true;
3712                 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
3713                     pw.println("Unknown option: " + arg);
3714                     return;
3715                 } else {
3716                     pw.println("Unknown command: " + arg);
3717                     return;
3718                 }
3719             }
3720         }
3721 
3722         synchronized (this) {
3723             pw.println("Current AppOps Service state:");
3724             if (!dumpHistory && !dumpWatchers) {
3725                 mConstants.dump(pw);
3726             }
3727             pw.println();
3728             final long now = System.currentTimeMillis();
3729             final long nowElapsed = SystemClock.elapsedRealtime();
3730             final long nowUptime = SystemClock.uptimeMillis();
3731             final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
3732             final Date date = new Date();
3733             boolean needSep = false;
3734             if (dumpOp < 0 && dumpMode < 0 && dumpPackage == null && mProfileOwners != null
3735                     && !dumpWatchers && !dumpHistory) {
3736                 pw.println("  Profile owners:");
3737                 for (int poi = 0; poi < mProfileOwners.size(); poi++) {
3738                     pw.print("    User #");
3739                     pw.print(mProfileOwners.keyAt(poi));
3740                     pw.print(": ");
3741                     UserHandle.formatUid(pw, mProfileOwners.valueAt(poi));
3742                     pw.println();
3743                 }
3744                 pw.println();
3745             }
3746             if (mOpModeWatchers.size() > 0 && !dumpHistory) {
3747                 boolean printedHeader = false;
3748                 for (int i=0; i<mOpModeWatchers.size(); i++) {
3749                     if (dumpOp >= 0 && dumpOp != mOpModeWatchers.keyAt(i)) {
3750                         continue;
3751                     }
3752                     boolean printedOpHeader = false;
3753                     ArraySet<ModeCallback> callbacks = mOpModeWatchers.valueAt(i);
3754                     for (int j=0; j<callbacks.size(); j++) {
3755                         final ModeCallback cb = callbacks.valueAt(j);
3756                         if (dumpPackage != null
3757                                 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) {
3758                             continue;
3759                         }
3760                         needSep = true;
3761                         if (!printedHeader) {
3762                             pw.println("  Op mode watchers:");
3763                             printedHeader = true;
3764                         }
3765                         if (!printedOpHeader) {
3766                             pw.print("    Op ");
3767                             pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i)));
3768                             pw.println(":");
3769                             printedOpHeader = true;
3770                         }
3771                         pw.print("      #"); pw.print(j); pw.print(": ");
3772                         pw.println(cb);
3773                     }
3774                 }
3775             }
3776             if (mPackageModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) {
3777                 boolean printedHeader = false;
3778                 for (int i=0; i<mPackageModeWatchers.size(); i++) {
3779                     if (dumpPackage != null && !dumpPackage.equals(mPackageModeWatchers.keyAt(i))) {
3780                         continue;
3781                     }
3782                     needSep = true;
3783                     if (!printedHeader) {
3784                         pw.println("  Package mode watchers:");
3785                         printedHeader = true;
3786                     }
3787                     pw.print("    Pkg "); pw.print(mPackageModeWatchers.keyAt(i));
3788                     pw.println(":");
3789                     ArraySet<ModeCallback> callbacks = mPackageModeWatchers.valueAt(i);
3790                     for (int j=0; j<callbacks.size(); j++) {
3791                         pw.print("      #"); pw.print(j); pw.print(": ");
3792                         pw.println(callbacks.valueAt(j));
3793                     }
3794                 }
3795             }
3796             if (mModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) {
3797                 boolean printedHeader = false;
3798                 for (int i=0; i<mModeWatchers.size(); i++) {
3799                     final ModeCallback cb = mModeWatchers.valueAt(i);
3800                     if (dumpPackage != null
3801                             && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) {
3802                         continue;
3803                     }
3804                     needSep = true;
3805                     if (!printedHeader) {
3806                         pw.println("  All op mode watchers:");
3807                         printedHeader = true;
3808                     }
3809                     pw.print("    ");
3810                     pw.print(Integer.toHexString(System.identityHashCode(mModeWatchers.keyAt(i))));
3811                     pw.print(": "); pw.println(cb);
3812                 }
3813             }
3814             if (mActiveWatchers.size() > 0 && dumpMode < 0) {
3815                 needSep = true;
3816                 boolean printedHeader = false;
3817                 for (int watcherNum = 0; watcherNum < mActiveWatchers.size(); watcherNum++) {
3818                     final SparseArray<ActiveCallback> activeWatchers =
3819                             mActiveWatchers.valueAt(watcherNum);
3820                     if (activeWatchers.size() <= 0) {
3821                         continue;
3822                     }
3823                     final ActiveCallback cb = activeWatchers.valueAt(0);
3824                     if (dumpOp >= 0 && activeWatchers.indexOfKey(dumpOp) < 0) {
3825                         continue;
3826                     }
3827                     if (dumpPackage != null
3828                             && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) {
3829                         continue;
3830                     }
3831                     if (!printedHeader) {
3832                         pw.println("  All op active watchers:");
3833                         printedHeader = true;
3834                     }
3835                     pw.print("    ");
3836                     pw.print(Integer.toHexString(System.identityHashCode(
3837                             mActiveWatchers.keyAt(watcherNum))));
3838                     pw.println(" ->");
3839                     pw.print("        [");
3840                     final int opCount = activeWatchers.size();
3841                     for (int opNum = 0; opNum < opCount; opNum++) {
3842                         if (opNum > 0) {
3843                             pw.print(' ');
3844                         }
3845                         pw.print(AppOpsManager.opToName(activeWatchers.keyAt(opNum)));
3846                         if (opNum < opCount - 1) {
3847                             pw.print(',');
3848                         }
3849                     }
3850                     pw.println("]");
3851                     pw.print("        ");
3852                     pw.println(cb);
3853                 }
3854             }
3855             if (mNotedWatchers.size() > 0 && dumpMode < 0) {
3856                 needSep = true;
3857                 boolean printedHeader = false;
3858                 for (int i = 0; i < mNotedWatchers.size(); i++) {
3859                     final SparseArray<NotedCallback> notedWatchers = mNotedWatchers.valueAt(i);
3860                     if (notedWatchers.size() <= 0) {
3861                         continue;
3862                     }
3863                     final NotedCallback cb = notedWatchers.valueAt(0);
3864                     if (dumpOp >= 0 && notedWatchers.indexOfKey(dumpOp) < 0) {
3865                         continue;
3866                     }
3867                     if (dumpPackage != null
3868                             && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) {
3869                         continue;
3870                     }
3871                     if (!printedHeader) {
3872                         pw.println("  All op noted watchers:");
3873                         printedHeader = true;
3874                     }
3875                     pw.print("    ");
3876                     pw.print(Integer.toHexString(System.identityHashCode(
3877                             mNotedWatchers.keyAt(i))));
3878                     pw.println(" ->");
3879                     pw.print("        [");
3880                     final int opCount = notedWatchers.size();
3881                     for (i = 0; i < opCount; i++) {
3882                         if (i > 0) {
3883                             pw.print(' ');
3884                         }
3885                         pw.print(AppOpsManager.opToName(notedWatchers.keyAt(i)));
3886                         if (i < opCount - 1) {
3887                             pw.print(',');
3888                         }
3889                     }
3890                     pw.println("]");
3891                     pw.print("        ");
3892                     pw.println(cb);
3893                 }
3894             }
3895             if (mClients.size() > 0 && dumpMode < 0 && !dumpWatchers && !dumpHistory) {
3896                 needSep = true;
3897                 boolean printedHeader = false;
3898                 for (int i=0; i<mClients.size(); i++) {
3899                     boolean printedClient = false;
3900                     ClientState cs = mClients.valueAt(i);
3901                     if (cs.mStartedOps.size() > 0) {
3902                         boolean printedStarted = false;
3903                         for (int j=0; j<cs.mStartedOps.size(); j++) {
3904                             Op op = cs.mStartedOps.get(j);
3905                             if (dumpOp >= 0 && op.op != dumpOp) {
3906                                 continue;
3907                             }
3908                             if (dumpPackage != null && !dumpPackage.equals(op.packageName)) {
3909                                 continue;
3910                             }
3911                             if (!printedHeader) {
3912                                 pw.println("  Clients:");
3913                                 printedHeader = true;
3914                             }
3915                             if (!printedClient) {
3916                                 pw.print("    "); pw.print(mClients.keyAt(i)); pw.println(":");
3917                                 pw.print("      "); pw.println(cs);
3918                                 printedClient = true;
3919                             }
3920                             if (!printedStarted) {
3921                                 pw.println("      Started ops:");
3922                                 printedStarted = true;
3923                             }
3924                             pw.print("        "); pw.print("uid="); pw.print(op.uidState.uid);
3925                             pw.print(" pkg="); pw.print(op.packageName);
3926                             pw.print(" op="); pw.println(AppOpsManager.opToName(op.op));
3927                         }
3928                     }
3929                 }
3930             }
3931             if (mAudioRestrictions.size() > 0 && dumpOp < 0 && dumpPackage != null
3932                     && dumpMode < 0 && !dumpWatchers && !dumpWatchers) {
3933                 boolean printedHeader = false;
3934                 for (int o=0; o<mAudioRestrictions.size(); o++) {
3935                     final String op = AppOpsManager.opToName(mAudioRestrictions.keyAt(o));
3936                     final SparseArray<Restriction> restrictions = mAudioRestrictions.valueAt(o);
3937                     for (int i=0; i<restrictions.size(); i++) {
3938                         if (!printedHeader){
3939                             pw.println("  Audio Restrictions:");
3940                             printedHeader = true;
3941                             needSep = true;
3942                         }
3943                         final int usage = restrictions.keyAt(i);
3944                         pw.print("    "); pw.print(op);
3945                         pw.print(" usage="); pw.print(AudioAttributes.usageToString(usage));
3946                         Restriction r = restrictions.valueAt(i);
3947                         pw.print(": mode="); pw.println(AppOpsManager.modeToName(r.mode));
3948                         if (!r.exceptionPackages.isEmpty()) {
3949                             pw.println("      Exceptions:");
3950                             for (int j=0; j<r.exceptionPackages.size(); j++) {
3951                                 pw.print("        "); pw.println(r.exceptionPackages.valueAt(j));
3952                             }
3953                         }
3954                     }
3955                 }
3956             }
3957             if (needSep) {
3958                 pw.println();
3959             }
3960             for (int i=0; i<mUidStates.size(); i++) {
3961                 UidState uidState = mUidStates.valueAt(i);
3962                 final SparseIntArray opModes = uidState.opModes;
3963                 final ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
3964 
3965                 if (dumpWatchers || dumpHistory) {
3966                     continue;
3967                 }
3968                 if (dumpOp >= 0 || dumpPackage != null || dumpMode >= 0) {
3969                     boolean hasOp = dumpOp < 0 || (uidState.opModes != null
3970                             && uidState.opModes.indexOfKey(dumpOp) >= 0);
3971                     boolean hasPackage = dumpPackage == null;
3972                     boolean hasMode = dumpMode < 0;
3973                     if (!hasMode && opModes != null) {
3974                         for (int opi = 0; !hasMode && opi < opModes.size(); opi++) {
3975                             if (opModes.valueAt(opi) == dumpMode) {
3976                                 hasMode = true;
3977                             }
3978                         }
3979                     }
3980                     if (pkgOps != null) {
3981                         for (int pkgi = 0;
3982                                  (!hasOp || !hasPackage || !hasMode) && pkgi < pkgOps.size();
3983                                  pkgi++) {
3984                             Ops ops = pkgOps.valueAt(pkgi);
3985                             if (!hasOp && ops != null && ops.indexOfKey(dumpOp) >= 0) {
3986                                 hasOp = true;
3987                             }
3988                             if (!hasMode) {
3989                                 for (int opi = 0; !hasMode && opi < ops.size(); opi++) {
3990                                     if (ops.valueAt(opi).mode == dumpMode) {
3991                                         hasMode = true;
3992                                     }
3993                                 }
3994                             }
3995                             if (!hasPackage && dumpPackage.equals(ops.packageName)) {
3996                                 hasPackage = true;
3997                             }
3998                         }
3999                     }
4000                     if (uidState.foregroundOps != null && !hasOp) {
4001                         if (uidState.foregroundOps.indexOfKey(dumpOp) > 0) {
4002                             hasOp = true;
4003                         }
4004                     }
4005                     if (!hasOp || !hasPackage || !hasMode) {
4006                         continue;
4007                     }
4008                 }
4009 
4010                 pw.print("  Uid "); UserHandle.formatUid(pw, uidState.uid); pw.println(":");
4011                 pw.print("    state=");
4012                 pw.println(AppOpsManager.getUidStateName(uidState.state));
4013                 if (uidState.state != uidState.pendingState) {
4014                     pw.print("    pendingState=");
4015                     pw.println(AppOpsManager.getUidStateName(uidState.pendingState));
4016                 }
4017                 if (uidState.pendingStateCommitTime != 0) {
4018                     pw.print("    pendingStateCommitTime=");
4019                     TimeUtils.formatDuration(uidState.pendingStateCommitTime, nowElapsed, pw);
4020                     pw.println();
4021                 }
4022                 if (uidState.startNesting != 0) {
4023                     pw.print("    startNesting=");
4024                     pw.println(uidState.startNesting);
4025                 }
4026                 if (uidState.foregroundOps != null && (dumpMode < 0
4027                         || dumpMode == AppOpsManager.MODE_FOREGROUND)) {
4028                     pw.println("    foregroundOps:");
4029                     for (int j = 0; j < uidState.foregroundOps.size(); j++) {
4030                         if (dumpOp >= 0 && dumpOp != uidState.foregroundOps.keyAt(j)) {
4031                             continue;
4032                         }
4033                         pw.print("      ");
4034                         pw.print(AppOpsManager.opToName(uidState.foregroundOps.keyAt(j)));
4035                         pw.print(": ");
4036                         pw.println(uidState.foregroundOps.valueAt(j) ? "WATCHER" : "SILENT");
4037                     }
4038                     pw.print("    hasForegroundWatchers=");
4039                     pw.println(uidState.hasForegroundWatchers);
4040                 }
4041                 needSep = true;
4042 
4043                 if (opModes != null) {
4044                     final int opModeCount = opModes.size();
4045                     for (int j = 0; j < opModeCount; j++) {
4046                         final int code = opModes.keyAt(j);
4047                         final int mode = opModes.valueAt(j);
4048                         if (dumpOp >= 0 && dumpOp != code) {
4049                             continue;
4050                         }
4051                         if (dumpMode >= 0 && dumpMode != mode) {
4052                             continue;
4053                         }
4054                         pw.print("      "); pw.print(AppOpsManager.opToName(code));
4055                         pw.print(": mode="); pw.println(AppOpsManager.modeToName(mode));
4056                     }
4057                 }
4058 
4059                 if (pkgOps == null) {
4060                     continue;
4061                 }
4062 
4063                 for (int pkgi = 0; pkgi < pkgOps.size(); pkgi++) {
4064                     final Ops ops = pkgOps.valueAt(pkgi);
4065                     if (dumpPackage != null && !dumpPackage.equals(ops.packageName)) {
4066                         continue;
4067                     }
4068                     boolean printedPackage = false;
4069                     for (int j=0; j<ops.size(); j++) {
4070                         final Op op = ops.valueAt(j);
4071                         final int opCode = op.op;
4072                         if (dumpOp >= 0 && dumpOp != opCode) {
4073                             continue;
4074                         }
4075                         if (dumpMode >= 0 && dumpMode != op.mode) {
4076                             continue;
4077                         }
4078                         if (!printedPackage) {
4079                             pw.print("    Package "); pw.print(ops.packageName); pw.println(":");
4080                             printedPackage = true;
4081                         }
4082                         pw.print("      "); pw.print(AppOpsManager.opToName(opCode));
4083                         pw.print(" ("); pw.print(AppOpsManager.modeToName(op.mode));
4084                         final int switchOp = AppOpsManager.opToSwitch(opCode);
4085                         if (switchOp != opCode) {
4086                             pw.print(" / switch ");
4087                             pw.print(AppOpsManager.opToName(switchOp));
4088                             final Op switchObj = ops.get(switchOp);
4089                             int mode = switchObj != null ? switchObj.mode
4090                                     : AppOpsManager.opToDefaultMode(switchOp);
4091                             pw.print("="); pw.print(AppOpsManager.modeToName(mode));
4092                         }
4093                         pw.println("): ");
4094                         dumpStatesLocked(pw, op, now, sdf, date, "          ");
4095                         if (op.running) {
4096                             pw.print("          Running start at: ");
4097                             TimeUtils.formatDuration(nowElapsed-op.startRealtime, pw);
4098                             pw.println();
4099                         }
4100                         if (op.startNesting != 0) {
4101                             pw.print("          startNesting=");
4102                             pw.println(op.startNesting);
4103                         }
4104                     }
4105                 }
4106             }
4107             if (needSep) {
4108                 pw.println();
4109             }
4110 
4111             final int userRestrictionCount = mOpUserRestrictions.size();
4112             for (int i = 0; i < userRestrictionCount; i++) {
4113                 IBinder token = mOpUserRestrictions.keyAt(i);
4114                 ClientRestrictionState restrictionState = mOpUserRestrictions.valueAt(i);
4115                 boolean printedTokenHeader = false;
4116 
4117                 if (dumpMode >= 0 || dumpWatchers || dumpHistory) {
4118                     continue;
4119                 }
4120 
4121                 final int restrictionCount = restrictionState.perUserRestrictions != null
4122                         ? restrictionState.perUserRestrictions.size() : 0;
4123                 if (restrictionCount > 0 && dumpPackage == null) {
4124                     boolean printedOpsHeader = false;
4125                     for (int j = 0; j < restrictionCount; j++) {
4126                         int userId = restrictionState.perUserRestrictions.keyAt(j);
4127                         boolean[] restrictedOps = restrictionState.perUserRestrictions.valueAt(j);
4128                         if (restrictedOps == null) {
4129                             continue;
4130                         }
4131                         if (dumpOp >= 0 && (dumpOp >= restrictedOps.length
4132                                 || !restrictedOps[dumpOp])) {
4133                             continue;
4134                         }
4135                         if (!printedTokenHeader) {
4136                             pw.println("  User restrictions for token " + token + ":");
4137                             printedTokenHeader = true;
4138                         }
4139                         if (!printedOpsHeader) {
4140                             pw.println("      Restricted ops:");
4141                             printedOpsHeader = true;
4142                         }
4143                         StringBuilder restrictedOpsValue = new StringBuilder();
4144                         restrictedOpsValue.append("[");
4145                         final int restrictedOpCount = restrictedOps.length;
4146                         for (int k = 0; k < restrictedOpCount; k++) {
4147                             if (restrictedOps[k]) {
4148                                 if (restrictedOpsValue.length() > 1) {
4149                                     restrictedOpsValue.append(", ");
4150                                 }
4151                                 restrictedOpsValue.append(AppOpsManager.opToName(k));
4152                             }
4153                         }
4154                         restrictedOpsValue.append("]");
4155                         pw.print("        "); pw.print("user: "); pw.print(userId);
4156                                 pw.print(" restricted ops: "); pw.println(restrictedOpsValue);
4157                     }
4158                 }
4159 
4160                 final int excludedPackageCount = restrictionState.perUserExcludedPackages != null
4161                         ? restrictionState.perUserExcludedPackages.size() : 0;
4162                 if (excludedPackageCount > 0 && dumpOp < 0) {
4163                     boolean printedPackagesHeader = false;
4164                     for (int j = 0; j < excludedPackageCount; j++) {
4165                         int userId = restrictionState.perUserExcludedPackages.keyAt(j);
4166                         String[] packageNames = restrictionState.perUserExcludedPackages.valueAt(j);
4167                         if (packageNames == null) {
4168                             continue;
4169                         }
4170                         boolean hasPackage;
4171                         if (dumpPackage != null) {
4172                             hasPackage = false;
4173                             for (String pkg : packageNames) {
4174                                 if (dumpPackage.equals(pkg)) {
4175                                     hasPackage = true;
4176                                     break;
4177                                 }
4178                             }
4179                         } else {
4180                             hasPackage = true;
4181                         }
4182                         if (!hasPackage) {
4183                             continue;
4184                         }
4185                         if (!printedTokenHeader) {
4186                             pw.println("  User restrictions for token " + token + ":");
4187                             printedTokenHeader = true;
4188                         }
4189                         if (!printedPackagesHeader) {
4190                             pw.println("      Excluded packages:");
4191                             printedPackagesHeader = true;
4192                         }
4193                         pw.print("        "); pw.print("user: "); pw.print(userId);
4194                                 pw.print(" packages: "); pw.println(Arrays.toString(packageNames));
4195                     }
4196                 }
4197             }
4198         }
4199 
4200         // Must not hold the appops lock
4201         if (dumpHistory && !dumpWatchers) {
4202             mHistoricalRegistry.dump("  ", pw, dumpUid, dumpPackage, dumpOp);
4203         }
4204     }
4205 
4206     private static final class Restriction {
4207         private static final ArraySet<String> NO_EXCEPTIONS = new ArraySet<String>();
4208         int mode;
4209         ArraySet<String> exceptionPackages = NO_EXCEPTIONS;
4210     }
4211 
4212     @Override
setUserRestrictions(Bundle restrictions, IBinder token, int userHandle)4213     public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) {
4214         checkSystemUid("setUserRestrictions");
4215         Preconditions.checkNotNull(restrictions);
4216         Preconditions.checkNotNull(token);
4217         for (int i = 0; i < AppOpsManager._NUM_OP; i++) {
4218             String restriction = AppOpsManager.opToRestriction(i);
4219             if (restriction != null) {
4220                 setUserRestrictionNoCheck(i, restrictions.getBoolean(restriction, false), token,
4221                         userHandle, null);
4222             }
4223         }
4224     }
4225 
4226     @Override
setUserRestriction(int code, boolean restricted, IBinder token, int userHandle, String[] exceptionPackages)4227     public void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle,
4228             String[] exceptionPackages) {
4229         if (Binder.getCallingPid() != Process.myPid()) {
4230             mContext.enforcePermission(Manifest.permission.MANAGE_APP_OPS_RESTRICTIONS,
4231                     Binder.getCallingPid(), Binder.getCallingUid(), null);
4232         }
4233         if (userHandle != UserHandle.getCallingUserId()) {
4234             if (mContext.checkCallingOrSelfPermission(Manifest.permission
4235                     .INTERACT_ACROSS_USERS_FULL) != PackageManager.PERMISSION_GRANTED
4236                 && mContext.checkCallingOrSelfPermission(Manifest.permission
4237                     .INTERACT_ACROSS_USERS) != PackageManager.PERMISSION_GRANTED) {
4238                 throw new SecurityException("Need INTERACT_ACROSS_USERS_FULL or"
4239                         + " INTERACT_ACROSS_USERS to interact cross user ");
4240             }
4241         }
4242         verifyIncomingOp(code);
4243         Preconditions.checkNotNull(token);
4244         setUserRestrictionNoCheck(code, restricted, token, userHandle, exceptionPackages);
4245     }
4246 
setUserRestrictionNoCheck(int code, boolean restricted, IBinder token, int userHandle, String[] exceptionPackages)4247     private void setUserRestrictionNoCheck(int code, boolean restricted, IBinder token,
4248             int userHandle, String[] exceptionPackages) {
4249         synchronized (AppOpsService.this) {
4250             ClientRestrictionState restrictionState = mOpUserRestrictions.get(token);
4251 
4252             if (restrictionState == null) {
4253                 try {
4254                     restrictionState = new ClientRestrictionState(token);
4255                 } catch (RemoteException e) {
4256                     return;
4257                 }
4258                 mOpUserRestrictions.put(token, restrictionState);
4259             }
4260 
4261             if (restrictionState.setRestriction(code, restricted, exceptionPackages, userHandle)) {
4262                 mHandler.sendMessage(PooledLambda.obtainMessage(
4263                         AppOpsService::notifyWatchersOfChange, this, code, UID_ANY));
4264             }
4265 
4266             if (restrictionState.isDefault()) {
4267                 mOpUserRestrictions.remove(token);
4268                 restrictionState.destroy();
4269             }
4270         }
4271     }
4272 
notifyWatchersOfChange(int code, int uid)4273     private void notifyWatchersOfChange(int code, int uid) {
4274         final ArraySet<ModeCallback> clonedCallbacks;
4275         synchronized (this) {
4276             ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code);
4277             if (callbacks == null) {
4278                 return;
4279             }
4280             clonedCallbacks = new ArraySet<>(callbacks);
4281         }
4282 
4283         notifyOpChanged(clonedCallbacks,  code, uid, null);
4284     }
4285 
4286     @Override
removeUser(int userHandle)4287     public void removeUser(int userHandle) throws RemoteException {
4288         checkSystemUid("removeUser");
4289         synchronized (AppOpsService.this) {
4290             final int tokenCount = mOpUserRestrictions.size();
4291             for (int i = tokenCount - 1; i >= 0; i--) {
4292                 ClientRestrictionState opRestrictions = mOpUserRestrictions.valueAt(i);
4293                 opRestrictions.removeUser(userHandle);
4294             }
4295             removeUidsForUserLocked(userHandle);
4296         }
4297     }
4298 
4299     @Override
isOperationActive(int code, int uid, String packageName)4300     public boolean isOperationActive(int code, int uid, String packageName) {
4301         if (Binder.getCallingUid() != uid) {
4302             if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS)
4303                     != PackageManager.PERMISSION_GRANTED) {
4304                 return false;
4305             }
4306         }
4307         verifyIncomingOp(code);
4308         final String resolvedPackageName = resolvePackageName(uid, packageName);
4309         if (resolvedPackageName == null) {
4310             return false;
4311         }
4312         synchronized (AppOpsService.this) {
4313             for (int i = mClients.size() - 1; i >= 0; i--) {
4314                 final ClientState client = mClients.valueAt(i);
4315                 for (int j = client.mStartedOps.size() - 1; j >= 0; j--) {
4316                     final Op op = client.mStartedOps.get(j);
4317                     if (op.op == code && op.uidState.uid == uid) return true;
4318                 }
4319             }
4320         }
4321         return false;
4322     }
4323 
4324     @Override
setHistoryParameters(@ppOpsManager.HistoricalMode int mode, long baseSnapshotInterval, int compressionStep)4325     public void setHistoryParameters(@AppOpsManager.HistoricalMode int mode,
4326             long baseSnapshotInterval, int compressionStep) {
4327         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
4328                 "setHistoryParameters");
4329         // Must not hold the appops lock
4330         mHistoricalRegistry.setHistoryParameters(mode, baseSnapshotInterval, compressionStep);
4331     }
4332 
4333     @Override
offsetHistory(long offsetMillis)4334     public void offsetHistory(long offsetMillis) {
4335         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
4336                 "offsetHistory");
4337         // Must not hold the appops lock
4338         mHistoricalRegistry.offsetHistory(offsetMillis);
4339     }
4340 
4341     @Override
addHistoricalOps(HistoricalOps ops)4342     public void addHistoricalOps(HistoricalOps ops) {
4343         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
4344                 "addHistoricalOps");
4345         // Must not hold the appops lock
4346         mHistoricalRegistry.addHistoricalOps(ops);
4347     }
4348 
4349     @Override
resetHistoryParameters()4350     public void resetHistoryParameters() {
4351         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
4352                 "resetHistoryParameters");
4353         // Must not hold the appops lock
4354         mHistoricalRegistry.resetHistoryParameters();
4355     }
4356 
4357     @Override
clearHistory()4358     public void clearHistory() {
4359         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
4360                 "clearHistory");
4361         // Must not hold the appops lock
4362         mHistoricalRegistry.clearHistory();
4363     }
4364 
removeUidsForUserLocked(int userHandle)4365     private void removeUidsForUserLocked(int userHandle) {
4366         for (int i = mUidStates.size() - 1; i >= 0; --i) {
4367             final int uid = mUidStates.keyAt(i);
4368             if (UserHandle.getUserId(uid) == userHandle) {
4369                 mUidStates.removeAt(i);
4370             }
4371         }
4372     }
4373 
checkSystemUid(String function)4374     private void checkSystemUid(String function) {
4375         int uid = Binder.getCallingUid();
4376         if (uid != Process.SYSTEM_UID) {
4377             throw new SecurityException(function + " must by called by the system");
4378         }
4379     }
4380 
resolvePackageName(int uid, String packageName)4381     private static String resolvePackageName(int uid, String packageName)  {
4382         if (uid == Process.ROOT_UID) {
4383             return "root";
4384         } else if (uid == Process.SHELL_UID) {
4385             return "com.android.shell";
4386         } else if (uid == Process.MEDIA_UID) {
4387             return "media";
4388         } else if (uid == Process.AUDIOSERVER_UID) {
4389             return "audioserver";
4390         } else if (uid == Process.CAMERASERVER_UID) {
4391             return "cameraserver";
4392         } else if (uid == Process.SYSTEM_UID && packageName == null) {
4393             return "android";
4394         }
4395         return packageName;
4396     }
4397 
resolveUid(String packageName)4398     private static int resolveUid(String packageName)  {
4399         if (packageName == null) {
4400             return -1;
4401         }
4402         switch (packageName) {
4403             case "root":
4404                 return Process.ROOT_UID;
4405             case "shell":
4406                 return Process.SHELL_UID;
4407             case "media":
4408                 return Process.MEDIA_UID;
4409             case "audioserver":
4410                 return Process.AUDIOSERVER_UID;
4411             case "cameraserver":
4412                 return Process.CAMERASERVER_UID;
4413         }
4414         return -1;
4415     }
4416 
getPackagesForUid(int uid)4417     private static String[] getPackagesForUid(int uid) {
4418         String[] packageNames = null;
4419 
4420         // Very early during boot the package manager is not yet or not yet fully started. At this
4421         // time there are no packages yet.
4422         if (AppGlobals.getPackageManager() != null) {
4423             try {
4424                 packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid);
4425             } catch (RemoteException e) {
4426                 /* ignore - local call */
4427             }
4428         }
4429         if (packageNames == null) {
4430             return EmptyArray.STRING;
4431         }
4432         return packageNames;
4433     }
4434 
4435     private final class ClientRestrictionState implements DeathRecipient {
4436         private final IBinder token;
4437         SparseArray<boolean[]> perUserRestrictions;
4438         SparseArray<String[]> perUserExcludedPackages;
4439 
ClientRestrictionState(IBinder token)4440         public ClientRestrictionState(IBinder token)
4441                 throws RemoteException {
4442             token.linkToDeath(this, 0);
4443             this.token = token;
4444         }
4445 
setRestriction(int code, boolean restricted, String[] excludedPackages, int userId)4446         public boolean setRestriction(int code, boolean restricted,
4447                 String[] excludedPackages, int userId) {
4448             boolean changed = false;
4449 
4450             if (perUserRestrictions == null && restricted) {
4451                 perUserRestrictions = new SparseArray<>();
4452             }
4453 
4454             int[] users;
4455             if (userId == UserHandle.USER_ALL) {
4456                 List<UserInfo> liveUsers = UserManager.get(mContext).getUsers(false);
4457 
4458                 users = new int[liveUsers.size()];
4459                 for (int i = 0; i < liveUsers.size(); i++) {
4460                     users[i] = liveUsers.get(i).id;
4461                 }
4462             } else {
4463                 users = new int[]{userId};
4464             }
4465 
4466             if (perUserRestrictions != null) {
4467                 int numUsers = users.length;
4468 
4469                 for (int i = 0; i < numUsers; i++) {
4470                     int thisUserId = users[i];
4471 
4472                     boolean[] userRestrictions = perUserRestrictions.get(thisUserId);
4473                     if (userRestrictions == null && restricted) {
4474                         userRestrictions = new boolean[AppOpsManager._NUM_OP];
4475                         perUserRestrictions.put(thisUserId, userRestrictions);
4476                     }
4477                     if (userRestrictions != null && userRestrictions[code] != restricted) {
4478                         userRestrictions[code] = restricted;
4479                         if (!restricted && isDefault(userRestrictions)) {
4480                             perUserRestrictions.remove(thisUserId);
4481                             userRestrictions = null;
4482                         }
4483                         changed = true;
4484                     }
4485 
4486                     if (userRestrictions != null) {
4487                         final boolean noExcludedPackages = ArrayUtils.isEmpty(excludedPackages);
4488                         if (perUserExcludedPackages == null && !noExcludedPackages) {
4489                             perUserExcludedPackages = new SparseArray<>();
4490                         }
4491                         if (perUserExcludedPackages != null && !Arrays.equals(excludedPackages,
4492                                 perUserExcludedPackages.get(thisUserId))) {
4493                             if (noExcludedPackages) {
4494                                 perUserExcludedPackages.remove(thisUserId);
4495                                 if (perUserExcludedPackages.size() <= 0) {
4496                                     perUserExcludedPackages = null;
4497                                 }
4498                             } else {
4499                                 perUserExcludedPackages.put(thisUserId, excludedPackages);
4500                             }
4501                             changed = true;
4502                         }
4503                     }
4504                 }
4505             }
4506 
4507             return changed;
4508         }
4509 
hasRestriction(int restriction, String packageName, int userId)4510         public boolean hasRestriction(int restriction, String packageName, int userId) {
4511             if (perUserRestrictions == null) {
4512                 return false;
4513             }
4514             boolean[] restrictions = perUserRestrictions.get(userId);
4515             if (restrictions == null) {
4516                 return false;
4517             }
4518             if (!restrictions[restriction]) {
4519                 return false;
4520             }
4521             if (perUserExcludedPackages == null) {
4522                 return true;
4523             }
4524             String[] perUserExclusions = perUserExcludedPackages.get(userId);
4525             if (perUserExclusions == null) {
4526                 return true;
4527             }
4528             return !ArrayUtils.contains(perUserExclusions, packageName);
4529         }
4530 
removeUser(int userId)4531         public void removeUser(int userId) {
4532             if (perUserExcludedPackages != null) {
4533                 perUserExcludedPackages.remove(userId);
4534                 if (perUserExcludedPackages.size() <= 0) {
4535                     perUserExcludedPackages = null;
4536                 }
4537             }
4538             if (perUserRestrictions != null) {
4539                 perUserRestrictions.remove(userId);
4540                 if (perUserRestrictions.size() <= 0) {
4541                     perUserRestrictions = null;
4542                 }
4543             }
4544         }
4545 
isDefault()4546         public boolean isDefault() {
4547             return perUserRestrictions == null || perUserRestrictions.size() <= 0;
4548         }
4549 
4550         @Override
binderDied()4551         public void binderDied() {
4552             synchronized (AppOpsService.this) {
4553                 mOpUserRestrictions.remove(token);
4554                 if (perUserRestrictions == null) {
4555                     return;
4556                 }
4557                 final int userCount = perUserRestrictions.size();
4558                 for (int i = 0; i < userCount; i++) {
4559                     final boolean[] restrictions = perUserRestrictions.valueAt(i);
4560                     final int restrictionCount = restrictions.length;
4561                     for (int j = 0; j < restrictionCount; j++) {
4562                         if (restrictions[j]) {
4563                             final int changedCode = j;
4564                             mHandler.post(() -> notifyWatchersOfChange(changedCode, UID_ANY));
4565                         }
4566                     }
4567                 }
4568                 destroy();
4569             }
4570         }
4571 
destroy()4572         public void destroy() {
4573             token.unlinkToDeath(this, 0);
4574         }
4575 
isDefault(boolean[] array)4576         private boolean isDefault(boolean[] array) {
4577             if (ArrayUtils.isEmpty(array)) {
4578                 return true;
4579             }
4580             for (boolean value : array) {
4581                 if (value) {
4582                     return false;
4583                 }
4584             }
4585             return true;
4586         }
4587     }
4588 
4589     private final class AppOpsManagerInternalImpl extends AppOpsManagerInternal {
setDeviceAndProfileOwners(SparseIntArray owners)4590         @Override public void setDeviceAndProfileOwners(SparseIntArray owners) {
4591             synchronized (AppOpsService.this) {
4592                 mProfileOwners = owners;
4593             }
4594         }
4595 
4596         @Override
setUidMode(int code, int uid, int mode)4597         public void setUidMode(int code, int uid, int mode) {
4598             AppOpsService.this.setUidMode(code, uid, mode);
4599         }
4600 
4601         @Override
setAllPkgModesToDefault(int code, int uid)4602         public void setAllPkgModesToDefault(int code, int uid) {
4603             AppOpsService.this.setAllPkgModesToDefault(code, uid);
4604         }
4605 
4606         @Override
checkOperationUnchecked(int code, int uid, @NonNull String packageName)4607         public @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName) {
4608             return AppOpsService.this.checkOperationUnchecked(code, uid, packageName, true, false);
4609         }
4610     }
4611 }
4612