1a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn/* 2a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * Copyright (C) 2012 The Android Open Source Project 3a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * 4a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License"); 5a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * you may not use this file except in compliance with the License. 6a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * You may obtain a copy of the License at 7a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * 8a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * http://www.apache.org/licenses/LICENSE-2.0 9a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * 10a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * Unless required by applicable law or agreed to in writing, software 11a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS, 12a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * See the License for the specific language governing permissions and 14a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * limitations under the License. 15a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn */ 16a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 17a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornpackage com.android.server; 18a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 19a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport java.io.File; 20a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport java.io.FileDescriptor; 2135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.io.FileInputStream; 2235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.io.FileNotFoundException; 2335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.io.FileOutputStream; 2435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.io.IOException; 25a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport java.io.PrintWriter; 269e9e2e73c6ec7bece20268196dc89ad0c8bafad4Wojciech Staszkiewiczimport java.nio.charset.StandardCharsets; 2735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.util.ArrayList; 28a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganovimport java.util.Arrays; 29215b44a1c2c883e628e1ab5b945a1a4aa04ee392Svetoslavimport java.util.Collections; 30a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport java.util.HashMap; 31c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackbornimport java.util.Iterator; 3235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.util.List; 33607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackbornimport java.util.Map; 34a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 359cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganovimport android.Manifest; 367b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackbornimport android.app.ActivityManager; 371c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monkimport android.app.ActivityThread; 382af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganovimport android.app.AppGlobals; 39a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.app.AppOpsManager; 40a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.content.Context; 411c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monkimport android.content.pm.ApplicationInfo; 421c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monkimport android.content.pm.IPackageManager; 43a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.content.pm.PackageManager; 447b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlockimport android.media.AudioAttributes; 4535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport android.os.AsyncTask; 46a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.Binder; 4762062996dd256df8b575b2ba1f0bf97109c4e0baJason Monkimport android.os.Bundle; 4835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport android.os.Handler; 49c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackbornimport android.os.IBinder; 50a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.Process; 51c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackbornimport android.os.RemoteException; 52268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackbornimport android.os.ResultReceiver; 53a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.ServiceManager; 54268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackbornimport android.os.ShellCommand; 55a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.UserHandle; 566ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganovimport android.os.storage.MountServiceInternal; 57e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackbornimport android.util.ArrayMap; 581af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.util.ArraySet; 59a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.AtomicFile; 605e45ee6752528791deb66b83d76250685de15d47Dianne Hackbornimport android.util.Log; 61a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.Slog; 62a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.SparseArray; 632af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganovimport android.util.SparseIntArray; 64a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.TimeUtils; 6535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport android.util.Xml; 66a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 67a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IAppOpsService; 68c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackbornimport com.android.internal.app.IAppOpsCallback; 696ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganovimport com.android.internal.os.Zygote; 702af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganovimport com.android.internal.util.ArrayUtils; 7135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport com.android.internal.util.FastXmlSerializer; 729cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganovimport com.android.internal.util.Preconditions; 7335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport com.android.internal.util.XmlUtils; 7435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 752af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganovimport libcore.util.EmptyArray; 7635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport org.xmlpull.v1.XmlPullParser; 7735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport org.xmlpull.v1.XmlPullParserException; 7835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport org.xmlpull.v1.XmlSerializer; 79a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 80a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornpublic class AppOpsService extends IAppOpsService.Stub { 81a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn static final String TAG = "AppOps"; 8235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn static final boolean DEBUG = false; 8335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 8435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn // Write at most every 30 minutes. 8535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000; 86a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 87a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Context mContext; 88a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final AtomicFile mFile; 8935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn final Handler mHandler; 9035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 9135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn boolean mWriteScheduled; 927b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn boolean mFastWriteScheduled; 9335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn final Runnable mWriteRunner = new Runnable() { 9435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public void run() { 9535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn synchronized (AppOpsService.this) { 9635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mWriteScheduled = false; 977b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn mFastWriteScheduled = false; 9835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() { 9935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn @Override protected Void doInBackground(Void... params) { 10035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn writeState(); 10135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return null; 10235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 10335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn }; 10435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null); 10535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 10635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 10735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn }; 108a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 1099cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov private final SparseArray<UidState> mUidStates = new SparseArray<>(); 110a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 11129931bc684bde6b430923122777684178ee2681cRuben Brunk /* 11229931bc684bde6b430923122777684178ee2681cRuben Brunk * These are app op restrictions imposed per user from various parties. 11329931bc684bde6b430923122777684178ee2681cRuben Brunk */ 114a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov private final ArrayMap<IBinder, ClientRestrictionState> mOpUserRestrictions = new ArrayMap<>(); 11562062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk 1162af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov private static final class UidState { 1172af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov public final int uid; 1182af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov public ArrayMap<String, Ops> pkgOps; 1192af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov public SparseIntArray opModes; 1202af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 1212af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov public UidState(int uid) { 1222af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov this.uid = uid; 1232af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 1242af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 1252af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov public void clear() { 1262af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov pkgOps = null; 1272af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov opModes = null; 1282af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 1292af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 1302af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov public boolean isDefault() { 1312af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov return (pkgOps == null || pkgOps.isEmpty()) 1322af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov && (opModes == null || opModes.size() <= 0); 1332af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 1342af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 1352af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 136c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn public final static class Ops extends SparseArray<Op> { 137a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn public final String packageName; 1382af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov public final UidState uidState; 1391c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk public final boolean isPrivileged; 140a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 1412af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov public Ops(String _packageName, UidState _uidState, boolean _isPrivileged) { 142a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn packageName = _packageName; 1432af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState = _uidState; 1441c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk isPrivileged = _isPrivileged; 145a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 146a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 147a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 148c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn public final static class Op { 149e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn public final int uid; 150e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn public final String packageName; 15199b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov public int proxyUid = -1; 15299b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov public String proxyPackageName; 153a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn public final int op; 1545e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn public int mode; 155a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn public int duration; 156a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn public long time; 1575e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn public long rejectTime; 15835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public int nesting; 159a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 160e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn public Op(int _uid, String _packageName, int _op) { 161e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn uid = _uid; 162e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn packageName = _packageName; 163a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn op = _op; 164f5d831915dd11e77cdcf5669228c55fe17a21c5eDavid Braun mode = AppOpsManager.opToDefaultMode(op); 165a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 166a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 167a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 168c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn final SparseArray<ArrayList<Callback>> mOpModeWatchers 169c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn = new SparseArray<ArrayList<Callback>>(); 170e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn final ArrayMap<String, ArrayList<Callback>> mPackageModeWatchers 171e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn = new ArrayMap<String, ArrayList<Callback>>(); 172e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn final ArrayMap<IBinder, Callback> mModeWatchers 173e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn = new ArrayMap<IBinder, Callback>(); 1741af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock final SparseArray<SparseArray<Restriction>> mAudioRestrictions 1751af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock = new SparseArray<SparseArray<Restriction>>(); 176c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn 177c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn public final class Callback implements DeathRecipient { 178c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn final IAppOpsCallback mCallback; 179c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn 180c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn public Callback(IAppOpsCallback callback) { 181c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn mCallback = callback; 182c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn try { 183c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn mCallback.asBinder().linkToDeath(this, 0); 184c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } catch (RemoteException e) { 185c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 186c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 187c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn 188c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn public void unlinkToDeath() { 189c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn mCallback.asBinder().unlinkToDeath(this, 0); 190c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 191c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn 192c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn @Override 193c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn public void binderDied() { 194c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn stopWatchingMode(mCallback); 195c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 196c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 197c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn 198e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<IBinder, ClientState>(); 199e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn 200e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn public final class ClientState extends Binder implements DeathRecipient { 201e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn final IBinder mAppToken; 202e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn final int mPid; 203e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn final ArrayList<Op> mStartedOps; 204e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn 205e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn public ClientState(IBinder appToken) { 206e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn mAppToken = appToken; 207e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn mPid = Binder.getCallingPid(); 208e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn if (appToken instanceof Binder) { 209e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn // For local clients, there is no reason to track them. 210e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn mStartedOps = null; 211e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } else { 212e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn mStartedOps = new ArrayList<Op>(); 213e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn try { 214e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn mAppToken.linkToDeath(this, 0); 215e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } catch (RemoteException e) { 216e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 217e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 218e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 219e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn 220e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn @Override 221e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn public String toString() { 222e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn return "ClientState{" + 223e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn "mAppToken=" + mAppToken + 224e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn ", " + (mStartedOps != null ? ("pid=" + mPid) : "local") + 225e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn '}'; 226e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 227e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn 228e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn @Override 229e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn public void binderDied() { 230e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn synchronized (AppOpsService.this) { 231e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn for (int i=mStartedOps.size()-1; i>=0; i--) { 232e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn finishOperationLocked(mStartedOps.get(i)); 233e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 234e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn mClients.remove(mAppToken); 235e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 236e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 237e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 238e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn 2396f357d3284a833cc50a990e14b39f389b8972254Jeff Brown public AppOpsService(File storagePath, Handler handler) { 24035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mFile = new AtomicFile(storagePath); 2416f357d3284a833cc50a990e14b39f389b8972254Jeff Brown mHandler = handler; 24235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn readState(); 243a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 244f5d831915dd11e77cdcf5669228c55fe17a21c5eDavid Braun 245a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn public void publish(Context context) { 246a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mContext = context; 247a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder()); 248a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 249a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 250514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn public void systemReady() { 251514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn synchronized (this) { 252514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn boolean changed = false; 2532af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov for (int i = mUidStates.size() - 1; i >= 0; i--) { 2542af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov UidState uidState = mUidStates.valueAt(i); 2552af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 2562af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov String[] packageNames = getPackagesForUid(uidState.uid); 2572af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (ArrayUtils.isEmpty(packageNames)) { 2582af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState.clear(); 2592af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov mUidStates.removeAt(i); 2602af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov changed = true; 2612af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov continue; 2622af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 2632af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 2642af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov ArrayMap<String, Ops> pkgs = uidState.pkgOps; 2652af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (pkgs == null) { 2662af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov continue; 2672af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 2682af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 269514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn Iterator<Ops> it = pkgs.values().iterator(); 270514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn while (it.hasNext()) { 271514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn Ops ops = it.next(); 272e2ed23e6b221185ce2587fb19a6e904dbf7ec77bJeff Sharkey int curUid = -1; 273514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn try { 274cd65448ccd13c4c2d0fe9e9623fec3a898ab9372Jeff Sharkey curUid = AppGlobals.getPackageManager().getPackageUid(ops.packageName, 275cd65448ccd13c4c2d0fe9e9623fec3a898ab9372Jeff Sharkey PackageManager.MATCH_UNINSTALLED_PACKAGES, 2762af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov UserHandle.getUserId(ops.uidState.uid)); 277e2ed23e6b221185ce2587fb19a6e904dbf7ec77bJeff Sharkey } catch (RemoteException ignored) { 278514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn } 2792af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (curUid != ops.uidState.uid) { 280514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn Slog.i(TAG, "Pruning old package " + ops.packageName 2812af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov + "/" + ops.uidState + ": new uid=" + curUid); 282514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn it.remove(); 283514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn changed = true; 284514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn } 285514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn } 2862af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 2872af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidState.isDefault()) { 2882af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov mUidStates.removeAt(i); 289514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn } 290514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn } 291514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn if (changed) { 2927b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn scheduleFastWriteLocked(); 293514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn } 294514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn } 2956ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov 2966ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov MountServiceInternal mountServiceInternal = LocalServices.getService( 2976ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov MountServiceInternal.class); 2986ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov mountServiceInternal.addExternalStoragePolicy( 2996ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov new MountServiceInternal.ExternalStorageMountPolicy() { 3006ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov @Override 3016ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov public int getMountMode(int uid, String packageName) { 3026ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov if (Process.isIsolated(uid)) { 3036ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov return Zygote.MOUNT_EXTERNAL_NONE; 3046ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov } 3056ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov if (noteOperation(AppOpsManager.OP_READ_EXTERNAL_STORAGE, uid, 3066ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov packageName) != AppOpsManager.MODE_ALLOWED) { 3076ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov return Zygote.MOUNT_EXTERNAL_NONE; 3086ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov } 3096ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov if (noteOperation(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, uid, 3106ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov packageName) != AppOpsManager.MODE_ALLOWED) { 3116ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov return Zygote.MOUNT_EXTERNAL_READ; 3126ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov } 3136ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov return Zygote.MOUNT_EXTERNAL_WRITE; 3146ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov } 3156ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov 3166ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov @Override 3176ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov public boolean hasExternalStorage(int uid, String packageName) { 3186ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov final int mountMode = getMountMode(uid, packageName); 3196ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov return mountMode == Zygote.MOUNT_EXTERNAL_READ 3206ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov || mountMode == Zygote.MOUNT_EXTERNAL_WRITE; 3216ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov } 3226ee871e59812fea4525c50231f677c4bd10c74b8Svet Ganov }); 323514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn } 324514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn 325514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn public void packageRemoved(int uid, String packageName) { 326514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn synchronized (this) { 3272af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov UidState uidState = mUidStates.get(uid); 3282af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidState == null) { 3292af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov return; 3302af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 3312af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 3322af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov boolean changed = false; 3332af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 3342af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov // Remove any package state if such. 3352af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidState.pkgOps != null && uidState.pkgOps.remove(packageName) != null) { 3362af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov changed = true; 3372af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 3382af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 3392af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov // If we just nuked the last package state check if the UID is valid. 3402af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (changed && uidState.pkgOps.isEmpty() 3412af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov && getPackagesForUid(uid).length <= 0) { 3422af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov mUidStates.remove(uid); 3432af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 3442af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 3452af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (changed) { 3462af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov scheduleFastWriteLocked(); 347514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn } 348514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn } 349514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn } 350514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn 351514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn public void uidRemoved(int uid) { 352514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn synchronized (this) { 3532af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (mUidStates.indexOfKey(uid) >= 0) { 3542af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov mUidStates.remove(uid); 3557b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn scheduleFastWriteLocked(); 356514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn } 357514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn } 358514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn } 359514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn 360a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn public void shutdown() { 361a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Slog.w(TAG, "Writing app ops before shutdown..."); 36235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn boolean doWrite = false; 36335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn synchronized (this) { 36435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (mWriteScheduled) { 36535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mWriteScheduled = false; 36635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn doWrite = true; 36735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 36835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 36935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (doWrite) { 37035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn writeState(); 37135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 372a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 373a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 37472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) { 37572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn ArrayList<AppOpsManager.OpEntry> resOps = null; 37672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn if (ops == null) { 37772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn resOps = new ArrayList<AppOpsManager.OpEntry>(); 37872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn for (int j=0; j<pkgOps.size(); j++) { 37972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn Op curOp = pkgOps.valueAt(j); 3805e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time, 38199b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov curOp.rejectTime, curOp.duration, curOp.proxyUid, 38299b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov curOp.proxyPackageName)); 38372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 38472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } else { 38572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn for (int j=0; j<ops.length; j++) { 38672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn Op curOp = pkgOps.get(ops[j]); 38772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn if (curOp != null) { 38872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn if (resOps == null) { 38972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn resOps = new ArrayList<AppOpsManager.OpEntry>(); 39072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 3915e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time, 39299b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov curOp.rejectTime, curOp.duration, curOp.proxyUid, 39399b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov curOp.proxyPackageName)); 39472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 39572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 39672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 39772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn return resOps; 39872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 39972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn 400a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn @Override 40135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) { 40235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 40335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 40435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn ArrayList<AppOpsManager.PackageOps> res = null; 405a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (this) { 4062af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int uidStateCount = mUidStates.size(); 4072af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov for (int i = 0; i < uidStateCount; i++) { 4082af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov UidState uidState = mUidStates.valueAt(i); 4092af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidState.pkgOps == null || uidState.pkgOps.isEmpty()) { 4102af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov continue; 4112af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 4122af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov ArrayMap<String, Ops> packages = uidState.pkgOps; 4132af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int packageCount = packages.size(); 4142af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov for (int j = 0; j < packageCount; j++) { 4152af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov Ops pkgOps = packages.valueAt(j); 41672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops); 41735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (resOps != null) { 41835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (res == null) { 41935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn res = new ArrayList<AppOpsManager.PackageOps>(); 42035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 42135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( 4222af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov pkgOps.packageName, pkgOps.uidState.uid, resOps); 42335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn res.add(resPackage); 42435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 42535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 426a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 427a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 42835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return res; 429a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 430a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 431a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn @Override 43272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, 43372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn int[] ops) { 43472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 43572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 436f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov String resolvedPackageName = resolvePackageName(uid, packageName); 437f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov if (resolvedPackageName == null) { 438f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov return Collections.emptyList(); 439f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov } 44072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn synchronized (this) { 441f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false); 44272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn if (pkgOps == null) { 44372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn return null; 44472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 44572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops); 44672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn if (resOps == null) { 44772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn return null; 44872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 44972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>(); 45072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( 4512af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov pkgOps.packageName, pkgOps.uidState.uid, resOps); 45272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn res.add(resPackage); 45372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn return res; 45472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 45572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 45672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn 457607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn private void pruneOp(Op op, int uid, String packageName) { 458607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn if (op.time == 0 && op.rejectTime == 0) { 459f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov Ops ops = getOpsRawLocked(uid, packageName, false); 460607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn if (ops != null) { 461607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn ops.remove(op.op); 462607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn if (ops.size() <= 0) { 4632af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov UidState uidState = ops.uidState; 4642af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov ArrayMap<String, Ops> pkgOps = uidState.pkgOps; 465607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn if (pkgOps != null) { 466607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn pkgOps.remove(ops.packageName); 4672af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (pkgOps.isEmpty()) { 4682af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState.pkgOps = null; 4692af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 4702af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidState.isDefault()) { 4712af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov mUidStates.remove(uid); 4722af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 4732af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 4742af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 4752af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 4762af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 4772af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 4782af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 4792af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov @Override 4802af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov public void setUidMode(int code, int uid, int mode) { 4812af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (Binder.getCallingPid() != Process.myPid()) { 4822af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 4832af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov Binder.getCallingPid(), Binder.getCallingUid(), null); 4842af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 4852af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov verifyIncomingOp(code); 4862af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov code = AppOpsManager.opToSwitch(code); 4872af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 4882af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov synchronized (this) { 4892af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int defaultMode = AppOpsManager.opToDefaultMode(code); 4902af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 4912af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov UidState uidState = getUidStateLocked(uid, false); 4922af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidState == null) { 4932af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (mode == defaultMode) { 4942af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov return; 4952af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 4962af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState = new UidState(uid); 4972af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState.opModes = new SparseIntArray(); 4982af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState.opModes.put(code, mode); 4992af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov mUidStates.put(uid, uidState); 5002af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov scheduleWriteLocked(); 5012af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } else if (uidState.opModes == null) { 5022af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (mode != defaultMode) { 5032af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState.opModes = new SparseIntArray(); 5042af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState.opModes.put(code, mode); 5052af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov scheduleWriteLocked(); 5062af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 5072af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } else { 5082af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidState.opModes.get(code) == mode) { 5092af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov return; 5102af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 5112af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (mode == defaultMode) { 5122af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState.opModes.delete(code); 5132af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidState.opModes.size() <= 0) { 5142af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState.opModes = null; 5152af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 5162af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } else { 5172af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState.opModes.put(code, mode); 5182af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 5192af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov scheduleWriteLocked(); 5202af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 5212af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 5222af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 523215b44a1c2c883e628e1ab5b945a1a4aa04ee392Svetoslav String[] uidPackageNames = getPackagesForUid(uid); 5242af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov ArrayMap<Callback, ArraySet<String>> callbackSpecs = null; 5252af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 52640b300fd80708fd100d22f22ff6100db20ee467friddle_hsu synchronized (this) { 52740b300fd80708fd100d22f22ff6100db20ee467friddle_hsu ArrayList<Callback> callbacks = mOpModeWatchers.get(code); 5282af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (callbacks != null) { 5292af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int callbackCount = callbacks.size(); 5302af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov for (int i = 0; i < callbackCount; i++) { 5312af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov Callback callback = callbacks.get(i); 53240b300fd80708fd100d22f22ff6100db20ee467friddle_hsu ArraySet<String> changedPackages = new ArraySet<>(); 53340b300fd80708fd100d22f22ff6100db20ee467friddle_hsu Collections.addAll(changedPackages, uidPackageNames); 53440b300fd80708fd100d22f22ff6100db20ee467friddle_hsu callbackSpecs = new ArrayMap<>(); 53540b300fd80708fd100d22f22ff6100db20ee467friddle_hsu callbackSpecs.put(callback, changedPackages); 53640b300fd80708fd100d22f22ff6100db20ee467friddle_hsu } 53740b300fd80708fd100d22f22ff6100db20ee467friddle_hsu } 53840b300fd80708fd100d22f22ff6100db20ee467friddle_hsu 53940b300fd80708fd100d22f22ff6100db20ee467friddle_hsu for (String uidPackageName : uidPackageNames) { 54040b300fd80708fd100d22f22ff6100db20ee467friddle_hsu callbacks = mPackageModeWatchers.get(uidPackageName); 54140b300fd80708fd100d22f22ff6100db20ee467friddle_hsu if (callbacks != null) { 54240b300fd80708fd100d22f22ff6100db20ee467friddle_hsu if (callbackSpecs == null) { 54340b300fd80708fd100d22f22ff6100db20ee467friddle_hsu callbackSpecs = new ArrayMap<>(); 54440b300fd80708fd100d22f22ff6100db20ee467friddle_hsu } 54540b300fd80708fd100d22f22ff6100db20ee467friddle_hsu final int callbackCount = callbacks.size(); 54640b300fd80708fd100d22f22ff6100db20ee467friddle_hsu for (int i = 0; i < callbackCount; i++) { 54740b300fd80708fd100d22f22ff6100db20ee467friddle_hsu Callback callback = callbacks.get(i); 54840b300fd80708fd100d22f22ff6100db20ee467friddle_hsu ArraySet<String> changedPackages = callbackSpecs.get(callback); 54940b300fd80708fd100d22f22ff6100db20ee467friddle_hsu if (changedPackages == null) { 55040b300fd80708fd100d22f22ff6100db20ee467friddle_hsu changedPackages = new ArraySet<>(); 55140b300fd80708fd100d22f22ff6100db20ee467friddle_hsu callbackSpecs.put(callback, changedPackages); 55240b300fd80708fd100d22f22ff6100db20ee467friddle_hsu } 55340b300fd80708fd100d22f22ff6100db20ee467friddle_hsu changedPackages.add(uidPackageName); 5542af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 5552af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 5562af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 5572af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 5582af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 5592af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (callbackSpecs == null) { 5602af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov return; 5612af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 5622af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 5632af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov // There are components watching for mode changes such as window manager 5642af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov // and location manager which are in our process. The callbacks in these 5652af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov // components may require permissions our remote caller does not have. 5662af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final long identity = Binder.clearCallingIdentity(); 5672af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov try { 5682af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov for (int i = 0; i < callbackSpecs.size(); i++) { 5692af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov Callback callback = callbackSpecs.keyAt(i); 5702af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov ArraySet<String> reportedPackageNames = callbackSpecs.valueAt(i); 5712af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov try { 5722af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (reportedPackageNames == null) { 573bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn callback.mCallback.opChanged(code, uid, null); 5742af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } else { 5752af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int reportedPackageCount = reportedPackageNames.size(); 5762af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov for (int j = 0; j < reportedPackageCount; j++) { 5772af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov String reportedPackageName = reportedPackageNames.valueAt(j); 578bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn callback.mCallback.opChanged(code, uid, reportedPackageName); 579607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 580607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 5812af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } catch (RemoteException e) { 5822af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov Log.w(TAG, "Error dispatching op op change", e); 583607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 584607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 5852af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } finally { 5862af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov Binder.restoreCallingIdentity(identity); 587607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 588607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 589607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn 59072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn @Override 5915e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn public void setMode(int code, int uid, String packageName, int mode) { 592b64afe17064f126eb782c42a238db65f080fc8f0Dianne Hackborn if (Binder.getCallingPid() != Process.myPid()) { 593b64afe17064f126eb782c42a238db65f080fc8f0Dianne Hackborn mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 594b64afe17064f126eb782c42a238db65f080fc8f0Dianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 595133b9df951c633a1f72b7e12f8aa9ee9d7da9db6Dianne Hackborn } 596961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn verifyIncomingOp(code); 597c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn ArrayList<Callback> repCbs = null; 598c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn code = AppOpsManager.opToSwitch(code); 5995e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn synchronized (this) { 6002af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov UidState uidState = getUidStateLocked(uid, false); 601c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn Op op = getOpLocked(code, uid, packageName, true); 6025e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn if (op != null) { 6035e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn if (op.mode != mode) { 6045e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn op.mode = mode; 605c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn ArrayList<Callback> cbs = mOpModeWatchers.get(code); 606c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn if (cbs != null) { 607c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn if (repCbs == null) { 608c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn repCbs = new ArrayList<Callback>(); 609c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 610c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn repCbs.addAll(cbs); 611c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 612c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn cbs = mPackageModeWatchers.get(packageName); 613c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn if (cbs != null) { 614c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn if (repCbs == null) { 615c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn repCbs = new ArrayList<Callback>(); 616c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 617c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn repCbs.addAll(cbs); 618c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 619f5d831915dd11e77cdcf5669228c55fe17a21c5eDavid Braun if (mode == AppOpsManager.opToDefaultMode(op.op)) { 620514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn // If going into the default mode, prune this op 621514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn // if there is nothing else interesting in it. 622607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn pruneOp(op, uid, packageName); 623514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn } 6247b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn scheduleFastWriteLocked(); 6255e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 6265e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 6275e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 628c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn if (repCbs != null) { 6293853611f77997fd7670163afdc8d9f546dfba566Svet Ganov // There are components watching for mode changes such as window manager 6303853611f77997fd7670163afdc8d9f546dfba566Svet Ganov // and location manager which are in our process. The callbacks in these 6313853611f77997fd7670163afdc8d9f546dfba566Svet Ganov // components may require permissions our remote caller does not have. 6323853611f77997fd7670163afdc8d9f546dfba566Svet Ganov final long identity = Binder.clearCallingIdentity(); 6333853611f77997fd7670163afdc8d9f546dfba566Svet Ganov try { 6343853611f77997fd7670163afdc8d9f546dfba566Svet Ganov for (int i = 0; i < repCbs.size(); i++) { 6353853611f77997fd7670163afdc8d9f546dfba566Svet Ganov try { 636bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn repCbs.get(i).mCallback.opChanged(code, uid, packageName); 6373853611f77997fd7670163afdc8d9f546dfba566Svet Ganov } catch (RemoteException e) { 6383853611f77997fd7670163afdc8d9f546dfba566Svet Ganov } 639c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 6403853611f77997fd7670163afdc8d9f546dfba566Svet Ganov } finally { 6413853611f77997fd7670163afdc8d9f546dfba566Svet Ganov Binder.restoreCallingIdentity(identity); 642c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 643c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 644c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 645c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn 646bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn private static HashMap<Callback, ArrayList<ChangeRec>> addCallbacks( 647bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn HashMap<Callback, ArrayList<ChangeRec>> callbacks, 648bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn int op, int uid, String packageName, ArrayList<Callback> cbs) { 649607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn if (cbs == null) { 650607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn return callbacks; 651607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 652607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn if (callbacks == null) { 653bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn callbacks = new HashMap<>(); 654607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 6552af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov boolean duplicate = false; 656607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn for (int i=0; i<cbs.size(); i++) { 657607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn Callback cb = cbs.get(i); 658bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn ArrayList<ChangeRec> reports = callbacks.get(cb); 659607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn if (reports == null) { 660bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn reports = new ArrayList<>(); 661607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn callbacks.put(cb, reports); 6622af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } else { 6632af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int reportCount = reports.size(); 6642af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov for (int j = 0; j < reportCount; j++) { 665bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn ChangeRec report = reports.get(j); 666bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn if (report.op == op && report.pkg.equals(packageName)) { 6672af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov duplicate = true; 6682af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov break; 6692af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 6702af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 6712af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 6722af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (!duplicate) { 673bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn reports.add(new ChangeRec(op, uid, packageName)); 674607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 675607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 676607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn return callbacks; 677607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 678607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn 679bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn static final class ChangeRec { 680bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn final int op; 681bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn final int uid; 682bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn final String pkg; 683bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn 684bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn ChangeRec(int _op, int _uid, String _pkg) { 685bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn op = _op; 686bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn uid = _uid; 687bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn pkg = _pkg; 688bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn } 689bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn } 690bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn 691607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn @Override 6927b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn public void resetAllModes(int reqUserId, String reqPackageName) { 6937b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn final int callingPid = Binder.getCallingPid(); 6947b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn final int callingUid = Binder.getCallingUid(); 695607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 6967b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn callingPid, callingUid, null); 6977b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn reqUserId = ActivityManager.handleIncomingUser(callingPid, callingUid, reqUserId, 6987b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn true, true, "resetAllModes", null); 6992af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 7002af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov int reqUid = -1; 7012af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (reqPackageName != null) { 7022af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov try { 7032af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov reqUid = AppGlobals.getPackageManager().getPackageUid( 704cd65448ccd13c4c2d0fe9e9623fec3a898ab9372Jeff Sharkey reqPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, reqUserId); 7052af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } catch (RemoteException e) { 7062af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov /* ignore - local call */ 7072af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 7082af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 7092af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 710bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn HashMap<Callback, ArrayList<ChangeRec>> callbacks = null; 711607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn synchronized (this) { 712607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn boolean changed = false; 7132af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov for (int i = mUidStates.size() - 1; i >= 0; i--) { 7142af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov UidState uidState = mUidStates.valueAt(i); 7152af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 7162af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov SparseIntArray opModes = uidState.opModes; 7172af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (opModes != null && (uidState.uid == reqUid || reqUid == -1)) { 7182af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int uidOpCount = opModes.size(); 7192af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov for (int j = uidOpCount - 1; j >= 0; j--) { 7202af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int code = opModes.keyAt(j); 7212af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (AppOpsManager.opAllowsReset(code)) { 7222af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov opModes.removeAt(j); 7232af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (opModes.size() <= 0) { 7242af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState.opModes = null; 7252af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 7262af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov for (String packageName : getPackagesForUid(uidState.uid)) { 727bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn callbacks = addCallbacks(callbacks, code, uidState.uid, packageName, 7282af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov mOpModeWatchers.get(code)); 729bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn callbacks = addCallbacks(callbacks, code, uidState.uid, packageName, 7302af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov mPackageModeWatchers.get(packageName)); 7312af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 7322af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 7332af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 7342af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 7352af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 7362af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidState.pkgOps == null) { 7372af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov continue; 7382af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 7392af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 7407b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn if (reqUserId != UserHandle.USER_ALL 7412af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov && reqUserId != UserHandle.getUserId(uidState.uid)) { 742d6a98979b5d45fff1fa842932274517e999a59c2Alexandra Gherghina // Skip any ops for a different user 743d6a98979b5d45fff1fa842932274517e999a59c2Alexandra Gherghina continue; 744d6a98979b5d45fff1fa842932274517e999a59c2Alexandra Gherghina } 7452af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 7462af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov Map<String, Ops> packages = uidState.pkgOps; 7477f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn Iterator<Map.Entry<String, Ops>> it = packages.entrySet().iterator(); 7487f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn while (it.hasNext()) { 7497f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn Map.Entry<String, Ops> ent = it.next(); 750607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn String packageName = ent.getKey(); 7517b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn if (reqPackageName != null && !reqPackageName.equals(packageName)) { 7527b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn // Skip any ops for a different package 7537b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn continue; 7547b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn } 755607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn Ops pkgOps = ent.getValue(); 7567f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn for (int j=pkgOps.size()-1; j>=0; j--) { 757607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn Op curOp = pkgOps.valueAt(j); 7588828d3a153e28fe631edcd5145e6cc706e0b34c8Dianne Hackborn if (AppOpsManager.opAllowsReset(curOp.op) 7598828d3a153e28fe631edcd5145e6cc706e0b34c8Dianne Hackborn && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) { 760f5d831915dd11e77cdcf5669228c55fe17a21c5eDavid Braun curOp.mode = AppOpsManager.opToDefaultMode(curOp.op); 761607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn changed = true; 762bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn callbacks = addCallbacks(callbacks, curOp.op, curOp.uid, packageName, 763607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn mOpModeWatchers.get(curOp.op)); 764bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn callbacks = addCallbacks(callbacks, curOp.op, curOp.uid, packageName, 765607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn mPackageModeWatchers.get(packageName)); 7667f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn if (curOp.time == 0 && curOp.rejectTime == 0) { 7677f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn pkgOps.removeAt(j); 7687f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn } 769607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 770607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 7717f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn if (pkgOps.size() == 0) { 7727f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn it.remove(); 7737f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn } 7747f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn } 7752af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidState.isDefault()) { 7762af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov mUidStates.remove(uidState.uid); 777607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 778607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 7792af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 780607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn if (changed) { 7817b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn scheduleFastWriteLocked(); 782607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 783607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 784607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn if (callbacks != null) { 785bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn for (Map.Entry<Callback, ArrayList<ChangeRec>> ent : callbacks.entrySet()) { 786607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn Callback cb = ent.getKey(); 787bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn ArrayList<ChangeRec> reports = ent.getValue(); 788607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn for (int i=0; i<reports.size(); i++) { 789bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn ChangeRec rep = reports.get(i); 790607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn try { 791bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn cb.mCallback.opChanged(rep.op, rep.uid, rep.pkg); 792607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } catch (RemoteException e) { 793607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 794607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 795607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 796607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 797607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn } 798607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn 799c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn @Override 800c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) { 8018de5971ac68fdae1a418ed6cd95d276b98b21996Svetoslav Ganov if (callback == null) { 8028de5971ac68fdae1a418ed6cd95d276b98b21996Svetoslav Ganov return; 8038de5971ac68fdae1a418ed6cd95d276b98b21996Svetoslav Ganov } 804c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn synchronized (this) { 8052af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov op = (op != AppOpsManager.OP_NONE) ? AppOpsManager.opToSwitch(op) : op; 806c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn Callback cb = mModeWatchers.get(callback.asBinder()); 807c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn if (cb == null) { 808c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn cb = new Callback(callback); 809c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn mModeWatchers.put(callback.asBinder(), cb); 810c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 811c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn if (op != AppOpsManager.OP_NONE) { 812c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn ArrayList<Callback> cbs = mOpModeWatchers.get(op); 813c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn if (cbs == null) { 814c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn cbs = new ArrayList<Callback>(); 815c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn mOpModeWatchers.put(op, cbs); 816c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 817c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn cbs.add(cb); 818c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 819c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn if (packageName != null) { 820c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn ArrayList<Callback> cbs = mPackageModeWatchers.get(packageName); 821c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn if (cbs == null) { 822c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn cbs = new ArrayList<Callback>(); 823c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn mPackageModeWatchers.put(packageName, cbs); 824c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 825c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn cbs.add(cb); 826c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 827c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 828c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 829c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn 830c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn @Override 831c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn public void stopWatchingMode(IAppOpsCallback callback) { 8328de5971ac68fdae1a418ed6cd95d276b98b21996Svetoslav Ganov if (callback == null) { 8338de5971ac68fdae1a418ed6cd95d276b98b21996Svetoslav Ganov return; 8348de5971ac68fdae1a418ed6cd95d276b98b21996Svetoslav Ganov } 835c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn synchronized (this) { 836c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn Callback cb = mModeWatchers.remove(callback.asBinder()); 837c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn if (cb != null) { 838c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn cb.unlinkToDeath(); 839e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn for (int i=mOpModeWatchers.size()-1; i>=0; i--) { 840c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn ArrayList<Callback> cbs = mOpModeWatchers.valueAt(i); 841c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn cbs.remove(cb); 842c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn if (cbs.size() <= 0) { 843c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn mOpModeWatchers.removeAt(i); 844c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 845c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 846e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn for (int i=mPackageModeWatchers.size()-1; i>=0; i--) { 847e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn ArrayList<Callback> cbs = mPackageModeWatchers.valueAt(i); 848e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn cbs.remove(cb); 849e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn if (cbs.size() <= 0) { 850e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn mPackageModeWatchers.removeAt(i); 851c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 852c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 853c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 854c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn } 8555e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 8565e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn 8575e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn @Override 858e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn public IBinder getToken(IBinder clientToken) { 859e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn synchronized (this) { 860e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn ClientState cs = mClients.get(clientToken); 861e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn if (cs == null) { 862e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn cs = new ClientState(clientToken); 863e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn mClients.put(clientToken, cs); 864e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 865e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn return cs; 866e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 867e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 868e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn 869e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn @Override 87035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public int checkOperation(int code, int uid, String packageName) { 871f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn verifyIncomingUid(uid); 872961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn verifyIncomingOp(code); 873f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov String resolvedPackageName = resolvePackageName(uid, packageName); 874f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov if (resolvedPackageName == null) { 875f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov return AppOpsManager.MODE_IGNORED; 876f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov } 877a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (this) { 878f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov if (isOpRestricted(uid, code, resolvedPackageName)) { 87962062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk return AppOpsManager.MODE_IGNORED; 88062062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk } 8812af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov code = AppOpsManager.opToSwitch(code); 8822af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov UidState uidState = getUidStateLocked(uid, false); 8832af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidState != null && uidState.opModes != null) { 8842af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int uidMode = uidState.opModes.get(code); 8852af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidMode != AppOpsManager.MODE_ALLOWED) { 8862af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov return uidMode; 8872af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 8882af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 889f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov Op op = getOpLocked(code, uid, resolvedPackageName, false); 890a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (op == null) { 891f5d831915dd11e77cdcf5669228c55fe17a21c5eDavid Braun return AppOpsManager.opToDefaultMode(code); 892a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 8935e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn return op.mode; 894a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 895a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 896a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 897a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn @Override 8987b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock public int checkAudioOperation(int code, int usage, int uid, String packageName) { 899efc4a344a173ae20ec72b8c05c45b794687fda87Andrei Stingaceanu boolean suspended; 900efc4a344a173ae20ec72b8c05c45b794687fda87Andrei Stingaceanu try { 901efc4a344a173ae20ec72b8c05c45b794687fda87Andrei Stingaceanu suspended = isPackageSuspendedForUser(packageName, uid); 902efc4a344a173ae20ec72b8c05c45b794687fda87Andrei Stingaceanu } catch (IllegalArgumentException ex) { 903efc4a344a173ae20ec72b8c05c45b794687fda87Andrei Stingaceanu // Package not found. 904efc4a344a173ae20ec72b8c05c45b794687fda87Andrei Stingaceanu suspended = false; 905efc4a344a173ae20ec72b8c05c45b794687fda87Andrei Stingaceanu } 906efc4a344a173ae20ec72b8c05c45b794687fda87Andrei Stingaceanu 907efc4a344a173ae20ec72b8c05c45b794687fda87Andrei Stingaceanu if (suspended) { 9082bc2febd56b12131e7a5e5b1ad49d62b3092ec17Andrei Stingaceanu Log.i(TAG, "Audio disabled for suspended package=" + packageName + " for uid=" + uid); 9092bc2febd56b12131e7a5e5b1ad49d62b3092ec17Andrei Stingaceanu return AppOpsManager.MODE_IGNORED; 9102bc2febd56b12131e7a5e5b1ad49d62b3092ec17Andrei Stingaceanu } 9112bc2febd56b12131e7a5e5b1ad49d62b3092ec17Andrei Stingaceanu 9121af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock synchronized (this) { 9137b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock final int mode = checkRestrictionLocked(code, usage, uid, packageName); 9141af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock if (mode != AppOpsManager.MODE_ALLOWED) { 9151af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock return mode; 9161af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 9171af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 9181af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock return checkOperation(code, uid, packageName); 9191af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 9201af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock 921355b232d7998cfc9b29d42a0356390e25191bcbdAndrei Stingaceanu private boolean isPackageSuspendedForUser(String pkg, int uid) { 9222bc2febd56b12131e7a5e5b1ad49d62b3092ec17Andrei Stingaceanu try { 923355b232d7998cfc9b29d42a0356390e25191bcbdAndrei Stingaceanu return AppGlobals.getPackageManager().isPackageSuspendedForUser( 924355b232d7998cfc9b29d42a0356390e25191bcbdAndrei Stingaceanu pkg, UserHandle.getUserId(uid)); 9252bc2febd56b12131e7a5e5b1ad49d62b3092ec17Andrei Stingaceanu } catch (RemoteException re) { 9262bc2febd56b12131e7a5e5b1ad49d62b3092ec17Andrei Stingaceanu throw new SecurityException("Could not talk to package manager service"); 9272bc2febd56b12131e7a5e5b1ad49d62b3092ec17Andrei Stingaceanu } 9282bc2febd56b12131e7a5e5b1ad49d62b3092ec17Andrei Stingaceanu } 9292bc2febd56b12131e7a5e5b1ad49d62b3092ec17Andrei Stingaceanu 9307b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock private int checkRestrictionLocked(int code, int usage, int uid, String packageName) { 9317b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock final SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code); 9327b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock if (usageRestrictions != null) { 9337b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock final Restriction r = usageRestrictions.get(usage); 9341af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock if (r != null && !r.exceptionPackages.contains(packageName)) { 9351af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock return r.mode; 9361af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 9371af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 9381af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock return AppOpsManager.MODE_ALLOWED; 9391af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 9401af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock 9411af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock @Override 9427b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock public void setAudioRestriction(int code, int usage, int uid, int mode, 9431af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock String[] exceptionPackages) { 9441af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock verifyIncomingUid(uid); 9451af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock verifyIncomingOp(code); 9461af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock synchronized (this) { 9477b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code); 9487b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock if (usageRestrictions == null) { 9497b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock usageRestrictions = new SparseArray<Restriction>(); 9507b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock mAudioRestrictions.put(code, usageRestrictions); 9511af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 9527b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock usageRestrictions.remove(usage); 9531af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock if (mode != AppOpsManager.MODE_ALLOWED) { 9541af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock final Restriction r = new Restriction(); 9551af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock r.mode = mode; 9561af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock if (exceptionPackages != null) { 9571af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock final int N = exceptionPackages.length; 9581af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock r.exceptionPackages = new ArraySet<String>(N); 9591af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock for (int i = 0; i < N; i++) { 9601af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock final String pkg = exceptionPackages[i]; 9611af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock if (pkg != null) { 9621af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock r.exceptionPackages.add(pkg.trim()); 9631af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 9641af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 9651af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 9667b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock usageRestrictions.put(usage, r); 9671af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 9681af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 969bb21c25b3f927eeb1a1e56fa3023093f0d74204cJulia Reynolds notifyWatchersOfChange(code); 9701af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 9711af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock 9721af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock @Override 973911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey public int checkPackage(int uid, String packageName) { 974f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov Preconditions.checkNotNull(packageName); 975911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey synchronized (this) { 9760fcef84cca23724c13ecfe775b90dec3614cc3e3Dianne Hackborn if (getOpsRawLocked(uid, packageName, true) != null) { 977911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey return AppOpsManager.MODE_ALLOWED; 978911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey } else { 979911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey return AppOpsManager.MODE_ERRORED; 980911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey } 981911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey } 982911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey } 983911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey 984911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey @Override 98599b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov public int noteProxyOperation(int code, String proxyPackageName, 98699b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov int proxiedUid, String proxiedPackageName) { 98799b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov verifyIncomingOp(code); 988f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov final int proxyUid = Binder.getCallingUid(); 989f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName); 990f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov if (resolveProxyPackageName == null) { 991f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov return AppOpsManager.MODE_IGNORED; 992f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov } 993f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov final int proxyMode = noteOperationUnchecked(code, proxyUid, 994f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov resolveProxyPackageName, -1, null); 99599b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) { 99699b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov return proxyMode; 99799b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov } 998f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov String resolveProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName); 999f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov if (resolveProxiedPackageName == null) { 1000f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov return AppOpsManager.MODE_IGNORED; 1001f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov } 1002f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName, 1003f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov proxyMode, resolveProxyPackageName); 100499b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov } 100599b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov 100699b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov @Override 100735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public int noteOperation(int code, int uid, String packageName) { 1008f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn verifyIncomingUid(uid); 1009961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn verifyIncomingOp(code); 1010f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov String resolvedPackageName = resolvePackageName(uid, packageName); 1011f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov if (resolvedPackageName == null) { 1012f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov return AppOpsManager.MODE_IGNORED; 1013f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov } 1014f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov return noteOperationUnchecked(code, uid, resolvedPackageName, 0, null); 101599b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov } 101699b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov 101799b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov private int noteOperationUnchecked(int code, int uid, String packageName, 101899b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov int proxyUid, String proxyPackageName) { 1019a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (this) { 1020f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov Ops ops = getOpsRawLocked(uid, packageName, true); 1021f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (ops == null) { 10225e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid 10235e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn + " package " + packageName); 1024911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey return AppOpsManager.MODE_ERRORED; 1025a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 1026f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn Op op = getOpLocked(ops, code, true); 10271c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk if (isOpRestricted(uid, code, packageName)) { 102862062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk return AppOpsManager.MODE_IGNORED; 102962062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk } 103035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (op.duration == -1) { 103135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName 1032a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn + " code " + code + " time=" + op.time + " duration=" + op.duration); 1033a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 103435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.duration = 0; 1035f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn final int switchCode = AppOpsManager.opToSwitch(code); 10362af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov UidState uidState = ops.uidState; 10371984bba8c80d9b9abb73836f7824428807d34a50Svetoslav Ganov // If there is a non-default per UID policy (we set UID op mode only if 10381984bba8c80d9b9abb73836f7824428807d34a50Svetoslav Ganov // non-default) it takes over, otherwise use the per package policy. 10391984bba8c80d9b9abb73836f7824428807d34a50Svetoslav Ganov if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) { 10402af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int uidMode = uidState.opModes.get(switchCode); 10412af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidMode != AppOpsManager.MODE_ALLOWED) { 10422af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code " 10432af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov + switchCode + " (" + code + ") uid " + uid + " package " 10442af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov + packageName); 10452af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov op.rejectTime = System.currentTimeMillis(); 10462af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov return uidMode; 10472af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 10481984bba8c80d9b9abb73836f7824428807d34a50Svetoslav Ganov } else { 10491984bba8c80d9b9abb73836f7824428807d34a50Svetoslav Ganov final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op; 10501984bba8c80d9b9abb73836f7824428807d34a50Svetoslav Ganov if (switchOp.mode != AppOpsManager.MODE_ALLOWED) { 10511984bba8c80d9b9abb73836f7824428807d34a50Svetoslav Ganov if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code " 10521984bba8c80d9b9abb73836f7824428807d34a50Svetoslav Ganov + switchCode + " (" + code + ") uid " + uid + " package " 10531984bba8c80d9b9abb73836f7824428807d34a50Svetoslav Ganov + packageName); 10541984bba8c80d9b9abb73836f7824428807d34a50Svetoslav Ganov op.rejectTime = System.currentTimeMillis(); 10551984bba8c80d9b9abb73836f7824428807d34a50Svetoslav Ganov return switchOp.mode; 10561984bba8c80d9b9abb73836f7824428807d34a50Svetoslav Ganov } 10575e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 10585e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn if (DEBUG) Log.d(TAG, "noteOperation: allowing code " + code + " uid " + uid 10595e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn + " package " + packageName); 10605e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn op.time = System.currentTimeMillis(); 1061514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn op.rejectTime = 0; 106299b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov op.proxyUid = proxyUid; 106399b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov op.proxyPackageName = proxyPackageName; 10645e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn return AppOpsManager.MODE_ALLOWED; 1065a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 1066a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 1067a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 1068a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn @Override 1069e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn public int startOperation(IBinder token, int code, int uid, String packageName) { 1070f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn verifyIncomingUid(uid); 1071961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn verifyIncomingOp(code); 1072f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov String resolvedPackageName = resolvePackageName(uid, packageName); 1073f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov if (resolvedPackageName == null) { 1074f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov return AppOpsManager.MODE_IGNORED; 1075f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov } 1076e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn ClientState client = (ClientState)token; 1077a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (this) { 1078f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov Ops ops = getOpsRawLocked(uid, resolvedPackageName, true); 1079f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (ops == null) { 10805e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid 1081f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov + " package " + resolvedPackageName); 1082911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey return AppOpsManager.MODE_ERRORED; 1083a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 1084f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn Op op = getOpLocked(ops, code, true); 1085f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov if (isOpRestricted(uid, code, resolvedPackageName)) { 108662062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk return AppOpsManager.MODE_IGNORED; 108762062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk } 1088f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn final int switchCode = AppOpsManager.opToSwitch(code); 10892af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov UidState uidState = ops.uidState; 10902af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidState.opModes != null) { 10912af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int uidMode = uidState.opModes.get(switchCode); 10922af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidMode != AppOpsManager.MODE_ALLOWED) { 10932af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code " 10942af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov + switchCode + " (" + code + ") uid " + uid + " package " 1095f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov + resolvedPackageName); 10962af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov op.rejectTime = System.currentTimeMillis(); 10972af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov return uidMode; 10982af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 10992af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 1100f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op; 1101f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (switchOp.mode != AppOpsManager.MODE_ALLOWED) { 1102f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code " 1103f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov + switchCode + " (" + code + ") uid " + uid + " package " 1104f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov + resolvedPackageName); 11055e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn op.rejectTime = System.currentTimeMillis(); 1106f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return switchOp.mode; 11075e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 11085e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid 1109f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov + " package " + resolvedPackageName); 111035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (op.nesting == 0) { 111135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.time = System.currentTimeMillis(); 1112514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn op.rejectTime = 0; 111335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.duration = -1; 1114a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 111535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.nesting++; 1116e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn if (client.mStartedOps != null) { 1117e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn client.mStartedOps.add(op); 1118e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 11195e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn return AppOpsManager.MODE_ALLOWED; 1120a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 1121a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 1122a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 1123a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn @Override 1124e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn public void finishOperation(IBinder token, int code, int uid, String packageName) { 1125f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn verifyIncomingUid(uid); 1126961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn verifyIncomingOp(code); 1127f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov String resolvedPackageName = resolvePackageName(uid, packageName); 1128f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov if (resolvedPackageName == null) { 1129f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov return; 1130f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov } 1131f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov if (!(token instanceof ClientState)) { 1132f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov return; 1133f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov } 1134f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov ClientState client = (ClientState) token; 1135a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (this) { 1136f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov Op op = getOpLocked(code, uid, resolvedPackageName, true); 1137a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (op == null) { 1138a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return; 1139a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 1140e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn if (client.mStartedOps != null) { 1141e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn if (!client.mStartedOps.remove(op)) { 1142e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn throw new IllegalStateException("Operation not started: uid" + op.uid 1143e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn + " pkg=" + op.packageName + " op=" + op.op); 114435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 1145e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 1146e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn finishOperationLocked(op); 1147e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 1148e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 1149e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn 1150b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganov @Override 1151b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganov public int permissionToOpCode(String permission) { 1152f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov if (permission == null) { 1153f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov return AppOpsManager.OP_NONE; 1154f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov } 1155b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganov return AppOpsManager.permissionToOpCode(permission); 1156b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganov } 1157b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganov 1158e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn void finishOperationLocked(Op op) { 1159e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn if (op.nesting <= 1) { 1160e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn if (op.nesting == 1) { 1161e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn op.duration = (int)(System.currentTimeMillis() - op.time); 1162e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn op.time += op.duration; 116335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } else { 1164e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn Slog.w(TAG, "Finishing op nesting under-run: uid " + op.uid + " pkg " 1165e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn + op.packageName + " code " + op.op + " time=" + op.time 1166e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn + " duration=" + op.duration + " nesting=" + op.nesting); 1167a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 1168e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn op.nesting = 0; 1169e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } else { 1170e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn op.nesting--; 1171a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 1172a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 1173a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 1174f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn private void verifyIncomingUid(int uid) { 1175a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (uid == Binder.getCallingUid()) { 1176f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return; 1177a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 1178a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (Binder.getCallingPid() == Process.myPid()) { 1179f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return; 1180a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 1181a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 1182a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 1183a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 1184a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 1185961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn private void verifyIncomingOp(int op) { 1186961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn if (op >= 0 && op < AppOpsManager._NUM_OP) { 1187961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn return; 1188961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn } 1189961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn throw new IllegalArgumentException("Bad operation #" + op); 1190961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn } 1191961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn 11922af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov private UidState getUidStateLocked(int uid, boolean edit) { 11932af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov UidState uidState = mUidStates.get(uid); 11942af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidState == null) { 11952af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (!edit) { 11962af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov return null; 11972af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 11982af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState = new UidState(uid); 11992af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov mUidStates.put(uid, uidState); 12002af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 12012af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov return uidState; 12022af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 12032af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 12040fcef84cca23724c13ecfe775b90dec3614cc3e3Dianne Hackborn private Ops getOpsRawLocked(int uid, String packageName, boolean edit) { 12052af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov UidState uidState = getUidStateLocked(uid, edit); 12062af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidState == null) { 12072af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov return null; 12082af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 12092af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 12102af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidState.pkgOps == null) { 121135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (!edit) { 121235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return null; 121335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 12142af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState.pkgOps = new ArrayMap<>(); 1215a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 12162af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 12172af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov Ops ops = uidState.pkgOps.get(packageName); 1218a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (ops == null) { 121935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (!edit) { 122035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return null; 122135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 12221c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk boolean isPrivileged = false; 1223a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn // This is the first time we have seen this package name under this uid, 1224a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn // so let's make sure it is valid. 1225514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn if (uid != 0) { 1226514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 1227a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 1228514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn int pkgUid = -1; 1229514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn try { 12301c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk ApplicationInfo appInfo = ActivityThread.getPackageManager() 1231cd65448ccd13c4c2d0fe9e9623fec3a898ab9372Jeff Sharkey .getApplicationInfo(packageName, 1232cd65448ccd13c4c2d0fe9e9623fec3a898ab9372Jeff Sharkey PackageManager.MATCH_DEBUG_TRIAGED_MISSING, 1233cd65448ccd13c4c2d0fe9e9623fec3a898ab9372Jeff Sharkey UserHandle.getUserId(uid)); 12341c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk if (appInfo != null) { 12351c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk pkgUid = appInfo.uid; 1236b9f8a5204a1b0b3919fa921e858d04124c582828Alex Klyubin isPrivileged = (appInfo.privateFlags 1237b9f8a5204a1b0b3919fa921e858d04124c582828Alex Klyubin & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; 12381c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk } else { 12391c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk if ("media".equals(packageName)) { 12401c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk pkgUid = Process.MEDIA_UID; 12411c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk isPrivileged = false; 1242ed0ea40a41aae8e65bc189efe6b631ca78259383Andy Hung } else if ("audioserver".equals(packageName)) { 1243ed0ea40a41aae8e65bc189efe6b631ca78259383Andy Hung pkgUid = Process.AUDIOSERVER_UID; 1244ed0ea40a41aae8e65bc189efe6b631ca78259383Andy Hung isPrivileged = false; 124575cade0a5fd5ec432870de9977f81091ab389423Chien-Yu Chen } else if ("cameraserver".equals(packageName)) { 124675cade0a5fd5ec432870de9977f81091ab389423Chien-Yu Chen pkgUid = Process.CAMERASERVER_UID; 124775cade0a5fd5ec432870de9977f81091ab389423Chien-Yu Chen isPrivileged = false; 12481c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk } 1249713df150b92a0a5eea877f99405e31eefbf93a09Dianne Hackborn } 12501c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk } catch (RemoteException e) { 12511c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk Slog.w(TAG, "Could not contact PackageManager", e); 1252514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn } 1253514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn if (pkgUid != uid) { 1254514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn // Oops! The package name is not valid for the uid they are calling 1255514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn // under. Abort. 1256bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn RuntimeException ex = new RuntimeException("here"); 1257bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn ex.fillInStackTrace(); 1258514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn Slog.w(TAG, "Bad call: specified package " + packageName 1259bef28feba57be7fd6a4d14a85a8229154338b2edDianne Hackborn + " under uid " + uid + " but it is really " + pkgUid, ex); 1260514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn return null; 1261514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn } 1262514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn } finally { 1263514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn Binder.restoreCallingIdentity(ident); 1264002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn } 1265a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 12662af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov ops = new Ops(packageName, uidState, isPrivileged); 12672af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState.pkgOps.put(packageName, ops); 1268a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 126972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn return ops; 127072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 127172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn 12725e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn private void scheduleWriteLocked() { 12735e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn if (!mWriteScheduled) { 12745e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn mWriteScheduled = true; 12755e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn mHandler.postDelayed(mWriteRunner, WRITE_DELAY); 12765e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 12775e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 12785e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn 12797b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn private void scheduleFastWriteLocked() { 12807b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn if (!mFastWriteScheduled) { 12815e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn mWriteScheduled = true; 12827b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn mFastWriteScheduled = true; 12837b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn mHandler.removeCallbacks(mWriteRunner); 12847b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn mHandler.postDelayed(mWriteRunner, 10*1000); 12855e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 12865e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 12875e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn 128872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn private Op getOpLocked(int code, int uid, String packageName, boolean edit) { 1289f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov Ops ops = getOpsRawLocked(uid, packageName, edit); 129072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn if (ops == null) { 129172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn return null; 129272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 1293f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return getOpLocked(ops, code, edit); 1294f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 1295f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn 1296f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn private Op getOpLocked(Ops ops, int code, boolean edit) { 1297a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Op op = ops.get(code); 1298a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (op == null) { 129935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (!edit) { 130035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return null; 130135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 13022af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov op = new Op(ops.uidState.uid, ops.packageName, code); 1303a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn ops.put(code, op); 1304a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 13055e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn if (edit) { 13065e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn scheduleWriteLocked(); 130735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 1308a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return op; 1309a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 1310a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 13111c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk private boolean isOpRestricted(int uid, int code, String packageName) { 131262062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk int userHandle = UserHandle.getUserId(uid); 13139cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov final int restrictionSetCount = mOpUserRestrictions.size(); 131429931bc684bde6b430923122777684178ee2681cRuben Brunk 13159cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov for (int i = 0; i < restrictionSetCount; i++) { 131629931bc684bde6b430923122777684178ee2681cRuben Brunk // For each client, check that the given op is not restricted, or that the given 131729931bc684bde6b430923122777684178ee2681cRuben Brunk // package is exempt from the restriction. 1318a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov ClientRestrictionState restrictionState = mOpUserRestrictions.valueAt(i); 1319ffddadb04a8df12f05f42721cc59e242e78c2a64Suprabh Shukla if (restrictionState.hasRestriction(code, packageName, userHandle)) { 1320ffddadb04a8df12f05f42721cc59e242e78c2a64Suprabh Shukla if (AppOpsManager.opAllowSystemBypassRestriction(code)) { 1321ffddadb04a8df12f05f42721cc59e242e78c2a64Suprabh Shukla // If we are the system, bypass user restrictions for certain codes 1322ffddadb04a8df12f05f42721cc59e242e78c2a64Suprabh Shukla synchronized (this) { 1323ffddadb04a8df12f05f42721cc59e242e78c2a64Suprabh Shukla Ops ops = getOpsRawLocked(uid, packageName, true); 1324ffddadb04a8df12f05f42721cc59e242e78c2a64Suprabh Shukla if ((ops != null) && ops.isPrivileged) { 1325ffddadb04a8df12f05f42721cc59e242e78c2a64Suprabh Shukla return false; 1326ffddadb04a8df12f05f42721cc59e242e78c2a64Suprabh Shukla } 13271c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk } 13281c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk } 13299cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov return true; 13301c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk } 133162062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk } 133262062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk return false; 133362062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk } 133462062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk 133535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn void readState() { 133635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn synchronized (mFile) { 133735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn synchronized (this) { 133835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn FileInputStream stream; 133935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn try { 134035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn stream = mFile.openRead(); 134135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (FileNotFoundException e) { 134235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty"); 134335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return; 134435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 134535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn boolean success = false; 13464d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn mUidStates.clear(); 134735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn try { 134835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlPullParser parser = Xml.newPullParser(); 13499e9e2e73c6ec7bece20268196dc89ad0c8bafad4Wojciech Staszkiewicz parser.setInput(stream, StandardCharsets.UTF_8.name()); 135035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int type; 135135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn while ((type = parser.next()) != XmlPullParser.START_TAG 135235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn && type != XmlPullParser.END_DOCUMENT) { 135335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn ; 135435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 135535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 135635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (type != XmlPullParser.START_TAG) { 135735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn throw new IllegalStateException("no start tag found"); 135835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 135935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 136035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int outerDepth = parser.getDepth(); 136135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 136235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 136335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 136435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn continue; 136535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 136635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 136735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn String tagName = parser.getName(); 136835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (tagName.equals("pkg")) { 13690997c5bd79d11e6ecb11970bfd9b9b911001ac0aDave Burke readPackage(parser); 1370215b44a1c2c883e628e1ab5b945a1a4aa04ee392Svetoslav } else if (tagName.equals("uid")) { 13712af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov readUidOps(parser); 137235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } else { 137335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Unknown element under <app-ops>: " 137435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn + parser.getName()); 137535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlUtils.skipCurrentTag(parser); 137635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 137735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 137835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn success = true; 137935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (IllegalStateException e) { 138035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed parsing " + e); 138135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (NullPointerException e) { 138235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed parsing " + e); 138335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (NumberFormatException e) { 138435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed parsing " + e); 138535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (XmlPullParserException e) { 138635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed parsing " + e); 138735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (IOException e) { 138835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed parsing " + e); 138935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (IndexOutOfBoundsException e) { 139035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed parsing " + e); 139135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } finally { 139235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (!success) { 13932af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov mUidStates.clear(); 139435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 139535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn try { 139635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn stream.close(); 139735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (IOException e) { 139835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 139935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 140035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 140135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 140235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 140335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 14042af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov void readUidOps(XmlPullParser parser) throws NumberFormatException, 14052af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov XmlPullParserException, IOException { 14062af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int uid = Integer.parseInt(parser.getAttributeValue(null, "n")); 14072af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov int outerDepth = parser.getDepth(); 14082af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov int type; 14092af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 14102af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 14112af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 14122af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov continue; 14132af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 14142af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 14152af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov String tagName = parser.getName(); 14162af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (tagName.equals("op")) { 14172af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int code = Integer.parseInt(parser.getAttributeValue(null, "n")); 14182af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int mode = Integer.parseInt(parser.getAttributeValue(null, "m")); 14192af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov UidState uidState = getUidStateLocked(uid, true); 14202af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidState.opModes == null) { 14212af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState.opModes = new SparseIntArray(); 14222af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 14232af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState.opModes.put(code, mode); 14242af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } else { 14252af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov Slog.w(TAG, "Unknown element under <uid-ops>: " 14262af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov + parser.getName()); 14272af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov XmlUtils.skipCurrentTag(parser); 14282af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 14292af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 14302af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 14312af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 14320997c5bd79d11e6ecb11970bfd9b9b911001ac0aDave Burke void readPackage(XmlPullParser parser) throws NumberFormatException, 143335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlPullParserException, IOException { 143435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn String pkgName = parser.getAttributeValue(null, "n"); 143535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int outerDepth = parser.getDepth(); 143635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int type; 143735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 143835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 143935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 144035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn continue; 144135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 144235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 144335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn String tagName = parser.getName(); 144435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (tagName.equals("uid")) { 14450997c5bd79d11e6ecb11970bfd9b9b911001ac0aDave Burke readUid(parser, pkgName); 144635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } else { 144735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Unknown element under <pkg>: " 144835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn + parser.getName()); 144935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlUtils.skipCurrentTag(parser); 145035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 145135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 145235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 145335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 14540997c5bd79d11e6ecb11970bfd9b9b911001ac0aDave Burke void readUid(XmlPullParser parser, String pkgName) throws NumberFormatException, 145535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlPullParserException, IOException { 145635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int uid = Integer.parseInt(parser.getAttributeValue(null, "n")); 14571c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk String isPrivilegedString = parser.getAttributeValue(null, "p"); 14581c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk boolean isPrivileged = false; 14591c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk if (isPrivilegedString == null) { 14601c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk try { 14611c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk IPackageManager packageManager = ActivityThread.getPackageManager(); 14621c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk if (packageManager != null) { 14631c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk ApplicationInfo appInfo = ActivityThread.getPackageManager() 14641c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk .getApplicationInfo(pkgName, 0, UserHandle.getUserId(uid)); 14651c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk if (appInfo != null) { 1466b9f8a5204a1b0b3919fa921e858d04124c582828Alex Klyubin isPrivileged = (appInfo.privateFlags 1467b9f8a5204a1b0b3919fa921e858d04124c582828Alex Klyubin & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; 14681c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk } 14691c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk } else { 14701c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk // Could not load data, don't add to cache so it will be loaded later. 14711c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk return; 14721c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk } 14731c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk } catch (RemoteException e) { 14741c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk Slog.w(TAG, "Could not contact PackageManager", e); 14751c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk } 14761c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk } else { 14771c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk isPrivileged = Boolean.parseBoolean(isPrivilegedString); 14781c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk } 147935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int outerDepth = parser.getDepth(); 148035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int type; 148135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 148235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 148335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 148435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn continue; 148535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 148635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 148735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn String tagName = parser.getName(); 148835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (tagName.equals("op")) { 1489e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn Op op = new Op(uid, pkgName, Integer.parseInt(parser.getAttributeValue(null, "n"))); 14905e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn String mode = parser.getAttributeValue(null, "m"); 14915e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn if (mode != null) { 14920997c5bd79d11e6ecb11970bfd9b9b911001ac0aDave Burke op.mode = Integer.parseInt(mode); 14935e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 14945e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn String time = parser.getAttributeValue(null, "t"); 14955e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn if (time != null) { 14965e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn op.time = Long.parseLong(time); 14975e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 14985e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn time = parser.getAttributeValue(null, "r"); 14995e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn if (time != null) { 15005e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn op.rejectTime = Long.parseLong(time); 15015e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 15025e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn String dur = parser.getAttributeValue(null, "d"); 15035e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn if (dur != null) { 15045e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn op.duration = Integer.parseInt(dur); 15055e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 150699b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov String proxyUid = parser.getAttributeValue(null, "pu"); 150799b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov if (proxyUid != null) { 150899b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov op.proxyUid = Integer.parseInt(proxyUid); 150999b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov } 151099b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov String proxyPackageName = parser.getAttributeValue(null, "pp"); 151199b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov if (proxyPackageName != null) { 151299b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov op.proxyPackageName = proxyPackageName; 151399b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov } 15142af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 15152af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov UidState uidState = getUidStateLocked(uid, true); 15162af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidState.pkgOps == null) { 15172af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState.pkgOps = new ArrayMap<>(); 151835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 15192af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 15202af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov Ops ops = uidState.pkgOps.get(pkgName); 152135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (ops == null) { 15222af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov ops = new Ops(pkgName, uidState, isPrivileged); 15232af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov uidState.pkgOps.put(pkgName, ops); 152435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 152535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn ops.put(op.op, op); 152635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } else { 152735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Unknown element under <pkg>: " 152835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn + parser.getName()); 152935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlUtils.skipCurrentTag(parser); 153035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 153135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 153235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 153335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 153435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn void writeState() { 153535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn synchronized (mFile) { 153635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null); 153735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 153835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn FileOutputStream stream; 153935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn try { 154035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn stream = mFile.startWrite(); 154135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (IOException e) { 154235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed to write state: " + e); 154335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return; 154435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 154535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 154635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn try { 154735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlSerializer out = new FastXmlSerializer(); 15489e9e2e73c6ec7bece20268196dc89ad0c8bafad4Wojciech Staszkiewicz out.setOutput(stream, StandardCharsets.UTF_8.name()); 154935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.startDocument(null, true); 15504d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn out.startTag(null, "app-ops"); 15512af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 15522af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int uidStateCount = mUidStates.size(); 15532af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov for (int i = 0; i < uidStateCount; i++) { 15542af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov UidState uidState = mUidStates.valueAt(i); 15552af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (uidState.opModes != null && uidState.opModes.size() > 0) { 15562af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov out.startTag(null, "uid"); 15572af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov out.attribute(null, "n", Integer.toString(uidState.uid)); 15582af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov SparseIntArray uidOpModes = uidState.opModes; 15592af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int opCount = uidOpModes.size(); 15602af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov for (int j = 0; j < opCount; j++) { 15612af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int op = uidOpModes.keyAt(j); 15622af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int mode = uidOpModes.valueAt(j); 15632af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov out.startTag(null, "op"); 15642af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov out.attribute(null, "n", Integer.toString(op)); 15652af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov out.attribute(null, "m", Integer.toString(mode)); 15662af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov out.endTag(null, "op"); 15672af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 15682af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov out.endTag(null, "uid"); 15692af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 15702af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 157135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 157235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (allOps != null) { 157335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn String lastPkg = null; 157435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn for (int i=0; i<allOps.size(); i++) { 157535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn AppOpsManager.PackageOps pkg = allOps.get(i); 157635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (!pkg.getPackageName().equals(lastPkg)) { 157735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (lastPkg != null) { 157835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.endTag(null, "pkg"); 157935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 158035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn lastPkg = pkg.getPackageName(); 158135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.startTag(null, "pkg"); 158235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.attribute(null, "n", lastPkg); 158335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 158435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.startTag(null, "uid"); 158535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.attribute(null, "n", Integer.toString(pkg.getUid())); 15861c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk synchronized (this) { 1587f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov Ops ops = getOpsRawLocked(pkg.getUid(), pkg.getPackageName(), false); 15881c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk // Should always be present as the list of PackageOps is generated 15891c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk // from Ops. 15901c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk if (ops != null) { 15911c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk out.attribute(null, "p", Boolean.toString(ops.isPrivileged)); 15921c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk } else { 15931c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk out.attribute(null, "p", Boolean.toString(false)); 15941c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk } 15951c7c319bb89b9988bfd12afc3e8d89449fd163fcJason Monk } 159635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn List<AppOpsManager.OpEntry> ops = pkg.getOps(); 159735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn for (int j=0; j<ops.size(); j++) { 159835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn AppOpsManager.OpEntry op = ops.get(j); 159935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.startTag(null, "op"); 160035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.attribute(null, "n", Integer.toString(op.getOp())); 1601f5d831915dd11e77cdcf5669228c55fe17a21c5eDavid Braun if (op.getMode() != AppOpsManager.opToDefaultMode(op.getOp())) { 16025e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn out.attribute(null, "m", Integer.toString(op.getMode())); 16035e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 16045e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn long time = op.getTime(); 16055e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn if (time != 0) { 16065e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn out.attribute(null, "t", Long.toString(time)); 16075e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 16085e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn time = op.getRejectTime(); 16095e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn if (time != 0) { 16105e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn out.attribute(null, "r", Long.toString(time)); 16115e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 16125e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn int dur = op.getDuration(); 16135e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn if (dur != 0) { 16145e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn out.attribute(null, "d", Integer.toString(dur)); 16155e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 161699b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov int proxyUid = op.getProxyUid(); 161799b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov if (proxyUid != -1) { 161899b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov out.attribute(null, "pu", Integer.toString(proxyUid)); 161999b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov } 162099b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov String proxyPackageName = op.getProxyPackageName(); 162199b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov if (proxyPackageName != null) { 162299b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov out.attribute(null, "pp", proxyPackageName); 162399b6043dad9d215cf15810b885b6b8c215dd5b5aSvet Ganov } 162435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.endTag(null, "op"); 162535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 162635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.endTag(null, "uid"); 162735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 162835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (lastPkg != null) { 162935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.endTag(null, "pkg"); 163035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 163135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 163235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 163335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.endTag(null, "app-ops"); 163435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.endDocument(); 163535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mFile.finishWrite(stream); 163635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (IOException e) { 163735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed to write state, restoring backup.", e); 163835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mFile.failWrite(stream); 163935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 164035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 164135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 164235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 1643268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn static class Shell extends ShellCommand { 1644268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn final IAppOpsService mInterface; 1645268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn final AppOpsService mInternal; 1646268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn 1647268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn int userId = UserHandle.USER_SYSTEM; 1648268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn String packageName; 1649268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn String opStr; 1650e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn String modeStr; 1651268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn int op; 1652e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn int mode; 1653268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn int packageUid; 1654268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn 1655268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn Shell(IAppOpsService iface, AppOpsService internal) { 1656268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn mInterface = iface; 1657268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn mInternal = internal; 1658268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1659268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn 1660268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn @Override 1661268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn public int onCommand(String cmd) { 1662268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return onShellCommand(this, cmd); 1663268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1664268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn 1665268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn @Override 1666268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn public void onHelp() { 1667268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn PrintWriter pw = getOutPrintWriter(); 1668268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn dumpCommandHelp(pw); 1669268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1670268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn 1671268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn private int strOpToOp(String op, PrintWriter err) { 1672268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn try { 1673268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return AppOpsManager.strOpToOp(op); 1674268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } catch (IllegalArgumentException e) { 1675268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1676268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn try { 1677268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return Integer.parseInt(op); 1678268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } catch (NumberFormatException e) { 1679268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1680268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn try { 1681268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return AppOpsManager.strDebugOpToOp(op); 1682268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } catch (IllegalArgumentException e) { 1683268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn err.println("Error: " + e.getMessage()); 1684268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return -1; 1685268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1686268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1687268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn 1688e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn int strModeToMode(String modeStr, PrintWriter err) { 1689e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn switch (modeStr) { 1690e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn case "allow": 1691e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn return AppOpsManager.MODE_ALLOWED; 1692e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn case "deny": 1693e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn return AppOpsManager.MODE_ERRORED; 1694e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn case "ignore": 1695e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn return AppOpsManager.MODE_IGNORED; 1696e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn case "default": 1697e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn return AppOpsManager.MODE_DEFAULT; 1698e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } 1699e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn try { 1700e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn return Integer.parseInt(modeStr); 1701e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } catch (NumberFormatException e) { 1702e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } 1703e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn err.println("Error: Mode " + modeStr + " is not valid"); 1704e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn return -1; 1705e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } 1706e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn 1707e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn int parseUserOpMode(int defMode, PrintWriter err) throws RemoteException { 1708e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn userId = UserHandle.USER_CURRENT; 1709e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn opStr = null; 1710e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn modeStr = null; 1711e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn for (String argument; (argument = getNextArg()) != null;) { 1712e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn if ("--user".equals(argument)) { 1713e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn userId = UserHandle.parseUserArg(getNextArgRequired()); 1714e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } else { 1715e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn if (opStr == null) { 1716e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn opStr = argument; 1717e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } else if (modeStr == null) { 1718e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn modeStr = argument; 1719e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn break; 1720e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } 1721e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } 1722e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } 1723e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn if (opStr == null) { 1724e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn err.println("Error: Operation not specified."); 1725e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn return -1; 1726e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } 1727e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn op = strOpToOp(opStr, err); 1728e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn if (op < 0) { 1729e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn return -1; 1730e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } 1731e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn if (modeStr != null) { 1732e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn if ((mode=strModeToMode(modeStr, err)) < 0) { 1733e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn return -1; 1734e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } 1735e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } else { 1736e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn mode = defMode; 1737e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } 1738e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn return 0; 1739e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } 1740e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn 1741268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn int parseUserPackageOp(boolean reqOp, PrintWriter err) throws RemoteException { 1742268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn userId = UserHandle.USER_CURRENT; 1743268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn packageName = null; 1744268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn opStr = null; 1745268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn for (String argument; (argument = getNextArg()) != null;) { 1746268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if ("--user".equals(argument)) { 1747268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn userId = UserHandle.parseUserArg(getNextArgRequired()); 1748268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } else { 1749268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if (packageName == null) { 1750268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn packageName = argument; 1751268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } else if (opStr == null) { 1752268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn opStr = argument; 1753268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn break; 1754268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1755268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1756268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1757268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if (packageName == null) { 1758268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn err.println("Error: Package name not specified."); 1759268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return -1; 1760268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } else if (opStr == null && reqOp) { 1761268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn err.println("Error: Operation not specified."); 1762268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return -1; 1763268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1764268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if (opStr != null) { 1765268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn op = strOpToOp(opStr, err); 1766268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if (op < 0) { 1767268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return -1; 1768268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1769268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } else { 1770268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn op = AppOpsManager.OP_NONE; 1771268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1772268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if (userId == UserHandle.USER_CURRENT) { 1773268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn userId = ActivityManager.getCurrentUser(); 1774268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1775268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if ("root".equals(packageName)) { 1776268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn packageUid = 0; 1777268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } else { 1778cd65448ccd13c4c2d0fe9e9623fec3a898ab9372Jeff Sharkey packageUid = AppGlobals.getPackageManager().getPackageUid(packageName, 1779cd65448ccd13c4c2d0fe9e9623fec3a898ab9372Jeff Sharkey PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); 1780268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1781268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if (packageUid < 0) { 1782268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn err.println("Error: No UID for " + packageName + " in user " + userId); 1783268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return -1; 1784268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1785268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return 0; 1786268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1787268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1788268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn 1789268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn @Override public void onShellCommand(FileDescriptor in, FileDescriptor out, 1790268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn FileDescriptor err, String[] args, ResultReceiver resultReceiver) { 1791268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn (new Shell(this, this)).exec(this, in, out, err, args, resultReceiver); 1792268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1793268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn 1794268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn static void dumpCommandHelp(PrintWriter pw) { 1795268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println("AppOps service (appops) commands:"); 1796268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println(" help"); 1797268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println(" Print this help text."); 1798268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println(" set [--user <USER_ID>] <PACKAGE> <OP> <MODE>"); 1799268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println(" Set the mode for a particular application and operation."); 1800268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println(" get [--user <USER_ID>] <PACKAGE> [<OP>]"); 1801268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println(" Return the mode for a particular application and optional operation."); 1802e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn pw.println(" query-op [--user <USER_ID>] <OP> [<MODE>]"); 1803e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn pw.println(" Print all packages that currently have the given op in the given mode."); 1804268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println(" reset [--user <USER_ID>] [<PACKAGE>]"); 1805268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println(" Reset the given application or all applications to default modes."); 18064d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn pw.println(" write-settings"); 18074d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn pw.println(" Immediately write pending changes to storage."); 18084d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn pw.println(" read-settings"); 18094d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn pw.println(" Read the last written settings, replacing current state in RAM."); 1810268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println(" options:"); 1811268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println(" <PACKAGE> an Android package name."); 1812268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println(" <OP> an AppOps operation."); 1813268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println(" <MODE> one of allow, ignore, deny, or default"); 1814268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println(" <USER_ID> the user id under which the package is installed. If --user is not"); 1815268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println(" specified, the current user is assumed."); 1816268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1817268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn 1818268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn static int onShellCommand(Shell shell, String cmd) { 1819268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if (cmd == null) { 1820268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return shell.handleDefaultCommands(cmd); 1821268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1822268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn PrintWriter pw = shell.getOutPrintWriter(); 1823268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn PrintWriter err = shell.getErrPrintWriter(); 1824268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn try { 1825268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn switch (cmd) { 1826268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn case "set": { 1827268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn int res = shell.parseUserPackageOp(true, err); 1828268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if (res < 0) { 1829268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return res; 1830268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1831268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn String modeStr = shell.getNextArg(); 1832268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if (modeStr == null) { 1833268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn err.println("Error: Mode not specified."); 1834268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return -1; 1835268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1836268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn 1837e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn final int mode = shell.strModeToMode(modeStr, err); 1838e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn if (mode < 0) { 1839e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn return -1; 1840268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1841268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn 1842268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn shell.mInterface.setMode(shell.op, shell.packageUid, shell.packageName, mode); 1843268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return 0; 1844268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1845268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn case "get": { 1846268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn int res = shell.parseUserPackageOp(false, err); 1847268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if (res < 0) { 1848268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return res; 1849268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1850268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn 1851268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn List<AppOpsManager.PackageOps> ops = shell.mInterface.getOpsForPackage( 1852268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn shell.packageUid, shell.packageName, 1853268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn shell.op != AppOpsManager.OP_NONE ? new int[] {shell.op} : null); 1854268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if (ops == null || ops.size() <= 0) { 1855268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println("No operations."); 1856268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return 0; 1857268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1858268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn final long now = System.currentTimeMillis(); 1859268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn for (int i=0; i<ops.size(); i++) { 1860268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn List<AppOpsManager.OpEntry> entries = ops.get(i).getOps(); 1861268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn for (int j=0; j<entries.size(); j++) { 1862268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn AppOpsManager.OpEntry ent = entries.get(j); 1863268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print(AppOpsManager.opToName(ent.getOp())); 1864268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print(": "); 1865268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn switch (ent.getMode()) { 1866268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn case AppOpsManager.MODE_ALLOWED: 1867268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print("allow"); 1868268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn break; 1869268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn case AppOpsManager.MODE_IGNORED: 1870268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print("ignore"); 1871268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn break; 1872268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn case AppOpsManager.MODE_ERRORED: 1873268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print("deny"); 1874268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn break; 1875268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn case AppOpsManager.MODE_DEFAULT: 1876268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print("default"); 1877268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn break; 1878268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn default: 1879268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print("mode="); 1880268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print(ent.getMode()); 1881268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn break; 1882268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1883268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if (ent.getTime() != 0) { 1884268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print("; time="); 1885268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn TimeUtils.formatDuration(now - ent.getTime(), pw); 1886268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print(" ago"); 1887268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1888268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if (ent.getRejectTime() != 0) { 1889268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print("; rejectTime="); 1890268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn TimeUtils.formatDuration(now - ent.getRejectTime(), pw); 1891268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print(" ago"); 1892268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1893268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if (ent.getDuration() == -1) { 1894268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print(" (running)"); 1895268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } else if (ent.getDuration() != 0) { 1896268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print("; duration="); 1897268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn TimeUtils.formatDuration(ent.getDuration(), pw); 1898268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1899268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println(); 1900268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1901e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } 1902e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn return 0; 1903e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } 1904e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn case "query-op": { 1905e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn int res = shell.parseUserOpMode(AppOpsManager.MODE_IGNORED, err); 1906e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn if (res < 0) { 1907e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn return res; 1908e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } 1909e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn List<AppOpsManager.PackageOps> ops = shell.mInterface.getPackagesForOps( 1910e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn new int[] {shell.op}); 1911e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn if (ops == null || ops.size() <= 0) { 1912e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn pw.println("No operations."); 1913e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn return 0; 1914e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } 1915e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn for (int i=0; i<ops.size(); i++) { 1916e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn final AppOpsManager.PackageOps pkg = ops.get(i); 1917e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn boolean hasMatch = false; 1918e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn final List<AppOpsManager.OpEntry> entries = ops.get(i).getOps(); 1919e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn for (int j=0; j<entries.size(); j++) { 1920e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn AppOpsManager.OpEntry ent = entries.get(j); 1921e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn if (ent.getOp() == shell.op && ent.getMode() == shell.mode) { 1922e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn hasMatch = true; 1923e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn break; 1924e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } 1925e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } 1926e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn if (hasMatch) { 1927e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn pw.println(pkg.getPackageName()); 1928e91f3e7e8d8aec8b880e6ed284a3889f849dfd91Dianne Hackborn } 1929268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1930268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return 0; 1931268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1932268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn case "reset": { 1933268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn String packageName = null; 1934268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn int userId = UserHandle.USER_CURRENT; 1935268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn for (String argument; (argument = shell.getNextArg()) != null;) { 1936268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if ("--user".equals(argument)) { 1937268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn String userStr = shell.getNextArgRequired(); 1938268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn userId = UserHandle.parseUserArg(userStr); 1939268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } else { 1940268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if (packageName == null) { 1941268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn packageName = argument; 1942268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } else { 1943268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn err.println("Error: Unsupported argument: " + argument); 1944268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return -1; 1945268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1946268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1947268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1948268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn 1949268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if (userId == UserHandle.USER_CURRENT) { 1950268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn userId = ActivityManager.getCurrentUser(); 1951268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1952268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn 1953268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn shell.mInterface.resetAllModes(userId, packageName); 1954268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print("Reset all modes for: "); 1955268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if (userId == UserHandle.USER_ALL) { 1956268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print("all users"); 1957268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } else { 1958268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print("user "); pw.print(userId); 1959268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1960268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print(", "); 1961268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn if (packageName == null) { 1962268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println("all packages"); 1963268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } else { 1964268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.print("package "); pw.println(packageName); 1965268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1966268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return 0; 1967268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1968268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn case "write-settings": { 1969268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn shell.mInternal.mContext.enforcePermission( 1970268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn android.Manifest.permission.UPDATE_APP_OPS_STATS, 1971268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 1972268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn long token = Binder.clearCallingIdentity(); 1973268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn try { 1974268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn synchronized (shell.mInternal) { 1975268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn shell.mInternal.mHandler.removeCallbacks(shell.mInternal.mWriteRunner); 1976268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1977268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn shell.mInternal.writeState(); 1978268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println("Current settings written."); 1979268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } finally { 1980268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn Binder.restoreCallingIdentity(token); 1981268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1982268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return 0; 1983268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1984268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn case "read-settings": { 1985268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn shell.mInternal.mContext.enforcePermission( 1986268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn android.Manifest.permission.UPDATE_APP_OPS_STATS, 1987268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 1988268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn long token = Binder.clearCallingIdentity(); 1989268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn try { 1990268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn shell.mInternal.readState(); 1991268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println("Last settings read."); 1992268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } finally { 1993268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn Binder.restoreCallingIdentity(token); 1994268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1995268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return 0; 1996268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 1997268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn default: 1998268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return shell.handleDefaultCommands(cmd); 1999268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 2000268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } catch (RemoteException e) { 2001268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println("Remote exception: " + e); 2002268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 2003268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn return -1; 2004268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn } 2005268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn 2006268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn private void dumpHelp(PrintWriter pw) { 2007268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println("AppOps service (appops) dump options:"); 2008268e4e3d00df6ea0eae6fca321e474a3d512fb7eDianne Hackborn pw.println(" none"); 20094d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn } 20104d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn 2011a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn @Override 2012a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2013a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 2014a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn != PackageManager.PERMISSION_GRANTED) { 2015a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.println("Permission Denial: can't dump ApOps service from from pid=" 2016a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn + Binder.getCallingPid() 2017a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn + ", uid=" + Binder.getCallingUid()); 2018a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return; 2019a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 2020a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 20214d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn if (args != null) { 20224d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn for (int i=0; i<args.length; i++) { 20234d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn String arg = args[i]; 20244d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn if ("-h".equals(arg)) { 20254d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn dumpHelp(pw); 20264d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn return; 20278f1ea834f9af5ccf6cea1f529f63e727cd13b6a8Tim Kilbourn } else if ("-a".equals(arg)) { 20288f1ea834f9af5ccf6cea1f529f63e727cd13b6a8Tim Kilbourn // dump all data 20294d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn } else if (arg.length() > 0 && arg.charAt(0) == '-'){ 20304d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn pw.println("Unknown option: " + arg); 20314d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn return; 20324d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn } else { 20334d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn pw.println("Unknown command: " + arg); 20344d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn return; 20354d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn } 20364d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn } 20374d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn } 20384d34bb8304ae2e85c2b12628c9a6346c6835de5dDianne Hackborn 2039a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (this) { 2040a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.println("Current AppOps Service state:"); 20415e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn final long now = System.currentTimeMillis(); 2042e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn boolean needSep = false; 2043e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn if (mOpModeWatchers.size() > 0) { 2044e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn needSep = true; 2045e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.println(" Op mode watchers:"); 2046e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn for (int i=0; i<mOpModeWatchers.size(); i++) { 2047e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.print(" Op "); pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i))); 2048e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.println(":"); 2049e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn ArrayList<Callback> callbacks = mOpModeWatchers.valueAt(i); 2050e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn for (int j=0; j<callbacks.size(); j++) { 2051e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.print(" #"); pw.print(j); pw.print(": "); 2052e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.println(callbacks.get(j)); 2053e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 2054e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 2055e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 2056e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn if (mPackageModeWatchers.size() > 0) { 2057e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn needSep = true; 2058e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.println(" Package mode watchers:"); 2059e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn for (int i=0; i<mPackageModeWatchers.size(); i++) { 2060e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.print(" Pkg "); pw.print(mPackageModeWatchers.keyAt(i)); 2061e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.println(":"); 2062e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn ArrayList<Callback> callbacks = mPackageModeWatchers.valueAt(i); 2063e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn for (int j=0; j<callbacks.size(); j++) { 2064e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.print(" #"); pw.print(j); pw.print(": "); 2065e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.println(callbacks.get(j)); 2066e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 2067e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 2068e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 2069e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn if (mModeWatchers.size() > 0) { 2070e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn needSep = true; 2071e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.println(" All mode watchers:"); 2072e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn for (int i=0; i<mModeWatchers.size(); i++) { 2073e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.print(" "); pw.print(mModeWatchers.keyAt(i)); 2074e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.print(" -> "); pw.println(mModeWatchers.valueAt(i)); 2075e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 2076e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 2077e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn if (mClients.size() > 0) { 2078e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn needSep = true; 2079e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.println(" Clients:"); 2080e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn for (int i=0; i<mClients.size(); i++) { 2081e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.print(" "); pw.print(mClients.keyAt(i)); pw.println(":"); 2082e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn ClientState cs = mClients.valueAt(i); 2083e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.print(" "); pw.println(cs); 2084e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn if (cs.mStartedOps != null && cs.mStartedOps.size() > 0) { 2085e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.println(" Started ops:"); 2086e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn for (int j=0; j<cs.mStartedOps.size(); j++) { 2087e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn Op op = cs.mStartedOps.get(j); 2088e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.print(" "); pw.print("uid="); pw.print(op.uid); 2089e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.print(" pkg="); pw.print(op.packageName); 2090e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.print(" op="); pw.println(AppOpsManager.opToName(op.op)); 2091e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 2092e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 2093e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 2094e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 20951af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock if (mAudioRestrictions.size() > 0) { 20961af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock boolean printedHeader = false; 20971af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock for (int o=0; o<mAudioRestrictions.size(); o++) { 20981af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock final String op = AppOpsManager.opToName(mAudioRestrictions.keyAt(o)); 20991af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock final SparseArray<Restriction> restrictions = mAudioRestrictions.valueAt(o); 21001af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock for (int i=0; i<restrictions.size(); i++) { 21011af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock if (!printedHeader){ 21021af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock pw.println(" Audio Restrictions:"); 21031af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock printedHeader = true; 21041af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock needSep = true; 21051af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 21067b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock final int usage = restrictions.keyAt(i); 21071af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock pw.print(" "); pw.print(op); 21087b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock pw.print(" usage="); pw.print(AudioAttributes.usageToString(usage)); 21091af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock Restriction r = restrictions.valueAt(i); 21101af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock pw.print(": mode="); pw.println(r.mode); 21111af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock if (!r.exceptionPackages.isEmpty()) { 21121af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock pw.println(" Exceptions:"); 21131af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock for (int j=0; j<r.exceptionPackages.size(); j++) { 21141af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock pw.print(" "); pw.println(r.exceptionPackages.valueAt(j)); 21151af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 21161af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 21171af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 21181af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 21191af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 2120e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn if (needSep) { 2121e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn pw.println(); 2122e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn } 21232af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov for (int i=0; i<mUidStates.size(); i++) { 21242af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov UidState uidState = mUidStates.valueAt(i); 21252af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 21262af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov pw.print(" Uid "); UserHandle.formatUid(pw, uidState.uid); pw.println(":"); 21272af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 21282af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov SparseIntArray opModes = uidState.opModes; 21292af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (opModes != null) { 21302af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int opModeCount = opModes.size(); 21312af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov for (int j = 0; j < opModeCount; j++) { 21322af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int code = opModes.keyAt(j); 21332af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov final int mode = opModes.valueAt(j); 21342af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov pw.print(" "); pw.print(AppOpsManager.opToName(code)); 21352af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov pw.print(": mode="); pw.println(mode); 21362af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 21372af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 21382af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 21392af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov ArrayMap<String, Ops> pkgOps = uidState.pkgOps; 21402af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov if (pkgOps == null) { 21412af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov continue; 21422af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 21432af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov 2144a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn for (Ops ops : pkgOps.values()) { 2145a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.print(" Package "); pw.print(ops.packageName); pw.println(":"); 2146a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn for (int j=0; j<ops.size(); j++) { 2147a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Op op = ops.valueAt(j); 21485e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn pw.print(" "); pw.print(AppOpsManager.opToName(op.op)); 21495e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn pw.print(": mode="); pw.print(op.mode); 21505e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn if (op.time != 0) { 21515e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn pw.print("; time="); TimeUtils.formatDuration(now-op.time, pw); 21525e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn pw.print(" ago"); 21535e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 21545e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn if (op.rejectTime != 0) { 21555e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn pw.print("; rejectTime="); TimeUtils.formatDuration(now-op.rejectTime, pw); 21565e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn pw.print(" ago"); 21575e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn } 2158a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (op.duration == -1) { 21597b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn pw.print(" (running)"); 21607b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn } else if (op.duration != 0) { 21617b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn pw.print("; duration="); TimeUtils.formatDuration(op.duration, pw); 2162a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 21637b7c58b3842d47c4c8df4876e2e2248c58477d97Dianne Hackborn pw.println(); 2164a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 2165a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 2166a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 2167a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 2168a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 21691af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock 21701af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock private static final class Restriction { 21711af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock private static final ArraySet<String> NO_EXCEPTIONS = new ArraySet<String>(); 21721af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock int mode; 21731af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock ArraySet<String> exceptionPackages = NO_EXCEPTIONS; 21741af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 217562062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk 217662062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk @Override 21779cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) { 217862062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk checkSystemUid("setUserRestrictions"); 2179f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov Preconditions.checkNotNull(restrictions); 21809cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov Preconditions.checkNotNull(token); 2181a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov for (int i = 0; i < AppOpsManager._NUM_OP; i++) { 218262062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk String restriction = AppOpsManager.opToRestriction(i); 218364e0dcb989f27fc9246f3b2f40accd261f574d7eSuprabh Shukla if (restriction != null) { 218464e0dcb989f27fc9246f3b2f40accd261f574d7eSuprabh Shukla setUserRestrictionNoCheck(i, restrictions.getBoolean(restriction, false), token, 218564e0dcb989f27fc9246f3b2f40accd261f574d7eSuprabh Shukla userHandle, null); 2186a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 21879cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov } 21889cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov } 21899cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov 21909cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov @Override 219129931bc684bde6b430923122777684178ee2681cRuben Brunk public void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle, 219229931bc684bde6b430923122777684178ee2681cRuben Brunk String[] exceptionPackages) { 21939cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov if (Binder.getCallingPid() != Process.myPid()) { 21949cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov mContext.enforcePermission(Manifest.permission.MANAGE_APP_OPS_RESTRICTIONS, 21959cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov Binder.getCallingPid(), Binder.getCallingUid(), null); 21969cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov } 21979cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov if (userHandle != UserHandle.getCallingUserId()) { 21989cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov if (mContext.checkCallingOrSelfPermission(Manifest.permission 21999cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov .INTERACT_ACROSS_USERS_FULL) != PackageManager.PERMISSION_GRANTED 22009cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov && mContext.checkCallingOrSelfPermission(Manifest.permission 22019cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov .INTERACT_ACROSS_USERS) != PackageManager.PERMISSION_GRANTED) { 22029cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov throw new SecurityException("Need INTERACT_ACROSS_USERS_FULL or" 22039cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov + " INTERACT_ACROSS_USERS to interact cross user "); 220462062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk } 220562062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk } 22069cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov verifyIncomingOp(code); 22079cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov Preconditions.checkNotNull(token); 220829931bc684bde6b430923122777684178ee2681cRuben Brunk setUserRestrictionNoCheck(code, restricted, token, userHandle, exceptionPackages); 22099cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov } 22109cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov 22119cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov private void setUserRestrictionNoCheck(int code, boolean restricted, IBinder token, 221229931bc684bde6b430923122777684178ee2681cRuben Brunk int userHandle, String[] exceptionPackages) { 2213a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov ClientRestrictionState restrictionState = mOpUserRestrictions.get(token); 221429931bc684bde6b430923122777684178ee2681cRuben Brunk 2215a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (restrictionState == null) { 2216a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov try { 2217a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov restrictionState = new ClientRestrictionState(token); 2218a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } catch (RemoteException e) { 2219a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov return; 222029931bc684bde6b430923122777684178ee2681cRuben Brunk } 2221a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov mOpUserRestrictions.put(token, restrictionState); 222229931bc684bde6b430923122777684178ee2681cRuben Brunk } 222329931bc684bde6b430923122777684178ee2681cRuben Brunk 2224a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (restrictionState.setRestriction(code, restricted, exceptionPackages, userHandle)) { 2225a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov notifyWatchersOfChange(code); 22269cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov } 22279cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov 2228a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (restrictionState.isDefault()) { 2229a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov mOpUserRestrictions.remove(token); 2230a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov restrictionState.destroy(); 2231a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2232bb21c25b3f927eeb1a1e56fa3023093f0d74204cJulia Reynolds } 2233bb21c25b3f927eeb1a1e56fa3023093f0d74204cJulia Reynolds 2234bb21c25b3f927eeb1a1e56fa3023093f0d74204cJulia Reynolds private void notifyWatchersOfChange(int code) { 22359cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov final ArrayList<Callback> clonedCallbacks; 22369cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov synchronized (this) { 22379cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov ArrayList<Callback> callbacks = mOpModeWatchers.get(code); 22389cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov if (callbacks == null) { 22399cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov return; 22409cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov } 22419cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov clonedCallbacks = new ArrayList<>(callbacks); 22429cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov } 22439cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov 22449cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov // There are components watching for mode changes such as window manager 22459cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov // and location manager which are in our process. The callbacks in these 2246a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov // components may require permissions our remote caller does not have.s 22479cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov final long identity = Binder.clearCallingIdentity(); 22489cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov try { 22499cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov final int callbackCount = clonedCallbacks.size(); 22509cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov for (int i = 0; i < callbackCount; i++) { 22519cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov Callback callback = clonedCallbacks.get(i); 22529cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov try { 22539cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov callback.mCallback.opChanged(code, -1, null); 22549cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov } catch (RemoteException e) { 22559cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov Log.w(TAG, "Error dispatching op op change", e); 22569cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov } 22579cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov } 22589cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov } finally { 22599cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov Binder.restoreCallingIdentity(identity); 22609cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov } 226162062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk } 226262062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk 226362062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk @Override 226462062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk public void removeUser(int userHandle) throws RemoteException { 226562062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk checkSystemUid("removeUser"); 22669cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov final int tokenCount = mOpUserRestrictions.size(); 22679cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov for (int i = tokenCount - 1; i >= 0; i--) { 2268a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov ClientRestrictionState opRestrictions = mOpUserRestrictions.valueAt(i); 2269a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov opRestrictions.removeUser(userHandle); 22709cea80cdddbecadb304eb7c8373cf1ed397f433aSvet Ganov } 227162062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk } 227262062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk 227362062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk private void checkSystemUid(String function) { 227462062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk int uid = Binder.getCallingUid(); 227562062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk if (uid != Process.SYSTEM_UID) { 227662062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk throw new SecurityException(function + " must by called by the system"); 227762062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk } 227862062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk } 227962062996dd256df8b575b2ba1f0bf97109c4e0baJason Monk 2280f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov private static String resolvePackageName(int uid, String packageName) { 2281f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov if (uid == 0) { 2282f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov return "root"; 2283f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov } else if (uid == Process.SHELL_UID) { 2284f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov return "com.android.shell"; 2285f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov } else if (uid == Process.SYSTEM_UID && packageName == null) { 2286f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov return "android"; 2287f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov } 2288f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov return packageName; 2289f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov } 2290f73adb6c7249a1655bcd2ec17760ec754502f59dSvetoslav Ganov 22912af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov private static String[] getPackagesForUid(int uid) { 2292f3807aa57267117eba83cc2a3b13add59d4a251aSvet Ganov String[] packageNames = null; 22932af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov try { 229440b300fd80708fd100d22f22ff6100db20ee467friddle_hsu packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid); 22952af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } catch (RemoteException e) { 22962af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov /* ignore - local call */ 22972af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 2298f3807aa57267117eba83cc2a3b13add59d4a251aSvet Ganov if (packageNames == null) { 2299f3807aa57267117eba83cc2a3b13add59d4a251aSvet Ganov return EmptyArray.STRING; 2300f3807aa57267117eba83cc2a3b13add59d4a251aSvet Ganov } 2301f3807aa57267117eba83cc2a3b13add59d4a251aSvet Ganov return packageNames; 23022af5708ab0e55fe68f1810cefdc6e3889233c186Svet Ganov } 2303a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov 2304a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov private final class ClientRestrictionState implements DeathRecipient { 2305a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov private final IBinder token; 2306a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov SparseArray<boolean[]> perUserRestrictions; 2307a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov SparseArray<String[]> perUserExcludedPackages; 2308a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov 2309a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov public ClientRestrictionState(IBinder token) 2310a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov throws RemoteException { 2311a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov token.linkToDeath(this, 0); 2312a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov this.token = token; 2313a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2314a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov 2315a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov public boolean setRestriction(int code, boolean restricted, 2316a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov String[] excludedPackages, int userId) { 2317a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov boolean changed = false; 2318a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov 2319a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (perUserRestrictions == null && restricted) { 2320a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov perUserRestrictions = new SparseArray<>(); 2321a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2322a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov 2323a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (perUserRestrictions != null) { 2324a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov boolean[] userRestrictions = perUserRestrictions.get(userId); 2325a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (userRestrictions == null && restricted) { 2326a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov userRestrictions = new boolean[AppOpsManager._NUM_OP]; 2327a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov perUserRestrictions.put(userId, userRestrictions); 2328a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2329a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (userRestrictions != null && userRestrictions[code] != restricted) { 2330a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov userRestrictions[code] = restricted; 2331a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (!restricted && isDefault(userRestrictions)) { 2332a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov perUserRestrictions.remove(userId); 2333a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov userRestrictions = null; 2334a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2335a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov changed = true; 2336a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2337a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov 2338a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (userRestrictions != null) { 2339a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov final boolean noExcludedPackages = ArrayUtils.isEmpty(excludedPackages); 2340a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (perUserExcludedPackages == null && !noExcludedPackages) { 2341a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov perUserExcludedPackages = new SparseArray<>(); 2342a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2343a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (perUserExcludedPackages != null && !Arrays.equals(excludedPackages, 2344a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov perUserExcludedPackages.get(userId))) { 2345a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (noExcludedPackages) { 2346a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov perUserExcludedPackages.remove(userId); 2347a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (perUserExcludedPackages.size() <= 0) { 2348a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov perUserExcludedPackages = null; 2349a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2350a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } else { 2351a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov perUserExcludedPackages.put(userId, excludedPackages); 2352a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2353a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov changed = true; 2354a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2355a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2356a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2357a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov 2358a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov return changed; 2359a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2360a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov 2361a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov public boolean hasRestriction(int restriction, String packageName, int userId) { 2362a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (perUserRestrictions == null) { 2363a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov return false; 2364a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2365a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov boolean[] restrictions = perUserRestrictions.get(userId); 2366a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (restrictions == null) { 2367a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov return false; 2368a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2369a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (!restrictions[restriction]) { 2370a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov return false; 2371a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2372a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (perUserExcludedPackages == null) { 2373a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov return true; 2374a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2375a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov String[] perUserExclusions = perUserExcludedPackages.get(userId); 2376a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (perUserExclusions == null) { 2377a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov return true; 2378a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2379a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov return !ArrayUtils.contains(perUserExclusions, packageName); 2380a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2381a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov 2382a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov public void removeUser(int userId) { 2383a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (perUserExcludedPackages != null) { 2384a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov perUserExcludedPackages.remove(userId); 2385a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (perUserExcludedPackages.size() <= 0) { 2386a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov perUserExcludedPackages = null; 2387a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2388a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2389a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2390a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov 2391a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov public boolean isDefault() { 2392a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov return perUserRestrictions == null || perUserRestrictions.size() <= 0; 2393a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2394a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov 2395a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov @Override 2396a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov public void binderDied() { 2397a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov synchronized (AppOpsService.this) { 2398a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov mOpUserRestrictions.remove(token); 2399a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (perUserRestrictions == null) { 2400a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov return; 2401a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2402a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov final int userCount = perUserRestrictions.size(); 2403a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov for (int i = 0; i < userCount; i++) { 2404a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov final boolean[] restrictions = perUserRestrictions.valueAt(i); 2405a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov final int restrictionCount = restrictions.length; 2406a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov for (int j = 0; j < restrictionCount; j++) { 2407a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (restrictions[j]) { 2408a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov final int changedCode = j; 2409a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov mHandler.post(() -> notifyWatchersOfChange(changedCode)); 2410a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2411a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2412a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2413a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov destroy(); 2414a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2415a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2416a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov 2417a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov public void destroy() { 2418a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov token.unlinkToDeath(this, 0); 2419a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2420a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov 2421a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov private boolean isDefault(boolean[] array) { 2422a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (ArrayUtils.isEmpty(array)) { 2423a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov return true; 2424a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2425a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov for (boolean value : array) { 2426a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov if (value) { 2427a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov return false; 2428a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2429a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2430a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov return true; 2431a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2432a8bbd76d9b5249c64ef31aa162e9a84abaad39baSvetoslav Ganov } 2433a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn} 2434