Home | History | Annotate | Download | only in server
      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 
    246         public Constants(Handler handler) {
    247             super(handler);
    248             updateConstants();
    249         }
    250 
    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
    260         public void onChange(boolean selfChange, Uri uri) {
    261             updateConstants();
    262         }
    263 
    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 
    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 
    318         public UidState(int uid) {
    319             this.uid = uid;
    320         }
    321 
    322         public void clear() {
    323             pkgOps = null;
    324             opModes = null;
    325         }
    326 
    327         public boolean isDefault() {
    328             return (pkgOps == null || pkgOps.isEmpty())
    329                     && (opModes == null || opModes.size() <= 0);
    330         }
    331 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    463         public boolean isWatchingUid(int uid) {
    464             return uid == UID_ANY || mWatchingUid < 0 || mWatchingUid == uid;
    465         }
    466 
    467         @Override
    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 
    484         void unlinkToDeath() {
    485             mCallback.asBinder().unlinkToDeath(this, 0);
    486         }
    487 
    488         @Override
    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 
    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
    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 
    527         void destroy() {
    528             mCallback.asBinder().unlinkToDeath(this, 0);
    529         }
    530 
    531         @Override
    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 
    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
    558         public String toString() {
    559             return "ClientState{" +
    560                     "mAppToken=" + mAppToken +
    561                     ", " + "pid=" + mPid +
    562                     '}';
    563         }
    564 
    565         @Override
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    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
    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
    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 
    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 
    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
    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
   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 
   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 
   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 
   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 
   1199         ChangeRec(int _op, int _uid, String _pkg) {
   1200             op = _op;
   1201             uid = _uid;
   1202             pkg = _pkg;
   1203         }
   1204     }
   1205 
   1206     @Override
   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 
   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
   1328     public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) {
   1329         startWatchingModeWithFlags(op, packageName, 0, callback);
   1330     }
   1331 
   1332     @Override
   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
   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
   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
   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
   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 
   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 
   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
   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
   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
   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
   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 
   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
   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
   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
   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
   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 
   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 
   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
   1829     public int permissionToOpCode(String permission) {
   1830         if (permission == null) {
   1831             return AppOpsManager.OP_NONE;
   1832         }
   1833         return AppOpsManager.permissionToOpCode(permission);
   1834     }
   1835 
   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 
   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 
   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 
   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 
   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 
   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 
   2002     private void scheduleWriteLocked() {
   2003         if (!mWriteScheduled) {
   2004             mWriteScheduled = true;
   2005             mHandler.postDelayed(mWriteRunner, WRITE_DELAY);
   2006         }
   2007     }
   2008 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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
   2519         public int onCommand(String cmd) {
   2520             return onShellCommand(this, cmd);
   2521         }
   2522 
   2523         @Override
   2524         public void onHelp() {
   2525             PrintWriter pw = getOutPrintWriter();
   2526             dumpCommandHelp(pw);
   2527         }
   2528 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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
   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 
   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 
   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 
   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 
   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 
   3623         public ClientRestrictionState(IBinder token)
   3624                 throws RemoteException {
   3625             token.linkToDeath(this, 0);
   3626             this.token = token;
   3627         }
   3628 
   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 
   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 
   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 
   3729         public boolean isDefault() {
   3730             return perUserRestrictions == null || perUserRestrictions.size() <= 0;
   3731         }
   3732 
   3733         @Override
   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 
   3755         public void destroy() {
   3756             token.unlinkToDeath(this, 0);
   3757         }
   3758 
   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 {
   3773         @Override public void setDeviceAndProfileOwners(SparseIntArray owners) {
   3774             synchronized (AppOpsService.this) {
   3775                 mProfileOwners = owners;
   3776             }
   3777         }
   3778     }
   3779 }
   3780