blob: d073bc60c766af1dbfea36129d986c2cf3af79f7 [file] [log] [blame]
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Svet Ganov8455ba22019-01-02 13:05:56 -080017package com.android.server.appop;
Dianne Hackborna06de0f2012-12-11 16:34:47 -080018
Svet Ganovaf189e32019-02-15 18:45:29 -080019import static android.app.AppOpsManager.MAX_PRIORITY_UID_STATE;
20import static android.app.AppOpsManager.MIN_PRIORITY_UID_STATE;
21import static android.app.AppOpsManager.OP_FLAGS_ALL;
Svet Ganov8455ba22019-01-02 13:05:56 -080022import static android.app.AppOpsManager.OP_NONE;
Philip P. Moltmanndde07852019-01-25 16:42:36 -080023import static android.app.AppOpsManager.OP_PLAY_AUDIO;
Hai Zhang2b98fb32018-09-21 15:18:46 -070024import static android.app.AppOpsManager.UID_STATE_BACKGROUND;
25import static android.app.AppOpsManager.UID_STATE_CACHED;
26import static android.app.AppOpsManager.UID_STATE_FOREGROUND;
27import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE;
Amith Yamasania0a30a12019-01-22 11:38:06 -080028import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE_LOCATION;
Svet Ganovaf189e32019-02-15 18:45:29 -080029import static android.app.AppOpsManager.UID_STATE_MAX_LAST_NON_RESTRICTED;
Hai Zhang2b98fb32018-09-21 15:18:46 -070030import static android.app.AppOpsManager.UID_STATE_PERSISTENT;
31import static android.app.AppOpsManager.UID_STATE_TOP;
Eugene Suslae4ee2c22018-11-05 12:23:30 -080032import static android.app.AppOpsManager.modeToName;
33import static android.app.AppOpsManager.opToName;
Svet Ganovaf189e32019-02-15 18:45:29 -080034import static android.app.AppOpsManager.resolveFirstUnrestrictedUidState;
Hai Zhang2b98fb32018-09-21 15:18:46 -070035
Philip P. Moltmanne683f192017-06-23 14:05:04 -070036import android.Manifest;
Svet Ganovad0a49b2018-10-29 10:07:08 -070037import android.annotation.NonNull;
38import android.annotation.Nullable;
Philip P. Moltmanne683f192017-06-23 14:05:04 -070039import android.app.ActivityManager;
40import android.app.ActivityThread;
41import android.app.AppGlobals;
42import android.app.AppOpsManager;
Svet Ganov8455ba22019-01-02 13:05:56 -080043import android.app.AppOpsManager.HistoricalOps;
Svet Ganov23c88db2019-01-22 20:38:11 -080044import android.app.AppOpsManager.HistoricalOpsRequest;
Svet Ganovaf189e32019-02-15 18:45:29 -080045import android.app.AppOpsManager.Mode;
46import android.app.AppOpsManager.OpEntry;
47import android.app.AppOpsManager.OpFlags;
Dianne Hackbornd5254412018-05-11 18:02:58 -070048import android.app.AppOpsManagerInternal;
Svet Ganovd873ae62018-06-25 16:39:23 -070049import android.app.AppOpsManagerInternal.CheckOpsDelegate;
Suprabh Shukla3017fe42018-11-08 19:00:01 -080050import android.content.BroadcastReceiver;
Dianne Hackborn65a4f252018-05-08 17:30:48 -070051import android.content.ContentResolver;
Philip P. Moltmanne683f192017-06-23 14:05:04 -070052import android.content.Context;
Suprabh Shukla3017fe42018-11-08 19:00:01 -080053import android.content.Intent;
54import android.content.IntentFilter;
Philip P. Moltmanne683f192017-06-23 14:05:04 -070055import android.content.pm.ApplicationInfo;
56import android.content.pm.IPackageManager;
57import android.content.pm.PackageManager;
58import android.content.pm.PackageManagerInternal;
59import android.content.pm.UserInfo;
Dianne Hackborn65a4f252018-05-08 17:30:48 -070060import android.database.ContentObserver;
Philip P. Moltmanne683f192017-06-23 14:05:04 -070061import android.media.AudioAttributes;
Dianne Hackborn65a4f252018-05-08 17:30:48 -070062import android.net.Uri;
Philip P. Moltmanne683f192017-06-23 14:05:04 -070063import android.os.AsyncTask;
64import android.os.Binder;
65import android.os.Bundle;
66import android.os.Handler;
67import android.os.IBinder;
68import android.os.Process;
Svet Ganov8455ba22019-01-02 13:05:56 -080069import android.os.RemoteCallback;
Philip P. Moltmanne683f192017-06-23 14:05:04 -070070import android.os.RemoteException;
71import android.os.ResultReceiver;
72import android.os.ServiceManager;
73import android.os.ShellCallback;
74import android.os.ShellCommand;
Dianne Hackborncd1f30b2018-04-23 17:38:09 -070075import android.os.SystemClock;
Philip P. Moltmanne683f192017-06-23 14:05:04 -070076import android.os.UserHandle;
77import android.os.UserManager;
Sudheer Shanka98cb3f02018-08-17 16:10:29 -070078import android.os.storage.StorageManager;
Philip P. Moltmanne683f192017-06-23 14:05:04 -070079import android.os.storage.StorageManagerInternal;
Dianne Hackborn65a4f252018-05-08 17:30:48 -070080import android.provider.Settings;
Philip P. Moltmanne683f192017-06-23 14:05:04 -070081import android.util.ArrayMap;
82import android.util.ArraySet;
83import android.util.AtomicFile;
Dianne Hackborn65a4f252018-05-08 17:30:48 -070084import android.util.KeyValueListParser;
Svet Ganovaf189e32019-02-15 18:45:29 -080085import android.util.LongSparseArray;
86import android.util.LongSparseLongArray;
Philip P. Moltmanne683f192017-06-23 14:05:04 -070087import android.util.Slog;
88import android.util.SparseArray;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -070089import android.util.SparseBooleanArray;
Philip P. Moltmanne683f192017-06-23 14:05:04 -070090import android.util.SparseIntArray;
91import android.util.TimeUtils;
92import android.util.Xml;
93
Todd Kennedy556efba2018-11-15 07:43:55 -080094import com.android.internal.annotations.GuardedBy;
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -070095import com.android.internal.annotations.VisibleForTesting;
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -080096import com.android.internal.app.IAppOpsActiveCallback;
Philip P. Moltmanne683f192017-06-23 14:05:04 -070097import com.android.internal.app.IAppOpsCallback;
Svet Ganovb3d2ae22018-12-17 22:06:15 -080098import com.android.internal.app.IAppOpsNotedCallback;
Philip P. Moltmanne683f192017-06-23 14:05:04 -070099import com.android.internal.app.IAppOpsService;
100import com.android.internal.os.Zygote;
101import com.android.internal.util.ArrayUtils;
102import com.android.internal.util.DumpUtils;
103import com.android.internal.util.FastXmlSerializer;
104import com.android.internal.util.Preconditions;
105import com.android.internal.util.XmlUtils;
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800106import com.android.internal.util.function.pooled.PooledLambda;
Svet Ganov8455ba22019-01-02 13:05:56 -0800107import com.android.server.LocalServices;
108import com.android.server.LockGuard;
Philip P. Moltmanndde07852019-01-25 16:42:36 -0800109
Philip P. Moltmanne683f192017-06-23 14:05:04 -0700110import libcore.util.EmptyArray;
111
112import org.xmlpull.v1.XmlPullParser;
113import org.xmlpull.v1.XmlPullParserException;
114import org.xmlpull.v1.XmlSerializer;
115
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800116import java.io.File;
117import java.io.FileDescriptor;
Dianne Hackborn35654b62013-01-14 17:38:02 -0800118import java.io.FileInputStream;
119import java.io.FileNotFoundException;
120import java.io.FileOutputStream;
121import java.io.IOException;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800122import java.io.PrintWriter;
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +0100123import java.nio.charset.StandardCharsets;
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700124import java.text.SimpleDateFormat;
Dianne Hackborn35654b62013-01-14 17:38:02 -0800125import java.util.ArrayList;
Svetoslav Ganova8bbd762016-05-13 17:08:16 -0700126import java.util.Arrays;
Svetoslav215b44a2015-08-04 19:03:40 -0700127import java.util.Collections;
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700128import java.util.Date;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800129import java.util.HashMap;
Dianne Hackbornc2293022013-02-06 23:14:49 -0800130import java.util.Iterator;
Dianne Hackborn35654b62013-01-14 17:38:02 -0800131import java.util.List;
Dianne Hackborn607b4142013-08-02 18:10:10 -0700132import java.util.Map;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800133
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800134public class AppOpsService extends IAppOpsService.Stub {
135 static final String TAG = "AppOps";
Dianne Hackborn35654b62013-01-14 17:38:02 -0800136 static final boolean DEBUG = false;
137
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -0700138 private static final int NO_VERSION = -1;
139 /** Increment by one every time and add the corresponding upgrade logic in
140 * {@link #upgradeLocked(int)} below. The first version was 1 */
141 private static final int CURRENT_VERSION = 1;
142
Dianne Hackborn35654b62013-01-14 17:38:02 -0800143 // Write at most every 30 minutes.
144 static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800145
Svet Ganov3a95f832018-03-23 17:44:30 -0700146 // Constant meaning that any UID should be matched when dispatching callbacks
147 private static final int UID_ANY = -2;
148
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700149 // Map from process states to the uid states we track.
150 private static final int[] PROCESS_STATE_TO_UID_STATE = new int[] {
151 UID_STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT
152 UID_STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
153 UID_STATE_TOP, // ActivityManager.PROCESS_STATE_TOP
Amith Yamasania0a30a12019-01-22 11:38:06 -0800154 UID_STATE_FOREGROUND_SERVICE_LOCATION,
155 // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION
Amith Yamasanif235d0b2019-03-20 22:49:43 -0700156 UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_TOP
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700157 UID_STATE_FOREGROUND_SERVICE, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
158 UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
159 UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
160 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
161 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
162 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_BACKUP
163 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_SERVICE
164 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_RECEIVER
165 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_TOP_SLEEPING
166 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
167 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_HOME
168 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
169 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
170 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
171 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_RECENT
172 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_EMPTY
173 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_NONEXISTENT
174 };
175
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800176 Context mContext;
177 final AtomicFile mFile;
Dianne Hackborn35654b62013-01-14 17:38:02 -0800178 final Handler mHandler;
179
Dianne Hackbornd5254412018-05-11 18:02:58 -0700180 private final AppOpsManagerInternalImpl mAppOpsManagerInternal
181 = new AppOpsManagerInternalImpl();
182
Dianne Hackborn35654b62013-01-14 17:38:02 -0800183 boolean mWriteScheduled;
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -0800184 boolean mFastWriteScheduled;
Dianne Hackborn35654b62013-01-14 17:38:02 -0800185 final Runnable mWriteRunner = new Runnable() {
186 public void run() {
187 synchronized (AppOpsService.this) {
188 mWriteScheduled = false;
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -0800189 mFastWriteScheduled = false;
Dianne Hackborn35654b62013-01-14 17:38:02 -0800190 AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
191 @Override protected Void doInBackground(Void... params) {
192 writeState();
193 return null;
194 }
195 };
196 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null);
197 }
198 }
199 };
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800200
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -0700201 @VisibleForTesting
202 final SparseArray<UidState> mUidStates = new SparseArray<>();
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800203
Svet Ganov8455ba22019-01-02 13:05:56 -0800204 private final HistoricalRegistry mHistoricalRegistry = new HistoricalRegistry(this);
205
Dianne Hackborn9fb93502018-06-18 12:29:44 -0700206 long mLastRealtime;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700207
Ruben Brunk29931bc2016-03-11 00:24:26 -0800208 /*
209 * These are app op restrictions imposed per user from various parties.
Ruben Brunk29931bc2016-03-11 00:24:26 -0800210 */
Svetoslav Ganova8bbd762016-05-13 17:08:16 -0700211 private final ArrayMap<IBinder, ClientRestrictionState> mOpUserRestrictions = new ArrayMap<>();
Jason Monk62062992014-05-06 09:55:28 -0400212
Dianne Hackbornd5254412018-05-11 18:02:58 -0700213 SparseIntArray mProfileOwners;
214
Todd Kennedy556efba2018-11-15 07:43:55 -0800215 @GuardedBy("this")
Svet Ganovd873ae62018-06-25 16:39:23 -0700216 private CheckOpsDelegate mCheckOpsDelegate;
217
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700218 /**
219 * All times are in milliseconds. These constants are kept synchronized with the system
220 * global Settings. Any access to this class or its fields should be done while
221 * holding the AppOpsService lock.
222 */
223 private final class Constants extends ContentObserver {
224 // Key names stored in the settings value.
Dianne Hackborne93ab412018-05-14 17:52:30 -0700225 private static final String KEY_TOP_STATE_SETTLE_TIME = "top_state_settle_time";
226 private static final String KEY_FG_SERVICE_STATE_SETTLE_TIME
227 = "fg_service_state_settle_time";
228 private static final String KEY_BG_STATE_SETTLE_TIME = "bg_state_settle_time";
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700229
230 /**
Dianne Hackborne93ab412018-05-14 17:52:30 -0700231 * How long we want for a drop in uid state from top to settle before applying it.
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700232 * @see Settings.Global#APP_OPS_CONSTANTS
Dianne Hackborne93ab412018-05-14 17:52:30 -0700233 * @see #KEY_TOP_STATE_SETTLE_TIME
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700234 */
Dianne Hackborne93ab412018-05-14 17:52:30 -0700235 public long TOP_STATE_SETTLE_TIME;
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700236
Dianne Hackborne93ab412018-05-14 17:52:30 -0700237 /**
238 * How long we want for a drop in uid state from foreground to settle before applying it.
239 * @see Settings.Global#APP_OPS_CONSTANTS
240 * @see #KEY_FG_SERVICE_STATE_SETTLE_TIME
241 */
242 public long FG_SERVICE_STATE_SETTLE_TIME;
243
244 /**
245 * How long we want for a drop in uid state from background to settle before applying it.
246 * @see Settings.Global#APP_OPS_CONSTANTS
247 * @see #KEY_BG_STATE_SETTLE_TIME
248 */
249 public long BG_STATE_SETTLE_TIME;
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700250
251 private final KeyValueListParser mParser = new KeyValueListParser(',');
252 private ContentResolver mResolver;
253
254 public Constants(Handler handler) {
255 super(handler);
256 updateConstants();
257 }
258
259 public void startMonitoring(ContentResolver resolver) {
260 mResolver = resolver;
261 mResolver.registerContentObserver(
Dianne Hackborn45c79b02018-05-11 09:46:13 -0700262 Settings.Global.getUriFor(Settings.Global.APP_OPS_CONSTANTS),
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700263 false, this);
264 updateConstants();
265 }
266
267 @Override
268 public void onChange(boolean selfChange, Uri uri) {
269 updateConstants();
270 }
271
272 private void updateConstants() {
Dianne Hackborn45c79b02018-05-11 09:46:13 -0700273 String value = mResolver != null ? Settings.Global.getString(mResolver,
274 Settings.Global.APP_OPS_CONSTANTS) : "";
275
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700276 synchronized (AppOpsService.this) {
277 try {
Dianne Hackborn45c79b02018-05-11 09:46:13 -0700278 mParser.setString(value);
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700279 } catch (IllegalArgumentException e) {
280 // Failed to parse the settings string, log this and move on
281 // with defaults.
282 Slog.e(TAG, "Bad app ops settings", e);
283 }
Dianne Hackborne93ab412018-05-14 17:52:30 -0700284 TOP_STATE_SETTLE_TIME = mParser.getDurationMillis(
285 KEY_TOP_STATE_SETTLE_TIME, 30 * 1000L);
286 FG_SERVICE_STATE_SETTLE_TIME = mParser.getDurationMillis(
287 KEY_FG_SERVICE_STATE_SETTLE_TIME, 10 * 1000L);
288 BG_STATE_SETTLE_TIME = mParser.getDurationMillis(
289 KEY_BG_STATE_SETTLE_TIME, 1 * 1000L);
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700290 }
291 }
292
293 void dump(PrintWriter pw) {
294 pw.println(" Settings:");
295
Dianne Hackborne93ab412018-05-14 17:52:30 -0700296 pw.print(" "); pw.print(KEY_TOP_STATE_SETTLE_TIME); pw.print("=");
297 TimeUtils.formatDuration(TOP_STATE_SETTLE_TIME, pw);
Dianne Hackbornb94d82f2018-05-16 17:03:01 -0700298 pw.println();
Dianne Hackborne93ab412018-05-14 17:52:30 -0700299 pw.print(" "); pw.print(KEY_FG_SERVICE_STATE_SETTLE_TIME); pw.print("=");
300 TimeUtils.formatDuration(FG_SERVICE_STATE_SETTLE_TIME, pw);
Dianne Hackbornb94d82f2018-05-16 17:03:01 -0700301 pw.println();
Dianne Hackborne93ab412018-05-14 17:52:30 -0700302 pw.print(" "); pw.print(KEY_BG_STATE_SETTLE_TIME); pw.print("=");
303 TimeUtils.formatDuration(BG_STATE_SETTLE_TIME, pw);
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700304 pw.println();
305 }
306 }
307
308 private final Constants mConstants;
309
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -0700310 @VisibleForTesting
311 static final class UidState {
Svet Ganov2af57082015-07-30 08:44:20 -0700312 public final int uid;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700313
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700314 public int state = UID_STATE_CACHED;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700315 public int pendingState = UID_STATE_CACHED;
316 public long pendingStateCommitTime;
317
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700318 public int startNesting;
Svet Ganov2af57082015-07-30 08:44:20 -0700319 public ArrayMap<String, Ops> pkgOps;
320 public SparseIntArray opModes;
321
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700322 // true indicates there is an interested observer, false there isn't but it has such an op
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700323 public SparseBooleanArray foregroundOps;
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700324 public boolean hasForegroundWatchers;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700325
Svet Ganov2af57082015-07-30 08:44:20 -0700326 public UidState(int uid) {
327 this.uid = uid;
328 }
329
330 public void clear() {
331 pkgOps = null;
332 opModes = null;
333 }
334
335 public boolean isDefault() {
336 return (pkgOps == null || pkgOps.isEmpty())
Svet Ganovaf189e32019-02-15 18:45:29 -0800337 && (opModes == null || opModes.size() <= 0)
338 && (state == UID_STATE_CACHED
339 && (pendingState == UID_STATE_CACHED));
Svet Ganov2af57082015-07-30 08:44:20 -0700340 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700341
Svet Ganovaf189e32019-02-15 18:45:29 -0800342 int evalMode(int op, int mode) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700343 if (mode == AppOpsManager.MODE_FOREGROUND) {
Svet Ganovaf189e32019-02-15 18:45:29 -0800344 return state <= AppOpsManager.resolveLastRestrictedUidState(op)
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700345 ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED;
346 }
347 return mode;
348 }
349
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700350 private void evalForegroundWatchers(int op, SparseArray<ArraySet<ModeCallback>> watchers,
351 SparseBooleanArray which) {
352 boolean curValue = which.get(op, false);
353 ArraySet<ModeCallback> callbacks = watchers.get(op);
354 if (callbacks != null) {
355 for (int cbi = callbacks.size() - 1; !curValue && cbi >= 0; cbi--) {
356 if ((callbacks.valueAt(cbi).mFlags
357 & AppOpsManager.WATCH_FOREGROUND_CHANGES) != 0) {
358 hasForegroundWatchers = true;
359 curValue = true;
360 }
361 }
362 }
363 which.put(op, curValue);
364 }
365
366 public void evalForegroundOps(SparseArray<ArraySet<ModeCallback>> watchers) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700367 SparseBooleanArray which = null;
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700368 hasForegroundWatchers = false;
369 if (opModes != null) {
370 for (int i = opModes.size() - 1; i >= 0; i--) {
371 if (opModes.valueAt(i) == AppOpsManager.MODE_FOREGROUND) {
372 if (which == null) {
373 which = new SparseBooleanArray();
374 }
375 evalForegroundWatchers(opModes.keyAt(i), watchers, which);
376 }
377 }
378 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700379 if (pkgOps != null) {
380 for (int i = pkgOps.size() - 1; i >= 0; i--) {
381 Ops ops = pkgOps.valueAt(i);
382 for (int j = ops.size() - 1; j >= 0; j--) {
383 if (ops.valueAt(j).mode == AppOpsManager.MODE_FOREGROUND) {
384 if (which == null) {
385 which = new SparseBooleanArray();
386 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700387 evalForegroundWatchers(ops.keyAt(j), watchers, which);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700388 }
389 }
390 }
391 }
392 foregroundOps = which;
393 }
Svet Ganov2af57082015-07-30 08:44:20 -0700394 }
395
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700396 final static class Ops extends SparseArray<Op> {
397 final String packageName;
398 final UidState uidState;
399 final boolean isPrivileged;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800400
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700401 Ops(String _packageName, UidState _uidState, boolean _isPrivileged) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800402 packageName = _packageName;
Svet Ganov2af57082015-07-30 08:44:20 -0700403 uidState = _uidState;
Jason Monk1c7c3192014-06-26 12:52:18 -0400404 isPrivileged = _isPrivileged;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800405 }
406 }
407
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700408 final static class Op {
Svet Ganovaf189e32019-02-15 18:45:29 -0800409 int op;
410 boolean running;
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700411 final UidState uidState;
Svet Ganovaf189e32019-02-15 18:45:29 -0800412 final @NonNull String packageName;
413
414 private @Mode int mode;
415 private @Nullable LongSparseLongArray mAccessTimes;
416 private @Nullable LongSparseLongArray mRejectTimes;
417 private @Nullable LongSparseLongArray mDurations;
418 private @Nullable LongSparseLongArray mProxyUids;
419 private @Nullable LongSparseArray<String> mProxyPackageNames;
420
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700421 int startNesting;
422 long startRealtime;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800423
Svet Ganovaf189e32019-02-15 18:45:29 -0800424 Op(UidState uidState, String packageName, int op) {
425 this.op = op;
426 this.uidState = uidState;
427 this.packageName = packageName;
428 this.mode = AppOpsManager.opToDefaultMode(op);
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700429 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700430
431 int getMode() {
Svet Ganovaf189e32019-02-15 18:45:29 -0800432 return mode;
433 }
434
435 int evalMode() {
436 return uidState.evalMode(op, mode);
437 }
438
439 /** @hide */
440 public void accessed(long time, int proxyUid, @Nullable String proxyPackageName,
441 @AppOpsManager.UidState int uidState, @OpFlags int flags) {
442 final long key = AppOpsManager.makeKey(uidState, flags);
443 if (mAccessTimes == null) {
444 mAccessTimes = new LongSparseLongArray();
445 }
446 mAccessTimes.put(key, time);
447 updateProxyState(key, proxyUid, proxyPackageName);
448 if (mDurations != null) {
449 mDurations.delete(key);
450 }
451 }
452
453 /** @hide */
454 public void rejected(long time, int proxyUid, @Nullable String proxyPackageName,
455 @AppOpsManager.UidState int uidState, @OpFlags int flags) {
456 final long key = AppOpsManager.makeKey(uidState, flags);
457 if (mRejectTimes == null) {
458 mRejectTimes = new LongSparseLongArray();
459 }
460 mRejectTimes.put(key, time);
461 updateProxyState(key, proxyUid, proxyPackageName);
462 if (mDurations != null) {
463 mDurations.delete(key);
464 }
465 }
466
467 /** @hide */
468 public void started(long time, @AppOpsManager.UidState int uidState, @OpFlags int flags) {
469 updateAccessTimeAndDuration(time, -1 /*duration*/, uidState, flags);
470 running = true;
471 }
472
473 /** @hide */
474 public void finished(long time, long duration, @AppOpsManager.UidState int uidState,
475 @OpFlags int flags) {
476 updateAccessTimeAndDuration(time, duration, uidState, flags);
477 running = false;
478 }
479
480 /** @hide */
481 public void running(long time, long duration, @AppOpsManager.UidState int uidState,
482 @OpFlags int flags) {
483 updateAccessTimeAndDuration(time, duration, uidState, flags);
484 }
485
486 /** @hide */
487 public void continuing(long duration, @AppOpsManager.UidState int uidState,
488 @OpFlags int flags) {
489 final long key = AppOpsManager.makeKey(uidState, flags);
490 if (mDurations == null) {
491 mDurations = new LongSparseLongArray();
492 }
493 mDurations.put(key, duration);
494 }
495
496 private void updateAccessTimeAndDuration(long time, long duration,
497 @AppOpsManager.UidState int uidState, @OpFlags int flags) {
498 final long key = AppOpsManager.makeKey(uidState, flags);
499 if (mAccessTimes == null) {
500 mAccessTimes = new LongSparseLongArray();
501 }
502 mAccessTimes.put(key, time);
503 if (mDurations == null) {
504 mDurations = new LongSparseLongArray();
505 }
506 mDurations.put(key, duration);
507 }
508
509 private void updateProxyState(long key, int proxyUid,
510 @Nullable String proxyPackageName) {
511 if (mProxyUids == null) {
512 mProxyUids = new LongSparseLongArray();
513 }
514 mProxyUids.put(key, proxyUid);
515 if (mProxyPackageNames == null) {
516 mProxyPackageNames = new LongSparseArray<>();
517 }
518 mProxyPackageNames.put(key, proxyPackageName);
519 }
520
521 boolean hasAnyTime() {
522 return (mAccessTimes != null && mAccessTimes.size() > 0)
523 || (mRejectTimes != null && mRejectTimes.size() > 0);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700524 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800525 }
526
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800527 final SparseArray<ArraySet<ModeCallback>> mOpModeWatchers = new SparseArray<>();
528 final ArrayMap<String, ArraySet<ModeCallback>> mPackageModeWatchers = new ArrayMap<>();
529 final ArrayMap<IBinder, ModeCallback> mModeWatchers = new ArrayMap<>();
530 final ArrayMap<IBinder, SparseArray<ActiveCallback>> mActiveWatchers = new ArrayMap<>();
Svet Ganovb3d2ae22018-12-17 22:06:15 -0800531 final ArrayMap<IBinder, SparseArray<NotedCallback>> mNotedWatchers = new ArrayMap<>();
Dianne Hackborn68d76552017-02-27 15:32:03 -0800532 final SparseArray<SparseArray<Restriction>> mAudioRestrictions = new SparseArray<>();
Dianne Hackbornc2293022013-02-06 23:14:49 -0800533
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700534 final class ModeCallback implements DeathRecipient {
Dianne Hackbornc2293022013-02-06 23:14:49 -0800535 final IAppOpsCallback mCallback;
Dianne Hackborn3b563fc2018-04-16 17:17:14 -0700536 final int mWatchingUid;
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700537 final int mFlags;
Dianne Hackborn3b563fc2018-04-16 17:17:14 -0700538 final int mCallingUid;
539 final int mCallingPid;
Dianne Hackbornc2293022013-02-06 23:14:49 -0800540
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700541 ModeCallback(IAppOpsCallback callback, int watchingUid, int flags, int callingUid,
Dianne Hackborn3b563fc2018-04-16 17:17:14 -0700542 int callingPid) {
Dianne Hackbornc2293022013-02-06 23:14:49 -0800543 mCallback = callback;
Dianne Hackborn3b563fc2018-04-16 17:17:14 -0700544 mWatchingUid = watchingUid;
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700545 mFlags = flags;
Dianne Hackborn3b563fc2018-04-16 17:17:14 -0700546 mCallingUid = callingUid;
547 mCallingPid = callingPid;
Dianne Hackbornc2293022013-02-06 23:14:49 -0800548 try {
549 mCallback.asBinder().linkToDeath(this, 0);
550 } catch (RemoteException e) {
Svet Ganovb3d2ae22018-12-17 22:06:15 -0800551 /*ignored*/
Dianne Hackbornc2293022013-02-06 23:14:49 -0800552 }
553 }
554
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700555 public boolean isWatchingUid(int uid) {
556 return uid == UID_ANY || mWatchingUid < 0 || mWatchingUid == uid;
557 }
558
Dianne Hackborn3b563fc2018-04-16 17:17:14 -0700559 @Override
560 public String toString() {
561 StringBuilder sb = new StringBuilder(128);
562 sb.append("ModeCallback{");
563 sb.append(Integer.toHexString(System.identityHashCode(this)));
564 sb.append(" watchinguid=");
565 UserHandle.formatUid(sb, mWatchingUid);
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700566 sb.append(" flags=0x");
567 sb.append(Integer.toHexString(mFlags));
Dianne Hackborn3b563fc2018-04-16 17:17:14 -0700568 sb.append(" from uid=");
569 UserHandle.formatUid(sb, mCallingUid);
570 sb.append(" pid=");
571 sb.append(mCallingPid);
572 sb.append('}');
573 return sb.toString();
574 }
575
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700576 void unlinkToDeath() {
Dianne Hackbornc2293022013-02-06 23:14:49 -0800577 mCallback.asBinder().unlinkToDeath(this, 0);
578 }
579
580 @Override
581 public void binderDied() {
582 stopWatchingMode(mCallback);
583 }
584 }
585
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700586 final class ActiveCallback implements DeathRecipient {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800587 final IAppOpsActiveCallback mCallback;
Dianne Hackborn3b563fc2018-04-16 17:17:14 -0700588 final int mWatchingUid;
589 final int mCallingUid;
590 final int mCallingPid;
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800591
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700592 ActiveCallback(IAppOpsActiveCallback callback, int watchingUid, int callingUid,
Dianne Hackborn3b563fc2018-04-16 17:17:14 -0700593 int callingPid) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800594 mCallback = callback;
Dianne Hackborn3b563fc2018-04-16 17:17:14 -0700595 mWatchingUid = watchingUid;
596 mCallingUid = callingUid;
597 mCallingPid = callingPid;
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800598 try {
599 mCallback.asBinder().linkToDeath(this, 0);
600 } catch (RemoteException e) {
Svet Ganovb3d2ae22018-12-17 22:06:15 -0800601 /*ignored*/
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800602 }
603 }
604
Dianne Hackborn3b563fc2018-04-16 17:17:14 -0700605 @Override
606 public String toString() {
607 StringBuilder sb = new StringBuilder(128);
608 sb.append("ActiveCallback{");
609 sb.append(Integer.toHexString(System.identityHashCode(this)));
610 sb.append(" watchinguid=");
611 UserHandle.formatUid(sb, mWatchingUid);
612 sb.append(" from uid=");
613 UserHandle.formatUid(sb, mCallingUid);
614 sb.append(" pid=");
615 sb.append(mCallingPid);
616 sb.append('}');
617 return sb.toString();
618 }
619
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700620 void destroy() {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800621 mCallback.asBinder().unlinkToDeath(this, 0);
622 }
623
624 @Override
625 public void binderDied() {
626 stopWatchingActive(mCallback);
627 }
628 }
629
Svet Ganovb3d2ae22018-12-17 22:06:15 -0800630 final class NotedCallback implements DeathRecipient {
631 final IAppOpsNotedCallback mCallback;
632 final int mWatchingUid;
633 final int mCallingUid;
634 final int mCallingPid;
635
636 NotedCallback(IAppOpsNotedCallback callback, int watchingUid, int callingUid,
637 int callingPid) {
638 mCallback = callback;
639 mWatchingUid = watchingUid;
640 mCallingUid = callingUid;
641 mCallingPid = callingPid;
642 try {
643 mCallback.asBinder().linkToDeath(this, 0);
644 } catch (RemoteException e) {
645 /*ignored*/
646 }
647 }
648
649 @Override
650 public String toString() {
651 StringBuilder sb = new StringBuilder(128);
652 sb.append("NotedCallback{");
653 sb.append(Integer.toHexString(System.identityHashCode(this)));
654 sb.append(" watchinguid=");
655 UserHandle.formatUid(sb, mWatchingUid);
656 sb.append(" from uid=");
657 UserHandle.formatUid(sb, mCallingUid);
658 sb.append(" pid=");
659 sb.append(mCallingPid);
660 sb.append('}');
661 return sb.toString();
662 }
663
664 void destroy() {
665 mCallback.asBinder().unlinkToDeath(this, 0);
666 }
667
668 @Override
669 public void binderDied() {
670 stopWatchingNoted(mCallback);
671 }
672 }
673
Svet Ganova7a0db62018-02-27 20:08:01 -0800674 final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<>();
Dianne Hackborne98f5db2013-07-17 17:23:25 -0700675
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700676 final class ClientState extends Binder implements DeathRecipient {
Svet Ganovf7b47252018-02-26 11:11:27 -0800677 final ArrayList<Op> mStartedOps = new ArrayList<>();
Dianne Hackborne98f5db2013-07-17 17:23:25 -0700678 final IBinder mAppToken;
679 final int mPid;
Dianne Hackborne98f5db2013-07-17 17:23:25 -0700680
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700681 ClientState(IBinder appToken) {
Dianne Hackborne98f5db2013-07-17 17:23:25 -0700682 mAppToken = appToken;
683 mPid = Binder.getCallingPid();
Svet Ganovf7b47252018-02-26 11:11:27 -0800684 // Watch only for remote processes dying
685 if (!(appToken instanceof Binder)) {
Dianne Hackborne98f5db2013-07-17 17:23:25 -0700686 try {
687 mAppToken.linkToDeath(this, 0);
688 } catch (RemoteException e) {
Svet Ganovf7b47252018-02-26 11:11:27 -0800689 /* do nothing */
Dianne Hackborne98f5db2013-07-17 17:23:25 -0700690 }
691 }
692 }
693
694 @Override
695 public String toString() {
696 return "ClientState{" +
697 "mAppToken=" + mAppToken +
Svet Ganovf7b47252018-02-26 11:11:27 -0800698 ", " + "pid=" + mPid +
Dianne Hackborne98f5db2013-07-17 17:23:25 -0700699 '}';
700 }
701
702 @Override
703 public void binderDied() {
704 synchronized (AppOpsService.this) {
705 for (int i=mStartedOps.size()-1; i>=0; i--) {
Svet Ganova7a0db62018-02-27 20:08:01 -0800706 finishOperationLocked(mStartedOps.get(i), /*finishNested*/ true);
Dianne Hackborne98f5db2013-07-17 17:23:25 -0700707 }
708 mClients.remove(mAppToken);
709 }
710 }
711 }
712
Jeff Brown6f357d32014-01-15 20:40:55 -0800713 public AppOpsService(File storagePath, Handler handler) {
Jeff Sharkey5f3e9342017-03-13 14:53:11 -0600714 LockGuard.installLock(this, LockGuard.INDEX_APP_OPS);
Dianne Hackborne17b4452018-01-10 13:15:40 -0800715 mFile = new AtomicFile(storagePath, "appops");
Jeff Brown6f357d32014-01-15 20:40:55 -0800716 mHandler = handler;
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700717 mConstants = new Constants(mHandler);
Dianne Hackborn35654b62013-01-14 17:38:02 -0800718 readState();
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800719 }
David Braunf5d83192013-09-16 13:43:51 -0700720
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800721 public void publish(Context context) {
722 mContext = context;
723 ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder());
Dianne Hackbornd5254412018-05-11 18:02:58 -0700724 LocalServices.addService(AppOpsManagerInternal.class, mAppOpsManagerInternal);
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800725 }
726
Dianne Hackborn514074f2013-02-11 10:52:46 -0800727 public void systemReady() {
Dianne Hackborn45c79b02018-05-11 09:46:13 -0700728 mConstants.startMonitoring(mContext.getContentResolver());
Svet Ganov8455ba22019-01-02 13:05:56 -0800729 mHistoricalRegistry.systemReady(mContext.getContentResolver());
Dianne Hackborn45c79b02018-05-11 09:46:13 -0700730
Dianne Hackborn514074f2013-02-11 10:52:46 -0800731 synchronized (this) {
732 boolean changed = false;
Svet Ganov2af57082015-07-30 08:44:20 -0700733 for (int i = mUidStates.size() - 1; i >= 0; i--) {
734 UidState uidState = mUidStates.valueAt(i);
735
736 String[] packageNames = getPackagesForUid(uidState.uid);
737 if (ArrayUtils.isEmpty(packageNames)) {
738 uidState.clear();
739 mUidStates.removeAt(i);
740 changed = true;
741 continue;
742 }
743
744 ArrayMap<String, Ops> pkgs = uidState.pkgOps;
745 if (pkgs == null) {
746 continue;
747 }
748
Dianne Hackborn514074f2013-02-11 10:52:46 -0800749 Iterator<Ops> it = pkgs.values().iterator();
750 while (it.hasNext()) {
751 Ops ops = it.next();
Jeff Sharkeye2ed23e2015-10-29 19:00:44 -0700752 int curUid = -1;
Dianne Hackborn514074f2013-02-11 10:52:46 -0800753 try {
Jeff Sharkeycd654482016-01-08 17:42:11 -0700754 curUid = AppGlobals.getPackageManager().getPackageUid(ops.packageName,
755 PackageManager.MATCH_UNINSTALLED_PACKAGES,
Svet Ganov2af57082015-07-30 08:44:20 -0700756 UserHandle.getUserId(ops.uidState.uid));
Jeff Sharkeye2ed23e2015-10-29 19:00:44 -0700757 } catch (RemoteException ignored) {
Dianne Hackborn514074f2013-02-11 10:52:46 -0800758 }
Svet Ganov2af57082015-07-30 08:44:20 -0700759 if (curUid != ops.uidState.uid) {
Dianne Hackborn514074f2013-02-11 10:52:46 -0800760 Slog.i(TAG, "Pruning old package " + ops.packageName
Svet Ganov2af57082015-07-30 08:44:20 -0700761 + "/" + ops.uidState + ": new uid=" + curUid);
Dianne Hackborn514074f2013-02-11 10:52:46 -0800762 it.remove();
763 changed = true;
764 }
765 }
Svet Ganov2af57082015-07-30 08:44:20 -0700766
767 if (uidState.isDefault()) {
768 mUidStates.removeAt(i);
Dianne Hackborn514074f2013-02-11 10:52:46 -0800769 }
770 }
771 if (changed) {
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -0800772 scheduleFastWriteLocked();
Dianne Hackborn514074f2013-02-11 10:52:46 -0800773 }
774 }
Svet Ganov6ee871e2015-07-10 14:29:33 -0700775
Suprabh Shukla3017fe42018-11-08 19:00:01 -0800776 final IntentFilter packageSuspendFilter = new IntentFilter();
777 packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
778 packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
779 mContext.registerReceiver(new BroadcastReceiver() {
780 @Override
781 public void onReceive(Context context, Intent intent) {
782 final int[] changedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
783 final String[] changedPkgs = intent.getStringArrayExtra(
784 Intent.EXTRA_CHANGED_PACKAGE_LIST);
Dianne Hackbornb298b352019-04-04 11:01:41 -0700785 ArraySet<ModeCallback> callbacks;
786 synchronized (AppOpsService.this) {
787 callbacks = mOpModeWatchers.get(OP_PLAY_AUDIO);
788 if (callbacks == null) {
789 return;
790 }
791 callbacks = new ArraySet<>(callbacks);
792 }
Suprabh Shukla3017fe42018-11-08 19:00:01 -0800793 for (int i = 0; i < changedUids.length; i++) {
794 final int changedUid = changedUids[i];
795 final String changedPkg = changedPkgs[i];
Dianne Hackbornb298b352019-04-04 11:01:41 -0700796 // We trust packagemanager to insert matching uid and packageNames in the
797 // extras
798 notifyOpChanged(callbacks, OP_PLAY_AUDIO, changedUid, changedPkg);
Suprabh Shukla3017fe42018-11-08 19:00:01 -0800799 }
800 }
801 }, packageSuspendFilter);
802
Suprabh Shuklaaef25132017-01-23 18:09:03 -0800803 PackageManagerInternal packageManagerInternal = LocalServices.getService(
804 PackageManagerInternal.class);
805 packageManagerInternal.setExternalSourcesPolicy(
806 new PackageManagerInternal.ExternalSourcesPolicy() {
807 @Override
808 public int getPackageTrustedToInstallApps(String packageName, int uid) {
809 int appOpMode = checkOperation(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES,
810 uid, packageName);
811 switch (appOpMode) {
812 case AppOpsManager.MODE_ALLOWED:
813 return PackageManagerInternal.ExternalSourcesPolicy.USER_TRUSTED;
814 case AppOpsManager.MODE_ERRORED:
815 return PackageManagerInternal.ExternalSourcesPolicy.USER_BLOCKED;
816 default:
817 return PackageManagerInternal.ExternalSourcesPolicy.USER_DEFAULT;
818 }
819 }
820 });
821
Jeff Sharkey10ec9d82018-11-28 14:52:45 -0700822 if (!StorageManager.hasIsolatedStorage()) {
Sudheer Shanka98cb3f02018-08-17 16:10:29 -0700823 StorageManagerInternal storageManagerInternal = LocalServices.getService(
824 StorageManagerInternal.class);
825 storageManagerInternal.addExternalStoragePolicy(
826 new StorageManagerInternal.ExternalStorageMountPolicy() {
827 @Override
828 public int getMountMode(int uid, String packageName) {
829 if (Process.isIsolated(uid)) {
830 return Zygote.MOUNT_EXTERNAL_NONE;
831 }
832 if (noteOperation(AppOpsManager.OP_READ_EXTERNAL_STORAGE, uid,
833 packageName) != AppOpsManager.MODE_ALLOWED) {
834 return Zygote.MOUNT_EXTERNAL_NONE;
835 }
836 if (noteOperation(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, uid,
837 packageName) != AppOpsManager.MODE_ALLOWED) {
838 return Zygote.MOUNT_EXTERNAL_READ;
839 }
840 return Zygote.MOUNT_EXTERNAL_WRITE;
Svet Ganov6ee871e2015-07-10 14:29:33 -0700841 }
Svet Ganov6ee871e2015-07-10 14:29:33 -0700842
Sudheer Shanka98cb3f02018-08-17 16:10:29 -0700843 @Override
844 public boolean hasExternalStorage(int uid, String packageName) {
845 final int mountMode = getMountMode(uid, packageName);
846 return mountMode == Zygote.MOUNT_EXTERNAL_READ
847 || mountMode == Zygote.MOUNT_EXTERNAL_WRITE;
848 }
849 });
850 }
Dianne Hackborn514074f2013-02-11 10:52:46 -0800851 }
852
853 public void packageRemoved(int uid, String packageName) {
854 synchronized (this) {
Svet Ganov2af57082015-07-30 08:44:20 -0700855 UidState uidState = mUidStates.get(uid);
856 if (uidState == null) {
857 return;
858 }
859
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800860 Ops ops = null;
Svet Ganov2af57082015-07-30 08:44:20 -0700861
862 // Remove any package state if such.
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800863 if (uidState.pkgOps != null) {
864 ops = uidState.pkgOps.remove(packageName);
Svet Ganov2af57082015-07-30 08:44:20 -0700865 }
866
867 // If we just nuked the last package state check if the UID is valid.
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800868 if (ops != null && uidState.pkgOps.isEmpty()
Svet Ganov2af57082015-07-30 08:44:20 -0700869 && getPackagesForUid(uid).length <= 0) {
870 mUidStates.remove(uid);
871 }
872
Svet Ganova7a0db62018-02-27 20:08:01 -0800873 // Finish ops other packages started on behalf of the package.
874 final int clientCount = mClients.size();
875 for (int i = 0; i < clientCount; i++) {
876 final ClientState client = mClients.valueAt(i);
877 if (client.mStartedOps == null) {
878 continue;
879 }
880 final int opCount = client.mStartedOps.size();
881 for (int j = opCount - 1; j >= 0; j--) {
882 final Op op = client.mStartedOps.get(j);
Svet Ganovaf189e32019-02-15 18:45:29 -0800883 if (uid == op.uidState.uid && packageName.equals(op.packageName)) {
Svet Ganova7a0db62018-02-27 20:08:01 -0800884 finishOperationLocked(op, /*finishNested*/ true);
885 client.mStartedOps.remove(j);
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700886 if (op.startNesting <= 0) {
Svet Ganova7a0db62018-02-27 20:08:01 -0800887 scheduleOpActiveChangedIfNeededLocked(op.op,
888 uid, packageName, false);
889 }
890 }
891 }
892 }
893
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800894 if (ops != null) {
Svet Ganov2af57082015-07-30 08:44:20 -0700895 scheduleFastWriteLocked();
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800896
897 final int opCount = ops.size();
898 for (int i = 0; i < opCount; i++) {
899 final Op op = ops.valueAt(i);
Svet Ganovaf189e32019-02-15 18:45:29 -0800900 if (op.running) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800901 scheduleOpActiveChangedIfNeededLocked(
Svet Ganovaf189e32019-02-15 18:45:29 -0800902 op.op, op.uidState.uid, op.packageName, false);
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800903 }
904 }
Dianne Hackborn514074f2013-02-11 10:52:46 -0800905 }
906 }
907 }
908
909 public void uidRemoved(int uid) {
910 synchronized (this) {
Svet Ganov2af57082015-07-30 08:44:20 -0700911 if (mUidStates.indexOfKey(uid) >= 0) {
912 mUidStates.remove(uid);
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -0800913 scheduleFastWriteLocked();
Dianne Hackborn514074f2013-02-11 10:52:46 -0800914 }
915 }
916 }
917
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700918 public void updateUidProcState(int uid, int procState) {
919 synchronized (this) {
920 final UidState uidState = getUidStateLocked(uid, true);
Amith Yamasania0a30a12019-01-22 11:38:06 -0800921 int newState = PROCESS_STATE_TO_UID_STATE[procState];
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700922 if (uidState != null && uidState.pendingState != newState) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700923 final int oldPendingState = uidState.pendingState;
924 uidState.pendingState = newState;
Svet Ganovaf189e32019-02-15 18:45:29 -0800925 if (newState < uidState.state || newState <= UID_STATE_MAX_LAST_NON_RESTRICTED) {
Dianne Hackborne93ab412018-05-14 17:52:30 -0700926 // We are moving to a more important state, or the new state is in the
927 // foreground, then always do it immediately.
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700928 commitUidPendingStateLocked(uidState);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700929 } else if (uidState.pendingStateCommitTime == 0) {
930 // We are moving to a less important state for the first time,
931 // delay the application for a bit.
Dianne Hackborne93ab412018-05-14 17:52:30 -0700932 final long settleTime;
933 if (uidState.state <= UID_STATE_TOP) {
934 settleTime = mConstants.TOP_STATE_SETTLE_TIME;
935 } else if (uidState.state <= UID_STATE_FOREGROUND_SERVICE) {
936 settleTime = mConstants.FG_SERVICE_STATE_SETTLE_TIME;
937 } else {
938 settleTime = mConstants.BG_STATE_SETTLE_TIME;
939 }
Dianne Hackborn9fb93502018-06-18 12:29:44 -0700940 uidState.pendingStateCommitTime = SystemClock.elapsedRealtime() + settleTime;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700941 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700942 if (uidState.startNesting != 0) {
943 // There is some actively running operation... need to find it
944 // and appropriately update its state.
945 final long now = System.currentTimeMillis();
946 for (int i = uidState.pkgOps.size() - 1; i >= 0; i--) {
947 final Ops ops = uidState.pkgOps.valueAt(i);
948 for (int j = ops.size() - 1; j >= 0; j--) {
949 final Op op = ops.valueAt(j);
950 if (op.startNesting > 0) {
Svet Ganovaf189e32019-02-15 18:45:29 -0800951 final long duration = SystemClock.elapsedRealtime()
952 - op.startRealtime;
953 // We don't support proxy long running ops (start/stop)
954 mHistoricalRegistry.increaseOpAccessDuration(op.op,
955 op.uidState.uid, op.packageName, oldPendingState,
956 AppOpsManager.OP_FLAG_SELF, duration);
957 // Finish the op in the old state
958 op.finished(now, duration, oldPendingState,
959 AppOpsManager.OP_FLAG_SELF);
960 // Start the op in the new state
961 op.startRealtime = now;
962 op.started(now, newState, AppOpsManager.OP_FLAG_SELF);
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700963 }
964 }
965 }
966 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700967 }
968 }
969 }
970
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800971 public void shutdown() {
972 Slog.w(TAG, "Writing app ops before shutdown...");
Dianne Hackborn35654b62013-01-14 17:38:02 -0800973 boolean doWrite = false;
974 synchronized (this) {
975 if (mWriteScheduled) {
976 mWriteScheduled = false;
977 doWrite = true;
978 }
979 }
980 if (doWrite) {
981 writeState();
982 }
983 }
984
Dianne Hackborn72e39832013-01-18 18:36:09 -0800985 private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) {
986 ArrayList<AppOpsManager.OpEntry> resOps = null;
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700987 final long elapsedNow = SystemClock.elapsedRealtime();
Dianne Hackborn72e39832013-01-18 18:36:09 -0800988 if (ops == null) {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700989 resOps = new ArrayList<>();
Dianne Hackborn72e39832013-01-18 18:36:09 -0800990 for (int j=0; j<pkgOps.size(); j++) {
991 Op curOp = pkgOps.valueAt(j);
Svet Ganovaf189e32019-02-15 18:45:29 -0800992 resOps.add(getOpEntryForResult(curOp, elapsedNow));
Dianne Hackborn72e39832013-01-18 18:36:09 -0800993 }
994 } else {
995 for (int j=0; j<ops.length; j++) {
996 Op curOp = pkgOps.get(ops[j]);
997 if (curOp != null) {
998 if (resOps == null) {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700999 resOps = new ArrayList<>();
Dianne Hackborn72e39832013-01-18 18:36:09 -08001000 }
Svet Ganovaf189e32019-02-15 18:45:29 -08001001 resOps.add(getOpEntryForResult(curOp, elapsedNow));
Dianne Hackborn72e39832013-01-18 18:36:09 -08001002 }
1003 }
1004 }
1005 return resOps;
1006 }
1007
Dianne Hackbornc7214a32017-04-11 13:32:47 -07001008 private ArrayList<AppOpsManager.OpEntry> collectOps(SparseIntArray uidOps, int[] ops) {
Eugene Suslae4ee2c22018-11-05 12:23:30 -08001009 if (uidOps == null) {
1010 return null;
1011 }
Dianne Hackbornc7214a32017-04-11 13:32:47 -07001012 ArrayList<AppOpsManager.OpEntry> resOps = null;
1013 if (ops == null) {
1014 resOps = new ArrayList<>();
1015 for (int j=0; j<uidOps.size(); j++) {
Svet Ganovaf189e32019-02-15 18:45:29 -08001016 resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j)));
Dianne Hackbornc7214a32017-04-11 13:32:47 -07001017 }
1018 } else {
1019 for (int j=0; j<ops.length; j++) {
1020 int index = uidOps.indexOfKey(ops[j]);
1021 if (index >= 0) {
1022 if (resOps == null) {
1023 resOps = new ArrayList<>();
1024 }
Svet Ganovaf189e32019-02-15 18:45:29 -08001025 resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j)));
Dianne Hackbornc7214a32017-04-11 13:32:47 -07001026 }
1027 }
1028 }
1029 return resOps;
1030 }
1031
Svet Ganovaf189e32019-02-15 18:45:29 -08001032 private static @NonNull OpEntry getOpEntryForResult(@NonNull Op op, long elapsedNow) {
1033 if (op.running) {
1034 op.continuing(elapsedNow - op.startRealtime,
1035 op.uidState.state, AppOpsManager.OP_FLAG_SELF);
1036 }
1037 final OpEntry entry = new OpEntry(op.op, op.running, op.mode,
1038 op.mAccessTimes != null ? op.mAccessTimes.clone() : null,
1039 op.mRejectTimes != null ? op.mRejectTimes.clone() : null,
1040 op.mDurations != null ? op.mDurations.clone() : null,
1041 op.mProxyUids != null ? op.mProxyUids.clone() : null,
1042 op.mProxyPackageNames != null ? op.mProxyPackageNames.clone() : null);
1043 return entry;
1044 }
1045
Dianne Hackborn35654b62013-01-14 17:38:02 -08001046 @Override
1047 public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
1048 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
1049 Binder.getCallingPid(), Binder.getCallingUid(), null);
1050 ArrayList<AppOpsManager.PackageOps> res = null;
1051 synchronized (this) {
Svet Ganov2af57082015-07-30 08:44:20 -07001052 final int uidStateCount = mUidStates.size();
1053 for (int i = 0; i < uidStateCount; i++) {
1054 UidState uidState = mUidStates.valueAt(i);
1055 if (uidState.pkgOps == null || uidState.pkgOps.isEmpty()) {
1056 continue;
1057 }
1058 ArrayMap<String, Ops> packages = uidState.pkgOps;
1059 final int packageCount = packages.size();
1060 for (int j = 0; j < packageCount; j++) {
1061 Ops pkgOps = packages.valueAt(j);
Dianne Hackborn72e39832013-01-18 18:36:09 -08001062 ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
Dianne Hackborn35654b62013-01-14 17:38:02 -08001063 if (resOps != null) {
1064 if (res == null) {
1065 res = new ArrayList<AppOpsManager.PackageOps>();
1066 }
1067 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
Svet Ganov2af57082015-07-30 08:44:20 -07001068 pkgOps.packageName, pkgOps.uidState.uid, resOps);
Dianne Hackborn35654b62013-01-14 17:38:02 -08001069 res.add(resPackage);
1070 }
1071 }
1072 }
1073 }
1074 return res;
1075 }
1076
1077 @Override
Dianne Hackborn72e39832013-01-18 18:36:09 -08001078 public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName,
1079 int[] ops) {
1080 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
1081 Binder.getCallingPid(), Binder.getCallingUid(), null);
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00001082 String resolvedPackageName = resolvePackageName(uid, packageName);
1083 if (resolvedPackageName == null) {
1084 return Collections.emptyList();
1085 }
Dianne Hackborn72e39832013-01-18 18:36:09 -08001086 synchronized (this) {
Yohei Yukawaa965d652017-10-12 15:02:26 -07001087 Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false /* edit */,
1088 false /* uidMismatchExpected */);
Dianne Hackborn72e39832013-01-18 18:36:09 -08001089 if (pkgOps == null) {
1090 return null;
1091 }
1092 ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
1093 if (resOps == null) {
1094 return null;
1095 }
1096 ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>();
1097 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
Svet Ganov2af57082015-07-30 08:44:20 -07001098 pkgOps.packageName, pkgOps.uidState.uid, resOps);
Dianne Hackborn72e39832013-01-18 18:36:09 -08001099 res.add(resPackage);
1100 return res;
1101 }
1102 }
1103
Dianne Hackbornc7214a32017-04-11 13:32:47 -07001104 @Override
Svet Ganov8455ba22019-01-02 13:05:56 -08001105 public void getHistoricalOps(int uid, @NonNull String packageName,
Svet Ganov23c88db2019-01-22 20:38:11 -08001106 @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis,
Svet Ganovaf189e32019-02-15 18:45:29 -08001107 @OpFlags int flags, @NonNull RemoteCallback callback) {
Svet Ganov23c88db2019-01-22 20:38:11 -08001108 // Use the builder to validate arguments.
Svet Ganovaf189e32019-02-15 18:45:29 -08001109 new HistoricalOpsRequest.Builder(
Svet Ganov23c88db2019-01-22 20:38:11 -08001110 beginTimeMillis, endTimeMillis)
1111 .setUid(uid)
1112 .setPackageName(packageName)
1113 .setOpNames(opNames)
Svet Ganovaf189e32019-02-15 18:45:29 -08001114 .setFlags(flags)
Svet Ganov23c88db2019-01-22 20:38:11 -08001115 .build();
Svet Ganov8455ba22019-01-02 13:05:56 -08001116 Preconditions.checkNotNull(callback, "callback cannot be null");
Svet Ganovad0a49b2018-10-29 10:07:08 -07001117
1118 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
Svet Ganov8455ba22019-01-02 13:05:56 -08001119 Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");
Svet Ganovad0a49b2018-10-29 10:07:08 -07001120
Svet Ganov23c88db2019-01-22 20:38:11 -08001121 final String[] opNamesArray = (opNames != null)
1122 ? opNames.toArray(new String[opNames.size()]) : null;
Svet Ganovad0a49b2018-10-29 10:07:08 -07001123
Svet Ganovaf189e32019-02-15 18:45:29 -08001124 // Must not hold the appops lock
1125 mHistoricalRegistry.getHistoricalOps(uid, packageName, opNamesArray,
1126 beginTimeMillis, endTimeMillis, flags, callback);
Svet Ganovad0a49b2018-10-29 10:07:08 -07001127 }
1128
1129 @Override
Svet Ganov8455ba22019-01-02 13:05:56 -08001130 public void getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName,
Svet Ganov23c88db2019-01-22 20:38:11 -08001131 @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis,
Svet Ganovaf189e32019-02-15 18:45:29 -08001132 @OpFlags int flags, @NonNull RemoteCallback callback) {
Svet Ganov23c88db2019-01-22 20:38:11 -08001133 // Use the builder to validate arguments.
Svet Ganovaf189e32019-02-15 18:45:29 -08001134 new HistoricalOpsRequest.Builder(
Svet Ganov23c88db2019-01-22 20:38:11 -08001135 beginTimeMillis, endTimeMillis)
1136 .setUid(uid)
1137 .setPackageName(packageName)
1138 .setOpNames(opNames)
Svet Ganovaf189e32019-02-15 18:45:29 -08001139 .setFlags(flags)
Svet Ganov23c88db2019-01-22 20:38:11 -08001140 .build();
Svet Ganov8455ba22019-01-02 13:05:56 -08001141 Preconditions.checkNotNull(callback, "callback cannot be null");
Svet Ganovad0a49b2018-10-29 10:07:08 -07001142
Svet Ganov8e5bf962019-03-19 23:59:03 -07001143 mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS,
Svet Ganov8455ba22019-01-02 13:05:56 -08001144 Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");
Svet Ganovad0a49b2018-10-29 10:07:08 -07001145
Svet Ganov23c88db2019-01-22 20:38:11 -08001146 final String[] opNamesArray = (opNames != null)
1147 ? opNames.toArray(new String[opNames.size()]) : null;
1148
Svet Ganov8455ba22019-01-02 13:05:56 -08001149 // Must not hold the appops lock
Svet Ganov23c88db2019-01-22 20:38:11 -08001150 mHistoricalRegistry.getHistoricalOpsFromDiskRaw(uid, packageName, opNamesArray,
Svet Ganovaf189e32019-02-15 18:45:29 -08001151 beginTimeMillis, endTimeMillis, flags, callback);
Svet Ganovad0a49b2018-10-29 10:07:08 -07001152 }
1153
1154 @Override
Svet Ganov8e5bf962019-03-19 23:59:03 -07001155 public void reloadNonHistoricalState() {
1156 mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS,
1157 Binder.getCallingPid(), Binder.getCallingUid(), "reloadNonHistoricalState");
1158 writeState();
1159 readState();
1160 }
1161
1162 @Override
Dianne Hackbornc7214a32017-04-11 13:32:47 -07001163 public List<AppOpsManager.PackageOps> getUidOps(int uid, int[] ops) {
1164 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
1165 Binder.getCallingPid(), Binder.getCallingUid(), null);
1166 synchronized (this) {
1167 UidState uidState = getUidStateLocked(uid, false);
1168 if (uidState == null) {
1169 return null;
1170 }
1171 ArrayList<AppOpsManager.OpEntry> resOps = collectOps(uidState.opModes, ops);
1172 if (resOps == null) {
1173 return null;
1174 }
1175 ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>();
1176 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
1177 null, uidState.uid, resOps);
1178 res.add(resPackage);
1179 return res;
1180 }
1181 }
1182
Dianne Hackborn607b4142013-08-02 18:10:10 -07001183 private void pruneOp(Op op, int uid, String packageName) {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07001184 if (!op.hasAnyTime()) {
Yohei Yukawaa965d652017-10-12 15:02:26 -07001185 Ops ops = getOpsRawLocked(uid, packageName, false /* edit */,
1186 false /* uidMismatchExpected */);
Dianne Hackborn607b4142013-08-02 18:10:10 -07001187 if (ops != null) {
1188 ops.remove(op.op);
1189 if (ops.size() <= 0) {
Svet Ganov2af57082015-07-30 08:44:20 -07001190 UidState uidState = ops.uidState;
1191 ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
Dianne Hackborn607b4142013-08-02 18:10:10 -07001192 if (pkgOps != null) {
1193 pkgOps.remove(ops.packageName);
Svet Ganov2af57082015-07-30 08:44:20 -07001194 if (pkgOps.isEmpty()) {
1195 uidState.pkgOps = null;
1196 }
1197 if (uidState.isDefault()) {
1198 mUidStates.remove(uid);
Dianne Hackborn607b4142013-08-02 18:10:10 -07001199 }
1200 }
1201 }
1202 }
1203 }
1204 }
1205
Svet Ganovaf189e32019-02-15 18:45:29 -08001206 private void enforceManageAppOpsModes(int callingPid, int callingUid, int targetUid) {
Dianne Hackbornd5254412018-05-11 18:02:58 -07001207 if (callingPid == Process.myPid()) {
1208 return;
1209 }
1210 final int callingUser = UserHandle.getUserId(callingUid);
1211 synchronized (this) {
1212 if (mProfileOwners != null && mProfileOwners.get(callingUser, -1) == callingUid) {
1213 if (targetUid >= 0 && callingUser == UserHandle.getUserId(targetUid)) {
1214 // Profile owners are allowed to change modes but only for apps
1215 // within their user.
1216 return;
1217 }
1218 }
1219 }
1220 mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
1221 Binder.getCallingPid(), Binder.getCallingUid(), null);
1222 }
1223
Dianne Hackborn72e39832013-01-18 18:36:09 -08001224 @Override
Svet Ganov2af57082015-07-30 08:44:20 -07001225 public void setUidMode(int code, int uid, int mode) {
Eugene Suslae4ee2c22018-11-05 12:23:30 -08001226 if (DEBUG) {
1227 Slog.i(TAG, "uid " + uid + " OP_" + opToName(code) + " := " + modeToName(mode)
1228 + " by uid " + Binder.getCallingUid());
1229 }
1230
Dianne Hackbornd5254412018-05-11 18:02:58 -07001231 enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
Svet Ganov2af57082015-07-30 08:44:20 -07001232 verifyIncomingOp(code);
1233 code = AppOpsManager.opToSwitch(code);
1234
1235 synchronized (this) {
1236 final int defaultMode = AppOpsManager.opToDefaultMode(code);
1237
1238 UidState uidState = getUidStateLocked(uid, false);
1239 if (uidState == null) {
1240 if (mode == defaultMode) {
1241 return;
1242 }
1243 uidState = new UidState(uid);
1244 uidState.opModes = new SparseIntArray();
1245 uidState.opModes.put(code, mode);
1246 mUidStates.put(uid, uidState);
1247 scheduleWriteLocked();
1248 } else if (uidState.opModes == null) {
1249 if (mode != defaultMode) {
1250 uidState.opModes = new SparseIntArray();
1251 uidState.opModes.put(code, mode);
1252 scheduleWriteLocked();
1253 }
1254 } else {
Hai Zhang2b98fb32018-09-21 15:18:46 -07001255 if (uidState.opModes.indexOfKey(code) >= 0 && uidState.opModes.get(code) == mode) {
Svet Ganov2af57082015-07-30 08:44:20 -07001256 return;
1257 }
1258 if (mode == defaultMode) {
1259 uidState.opModes.delete(code);
1260 if (uidState.opModes.size() <= 0) {
1261 uidState.opModes = null;
1262 }
1263 } else {
1264 uidState.opModes.put(code, mode);
1265 }
1266 scheduleWriteLocked();
1267 }
Wei Wang711eb662019-03-21 18:24:17 -07001268 uidState.evalForegroundOps(mOpModeWatchers);
Svet Ganov2af57082015-07-30 08:44:20 -07001269 }
1270
Svetoslav215b44a2015-08-04 19:03:40 -07001271 String[] uidPackageNames = getPackagesForUid(uid);
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001272 ArrayMap<ModeCallback, ArraySet<String>> callbackSpecs = null;
Svet Ganov2af57082015-07-30 08:44:20 -07001273
riddle_hsu40b300f2015-11-23 13:22:03 +08001274 synchronized (this) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001275 ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code);
Svet Ganov2af57082015-07-30 08:44:20 -07001276 if (callbacks != null) {
Svet Ganov2af57082015-07-30 08:44:20 -07001277 final int callbackCount = callbacks.size();
1278 for (int i = 0; i < callbackCount; i++) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001279 ModeCallback callback = callbacks.valueAt(i);
riddle_hsu40b300f2015-11-23 13:22:03 +08001280 ArraySet<String> changedPackages = new ArraySet<>();
1281 Collections.addAll(changedPackages, uidPackageNames);
Dianne Hackborn65a4f252018-05-08 17:30:48 -07001282 if (callbackSpecs == null) {
1283 callbackSpecs = new ArrayMap<>();
1284 }
riddle_hsu40b300f2015-11-23 13:22:03 +08001285 callbackSpecs.put(callback, changedPackages);
1286 }
1287 }
1288
1289 for (String uidPackageName : uidPackageNames) {
1290 callbacks = mPackageModeWatchers.get(uidPackageName);
1291 if (callbacks != null) {
1292 if (callbackSpecs == null) {
1293 callbackSpecs = new ArrayMap<>();
Svet Ganov2af57082015-07-30 08:44:20 -07001294 }
riddle_hsu40b300f2015-11-23 13:22:03 +08001295 final int callbackCount = callbacks.size();
1296 for (int i = 0; i < callbackCount; i++) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001297 ModeCallback callback = callbacks.valueAt(i);
riddle_hsu40b300f2015-11-23 13:22:03 +08001298 ArraySet<String> changedPackages = callbackSpecs.get(callback);
1299 if (changedPackages == null) {
1300 changedPackages = new ArraySet<>();
1301 callbackSpecs.put(callback, changedPackages);
1302 }
1303 changedPackages.add(uidPackageName);
1304 }
Svet Ganov2af57082015-07-30 08:44:20 -07001305 }
1306 }
1307 }
1308
1309 if (callbackSpecs == null) {
1310 return;
1311 }
1312
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001313 for (int i = 0; i < callbackSpecs.size(); i++) {
1314 final ModeCallback callback = callbackSpecs.keyAt(i);
1315 final ArraySet<String> reportedPackageNames = callbackSpecs.valueAt(i);
1316 if (reportedPackageNames == null) {
1317 mHandler.sendMessage(PooledLambda.obtainMessage(
1318 AppOpsService::notifyOpChanged,
1319 this, callback, code, uid, (String) null));
1320
1321 } else {
1322 final int reportedPackageCount = reportedPackageNames.size();
1323 for (int j = 0; j < reportedPackageCount; j++) {
1324 final String reportedPackageName = reportedPackageNames.valueAt(j);
1325 mHandler.sendMessage(PooledLambda.obtainMessage(
1326 AppOpsService::notifyOpChanged,
1327 this, callback, code, uid, reportedPackageName));
Svet Ganov2af57082015-07-30 08:44:20 -07001328 }
1329 }
Svet Ganov2af57082015-07-30 08:44:20 -07001330 }
1331 }
1332
Philip P. Moltmanndde07852019-01-25 16:42:36 -08001333 /**
1334 * Set all {@link #setMode (package) modes} for this uid to the default value.
1335 *
1336 * @param code The app-op
1337 * @param uid The uid
1338 */
1339 private void setAllPkgModesToDefault(int code, int uid) {
1340 synchronized (this) {
1341 UidState uidState = getUidStateLocked(uid, false);
1342 if (uidState == null) {
1343 return;
1344 }
1345
1346 ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
1347 if (pkgOps == null) {
1348 return;
1349 }
1350
Svet Ganovaf189e32019-02-15 18:45:29 -08001351 boolean scheduleWrite = false;
1352
Philip P. Moltmanndde07852019-01-25 16:42:36 -08001353 int numPkgs = pkgOps.size();
1354 for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) {
1355 Ops ops = pkgOps.valueAt(pkgNum);
1356
1357 Op op = ops.get(code);
1358 if (op == null) {
1359 continue;
1360 }
1361
1362 int defaultMode = AppOpsManager.opToDefaultMode(code);
1363 if (op.mode != defaultMode) {
Philip P. Moltmanndde07852019-01-25 16:42:36 -08001364 op.mode = defaultMode;
Svet Ganovaf189e32019-02-15 18:45:29 -08001365 scheduleWrite = true;
Philip P. Moltmanndde07852019-01-25 16:42:36 -08001366 }
1367 }
Svet Ganovaf189e32019-02-15 18:45:29 -08001368
1369 if (scheduleWrite) {
1370 scheduleWriteLocked();
1371 }
Philip P. Moltmanndde07852019-01-25 16:42:36 -08001372 }
1373 }
1374
Svet Ganov2af57082015-07-30 08:44:20 -07001375 @Override
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001376 public void setMode(int code, int uid, String packageName, int mode) {
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07001377 setMode(code, uid, packageName, mode, true, false);
1378 }
1379
1380 /**
1381 * Sets the mode for a certain op and uid.
1382 *
1383 * @param code The op code to set
1384 * @param uid The UID for which to set
1385 * @param packageName The package for which to set
1386 * @param mode The new mode to set
1387 * @param verifyUid Iff {@code true}, check that the package name belongs to the uid
1388 * @param isPrivileged Whether the package is privileged. (Only used if {@code verifyUid ==
1389 * false})
1390 */
1391 private void setMode(int code, int uid, @NonNull String packageName, int mode,
1392 boolean verifyUid, boolean isPrivileged) {
Dianne Hackbornd5254412018-05-11 18:02:58 -07001393 enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
Dianne Hackborn961321f2013-02-05 17:22:41 -08001394 verifyIncomingOp(code);
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001395 ArraySet<ModeCallback> repCbs = null;
Dianne Hackbornc2293022013-02-06 23:14:49 -08001396 code = AppOpsManager.opToSwitch(code);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001397 synchronized (this) {
Svet Ganov2af57082015-07-30 08:44:20 -07001398 UidState uidState = getUidStateLocked(uid, false);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07001399 Op op = getOpLocked(code, uid, packageName, true, verifyUid, isPrivileged);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001400 if (op != null) {
1401 if (op.mode != mode) {
1402 op.mode = mode;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07001403 if (uidState != null) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07001404 uidState.evalForegroundOps(mOpModeWatchers);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07001405 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001406 ArraySet<ModeCallback> cbs = mOpModeWatchers.get(code);
Dianne Hackbornc2293022013-02-06 23:14:49 -08001407 if (cbs != null) {
1408 if (repCbs == null) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001409 repCbs = new ArraySet<>();
Dianne Hackbornc2293022013-02-06 23:14:49 -08001410 }
1411 repCbs.addAll(cbs);
1412 }
1413 cbs = mPackageModeWatchers.get(packageName);
1414 if (cbs != null) {
1415 if (repCbs == null) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001416 repCbs = new ArraySet<>();
Dianne Hackbornc2293022013-02-06 23:14:49 -08001417 }
1418 repCbs.addAll(cbs);
1419 }
David Braunf5d83192013-09-16 13:43:51 -07001420 if (mode == AppOpsManager.opToDefaultMode(op.op)) {
Dianne Hackborn514074f2013-02-11 10:52:46 -08001421 // If going into the default mode, prune this op
1422 // if there is nothing else interesting in it.
Dianne Hackborn607b4142013-08-02 18:10:10 -07001423 pruneOp(op, uid, packageName);
Dianne Hackborn514074f2013-02-11 10:52:46 -08001424 }
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -08001425 scheduleFastWriteLocked();
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001426 }
1427 }
1428 }
Dianne Hackbornc2293022013-02-06 23:14:49 -08001429 if (repCbs != null) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001430 mHandler.sendMessage(PooledLambda.obtainMessage(
1431 AppOpsService::notifyOpChanged,
1432 this, repCbs, code, uid, packageName));
Dianne Hackbornc2293022013-02-06 23:14:49 -08001433 }
1434 }
1435
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001436 private void notifyOpChanged(ArraySet<ModeCallback> callbacks, int code,
1437 int uid, String packageName) {
1438 for (int i = 0; i < callbacks.size(); i++) {
1439 final ModeCallback callback = callbacks.valueAt(i);
1440 notifyOpChanged(callback, code, uid, packageName);
1441 }
1442 }
1443
1444 private void notifyOpChanged(ModeCallback callback, int code,
1445 int uid, String packageName) {
Dianne Hackborn3b563fc2018-04-16 17:17:14 -07001446 if (uid != UID_ANY && callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001447 return;
1448 }
1449 // There are components watching for mode changes such as window manager
1450 // and location manager which are in our process. The callbacks in these
1451 // components may require permissions our remote caller does not have.
1452 final long identity = Binder.clearCallingIdentity();
1453 try {
1454 callback.mCallback.opChanged(code, uid, packageName);
1455 } catch (RemoteException e) {
1456 /* ignore */
1457 } finally {
1458 Binder.restoreCallingIdentity(identity);
1459 }
1460 }
1461
1462 private static HashMap<ModeCallback, ArrayList<ChangeRec>> addCallbacks(
1463 HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks,
1464 int op, int uid, String packageName, ArraySet<ModeCallback> cbs) {
Dianne Hackborn607b4142013-08-02 18:10:10 -07001465 if (cbs == null) {
1466 return callbacks;
1467 }
1468 if (callbacks == null) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001469 callbacks = new HashMap<>();
Dianne Hackborn607b4142013-08-02 18:10:10 -07001470 }
Svet Ganov2af57082015-07-30 08:44:20 -07001471 boolean duplicate = false;
Dianne Hackborn68d76552017-02-27 15:32:03 -08001472 final int N = cbs.size();
1473 for (int i=0; i<N; i++) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001474 ModeCallback cb = cbs.valueAt(i);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001475 ArrayList<ChangeRec> reports = callbacks.get(cb);
Dianne Hackborn607b4142013-08-02 18:10:10 -07001476 if (reports == null) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001477 reports = new ArrayList<>();
Dianne Hackborn607b4142013-08-02 18:10:10 -07001478 callbacks.put(cb, reports);
Svet Ganov2af57082015-07-30 08:44:20 -07001479 } else {
1480 final int reportCount = reports.size();
1481 for (int j = 0; j < reportCount; j++) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001482 ChangeRec report = reports.get(j);
1483 if (report.op == op && report.pkg.equals(packageName)) {
Svet Ganov2af57082015-07-30 08:44:20 -07001484 duplicate = true;
1485 break;
1486 }
1487 }
Dianne Hackborn607b4142013-08-02 18:10:10 -07001488 }
Svet Ganov2af57082015-07-30 08:44:20 -07001489 if (!duplicate) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001490 reports.add(new ChangeRec(op, uid, packageName));
Svet Ganov2af57082015-07-30 08:44:20 -07001491 }
Dianne Hackborn607b4142013-08-02 18:10:10 -07001492 }
1493 return callbacks;
1494 }
1495
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001496 static final class ChangeRec {
1497 final int op;
1498 final int uid;
1499 final String pkg;
1500
1501 ChangeRec(int _op, int _uid, String _pkg) {
1502 op = _op;
1503 uid = _uid;
1504 pkg = _pkg;
1505 }
1506 }
1507
Dianne Hackborn607b4142013-08-02 18:10:10 -07001508 @Override
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -08001509 public void resetAllModes(int reqUserId, String reqPackageName) {
1510 final int callingPid = Binder.getCallingPid();
1511 final int callingUid = Binder.getCallingUid();
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -08001512 reqUserId = ActivityManager.handleIncomingUser(callingPid, callingUid, reqUserId,
1513 true, true, "resetAllModes", null);
Svet Ganov2af57082015-07-30 08:44:20 -07001514
1515 int reqUid = -1;
1516 if (reqPackageName != null) {
1517 try {
1518 reqUid = AppGlobals.getPackageManager().getPackageUid(
Jeff Sharkeycd654482016-01-08 17:42:11 -07001519 reqPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, reqUserId);
Svet Ganov2af57082015-07-30 08:44:20 -07001520 } catch (RemoteException e) {
1521 /* ignore - local call */
1522 }
1523 }
1524
Dianne Hackbornd5254412018-05-11 18:02:58 -07001525 enforceManageAppOpsModes(callingPid, callingUid, reqUid);
1526
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001527 HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks = null;
Dianne Hackborn607b4142013-08-02 18:10:10 -07001528 synchronized (this) {
1529 boolean changed = false;
Svet Ganov2af57082015-07-30 08:44:20 -07001530 for (int i = mUidStates.size() - 1; i >= 0; i--) {
1531 UidState uidState = mUidStates.valueAt(i);
1532
1533 SparseIntArray opModes = uidState.opModes;
1534 if (opModes != null && (uidState.uid == reqUid || reqUid == -1)) {
1535 final int uidOpCount = opModes.size();
1536 for (int j = uidOpCount - 1; j >= 0; j--) {
1537 final int code = opModes.keyAt(j);
1538 if (AppOpsManager.opAllowsReset(code)) {
1539 opModes.removeAt(j);
1540 if (opModes.size() <= 0) {
1541 uidState.opModes = null;
1542 }
1543 for (String packageName : getPackagesForUid(uidState.uid)) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001544 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
Svet Ganov2af57082015-07-30 08:44:20 -07001545 mOpModeWatchers.get(code));
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001546 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
Svet Ganov2af57082015-07-30 08:44:20 -07001547 mPackageModeWatchers.get(packageName));
1548 }
1549 }
1550 }
1551 }
1552
1553 if (uidState.pkgOps == null) {
1554 continue;
1555 }
1556
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -08001557 if (reqUserId != UserHandle.USER_ALL
Svet Ganov2af57082015-07-30 08:44:20 -07001558 && reqUserId != UserHandle.getUserId(uidState.uid)) {
Alexandra Gherghinad6a98972014-08-04 17:05:34 +01001559 // Skip any ops for a different user
1560 continue;
1561 }
Svet Ganov2af57082015-07-30 08:44:20 -07001562
1563 Map<String, Ops> packages = uidState.pkgOps;
Dianne Hackborn7f09ec32013-08-07 15:36:08 -07001564 Iterator<Map.Entry<String, Ops>> it = packages.entrySet().iterator();
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07001565 boolean uidChanged = false;
Dianne Hackborn7f09ec32013-08-07 15:36:08 -07001566 while (it.hasNext()) {
1567 Map.Entry<String, Ops> ent = it.next();
Dianne Hackborn607b4142013-08-02 18:10:10 -07001568 String packageName = ent.getKey();
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -08001569 if (reqPackageName != null && !reqPackageName.equals(packageName)) {
1570 // Skip any ops for a different package
1571 continue;
1572 }
Dianne Hackborn607b4142013-08-02 18:10:10 -07001573 Ops pkgOps = ent.getValue();
Dianne Hackborn7f09ec32013-08-07 15:36:08 -07001574 for (int j=pkgOps.size()-1; j>=0; j--) {
Dianne Hackborn607b4142013-08-02 18:10:10 -07001575 Op curOp = pkgOps.valueAt(j);
Dianne Hackborn8828d3a2013-09-25 16:47:10 -07001576 if (AppOpsManager.opAllowsReset(curOp.op)
1577 && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) {
David Braunf5d83192013-09-16 13:43:51 -07001578 curOp.mode = AppOpsManager.opToDefaultMode(curOp.op);
Dianne Hackborn607b4142013-08-02 18:10:10 -07001579 changed = true;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07001580 uidChanged = true;
Svet Ganovaf189e32019-02-15 18:45:29 -08001581 final int uid = curOp.uidState.uid;
1582 callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
Dianne Hackborn607b4142013-08-02 18:10:10 -07001583 mOpModeWatchers.get(curOp.op));
Svet Ganovaf189e32019-02-15 18:45:29 -08001584 callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
Dianne Hackborn607b4142013-08-02 18:10:10 -07001585 mPackageModeWatchers.get(packageName));
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07001586 if (!curOp.hasAnyTime()) {
Dianne Hackborn7f09ec32013-08-07 15:36:08 -07001587 pkgOps.removeAt(j);
1588 }
Dianne Hackborn607b4142013-08-02 18:10:10 -07001589 }
1590 }
Dianne Hackborn7f09ec32013-08-07 15:36:08 -07001591 if (pkgOps.size() == 0) {
1592 it.remove();
1593 }
1594 }
Svet Ganov2af57082015-07-30 08:44:20 -07001595 if (uidState.isDefault()) {
1596 mUidStates.remove(uidState.uid);
Dianne Hackborn607b4142013-08-02 18:10:10 -07001597 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07001598 if (uidChanged) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07001599 uidState.evalForegroundOps(mOpModeWatchers);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07001600 }
Dianne Hackborn607b4142013-08-02 18:10:10 -07001601 }
Svet Ganov2af57082015-07-30 08:44:20 -07001602
Dianne Hackborn607b4142013-08-02 18:10:10 -07001603 if (changed) {
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -08001604 scheduleFastWriteLocked();
Dianne Hackborn607b4142013-08-02 18:10:10 -07001605 }
1606 }
1607 if (callbacks != null) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001608 for (Map.Entry<ModeCallback, ArrayList<ChangeRec>> ent : callbacks.entrySet()) {
1609 ModeCallback cb = ent.getKey();
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001610 ArrayList<ChangeRec> reports = ent.getValue();
Dianne Hackborn607b4142013-08-02 18:10:10 -07001611 for (int i=0; i<reports.size(); i++) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001612 ChangeRec rep = reports.get(i);
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001613 mHandler.sendMessage(PooledLambda.obtainMessage(
1614 AppOpsService::notifyOpChanged,
1615 this, cb, rep.op, rep.uid, rep.pkg));
Dianne Hackborn607b4142013-08-02 18:10:10 -07001616 }
1617 }
1618 }
1619 }
1620
Dianne Hackborn65a4f252018-05-08 17:30:48 -07001621 private void evalAllForegroundOpsLocked() {
1622 for (int uidi = mUidStates.size() - 1; uidi >= 0; uidi--) {
1623 final UidState uidState = mUidStates.valueAt(uidi);
1624 if (uidState.foregroundOps != null) {
1625 uidState.evalForegroundOps(mOpModeWatchers);
1626 }
1627 }
1628 }
1629
Dianne Hackbornc2293022013-02-06 23:14:49 -08001630 @Override
1631 public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07001632 startWatchingModeWithFlags(op, packageName, 0, callback);
1633 }
1634
1635 @Override
1636 public void startWatchingModeWithFlags(int op, String packageName, int flags,
1637 IAppOpsCallback callback) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001638 int watchedUid = -1;
Dianne Hackborn3b563fc2018-04-16 17:17:14 -07001639 final int callingUid = Binder.getCallingUid();
1640 final int callingPid = Binder.getCallingPid();
Dianne Hackborn5376edd2018-06-05 13:21:16 -07001641 // TODO: should have a privileged permission to protect this.
1642 // Also, if the caller has requested WATCH_FOREGROUND_CHANGES, should we require
1643 // the USAGE_STATS permission since this can provide information about when an
1644 // app is in the foreground?
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001645 Preconditions.checkArgumentInRange(op, AppOpsManager.OP_NONE,
1646 AppOpsManager._NUM_OP - 1, "Invalid op code: " + op);
Svetoslav Ganov8de59712015-12-09 18:25:13 -08001647 if (callback == null) {
1648 return;
1649 }
Dianne Hackbornc2293022013-02-06 23:14:49 -08001650 synchronized (this) {
Svet Ganov2af57082015-07-30 08:44:20 -07001651 op = (op != AppOpsManager.OP_NONE) ? AppOpsManager.opToSwitch(op) : op;
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001652 ModeCallback cb = mModeWatchers.get(callback.asBinder());
Dianne Hackbornc2293022013-02-06 23:14:49 -08001653 if (cb == null) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07001654 cb = new ModeCallback(callback, watchedUid, flags, callingUid, callingPid);
Dianne Hackbornc2293022013-02-06 23:14:49 -08001655 mModeWatchers.put(callback.asBinder(), cb);
1656 }
1657 if (op != AppOpsManager.OP_NONE) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001658 ArraySet<ModeCallback> cbs = mOpModeWatchers.get(op);
Dianne Hackbornc2293022013-02-06 23:14:49 -08001659 if (cbs == null) {
Dianne Hackborn68d76552017-02-27 15:32:03 -08001660 cbs = new ArraySet<>();
Dianne Hackbornc2293022013-02-06 23:14:49 -08001661 mOpModeWatchers.put(op, cbs);
1662 }
1663 cbs.add(cb);
1664 }
1665 if (packageName != null) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001666 ArraySet<ModeCallback> cbs = mPackageModeWatchers.get(packageName);
Dianne Hackbornc2293022013-02-06 23:14:49 -08001667 if (cbs == null) {
Dianne Hackborn68d76552017-02-27 15:32:03 -08001668 cbs = new ArraySet<>();
Dianne Hackbornc2293022013-02-06 23:14:49 -08001669 mPackageModeWatchers.put(packageName, cbs);
1670 }
1671 cbs.add(cb);
1672 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07001673 evalAllForegroundOpsLocked();
Dianne Hackbornc2293022013-02-06 23:14:49 -08001674 }
1675 }
1676
1677 @Override
1678 public void stopWatchingMode(IAppOpsCallback callback) {
Svetoslav Ganov8de59712015-12-09 18:25:13 -08001679 if (callback == null) {
1680 return;
1681 }
Dianne Hackbornc2293022013-02-06 23:14:49 -08001682 synchronized (this) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001683 ModeCallback cb = mModeWatchers.remove(callback.asBinder());
Dianne Hackbornc2293022013-02-06 23:14:49 -08001684 if (cb != null) {
1685 cb.unlinkToDeath();
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001686 for (int i=mOpModeWatchers.size()-1; i>=0; i--) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001687 ArraySet<ModeCallback> cbs = mOpModeWatchers.valueAt(i);
Dianne Hackbornc2293022013-02-06 23:14:49 -08001688 cbs.remove(cb);
1689 if (cbs.size() <= 0) {
1690 mOpModeWatchers.removeAt(i);
1691 }
1692 }
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001693 for (int i=mPackageModeWatchers.size()-1; i>=0; i--) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001694 ArraySet<ModeCallback> cbs = mPackageModeWatchers.valueAt(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001695 cbs.remove(cb);
1696 if (cbs.size() <= 0) {
1697 mPackageModeWatchers.removeAt(i);
Dianne Hackbornc2293022013-02-06 23:14:49 -08001698 }
1699 }
1700 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07001701 evalAllForegroundOpsLocked();
Dianne Hackbornc2293022013-02-06 23:14:49 -08001702 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001703 }
1704
1705 @Override
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001706 public IBinder getToken(IBinder clientToken) {
1707 synchronized (this) {
1708 ClientState cs = mClients.get(clientToken);
1709 if (cs == null) {
1710 cs = new ClientState(clientToken);
1711 mClients.put(clientToken, cs);
1712 }
1713 return cs;
1714 }
1715 }
1716
Svet Ganovd873ae62018-06-25 16:39:23 -07001717 public CheckOpsDelegate getAppOpsServiceDelegate() {
1718 synchronized (this) {
1719 return mCheckOpsDelegate;
1720 }
1721 }
1722
1723 public void setAppOpsServiceDelegate(CheckOpsDelegate delegate) {
1724 synchronized (this) {
1725 mCheckOpsDelegate = delegate;
1726 }
1727 }
1728
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001729 @Override
Svet Ganov9d528a12018-12-19 17:23:11 -08001730 public int checkOperationRaw(int code, int uid, String packageName) {
1731 return checkOperationInternal(code, uid, packageName, true /*raw*/);
1732 }
1733
1734 @Override
Dianne Hackborn35654b62013-01-14 17:38:02 -08001735 public int checkOperation(int code, int uid, String packageName) {
Svet Ganov9d528a12018-12-19 17:23:11 -08001736 return checkOperationInternal(code, uid, packageName, false /*raw*/);
1737 }
1738
1739 private int checkOperationInternal(int code, int uid, String packageName, boolean raw) {
Svet Ganovd873ae62018-06-25 16:39:23 -07001740 final CheckOpsDelegate delegate;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001741 synchronized (this) {
Svet Ganovd873ae62018-06-25 16:39:23 -07001742 delegate = mCheckOpsDelegate;
1743 }
Todd Kennedy556efba2018-11-15 07:43:55 -08001744 if (delegate == null) {
Svet Ganov9d528a12018-12-19 17:23:11 -08001745 return checkOperationImpl(code, uid, packageName, raw);
Todd Kennedy556efba2018-11-15 07:43:55 -08001746 }
Svet Ganov9d528a12018-12-19 17:23:11 -08001747 return delegate.checkOperation(code, uid, packageName, raw,
Svet Ganovd873ae62018-06-25 16:39:23 -07001748 AppOpsService.this::checkOperationImpl);
1749 }
1750
Svet Ganov9d528a12018-12-19 17:23:11 -08001751 private int checkOperationImpl(int code, int uid, String packageName,
1752 boolean raw) {
Todd Kennedy556efba2018-11-15 07:43:55 -08001753 verifyIncomingUid(uid);
1754 verifyIncomingOp(code);
1755 String resolvedPackageName = resolvePackageName(uid, packageName);
1756 if (resolvedPackageName == null) {
1757 return AppOpsManager.MODE_IGNORED;
1758 }
Svet Ganov9d528a12018-12-19 17:23:11 -08001759 return checkOperationUnchecked(code, uid, resolvedPackageName, raw);
Todd Kennedy556efba2018-11-15 07:43:55 -08001760 }
1761
Philip P. Moltmann724150d2019-03-11 17:01:05 -07001762 /**
1763 * @see #checkOperationUnchecked(int, int, String, boolean, boolean)
1764 */
1765 private @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName,
1766 boolean raw) {
1767 return checkOperationUnchecked(code, uid, packageName, raw, true);
1768 }
1769
1770 /**
1771 * Get the mode of an app-op.
1772 *
1773 * @param code The code of the op
1774 * @param uid The uid of the package the op belongs to
1775 * @param packageName The package the op belongs to
1776 * @param raw If the raw state of eval-ed state should be checked.
1777 * @param verify If the code should check the package belongs to the uid
1778 *
1779 * @return The mode of the op
1780 */
1781 private @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName,
1782 boolean raw, boolean verify) {
Svet Ganovd873ae62018-06-25 16:39:23 -07001783 synchronized (this) {
Philip P. Moltmann724150d2019-03-11 17:01:05 -07001784 if (verify) {
1785 checkPackage(uid, packageName);
1786 }
Todd Kennedy556efba2018-11-15 07:43:55 -08001787 if (isOpRestrictedLocked(uid, code, packageName)) {
Jason Monk62062992014-05-06 09:55:28 -04001788 return AppOpsManager.MODE_IGNORED;
1789 }
Svet Ganov2af57082015-07-30 08:44:20 -07001790 code = AppOpsManager.opToSwitch(code);
1791 UidState uidState = getUidStateLocked(uid, false);
Svet Ganovee438d42017-01-19 18:04:38 -08001792 if (uidState != null && uidState.opModes != null
1793 && uidState.opModes.indexOfKey(code) >= 0) {
Svet Ganov9d528a12018-12-19 17:23:11 -08001794 final int rawMode = uidState.opModes.get(code);
Svet Ganovaf189e32019-02-15 18:45:29 -08001795 return raw ? rawMode : uidState.evalMode(code, rawMode);
Svet Ganov2af57082015-07-30 08:44:20 -07001796 }
Philip P. Moltmann724150d2019-03-11 17:01:05 -07001797 Op op = getOpLocked(code, uid, packageName, false, verify, false);
Dianne Hackborn35654b62013-01-14 17:38:02 -08001798 if (op == null) {
David Braunf5d83192013-09-16 13:43:51 -07001799 return AppOpsManager.opToDefaultMode(code);
Dianne Hackborn35654b62013-01-14 17:38:02 -08001800 }
Svet Ganovaf189e32019-02-15 18:45:29 -08001801 return raw ? op.mode : op.evalMode();
Dianne Hackborn35654b62013-01-14 17:38:02 -08001802 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001803 }
1804
1805 @Override
John Spurlock7b414672014-07-18 13:02:39 -04001806 public int checkAudioOperation(int code, int usage, int uid, String packageName) {
Svet Ganovd873ae62018-06-25 16:39:23 -07001807 final CheckOpsDelegate delegate;
John Spurlock1af30c72014-03-10 08:33:35 -04001808 synchronized (this) {
Svet Ganovd873ae62018-06-25 16:39:23 -07001809 delegate = mCheckOpsDelegate;
1810 }
Todd Kennedy556efba2018-11-15 07:43:55 -08001811 if (delegate == null) {
1812 return checkAudioOperationImpl(code, usage, uid, packageName);
1813 }
Svet Ganovd873ae62018-06-25 16:39:23 -07001814 return delegate.checkAudioOperation(code, usage, uid, packageName,
1815 AppOpsService.this::checkAudioOperationImpl);
1816 }
1817
1818 private int checkAudioOperationImpl(int code, int usage, int uid, String packageName) {
Todd Kennedy556efba2018-11-15 07:43:55 -08001819 boolean suspended;
1820 try {
1821 suspended = isPackageSuspendedForUser(packageName, uid);
1822 } catch (IllegalArgumentException ex) {
1823 // Package not found.
1824 suspended = false;
1825 }
1826
1827 if (suspended) {
1828 Slog.i(TAG, "Audio disabled for suspended package=" + packageName
1829 + " for uid=" + uid);
1830 return AppOpsManager.MODE_IGNORED;
1831 }
1832
Svet Ganovd873ae62018-06-25 16:39:23 -07001833 synchronized (this) {
John Spurlock7b414672014-07-18 13:02:39 -04001834 final int mode = checkRestrictionLocked(code, usage, uid, packageName);
John Spurlock1af30c72014-03-10 08:33:35 -04001835 if (mode != AppOpsManager.MODE_ALLOWED) {
1836 return mode;
1837 }
1838 }
1839 return checkOperation(code, uid, packageName);
1840 }
1841
Andrei Stingaceanu355b2322016-02-12 16:43:51 +00001842 private boolean isPackageSuspendedForUser(String pkg, int uid) {
Andrei Stingaceanu2bc2feb2016-02-11 16:23:49 +00001843 try {
Andrei Stingaceanu355b2322016-02-12 16:43:51 +00001844 return AppGlobals.getPackageManager().isPackageSuspendedForUser(
1845 pkg, UserHandle.getUserId(uid));
Andrei Stingaceanu2bc2feb2016-02-11 16:23:49 +00001846 } catch (RemoteException re) {
1847 throw new SecurityException("Could not talk to package manager service");
1848 }
Andrei Stingaceanu2bc2feb2016-02-11 16:23:49 +00001849 }
1850
John Spurlock7b414672014-07-18 13:02:39 -04001851 private int checkRestrictionLocked(int code, int usage, int uid, String packageName) {
1852 final SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code);
1853 if (usageRestrictions != null) {
1854 final Restriction r = usageRestrictions.get(usage);
John Spurlock1af30c72014-03-10 08:33:35 -04001855 if (r != null && !r.exceptionPackages.contains(packageName)) {
1856 return r.mode;
1857 }
1858 }
1859 return AppOpsManager.MODE_ALLOWED;
1860 }
1861
1862 @Override
John Spurlock7b414672014-07-18 13:02:39 -04001863 public void setAudioRestriction(int code, int usage, int uid, int mode,
John Spurlock1af30c72014-03-10 08:33:35 -04001864 String[] exceptionPackages) {
Dianne Hackbornd5254412018-05-11 18:02:58 -07001865 enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
John Spurlock1af30c72014-03-10 08:33:35 -04001866 verifyIncomingUid(uid);
1867 verifyIncomingOp(code);
1868 synchronized (this) {
John Spurlock7b414672014-07-18 13:02:39 -04001869 SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code);
1870 if (usageRestrictions == null) {
1871 usageRestrictions = new SparseArray<Restriction>();
1872 mAudioRestrictions.put(code, usageRestrictions);
John Spurlock1af30c72014-03-10 08:33:35 -04001873 }
John Spurlock7b414672014-07-18 13:02:39 -04001874 usageRestrictions.remove(usage);
John Spurlock1af30c72014-03-10 08:33:35 -04001875 if (mode != AppOpsManager.MODE_ALLOWED) {
1876 final Restriction r = new Restriction();
1877 r.mode = mode;
1878 if (exceptionPackages != null) {
1879 final int N = exceptionPackages.length;
1880 r.exceptionPackages = new ArraySet<String>(N);
1881 for (int i = 0; i < N; i++) {
1882 final String pkg = exceptionPackages[i];
1883 if (pkg != null) {
1884 r.exceptionPackages.add(pkg.trim());
1885 }
1886 }
1887 }
John Spurlock7b414672014-07-18 13:02:39 -04001888 usageRestrictions.put(usage, r);
John Spurlock1af30c72014-03-10 08:33:35 -04001889 }
1890 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001891
1892 mHandler.sendMessage(PooledLambda.obtainMessage(
Svet Ganov3a95f832018-03-23 17:44:30 -07001893 AppOpsService::notifyWatchersOfChange, this, code, UID_ANY));
John Spurlock1af30c72014-03-10 08:33:35 -04001894 }
1895
1896 @Override
Jeff Sharkey911d7f42013-09-05 18:11:45 -07001897 public int checkPackage(int uid, String packageName) {
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00001898 Preconditions.checkNotNull(packageName);
Jeff Sharkey911d7f42013-09-05 18:11:45 -07001899 synchronized (this) {
Yohei Yukawaa965d652017-10-12 15:02:26 -07001900 Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
1901 true /* uidMismatchExpected */);
1902 if (ops != null) {
Jeff Sharkey911d7f42013-09-05 18:11:45 -07001903 return AppOpsManager.MODE_ALLOWED;
1904 } else {
1905 return AppOpsManager.MODE_ERRORED;
1906 }
1907 }
1908 }
1909
1910 @Override
Svet Ganovd873ae62018-06-25 16:39:23 -07001911 public int noteProxyOperation(int code, int proxyUid,
1912 String proxyPackageName, int proxiedUid, String proxiedPackageName) {
1913 verifyIncomingUid(proxyUid);
Svet Ganov99b60432015-06-27 13:15:22 -07001914 verifyIncomingOp(code);
Svet Ganovaf189e32019-02-15 18:45:29 -08001915
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00001916 String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
1917 if (resolveProxyPackageName == null) {
1918 return AppOpsManager.MODE_IGNORED;
1919 }
Svet Ganovaf189e32019-02-15 18:45:29 -08001920
1921 final boolean isProxyTrusted = mContext.checkPermission(
1922 Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
1923 == PackageManager.PERMISSION_GRANTED;
1924
1925 final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
1926 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00001927 final int proxyMode = noteOperationUnchecked(code, proxyUid,
Svet Ganovaf189e32019-02-15 18:45:29 -08001928 resolveProxyPackageName, Process.INVALID_UID, null, proxyFlags);
Svet Ganov99b60432015-06-27 13:15:22 -07001929 if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) {
1930 return proxyMode;
1931 }
Svet Ganovaf189e32019-02-15 18:45:29 -08001932
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00001933 String resolveProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName);
1934 if (resolveProxiedPackageName == null) {
1935 return AppOpsManager.MODE_IGNORED;
1936 }
Svet Ganovaf189e32019-02-15 18:45:29 -08001937 final int proxiedFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXIED
1938 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED;
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00001939 return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName,
Svet Ganovaf189e32019-02-15 18:45:29 -08001940 proxyUid, resolveProxyPackageName, proxiedFlags);
Svet Ganov99b60432015-06-27 13:15:22 -07001941 }
1942
1943 @Override
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001944 public int noteOperation(int code, int uid, String packageName) {
Svet Ganovd873ae62018-06-25 16:39:23 -07001945 final CheckOpsDelegate delegate;
1946 synchronized (this) {
Svet Ganovd873ae62018-06-25 16:39:23 -07001947 delegate = mCheckOpsDelegate;
1948 }
Todd Kennedy556efba2018-11-15 07:43:55 -08001949 if (delegate == null) {
1950 return noteOperationImpl(code, uid, packageName);
1951 }
Svet Ganovd873ae62018-06-25 16:39:23 -07001952 return delegate.noteOperation(code, uid, packageName,
1953 AppOpsService.this::noteOperationImpl);
1954 }
1955
1956 private int noteOperationImpl(int code, int uid, String packageName) {
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001957 verifyIncomingUid(uid);
Dianne Hackborn961321f2013-02-05 17:22:41 -08001958 verifyIncomingOp(code);
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00001959 String resolvedPackageName = resolvePackageName(uid, packageName);
1960 if (resolvedPackageName == null) {
1961 return AppOpsManager.MODE_IGNORED;
1962 }
Svet Ganovaf189e32019-02-15 18:45:29 -08001963 return noteOperationUnchecked(code, uid, resolvedPackageName, Process.INVALID_UID, null,
1964 AppOpsManager.OP_FLAG_SELF);
Svet Ganov99b60432015-06-27 13:15:22 -07001965 }
1966
1967 private int noteOperationUnchecked(int code, int uid, String packageName,
Svet Ganovaf189e32019-02-15 18:45:29 -08001968 int proxyUid, String proxyPackageName, @OpFlags int flags) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001969 synchronized (this) {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07001970 final Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
Yohei Yukawaa965d652017-10-12 15:02:26 -07001971 false /* uidMismatchExpected */);
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001972 if (ops == null) {
Svet Ganovb3d2ae22018-12-17 22:06:15 -08001973 scheduleOpNotedIfNeededLocked(code, uid, packageName,
1974 AppOpsManager.MODE_IGNORED);
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001975 if (DEBUG) Slog.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001976 + " package " + packageName);
Jeff Sharkey911d7f42013-09-05 18:11:45 -07001977 return AppOpsManager.MODE_ERRORED;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001978 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07001979 final Op op = getOpLocked(ops, code, true);
Svet Ganov442ed572016-08-17 17:29:43 -07001980 if (isOpRestrictedLocked(uid, code, packageName)) {
Svet Ganovb3d2ae22018-12-17 22:06:15 -08001981 scheduleOpNotedIfNeededLocked(code, uid, packageName,
1982 AppOpsManager.MODE_IGNORED);
Jason Monk62062992014-05-06 09:55:28 -04001983 return AppOpsManager.MODE_IGNORED;
1984 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07001985 final UidState uidState = ops.uidState;
Svet Ganovaf189e32019-02-15 18:45:29 -08001986 if (op.running) {
1987 final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes,
1988 op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001989 Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
Svet Ganovaf189e32019-02-15 18:45:29 -08001990 + " code " + code + " time=" + entry.getLastAccessTime(uidState.state,
1991 uidState.state, flags) + " duration=" + entry.getLastDuration(
1992 uidState.state, uidState.state, flags));
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001993 }
Svet Ganovaf189e32019-02-15 18:45:29 -08001994
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001995 final int switchCode = AppOpsManager.opToSwitch(code);
Svetoslav Ganov1984bba2016-04-05 13:39:25 -07001996 // If there is a non-default per UID policy (we set UID op mode only if
1997 // non-default) it takes over, otherwise use the per package policy.
1998 if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
Svet Ganovaf189e32019-02-15 18:45:29 -08001999 final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode));
Svet Ganov2af57082015-07-30 08:44:20 -07002000 if (uidMode != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002001 if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
Svet Ganov2af57082015-07-30 08:44:20 -07002002 + switchCode + " (" + code + ") uid " + uid + " package "
2003 + packageName);
Svet Ganovaf189e32019-02-15 18:45:29 -08002004 op.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName,
2005 uidState.state, flags);
2006 mHistoricalRegistry.incrementOpRejected(code, uid, packageName,
2007 uidState.state, flags);
Svet Ganovb3d2ae22018-12-17 22:06:15 -08002008 scheduleOpNotedIfNeededLocked(code, uid, packageName, uidMode);
Svet Ganov2af57082015-07-30 08:44:20 -07002009 return uidMode;
2010 }
Svetoslav Ganov1984bba2016-04-05 13:39:25 -07002011 } else {
2012 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
Svet Ganovaf189e32019-02-15 18:45:29 -08002013 final int mode = switchOp.evalMode();
2014 if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002015 if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + mode + " for code "
Svetoslav Ganov1984bba2016-04-05 13:39:25 -07002016 + switchCode + " (" + code + ") uid " + uid + " package "
2017 + packageName);
Svet Ganovaf189e32019-02-15 18:45:29 -08002018 op.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName,
2019 uidState.state, flags);
2020 mHistoricalRegistry.incrementOpRejected(code, uid, packageName,
2021 uidState.state, flags);
2022 scheduleOpNotedIfNeededLocked(code, uid, packageName, mode);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002023 return mode;
Svetoslav Ganov1984bba2016-04-05 13:39:25 -07002024 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002025 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002026 if (DEBUG) Slog.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002027 + " package " + packageName);
Svet Ganovaf189e32019-02-15 18:45:29 -08002028 op.accessed(System.currentTimeMillis(), proxyUid, proxyPackageName,
2029 uidState.state, flags);
Svet Ganov8455ba22019-01-02 13:05:56 -08002030 mHistoricalRegistry.incrementOpAccessedCount(op.op, uid, packageName,
Svet Ganovaf189e32019-02-15 18:45:29 -08002031 uidState.state, flags);
Svet Ganovb3d2ae22018-12-17 22:06:15 -08002032 scheduleOpNotedIfNeededLocked(code, uid, packageName,
2033 AppOpsManager.MODE_ALLOWED);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002034 return AppOpsManager.MODE_ALLOWED;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002035 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002036 }
2037
2038 @Override
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002039 public void startWatchingActive(int[] ops, IAppOpsActiveCallback callback) {
Svet Ganovf7b47252018-02-26 11:11:27 -08002040 int watchedUid = -1;
Dianne Hackborn3b563fc2018-04-16 17:17:14 -07002041 final int callingUid = Binder.getCallingUid();
2042 final int callingPid = Binder.getCallingPid();
Svet Ganovf7b47252018-02-26 11:11:27 -08002043 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS)
2044 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn3b563fc2018-04-16 17:17:14 -07002045 watchedUid = callingUid;
Svet Ganovf7b47252018-02-26 11:11:27 -08002046 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002047 if (ops != null) {
2048 Preconditions.checkArrayElementsInRange(ops, 0,
2049 AppOpsManager._NUM_OP - 1, "Invalid op code in: " + Arrays.toString(ops));
2050 }
2051 if (callback == null) {
2052 return;
2053 }
2054 synchronized (this) {
2055 SparseArray<ActiveCallback> callbacks = mActiveWatchers.get(callback.asBinder());
2056 if (callbacks == null) {
2057 callbacks = new SparseArray<>();
2058 mActiveWatchers.put(callback.asBinder(), callbacks);
2059 }
Dianne Hackborn3b563fc2018-04-16 17:17:14 -07002060 final ActiveCallback activeCallback = new ActiveCallback(callback, watchedUid,
2061 callingUid, callingPid);
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002062 for (int op : ops) {
2063 callbacks.put(op, activeCallback);
2064 }
2065 }
2066 }
2067
2068 @Override
2069 public void stopWatchingActive(IAppOpsActiveCallback callback) {
2070 if (callback == null) {
2071 return;
2072 }
2073 synchronized (this) {
2074 final SparseArray<ActiveCallback> activeCallbacks =
2075 mActiveWatchers.remove(callback.asBinder());
2076 if (activeCallbacks == null) {
2077 return;
2078 }
2079 final int callbackCount = activeCallbacks.size();
2080 for (int i = 0; i < callbackCount; i++) {
Svet Ganovb3d2ae22018-12-17 22:06:15 -08002081 activeCallbacks.valueAt(i).destroy();
2082 }
2083 }
2084 }
2085
2086 @Override
2087 public void startWatchingNoted(@NonNull int[] ops, @NonNull IAppOpsNotedCallback callback) {
2088 int watchedUid = Process.INVALID_UID;
2089 final int callingUid = Binder.getCallingUid();
2090 final int callingPid = Binder.getCallingPid();
2091 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS)
2092 != PackageManager.PERMISSION_GRANTED) {
2093 watchedUid = callingUid;
2094 }
2095 Preconditions.checkArgument(!ArrayUtils.isEmpty(ops), "Ops cannot be null or empty");
2096 Preconditions.checkArrayElementsInRange(ops, 0, AppOpsManager._NUM_OP - 1,
2097 "Invalid op code in: " + Arrays.toString(ops));
2098 Preconditions.checkNotNull(callback, "Callback cannot be null");
2099 synchronized (this) {
2100 SparseArray<NotedCallback> callbacks = mNotedWatchers.get(callback.asBinder());
2101 if (callbacks == null) {
2102 callbacks = new SparseArray<>();
2103 mNotedWatchers.put(callback.asBinder(), callbacks);
2104 }
2105 final NotedCallback notedCallback = new NotedCallback(callback, watchedUid,
2106 callingUid, callingPid);
2107 for (int op : ops) {
2108 callbacks.put(op, notedCallback);
2109 }
2110 }
2111 }
2112
2113 @Override
2114 public void stopWatchingNoted(IAppOpsNotedCallback callback) {
2115 Preconditions.checkNotNull(callback, "Callback cannot be null");
2116 synchronized (this) {
2117 final SparseArray<NotedCallback> notedCallbacks =
2118 mNotedWatchers.remove(callback.asBinder());
2119 if (notedCallbacks == null) {
2120 return;
2121 }
2122 final int callbackCount = notedCallbacks.size();
2123 for (int i = 0; i < callbackCount; i++) {
2124 notedCallbacks.valueAt(i).destroy();
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002125 }
2126 }
2127 }
2128
2129 @Override
Svet Ganovf7b47252018-02-26 11:11:27 -08002130 public int startOperation(IBinder token, int code, int uid, String packageName,
2131 boolean startIfModeDefault) {
Dianne Hackbornf265ea92013-01-31 15:00:51 -08002132 verifyIncomingUid(uid);
Dianne Hackborn961321f2013-02-05 17:22:41 -08002133 verifyIncomingOp(code);
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00002134 String resolvedPackageName = resolvePackageName(uid, packageName);
2135 if (resolvedPackageName == null) {
2136 return AppOpsManager.MODE_IGNORED;
2137 }
Dianne Hackborne98f5db2013-07-17 17:23:25 -07002138 ClientState client = (ClientState)token;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002139 synchronized (this) {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002140 final Ops ops = getOpsRawLocked(uid, resolvedPackageName, true /* edit */,
Yohei Yukawaa965d652017-10-12 15:02:26 -07002141 false /* uidMismatchExpected */);
Dianne Hackbornf265ea92013-01-31 15:00:51 -08002142 if (ops == null) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002143 if (DEBUG) Slog.d(TAG, "startOperation: no op for code " + code + " uid " + uid
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00002144 + " package " + resolvedPackageName);
Jeff Sharkey911d7f42013-09-05 18:11:45 -07002145 return AppOpsManager.MODE_ERRORED;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002146 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002147 final Op op = getOpLocked(ops, code, true);
Svet Ganov442ed572016-08-17 17:29:43 -07002148 if (isOpRestrictedLocked(uid, code, resolvedPackageName)) {
Jason Monk62062992014-05-06 09:55:28 -04002149 return AppOpsManager.MODE_IGNORED;
2150 }
Dianne Hackbornf265ea92013-01-31 15:00:51 -08002151 final int switchCode = AppOpsManager.opToSwitch(code);
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002152 final UidState uidState = ops.uidState;
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002153 // If there is a non-default per UID policy (we set UID op mode only if
2154 // non-default) it takes over, otherwise use the per package policy.
Svet Ganovaf189e32019-02-15 18:45:29 -08002155 final int opCode = op.op;
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002156 if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
Svet Ganovaf189e32019-02-15 18:45:29 -08002157 final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode));
Svet Ganovf7b47252018-02-26 11:11:27 -08002158 if (uidMode != AppOpsManager.MODE_ALLOWED
2159 && (!startIfModeDefault || uidMode != AppOpsManager.MODE_DEFAULT)) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002160 if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
Svet Ganov2af57082015-07-30 08:44:20 -07002161 + switchCode + " (" + code + ") uid " + uid + " package "
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00002162 + resolvedPackageName);
Svet Ganovaf189e32019-02-15 18:45:29 -08002163 // We don't support proxy long running ops (start/stop)
2164 op.rejected(System.currentTimeMillis(), -1 /*proxyUid*/,
2165 null /*proxyPackage*/, uidState.state, AppOpsManager.OP_FLAG_SELF);
2166 mHistoricalRegistry.incrementOpRejected(opCode, uid, packageName,
2167 uidState.state, AppOpsManager.OP_FLAG_SELF);
Svet Ganov2af57082015-07-30 08:44:20 -07002168 return uidMode;
2169 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002170 } else {
2171 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
Svet Ganovaf189e32019-02-15 18:45:29 -08002172 final int mode = switchOp.evalMode();
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002173 if (mode != AppOpsManager.MODE_ALLOWED
2174 && (!startIfModeDefault || mode != AppOpsManager.MODE_DEFAULT)) {
2175 if (DEBUG) Slog.d(TAG, "startOperation: reject #" + mode + " for code "
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002176 + switchCode + " (" + code + ") uid " + uid + " package "
2177 + resolvedPackageName);
Svet Ganovaf189e32019-02-15 18:45:29 -08002178 // We don't support proxy long running ops (start/stop)
2179 op.rejected(System.currentTimeMillis(), -1 /*proxyUid*/,
2180 null /*proxyPackage*/, uidState.state, AppOpsManager.OP_FLAG_SELF);
2181 mHistoricalRegistry.incrementOpRejected(opCode, uid, packageName,
2182 uidState.state, AppOpsManager.OP_FLAG_SELF);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002183 return mode;
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002184 }
Svet Ganov2af57082015-07-30 08:44:20 -07002185 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002186 if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00002187 + " package " + resolvedPackageName);
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002188 if (op.startNesting == 0) {
2189 op.startRealtime = SystemClock.elapsedRealtime();
Svet Ganovaf189e32019-02-15 18:45:29 -08002190 // We don't support proxy long running ops (start/stop)
2191 op.started(System.currentTimeMillis(), uidState.state,
2192 AppOpsManager.OP_FLAG_SELF);
2193 mHistoricalRegistry.incrementOpAccessedCount(opCode, uid, packageName,
2194 uidState.state, AppOpsManager.OP_FLAG_SELF);
2195
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002196 scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, true);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002197 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002198 op.startNesting++;
2199 uidState.startNesting++;
Dianne Hackborne98f5db2013-07-17 17:23:25 -07002200 if (client.mStartedOps != null) {
2201 client.mStartedOps.add(op);
2202 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002203 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002204
2205 return AppOpsManager.MODE_ALLOWED;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002206 }
2207
2208 @Override
Dianne Hackborne98f5db2013-07-17 17:23:25 -07002209 public void finishOperation(IBinder token, int code, int uid, String packageName) {
Dianne Hackbornf265ea92013-01-31 15:00:51 -08002210 verifyIncomingUid(uid);
Dianne Hackborn961321f2013-02-05 17:22:41 -08002211 verifyIncomingOp(code);
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00002212 String resolvedPackageName = resolvePackageName(uid, packageName);
2213 if (resolvedPackageName == null) {
2214 return;
2215 }
2216 if (!(token instanceof ClientState)) {
2217 return;
2218 }
2219 ClientState client = (ClientState) token;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002220 synchronized (this) {
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002221 Op op = getOpLocked(code, uid, resolvedPackageName, true, true, false);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002222 if (op == null) {
2223 return;
2224 }
Svet Ganovf7b47252018-02-26 11:11:27 -08002225 if (!client.mStartedOps.remove(op)) {
Svet Ganovf5d5af12018-03-18 11:51:17 -07002226 // We finish ops when packages get removed to guarantee no dangling
2227 // started ops. However, some part of the system may asynchronously
2228 // finish ops for an already gone package. Hence, finishing an op
2229 // for a non existing package is fine and we don't log as a wtf.
2230 final long identity = Binder.clearCallingIdentity();
2231 try {
2232 if (LocalServices.getService(PackageManagerInternal.class).getPackageUid(
2233 resolvedPackageName, 0, UserHandle.getUserId(uid)) < 0) {
2234 Slog.i(TAG, "Finishing op=" + AppOpsManager.opToName(code)
2235 + " for non-existing package=" + resolvedPackageName
2236 + " in uid=" + uid);
2237 return;
2238 }
2239 } finally {
2240 Binder.restoreCallingIdentity(identity);
2241 }
Svet Ganovaf189e32019-02-15 18:45:29 -08002242 Slog.wtf(TAG, "Operation not started: uid=" + op.uidState.uid + " pkg="
Svet Ganovf5d5af12018-03-18 11:51:17 -07002243 + op.packageName + " op=" + AppOpsManager.opToName(op.op));
Svet Ganov31d83ae2018-03-15 10:45:56 -07002244 return;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002245 }
Svet Ganova7a0db62018-02-27 20:08:01 -08002246 finishOperationLocked(op, /*finishNested*/ false);
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002247 if (op.startNesting <= 0) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002248 scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, false);
2249 }
2250 }
2251 }
2252
2253 private void scheduleOpActiveChangedIfNeededLocked(int code, int uid, String packageName,
2254 boolean active) {
2255 ArraySet<ActiveCallback> dispatchedCallbacks = null;
2256 final int callbackListCount = mActiveWatchers.size();
2257 for (int i = 0; i < callbackListCount; i++) {
2258 final SparseArray<ActiveCallback> callbacks = mActiveWatchers.valueAt(i);
2259 ActiveCallback callback = callbacks.get(code);
2260 if (callback != null) {
Dianne Hackborn3b563fc2018-04-16 17:17:14 -07002261 if (callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) {
Svet Ganovf7b47252018-02-26 11:11:27 -08002262 continue;
2263 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002264 if (dispatchedCallbacks == null) {
2265 dispatchedCallbacks = new ArraySet<>();
2266 }
2267 dispatchedCallbacks.add(callback);
2268 }
2269 }
2270 if (dispatchedCallbacks == null) {
2271 return;
2272 }
2273 mHandler.sendMessage(PooledLambda.obtainMessage(
2274 AppOpsService::notifyOpActiveChanged,
2275 this, dispatchedCallbacks, code, uid, packageName, active));
2276 }
2277
2278 private void notifyOpActiveChanged(ArraySet<ActiveCallback> callbacks,
2279 int code, int uid, String packageName, boolean active) {
2280 // There are components watching for mode changes such as window manager
2281 // and location manager which are in our process. The callbacks in these
2282 // components may require permissions our remote caller does not have.
2283 final long identity = Binder.clearCallingIdentity();
2284 try {
2285 final int callbackCount = callbacks.size();
2286 for (int i = 0; i < callbackCount; i++) {
2287 final ActiveCallback callback = callbacks.valueAt(i);
2288 try {
2289 callback.mCallback.opActiveChanged(code, uid, packageName, active);
2290 } catch (RemoteException e) {
2291 /* do nothing */
2292 }
2293 }
2294 } finally {
2295 Binder.restoreCallingIdentity(identity);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07002296 }
2297 }
2298
Svet Ganovb3d2ae22018-12-17 22:06:15 -08002299 private void scheduleOpNotedIfNeededLocked(int code, int uid, String packageName,
2300 int result) {
2301 ArraySet<NotedCallback> dispatchedCallbacks = null;
2302 final int callbackListCount = mNotedWatchers.size();
2303 for (int i = 0; i < callbackListCount; i++) {
2304 final SparseArray<NotedCallback> callbacks = mNotedWatchers.valueAt(i);
2305 final NotedCallback callback = callbacks.get(code);
2306 if (callback != null) {
2307 if (callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) {
2308 continue;
2309 }
2310 if (dispatchedCallbacks == null) {
2311 dispatchedCallbacks = new ArraySet<>();
2312 }
2313 dispatchedCallbacks.add(callback);
2314 }
2315 }
2316 if (dispatchedCallbacks == null) {
2317 return;
2318 }
2319 mHandler.sendMessage(PooledLambda.obtainMessage(
2320 AppOpsService::notifyOpChecked,
2321 this, dispatchedCallbacks, code, uid, packageName, result));
2322 }
2323
2324 private void notifyOpChecked(ArraySet<NotedCallback> callbacks,
2325 int code, int uid, String packageName, int result) {
2326 // There are components watching for checks in our process. The callbacks in
2327 // these components may require permissions our remote caller does not have.
2328 final long identity = Binder.clearCallingIdentity();
2329 try {
2330 final int callbackCount = callbacks.size();
2331 for (int i = 0; i < callbackCount; i++) {
2332 final NotedCallback callback = callbacks.valueAt(i);
2333 try {
2334 callback.mCallback.opNoted(code, uid, packageName, result);
2335 } catch (RemoteException e) {
2336 /* do nothing */
2337 }
2338 }
2339 } finally {
2340 Binder.restoreCallingIdentity(identity);
2341 }
2342 }
2343
Svet Ganovb9d71a62015-04-30 10:38:13 -07002344 @Override
2345 public int permissionToOpCode(String permission) {
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00002346 if (permission == null) {
2347 return AppOpsManager.OP_NONE;
2348 }
Svet Ganovb9d71a62015-04-30 10:38:13 -07002349 return AppOpsManager.permissionToOpCode(permission);
2350 }
2351
Svet Ganova7a0db62018-02-27 20:08:01 -08002352 void finishOperationLocked(Op op, boolean finishNested) {
Svet Ganovaf189e32019-02-15 18:45:29 -08002353 final int opCode = op.op;
2354 final int uid = op.uidState.uid;
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002355 if (op.startNesting <= 1 || finishNested) {
2356 if (op.startNesting == 1 || finishNested) {
Svet Ganovaf189e32019-02-15 18:45:29 -08002357 // We don't support proxy long running ops (start/stop)
2358 final long duration = SystemClock.elapsedRealtime() - op.startRealtime;
2359 op.finished(System.currentTimeMillis(), duration, op.uidState.state,
2360 AppOpsManager.OP_FLAG_SELF);
2361 mHistoricalRegistry.increaseOpAccessDuration(opCode, uid, op.packageName,
2362 op.uidState.state, AppOpsManager.OP_FLAG_SELF, duration);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07002363 } else {
Svet Ganovaf189e32019-02-15 18:45:29 -08002364 final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes,
2365 op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames);
2366 Slog.w(TAG, "Finishing op nesting under-run: uid " + uid + " pkg "
2367 + op.packageName + " code " + opCode + " time="
2368 + entry.getLastAccessTime(OP_FLAGS_ALL)
2369 + " duration=" + entry.getLastDuration(MAX_PRIORITY_UID_STATE,
2370 MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL) + " nesting=" + op.startNesting);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07002371 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002372 if (op.startNesting >= 1) {
2373 op.uidState.startNesting -= op.startNesting;
2374 }
2375 op.startNesting = 0;
Dianne Hackborne98f5db2013-07-17 17:23:25 -07002376 } else {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002377 op.startNesting--;
2378 op.uidState.startNesting--;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002379 }
2380 }
2381
Dianne Hackbornf265ea92013-01-31 15:00:51 -08002382 private void verifyIncomingUid(int uid) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002383 if (uid == Binder.getCallingUid()) {
Dianne Hackbornf265ea92013-01-31 15:00:51 -08002384 return;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002385 }
2386 if (Binder.getCallingPid() == Process.myPid()) {
Dianne Hackbornf265ea92013-01-31 15:00:51 -08002387 return;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002388 }
2389 mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
2390 Binder.getCallingPid(), Binder.getCallingUid(), null);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002391 }
2392
Dianne Hackborn961321f2013-02-05 17:22:41 -08002393 private void verifyIncomingOp(int op) {
2394 if (op >= 0 && op < AppOpsManager._NUM_OP) {
2395 return;
2396 }
2397 throw new IllegalArgumentException("Bad operation #" + op);
2398 }
2399
Philip P. Moltmann724150d2019-03-11 17:01:05 -07002400 private @Nullable UidState getUidStateLocked(int uid, boolean edit) {
Svet Ganov2af57082015-07-30 08:44:20 -07002401 UidState uidState = mUidStates.get(uid);
2402 if (uidState == null) {
2403 if (!edit) {
2404 return null;
2405 }
2406 uidState = new UidState(uid);
2407 mUidStates.put(uid, uidState);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002408 } else {
2409 if (uidState.pendingStateCommitTime != 0) {
Dianne Hackborn9fb93502018-06-18 12:29:44 -07002410 if (uidState.pendingStateCommitTime < mLastRealtime) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07002411 commitUidPendingStateLocked(uidState);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002412 } else {
Dianne Hackborn9fb93502018-06-18 12:29:44 -07002413 mLastRealtime = SystemClock.elapsedRealtime();
2414 if (uidState.pendingStateCommitTime < mLastRealtime) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07002415 commitUidPendingStateLocked(uidState);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002416 }
2417 }
2418 }
Svet Ganov2af57082015-07-30 08:44:20 -07002419 }
2420 return uidState;
2421 }
2422
Dianne Hackborn65a4f252018-05-08 17:30:48 -07002423 private void commitUidPendingStateLocked(UidState uidState) {
Svet Ganovaf189e32019-02-15 18:45:29 -08002424 final boolean lastForeground = uidState.state <= UID_STATE_MAX_LAST_NON_RESTRICTED;
2425 final boolean nowForeground = uidState.pendingState <= UID_STATE_MAX_LAST_NON_RESTRICTED;
Dianne Hackborne93ab412018-05-14 17:52:30 -07002426 if (uidState.hasForegroundWatchers && lastForeground != nowForeground) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07002427 for (int fgi = uidState.foregroundOps.size() - 1; fgi >= 0; fgi--) {
2428 if (!uidState.foregroundOps.valueAt(fgi)) {
2429 continue;
2430 }
2431 final int code = uidState.foregroundOps.keyAt(fgi);
Svet Ganovaf189e32019-02-15 18:45:29 -08002432 // For location ops we consider fg state only if the fg service
2433 // is of location type, for all other ops any fg service will do.
Wei Wang711eb662019-03-21 18:24:17 -07002434 final long firstUnrestrictedUidState = resolveFirstUnrestrictedUidState(code);
2435 final boolean resolvedLastFg = uidState.state <= firstUnrestrictedUidState;
2436 final boolean resolvedNowFg = uidState.pendingState <= firstUnrestrictedUidState;
2437 if (resolvedLastFg == resolvedNowFg) {
Svet Ganovaf189e32019-02-15 18:45:29 -08002438 continue;
2439 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07002440 final ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code);
2441 if (callbacks != null) {
2442 for (int cbi = callbacks.size() - 1; cbi >= 0; cbi--) {
2443 final ModeCallback callback = callbacks.valueAt(cbi);
2444 if ((callback.mFlags & AppOpsManager.WATCH_FOREGROUND_CHANGES) == 0
2445 || !callback.isWatchingUid(uidState.uid)) {
2446 continue;
2447 }
2448 boolean doAllPackages = uidState.opModes != null
Hai Zhang2b98fb32018-09-21 15:18:46 -07002449 && uidState.opModes.indexOfKey(code) >= 0
Dianne Hackborn65a4f252018-05-08 17:30:48 -07002450 && uidState.opModes.get(code) == AppOpsManager.MODE_FOREGROUND;
2451 if (uidState.pkgOps != null) {
2452 for (int pkgi = uidState.pkgOps.size() - 1; pkgi >= 0; pkgi--) {
2453 final Op op = uidState.pkgOps.valueAt(pkgi).get(code);
Svet Ganovaf189e32019-02-15 18:45:29 -08002454 if (op == null) {
2455 continue;
2456 }
2457 if (doAllPackages || op.mode == AppOpsManager.MODE_FOREGROUND) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07002458 mHandler.sendMessage(PooledLambda.obtainMessage(
2459 AppOpsService::notifyOpChanged,
2460 this, callback, code, uidState.uid,
2461 uidState.pkgOps.keyAt(pkgi)));
2462 }
2463 }
2464 }
2465 }
2466 }
2467 }
2468 }
Wei Wang711eb662019-03-21 18:24:17 -07002469 uidState.state = uidState.pendingState;
2470 uidState.pendingStateCommitTime = 0;
Dianne Hackborn65a4f252018-05-08 17:30:48 -07002471 }
2472
Yohei Yukawaa965d652017-10-12 15:02:26 -07002473 private Ops getOpsRawLocked(int uid, String packageName, boolean edit,
2474 boolean uidMismatchExpected) {
Svet Ganov2af57082015-07-30 08:44:20 -07002475 UidState uidState = getUidStateLocked(uid, edit);
2476 if (uidState == null) {
2477 return null;
2478 }
2479
2480 if (uidState.pkgOps == null) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08002481 if (!edit) {
2482 return null;
2483 }
Svet Ganov2af57082015-07-30 08:44:20 -07002484 uidState.pkgOps = new ArrayMap<>();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002485 }
Svet Ganov2af57082015-07-30 08:44:20 -07002486
2487 Ops ops = uidState.pkgOps.get(packageName);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002488 if (ops == null) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08002489 if (!edit) {
2490 return null;
2491 }
Jason Monk1c7c3192014-06-26 12:52:18 -04002492 boolean isPrivileged = false;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002493 // This is the first time we have seen this package name under this uid,
2494 // so let's make sure it is valid.
Dianne Hackborn514074f2013-02-11 10:52:46 -08002495 if (uid != 0) {
2496 final long ident = Binder.clearCallingIdentity();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002497 try {
Dianne Hackborn514074f2013-02-11 10:52:46 -08002498 int pkgUid = -1;
2499 try {
Jason Monk1c7c3192014-06-26 12:52:18 -04002500 ApplicationInfo appInfo = ActivityThread.getPackageManager()
Jeff Sharkeycd654482016-01-08 17:42:11 -07002501 .getApplicationInfo(packageName,
Svet Ganovad0a49b2018-10-29 10:07:08 -07002502 PackageManager.MATCH_DIRECT_BOOT_AWARE
Svet Ganov8455ba22019-01-02 13:05:56 -08002503 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
Jeff Sharkeycd654482016-01-08 17:42:11 -07002504 UserHandle.getUserId(uid));
Jason Monk1c7c3192014-06-26 12:52:18 -04002505 if (appInfo != null) {
2506 pkgUid = appInfo.uid;
Alex Klyubinb9f8a522015-02-03 11:12:59 -08002507 isPrivileged = (appInfo.privateFlags
2508 & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
Jason Monk1c7c3192014-06-26 12:52:18 -04002509 } else {
Svet Ganov82f09bc2018-01-12 22:08:40 -08002510 pkgUid = resolveUid(packageName);
2511 if (pkgUid >= 0) {
Chien-Yu Chen75cade02016-01-11 10:56:21 -08002512 isPrivileged = false;
Jason Monk1c7c3192014-06-26 12:52:18 -04002513 }
Dianne Hackborn713df152013-05-17 11:27:57 -07002514 }
Jason Monk1c7c3192014-06-26 12:52:18 -04002515 } catch (RemoteException e) {
2516 Slog.w(TAG, "Could not contact PackageManager", e);
Dianne Hackborn514074f2013-02-11 10:52:46 -08002517 }
2518 if (pkgUid != uid) {
2519 // Oops! The package name is not valid for the uid they are calling
2520 // under. Abort.
Yohei Yukawaa965d652017-10-12 15:02:26 -07002521 if (!uidMismatchExpected) {
2522 RuntimeException ex = new RuntimeException("here");
2523 ex.fillInStackTrace();
2524 Slog.w(TAG, "Bad call: specified package " + packageName
2525 + " under uid " + uid + " but it is really " + pkgUid, ex);
2526 }
Dianne Hackborn514074f2013-02-11 10:52:46 -08002527 return null;
2528 }
2529 } finally {
2530 Binder.restoreCallingIdentity(ident);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002531 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002532 }
Svet Ganov2af57082015-07-30 08:44:20 -07002533 ops = new Ops(packageName, uidState, isPrivileged);
2534 uidState.pkgOps.put(packageName, ops);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002535 }
Dianne Hackborn72e39832013-01-18 18:36:09 -08002536 return ops;
2537 }
2538
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002539 /**
2540 * Get the state of all ops for a package, <b>don't verify that package belongs to uid</b>.
2541 *
2542 * <p>Usually callers should use {@link #getOpLocked} and not call this directly.
2543 *
2544 * @param uid The uid the of the package
2545 * @param packageName The package name for which to get the state for
2546 * @param edit Iff {@code true} create the {@link Ops} object if not yet created
2547 * @param isPrivileged Whether the package is privileged or not
2548 *
2549 * @return The {@link Ops state} of all ops for the package
2550 */
2551 private @Nullable Ops getOpsRawNoVerifyLocked(int uid, @NonNull String packageName,
2552 boolean edit, boolean isPrivileged) {
2553 UidState uidState = getUidStateLocked(uid, edit);
2554 if (uidState == null) {
2555 return null;
2556 }
2557
2558 if (uidState.pkgOps == null) {
2559 if (!edit) {
2560 return null;
2561 }
2562 uidState.pkgOps = new ArrayMap<>();
2563 }
2564
2565 Ops ops = uidState.pkgOps.get(packageName);
2566 if (ops == null) {
2567 if (!edit) {
2568 return null;
2569 }
2570 ops = new Ops(packageName, uidState, isPrivileged);
2571 uidState.pkgOps.put(packageName, ops);
2572 }
2573 return ops;
2574 }
2575
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002576 private void scheduleWriteLocked() {
2577 if (!mWriteScheduled) {
2578 mWriteScheduled = true;
2579 mHandler.postDelayed(mWriteRunner, WRITE_DELAY);
2580 }
2581 }
2582
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -08002583 private void scheduleFastWriteLocked() {
2584 if (!mFastWriteScheduled) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002585 mWriteScheduled = true;
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -08002586 mFastWriteScheduled = true;
2587 mHandler.removeCallbacks(mWriteRunner);
2588 mHandler.postDelayed(mWriteRunner, 10*1000);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002589 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002590 }
2591
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002592 /**
2593 * Get the state of an op for a uid.
2594 *
2595 * @param code The code of the op
2596 * @param uid The uid the of the package
2597 * @param packageName The package name for which to get the state for
2598 * @param edit Iff {@code true} create the {@link Op} object if not yet created
2599 * @param verifyUid Iff {@code true} check that the package belongs to the uid
2600 * @param isPrivileged Whether the package is privileged or not (only used if {@code verifyUid
2601 * == false})
2602 *
2603 * @return The {@link Op state} of the op
2604 */
2605 private @Nullable Op getOpLocked(int code, int uid, @NonNull String packageName, boolean edit,
2606 boolean verifyUid, boolean isPrivileged) {
2607 Ops ops;
2608
2609 if (verifyUid) {
2610 ops = getOpsRawLocked(uid, packageName, edit, false /* uidMismatchExpected */);
2611 } else {
2612 ops = getOpsRawNoVerifyLocked(uid, packageName, edit, isPrivileged);
2613 }
2614
Dianne Hackborn72e39832013-01-18 18:36:09 -08002615 if (ops == null) {
2616 return null;
2617 }
Dianne Hackbornf265ea92013-01-31 15:00:51 -08002618 return getOpLocked(ops, code, edit);
2619 }
2620
2621 private Op getOpLocked(Ops ops, int code, boolean edit) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002622 Op op = ops.get(code);
2623 if (op == null) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08002624 if (!edit) {
2625 return null;
2626 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002627 op = new Op(ops.uidState, ops.packageName, code);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002628 ops.put(code, op);
2629 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002630 if (edit) {
2631 scheduleWriteLocked();
Dianne Hackborn35654b62013-01-14 17:38:02 -08002632 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002633 return op;
2634 }
2635
Svet Ganov442ed572016-08-17 17:29:43 -07002636 private boolean isOpRestrictedLocked(int uid, int code, String packageName) {
Jason Monk62062992014-05-06 09:55:28 -04002637 int userHandle = UserHandle.getUserId(uid);
Svet Ganov9cea80cd2016-02-16 11:47:00 -08002638 final int restrictionSetCount = mOpUserRestrictions.size();
Ruben Brunk29931bc2016-03-11 00:24:26 -08002639
Svet Ganov9cea80cd2016-02-16 11:47:00 -08002640 for (int i = 0; i < restrictionSetCount; i++) {
Ruben Brunk29931bc2016-03-11 00:24:26 -08002641 // For each client, check that the given op is not restricted, or that the given
2642 // package is exempt from the restriction.
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07002643 ClientRestrictionState restrictionState = mOpUserRestrictions.valueAt(i);
Suprabh Shuklaffddadb2016-05-20 16:37:26 -07002644 if (restrictionState.hasRestriction(code, packageName, userHandle)) {
2645 if (AppOpsManager.opAllowSystemBypassRestriction(code)) {
2646 // If we are the system, bypass user restrictions for certain codes
2647 synchronized (this) {
Yohei Yukawaa965d652017-10-12 15:02:26 -07002648 Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
2649 false /* uidMismatchExpected */);
Suprabh Shuklaffddadb2016-05-20 16:37:26 -07002650 if ((ops != null) && ops.isPrivileged) {
2651 return false;
2652 }
Ruben Brunk32f0fa42016-03-11 19:07:07 -08002653 }
Ruben Brunk29931bc2016-03-11 00:24:26 -08002654 }
Svet Ganov9cea80cd2016-02-16 11:47:00 -08002655 return true;
Jason Monk1c7c3192014-06-26 12:52:18 -04002656 }
Jason Monk62062992014-05-06 09:55:28 -04002657 }
2658 return false;
2659 }
2660
Dianne Hackborn35654b62013-01-14 17:38:02 -08002661 void readState() {
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07002662 int oldVersion = NO_VERSION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08002663 synchronized (mFile) {
2664 synchronized (this) {
2665 FileInputStream stream;
2666 try {
2667 stream = mFile.openRead();
2668 } catch (FileNotFoundException e) {
2669 Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty");
2670 return;
2671 }
2672 boolean success = false;
Dianne Hackborn4d34bb82015-08-07 18:26:38 -07002673 mUidStates.clear();
Dianne Hackborn35654b62013-01-14 17:38:02 -08002674 try {
2675 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002676 parser.setInput(stream, StandardCharsets.UTF_8.name());
Dianne Hackborn35654b62013-01-14 17:38:02 -08002677 int type;
2678 while ((type = parser.next()) != XmlPullParser.START_TAG
2679 && type != XmlPullParser.END_DOCUMENT) {
2680 ;
2681 }
2682
2683 if (type != XmlPullParser.START_TAG) {
2684 throw new IllegalStateException("no start tag found");
2685 }
2686
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07002687 final String versionString = parser.getAttributeValue(null, "v");
2688 if (versionString != null) {
2689 oldVersion = Integer.parseInt(versionString);
2690 }
2691
Dianne Hackborn35654b62013-01-14 17:38:02 -08002692 int outerDepth = parser.getDepth();
2693 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2694 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2695 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2696 continue;
2697 }
2698
2699 String tagName = parser.getName();
2700 if (tagName.equals("pkg")) {
Dave Burke0997c5bd2013-08-02 20:25:02 +00002701 readPackage(parser);
Svetoslav215b44a2015-08-04 19:03:40 -07002702 } else if (tagName.equals("uid")) {
Svet Ganov2af57082015-07-30 08:44:20 -07002703 readUidOps(parser);
Dianne Hackborn35654b62013-01-14 17:38:02 -08002704 } else {
2705 Slog.w(TAG, "Unknown element under <app-ops>: "
2706 + parser.getName());
2707 XmlUtils.skipCurrentTag(parser);
2708 }
2709 }
2710 success = true;
2711 } catch (IllegalStateException e) {
2712 Slog.w(TAG, "Failed parsing " + e);
2713 } catch (NullPointerException e) {
2714 Slog.w(TAG, "Failed parsing " + e);
2715 } catch (NumberFormatException e) {
2716 Slog.w(TAG, "Failed parsing " + e);
2717 } catch (XmlPullParserException e) {
2718 Slog.w(TAG, "Failed parsing " + e);
2719 } catch (IOException e) {
2720 Slog.w(TAG, "Failed parsing " + e);
2721 } catch (IndexOutOfBoundsException e) {
2722 Slog.w(TAG, "Failed parsing " + e);
2723 } finally {
2724 if (!success) {
Svet Ganov2af57082015-07-30 08:44:20 -07002725 mUidStates.clear();
Dianne Hackborn35654b62013-01-14 17:38:02 -08002726 }
2727 try {
2728 stream.close();
2729 } catch (IOException e) {
2730 }
2731 }
2732 }
2733 }
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07002734 synchronized (this) {
2735 upgradeLocked(oldVersion);
2736 }
2737 }
2738
2739 private void upgradeRunAnyInBackgroundLocked() {
2740 for (int i = 0; i < mUidStates.size(); i++) {
2741 final UidState uidState = mUidStates.valueAt(i);
2742 if (uidState == null) {
2743 continue;
2744 }
2745 if (uidState.opModes != null) {
2746 final int idx = uidState.opModes.indexOfKey(AppOpsManager.OP_RUN_IN_BACKGROUND);
2747 if (idx >= 0) {
2748 uidState.opModes.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
Svet Ganovaf189e32019-02-15 18:45:29 -08002749 uidState.opModes.valueAt(idx));
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07002750 }
2751 }
2752 if (uidState.pkgOps == null) {
2753 continue;
2754 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002755 boolean changed = false;
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07002756 for (int j = 0; j < uidState.pkgOps.size(); j++) {
2757 Ops ops = uidState.pkgOps.valueAt(j);
2758 if (ops != null) {
2759 final Op op = ops.get(AppOpsManager.OP_RUN_IN_BACKGROUND);
2760 if (op != null && op.mode != AppOpsManager.opToDefaultMode(op.op)) {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002761 final Op copy = new Op(op.uidState, op.packageName,
Svet Ganovaf189e32019-02-15 18:45:29 -08002762 AppOpsManager.OP_RUN_ANY_IN_BACKGROUND);
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07002763 copy.mode = op.mode;
2764 ops.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, copy);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002765 changed = true;
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07002766 }
2767 }
2768 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002769 if (changed) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07002770 uidState.evalForegroundOps(mOpModeWatchers);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002771 }
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07002772 }
2773 }
2774
2775 private void upgradeLocked(int oldVersion) {
2776 if (oldVersion >= CURRENT_VERSION) {
2777 return;
2778 }
2779 Slog.d(TAG, "Upgrading app-ops xml from version " + oldVersion + " to " + CURRENT_VERSION);
2780 switch (oldVersion) {
2781 case NO_VERSION:
2782 upgradeRunAnyInBackgroundLocked();
2783 // fall through
2784 case 1:
2785 // for future upgrades
2786 }
2787 scheduleFastWriteLocked();
Dianne Hackborn35654b62013-01-14 17:38:02 -08002788 }
2789
Svet Ganovaf189e32019-02-15 18:45:29 -08002790 private void readUidOps(XmlPullParser parser) throws NumberFormatException,
Svet Ganov2af57082015-07-30 08:44:20 -07002791 XmlPullParserException, IOException {
2792 final int uid = Integer.parseInt(parser.getAttributeValue(null, "n"));
2793 int outerDepth = parser.getDepth();
2794 int type;
2795 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2796 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2797 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2798 continue;
2799 }
2800
2801 String tagName = parser.getName();
2802 if (tagName.equals("op")) {
2803 final int code = Integer.parseInt(parser.getAttributeValue(null, "n"));
2804 final int mode = Integer.parseInt(parser.getAttributeValue(null, "m"));
2805 UidState uidState = getUidStateLocked(uid, true);
2806 if (uidState.opModes == null) {
2807 uidState.opModes = new SparseIntArray();
2808 }
2809 uidState.opModes.put(code, mode);
2810 } else {
2811 Slog.w(TAG, "Unknown element under <uid-ops>: "
2812 + parser.getName());
2813 XmlUtils.skipCurrentTag(parser);
2814 }
2815 }
2816 }
2817
Svet Ganovaf189e32019-02-15 18:45:29 -08002818 private void readPackage(XmlPullParser parser)
2819 throws NumberFormatException, XmlPullParserException, IOException {
Dianne Hackborn35654b62013-01-14 17:38:02 -08002820 String pkgName = parser.getAttributeValue(null, "n");
2821 int outerDepth = parser.getDepth();
2822 int type;
2823 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2824 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2825 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2826 continue;
2827 }
2828
2829 String tagName = parser.getName();
2830 if (tagName.equals("uid")) {
Dave Burke0997c5bd2013-08-02 20:25:02 +00002831 readUid(parser, pkgName);
Dianne Hackborn35654b62013-01-14 17:38:02 -08002832 } else {
2833 Slog.w(TAG, "Unknown element under <pkg>: "
2834 + parser.getName());
2835 XmlUtils.skipCurrentTag(parser);
2836 }
2837 }
2838 }
2839
Svet Ganovaf189e32019-02-15 18:45:29 -08002840 private void readUid(XmlPullParser parser, String pkgName)
2841 throws NumberFormatException, XmlPullParserException, IOException {
Dianne Hackborn35654b62013-01-14 17:38:02 -08002842 int uid = Integer.parseInt(parser.getAttributeValue(null, "n"));
Svet Ganovaf189e32019-02-15 18:45:29 -08002843 final UidState uidState = getUidStateLocked(uid, true);
Jason Monk1c7c3192014-06-26 12:52:18 -04002844 String isPrivilegedString = parser.getAttributeValue(null, "p");
2845 boolean isPrivileged = false;
2846 if (isPrivilegedString == null) {
2847 try {
2848 IPackageManager packageManager = ActivityThread.getPackageManager();
2849 if (packageManager != null) {
2850 ApplicationInfo appInfo = ActivityThread.getPackageManager()
2851 .getApplicationInfo(pkgName, 0, UserHandle.getUserId(uid));
2852 if (appInfo != null) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08002853 isPrivileged = (appInfo.privateFlags
2854 & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
Jason Monk1c7c3192014-06-26 12:52:18 -04002855 }
2856 } else {
2857 // Could not load data, don't add to cache so it will be loaded later.
2858 return;
2859 }
2860 } catch (RemoteException e) {
2861 Slog.w(TAG, "Could not contact PackageManager", e);
2862 }
2863 } else {
2864 isPrivileged = Boolean.parseBoolean(isPrivilegedString);
2865 }
Dianne Hackborn35654b62013-01-14 17:38:02 -08002866 int outerDepth = parser.getDepth();
2867 int type;
2868 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2869 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2870 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2871 continue;
2872 }
Dianne Hackborn35654b62013-01-14 17:38:02 -08002873 String tagName = parser.getName();
2874 if (tagName.equals("op")) {
Svet Ganovaf189e32019-02-15 18:45:29 -08002875 readOp(parser, uidState, pkgName, isPrivileged);
Dianne Hackborn35654b62013-01-14 17:38:02 -08002876 } else {
2877 Slog.w(TAG, "Unknown element under <pkg>: "
2878 + parser.getName());
2879 XmlUtils.skipCurrentTag(parser);
2880 }
2881 }
Svet Ganovaf189e32019-02-15 18:45:29 -08002882 uidState.evalForegroundOps(mOpModeWatchers);
2883 }
2884
2885 private void readOp(XmlPullParser parser, @NonNull UidState uidState,
2886 @NonNull String pkgName, boolean isPrivileged) throws NumberFormatException,
2887 XmlPullParserException, IOException {
2888 Op op = new Op(uidState, pkgName,
2889 Integer.parseInt(parser.getAttributeValue(null, "n")));
2890
2891 final int mode = XmlUtils.readIntAttribute(parser, "m",
2892 AppOpsManager.opToDefaultMode(op.op));
2893 op.mode = mode;
2894
2895 int outerDepth = parser.getDepth();
2896 int type;
2897 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2898 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2899 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2900 continue;
2901 }
2902 String tagName = parser.getName();
2903 if (tagName.equals("st")) {
2904 final long key = XmlUtils.readLongAttribute(parser, "n");
2905
2906 final int flags = AppOpsManager.extractFlagsFromKey(key);
2907 final int state = AppOpsManager.extractUidStateFromKey(key);
2908
2909 final long accessTime = XmlUtils.readLongAttribute(parser, "t", 0);
2910 final long rejectTime = XmlUtils.readLongAttribute(parser, "r", 0);
2911 final long accessDuration = XmlUtils.readLongAttribute(parser, "d", 0);
2912 final String proxyPkg = XmlUtils.readStringAttribute(parser, "pp");
2913 final int proxyUid = XmlUtils.readIntAttribute(parser, "pu", 0);
2914
2915 if (accessTime > 0) {
2916 op.accessed(accessTime, proxyUid, proxyPkg, state, flags);
2917 }
2918 if (rejectTime > 0) {
2919 op.rejected(rejectTime, proxyUid, proxyPkg, state, flags);
2920 }
2921 if (accessDuration > 0) {
2922 op.running(accessTime, accessDuration, state, flags);
2923 }
2924 } else {
2925 Slog.w(TAG, "Unknown element under <op>: "
2926 + parser.getName());
2927 XmlUtils.skipCurrentTag(parser);
2928 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002929 }
Svet Ganovaf189e32019-02-15 18:45:29 -08002930
2931 if (uidState.pkgOps == null) {
2932 uidState.pkgOps = new ArrayMap<>();
2933 }
2934 Ops ops = uidState.pkgOps.get(pkgName);
2935 if (ops == null) {
2936 ops = new Ops(pkgName, uidState, isPrivileged);
2937 uidState.pkgOps.put(pkgName, ops);
2938 }
2939 ops.put(op.op, op);
Dianne Hackborn35654b62013-01-14 17:38:02 -08002940 }
2941
2942 void writeState() {
2943 synchronized (mFile) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08002944 FileOutputStream stream;
2945 try {
2946 stream = mFile.startWrite();
2947 } catch (IOException e) {
2948 Slog.w(TAG, "Failed to write state: " + e);
2949 return;
2950 }
2951
Dianne Hackborne17b4452018-01-10 13:15:40 -08002952 List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null);
2953
Dianne Hackborn35654b62013-01-14 17:38:02 -08002954 try {
2955 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002956 out.setOutput(stream, StandardCharsets.UTF_8.name());
Dianne Hackborn35654b62013-01-14 17:38:02 -08002957 out.startDocument(null, true);
Dianne Hackborn4d34bb82015-08-07 18:26:38 -07002958 out.startTag(null, "app-ops");
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07002959 out.attribute(null, "v", String.valueOf(CURRENT_VERSION));
Svet Ganov2af57082015-07-30 08:44:20 -07002960
2961 final int uidStateCount = mUidStates.size();
2962 for (int i = 0; i < uidStateCount; i++) {
2963 UidState uidState = mUidStates.valueAt(i);
2964 if (uidState.opModes != null && uidState.opModes.size() > 0) {
2965 out.startTag(null, "uid");
2966 out.attribute(null, "n", Integer.toString(uidState.uid));
2967 SparseIntArray uidOpModes = uidState.opModes;
2968 final int opCount = uidOpModes.size();
2969 for (int j = 0; j < opCount; j++) {
2970 final int op = uidOpModes.keyAt(j);
2971 final int mode = uidOpModes.valueAt(j);
2972 out.startTag(null, "op");
2973 out.attribute(null, "n", Integer.toString(op));
2974 out.attribute(null, "m", Integer.toString(mode));
2975 out.endTag(null, "op");
2976 }
2977 out.endTag(null, "uid");
2978 }
2979 }
Dianne Hackborn35654b62013-01-14 17:38:02 -08002980
2981 if (allOps != null) {
2982 String lastPkg = null;
2983 for (int i=0; i<allOps.size(); i++) {
2984 AppOpsManager.PackageOps pkg = allOps.get(i);
2985 if (!pkg.getPackageName().equals(lastPkg)) {
2986 if (lastPkg != null) {
2987 out.endTag(null, "pkg");
2988 }
2989 lastPkg = pkg.getPackageName();
2990 out.startTag(null, "pkg");
2991 out.attribute(null, "n", lastPkg);
2992 }
2993 out.startTag(null, "uid");
2994 out.attribute(null, "n", Integer.toString(pkg.getUid()));
Jason Monk1c7c3192014-06-26 12:52:18 -04002995 synchronized (this) {
Yohei Yukawaa965d652017-10-12 15:02:26 -07002996 Ops ops = getOpsRawLocked(pkg.getUid(), pkg.getPackageName(),
2997 false /* edit */, false /* uidMismatchExpected */);
Jason Monk1c7c3192014-06-26 12:52:18 -04002998 // Should always be present as the list of PackageOps is generated
2999 // from Ops.
3000 if (ops != null) {
3001 out.attribute(null, "p", Boolean.toString(ops.isPrivileged));
3002 } else {
3003 out.attribute(null, "p", Boolean.toString(false));
3004 }
3005 }
Dianne Hackborn35654b62013-01-14 17:38:02 -08003006 List<AppOpsManager.OpEntry> ops = pkg.getOps();
3007 for (int j=0; j<ops.size(); j++) {
3008 AppOpsManager.OpEntry op = ops.get(j);
3009 out.startTag(null, "op");
3010 out.attribute(null, "n", Integer.toString(op.getOp()));
David Braunf5d83192013-09-16 13:43:51 -07003011 if (op.getMode() != AppOpsManager.opToDefaultMode(op.getOp())) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08003012 out.attribute(null, "m", Integer.toString(op.getMode()));
3013 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003014
3015 final LongSparseArray keys = op.collectKeys();
3016 if (keys == null || keys.size() <= 0) {
Svet Ganov8e5bf962019-03-19 23:59:03 -07003017 out.endTag(null, "op");
Svet Ganovaf189e32019-02-15 18:45:29 -08003018 continue;
3019 }
3020
3021 final int keyCount = keys.size();
3022 for (int k = 0; k < keyCount; k++) {
3023 final long key = keys.keyAt(k);
3024
3025 final int uidState = AppOpsManager.extractUidStateFromKey(key);
3026 final int flags = AppOpsManager.extractFlagsFromKey(key);
3027
3028 final long accessTime = op.getLastAccessTime(
3029 uidState, uidState, flags);
3030 final long rejectTime = op.getLastRejectTime(
3031 uidState, uidState, flags);
3032 final long accessDuration = op.getLastDuration(
3033 uidState, uidState, flags);
3034 final String proxyPkg = op.getProxyPackageName(uidState, flags);
3035 final int proxyUid = op.getProxyUid(uidState, flags);
3036
3037 if (accessTime <= 0 && rejectTime <= 0 && accessDuration <= 0
3038 && proxyPkg == null && proxyUid < 0) {
3039 continue;
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003040 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003041
3042 out.startTag(null, "st");
3043 out.attribute(null, "n", Long.toString(key));
3044 if (accessTime > 0) {
3045 out.attribute(null, "t", Long.toString(accessTime));
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003046 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003047 if (rejectTime > 0) {
3048 out.attribute(null, "r", Long.toString(rejectTime));
3049 }
3050 if (accessDuration > 0) {
3051 out.attribute(null, "d", Long.toString(accessDuration));
3052 }
3053 if (proxyPkg != null) {
3054 out.attribute(null, "pp", proxyPkg);
3055 }
3056 if (proxyUid >= 0) {
3057 out.attribute(null, "pu", Integer.toString(proxyUid));
3058 }
3059 out.endTag(null, "st");
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08003060 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003061
Dianne Hackborn35654b62013-01-14 17:38:02 -08003062 out.endTag(null, "op");
3063 }
3064 out.endTag(null, "uid");
3065 }
3066 if (lastPkg != null) {
3067 out.endTag(null, "pkg");
3068 }
3069 }
3070
3071 out.endTag(null, "app-ops");
3072 out.endDocument();
3073 mFile.finishWrite(stream);
3074 } catch (IOException e) {
3075 Slog.w(TAG, "Failed to write state, restoring backup.", e);
3076 mFile.failWrite(stream);
3077 }
3078 }
3079 }
3080
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003081 static class Shell extends ShellCommand {
3082 final IAppOpsService mInterface;
3083 final AppOpsService mInternal;
3084
3085 int userId = UserHandle.USER_SYSTEM;
3086 String packageName;
3087 String opStr;
Dianne Hackborne91f3e72016-03-25 18:48:15 -07003088 String modeStr;
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003089 int op;
Dianne Hackborne91f3e72016-03-25 18:48:15 -07003090 int mode;
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003091 int packageUid;
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003092 int nonpackageUid;
Julia Reynolds6cb5fcc2018-02-27 17:33:52 -05003093 final static Binder sBinder = new Binder();
3094 IBinder mToken;
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003095
3096 Shell(IAppOpsService iface, AppOpsService internal) {
3097 mInterface = iface;
3098 mInternal = internal;
Julia Reynolds6cb5fcc2018-02-27 17:33:52 -05003099 try {
3100 mToken = mInterface.getToken(sBinder);
3101 } catch (RemoteException e) {
3102 }
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003103 }
3104
3105 @Override
3106 public int onCommand(String cmd) {
3107 return onShellCommand(this, cmd);
3108 }
3109
3110 @Override
3111 public void onHelp() {
3112 PrintWriter pw = getOutPrintWriter();
3113 dumpCommandHelp(pw);
3114 }
3115
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003116 static private int strOpToOp(String op, PrintWriter err) {
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003117 try {
3118 return AppOpsManager.strOpToOp(op);
3119 } catch (IllegalArgumentException e) {
3120 }
3121 try {
3122 return Integer.parseInt(op);
3123 } catch (NumberFormatException e) {
3124 }
3125 try {
3126 return AppOpsManager.strDebugOpToOp(op);
3127 } catch (IllegalArgumentException e) {
3128 err.println("Error: " + e.getMessage());
3129 return -1;
3130 }
3131 }
3132
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003133 static int strModeToMode(String modeStr, PrintWriter err) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003134 for (int i = AppOpsManager.MODE_NAMES.length - 1; i >= 0; i--) {
3135 if (AppOpsManager.MODE_NAMES[i].equals(modeStr)) {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003136 return i;
3137 }
Dianne Hackborne91f3e72016-03-25 18:48:15 -07003138 }
3139 try {
3140 return Integer.parseInt(modeStr);
3141 } catch (NumberFormatException e) {
3142 }
3143 err.println("Error: Mode " + modeStr + " is not valid");
3144 return -1;
3145 }
3146
3147 int parseUserOpMode(int defMode, PrintWriter err) throws RemoteException {
3148 userId = UserHandle.USER_CURRENT;
3149 opStr = null;
3150 modeStr = null;
3151 for (String argument; (argument = getNextArg()) != null;) {
3152 if ("--user".equals(argument)) {
3153 userId = UserHandle.parseUserArg(getNextArgRequired());
3154 } else {
3155 if (opStr == null) {
3156 opStr = argument;
3157 } else if (modeStr == null) {
3158 modeStr = argument;
3159 break;
3160 }
3161 }
3162 }
3163 if (opStr == null) {
3164 err.println("Error: Operation not specified.");
3165 return -1;
3166 }
3167 op = strOpToOp(opStr, err);
3168 if (op < 0) {
3169 return -1;
3170 }
3171 if (modeStr != null) {
3172 if ((mode=strModeToMode(modeStr, err)) < 0) {
3173 return -1;
3174 }
3175 } else {
3176 mode = defMode;
3177 }
3178 return 0;
3179 }
3180
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003181 int parseUserPackageOp(boolean reqOp, PrintWriter err) throws RemoteException {
3182 userId = UserHandle.USER_CURRENT;
3183 packageName = null;
3184 opStr = null;
3185 for (String argument; (argument = getNextArg()) != null;) {
3186 if ("--user".equals(argument)) {
3187 userId = UserHandle.parseUserArg(getNextArgRequired());
3188 } else {
3189 if (packageName == null) {
3190 packageName = argument;
3191 } else if (opStr == null) {
3192 opStr = argument;
3193 break;
3194 }
3195 }
3196 }
3197 if (packageName == null) {
3198 err.println("Error: Package name not specified.");
3199 return -1;
3200 } else if (opStr == null && reqOp) {
3201 err.println("Error: Operation not specified.");
3202 return -1;
3203 }
3204 if (opStr != null) {
3205 op = strOpToOp(opStr, err);
3206 if (op < 0) {
3207 return -1;
3208 }
3209 } else {
3210 op = AppOpsManager.OP_NONE;
3211 }
3212 if (userId == UserHandle.USER_CURRENT) {
3213 userId = ActivityManager.getCurrentUser();
3214 }
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003215 nonpackageUid = -1;
3216 try {
3217 nonpackageUid = Integer.parseInt(packageName);
3218 } catch (NumberFormatException e) {
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003219 }
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003220 if (nonpackageUid == -1 && packageName.length() > 1 && packageName.charAt(0) == 'u'
3221 && packageName.indexOf('.') < 0) {
3222 int i = 1;
3223 while (i < packageName.length() && packageName.charAt(i) >= '0'
3224 && packageName.charAt(i) <= '9') {
3225 i++;
3226 }
3227 if (i > 1 && i < packageName.length()) {
3228 String userStr = packageName.substring(1, i);
3229 try {
3230 int user = Integer.parseInt(userStr);
3231 char type = packageName.charAt(i);
3232 i++;
3233 int startTypeVal = i;
3234 while (i < packageName.length() && packageName.charAt(i) >= '0'
3235 && packageName.charAt(i) <= '9') {
3236 i++;
3237 }
3238 if (i > startTypeVal) {
3239 String typeValStr = packageName.substring(startTypeVal, i);
3240 try {
3241 int typeVal = Integer.parseInt(typeValStr);
3242 if (type == 'a') {
3243 nonpackageUid = UserHandle.getUid(user,
3244 typeVal + Process.FIRST_APPLICATION_UID);
3245 } else if (type == 's') {
3246 nonpackageUid = UserHandle.getUid(user, typeVal);
3247 }
3248 } catch (NumberFormatException e) {
3249 }
3250 }
3251 } catch (NumberFormatException e) {
3252 }
3253 }
3254 }
3255 if (nonpackageUid != -1) {
3256 packageName = null;
3257 } else {
Svet Ganov82f09bc2018-01-12 22:08:40 -08003258 packageUid = resolveUid(packageName);
3259 if (packageUid < 0) {
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003260 packageUid = AppGlobals.getPackageManager().getPackageUid(packageName,
3261 PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
3262 }
3263 if (packageUid < 0) {
3264 err.println("Error: No UID for " + packageName + " in user " + userId);
3265 return -1;
3266 }
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003267 }
3268 return 0;
3269 }
3270 }
3271
3272 @Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
Dianne Hackborn354736e2016-08-22 17:00:05 -07003273 FileDescriptor err, String[] args, ShellCallback callback,
3274 ResultReceiver resultReceiver) {
3275 (new Shell(this, this)).exec(this, in, out, err, args, callback, resultReceiver);
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003276 }
3277
3278 static void dumpCommandHelp(PrintWriter pw) {
3279 pw.println("AppOps service (appops) commands:");
3280 pw.println(" help");
3281 pw.println(" Print this help text.");
Julia Reynolds6cb5fcc2018-02-27 17:33:52 -05003282 pw.println(" start [--user <USER_ID>] <PACKAGE | UID> <OP> ");
3283 pw.println(" Starts a given operation for a particular application.");
3284 pw.println(" stop [--user <USER_ID>] <PACKAGE | UID> <OP> ");
3285 pw.println(" Stops a given operation for a particular application.");
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003286 pw.println(" set [--user <USER_ID>] <PACKAGE | UID> <OP> <MODE>");
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003287 pw.println(" Set the mode for a particular application and operation.");
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003288 pw.println(" get [--user <USER_ID>] <PACKAGE | UID> [<OP>]");
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003289 pw.println(" Return the mode for a particular application and optional operation.");
Dianne Hackborne91f3e72016-03-25 18:48:15 -07003290 pw.println(" query-op [--user <USER_ID>] <OP> [<MODE>]");
3291 pw.println(" Print all packages that currently have the given op in the given mode.");
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003292 pw.println(" reset [--user <USER_ID>] [<PACKAGE>]");
3293 pw.println(" Reset the given application or all applications to default modes.");
Dianne Hackborn4d34bb82015-08-07 18:26:38 -07003294 pw.println(" write-settings");
3295 pw.println(" Immediately write pending changes to storage.");
3296 pw.println(" read-settings");
3297 pw.println(" Read the last written settings, replacing current state in RAM.");
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003298 pw.println(" options:");
3299 pw.println(" <PACKAGE> an Android package name.");
3300 pw.println(" <OP> an AppOps operation.");
3301 pw.println(" <MODE> one of allow, ignore, deny, or default");
3302 pw.println(" <USER_ID> the user id under which the package is installed. If --user is not");
3303 pw.println(" specified, the current user is assumed.");
3304 }
3305
3306 static int onShellCommand(Shell shell, String cmd) {
3307 if (cmd == null) {
3308 return shell.handleDefaultCommands(cmd);
3309 }
3310 PrintWriter pw = shell.getOutPrintWriter();
3311 PrintWriter err = shell.getErrPrintWriter();
3312 try {
3313 switch (cmd) {
3314 case "set": {
3315 int res = shell.parseUserPackageOp(true, err);
3316 if (res < 0) {
3317 return res;
3318 }
3319 String modeStr = shell.getNextArg();
3320 if (modeStr == null) {
3321 err.println("Error: Mode not specified.");
3322 return -1;
3323 }
3324
Dianne Hackborne91f3e72016-03-25 18:48:15 -07003325 final int mode = shell.strModeToMode(modeStr, err);
3326 if (mode < 0) {
3327 return -1;
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003328 }
3329
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003330 if (shell.packageName != null) {
3331 shell.mInterface.setMode(shell.op, shell.packageUid, shell.packageName,
3332 mode);
3333 } else {
3334 shell.mInterface.setUidMode(shell.op, shell.nonpackageUid, mode);
3335 }
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003336 return 0;
3337 }
3338 case "get": {
3339 int res = shell.parseUserPackageOp(false, err);
3340 if (res < 0) {
3341 return res;
3342 }
3343
Eugene Suslae4ee2c22018-11-05 12:23:30 -08003344 List<AppOpsManager.PackageOps> ops = new ArrayList<>();
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003345 if (shell.packageName != null) {
Eugene Suslae4ee2c22018-11-05 12:23:30 -08003346 // Uid mode overrides package mode, so make sure it's also reported
3347 List<AppOpsManager.PackageOps> r = shell.mInterface.getUidOps(
3348 shell.packageUid,
3349 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null);
3350 if (r != null) {
3351 ops.addAll(r);
3352 }
3353 r = shell.mInterface.getOpsForPackage(
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003354 shell.packageUid, shell.packageName,
3355 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null);
Eugene Suslae4ee2c22018-11-05 12:23:30 -08003356 if (r != null) {
3357 ops.addAll(r);
3358 }
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003359 } else {
3360 ops = shell.mInterface.getUidOps(
3361 shell.nonpackageUid,
3362 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null);
3363 }
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003364 if (ops == null || ops.size() <= 0) {
3365 pw.println("No operations.");
Svet Ganov82f09bc2018-01-12 22:08:40 -08003366 if (shell.op > AppOpsManager.OP_NONE && shell.op < AppOpsManager._NUM_OP) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003367 pw.println("Default mode: " + AppOpsManager.modeToName(
Svet Ganov82f09bc2018-01-12 22:08:40 -08003368 AppOpsManager.opToDefaultMode(shell.op)));
3369 }
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003370 return 0;
3371 }
3372 final long now = System.currentTimeMillis();
3373 for (int i=0; i<ops.size(); i++) {
Eugene Suslae4ee2c22018-11-05 12:23:30 -08003374 AppOpsManager.PackageOps packageOps = ops.get(i);
3375 if (packageOps.getPackageName() == null) {
3376 pw.print("Uid mode: ");
3377 }
3378 List<AppOpsManager.OpEntry> entries = packageOps.getOps();
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003379 for (int j=0; j<entries.size(); j++) {
3380 AppOpsManager.OpEntry ent = entries.get(j);
3381 pw.print(AppOpsManager.opToName(ent.getOp()));
3382 pw.print(": ");
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003383 pw.print(AppOpsManager.modeToName(ent.getMode()));
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003384 if (ent.getTime() != 0) {
3385 pw.print("; time=");
3386 TimeUtils.formatDuration(now - ent.getTime(), pw);
3387 pw.print(" ago");
3388 }
3389 if (ent.getRejectTime() != 0) {
3390 pw.print("; rejectTime=");
3391 TimeUtils.formatDuration(now - ent.getRejectTime(), pw);
3392 pw.print(" ago");
3393 }
3394 if (ent.getDuration() == -1) {
3395 pw.print(" (running)");
3396 } else if (ent.getDuration() != 0) {
3397 pw.print("; duration=");
3398 TimeUtils.formatDuration(ent.getDuration(), pw);
3399 }
3400 pw.println();
3401 }
3402 }
3403 return 0;
3404 }
Dianne Hackborne91f3e72016-03-25 18:48:15 -07003405 case "query-op": {
3406 int res = shell.parseUserOpMode(AppOpsManager.MODE_IGNORED, err);
3407 if (res < 0) {
3408 return res;
3409 }
3410 List<AppOpsManager.PackageOps> ops = shell.mInterface.getPackagesForOps(
3411 new int[] {shell.op});
3412 if (ops == null || ops.size() <= 0) {
3413 pw.println("No operations.");
3414 return 0;
3415 }
3416 for (int i=0; i<ops.size(); i++) {
3417 final AppOpsManager.PackageOps pkg = ops.get(i);
3418 boolean hasMatch = false;
3419 final List<AppOpsManager.OpEntry> entries = ops.get(i).getOps();
3420 for (int j=0; j<entries.size(); j++) {
3421 AppOpsManager.OpEntry ent = entries.get(j);
3422 if (ent.getOp() == shell.op && ent.getMode() == shell.mode) {
3423 hasMatch = true;
3424 break;
3425 }
3426 }
3427 if (hasMatch) {
3428 pw.println(pkg.getPackageName());
3429 }
3430 }
3431 return 0;
3432 }
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003433 case "reset": {
3434 String packageName = null;
3435 int userId = UserHandle.USER_CURRENT;
3436 for (String argument; (argument = shell.getNextArg()) != null;) {
3437 if ("--user".equals(argument)) {
3438 String userStr = shell.getNextArgRequired();
3439 userId = UserHandle.parseUserArg(userStr);
3440 } else {
3441 if (packageName == null) {
3442 packageName = argument;
3443 } else {
3444 err.println("Error: Unsupported argument: " + argument);
3445 return -1;
3446 }
3447 }
3448 }
3449
3450 if (userId == UserHandle.USER_CURRENT) {
3451 userId = ActivityManager.getCurrentUser();
3452 }
3453
3454 shell.mInterface.resetAllModes(userId, packageName);
3455 pw.print("Reset all modes for: ");
3456 if (userId == UserHandle.USER_ALL) {
3457 pw.print("all users");
3458 } else {
3459 pw.print("user "); pw.print(userId);
3460 }
3461 pw.print(", ");
3462 if (packageName == null) {
3463 pw.println("all packages");
3464 } else {
3465 pw.print("package "); pw.println(packageName);
3466 }
3467 return 0;
3468 }
3469 case "write-settings": {
Dianne Hackbornd5254412018-05-11 18:02:58 -07003470 shell.mInternal.enforceManageAppOpsModes(Binder.getCallingPid(),
3471 Binder.getCallingUid(), -1);
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003472 long token = Binder.clearCallingIdentity();
3473 try {
3474 synchronized (shell.mInternal) {
3475 shell.mInternal.mHandler.removeCallbacks(shell.mInternal.mWriteRunner);
3476 }
3477 shell.mInternal.writeState();
3478 pw.println("Current settings written.");
3479 } finally {
3480 Binder.restoreCallingIdentity(token);
3481 }
3482 return 0;
3483 }
3484 case "read-settings": {
Dianne Hackbornd5254412018-05-11 18:02:58 -07003485 shell.mInternal.enforceManageAppOpsModes(Binder.getCallingPid(),
3486 Binder.getCallingUid(), -1);
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003487 long token = Binder.clearCallingIdentity();
3488 try {
3489 shell.mInternal.readState();
3490 pw.println("Last settings read.");
3491 } finally {
3492 Binder.restoreCallingIdentity(token);
3493 }
3494 return 0;
3495 }
Julia Reynolds6cb5fcc2018-02-27 17:33:52 -05003496 case "start": {
3497 int res = shell.parseUserPackageOp(true, err);
3498 if (res < 0) {
3499 return res;
3500 }
3501
3502 if (shell.packageName != null) {
3503 shell.mInterface.startOperation(shell.mToken,
3504 shell.op, shell.packageUid, shell.packageName, true);
3505 } else {
3506 return -1;
3507 }
3508 return 0;
3509 }
3510 case "stop": {
3511 int res = shell.parseUserPackageOp(true, err);
3512 if (res < 0) {
3513 return res;
3514 }
3515
3516 if (shell.packageName != null) {
3517 shell.mInterface.finishOperation(shell.mToken,
3518 shell.op, shell.packageUid, shell.packageName);
3519 } else {
3520 return -1;
3521 }
3522 return 0;
3523 }
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003524 default:
3525 return shell.handleDefaultCommands(cmd);
3526 }
3527 } catch (RemoteException e) {
3528 pw.println("Remote exception: " + e);
3529 }
3530 return -1;
3531 }
3532
3533 private void dumpHelp(PrintWriter pw) {
3534 pw.println("AppOps service (appops) dump options:");
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003535 pw.println(" -h");
3536 pw.println(" Print this help text.");
3537 pw.println(" --op [OP]");
3538 pw.println(" Limit output to data associated with the given app op code.");
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003539 pw.println(" --mode [MODE]");
3540 pw.println(" Limit output to data associated with the given app op mode.");
3541 pw.println(" --package [PACKAGE]");
3542 pw.println(" Limit output to data associated with the given package name.");
Dianne Hackborn125dc532019-01-09 13:31:48 -08003543 pw.println(" --watchers");
3544 pw.println(" Only output the watcher sections.");
Svet Ganovaf189e32019-02-15 18:45:29 -08003545 pw.println(" --history");
3546 pw.println(" Output the historical data.");
Dianne Hackborn4d34bb82015-08-07 18:26:38 -07003547 }
3548
Svet Ganovaf189e32019-02-15 18:45:29 -08003549 private void dumpStatesLocked(@NonNull PrintWriter pw, @NonNull Op op,
3550 long now, @NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix) {
3551
3552 final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes,
3553 op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames);
3554
3555 final LongSparseArray keys = entry.collectKeys();
3556 if (keys == null || keys.size() <= 0) {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003557 return;
3558 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003559
3560 final int keyCount = keys.size();
3561 for (int k = 0; k < keyCount; k++) {
3562 final long key = keys.keyAt(k);
3563
3564 final int uidState = AppOpsManager.extractUidStateFromKey(key);
3565 final int flags = AppOpsManager.extractFlagsFromKey(key);
3566
3567 final long accessTime = entry.getLastAccessTime(
3568 uidState, uidState, flags);
3569 final long rejectTime = entry.getLastRejectTime(
3570 uidState, uidState, flags);
3571 final long accessDuration = entry.getLastDuration(
3572 uidState, uidState, flags);
3573 final String proxyPkg = entry.getProxyPackageName(uidState, flags);
3574 final int proxyUid = entry.getProxyUid(uidState, flags);
3575
3576 if (accessTime > 0) {
3577 pw.print(prefix);
3578 pw.print("Access: ");
3579 pw.print(AppOpsManager.keyToString(key));
3580 pw.print(" ");
3581 date.setTime(accessTime);
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003582 pw.print(sdf.format(date));
3583 pw.print(" (");
Svet Ganovaf189e32019-02-15 18:45:29 -08003584 TimeUtils.formatDuration(accessTime - now, pw);
3585 pw.print(")");
3586 if (accessDuration > 0) {
3587 pw.print(" duration=");
3588 TimeUtils.formatDuration(accessDuration, pw);
3589 }
3590 if (proxyUid >= 0) {
3591 pw.print(" proxy[");
3592 pw.print("uid=");
3593 pw.print(proxyUid);
3594 pw.print(", pkg=");
3595 pw.print(proxyPkg);
3596 pw.print("]");
3597 }
3598 pw.println();
3599 }
3600
3601 if (rejectTime > 0) {
3602 pw.print(prefix);
3603 pw.print("Reject: ");
3604 pw.print(AppOpsManager.keyToString(key));
3605 date.setTime(rejectTime);
3606 pw.print(sdf.format(date));
3607 pw.print(" (");
3608 TimeUtils.formatDuration(rejectTime - now, pw);
3609 pw.print(")");
3610 if (proxyUid >= 0) {
3611 pw.print(" proxy[");
3612 pw.print("uid=");
3613 pw.print(proxyUid);
3614 pw.print(", pkg=");
3615 pw.print(proxyPkg);
3616 pw.print("]");
3617 }
3618 pw.println();
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003619 }
3620 }
3621 }
3622
Dianne Hackborna06de0f2012-12-11 16:34:47 -08003623 @Override
3624 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkey6df866a2017-03-31 14:08:23 -06003625 if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08003626
Svet Ganov8455ba22019-01-02 13:05:56 -08003627 int dumpOp = OP_NONE;
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003628 String dumpPackage = null;
Svet Ganov8455ba22019-01-02 13:05:56 -08003629 int dumpUid = Process.INVALID_UID;
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003630 int dumpMode = -1;
Dianne Hackborn125dc532019-01-09 13:31:48 -08003631 boolean dumpWatchers = false;
Svet Ganovaf189e32019-02-15 18:45:29 -08003632 boolean dumpHistory = false;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003633
Dianne Hackborn4d34bb82015-08-07 18:26:38 -07003634 if (args != null) {
3635 for (int i=0; i<args.length; i++) {
3636 String arg = args[i];
3637 if ("-h".equals(arg)) {
3638 dumpHelp(pw);
3639 return;
Tim Kilbourn8f1ea832015-08-26 15:07:37 -07003640 } else if ("-a".equals(arg)) {
3641 // dump all data
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003642 } else if ("--op".equals(arg)) {
3643 i++;
3644 if (i >= args.length) {
3645 pw.println("No argument for --op option");
3646 return;
3647 }
3648 dumpOp = Shell.strOpToOp(args[i], pw);
3649 if (dumpOp < 0) {
3650 return;
3651 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003652 } else if ("--package".equals(arg)) {
3653 i++;
3654 if (i >= args.length) {
3655 pw.println("No argument for --package option");
3656 return;
3657 }
3658 dumpPackage = args[i];
3659 try {
3660 dumpUid = AppGlobals.getPackageManager().getPackageUid(dumpPackage,
3661 PackageManager.MATCH_KNOWN_PACKAGES | PackageManager.MATCH_INSTANT,
3662 0);
3663 } catch (RemoteException e) {
3664 }
3665 if (dumpUid < 0) {
3666 pw.println("Unknown package: " + dumpPackage);
3667 return;
3668 }
3669 dumpUid = UserHandle.getAppId(dumpUid);
3670 } else if ("--mode".equals(arg)) {
3671 i++;
3672 if (i >= args.length) {
3673 pw.println("No argument for --mode option");
3674 return;
3675 }
3676 dumpMode = Shell.strModeToMode(args[i], pw);
3677 if (dumpMode < 0) {
3678 return;
3679 }
Dianne Hackborn125dc532019-01-09 13:31:48 -08003680 } else if ("--watchers".equals(arg)) {
3681 dumpWatchers = true;
Svet Ganovaf189e32019-02-15 18:45:29 -08003682 } else if ("--history".equals(arg)) {
3683 dumpHistory = true;
Dianne Hackborn4d34bb82015-08-07 18:26:38 -07003684 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
3685 pw.println("Unknown option: " + arg);
3686 return;
3687 } else {
3688 pw.println("Unknown command: " + arg);
3689 return;
3690 }
3691 }
3692 }
3693
Dianne Hackborna06de0f2012-12-11 16:34:47 -08003694 synchronized (this) {
3695 pw.println("Current AppOps Service state:");
Svet Ganovaf189e32019-02-15 18:45:29 -08003696 if (!dumpHistory && !dumpWatchers) {
3697 mConstants.dump(pw);
3698 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003699 pw.println();
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08003700 final long now = System.currentTimeMillis();
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003701 final long nowElapsed = SystemClock.elapsedRealtime();
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003702 final long nowUptime = SystemClock.uptimeMillis();
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003703 final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
3704 final Date date = new Date();
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003705 boolean needSep = false;
Dianne Hackborn125dc532019-01-09 13:31:48 -08003706 if (dumpOp < 0 && dumpMode < 0 && dumpPackage == null && mProfileOwners != null
Svet Ganovaf189e32019-02-15 18:45:29 -08003707 && !dumpWatchers && !dumpHistory) {
Dianne Hackbornd5254412018-05-11 18:02:58 -07003708 pw.println(" Profile owners:");
3709 for (int poi = 0; poi < mProfileOwners.size(); poi++) {
3710 pw.print(" User #");
3711 pw.print(mProfileOwners.keyAt(poi));
3712 pw.print(": ");
3713 UserHandle.formatUid(pw, mProfileOwners.valueAt(poi));
3714 pw.println();
3715 }
3716 pw.println();
3717 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003718 if (mOpModeWatchers.size() > 0 && !dumpHistory) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003719 boolean printedHeader = false;
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003720 for (int i=0; i<mOpModeWatchers.size(); i++) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003721 if (dumpOp >= 0 && dumpOp != mOpModeWatchers.keyAt(i)) {
3722 continue;
3723 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003724 boolean printedOpHeader = false;
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08003725 ArraySet<ModeCallback> callbacks = mOpModeWatchers.valueAt(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003726 for (int j=0; j<callbacks.size(); j++) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003727 final ModeCallback cb = callbacks.valueAt(j);
Dianne Hackborn125dc532019-01-09 13:31:48 -08003728 if (dumpPackage != null
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003729 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) {
3730 continue;
3731 }
3732 needSep = true;
3733 if (!printedHeader) {
3734 pw.println(" Op mode watchers:");
3735 printedHeader = true;
3736 }
3737 if (!printedOpHeader) {
3738 pw.print(" Op ");
3739 pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i)));
3740 pw.println(":");
3741 printedOpHeader = true;
3742 }
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003743 pw.print(" #"); pw.print(j); pw.print(": ");
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003744 pw.println(cb);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003745 }
3746 }
3747 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003748 if (mPackageModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003749 boolean printedHeader = false;
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003750 for (int i=0; i<mPackageModeWatchers.size(); i++) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003751 if (dumpPackage != null && !dumpPackage.equals(mPackageModeWatchers.keyAt(i))) {
3752 continue;
3753 }
3754 needSep = true;
3755 if (!printedHeader) {
3756 pw.println(" Package mode watchers:");
3757 printedHeader = true;
3758 }
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003759 pw.print(" Pkg "); pw.print(mPackageModeWatchers.keyAt(i));
3760 pw.println(":");
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08003761 ArraySet<ModeCallback> callbacks = mPackageModeWatchers.valueAt(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003762 for (int j=0; j<callbacks.size(); j++) {
3763 pw.print(" #"); pw.print(j); pw.print(": ");
Dianne Hackborn68d76552017-02-27 15:32:03 -08003764 pw.println(callbacks.valueAt(j));
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003765 }
3766 }
3767 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003768 if (mModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003769 boolean printedHeader = false;
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003770 for (int i=0; i<mModeWatchers.size(); i++) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003771 final ModeCallback cb = mModeWatchers.valueAt(i);
Dianne Hackborn125dc532019-01-09 13:31:48 -08003772 if (dumpPackage != null
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003773 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) {
3774 continue;
3775 }
3776 needSep = true;
3777 if (!printedHeader) {
3778 pw.println(" All op mode watchers:");
3779 printedHeader = true;
3780 }
Dianne Hackborn3b563fc2018-04-16 17:17:14 -07003781 pw.print(" ");
3782 pw.print(Integer.toHexString(System.identityHashCode(mModeWatchers.keyAt(i))));
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003783 pw.print(": "); pw.println(cb);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003784 }
3785 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003786 if (mActiveWatchers.size() > 0 && dumpMode < 0) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08003787 needSep = true;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003788 boolean printedHeader = false;
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08003789 for (int i = 0; i < mActiveWatchers.size(); i++) {
3790 final SparseArray<ActiveCallback> activeWatchers = mActiveWatchers.valueAt(i);
3791 if (activeWatchers.size() <= 0) {
3792 continue;
3793 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003794 final ActiveCallback cb = activeWatchers.valueAt(0);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003795 if (dumpOp >= 0 && activeWatchers.indexOfKey(dumpOp) < 0) {
3796 continue;
3797 }
Dianne Hackborn125dc532019-01-09 13:31:48 -08003798 if (dumpPackage != null
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003799 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) {
3800 continue;
3801 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003802 if (!printedHeader) {
3803 pw.println(" All op active watchers:");
3804 printedHeader = true;
3805 }
Dianne Hackborn3b563fc2018-04-16 17:17:14 -07003806 pw.print(" ");
3807 pw.print(Integer.toHexString(System.identityHashCode(
3808 mActiveWatchers.keyAt(i))));
3809 pw.println(" ->");
3810 pw.print(" [");
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08003811 final int opCount = activeWatchers.size();
3812 for (i = 0; i < opCount; i++) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003813 if (i > 0) {
3814 pw.print(' ');
3815 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08003816 pw.print(AppOpsManager.opToName(activeWatchers.keyAt(i)));
3817 if (i < opCount - 1) {
3818 pw.print(',');
3819 }
3820 }
Dianne Hackborn3b563fc2018-04-16 17:17:14 -07003821 pw.println("]");
3822 pw.print(" ");
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003823 pw.println(cb);
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08003824 }
3825 }
Svet Ganovb3d2ae22018-12-17 22:06:15 -08003826 if (mNotedWatchers.size() > 0 && dumpMode < 0) {
3827 needSep = true;
3828 boolean printedHeader = false;
3829 for (int i = 0; i < mNotedWatchers.size(); i++) {
3830 final SparseArray<NotedCallback> notedWatchers = mNotedWatchers.valueAt(i);
3831 if (notedWatchers.size() <= 0) {
3832 continue;
3833 }
3834 final NotedCallback cb = notedWatchers.valueAt(0);
3835 if (dumpOp >= 0 && notedWatchers.indexOfKey(dumpOp) < 0) {
3836 continue;
3837 }
Dianne Hackborn125dc532019-01-09 13:31:48 -08003838 if (dumpPackage != null
Svet Ganovb3d2ae22018-12-17 22:06:15 -08003839 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) {
3840 continue;
3841 }
3842 if (!printedHeader) {
3843 pw.println(" All op noted watchers:");
3844 printedHeader = true;
3845 }
3846 pw.print(" ");
3847 pw.print(Integer.toHexString(System.identityHashCode(
3848 mNotedWatchers.keyAt(i))));
3849 pw.println(" ->");
3850 pw.print(" [");
3851 final int opCount = notedWatchers.size();
3852 for (i = 0; i < opCount; i++) {
3853 if (i > 0) {
3854 pw.print(' ');
3855 }
3856 pw.print(AppOpsManager.opToName(notedWatchers.keyAt(i)));
3857 if (i < opCount - 1) {
3858 pw.print(',');
3859 }
3860 }
3861 pw.println("]");
3862 pw.print(" ");
3863 pw.println(cb);
3864 }
3865 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003866 if (mClients.size() > 0 && dumpMode < 0 && !dumpWatchers && !dumpHistory) {
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003867 needSep = true;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003868 boolean printedHeader = false;
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003869 for (int i=0; i<mClients.size(); i++) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003870 boolean printedClient = false;
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003871 ClientState cs = mClients.valueAt(i);
Svet Ganovf7b47252018-02-26 11:11:27 -08003872 if (cs.mStartedOps.size() > 0) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003873 boolean printedStarted = false;
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003874 for (int j=0; j<cs.mStartedOps.size(); j++) {
3875 Op op = cs.mStartedOps.get(j);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003876 if (dumpOp >= 0 && op.op != dumpOp) {
3877 continue;
3878 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003879 if (dumpPackage != null && !dumpPackage.equals(op.packageName)) {
3880 continue;
3881 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003882 if (!printedHeader) {
3883 pw.println(" Clients:");
3884 printedHeader = true;
3885 }
3886 if (!printedClient) {
3887 pw.print(" "); pw.print(mClients.keyAt(i)); pw.println(":");
3888 pw.print(" "); pw.println(cs);
3889 printedClient = true;
3890 }
3891 if (!printedStarted) {
3892 pw.println(" Started ops:");
3893 printedStarted = true;
3894 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003895 pw.print(" "); pw.print("uid="); pw.print(op.uidState.uid);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003896 pw.print(" pkg="); pw.print(op.packageName);
3897 pw.print(" op="); pw.println(AppOpsManager.opToName(op.op));
3898 }
3899 }
3900 }
3901 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003902 if (mAudioRestrictions.size() > 0 && dumpOp < 0 && dumpPackage != null
Svet Ganovaf189e32019-02-15 18:45:29 -08003903 && dumpMode < 0 && !dumpWatchers && !dumpWatchers) {
John Spurlock1af30c72014-03-10 08:33:35 -04003904 boolean printedHeader = false;
3905 for (int o=0; o<mAudioRestrictions.size(); o++) {
3906 final String op = AppOpsManager.opToName(mAudioRestrictions.keyAt(o));
3907 final SparseArray<Restriction> restrictions = mAudioRestrictions.valueAt(o);
3908 for (int i=0; i<restrictions.size(); i++) {
3909 if (!printedHeader){
3910 pw.println(" Audio Restrictions:");
3911 printedHeader = true;
3912 needSep = true;
3913 }
John Spurlock7b414672014-07-18 13:02:39 -04003914 final int usage = restrictions.keyAt(i);
John Spurlock1af30c72014-03-10 08:33:35 -04003915 pw.print(" "); pw.print(op);
John Spurlock7b414672014-07-18 13:02:39 -04003916 pw.print(" usage="); pw.print(AudioAttributes.usageToString(usage));
John Spurlock1af30c72014-03-10 08:33:35 -04003917 Restriction r = restrictions.valueAt(i);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003918 pw.print(": mode="); pw.println(AppOpsManager.modeToName(r.mode));
John Spurlock1af30c72014-03-10 08:33:35 -04003919 if (!r.exceptionPackages.isEmpty()) {
3920 pw.println(" Exceptions:");
3921 for (int j=0; j<r.exceptionPackages.size(); j++) {
3922 pw.print(" "); pw.println(r.exceptionPackages.valueAt(j));
3923 }
3924 }
3925 }
3926 }
3927 }
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003928 if (needSep) {
3929 pw.println();
3930 }
Svet Ganov2af57082015-07-30 08:44:20 -07003931 for (int i=0; i<mUidStates.size(); i++) {
3932 UidState uidState = mUidStates.valueAt(i);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003933 final SparseIntArray opModes = uidState.opModes;
3934 final ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
3935
Svet Ganovaf189e32019-02-15 18:45:29 -08003936 if (dumpWatchers || dumpHistory) {
Dianne Hackborn125dc532019-01-09 13:31:48 -08003937 continue;
3938 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003939 if (dumpOp >= 0 || dumpPackage != null || dumpMode >= 0) {
3940 boolean hasOp = dumpOp < 0 || (uidState.opModes != null
3941 && uidState.opModes.indexOfKey(dumpOp) >= 0);
3942 boolean hasPackage = dumpPackage == null;
3943 boolean hasMode = dumpMode < 0;
3944 if (!hasMode && opModes != null) {
3945 for (int opi = 0; !hasMode && opi < opModes.size(); opi++) {
3946 if (opModes.valueAt(opi) == dumpMode) {
3947 hasMode = true;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003948 }
3949 }
3950 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003951 if (pkgOps != null) {
3952 for (int pkgi = 0;
Svet Ganov8455ba22019-01-02 13:05:56 -08003953 (!hasOp || !hasPackage || !hasMode) && pkgi < pkgOps.size();
3954 pkgi++) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003955 Ops ops = pkgOps.valueAt(pkgi);
3956 if (!hasOp && ops != null && ops.indexOfKey(dumpOp) >= 0) {
3957 hasOp = true;
3958 }
3959 if (!hasMode) {
3960 for (int opi = 0; !hasMode && opi < ops.size(); opi++) {
3961 if (ops.valueAt(opi).mode == dumpMode) {
3962 hasMode = true;
3963 }
3964 }
3965 }
3966 if (!hasPackage && dumpPackage.equals(ops.packageName)) {
3967 hasPackage = true;
3968 }
3969 }
3970 }
3971 if (uidState.foregroundOps != null && !hasOp) {
3972 if (uidState.foregroundOps.indexOfKey(dumpOp) > 0) {
3973 hasOp = true;
3974 }
3975 }
3976 if (!hasOp || !hasPackage || !hasMode) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003977 continue;
3978 }
3979 }
Svet Ganov2af57082015-07-30 08:44:20 -07003980
3981 pw.print(" Uid "); UserHandle.formatUid(pw, uidState.uid); pw.println(":");
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003982 pw.print(" state=");
Svet Ganovaf189e32019-02-15 18:45:29 -08003983 pw.println(AppOpsManager.getUidStateName(uidState.state));
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003984 if (uidState.state != uidState.pendingState) {
3985 pw.print(" pendingState=");
Svet Ganovaf189e32019-02-15 18:45:29 -08003986 pw.println(AppOpsManager.getUidStateName(uidState.pendingState));
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003987 }
3988 if (uidState.pendingStateCommitTime != 0) {
3989 pw.print(" pendingStateCommitTime=");
Dianne Hackborn9fb93502018-06-18 12:29:44 -07003990 TimeUtils.formatDuration(uidState.pendingStateCommitTime, nowElapsed, pw);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003991 pw.println();
3992 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003993 if (uidState.startNesting != 0) {
3994 pw.print(" startNesting=");
3995 pw.println(uidState.startNesting);
3996 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003997 if (uidState.foregroundOps != null && (dumpMode < 0
3998 || dumpMode == AppOpsManager.MODE_FOREGROUND)) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003999 pw.println(" foregroundOps:");
4000 for (int j = 0; j < uidState.foregroundOps.size(); j++) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07004001 if (dumpOp >= 0 && dumpOp != uidState.foregroundOps.keyAt(j)) {
4002 continue;
4003 }
4004 pw.print(" ");
4005 pw.print(AppOpsManager.opToName(uidState.foregroundOps.keyAt(j)));
4006 pw.print(": ");
4007 pw.println(uidState.foregroundOps.valueAt(j) ? "WATCHER" : "SILENT");
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004008 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07004009 pw.print(" hasForegroundWatchers=");
4010 pw.println(uidState.hasForegroundWatchers);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004011 }
Svet Ganovee438d42017-01-19 18:04:38 -08004012 needSep = true;
Svet Ganov2af57082015-07-30 08:44:20 -07004013
Svet Ganov2af57082015-07-30 08:44:20 -07004014 if (opModes != null) {
4015 final int opModeCount = opModes.size();
4016 for (int j = 0; j < opModeCount; j++) {
4017 final int code = opModes.keyAt(j);
4018 final int mode = opModes.valueAt(j);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004019 if (dumpOp >= 0 && dumpOp != code) {
4020 continue;
4021 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07004022 if (dumpMode >= 0 && dumpMode != mode) {
4023 continue;
4024 }
Svet Ganov2af57082015-07-30 08:44:20 -07004025 pw.print(" "); pw.print(AppOpsManager.opToName(code));
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004026 pw.print(": mode="); pw.println(AppOpsManager.modeToName(mode));
Svet Ganov2af57082015-07-30 08:44:20 -07004027 }
4028 }
4029
Svet Ganov2af57082015-07-30 08:44:20 -07004030 if (pkgOps == null) {
4031 continue;
4032 }
4033
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004034 for (int pkgi = 0; pkgi < pkgOps.size(); pkgi++) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07004035 final Ops ops = pkgOps.valueAt(pkgi);
4036 if (dumpPackage != null && !dumpPackage.equals(ops.packageName)) {
4037 continue;
4038 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004039 boolean printedPackage = false;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08004040 for (int j=0; j<ops.size(); j++) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07004041 final Op op = ops.valueAt(j);
Svet Ganovaf189e32019-02-15 18:45:29 -08004042 final int opCode = op.op;
4043 if (dumpOp >= 0 && dumpOp != opCode) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004044 continue;
4045 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07004046 if (dumpMode >= 0 && dumpMode != op.mode) {
4047 continue;
4048 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004049 if (!printedPackage) {
4050 pw.print(" Package "); pw.print(ops.packageName); pw.println(":");
4051 printedPackage = true;
4052 }
Svet Ganovaf189e32019-02-15 18:45:29 -08004053 pw.print(" "); pw.print(AppOpsManager.opToName(opCode));
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004054 pw.print(" ("); pw.print(AppOpsManager.modeToName(op.mode));
Svet Ganovaf189e32019-02-15 18:45:29 -08004055 final int switchOp = AppOpsManager.opToSwitch(opCode);
4056 if (switchOp != opCode) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07004057 pw.print(" / switch ");
4058 pw.print(AppOpsManager.opToName(switchOp));
4059 final Op switchObj = ops.get(switchOp);
Svet Ganovaf189e32019-02-15 18:45:29 -08004060 int mode = switchObj != null ? switchObj.mode
4061 : AppOpsManager.opToDefaultMode(switchOp);
Dianne Hackborn65a4f252018-05-08 17:30:48 -07004062 pw.print("="); pw.print(AppOpsManager.modeToName(mode));
4063 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004064 pw.println("): ");
Svet Ganovaf189e32019-02-15 18:45:29 -08004065 dumpStatesLocked(pw, op, now, sdf, date, " ");
4066 if (op.running) {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07004067 pw.print(" Running start at: ");
4068 TimeUtils.formatDuration(nowElapsed-op.startRealtime, pw);
4069 pw.println();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08004070 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07004071 if (op.startNesting != 0) {
4072 pw.print(" startNesting=");
4073 pw.println(op.startNesting);
4074 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -08004075 }
4076 }
4077 }
Svet Ganovee438d42017-01-19 18:04:38 -08004078 if (needSep) {
4079 pw.println();
4080 }
4081
4082 final int userRestrictionCount = mOpUserRestrictions.size();
4083 for (int i = 0; i < userRestrictionCount; i++) {
4084 IBinder token = mOpUserRestrictions.keyAt(i);
4085 ClientRestrictionState restrictionState = mOpUserRestrictions.valueAt(i);
Dianne Hackborn125dc532019-01-09 13:31:48 -08004086 boolean printedTokenHeader = false;
4087
Svet Ganovaf189e32019-02-15 18:45:29 -08004088 if (dumpMode >= 0 || dumpWatchers || dumpHistory) {
Dianne Hackborn125dc532019-01-09 13:31:48 -08004089 continue;
4090 }
Svet Ganovee438d42017-01-19 18:04:38 -08004091
4092 final int restrictionCount = restrictionState.perUserRestrictions != null
4093 ? restrictionState.perUserRestrictions.size() : 0;
Dianne Hackborn125dc532019-01-09 13:31:48 -08004094 if (restrictionCount > 0 && dumpPackage == null) {
4095 boolean printedOpsHeader = false;
Svet Ganovee438d42017-01-19 18:04:38 -08004096 for (int j = 0; j < restrictionCount; j++) {
4097 int userId = restrictionState.perUserRestrictions.keyAt(j);
4098 boolean[] restrictedOps = restrictionState.perUserRestrictions.valueAt(j);
4099 if (restrictedOps == null) {
4100 continue;
4101 }
Dianne Hackborn125dc532019-01-09 13:31:48 -08004102 if (dumpOp >= 0 && (dumpOp >= restrictedOps.length
4103 || !restrictedOps[dumpOp])) {
4104 continue;
4105 }
4106 if (!printedTokenHeader) {
4107 pw.println(" User restrictions for token " + token + ":");
4108 printedTokenHeader = true;
4109 }
4110 if (!printedOpsHeader) {
4111 pw.println(" Restricted ops:");
4112 printedOpsHeader = true;
4113 }
Svet Ganovee438d42017-01-19 18:04:38 -08004114 StringBuilder restrictedOpsValue = new StringBuilder();
4115 restrictedOpsValue.append("[");
4116 final int restrictedOpCount = restrictedOps.length;
4117 for (int k = 0; k < restrictedOpCount; k++) {
4118 if (restrictedOps[k]) {
4119 if (restrictedOpsValue.length() > 1) {
4120 restrictedOpsValue.append(", ");
4121 }
4122 restrictedOpsValue.append(AppOpsManager.opToName(k));
4123 }
4124 }
4125 restrictedOpsValue.append("]");
4126 pw.print(" "); pw.print("user: "); pw.print(userId);
4127 pw.print(" restricted ops: "); pw.println(restrictedOpsValue);
4128 }
4129 }
4130
4131 final int excludedPackageCount = restrictionState.perUserExcludedPackages != null
4132 ? restrictionState.perUserExcludedPackages.size() : 0;
Dianne Hackborn125dc532019-01-09 13:31:48 -08004133 if (excludedPackageCount > 0 && dumpOp < 0) {
4134 boolean printedPackagesHeader = false;
Svet Ganovee438d42017-01-19 18:04:38 -08004135 for (int j = 0; j < excludedPackageCount; j++) {
4136 int userId = restrictionState.perUserExcludedPackages.keyAt(j);
4137 String[] packageNames = restrictionState.perUserExcludedPackages.valueAt(j);
Dianne Hackborn125dc532019-01-09 13:31:48 -08004138 if (packageNames == null) {
4139 continue;
4140 }
4141 boolean hasPackage;
4142 if (dumpPackage != null) {
4143 hasPackage = false;
4144 for (String pkg : packageNames) {
4145 if (dumpPackage.equals(pkg)) {
4146 hasPackage = true;
4147 break;
4148 }
4149 }
4150 } else {
4151 hasPackage = true;
4152 }
4153 if (!hasPackage) {
4154 continue;
4155 }
4156 if (!printedTokenHeader) {
4157 pw.println(" User restrictions for token " + token + ":");
4158 printedTokenHeader = true;
4159 }
4160 if (!printedPackagesHeader) {
4161 pw.println(" Excluded packages:");
4162 printedPackagesHeader = true;
4163 }
Svet Ganovee438d42017-01-19 18:04:38 -08004164 pw.print(" "); pw.print("user: "); pw.print(userId);
4165 pw.print(" packages: "); pw.println(Arrays.toString(packageNames));
4166 }
4167 }
4168 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -08004169 }
Svet Ganov8455ba22019-01-02 13:05:56 -08004170
4171 // Must not hold the appops lock
Svet Ganovaf189e32019-02-15 18:45:29 -08004172 if (dumpHistory && !dumpWatchers) {
4173 mHistoricalRegistry.dump(" ", pw, dumpUid, dumpPackage, dumpOp);
4174 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -08004175 }
John Spurlock1af30c72014-03-10 08:33:35 -04004176
4177 private static final class Restriction {
4178 private static final ArraySet<String> NO_EXCEPTIONS = new ArraySet<String>();
4179 int mode;
4180 ArraySet<String> exceptionPackages = NO_EXCEPTIONS;
4181 }
Jason Monk62062992014-05-06 09:55:28 -04004182
4183 @Override
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004184 public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) {
Jason Monk62062992014-05-06 09:55:28 -04004185 checkSystemUid("setUserRestrictions");
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00004186 Preconditions.checkNotNull(restrictions);
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004187 Preconditions.checkNotNull(token);
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07004188 for (int i = 0; i < AppOpsManager._NUM_OP; i++) {
Jason Monk62062992014-05-06 09:55:28 -04004189 String restriction = AppOpsManager.opToRestriction(i);
Suprabh Shukla64e0dcb2016-05-24 16:23:11 -07004190 if (restriction != null) {
4191 setUserRestrictionNoCheck(i, restrictions.getBoolean(restriction, false), token,
4192 userHandle, null);
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07004193 }
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004194 }
4195 }
4196
4197 @Override
Ruben Brunk29931bc2016-03-11 00:24:26 -08004198 public void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle,
4199 String[] exceptionPackages) {
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004200 if (Binder.getCallingPid() != Process.myPid()) {
4201 mContext.enforcePermission(Manifest.permission.MANAGE_APP_OPS_RESTRICTIONS,
4202 Binder.getCallingPid(), Binder.getCallingUid(), null);
4203 }
4204 if (userHandle != UserHandle.getCallingUserId()) {
4205 if (mContext.checkCallingOrSelfPermission(Manifest.permission
4206 .INTERACT_ACROSS_USERS_FULL) != PackageManager.PERMISSION_GRANTED
4207 && mContext.checkCallingOrSelfPermission(Manifest.permission
4208 .INTERACT_ACROSS_USERS) != PackageManager.PERMISSION_GRANTED) {
4209 throw new SecurityException("Need INTERACT_ACROSS_USERS_FULL or"
4210 + " INTERACT_ACROSS_USERS to interact cross user ");
Jason Monk62062992014-05-06 09:55:28 -04004211 }
4212 }
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004213 verifyIncomingOp(code);
4214 Preconditions.checkNotNull(token);
Ruben Brunk29931bc2016-03-11 00:24:26 -08004215 setUserRestrictionNoCheck(code, restricted, token, userHandle, exceptionPackages);
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004216 }
4217
4218 private void setUserRestrictionNoCheck(int code, boolean restricted, IBinder token,
Ruben Brunk29931bc2016-03-11 00:24:26 -08004219 int userHandle, String[] exceptionPackages) {
Svet Ganov442ed572016-08-17 17:29:43 -07004220 synchronized (AppOpsService.this) {
4221 ClientRestrictionState restrictionState = mOpUserRestrictions.get(token);
4222
4223 if (restrictionState == null) {
4224 try {
4225 restrictionState = new ClientRestrictionState(token);
4226 } catch (RemoteException e) {
4227 return;
4228 }
4229 mOpUserRestrictions.put(token, restrictionState);
Ruben Brunk29931bc2016-03-11 00:24:26 -08004230 }
Svet Ganov442ed572016-08-17 17:29:43 -07004231
4232 if (restrictionState.setRestriction(code, restricted, exceptionPackages, userHandle)) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08004233 mHandler.sendMessage(PooledLambda.obtainMessage(
Svet Ganov3a95f832018-03-23 17:44:30 -07004234 AppOpsService::notifyWatchersOfChange, this, code, UID_ANY));
Svet Ganov442ed572016-08-17 17:29:43 -07004235 }
4236
4237 if (restrictionState.isDefault()) {
4238 mOpUserRestrictions.remove(token);
4239 restrictionState.destroy();
4240 }
Ruben Brunk29931bc2016-03-11 00:24:26 -08004241 }
Julia Reynoldsbb21c252016-04-05 16:01:49 -04004242 }
4243
Svet Ganov3a95f832018-03-23 17:44:30 -07004244 private void notifyWatchersOfChange(int code, int uid) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08004245 final ArraySet<ModeCallback> clonedCallbacks;
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004246 synchronized (this) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08004247 ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code);
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004248 if (callbacks == null) {
4249 return;
4250 }
Dianne Hackborn68d76552017-02-27 15:32:03 -08004251 clonedCallbacks = new ArraySet<>(callbacks);
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004252 }
4253
Svet Ganov3a95f832018-03-23 17:44:30 -07004254 notifyOpChanged(clonedCallbacks, code, uid, null);
Jason Monk62062992014-05-06 09:55:28 -04004255 }
4256
4257 @Override
4258 public void removeUser(int userHandle) throws RemoteException {
4259 checkSystemUid("removeUser");
Svet Ganov442ed572016-08-17 17:29:43 -07004260 synchronized (AppOpsService.this) {
4261 final int tokenCount = mOpUserRestrictions.size();
4262 for (int i = tokenCount - 1; i >= 0; i--) {
4263 ClientRestrictionState opRestrictions = mOpUserRestrictions.valueAt(i);
4264 opRestrictions.removeUser(userHandle);
4265 }
Sudheer Shankabc2fadd2016-09-27 17:36:39 -07004266 removeUidsForUserLocked(userHandle);
4267 }
4268 }
4269
Jeff Sharkey35e46d22017-06-09 10:01:20 -06004270 @Override
4271 public boolean isOperationActive(int code, int uid, String packageName) {
Svet Ganovf7b47252018-02-26 11:11:27 -08004272 if (Binder.getCallingUid() != uid) {
4273 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS)
4274 != PackageManager.PERMISSION_GRANTED) {
4275 return false;
4276 }
4277 }
Jeff Sharkey35e46d22017-06-09 10:01:20 -06004278 verifyIncomingOp(code);
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08004279 final String resolvedPackageName = resolvePackageName(uid, packageName);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06004280 if (resolvedPackageName == null) {
4281 return false;
4282 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08004283 synchronized (AppOpsService.this) {
Jeff Sharkey35e46d22017-06-09 10:01:20 -06004284 for (int i = mClients.size() - 1; i >= 0; i--) {
4285 final ClientState client = mClients.valueAt(i);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06004286 for (int j = client.mStartedOps.size() - 1; j >= 0; j--) {
4287 final Op op = client.mStartedOps.get(j);
Svet Ganovaf189e32019-02-15 18:45:29 -08004288 if (op.op == code && op.uidState.uid == uid) return true;
Jeff Sharkey35e46d22017-06-09 10:01:20 -06004289 }
4290 }
4291 }
4292 return false;
4293 }
4294
Svet Ganov8455ba22019-01-02 13:05:56 -08004295 @Override
4296 public void setHistoryParameters(@AppOpsManager.HistoricalMode int mode,
4297 long baseSnapshotInterval, int compressionStep) {
4298 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
4299 "setHistoryParameters");
4300 // Must not hold the appops lock
4301 mHistoricalRegistry.setHistoryParameters(mode, baseSnapshotInterval, compressionStep);
4302 }
4303
4304 @Override
4305 public void offsetHistory(long offsetMillis) {
4306 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
4307 "offsetHistory");
4308 // Must not hold the appops lock
4309 mHistoricalRegistry.offsetHistory(offsetMillis);
4310 }
4311
4312 @Override
4313 public void addHistoricalOps(HistoricalOps ops) {
4314 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
4315 "addHistoricalOps");
4316 // Must not hold the appops lock
4317 mHistoricalRegistry.addHistoricalOps(ops);
4318 }
4319
4320 @Override
4321 public void resetHistoryParameters() {
4322 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
4323 "resetHistoryParameters");
4324 // Must not hold the appops lock
4325 mHistoricalRegistry.resetHistoryParameters();
4326 }
4327
4328 @Override
4329 public void clearHistory() {
4330 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
4331 "clearHistory");
4332 // Must not hold the appops lock
4333 mHistoricalRegistry.clearHistory();
4334 }
4335
Sudheer Shankabc2fadd2016-09-27 17:36:39 -07004336 private void removeUidsForUserLocked(int userHandle) {
4337 for (int i = mUidStates.size() - 1; i >= 0; --i) {
4338 final int uid = mUidStates.keyAt(i);
4339 if (UserHandle.getUserId(uid) == userHandle) {
4340 mUidStates.removeAt(i);
4341 }
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004342 }
4343 }
4344
Jason Monk62062992014-05-06 09:55:28 -04004345 private void checkSystemUid(String function) {
4346 int uid = Binder.getCallingUid();
4347 if (uid != Process.SYSTEM_UID) {
4348 throw new SecurityException(function + " must by called by the system");
4349 }
4350 }
4351
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00004352 private static String resolvePackageName(int uid, String packageName) {
Svet Ganov82f09bc2018-01-12 22:08:40 -08004353 if (uid == Process.ROOT_UID) {
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00004354 return "root";
4355 } else if (uid == Process.SHELL_UID) {
4356 return "com.android.shell";
Svet Ganov82f09bc2018-01-12 22:08:40 -08004357 } else if (uid == Process.MEDIA_UID) {
4358 return "media";
4359 } else if (uid == Process.AUDIOSERVER_UID) {
4360 return "audioserver";
4361 } else if (uid == Process.CAMERASERVER_UID) {
4362 return "cameraserver";
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00004363 } else if (uid == Process.SYSTEM_UID && packageName == null) {
4364 return "android";
4365 }
4366 return packageName;
4367 }
4368
Svet Ganov82f09bc2018-01-12 22:08:40 -08004369 private static int resolveUid(String packageName) {
4370 if (packageName == null) {
4371 return -1;
4372 }
4373 switch (packageName) {
4374 case "root":
4375 return Process.ROOT_UID;
4376 case "shell":
4377 return Process.SHELL_UID;
4378 case "media":
4379 return Process.MEDIA_UID;
4380 case "audioserver":
4381 return Process.AUDIOSERVER_UID;
4382 case "cameraserver":
4383 return Process.CAMERASERVER_UID;
4384 }
4385 return -1;
4386 }
4387
Svet Ganov2af57082015-07-30 08:44:20 -07004388 private static String[] getPackagesForUid(int uid) {
Svet Ganovf3807aa2015-08-02 10:09:56 -07004389 String[] packageNames = null;
Philip P. Moltmann159d98b2018-12-20 08:30:53 -08004390
4391 // Very early during boot the package manager is not yet or not yet fully started. At this
4392 // time there are no packages yet.
4393 if (AppGlobals.getPackageManager() != null) {
4394 try {
4395 packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid);
4396 } catch (RemoteException e) {
4397 /* ignore - local call */
4398 }
Svet Ganov2af57082015-07-30 08:44:20 -07004399 }
Svet Ganovf3807aa2015-08-02 10:09:56 -07004400 if (packageNames == null) {
4401 return EmptyArray.STRING;
4402 }
4403 return packageNames;
Svet Ganov2af57082015-07-30 08:44:20 -07004404 }
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07004405
4406 private final class ClientRestrictionState implements DeathRecipient {
4407 private final IBinder token;
4408 SparseArray<boolean[]> perUserRestrictions;
4409 SparseArray<String[]> perUserExcludedPackages;
4410
4411 public ClientRestrictionState(IBinder token)
4412 throws RemoteException {
4413 token.linkToDeath(this, 0);
4414 this.token = token;
4415 }
4416
4417 public boolean setRestriction(int code, boolean restricted,
4418 String[] excludedPackages, int userId) {
4419 boolean changed = false;
4420
4421 if (perUserRestrictions == null && restricted) {
4422 perUserRestrictions = new SparseArray<>();
4423 }
4424
Philip P. Moltmanne683f192017-06-23 14:05:04 -07004425 int[] users;
4426 if (userId == UserHandle.USER_ALL) {
4427 List<UserInfo> liveUsers = UserManager.get(mContext).getUsers(false);
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07004428
Philip P. Moltmanne683f192017-06-23 14:05:04 -07004429 users = new int[liveUsers.size()];
4430 for (int i = 0; i < liveUsers.size(); i++) {
4431 users[i] = liveUsers.get(i).id;
4432 }
4433 } else {
4434 users = new int[]{userId};
4435 }
4436
4437 if (perUserRestrictions != null) {
4438 int numUsers = users.length;
4439
4440 for (int i = 0; i < numUsers; i++) {
4441 int thisUserId = users[i];
4442
4443 boolean[] userRestrictions = perUserRestrictions.get(thisUserId);
4444 if (userRestrictions == null && restricted) {
4445 userRestrictions = new boolean[AppOpsManager._NUM_OP];
4446 perUserRestrictions.put(thisUserId, userRestrictions);
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07004447 }
Philip P. Moltmanne683f192017-06-23 14:05:04 -07004448 if (userRestrictions != null && userRestrictions[code] != restricted) {
4449 userRestrictions[code] = restricted;
4450 if (!restricted && isDefault(userRestrictions)) {
4451 perUserRestrictions.remove(thisUserId);
4452 userRestrictions = null;
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07004453 }
4454 changed = true;
4455 }
Philip P. Moltmanne683f192017-06-23 14:05:04 -07004456
4457 if (userRestrictions != null) {
4458 final boolean noExcludedPackages = ArrayUtils.isEmpty(excludedPackages);
4459 if (perUserExcludedPackages == null && !noExcludedPackages) {
4460 perUserExcludedPackages = new SparseArray<>();
4461 }
4462 if (perUserExcludedPackages != null && !Arrays.equals(excludedPackages,
4463 perUserExcludedPackages.get(thisUserId))) {
4464 if (noExcludedPackages) {
4465 perUserExcludedPackages.remove(thisUserId);
4466 if (perUserExcludedPackages.size() <= 0) {
4467 perUserExcludedPackages = null;
4468 }
4469 } else {
4470 perUserExcludedPackages.put(thisUserId, excludedPackages);
4471 }
4472 changed = true;
4473 }
4474 }
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07004475 }
4476 }
4477
4478 return changed;
4479 }
4480
4481 public boolean hasRestriction(int restriction, String packageName, int userId) {
4482 if (perUserRestrictions == null) {
4483 return false;
4484 }
4485 boolean[] restrictions = perUserRestrictions.get(userId);
4486 if (restrictions == null) {
4487 return false;
4488 }
4489 if (!restrictions[restriction]) {
4490 return false;
4491 }
4492 if (perUserExcludedPackages == null) {
4493 return true;
4494 }
4495 String[] perUserExclusions = perUserExcludedPackages.get(userId);
4496 if (perUserExclusions == null) {
4497 return true;
4498 }
4499 return !ArrayUtils.contains(perUserExclusions, packageName);
4500 }
4501
4502 public void removeUser(int userId) {
4503 if (perUserExcludedPackages != null) {
4504 perUserExcludedPackages.remove(userId);
4505 if (perUserExcludedPackages.size() <= 0) {
4506 perUserExcludedPackages = null;
4507 }
4508 }
Sudheer Shankabc2fadd2016-09-27 17:36:39 -07004509 if (perUserRestrictions != null) {
4510 perUserRestrictions.remove(userId);
4511 if (perUserRestrictions.size() <= 0) {
4512 perUserRestrictions = null;
4513 }
4514 }
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07004515 }
4516
4517 public boolean isDefault() {
4518 return perUserRestrictions == null || perUserRestrictions.size() <= 0;
4519 }
4520
4521 @Override
4522 public void binderDied() {
4523 synchronized (AppOpsService.this) {
4524 mOpUserRestrictions.remove(token);
4525 if (perUserRestrictions == null) {
4526 return;
4527 }
4528 final int userCount = perUserRestrictions.size();
4529 for (int i = 0; i < userCount; i++) {
4530 final boolean[] restrictions = perUserRestrictions.valueAt(i);
4531 final int restrictionCount = restrictions.length;
4532 for (int j = 0; j < restrictionCount; j++) {
4533 if (restrictions[j]) {
4534 final int changedCode = j;
Svet Ganov3a95f832018-03-23 17:44:30 -07004535 mHandler.post(() -> notifyWatchersOfChange(changedCode, UID_ANY));
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07004536 }
4537 }
4538 }
4539 destroy();
4540 }
4541 }
4542
4543 public void destroy() {
4544 token.unlinkToDeath(this, 0);
4545 }
4546
4547 private boolean isDefault(boolean[] array) {
4548 if (ArrayUtils.isEmpty(array)) {
4549 return true;
4550 }
4551 for (boolean value : array) {
4552 if (value) {
4553 return false;
4554 }
4555 }
4556 return true;
4557 }
4558 }
Dianne Hackbornd5254412018-05-11 18:02:58 -07004559
4560 private final class AppOpsManagerInternalImpl extends AppOpsManagerInternal {
4561 @Override public void setDeviceAndProfileOwners(SparseIntArray owners) {
4562 synchronized (AppOpsService.this) {
4563 mProfileOwners = owners;
4564 }
4565 }
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07004566
4567 @Override
Philip P. Moltmann159d98b2018-12-20 08:30:53 -08004568 public void setUidMode(int code, int uid, int mode) {
4569 AppOpsService.this.setUidMode(code, uid, mode);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07004570 }
Philip P. Moltmanndde07852019-01-25 16:42:36 -08004571
4572 @Override
4573 public void setAllPkgModesToDefault(int code, int uid) {
4574 AppOpsService.this.setAllPkgModesToDefault(code, uid);
4575 }
Philip P. Moltmann724150d2019-03-11 17:01:05 -07004576
4577 @Override
4578 public @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName) {
4579 return AppOpsService.this.checkOperationUnchecked(code, uid, packageName, true, false);
4580 }
Dianne Hackbornd5254412018-05-11 18:02:58 -07004581 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -08004582}