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