blob: c9e7cfa732597715eb7df87b6bbf01ab4c2e2723 [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);
785 final ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(OP_PLAY_AUDIO);
786 for (int i = 0; i < changedUids.length; i++) {
787 final int changedUid = changedUids[i];
788 final String changedPkg = changedPkgs[i];
789 // We trust packagemanager to insert matching uid and packageNames in the extras
790 mHandler.sendMessage(PooledLambda.obtainMessage(AppOpsService::notifyOpChanged,
791 AppOpsService.this, callbacks, OP_PLAY_AUDIO, changedUid, changedPkg));
792 }
793 }
794 }, packageSuspendFilter);
795
Suprabh Shuklaaef25132017-01-23 18:09:03 -0800796 PackageManagerInternal packageManagerInternal = LocalServices.getService(
797 PackageManagerInternal.class);
798 packageManagerInternal.setExternalSourcesPolicy(
799 new PackageManagerInternal.ExternalSourcesPolicy() {
800 @Override
801 public int getPackageTrustedToInstallApps(String packageName, int uid) {
802 int appOpMode = checkOperation(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES,
803 uid, packageName);
804 switch (appOpMode) {
805 case AppOpsManager.MODE_ALLOWED:
806 return PackageManagerInternal.ExternalSourcesPolicy.USER_TRUSTED;
807 case AppOpsManager.MODE_ERRORED:
808 return PackageManagerInternal.ExternalSourcesPolicy.USER_BLOCKED;
809 default:
810 return PackageManagerInternal.ExternalSourcesPolicy.USER_DEFAULT;
811 }
812 }
813 });
814
Jeff Sharkey10ec9d82018-11-28 14:52:45 -0700815 if (!StorageManager.hasIsolatedStorage()) {
Sudheer Shanka98cb3f02018-08-17 16:10:29 -0700816 StorageManagerInternal storageManagerInternal = LocalServices.getService(
817 StorageManagerInternal.class);
818 storageManagerInternal.addExternalStoragePolicy(
819 new StorageManagerInternal.ExternalStorageMountPolicy() {
820 @Override
821 public int getMountMode(int uid, String packageName) {
822 if (Process.isIsolated(uid)) {
823 return Zygote.MOUNT_EXTERNAL_NONE;
824 }
825 if (noteOperation(AppOpsManager.OP_READ_EXTERNAL_STORAGE, uid,
826 packageName) != AppOpsManager.MODE_ALLOWED) {
827 return Zygote.MOUNT_EXTERNAL_NONE;
828 }
829 if (noteOperation(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, uid,
830 packageName) != AppOpsManager.MODE_ALLOWED) {
831 return Zygote.MOUNT_EXTERNAL_READ;
832 }
833 return Zygote.MOUNT_EXTERNAL_WRITE;
Svet Ganov6ee871e2015-07-10 14:29:33 -0700834 }
Svet Ganov6ee871e2015-07-10 14:29:33 -0700835
Sudheer Shanka98cb3f02018-08-17 16:10:29 -0700836 @Override
837 public boolean hasExternalStorage(int uid, String packageName) {
838 final int mountMode = getMountMode(uid, packageName);
839 return mountMode == Zygote.MOUNT_EXTERNAL_READ
840 || mountMode == Zygote.MOUNT_EXTERNAL_WRITE;
841 }
842 });
843 }
Dianne Hackborn514074f2013-02-11 10:52:46 -0800844 }
845
846 public void packageRemoved(int uid, String packageName) {
847 synchronized (this) {
Svet Ganov2af57082015-07-30 08:44:20 -0700848 UidState uidState = mUidStates.get(uid);
849 if (uidState == null) {
850 return;
851 }
852
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800853 Ops ops = null;
Svet Ganov2af57082015-07-30 08:44:20 -0700854
855 // Remove any package state if such.
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800856 if (uidState.pkgOps != null) {
857 ops = uidState.pkgOps.remove(packageName);
Svet Ganov2af57082015-07-30 08:44:20 -0700858 }
859
860 // If we just nuked the last package state check if the UID is valid.
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800861 if (ops != null && uidState.pkgOps.isEmpty()
Svet Ganov2af57082015-07-30 08:44:20 -0700862 && getPackagesForUid(uid).length <= 0) {
863 mUidStates.remove(uid);
864 }
865
Svet Ganova7a0db62018-02-27 20:08:01 -0800866 // Finish ops other packages started on behalf of the package.
867 final int clientCount = mClients.size();
868 for (int i = 0; i < clientCount; i++) {
869 final ClientState client = mClients.valueAt(i);
870 if (client.mStartedOps == null) {
871 continue;
872 }
873 final int opCount = client.mStartedOps.size();
874 for (int j = opCount - 1; j >= 0; j--) {
875 final Op op = client.mStartedOps.get(j);
Svet Ganovaf189e32019-02-15 18:45:29 -0800876 if (uid == op.uidState.uid && packageName.equals(op.packageName)) {
Svet Ganova7a0db62018-02-27 20:08:01 -0800877 finishOperationLocked(op, /*finishNested*/ true);
878 client.mStartedOps.remove(j);
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700879 if (op.startNesting <= 0) {
Svet Ganova7a0db62018-02-27 20:08:01 -0800880 scheduleOpActiveChangedIfNeededLocked(op.op,
881 uid, packageName, false);
882 }
883 }
884 }
885 }
886
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800887 if (ops != null) {
Svet Ganov2af57082015-07-30 08:44:20 -0700888 scheduleFastWriteLocked();
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800889
890 final int opCount = ops.size();
891 for (int i = 0; i < opCount; i++) {
892 final Op op = ops.valueAt(i);
Svet Ganovaf189e32019-02-15 18:45:29 -0800893 if (op.running) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800894 scheduleOpActiveChangedIfNeededLocked(
Svet Ganovaf189e32019-02-15 18:45:29 -0800895 op.op, op.uidState.uid, op.packageName, false);
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -0800896 }
897 }
Dianne Hackborn514074f2013-02-11 10:52:46 -0800898 }
899 }
900 }
901
902 public void uidRemoved(int uid) {
903 synchronized (this) {
Svet Ganov2af57082015-07-30 08:44:20 -0700904 if (mUidStates.indexOfKey(uid) >= 0) {
905 mUidStates.remove(uid);
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -0800906 scheduleFastWriteLocked();
Dianne Hackborn514074f2013-02-11 10:52:46 -0800907 }
908 }
909 }
910
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700911 public void updateUidProcState(int uid, int procState) {
912 synchronized (this) {
913 final UidState uidState = getUidStateLocked(uid, true);
Amith Yamasania0a30a12019-01-22 11:38:06 -0800914 int newState = PROCESS_STATE_TO_UID_STATE[procState];
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700915 if (uidState != null && uidState.pendingState != newState) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700916 final int oldPendingState = uidState.pendingState;
917 uidState.pendingState = newState;
Svet Ganovaf189e32019-02-15 18:45:29 -0800918 if (newState < uidState.state || newState <= UID_STATE_MAX_LAST_NON_RESTRICTED) {
Dianne Hackborne93ab412018-05-14 17:52:30 -0700919 // We are moving to a more important state, or the new state is in the
920 // foreground, then always do it immediately.
Dianne Hackborn65a4f252018-05-08 17:30:48 -0700921 commitUidPendingStateLocked(uidState);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700922 } else if (uidState.pendingStateCommitTime == 0) {
923 // We are moving to a less important state for the first time,
924 // delay the application for a bit.
Dianne Hackborne93ab412018-05-14 17:52:30 -0700925 final long settleTime;
926 if (uidState.state <= UID_STATE_TOP) {
927 settleTime = mConstants.TOP_STATE_SETTLE_TIME;
928 } else if (uidState.state <= UID_STATE_FOREGROUND_SERVICE) {
929 settleTime = mConstants.FG_SERVICE_STATE_SETTLE_TIME;
930 } else {
931 settleTime = mConstants.BG_STATE_SETTLE_TIME;
932 }
Dianne Hackborn9fb93502018-06-18 12:29:44 -0700933 uidState.pendingStateCommitTime = SystemClock.elapsedRealtime() + settleTime;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -0700934 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700935 if (uidState.startNesting != 0) {
936 // There is some actively running operation... need to find it
937 // and appropriately update its state.
938 final long now = System.currentTimeMillis();
939 for (int i = uidState.pkgOps.size() - 1; i >= 0; i--) {
940 final Ops ops = uidState.pkgOps.valueAt(i);
941 for (int j = ops.size() - 1; j >= 0; j--) {
942 final Op op = ops.valueAt(j);
943 if (op.startNesting > 0) {
Svet Ganovaf189e32019-02-15 18:45:29 -0800944 final long duration = SystemClock.elapsedRealtime()
945 - op.startRealtime;
946 // We don't support proxy long running ops (start/stop)
947 mHistoricalRegistry.increaseOpAccessDuration(op.op,
948 op.uidState.uid, op.packageName, oldPendingState,
949 AppOpsManager.OP_FLAG_SELF, duration);
950 // Finish the op in the old state
951 op.finished(now, duration, oldPendingState,
952 AppOpsManager.OP_FLAG_SELF);
953 // Start the op in the new state
954 op.startRealtime = now;
955 op.started(now, newState, AppOpsManager.OP_FLAG_SELF);
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700956 }
957 }
958 }
959 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700960 }
961 }
962 }
963
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800964 public void shutdown() {
965 Slog.w(TAG, "Writing app ops before shutdown...");
Dianne Hackborn35654b62013-01-14 17:38:02 -0800966 boolean doWrite = false;
967 synchronized (this) {
968 if (mWriteScheduled) {
969 mWriteScheduled = false;
970 doWrite = true;
971 }
972 }
973 if (doWrite) {
974 writeState();
975 }
976 }
977
Dianne Hackborn72e39832013-01-18 18:36:09 -0800978 private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) {
979 ArrayList<AppOpsManager.OpEntry> resOps = null;
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700980 final long elapsedNow = SystemClock.elapsedRealtime();
Dianne Hackborn72e39832013-01-18 18:36:09 -0800981 if (ops == null) {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700982 resOps = new ArrayList<>();
Dianne Hackborn72e39832013-01-18 18:36:09 -0800983 for (int j=0; j<pkgOps.size(); j++) {
984 Op curOp = pkgOps.valueAt(j);
Svet Ganovaf189e32019-02-15 18:45:29 -0800985 resOps.add(getOpEntryForResult(curOp, elapsedNow));
Dianne Hackborn72e39832013-01-18 18:36:09 -0800986 }
987 } else {
988 for (int j=0; j<ops.length; j++) {
989 Op curOp = pkgOps.get(ops[j]);
990 if (curOp != null) {
991 if (resOps == null) {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -0700992 resOps = new ArrayList<>();
Dianne Hackborn72e39832013-01-18 18:36:09 -0800993 }
Svet Ganovaf189e32019-02-15 18:45:29 -0800994 resOps.add(getOpEntryForResult(curOp, elapsedNow));
Dianne Hackborn72e39832013-01-18 18:36:09 -0800995 }
996 }
997 }
998 return resOps;
999 }
1000
Dianne Hackbornc7214a32017-04-11 13:32:47 -07001001 private ArrayList<AppOpsManager.OpEntry> collectOps(SparseIntArray uidOps, int[] ops) {
Eugene Suslae4ee2c22018-11-05 12:23:30 -08001002 if (uidOps == null) {
1003 return null;
1004 }
Dianne Hackbornc7214a32017-04-11 13:32:47 -07001005 ArrayList<AppOpsManager.OpEntry> resOps = null;
1006 if (ops == null) {
1007 resOps = new ArrayList<>();
1008 for (int j=0; j<uidOps.size(); j++) {
Svet Ganovaf189e32019-02-15 18:45:29 -08001009 resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j)));
Dianne Hackbornc7214a32017-04-11 13:32:47 -07001010 }
1011 } else {
1012 for (int j=0; j<ops.length; j++) {
1013 int index = uidOps.indexOfKey(ops[j]);
1014 if (index >= 0) {
1015 if (resOps == null) {
1016 resOps = new ArrayList<>();
1017 }
Svet Ganovaf189e32019-02-15 18:45:29 -08001018 resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j)));
Dianne Hackbornc7214a32017-04-11 13:32:47 -07001019 }
1020 }
1021 }
1022 return resOps;
1023 }
1024
Svet Ganovaf189e32019-02-15 18:45:29 -08001025 private static @NonNull OpEntry getOpEntryForResult(@NonNull Op op, long elapsedNow) {
1026 if (op.running) {
1027 op.continuing(elapsedNow - op.startRealtime,
1028 op.uidState.state, AppOpsManager.OP_FLAG_SELF);
1029 }
1030 final OpEntry entry = new OpEntry(op.op, op.running, op.mode,
1031 op.mAccessTimes != null ? op.mAccessTimes.clone() : null,
1032 op.mRejectTimes != null ? op.mRejectTimes.clone() : null,
1033 op.mDurations != null ? op.mDurations.clone() : null,
1034 op.mProxyUids != null ? op.mProxyUids.clone() : null,
1035 op.mProxyPackageNames != null ? op.mProxyPackageNames.clone() : null);
1036 return entry;
1037 }
1038
Dianne Hackborn35654b62013-01-14 17:38:02 -08001039 @Override
1040 public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
1041 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
1042 Binder.getCallingPid(), Binder.getCallingUid(), null);
1043 ArrayList<AppOpsManager.PackageOps> res = null;
1044 synchronized (this) {
Svet Ganov2af57082015-07-30 08:44:20 -07001045 final int uidStateCount = mUidStates.size();
1046 for (int i = 0; i < uidStateCount; i++) {
1047 UidState uidState = mUidStates.valueAt(i);
1048 if (uidState.pkgOps == null || uidState.pkgOps.isEmpty()) {
1049 continue;
1050 }
1051 ArrayMap<String, Ops> packages = uidState.pkgOps;
1052 final int packageCount = packages.size();
1053 for (int j = 0; j < packageCount; j++) {
1054 Ops pkgOps = packages.valueAt(j);
Dianne Hackborn72e39832013-01-18 18:36:09 -08001055 ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
Dianne Hackborn35654b62013-01-14 17:38:02 -08001056 if (resOps != null) {
1057 if (res == null) {
1058 res = new ArrayList<AppOpsManager.PackageOps>();
1059 }
1060 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
Svet Ganov2af57082015-07-30 08:44:20 -07001061 pkgOps.packageName, pkgOps.uidState.uid, resOps);
Dianne Hackborn35654b62013-01-14 17:38:02 -08001062 res.add(resPackage);
1063 }
1064 }
1065 }
1066 }
1067 return res;
1068 }
1069
1070 @Override
Dianne Hackborn72e39832013-01-18 18:36:09 -08001071 public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName,
1072 int[] ops) {
1073 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
1074 Binder.getCallingPid(), Binder.getCallingUid(), null);
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00001075 String resolvedPackageName = resolvePackageName(uid, packageName);
1076 if (resolvedPackageName == null) {
1077 return Collections.emptyList();
1078 }
Dianne Hackborn72e39832013-01-18 18:36:09 -08001079 synchronized (this) {
Yohei Yukawaa965d652017-10-12 15:02:26 -07001080 Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false /* edit */,
1081 false /* uidMismatchExpected */);
Dianne Hackborn72e39832013-01-18 18:36:09 -08001082 if (pkgOps == null) {
1083 return null;
1084 }
1085 ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
1086 if (resOps == null) {
1087 return null;
1088 }
1089 ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>();
1090 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
Svet Ganov2af57082015-07-30 08:44:20 -07001091 pkgOps.packageName, pkgOps.uidState.uid, resOps);
Dianne Hackborn72e39832013-01-18 18:36:09 -08001092 res.add(resPackage);
1093 return res;
1094 }
1095 }
1096
Dianne Hackbornc7214a32017-04-11 13:32:47 -07001097 @Override
Svet Ganov8455ba22019-01-02 13:05:56 -08001098 public void getHistoricalOps(int uid, @NonNull String packageName,
Svet Ganov23c88db2019-01-22 20:38:11 -08001099 @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis,
Svet Ganovaf189e32019-02-15 18:45:29 -08001100 @OpFlags int flags, @NonNull RemoteCallback callback) {
Svet Ganov23c88db2019-01-22 20:38:11 -08001101 // Use the builder to validate arguments.
Svet Ganovaf189e32019-02-15 18:45:29 -08001102 new HistoricalOpsRequest.Builder(
Svet Ganov23c88db2019-01-22 20:38:11 -08001103 beginTimeMillis, endTimeMillis)
1104 .setUid(uid)
1105 .setPackageName(packageName)
1106 .setOpNames(opNames)
Svet Ganovaf189e32019-02-15 18:45:29 -08001107 .setFlags(flags)
Svet Ganov23c88db2019-01-22 20:38:11 -08001108 .build();
Svet Ganov8455ba22019-01-02 13:05:56 -08001109 Preconditions.checkNotNull(callback, "callback cannot be null");
Svet Ganovad0a49b2018-10-29 10:07:08 -07001110
1111 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
Svet Ganov8455ba22019-01-02 13:05:56 -08001112 Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");
Svet Ganovad0a49b2018-10-29 10:07:08 -07001113
Svet Ganov23c88db2019-01-22 20:38:11 -08001114 final String[] opNamesArray = (opNames != null)
1115 ? opNames.toArray(new String[opNames.size()]) : null;
Svet Ganovad0a49b2018-10-29 10:07:08 -07001116
Svet Ganovaf189e32019-02-15 18:45:29 -08001117 // Must not hold the appops lock
1118 mHistoricalRegistry.getHistoricalOps(uid, packageName, opNamesArray,
1119 beginTimeMillis, endTimeMillis, flags, callback);
Svet Ganovad0a49b2018-10-29 10:07:08 -07001120 }
1121
1122 @Override
Svet Ganov8455ba22019-01-02 13:05:56 -08001123 public void getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName,
Svet Ganov23c88db2019-01-22 20:38:11 -08001124 @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis,
Svet Ganovaf189e32019-02-15 18:45:29 -08001125 @OpFlags int flags, @NonNull RemoteCallback callback) {
Svet Ganov23c88db2019-01-22 20:38:11 -08001126 // Use the builder to validate arguments.
Svet Ganovaf189e32019-02-15 18:45:29 -08001127 new HistoricalOpsRequest.Builder(
Svet Ganov23c88db2019-01-22 20:38:11 -08001128 beginTimeMillis, endTimeMillis)
1129 .setUid(uid)
1130 .setPackageName(packageName)
1131 .setOpNames(opNames)
Svet Ganovaf189e32019-02-15 18:45:29 -08001132 .setFlags(flags)
Svet Ganov23c88db2019-01-22 20:38:11 -08001133 .build();
Svet Ganov8455ba22019-01-02 13:05:56 -08001134 Preconditions.checkNotNull(callback, "callback cannot be null");
Svet Ganovad0a49b2018-10-29 10:07:08 -07001135
Svet Ganov8e5bf962019-03-19 23:59:03 -07001136 mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS,
Svet Ganov8455ba22019-01-02 13:05:56 -08001137 Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");
Svet Ganovad0a49b2018-10-29 10:07:08 -07001138
Svet Ganov23c88db2019-01-22 20:38:11 -08001139 final String[] opNamesArray = (opNames != null)
1140 ? opNames.toArray(new String[opNames.size()]) : null;
1141
Svet Ganov8455ba22019-01-02 13:05:56 -08001142 // Must not hold the appops lock
Svet Ganov23c88db2019-01-22 20:38:11 -08001143 mHistoricalRegistry.getHistoricalOpsFromDiskRaw(uid, packageName, opNamesArray,
Svet Ganovaf189e32019-02-15 18:45:29 -08001144 beginTimeMillis, endTimeMillis, flags, callback);
Svet Ganovad0a49b2018-10-29 10:07:08 -07001145 }
1146
1147 @Override
Svet Ganov8e5bf962019-03-19 23:59:03 -07001148 public void reloadNonHistoricalState() {
1149 mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS,
1150 Binder.getCallingPid(), Binder.getCallingUid(), "reloadNonHistoricalState");
1151 writeState();
1152 readState();
1153 }
1154
1155 @Override
Dianne Hackbornc7214a32017-04-11 13:32:47 -07001156 public List<AppOpsManager.PackageOps> getUidOps(int uid, int[] ops) {
1157 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
1158 Binder.getCallingPid(), Binder.getCallingUid(), null);
1159 synchronized (this) {
1160 UidState uidState = getUidStateLocked(uid, false);
1161 if (uidState == null) {
1162 return null;
1163 }
1164 ArrayList<AppOpsManager.OpEntry> resOps = collectOps(uidState.opModes, ops);
1165 if (resOps == null) {
1166 return null;
1167 }
1168 ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>();
1169 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
1170 null, uidState.uid, resOps);
1171 res.add(resPackage);
1172 return res;
1173 }
1174 }
1175
Dianne Hackborn607b4142013-08-02 18:10:10 -07001176 private void pruneOp(Op op, int uid, String packageName) {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07001177 if (!op.hasAnyTime()) {
Yohei Yukawaa965d652017-10-12 15:02:26 -07001178 Ops ops = getOpsRawLocked(uid, packageName, false /* edit */,
1179 false /* uidMismatchExpected */);
Dianne Hackborn607b4142013-08-02 18:10:10 -07001180 if (ops != null) {
1181 ops.remove(op.op);
1182 if (ops.size() <= 0) {
Svet Ganov2af57082015-07-30 08:44:20 -07001183 UidState uidState = ops.uidState;
1184 ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
Dianne Hackborn607b4142013-08-02 18:10:10 -07001185 if (pkgOps != null) {
1186 pkgOps.remove(ops.packageName);
Svet Ganov2af57082015-07-30 08:44:20 -07001187 if (pkgOps.isEmpty()) {
1188 uidState.pkgOps = null;
1189 }
1190 if (uidState.isDefault()) {
1191 mUidStates.remove(uid);
Dianne Hackborn607b4142013-08-02 18:10:10 -07001192 }
1193 }
1194 }
1195 }
1196 }
1197 }
1198
Svet Ganovaf189e32019-02-15 18:45:29 -08001199 private void enforceManageAppOpsModes(int callingPid, int callingUid, int targetUid) {
Dianne Hackbornd5254412018-05-11 18:02:58 -07001200 if (callingPid == Process.myPid()) {
1201 return;
1202 }
1203 final int callingUser = UserHandle.getUserId(callingUid);
1204 synchronized (this) {
1205 if (mProfileOwners != null && mProfileOwners.get(callingUser, -1) == callingUid) {
1206 if (targetUid >= 0 && callingUser == UserHandle.getUserId(targetUid)) {
1207 // Profile owners are allowed to change modes but only for apps
1208 // within their user.
1209 return;
1210 }
1211 }
1212 }
1213 mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
1214 Binder.getCallingPid(), Binder.getCallingUid(), null);
1215 }
1216
Dianne Hackborn72e39832013-01-18 18:36:09 -08001217 @Override
Svet Ganov2af57082015-07-30 08:44:20 -07001218 public void setUidMode(int code, int uid, int mode) {
Eugene Suslae4ee2c22018-11-05 12:23:30 -08001219 if (DEBUG) {
1220 Slog.i(TAG, "uid " + uid + " OP_" + opToName(code) + " := " + modeToName(mode)
1221 + " by uid " + Binder.getCallingUid());
1222 }
1223
Dianne Hackbornd5254412018-05-11 18:02:58 -07001224 enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
Svet Ganov2af57082015-07-30 08:44:20 -07001225 verifyIncomingOp(code);
1226 code = AppOpsManager.opToSwitch(code);
1227
1228 synchronized (this) {
1229 final int defaultMode = AppOpsManager.opToDefaultMode(code);
1230
1231 UidState uidState = getUidStateLocked(uid, false);
1232 if (uidState == null) {
1233 if (mode == defaultMode) {
1234 return;
1235 }
1236 uidState = new UidState(uid);
1237 uidState.opModes = new SparseIntArray();
1238 uidState.opModes.put(code, mode);
1239 mUidStates.put(uid, uidState);
1240 scheduleWriteLocked();
1241 } else if (uidState.opModes == null) {
1242 if (mode != defaultMode) {
1243 uidState.opModes = new SparseIntArray();
1244 uidState.opModes.put(code, mode);
1245 scheduleWriteLocked();
1246 }
1247 } else {
Hai Zhang2b98fb32018-09-21 15:18:46 -07001248 if (uidState.opModes.indexOfKey(code) >= 0 && uidState.opModes.get(code) == mode) {
Svet Ganov2af57082015-07-30 08:44:20 -07001249 return;
1250 }
1251 if (mode == defaultMode) {
1252 uidState.opModes.delete(code);
1253 if (uidState.opModes.size() <= 0) {
1254 uidState.opModes = null;
1255 }
1256 } else {
1257 uidState.opModes.put(code, mode);
1258 }
1259 scheduleWriteLocked();
1260 }
Wei Wang711eb662019-03-21 18:24:17 -07001261 uidState.evalForegroundOps(mOpModeWatchers);
Svet Ganov2af57082015-07-30 08:44:20 -07001262 }
1263
Svetoslav215b44a2015-08-04 19:03:40 -07001264 String[] uidPackageNames = getPackagesForUid(uid);
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001265 ArrayMap<ModeCallback, ArraySet<String>> callbackSpecs = null;
Svet Ganov2af57082015-07-30 08:44:20 -07001266
riddle_hsu40b300f2015-11-23 13:22:03 +08001267 synchronized (this) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001268 ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code);
Svet Ganov2af57082015-07-30 08:44:20 -07001269 if (callbacks != null) {
Svet Ganov2af57082015-07-30 08:44:20 -07001270 final int callbackCount = callbacks.size();
1271 for (int i = 0; i < callbackCount; i++) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001272 ModeCallback callback = callbacks.valueAt(i);
riddle_hsu40b300f2015-11-23 13:22:03 +08001273 ArraySet<String> changedPackages = new ArraySet<>();
1274 Collections.addAll(changedPackages, uidPackageNames);
Dianne Hackborn65a4f252018-05-08 17:30:48 -07001275 if (callbackSpecs == null) {
1276 callbackSpecs = new ArrayMap<>();
1277 }
riddle_hsu40b300f2015-11-23 13:22:03 +08001278 callbackSpecs.put(callback, changedPackages);
1279 }
1280 }
1281
1282 for (String uidPackageName : uidPackageNames) {
1283 callbacks = mPackageModeWatchers.get(uidPackageName);
1284 if (callbacks != null) {
1285 if (callbackSpecs == null) {
1286 callbackSpecs = new ArrayMap<>();
Svet Ganov2af57082015-07-30 08:44:20 -07001287 }
riddle_hsu40b300f2015-11-23 13:22:03 +08001288 final int callbackCount = callbacks.size();
1289 for (int i = 0; i < callbackCount; i++) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001290 ModeCallback callback = callbacks.valueAt(i);
riddle_hsu40b300f2015-11-23 13:22:03 +08001291 ArraySet<String> changedPackages = callbackSpecs.get(callback);
1292 if (changedPackages == null) {
1293 changedPackages = new ArraySet<>();
1294 callbackSpecs.put(callback, changedPackages);
1295 }
1296 changedPackages.add(uidPackageName);
1297 }
Svet Ganov2af57082015-07-30 08:44:20 -07001298 }
1299 }
1300 }
1301
1302 if (callbackSpecs == null) {
1303 return;
1304 }
1305
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001306 for (int i = 0; i < callbackSpecs.size(); i++) {
1307 final ModeCallback callback = callbackSpecs.keyAt(i);
1308 final ArraySet<String> reportedPackageNames = callbackSpecs.valueAt(i);
1309 if (reportedPackageNames == null) {
1310 mHandler.sendMessage(PooledLambda.obtainMessage(
1311 AppOpsService::notifyOpChanged,
1312 this, callback, code, uid, (String) null));
1313
1314 } else {
1315 final int reportedPackageCount = reportedPackageNames.size();
1316 for (int j = 0; j < reportedPackageCount; j++) {
1317 final String reportedPackageName = reportedPackageNames.valueAt(j);
1318 mHandler.sendMessage(PooledLambda.obtainMessage(
1319 AppOpsService::notifyOpChanged,
1320 this, callback, code, uid, reportedPackageName));
Svet Ganov2af57082015-07-30 08:44:20 -07001321 }
1322 }
Svet Ganov2af57082015-07-30 08:44:20 -07001323 }
1324 }
1325
Philip P. Moltmanndde07852019-01-25 16:42:36 -08001326 /**
1327 * Set all {@link #setMode (package) modes} for this uid to the default value.
1328 *
1329 * @param code The app-op
1330 * @param uid The uid
1331 */
1332 private void setAllPkgModesToDefault(int code, int uid) {
1333 synchronized (this) {
1334 UidState uidState = getUidStateLocked(uid, false);
1335 if (uidState == null) {
1336 return;
1337 }
1338
1339 ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
1340 if (pkgOps == null) {
1341 return;
1342 }
1343
Svet Ganovaf189e32019-02-15 18:45:29 -08001344 boolean scheduleWrite = false;
1345
Philip P. Moltmanndde07852019-01-25 16:42:36 -08001346 int numPkgs = pkgOps.size();
1347 for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) {
1348 Ops ops = pkgOps.valueAt(pkgNum);
1349
1350 Op op = ops.get(code);
1351 if (op == null) {
1352 continue;
1353 }
1354
1355 int defaultMode = AppOpsManager.opToDefaultMode(code);
1356 if (op.mode != defaultMode) {
Philip P. Moltmanndde07852019-01-25 16:42:36 -08001357 op.mode = defaultMode;
Svet Ganovaf189e32019-02-15 18:45:29 -08001358 scheduleWrite = true;
Philip P. Moltmanndde07852019-01-25 16:42:36 -08001359 }
1360 }
Svet Ganovaf189e32019-02-15 18:45:29 -08001361
1362 if (scheduleWrite) {
1363 scheduleWriteLocked();
1364 }
Philip P. Moltmanndde07852019-01-25 16:42:36 -08001365 }
1366 }
1367
Svet Ganov2af57082015-07-30 08:44:20 -07001368 @Override
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001369 public void setMode(int code, int uid, String packageName, int mode) {
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07001370 setMode(code, uid, packageName, mode, true, false);
1371 }
1372
1373 /**
1374 * Sets the mode for a certain op and uid.
1375 *
1376 * @param code The op code to set
1377 * @param uid The UID for which to set
1378 * @param packageName The package for which to set
1379 * @param mode The new mode to set
1380 * @param verifyUid Iff {@code true}, check that the package name belongs to the uid
1381 * @param isPrivileged Whether the package is privileged. (Only used if {@code verifyUid ==
1382 * false})
1383 */
1384 private void setMode(int code, int uid, @NonNull String packageName, int mode,
1385 boolean verifyUid, boolean isPrivileged) {
Dianne Hackbornd5254412018-05-11 18:02:58 -07001386 enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
Dianne Hackborn961321f2013-02-05 17:22:41 -08001387 verifyIncomingOp(code);
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001388 ArraySet<ModeCallback> repCbs = null;
Dianne Hackbornc2293022013-02-06 23:14:49 -08001389 code = AppOpsManager.opToSwitch(code);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001390 synchronized (this) {
Svet Ganov2af57082015-07-30 08:44:20 -07001391 UidState uidState = getUidStateLocked(uid, false);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07001392 Op op = getOpLocked(code, uid, packageName, true, verifyUid, isPrivileged);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001393 if (op != null) {
1394 if (op.mode != mode) {
1395 op.mode = mode;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07001396 if (uidState != null) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07001397 uidState.evalForegroundOps(mOpModeWatchers);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07001398 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001399 ArraySet<ModeCallback> cbs = mOpModeWatchers.get(code);
Dianne Hackbornc2293022013-02-06 23:14:49 -08001400 if (cbs != null) {
1401 if (repCbs == null) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001402 repCbs = new ArraySet<>();
Dianne Hackbornc2293022013-02-06 23:14:49 -08001403 }
1404 repCbs.addAll(cbs);
1405 }
1406 cbs = mPackageModeWatchers.get(packageName);
1407 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 }
David Braunf5d83192013-09-16 13:43:51 -07001413 if (mode == AppOpsManager.opToDefaultMode(op.op)) {
Dianne Hackborn514074f2013-02-11 10:52:46 -08001414 // If going into the default mode, prune this op
1415 // if there is nothing else interesting in it.
Dianne Hackborn607b4142013-08-02 18:10:10 -07001416 pruneOp(op, uid, packageName);
Dianne Hackborn514074f2013-02-11 10:52:46 -08001417 }
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -08001418 scheduleFastWriteLocked();
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001419 }
1420 }
1421 }
Dianne Hackbornc2293022013-02-06 23:14:49 -08001422 if (repCbs != null) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001423 mHandler.sendMessage(PooledLambda.obtainMessage(
1424 AppOpsService::notifyOpChanged,
1425 this, repCbs, code, uid, packageName));
Dianne Hackbornc2293022013-02-06 23:14:49 -08001426 }
1427 }
1428
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001429 private void notifyOpChanged(ArraySet<ModeCallback> callbacks, int code,
1430 int uid, String packageName) {
1431 for (int i = 0; i < callbacks.size(); i++) {
1432 final ModeCallback callback = callbacks.valueAt(i);
1433 notifyOpChanged(callback, code, uid, packageName);
1434 }
1435 }
1436
1437 private void notifyOpChanged(ModeCallback callback, int code,
1438 int uid, String packageName) {
Dianne Hackborn3b563fc2018-04-16 17:17:14 -07001439 if (uid != UID_ANY && callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001440 return;
1441 }
1442 // There are components watching for mode changes such as window manager
1443 // and location manager which are in our process. The callbacks in these
1444 // components may require permissions our remote caller does not have.
1445 final long identity = Binder.clearCallingIdentity();
1446 try {
1447 callback.mCallback.opChanged(code, uid, packageName);
1448 } catch (RemoteException e) {
1449 /* ignore */
1450 } finally {
1451 Binder.restoreCallingIdentity(identity);
1452 }
1453 }
1454
1455 private static HashMap<ModeCallback, ArrayList<ChangeRec>> addCallbacks(
1456 HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks,
1457 int op, int uid, String packageName, ArraySet<ModeCallback> cbs) {
Dianne Hackborn607b4142013-08-02 18:10:10 -07001458 if (cbs == null) {
1459 return callbacks;
1460 }
1461 if (callbacks == null) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001462 callbacks = new HashMap<>();
Dianne Hackborn607b4142013-08-02 18:10:10 -07001463 }
Svet Ganov2af57082015-07-30 08:44:20 -07001464 boolean duplicate = false;
Dianne Hackborn68d76552017-02-27 15:32:03 -08001465 final int N = cbs.size();
1466 for (int i=0; i<N; i++) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001467 ModeCallback cb = cbs.valueAt(i);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001468 ArrayList<ChangeRec> reports = callbacks.get(cb);
Dianne Hackborn607b4142013-08-02 18:10:10 -07001469 if (reports == null) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001470 reports = new ArrayList<>();
Dianne Hackborn607b4142013-08-02 18:10:10 -07001471 callbacks.put(cb, reports);
Svet Ganov2af57082015-07-30 08:44:20 -07001472 } else {
1473 final int reportCount = reports.size();
1474 for (int j = 0; j < reportCount; j++) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001475 ChangeRec report = reports.get(j);
1476 if (report.op == op && report.pkg.equals(packageName)) {
Svet Ganov2af57082015-07-30 08:44:20 -07001477 duplicate = true;
1478 break;
1479 }
1480 }
Dianne Hackborn607b4142013-08-02 18:10:10 -07001481 }
Svet Ganov2af57082015-07-30 08:44:20 -07001482 if (!duplicate) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001483 reports.add(new ChangeRec(op, uid, packageName));
Svet Ganov2af57082015-07-30 08:44:20 -07001484 }
Dianne Hackborn607b4142013-08-02 18:10:10 -07001485 }
1486 return callbacks;
1487 }
1488
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001489 static final class ChangeRec {
1490 final int op;
1491 final int uid;
1492 final String pkg;
1493
1494 ChangeRec(int _op, int _uid, String _pkg) {
1495 op = _op;
1496 uid = _uid;
1497 pkg = _pkg;
1498 }
1499 }
1500
Dianne Hackborn607b4142013-08-02 18:10:10 -07001501 @Override
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -08001502 public void resetAllModes(int reqUserId, String reqPackageName) {
1503 final int callingPid = Binder.getCallingPid();
1504 final int callingUid = Binder.getCallingUid();
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -08001505 reqUserId = ActivityManager.handleIncomingUser(callingPid, callingUid, reqUserId,
1506 true, true, "resetAllModes", null);
Svet Ganov2af57082015-07-30 08:44:20 -07001507
1508 int reqUid = -1;
1509 if (reqPackageName != null) {
1510 try {
1511 reqUid = AppGlobals.getPackageManager().getPackageUid(
Jeff Sharkeycd654482016-01-08 17:42:11 -07001512 reqPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, reqUserId);
Svet Ganov2af57082015-07-30 08:44:20 -07001513 } catch (RemoteException e) {
1514 /* ignore - local call */
1515 }
1516 }
1517
Dianne Hackbornd5254412018-05-11 18:02:58 -07001518 enforceManageAppOpsModes(callingPid, callingUid, reqUid);
1519
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001520 HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks = null;
Dianne Hackborn607b4142013-08-02 18:10:10 -07001521 synchronized (this) {
1522 boolean changed = false;
Svet Ganov2af57082015-07-30 08:44:20 -07001523 for (int i = mUidStates.size() - 1; i >= 0; i--) {
1524 UidState uidState = mUidStates.valueAt(i);
1525
1526 SparseIntArray opModes = uidState.opModes;
1527 if (opModes != null && (uidState.uid == reqUid || reqUid == -1)) {
1528 final int uidOpCount = opModes.size();
1529 for (int j = uidOpCount - 1; j >= 0; j--) {
1530 final int code = opModes.keyAt(j);
1531 if (AppOpsManager.opAllowsReset(code)) {
1532 opModes.removeAt(j);
1533 if (opModes.size() <= 0) {
1534 uidState.opModes = null;
1535 }
1536 for (String packageName : getPackagesForUid(uidState.uid)) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001537 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
Svet Ganov2af57082015-07-30 08:44:20 -07001538 mOpModeWatchers.get(code));
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001539 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
Svet Ganov2af57082015-07-30 08:44:20 -07001540 mPackageModeWatchers.get(packageName));
1541 }
1542 }
1543 }
1544 }
1545
1546 if (uidState.pkgOps == null) {
1547 continue;
1548 }
1549
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -08001550 if (reqUserId != UserHandle.USER_ALL
Svet Ganov2af57082015-07-30 08:44:20 -07001551 && reqUserId != UserHandle.getUserId(uidState.uid)) {
Alexandra Gherghinad6a98972014-08-04 17:05:34 +01001552 // Skip any ops for a different user
1553 continue;
1554 }
Svet Ganov2af57082015-07-30 08:44:20 -07001555
1556 Map<String, Ops> packages = uidState.pkgOps;
Dianne Hackborn7f09ec32013-08-07 15:36:08 -07001557 Iterator<Map.Entry<String, Ops>> it = packages.entrySet().iterator();
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07001558 boolean uidChanged = false;
Dianne Hackborn7f09ec32013-08-07 15:36:08 -07001559 while (it.hasNext()) {
1560 Map.Entry<String, Ops> ent = it.next();
Dianne Hackborn607b4142013-08-02 18:10:10 -07001561 String packageName = ent.getKey();
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -08001562 if (reqPackageName != null && !reqPackageName.equals(packageName)) {
1563 // Skip any ops for a different package
1564 continue;
1565 }
Dianne Hackborn607b4142013-08-02 18:10:10 -07001566 Ops pkgOps = ent.getValue();
Dianne Hackborn7f09ec32013-08-07 15:36:08 -07001567 for (int j=pkgOps.size()-1; j>=0; j--) {
Dianne Hackborn607b4142013-08-02 18:10:10 -07001568 Op curOp = pkgOps.valueAt(j);
Dianne Hackborn8828d3a2013-09-25 16:47:10 -07001569 if (AppOpsManager.opAllowsReset(curOp.op)
1570 && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) {
David Braunf5d83192013-09-16 13:43:51 -07001571 curOp.mode = AppOpsManager.opToDefaultMode(curOp.op);
Dianne Hackborn607b4142013-08-02 18:10:10 -07001572 changed = true;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07001573 uidChanged = true;
Svet Ganovaf189e32019-02-15 18:45:29 -08001574 final int uid = curOp.uidState.uid;
1575 callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
Dianne Hackborn607b4142013-08-02 18:10:10 -07001576 mOpModeWatchers.get(curOp.op));
Svet Ganovaf189e32019-02-15 18:45:29 -08001577 callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
Dianne Hackborn607b4142013-08-02 18:10:10 -07001578 mPackageModeWatchers.get(packageName));
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07001579 if (!curOp.hasAnyTime()) {
Dianne Hackborn7f09ec32013-08-07 15:36:08 -07001580 pkgOps.removeAt(j);
1581 }
Dianne Hackborn607b4142013-08-02 18:10:10 -07001582 }
1583 }
Dianne Hackborn7f09ec32013-08-07 15:36:08 -07001584 if (pkgOps.size() == 0) {
1585 it.remove();
1586 }
1587 }
Svet Ganov2af57082015-07-30 08:44:20 -07001588 if (uidState.isDefault()) {
1589 mUidStates.remove(uidState.uid);
Dianne Hackborn607b4142013-08-02 18:10:10 -07001590 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07001591 if (uidChanged) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07001592 uidState.evalForegroundOps(mOpModeWatchers);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07001593 }
Dianne Hackborn607b4142013-08-02 18:10:10 -07001594 }
Svet Ganov2af57082015-07-30 08:44:20 -07001595
Dianne Hackborn607b4142013-08-02 18:10:10 -07001596 if (changed) {
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -08001597 scheduleFastWriteLocked();
Dianne Hackborn607b4142013-08-02 18:10:10 -07001598 }
1599 }
1600 if (callbacks != null) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001601 for (Map.Entry<ModeCallback, ArrayList<ChangeRec>> ent : callbacks.entrySet()) {
1602 ModeCallback cb = ent.getKey();
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001603 ArrayList<ChangeRec> reports = ent.getValue();
Dianne Hackborn607b4142013-08-02 18:10:10 -07001604 for (int i=0; i<reports.size(); i++) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001605 ChangeRec rep = reports.get(i);
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001606 mHandler.sendMessage(PooledLambda.obtainMessage(
1607 AppOpsService::notifyOpChanged,
1608 this, cb, rep.op, rep.uid, rep.pkg));
Dianne Hackborn607b4142013-08-02 18:10:10 -07001609 }
1610 }
1611 }
1612 }
1613
Dianne Hackborn65a4f252018-05-08 17:30:48 -07001614 private void evalAllForegroundOpsLocked() {
1615 for (int uidi = mUidStates.size() - 1; uidi >= 0; uidi--) {
1616 final UidState uidState = mUidStates.valueAt(uidi);
1617 if (uidState.foregroundOps != null) {
1618 uidState.evalForegroundOps(mOpModeWatchers);
1619 }
1620 }
1621 }
1622
Dianne Hackbornc2293022013-02-06 23:14:49 -08001623 @Override
1624 public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07001625 startWatchingModeWithFlags(op, packageName, 0, callback);
1626 }
1627
1628 @Override
1629 public void startWatchingModeWithFlags(int op, String packageName, int flags,
1630 IAppOpsCallback callback) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001631 int watchedUid = -1;
Dianne Hackborn3b563fc2018-04-16 17:17:14 -07001632 final int callingUid = Binder.getCallingUid();
1633 final int callingPid = Binder.getCallingPid();
Dianne Hackborn5376edd2018-06-05 13:21:16 -07001634 // TODO: should have a privileged permission to protect this.
1635 // Also, if the caller has requested WATCH_FOREGROUND_CHANGES, should we require
1636 // the USAGE_STATS permission since this can provide information about when an
1637 // app is in the foreground?
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001638 Preconditions.checkArgumentInRange(op, AppOpsManager.OP_NONE,
1639 AppOpsManager._NUM_OP - 1, "Invalid op code: " + op);
Svetoslav Ganov8de59712015-12-09 18:25:13 -08001640 if (callback == null) {
1641 return;
1642 }
Dianne Hackbornc2293022013-02-06 23:14:49 -08001643 synchronized (this) {
Svet Ganov2af57082015-07-30 08:44:20 -07001644 op = (op != AppOpsManager.OP_NONE) ? AppOpsManager.opToSwitch(op) : op;
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001645 ModeCallback cb = mModeWatchers.get(callback.asBinder());
Dianne Hackbornc2293022013-02-06 23:14:49 -08001646 if (cb == null) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07001647 cb = new ModeCallback(callback, watchedUid, flags, callingUid, callingPid);
Dianne Hackbornc2293022013-02-06 23:14:49 -08001648 mModeWatchers.put(callback.asBinder(), cb);
1649 }
1650 if (op != AppOpsManager.OP_NONE) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001651 ArraySet<ModeCallback> cbs = mOpModeWatchers.get(op);
Dianne Hackbornc2293022013-02-06 23:14:49 -08001652 if (cbs == null) {
Dianne Hackborn68d76552017-02-27 15:32:03 -08001653 cbs = new ArraySet<>();
Dianne Hackbornc2293022013-02-06 23:14:49 -08001654 mOpModeWatchers.put(op, cbs);
1655 }
1656 cbs.add(cb);
1657 }
1658 if (packageName != null) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001659 ArraySet<ModeCallback> cbs = mPackageModeWatchers.get(packageName);
Dianne Hackbornc2293022013-02-06 23:14:49 -08001660 if (cbs == null) {
Dianne Hackborn68d76552017-02-27 15:32:03 -08001661 cbs = new ArraySet<>();
Dianne Hackbornc2293022013-02-06 23:14:49 -08001662 mPackageModeWatchers.put(packageName, cbs);
1663 }
1664 cbs.add(cb);
1665 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07001666 evalAllForegroundOpsLocked();
Dianne Hackbornc2293022013-02-06 23:14:49 -08001667 }
1668 }
1669
1670 @Override
1671 public void stopWatchingMode(IAppOpsCallback callback) {
Svetoslav Ganov8de59712015-12-09 18:25:13 -08001672 if (callback == null) {
1673 return;
1674 }
Dianne Hackbornc2293022013-02-06 23:14:49 -08001675 synchronized (this) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001676 ModeCallback cb = mModeWatchers.remove(callback.asBinder());
Dianne Hackbornc2293022013-02-06 23:14:49 -08001677 if (cb != null) {
1678 cb.unlinkToDeath();
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001679 for (int i=mOpModeWatchers.size()-1; i>=0; i--) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001680 ArraySet<ModeCallback> cbs = mOpModeWatchers.valueAt(i);
Dianne Hackbornc2293022013-02-06 23:14:49 -08001681 cbs.remove(cb);
1682 if (cbs.size() <= 0) {
1683 mOpModeWatchers.removeAt(i);
1684 }
1685 }
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001686 for (int i=mPackageModeWatchers.size()-1; i>=0; i--) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001687 ArraySet<ModeCallback> cbs = mPackageModeWatchers.valueAt(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001688 cbs.remove(cb);
1689 if (cbs.size() <= 0) {
1690 mPackageModeWatchers.removeAt(i);
Dianne Hackbornc2293022013-02-06 23:14:49 -08001691 }
1692 }
1693 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07001694 evalAllForegroundOpsLocked();
Dianne Hackbornc2293022013-02-06 23:14:49 -08001695 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001696 }
1697
1698 @Override
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001699 public IBinder getToken(IBinder clientToken) {
1700 synchronized (this) {
1701 ClientState cs = mClients.get(clientToken);
1702 if (cs == null) {
1703 cs = new ClientState(clientToken);
1704 mClients.put(clientToken, cs);
1705 }
1706 return cs;
1707 }
1708 }
1709
Svet Ganovd873ae62018-06-25 16:39:23 -07001710 public CheckOpsDelegate getAppOpsServiceDelegate() {
1711 synchronized (this) {
1712 return mCheckOpsDelegate;
1713 }
1714 }
1715
1716 public void setAppOpsServiceDelegate(CheckOpsDelegate delegate) {
1717 synchronized (this) {
1718 mCheckOpsDelegate = delegate;
1719 }
1720 }
1721
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001722 @Override
Svet Ganov9d528a12018-12-19 17:23:11 -08001723 public int checkOperationRaw(int code, int uid, String packageName) {
1724 return checkOperationInternal(code, uid, packageName, true /*raw*/);
1725 }
1726
1727 @Override
Dianne Hackborn35654b62013-01-14 17:38:02 -08001728 public int checkOperation(int code, int uid, String packageName) {
Svet Ganov9d528a12018-12-19 17:23:11 -08001729 return checkOperationInternal(code, uid, packageName, false /*raw*/);
1730 }
1731
1732 private int checkOperationInternal(int code, int uid, String packageName, boolean raw) {
Svet Ganovd873ae62018-06-25 16:39:23 -07001733 final CheckOpsDelegate delegate;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001734 synchronized (this) {
Svet Ganovd873ae62018-06-25 16:39:23 -07001735 delegate = mCheckOpsDelegate;
1736 }
Todd Kennedy556efba2018-11-15 07:43:55 -08001737 if (delegate == null) {
Svet Ganov9d528a12018-12-19 17:23:11 -08001738 return checkOperationImpl(code, uid, packageName, raw);
Todd Kennedy556efba2018-11-15 07:43:55 -08001739 }
Svet Ganov9d528a12018-12-19 17:23:11 -08001740 return delegate.checkOperation(code, uid, packageName, raw,
Svet Ganovd873ae62018-06-25 16:39:23 -07001741 AppOpsService.this::checkOperationImpl);
1742 }
1743
Svet Ganov9d528a12018-12-19 17:23:11 -08001744 private int checkOperationImpl(int code, int uid, String packageName,
1745 boolean raw) {
Todd Kennedy556efba2018-11-15 07:43:55 -08001746 verifyIncomingUid(uid);
1747 verifyIncomingOp(code);
1748 String resolvedPackageName = resolvePackageName(uid, packageName);
1749 if (resolvedPackageName == null) {
1750 return AppOpsManager.MODE_IGNORED;
1751 }
Svet Ganov9d528a12018-12-19 17:23:11 -08001752 return checkOperationUnchecked(code, uid, resolvedPackageName, raw);
Todd Kennedy556efba2018-11-15 07:43:55 -08001753 }
1754
Philip P. Moltmann724150d2019-03-11 17:01:05 -07001755 /**
1756 * @see #checkOperationUnchecked(int, int, String, boolean, boolean)
1757 */
1758 private @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName,
1759 boolean raw) {
1760 return checkOperationUnchecked(code, uid, packageName, raw, true);
1761 }
1762
1763 /**
1764 * Get the mode of an app-op.
1765 *
1766 * @param code The code of the op
1767 * @param uid The uid of the package the op belongs to
1768 * @param packageName The package the op belongs to
1769 * @param raw If the raw state of eval-ed state should be checked.
1770 * @param verify If the code should check the package belongs to the uid
1771 *
1772 * @return The mode of the op
1773 */
1774 private @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName,
1775 boolean raw, boolean verify) {
Svet Ganovd873ae62018-06-25 16:39:23 -07001776 synchronized (this) {
Philip P. Moltmann724150d2019-03-11 17:01:05 -07001777 if (verify) {
1778 checkPackage(uid, packageName);
1779 }
Todd Kennedy556efba2018-11-15 07:43:55 -08001780 if (isOpRestrictedLocked(uid, code, packageName)) {
Jason Monk62062992014-05-06 09:55:28 -04001781 return AppOpsManager.MODE_IGNORED;
1782 }
Svet Ganov2af57082015-07-30 08:44:20 -07001783 code = AppOpsManager.opToSwitch(code);
1784 UidState uidState = getUidStateLocked(uid, false);
Svet Ganovee438d42017-01-19 18:04:38 -08001785 if (uidState != null && uidState.opModes != null
1786 && uidState.opModes.indexOfKey(code) >= 0) {
Svet Ganov9d528a12018-12-19 17:23:11 -08001787 final int rawMode = uidState.opModes.get(code);
Svet Ganovaf189e32019-02-15 18:45:29 -08001788 return raw ? rawMode : uidState.evalMode(code, rawMode);
Svet Ganov2af57082015-07-30 08:44:20 -07001789 }
Philip P. Moltmann724150d2019-03-11 17:01:05 -07001790 Op op = getOpLocked(code, uid, packageName, false, verify, false);
Dianne Hackborn35654b62013-01-14 17:38:02 -08001791 if (op == null) {
David Braunf5d83192013-09-16 13:43:51 -07001792 return AppOpsManager.opToDefaultMode(code);
Dianne Hackborn35654b62013-01-14 17:38:02 -08001793 }
Svet Ganovaf189e32019-02-15 18:45:29 -08001794 return raw ? op.mode : op.evalMode();
Dianne Hackborn35654b62013-01-14 17:38:02 -08001795 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001796 }
1797
1798 @Override
John Spurlock7b414672014-07-18 13:02:39 -04001799 public int checkAudioOperation(int code, int usage, int uid, String packageName) {
Svet Ganovd873ae62018-06-25 16:39:23 -07001800 final CheckOpsDelegate delegate;
John Spurlock1af30c72014-03-10 08:33:35 -04001801 synchronized (this) {
Svet Ganovd873ae62018-06-25 16:39:23 -07001802 delegate = mCheckOpsDelegate;
1803 }
Todd Kennedy556efba2018-11-15 07:43:55 -08001804 if (delegate == null) {
1805 return checkAudioOperationImpl(code, usage, uid, packageName);
1806 }
Svet Ganovd873ae62018-06-25 16:39:23 -07001807 return delegate.checkAudioOperation(code, usage, uid, packageName,
1808 AppOpsService.this::checkAudioOperationImpl);
1809 }
1810
1811 private int checkAudioOperationImpl(int code, int usage, int uid, String packageName) {
Todd Kennedy556efba2018-11-15 07:43:55 -08001812 boolean suspended;
1813 try {
1814 suspended = isPackageSuspendedForUser(packageName, uid);
1815 } catch (IllegalArgumentException ex) {
1816 // Package not found.
1817 suspended = false;
1818 }
1819
1820 if (suspended) {
1821 Slog.i(TAG, "Audio disabled for suspended package=" + packageName
1822 + " for uid=" + uid);
1823 return AppOpsManager.MODE_IGNORED;
1824 }
1825
Svet Ganovd873ae62018-06-25 16:39:23 -07001826 synchronized (this) {
John Spurlock7b414672014-07-18 13:02:39 -04001827 final int mode = checkRestrictionLocked(code, usage, uid, packageName);
John Spurlock1af30c72014-03-10 08:33:35 -04001828 if (mode != AppOpsManager.MODE_ALLOWED) {
1829 return mode;
1830 }
1831 }
1832 return checkOperation(code, uid, packageName);
1833 }
1834
Andrei Stingaceanu355b2322016-02-12 16:43:51 +00001835 private boolean isPackageSuspendedForUser(String pkg, int uid) {
Andrei Stingaceanu2bc2feb2016-02-11 16:23:49 +00001836 try {
Andrei Stingaceanu355b2322016-02-12 16:43:51 +00001837 return AppGlobals.getPackageManager().isPackageSuspendedForUser(
1838 pkg, UserHandle.getUserId(uid));
Andrei Stingaceanu2bc2feb2016-02-11 16:23:49 +00001839 } catch (RemoteException re) {
1840 throw new SecurityException("Could not talk to package manager service");
1841 }
Andrei Stingaceanu2bc2feb2016-02-11 16:23:49 +00001842 }
1843
John Spurlock7b414672014-07-18 13:02:39 -04001844 private int checkRestrictionLocked(int code, int usage, int uid, String packageName) {
1845 final SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code);
1846 if (usageRestrictions != null) {
1847 final Restriction r = usageRestrictions.get(usage);
John Spurlock1af30c72014-03-10 08:33:35 -04001848 if (r != null && !r.exceptionPackages.contains(packageName)) {
1849 return r.mode;
1850 }
1851 }
1852 return AppOpsManager.MODE_ALLOWED;
1853 }
1854
1855 @Override
John Spurlock7b414672014-07-18 13:02:39 -04001856 public void setAudioRestriction(int code, int usage, int uid, int mode,
John Spurlock1af30c72014-03-10 08:33:35 -04001857 String[] exceptionPackages) {
Dianne Hackbornd5254412018-05-11 18:02:58 -07001858 enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
John Spurlock1af30c72014-03-10 08:33:35 -04001859 verifyIncomingUid(uid);
1860 verifyIncomingOp(code);
1861 synchronized (this) {
John Spurlock7b414672014-07-18 13:02:39 -04001862 SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code);
1863 if (usageRestrictions == null) {
1864 usageRestrictions = new SparseArray<Restriction>();
1865 mAudioRestrictions.put(code, usageRestrictions);
John Spurlock1af30c72014-03-10 08:33:35 -04001866 }
John Spurlock7b414672014-07-18 13:02:39 -04001867 usageRestrictions.remove(usage);
John Spurlock1af30c72014-03-10 08:33:35 -04001868 if (mode != AppOpsManager.MODE_ALLOWED) {
1869 final Restriction r = new Restriction();
1870 r.mode = mode;
1871 if (exceptionPackages != null) {
1872 final int N = exceptionPackages.length;
1873 r.exceptionPackages = new ArraySet<String>(N);
1874 for (int i = 0; i < N; i++) {
1875 final String pkg = exceptionPackages[i];
1876 if (pkg != null) {
1877 r.exceptionPackages.add(pkg.trim());
1878 }
1879 }
1880 }
John Spurlock7b414672014-07-18 13:02:39 -04001881 usageRestrictions.put(usage, r);
John Spurlock1af30c72014-03-10 08:33:35 -04001882 }
1883 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001884
1885 mHandler.sendMessage(PooledLambda.obtainMessage(
Svet Ganov3a95f832018-03-23 17:44:30 -07001886 AppOpsService::notifyWatchersOfChange, this, code, UID_ANY));
John Spurlock1af30c72014-03-10 08:33:35 -04001887 }
1888
1889 @Override
Jeff Sharkey911d7f42013-09-05 18:11:45 -07001890 public int checkPackage(int uid, String packageName) {
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00001891 Preconditions.checkNotNull(packageName);
Jeff Sharkey911d7f42013-09-05 18:11:45 -07001892 synchronized (this) {
Yohei Yukawaa965d652017-10-12 15:02:26 -07001893 Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
1894 true /* uidMismatchExpected */);
1895 if (ops != null) {
Jeff Sharkey911d7f42013-09-05 18:11:45 -07001896 return AppOpsManager.MODE_ALLOWED;
1897 } else {
1898 return AppOpsManager.MODE_ERRORED;
1899 }
1900 }
1901 }
1902
1903 @Override
Svet Ganovd873ae62018-06-25 16:39:23 -07001904 public int noteProxyOperation(int code, int proxyUid,
1905 String proxyPackageName, int proxiedUid, String proxiedPackageName) {
1906 verifyIncomingUid(proxyUid);
Svet Ganov99b60432015-06-27 13:15:22 -07001907 verifyIncomingOp(code);
Svet Ganovaf189e32019-02-15 18:45:29 -08001908
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00001909 String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
1910 if (resolveProxyPackageName == null) {
1911 return AppOpsManager.MODE_IGNORED;
1912 }
Svet Ganovaf189e32019-02-15 18:45:29 -08001913
1914 final boolean isProxyTrusted = mContext.checkPermission(
1915 Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
1916 == PackageManager.PERMISSION_GRANTED;
1917
1918 final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
1919 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00001920 final int proxyMode = noteOperationUnchecked(code, proxyUid,
Svet Ganovaf189e32019-02-15 18:45:29 -08001921 resolveProxyPackageName, Process.INVALID_UID, null, proxyFlags);
Svet Ganov99b60432015-06-27 13:15:22 -07001922 if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) {
1923 return proxyMode;
1924 }
Svet Ganovaf189e32019-02-15 18:45:29 -08001925
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00001926 String resolveProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName);
1927 if (resolveProxiedPackageName == null) {
1928 return AppOpsManager.MODE_IGNORED;
1929 }
Svet Ganovaf189e32019-02-15 18:45:29 -08001930 final int proxiedFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXIED
1931 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED;
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00001932 return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName,
Svet Ganovaf189e32019-02-15 18:45:29 -08001933 proxyUid, resolveProxyPackageName, proxiedFlags);
Svet Ganov99b60432015-06-27 13:15:22 -07001934 }
1935
1936 @Override
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001937 public int noteOperation(int code, int uid, String packageName) {
Svet Ganovd873ae62018-06-25 16:39:23 -07001938 final CheckOpsDelegate delegate;
1939 synchronized (this) {
Svet Ganovd873ae62018-06-25 16:39:23 -07001940 delegate = mCheckOpsDelegate;
1941 }
Todd Kennedy556efba2018-11-15 07:43:55 -08001942 if (delegate == null) {
1943 return noteOperationImpl(code, uid, packageName);
1944 }
Svet Ganovd873ae62018-06-25 16:39:23 -07001945 return delegate.noteOperation(code, uid, packageName,
1946 AppOpsService.this::noteOperationImpl);
1947 }
1948
1949 private int noteOperationImpl(int code, int uid, String packageName) {
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001950 verifyIncomingUid(uid);
Dianne Hackborn961321f2013-02-05 17:22:41 -08001951 verifyIncomingOp(code);
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00001952 String resolvedPackageName = resolvePackageName(uid, packageName);
1953 if (resolvedPackageName == null) {
1954 return AppOpsManager.MODE_IGNORED;
1955 }
Svet Ganovaf189e32019-02-15 18:45:29 -08001956 return noteOperationUnchecked(code, uid, resolvedPackageName, Process.INVALID_UID, null,
1957 AppOpsManager.OP_FLAG_SELF);
Svet Ganov99b60432015-06-27 13:15:22 -07001958 }
1959
1960 private int noteOperationUnchecked(int code, int uid, String packageName,
Svet Ganovaf189e32019-02-15 18:45:29 -08001961 int proxyUid, String proxyPackageName, @OpFlags int flags) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001962 synchronized (this) {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07001963 final Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
Yohei Yukawaa965d652017-10-12 15:02:26 -07001964 false /* uidMismatchExpected */);
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001965 if (ops == null) {
Svet Ganovb3d2ae22018-12-17 22:06:15 -08001966 scheduleOpNotedIfNeededLocked(code, uid, packageName,
1967 AppOpsManager.MODE_IGNORED);
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08001968 if (DEBUG) Slog.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001969 + " package " + packageName);
Jeff Sharkey911d7f42013-09-05 18:11:45 -07001970 return AppOpsManager.MODE_ERRORED;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001971 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07001972 final Op op = getOpLocked(ops, code, true);
Svet Ganov442ed572016-08-17 17:29:43 -07001973 if (isOpRestrictedLocked(uid, code, packageName)) {
Svet Ganovb3d2ae22018-12-17 22:06:15 -08001974 scheduleOpNotedIfNeededLocked(code, uid, packageName,
1975 AppOpsManager.MODE_IGNORED);
Jason Monk62062992014-05-06 09:55:28 -04001976 return AppOpsManager.MODE_IGNORED;
1977 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07001978 final UidState uidState = ops.uidState;
Svet Ganovaf189e32019-02-15 18:45:29 -08001979 if (op.running) {
1980 final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes,
1981 op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001982 Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
Svet Ganovaf189e32019-02-15 18:45:29 -08001983 + " code " + code + " time=" + entry.getLastAccessTime(uidState.state,
1984 uidState.state, flags) + " duration=" + entry.getLastDuration(
1985 uidState.state, uidState.state, flags));
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001986 }
Svet Ganovaf189e32019-02-15 18:45:29 -08001987
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001988 final int switchCode = AppOpsManager.opToSwitch(code);
Svetoslav Ganov1984bba2016-04-05 13:39:25 -07001989 // If there is a non-default per UID policy (we set UID op mode only if
1990 // non-default) it takes over, otherwise use the per package policy.
1991 if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
Svet Ganovaf189e32019-02-15 18:45:29 -08001992 final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode));
Svet Ganov2af57082015-07-30 08:44:20 -07001993 if (uidMode != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07001994 if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
Svet Ganov2af57082015-07-30 08:44:20 -07001995 + switchCode + " (" + code + ") uid " + uid + " package "
1996 + packageName);
Svet Ganovaf189e32019-02-15 18:45:29 -08001997 op.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName,
1998 uidState.state, flags);
1999 mHistoricalRegistry.incrementOpRejected(code, uid, packageName,
2000 uidState.state, flags);
Svet Ganovb3d2ae22018-12-17 22:06:15 -08002001 scheduleOpNotedIfNeededLocked(code, uid, packageName, uidMode);
Svet Ganov2af57082015-07-30 08:44:20 -07002002 return uidMode;
2003 }
Svetoslav Ganov1984bba2016-04-05 13:39:25 -07002004 } else {
2005 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
Svet Ganovaf189e32019-02-15 18:45:29 -08002006 final int mode = switchOp.evalMode();
2007 if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002008 if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + mode + " for code "
Svetoslav Ganov1984bba2016-04-05 13:39:25 -07002009 + switchCode + " (" + code + ") uid " + uid + " package "
2010 + packageName);
Svet Ganovaf189e32019-02-15 18:45:29 -08002011 op.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName,
2012 uidState.state, flags);
2013 mHistoricalRegistry.incrementOpRejected(code, uid, packageName,
2014 uidState.state, flags);
2015 scheduleOpNotedIfNeededLocked(code, uid, packageName, mode);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002016 return mode;
Svetoslav Ganov1984bba2016-04-05 13:39:25 -07002017 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002018 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002019 if (DEBUG) Slog.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002020 + " package " + packageName);
Svet Ganovaf189e32019-02-15 18:45:29 -08002021 op.accessed(System.currentTimeMillis(), proxyUid, proxyPackageName,
2022 uidState.state, flags);
Svet Ganov8455ba22019-01-02 13:05:56 -08002023 mHistoricalRegistry.incrementOpAccessedCount(op.op, uid, packageName,
Svet Ganovaf189e32019-02-15 18:45:29 -08002024 uidState.state, flags);
Svet Ganovb3d2ae22018-12-17 22:06:15 -08002025 scheduleOpNotedIfNeededLocked(code, uid, packageName,
2026 AppOpsManager.MODE_ALLOWED);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002027 return AppOpsManager.MODE_ALLOWED;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002028 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002029 }
2030
2031 @Override
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002032 public void startWatchingActive(int[] ops, IAppOpsActiveCallback callback) {
Svet Ganovf7b47252018-02-26 11:11:27 -08002033 int watchedUid = -1;
Dianne Hackborn3b563fc2018-04-16 17:17:14 -07002034 final int callingUid = Binder.getCallingUid();
2035 final int callingPid = Binder.getCallingPid();
Svet Ganovf7b47252018-02-26 11:11:27 -08002036 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS)
2037 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn3b563fc2018-04-16 17:17:14 -07002038 watchedUid = callingUid;
Svet Ganovf7b47252018-02-26 11:11:27 -08002039 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002040 if (ops != null) {
2041 Preconditions.checkArrayElementsInRange(ops, 0,
2042 AppOpsManager._NUM_OP - 1, "Invalid op code in: " + Arrays.toString(ops));
2043 }
2044 if (callback == null) {
2045 return;
2046 }
2047 synchronized (this) {
2048 SparseArray<ActiveCallback> callbacks = mActiveWatchers.get(callback.asBinder());
2049 if (callbacks == null) {
2050 callbacks = new SparseArray<>();
2051 mActiveWatchers.put(callback.asBinder(), callbacks);
2052 }
Dianne Hackborn3b563fc2018-04-16 17:17:14 -07002053 final ActiveCallback activeCallback = new ActiveCallback(callback, watchedUid,
2054 callingUid, callingPid);
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002055 for (int op : ops) {
2056 callbacks.put(op, activeCallback);
2057 }
2058 }
2059 }
2060
2061 @Override
2062 public void stopWatchingActive(IAppOpsActiveCallback callback) {
2063 if (callback == null) {
2064 return;
2065 }
2066 synchronized (this) {
2067 final SparseArray<ActiveCallback> activeCallbacks =
2068 mActiveWatchers.remove(callback.asBinder());
2069 if (activeCallbacks == null) {
2070 return;
2071 }
2072 final int callbackCount = activeCallbacks.size();
2073 for (int i = 0; i < callbackCount; i++) {
Svet Ganovb3d2ae22018-12-17 22:06:15 -08002074 activeCallbacks.valueAt(i).destroy();
2075 }
2076 }
2077 }
2078
2079 @Override
2080 public void startWatchingNoted(@NonNull int[] ops, @NonNull IAppOpsNotedCallback callback) {
2081 int watchedUid = Process.INVALID_UID;
2082 final int callingUid = Binder.getCallingUid();
2083 final int callingPid = Binder.getCallingPid();
2084 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS)
2085 != PackageManager.PERMISSION_GRANTED) {
2086 watchedUid = callingUid;
2087 }
2088 Preconditions.checkArgument(!ArrayUtils.isEmpty(ops), "Ops cannot be null or empty");
2089 Preconditions.checkArrayElementsInRange(ops, 0, AppOpsManager._NUM_OP - 1,
2090 "Invalid op code in: " + Arrays.toString(ops));
2091 Preconditions.checkNotNull(callback, "Callback cannot be null");
2092 synchronized (this) {
2093 SparseArray<NotedCallback> callbacks = mNotedWatchers.get(callback.asBinder());
2094 if (callbacks == null) {
2095 callbacks = new SparseArray<>();
2096 mNotedWatchers.put(callback.asBinder(), callbacks);
2097 }
2098 final NotedCallback notedCallback = new NotedCallback(callback, watchedUid,
2099 callingUid, callingPid);
2100 for (int op : ops) {
2101 callbacks.put(op, notedCallback);
2102 }
2103 }
2104 }
2105
2106 @Override
2107 public void stopWatchingNoted(IAppOpsNotedCallback callback) {
2108 Preconditions.checkNotNull(callback, "Callback cannot be null");
2109 synchronized (this) {
2110 final SparseArray<NotedCallback> notedCallbacks =
2111 mNotedWatchers.remove(callback.asBinder());
2112 if (notedCallbacks == null) {
2113 return;
2114 }
2115 final int callbackCount = notedCallbacks.size();
2116 for (int i = 0; i < callbackCount; i++) {
2117 notedCallbacks.valueAt(i).destroy();
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002118 }
2119 }
2120 }
2121
2122 @Override
Svet Ganovf7b47252018-02-26 11:11:27 -08002123 public int startOperation(IBinder token, int code, int uid, String packageName,
2124 boolean startIfModeDefault) {
Dianne Hackbornf265ea92013-01-31 15:00:51 -08002125 verifyIncomingUid(uid);
Dianne Hackborn961321f2013-02-05 17:22:41 -08002126 verifyIncomingOp(code);
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00002127 String resolvedPackageName = resolvePackageName(uid, packageName);
2128 if (resolvedPackageName == null) {
2129 return AppOpsManager.MODE_IGNORED;
2130 }
Dianne Hackborne98f5db2013-07-17 17:23:25 -07002131 ClientState client = (ClientState)token;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002132 synchronized (this) {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002133 final Ops ops = getOpsRawLocked(uid, resolvedPackageName, true /* edit */,
Yohei Yukawaa965d652017-10-12 15:02:26 -07002134 false /* uidMismatchExpected */);
Dianne Hackbornf265ea92013-01-31 15:00:51 -08002135 if (ops == null) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002136 if (DEBUG) Slog.d(TAG, "startOperation: no op for code " + code + " uid " + uid
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00002137 + " package " + resolvedPackageName);
Jeff Sharkey911d7f42013-09-05 18:11:45 -07002138 return AppOpsManager.MODE_ERRORED;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002139 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002140 final Op op = getOpLocked(ops, code, true);
Svet Ganov442ed572016-08-17 17:29:43 -07002141 if (isOpRestrictedLocked(uid, code, resolvedPackageName)) {
Jason Monk62062992014-05-06 09:55:28 -04002142 return AppOpsManager.MODE_IGNORED;
2143 }
Dianne Hackbornf265ea92013-01-31 15:00:51 -08002144 final int switchCode = AppOpsManager.opToSwitch(code);
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002145 final UidState uidState = ops.uidState;
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002146 // If there is a non-default per UID policy (we set UID op mode only if
2147 // non-default) it takes over, otherwise use the per package policy.
Svet Ganovaf189e32019-02-15 18:45:29 -08002148 final int opCode = op.op;
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002149 if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
Svet Ganovaf189e32019-02-15 18:45:29 -08002150 final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode));
Svet Ganovf7b47252018-02-26 11:11:27 -08002151 if (uidMode != AppOpsManager.MODE_ALLOWED
2152 && (!startIfModeDefault || uidMode != AppOpsManager.MODE_DEFAULT)) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002153 if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
Svet Ganov2af57082015-07-30 08:44:20 -07002154 + switchCode + " (" + code + ") uid " + uid + " package "
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00002155 + resolvedPackageName);
Svet Ganovaf189e32019-02-15 18:45:29 -08002156 // We don't support proxy long running ops (start/stop)
2157 op.rejected(System.currentTimeMillis(), -1 /*proxyUid*/,
2158 null /*proxyPackage*/, uidState.state, AppOpsManager.OP_FLAG_SELF);
2159 mHistoricalRegistry.incrementOpRejected(opCode, uid, packageName,
2160 uidState.state, AppOpsManager.OP_FLAG_SELF);
Svet Ganov2af57082015-07-30 08:44:20 -07002161 return uidMode;
2162 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002163 } else {
2164 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
Svet Ganovaf189e32019-02-15 18:45:29 -08002165 final int mode = switchOp.evalMode();
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002166 if (mode != AppOpsManager.MODE_ALLOWED
2167 && (!startIfModeDefault || mode != AppOpsManager.MODE_DEFAULT)) {
2168 if (DEBUG) Slog.d(TAG, "startOperation: reject #" + mode + " for code "
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002169 + switchCode + " (" + code + ") uid " + uid + " package "
2170 + resolvedPackageName);
Svet Ganovaf189e32019-02-15 18:45:29 -08002171 // We don't support proxy long running ops (start/stop)
2172 op.rejected(System.currentTimeMillis(), -1 /*proxyUid*/,
2173 null /*proxyPackage*/, uidState.state, AppOpsManager.OP_FLAG_SELF);
2174 mHistoricalRegistry.incrementOpRejected(opCode, uid, packageName,
2175 uidState.state, AppOpsManager.OP_FLAG_SELF);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002176 return mode;
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002177 }
Svet Ganov2af57082015-07-30 08:44:20 -07002178 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002179 if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00002180 + " package " + resolvedPackageName);
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002181 if (op.startNesting == 0) {
2182 op.startRealtime = SystemClock.elapsedRealtime();
Svet Ganovaf189e32019-02-15 18:45:29 -08002183 // We don't support proxy long running ops (start/stop)
2184 op.started(System.currentTimeMillis(), uidState.state,
2185 AppOpsManager.OP_FLAG_SELF);
2186 mHistoricalRegistry.incrementOpAccessedCount(opCode, uid, packageName,
2187 uidState.state, AppOpsManager.OP_FLAG_SELF);
2188
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002189 scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, true);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002190 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002191 op.startNesting++;
2192 uidState.startNesting++;
Dianne Hackborne98f5db2013-07-17 17:23:25 -07002193 if (client.mStartedOps != null) {
2194 client.mStartedOps.add(op);
2195 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002196 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002197
2198 return AppOpsManager.MODE_ALLOWED;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002199 }
2200
2201 @Override
Dianne Hackborne98f5db2013-07-17 17:23:25 -07002202 public void finishOperation(IBinder token, int code, int uid, String packageName) {
Dianne Hackbornf265ea92013-01-31 15:00:51 -08002203 verifyIncomingUid(uid);
Dianne Hackborn961321f2013-02-05 17:22:41 -08002204 verifyIncomingOp(code);
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00002205 String resolvedPackageName = resolvePackageName(uid, packageName);
2206 if (resolvedPackageName == null) {
2207 return;
2208 }
2209 if (!(token instanceof ClientState)) {
2210 return;
2211 }
2212 ClientState client = (ClientState) token;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002213 synchronized (this) {
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002214 Op op = getOpLocked(code, uid, resolvedPackageName, true, true, false);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002215 if (op == null) {
2216 return;
2217 }
Svet Ganovf7b47252018-02-26 11:11:27 -08002218 if (!client.mStartedOps.remove(op)) {
Svet Ganovf5d5af12018-03-18 11:51:17 -07002219 // We finish ops when packages get removed to guarantee no dangling
2220 // started ops. However, some part of the system may asynchronously
2221 // finish ops for an already gone package. Hence, finishing an op
2222 // for a non existing package is fine and we don't log as a wtf.
2223 final long identity = Binder.clearCallingIdentity();
2224 try {
2225 if (LocalServices.getService(PackageManagerInternal.class).getPackageUid(
2226 resolvedPackageName, 0, UserHandle.getUserId(uid)) < 0) {
2227 Slog.i(TAG, "Finishing op=" + AppOpsManager.opToName(code)
2228 + " for non-existing package=" + resolvedPackageName
2229 + " in uid=" + uid);
2230 return;
2231 }
2232 } finally {
2233 Binder.restoreCallingIdentity(identity);
2234 }
Svet Ganovaf189e32019-02-15 18:45:29 -08002235 Slog.wtf(TAG, "Operation not started: uid=" + op.uidState.uid + " pkg="
Svet Ganovf5d5af12018-03-18 11:51:17 -07002236 + op.packageName + " op=" + AppOpsManager.opToName(op.op));
Svet Ganov31d83ae2018-03-15 10:45:56 -07002237 return;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002238 }
Svet Ganova7a0db62018-02-27 20:08:01 -08002239 finishOperationLocked(op, /*finishNested*/ false);
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002240 if (op.startNesting <= 0) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002241 scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, false);
2242 }
2243 }
2244 }
2245
2246 private void scheduleOpActiveChangedIfNeededLocked(int code, int uid, String packageName,
2247 boolean active) {
2248 ArraySet<ActiveCallback> dispatchedCallbacks = null;
2249 final int callbackListCount = mActiveWatchers.size();
2250 for (int i = 0; i < callbackListCount; i++) {
2251 final SparseArray<ActiveCallback> callbacks = mActiveWatchers.valueAt(i);
2252 ActiveCallback callback = callbacks.get(code);
2253 if (callback != null) {
Dianne Hackborn3b563fc2018-04-16 17:17:14 -07002254 if (callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) {
Svet Ganovf7b47252018-02-26 11:11:27 -08002255 continue;
2256 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08002257 if (dispatchedCallbacks == null) {
2258 dispatchedCallbacks = new ArraySet<>();
2259 }
2260 dispatchedCallbacks.add(callback);
2261 }
2262 }
2263 if (dispatchedCallbacks == null) {
2264 return;
2265 }
2266 mHandler.sendMessage(PooledLambda.obtainMessage(
2267 AppOpsService::notifyOpActiveChanged,
2268 this, dispatchedCallbacks, code, uid, packageName, active));
2269 }
2270
2271 private void notifyOpActiveChanged(ArraySet<ActiveCallback> callbacks,
2272 int code, int uid, String packageName, boolean active) {
2273 // There are components watching for mode changes such as window manager
2274 // and location manager which are in our process. The callbacks in these
2275 // components may require permissions our remote caller does not have.
2276 final long identity = Binder.clearCallingIdentity();
2277 try {
2278 final int callbackCount = callbacks.size();
2279 for (int i = 0; i < callbackCount; i++) {
2280 final ActiveCallback callback = callbacks.valueAt(i);
2281 try {
2282 callback.mCallback.opActiveChanged(code, uid, packageName, active);
2283 } catch (RemoteException e) {
2284 /* do nothing */
2285 }
2286 }
2287 } finally {
2288 Binder.restoreCallingIdentity(identity);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07002289 }
2290 }
2291
Svet Ganovb3d2ae22018-12-17 22:06:15 -08002292 private void scheduleOpNotedIfNeededLocked(int code, int uid, String packageName,
2293 int result) {
2294 ArraySet<NotedCallback> dispatchedCallbacks = null;
2295 final int callbackListCount = mNotedWatchers.size();
2296 for (int i = 0; i < callbackListCount; i++) {
2297 final SparseArray<NotedCallback> callbacks = mNotedWatchers.valueAt(i);
2298 final NotedCallback callback = callbacks.get(code);
2299 if (callback != null) {
2300 if (callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) {
2301 continue;
2302 }
2303 if (dispatchedCallbacks == null) {
2304 dispatchedCallbacks = new ArraySet<>();
2305 }
2306 dispatchedCallbacks.add(callback);
2307 }
2308 }
2309 if (dispatchedCallbacks == null) {
2310 return;
2311 }
2312 mHandler.sendMessage(PooledLambda.obtainMessage(
2313 AppOpsService::notifyOpChecked,
2314 this, dispatchedCallbacks, code, uid, packageName, result));
2315 }
2316
2317 private void notifyOpChecked(ArraySet<NotedCallback> callbacks,
2318 int code, int uid, String packageName, int result) {
2319 // There are components watching for checks in our process. The callbacks in
2320 // these components may require permissions our remote caller does not have.
2321 final long identity = Binder.clearCallingIdentity();
2322 try {
2323 final int callbackCount = callbacks.size();
2324 for (int i = 0; i < callbackCount; i++) {
2325 final NotedCallback callback = callbacks.valueAt(i);
2326 try {
2327 callback.mCallback.opNoted(code, uid, packageName, result);
2328 } catch (RemoteException e) {
2329 /* do nothing */
2330 }
2331 }
2332 } finally {
2333 Binder.restoreCallingIdentity(identity);
2334 }
2335 }
2336
Svet Ganovb9d71a62015-04-30 10:38:13 -07002337 @Override
2338 public int permissionToOpCode(String permission) {
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00002339 if (permission == null) {
2340 return AppOpsManager.OP_NONE;
2341 }
Svet Ganovb9d71a62015-04-30 10:38:13 -07002342 return AppOpsManager.permissionToOpCode(permission);
2343 }
2344
Svet Ganova7a0db62018-02-27 20:08:01 -08002345 void finishOperationLocked(Op op, boolean finishNested) {
Svet Ganovaf189e32019-02-15 18:45:29 -08002346 final int opCode = op.op;
2347 final int uid = op.uidState.uid;
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002348 if (op.startNesting <= 1 || finishNested) {
2349 if (op.startNesting == 1 || finishNested) {
Svet Ganovaf189e32019-02-15 18:45:29 -08002350 // We don't support proxy long running ops (start/stop)
2351 final long duration = SystemClock.elapsedRealtime() - op.startRealtime;
2352 op.finished(System.currentTimeMillis(), duration, op.uidState.state,
2353 AppOpsManager.OP_FLAG_SELF);
2354 mHistoricalRegistry.increaseOpAccessDuration(opCode, uid, op.packageName,
2355 op.uidState.state, AppOpsManager.OP_FLAG_SELF, duration);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07002356 } else {
Svet Ganovaf189e32019-02-15 18:45:29 -08002357 final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes,
2358 op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames);
2359 Slog.w(TAG, "Finishing op nesting under-run: uid " + uid + " pkg "
2360 + op.packageName + " code " + opCode + " time="
2361 + entry.getLastAccessTime(OP_FLAGS_ALL)
2362 + " duration=" + entry.getLastDuration(MAX_PRIORITY_UID_STATE,
2363 MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL) + " nesting=" + op.startNesting);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07002364 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002365 if (op.startNesting >= 1) {
2366 op.uidState.startNesting -= op.startNesting;
2367 }
2368 op.startNesting = 0;
Dianne Hackborne98f5db2013-07-17 17:23:25 -07002369 } else {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002370 op.startNesting--;
2371 op.uidState.startNesting--;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002372 }
2373 }
2374
Dianne Hackbornf265ea92013-01-31 15:00:51 -08002375 private void verifyIncomingUid(int uid) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002376 if (uid == Binder.getCallingUid()) {
Dianne Hackbornf265ea92013-01-31 15:00:51 -08002377 return;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002378 }
2379 if (Binder.getCallingPid() == Process.myPid()) {
Dianne Hackbornf265ea92013-01-31 15:00:51 -08002380 return;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002381 }
2382 mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
2383 Binder.getCallingPid(), Binder.getCallingUid(), null);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002384 }
2385
Dianne Hackborn961321f2013-02-05 17:22:41 -08002386 private void verifyIncomingOp(int op) {
2387 if (op >= 0 && op < AppOpsManager._NUM_OP) {
2388 return;
2389 }
2390 throw new IllegalArgumentException("Bad operation #" + op);
2391 }
2392
Philip P. Moltmann724150d2019-03-11 17:01:05 -07002393 private @Nullable UidState getUidStateLocked(int uid, boolean edit) {
Svet Ganov2af57082015-07-30 08:44:20 -07002394 UidState uidState = mUidStates.get(uid);
2395 if (uidState == null) {
2396 if (!edit) {
2397 return null;
2398 }
2399 uidState = new UidState(uid);
2400 mUidStates.put(uid, uidState);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002401 } else {
2402 if (uidState.pendingStateCommitTime != 0) {
Dianne Hackborn9fb93502018-06-18 12:29:44 -07002403 if (uidState.pendingStateCommitTime < mLastRealtime) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07002404 commitUidPendingStateLocked(uidState);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002405 } else {
Dianne Hackborn9fb93502018-06-18 12:29:44 -07002406 mLastRealtime = SystemClock.elapsedRealtime();
2407 if (uidState.pendingStateCommitTime < mLastRealtime) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07002408 commitUidPendingStateLocked(uidState);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002409 }
2410 }
2411 }
Svet Ganov2af57082015-07-30 08:44:20 -07002412 }
2413 return uidState;
2414 }
2415
Dianne Hackborn65a4f252018-05-08 17:30:48 -07002416 private void commitUidPendingStateLocked(UidState uidState) {
Svet Ganovaf189e32019-02-15 18:45:29 -08002417 final boolean lastForeground = uidState.state <= UID_STATE_MAX_LAST_NON_RESTRICTED;
2418 final boolean nowForeground = uidState.pendingState <= UID_STATE_MAX_LAST_NON_RESTRICTED;
Dianne Hackborne93ab412018-05-14 17:52:30 -07002419 if (uidState.hasForegroundWatchers && lastForeground != nowForeground) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07002420 for (int fgi = uidState.foregroundOps.size() - 1; fgi >= 0; fgi--) {
2421 if (!uidState.foregroundOps.valueAt(fgi)) {
2422 continue;
2423 }
2424 final int code = uidState.foregroundOps.keyAt(fgi);
Svet Ganovaf189e32019-02-15 18:45:29 -08002425 // For location ops we consider fg state only if the fg service
2426 // is of location type, for all other ops any fg service will do.
Wei Wang711eb662019-03-21 18:24:17 -07002427 final long firstUnrestrictedUidState = resolveFirstUnrestrictedUidState(code);
2428 final boolean resolvedLastFg = uidState.state <= firstUnrestrictedUidState;
2429 final boolean resolvedNowFg = uidState.pendingState <= firstUnrestrictedUidState;
2430 if (resolvedLastFg == resolvedNowFg) {
Svet Ganovaf189e32019-02-15 18:45:29 -08002431 continue;
2432 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07002433 final ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code);
2434 if (callbacks != null) {
2435 for (int cbi = callbacks.size() - 1; cbi >= 0; cbi--) {
2436 final ModeCallback callback = callbacks.valueAt(cbi);
2437 if ((callback.mFlags & AppOpsManager.WATCH_FOREGROUND_CHANGES) == 0
2438 || !callback.isWatchingUid(uidState.uid)) {
2439 continue;
2440 }
2441 boolean doAllPackages = uidState.opModes != null
Hai Zhang2b98fb32018-09-21 15:18:46 -07002442 && uidState.opModes.indexOfKey(code) >= 0
Dianne Hackborn65a4f252018-05-08 17:30:48 -07002443 && uidState.opModes.get(code) == AppOpsManager.MODE_FOREGROUND;
2444 if (uidState.pkgOps != null) {
2445 for (int pkgi = uidState.pkgOps.size() - 1; pkgi >= 0; pkgi--) {
2446 final Op op = uidState.pkgOps.valueAt(pkgi).get(code);
Svet Ganovaf189e32019-02-15 18:45:29 -08002447 if (op == null) {
2448 continue;
2449 }
2450 if (doAllPackages || op.mode == AppOpsManager.MODE_FOREGROUND) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07002451 mHandler.sendMessage(PooledLambda.obtainMessage(
2452 AppOpsService::notifyOpChanged,
2453 this, callback, code, uidState.uid,
2454 uidState.pkgOps.keyAt(pkgi)));
2455 }
2456 }
2457 }
2458 }
2459 }
2460 }
2461 }
Wei Wang711eb662019-03-21 18:24:17 -07002462 uidState.state = uidState.pendingState;
2463 uidState.pendingStateCommitTime = 0;
Dianne Hackborn65a4f252018-05-08 17:30:48 -07002464 }
2465
Yohei Yukawaa965d652017-10-12 15:02:26 -07002466 private Ops getOpsRawLocked(int uid, String packageName, boolean edit,
2467 boolean uidMismatchExpected) {
Svet Ganov2af57082015-07-30 08:44:20 -07002468 UidState uidState = getUidStateLocked(uid, edit);
2469 if (uidState == null) {
2470 return null;
2471 }
2472
2473 if (uidState.pkgOps == null) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08002474 if (!edit) {
2475 return null;
2476 }
Svet Ganov2af57082015-07-30 08:44:20 -07002477 uidState.pkgOps = new ArrayMap<>();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002478 }
Svet Ganov2af57082015-07-30 08:44:20 -07002479
2480 Ops ops = uidState.pkgOps.get(packageName);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002481 if (ops == null) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08002482 if (!edit) {
2483 return null;
2484 }
Jason Monk1c7c3192014-06-26 12:52:18 -04002485 boolean isPrivileged = false;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002486 // This is the first time we have seen this package name under this uid,
2487 // so let's make sure it is valid.
Dianne Hackborn514074f2013-02-11 10:52:46 -08002488 if (uid != 0) {
2489 final long ident = Binder.clearCallingIdentity();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002490 try {
Dianne Hackborn514074f2013-02-11 10:52:46 -08002491 int pkgUid = -1;
2492 try {
Jason Monk1c7c3192014-06-26 12:52:18 -04002493 ApplicationInfo appInfo = ActivityThread.getPackageManager()
Jeff Sharkeycd654482016-01-08 17:42:11 -07002494 .getApplicationInfo(packageName,
Svet Ganovad0a49b2018-10-29 10:07:08 -07002495 PackageManager.MATCH_DIRECT_BOOT_AWARE
Svet Ganov8455ba22019-01-02 13:05:56 -08002496 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
Jeff Sharkeycd654482016-01-08 17:42:11 -07002497 UserHandle.getUserId(uid));
Jason Monk1c7c3192014-06-26 12:52:18 -04002498 if (appInfo != null) {
2499 pkgUid = appInfo.uid;
Alex Klyubinb9f8a522015-02-03 11:12:59 -08002500 isPrivileged = (appInfo.privateFlags
2501 & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
Jason Monk1c7c3192014-06-26 12:52:18 -04002502 } else {
Svet Ganov82f09bc2018-01-12 22:08:40 -08002503 pkgUid = resolveUid(packageName);
2504 if (pkgUid >= 0) {
Chien-Yu Chen75cade02016-01-11 10:56:21 -08002505 isPrivileged = false;
Jason Monk1c7c3192014-06-26 12:52:18 -04002506 }
Dianne Hackborn713df152013-05-17 11:27:57 -07002507 }
Jason Monk1c7c3192014-06-26 12:52:18 -04002508 } catch (RemoteException e) {
2509 Slog.w(TAG, "Could not contact PackageManager", e);
Dianne Hackborn514074f2013-02-11 10:52:46 -08002510 }
2511 if (pkgUid != uid) {
2512 // Oops! The package name is not valid for the uid they are calling
2513 // under. Abort.
Yohei Yukawaa965d652017-10-12 15:02:26 -07002514 if (!uidMismatchExpected) {
2515 RuntimeException ex = new RuntimeException("here");
2516 ex.fillInStackTrace();
2517 Slog.w(TAG, "Bad call: specified package " + packageName
2518 + " under uid " + uid + " but it is really " + pkgUid, ex);
2519 }
Dianne Hackborn514074f2013-02-11 10:52:46 -08002520 return null;
2521 }
2522 } finally {
2523 Binder.restoreCallingIdentity(ident);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002524 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002525 }
Svet Ganov2af57082015-07-30 08:44:20 -07002526 ops = new Ops(packageName, uidState, isPrivileged);
2527 uidState.pkgOps.put(packageName, ops);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002528 }
Dianne Hackborn72e39832013-01-18 18:36:09 -08002529 return ops;
2530 }
2531
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002532 /**
2533 * Get the state of all ops for a package, <b>don't verify that package belongs to uid</b>.
2534 *
2535 * <p>Usually callers should use {@link #getOpLocked} and not call this directly.
2536 *
2537 * @param uid The uid the of the package
2538 * @param packageName The package name for which to get the state for
2539 * @param edit Iff {@code true} create the {@link Ops} object if not yet created
2540 * @param isPrivileged Whether the package is privileged or not
2541 *
2542 * @return The {@link Ops state} of all ops for the package
2543 */
2544 private @Nullable Ops getOpsRawNoVerifyLocked(int uid, @NonNull String packageName,
2545 boolean edit, boolean isPrivileged) {
2546 UidState uidState = getUidStateLocked(uid, edit);
2547 if (uidState == null) {
2548 return null;
2549 }
2550
2551 if (uidState.pkgOps == null) {
2552 if (!edit) {
2553 return null;
2554 }
2555 uidState.pkgOps = new ArrayMap<>();
2556 }
2557
2558 Ops ops = uidState.pkgOps.get(packageName);
2559 if (ops == null) {
2560 if (!edit) {
2561 return null;
2562 }
2563 ops = new Ops(packageName, uidState, isPrivileged);
2564 uidState.pkgOps.put(packageName, ops);
2565 }
2566 return ops;
2567 }
2568
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002569 private void scheduleWriteLocked() {
2570 if (!mWriteScheduled) {
2571 mWriteScheduled = true;
2572 mHandler.postDelayed(mWriteRunner, WRITE_DELAY);
2573 }
2574 }
2575
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -08002576 private void scheduleFastWriteLocked() {
2577 if (!mFastWriteScheduled) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002578 mWriteScheduled = true;
Dianne Hackborn7b7c58b2014-12-02 18:32:20 -08002579 mFastWriteScheduled = true;
2580 mHandler.removeCallbacks(mWriteRunner);
2581 mHandler.postDelayed(mWriteRunner, 10*1000);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002582 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002583 }
2584
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002585 /**
2586 * Get the state of an op for a uid.
2587 *
2588 * @param code The code of the op
2589 * @param uid The uid the of the package
2590 * @param packageName The package name for which to get the state for
2591 * @param edit Iff {@code true} create the {@link Op} object if not yet created
2592 * @param verifyUid Iff {@code true} check that the package belongs to the uid
2593 * @param isPrivileged Whether the package is privileged or not (only used if {@code verifyUid
2594 * == false})
2595 *
2596 * @return The {@link Op state} of the op
2597 */
2598 private @Nullable Op getOpLocked(int code, int uid, @NonNull String packageName, boolean edit,
2599 boolean verifyUid, boolean isPrivileged) {
2600 Ops ops;
2601
2602 if (verifyUid) {
2603 ops = getOpsRawLocked(uid, packageName, edit, false /* uidMismatchExpected */);
2604 } else {
2605 ops = getOpsRawNoVerifyLocked(uid, packageName, edit, isPrivileged);
2606 }
2607
Dianne Hackborn72e39832013-01-18 18:36:09 -08002608 if (ops == null) {
2609 return null;
2610 }
Dianne Hackbornf265ea92013-01-31 15:00:51 -08002611 return getOpLocked(ops, code, edit);
2612 }
2613
2614 private Op getOpLocked(Ops ops, int code, boolean edit) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002615 Op op = ops.get(code);
2616 if (op == null) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08002617 if (!edit) {
2618 return null;
2619 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002620 op = new Op(ops.uidState, ops.packageName, code);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002621 ops.put(code, op);
2622 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002623 if (edit) {
2624 scheduleWriteLocked();
Dianne Hackborn35654b62013-01-14 17:38:02 -08002625 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002626 return op;
2627 }
2628
Svet Ganov442ed572016-08-17 17:29:43 -07002629 private boolean isOpRestrictedLocked(int uid, int code, String packageName) {
Jason Monk62062992014-05-06 09:55:28 -04002630 int userHandle = UserHandle.getUserId(uid);
Svet Ganov9cea80cd2016-02-16 11:47:00 -08002631 final int restrictionSetCount = mOpUserRestrictions.size();
Ruben Brunk29931bc2016-03-11 00:24:26 -08002632
Svet Ganov9cea80cd2016-02-16 11:47:00 -08002633 for (int i = 0; i < restrictionSetCount; i++) {
Ruben Brunk29931bc2016-03-11 00:24:26 -08002634 // For each client, check that the given op is not restricted, or that the given
2635 // package is exempt from the restriction.
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07002636 ClientRestrictionState restrictionState = mOpUserRestrictions.valueAt(i);
Suprabh Shuklaffddadb2016-05-20 16:37:26 -07002637 if (restrictionState.hasRestriction(code, packageName, userHandle)) {
2638 if (AppOpsManager.opAllowSystemBypassRestriction(code)) {
2639 // If we are the system, bypass user restrictions for certain codes
2640 synchronized (this) {
Yohei Yukawaa965d652017-10-12 15:02:26 -07002641 Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
2642 false /* uidMismatchExpected */);
Suprabh Shuklaffddadb2016-05-20 16:37:26 -07002643 if ((ops != null) && ops.isPrivileged) {
2644 return false;
2645 }
Ruben Brunk32f0fa42016-03-11 19:07:07 -08002646 }
Ruben Brunk29931bc2016-03-11 00:24:26 -08002647 }
Svet Ganov9cea80cd2016-02-16 11:47:00 -08002648 return true;
Jason Monk1c7c3192014-06-26 12:52:18 -04002649 }
Jason Monk62062992014-05-06 09:55:28 -04002650 }
2651 return false;
2652 }
2653
Dianne Hackborn35654b62013-01-14 17:38:02 -08002654 void readState() {
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07002655 int oldVersion = NO_VERSION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08002656 synchronized (mFile) {
2657 synchronized (this) {
2658 FileInputStream stream;
2659 try {
2660 stream = mFile.openRead();
2661 } catch (FileNotFoundException e) {
2662 Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty");
2663 return;
2664 }
2665 boolean success = false;
Dianne Hackborn4d34bb82015-08-07 18:26:38 -07002666 mUidStates.clear();
Dianne Hackborn35654b62013-01-14 17:38:02 -08002667 try {
2668 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002669 parser.setInput(stream, StandardCharsets.UTF_8.name());
Dianne Hackborn35654b62013-01-14 17:38:02 -08002670 int type;
2671 while ((type = parser.next()) != XmlPullParser.START_TAG
2672 && type != XmlPullParser.END_DOCUMENT) {
2673 ;
2674 }
2675
2676 if (type != XmlPullParser.START_TAG) {
2677 throw new IllegalStateException("no start tag found");
2678 }
2679
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07002680 final String versionString = parser.getAttributeValue(null, "v");
2681 if (versionString != null) {
2682 oldVersion = Integer.parseInt(versionString);
2683 }
2684
Dianne Hackborn35654b62013-01-14 17:38:02 -08002685 int outerDepth = parser.getDepth();
2686 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2687 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2688 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2689 continue;
2690 }
2691
2692 String tagName = parser.getName();
2693 if (tagName.equals("pkg")) {
Dave Burke0997c5bd2013-08-02 20:25:02 +00002694 readPackage(parser);
Svetoslav215b44a2015-08-04 19:03:40 -07002695 } else if (tagName.equals("uid")) {
Svet Ganov2af57082015-07-30 08:44:20 -07002696 readUidOps(parser);
Dianne Hackborn35654b62013-01-14 17:38:02 -08002697 } else {
2698 Slog.w(TAG, "Unknown element under <app-ops>: "
2699 + parser.getName());
2700 XmlUtils.skipCurrentTag(parser);
2701 }
2702 }
2703 success = true;
2704 } catch (IllegalStateException e) {
2705 Slog.w(TAG, "Failed parsing " + e);
2706 } catch (NullPointerException e) {
2707 Slog.w(TAG, "Failed parsing " + e);
2708 } catch (NumberFormatException e) {
2709 Slog.w(TAG, "Failed parsing " + e);
2710 } catch (XmlPullParserException e) {
2711 Slog.w(TAG, "Failed parsing " + e);
2712 } catch (IOException e) {
2713 Slog.w(TAG, "Failed parsing " + e);
2714 } catch (IndexOutOfBoundsException e) {
2715 Slog.w(TAG, "Failed parsing " + e);
2716 } finally {
2717 if (!success) {
Svet Ganov2af57082015-07-30 08:44:20 -07002718 mUidStates.clear();
Dianne Hackborn35654b62013-01-14 17:38:02 -08002719 }
2720 try {
2721 stream.close();
2722 } catch (IOException e) {
2723 }
2724 }
2725 }
2726 }
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07002727 synchronized (this) {
2728 upgradeLocked(oldVersion);
2729 }
2730 }
2731
2732 private void upgradeRunAnyInBackgroundLocked() {
2733 for (int i = 0; i < mUidStates.size(); i++) {
2734 final UidState uidState = mUidStates.valueAt(i);
2735 if (uidState == null) {
2736 continue;
2737 }
2738 if (uidState.opModes != null) {
2739 final int idx = uidState.opModes.indexOfKey(AppOpsManager.OP_RUN_IN_BACKGROUND);
2740 if (idx >= 0) {
2741 uidState.opModes.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
Svet Ganovaf189e32019-02-15 18:45:29 -08002742 uidState.opModes.valueAt(idx));
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07002743 }
2744 }
2745 if (uidState.pkgOps == null) {
2746 continue;
2747 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002748 boolean changed = false;
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07002749 for (int j = 0; j < uidState.pkgOps.size(); j++) {
2750 Ops ops = uidState.pkgOps.valueAt(j);
2751 if (ops != null) {
2752 final Op op = ops.get(AppOpsManager.OP_RUN_IN_BACKGROUND);
2753 if (op != null && op.mode != AppOpsManager.opToDefaultMode(op.op)) {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07002754 final Op copy = new Op(op.uidState, op.packageName,
Svet Ganovaf189e32019-02-15 18:45:29 -08002755 AppOpsManager.OP_RUN_ANY_IN_BACKGROUND);
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07002756 copy.mode = op.mode;
2757 ops.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, copy);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002758 changed = true;
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07002759 }
2760 }
2761 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002762 if (changed) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07002763 uidState.evalForegroundOps(mOpModeWatchers);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002764 }
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07002765 }
2766 }
2767
2768 private void upgradeLocked(int oldVersion) {
2769 if (oldVersion >= CURRENT_VERSION) {
2770 return;
2771 }
2772 Slog.d(TAG, "Upgrading app-ops xml from version " + oldVersion + " to " + CURRENT_VERSION);
2773 switch (oldVersion) {
2774 case NO_VERSION:
2775 upgradeRunAnyInBackgroundLocked();
2776 // fall through
2777 case 1:
2778 // for future upgrades
2779 }
2780 scheduleFastWriteLocked();
Dianne Hackborn35654b62013-01-14 17:38:02 -08002781 }
2782
Svet Ganovaf189e32019-02-15 18:45:29 -08002783 private void readUidOps(XmlPullParser parser) throws NumberFormatException,
Svet Ganov2af57082015-07-30 08:44:20 -07002784 XmlPullParserException, IOException {
2785 final int uid = Integer.parseInt(parser.getAttributeValue(null, "n"));
2786 int outerDepth = parser.getDepth();
2787 int type;
2788 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2789 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2790 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2791 continue;
2792 }
2793
2794 String tagName = parser.getName();
2795 if (tagName.equals("op")) {
2796 final int code = Integer.parseInt(parser.getAttributeValue(null, "n"));
2797 final int mode = Integer.parseInt(parser.getAttributeValue(null, "m"));
2798 UidState uidState = getUidStateLocked(uid, true);
2799 if (uidState.opModes == null) {
2800 uidState.opModes = new SparseIntArray();
2801 }
2802 uidState.opModes.put(code, mode);
2803 } else {
2804 Slog.w(TAG, "Unknown element under <uid-ops>: "
2805 + parser.getName());
2806 XmlUtils.skipCurrentTag(parser);
2807 }
2808 }
2809 }
2810
Svet Ganovaf189e32019-02-15 18:45:29 -08002811 private void readPackage(XmlPullParser parser)
2812 throws NumberFormatException, XmlPullParserException, IOException {
Dianne Hackborn35654b62013-01-14 17:38:02 -08002813 String pkgName = parser.getAttributeValue(null, "n");
2814 int outerDepth = parser.getDepth();
2815 int type;
2816 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2817 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2818 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2819 continue;
2820 }
2821
2822 String tagName = parser.getName();
2823 if (tagName.equals("uid")) {
Dave Burke0997c5bd2013-08-02 20:25:02 +00002824 readUid(parser, pkgName);
Dianne Hackborn35654b62013-01-14 17:38:02 -08002825 } else {
2826 Slog.w(TAG, "Unknown element under <pkg>: "
2827 + parser.getName());
2828 XmlUtils.skipCurrentTag(parser);
2829 }
2830 }
2831 }
2832
Svet Ganovaf189e32019-02-15 18:45:29 -08002833 private void readUid(XmlPullParser parser, String pkgName)
2834 throws NumberFormatException, XmlPullParserException, IOException {
Dianne Hackborn35654b62013-01-14 17:38:02 -08002835 int uid = Integer.parseInt(parser.getAttributeValue(null, "n"));
Svet Ganovaf189e32019-02-15 18:45:29 -08002836 final UidState uidState = getUidStateLocked(uid, true);
Jason Monk1c7c3192014-06-26 12:52:18 -04002837 String isPrivilegedString = parser.getAttributeValue(null, "p");
2838 boolean isPrivileged = false;
2839 if (isPrivilegedString == null) {
2840 try {
2841 IPackageManager packageManager = ActivityThread.getPackageManager();
2842 if (packageManager != null) {
2843 ApplicationInfo appInfo = ActivityThread.getPackageManager()
2844 .getApplicationInfo(pkgName, 0, UserHandle.getUserId(uid));
2845 if (appInfo != null) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08002846 isPrivileged = (appInfo.privateFlags
2847 & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
Jason Monk1c7c3192014-06-26 12:52:18 -04002848 }
2849 } else {
2850 // Could not load data, don't add to cache so it will be loaded later.
2851 return;
2852 }
2853 } catch (RemoteException e) {
2854 Slog.w(TAG, "Could not contact PackageManager", e);
2855 }
2856 } else {
2857 isPrivileged = Boolean.parseBoolean(isPrivilegedString);
2858 }
Dianne Hackborn35654b62013-01-14 17:38:02 -08002859 int outerDepth = parser.getDepth();
2860 int type;
2861 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2862 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2863 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2864 continue;
2865 }
Dianne Hackborn35654b62013-01-14 17:38:02 -08002866 String tagName = parser.getName();
2867 if (tagName.equals("op")) {
Svet Ganovaf189e32019-02-15 18:45:29 -08002868 readOp(parser, uidState, pkgName, isPrivileged);
Dianne Hackborn35654b62013-01-14 17:38:02 -08002869 } else {
2870 Slog.w(TAG, "Unknown element under <pkg>: "
2871 + parser.getName());
2872 XmlUtils.skipCurrentTag(parser);
2873 }
2874 }
Svet Ganovaf189e32019-02-15 18:45:29 -08002875 uidState.evalForegroundOps(mOpModeWatchers);
2876 }
2877
2878 private void readOp(XmlPullParser parser, @NonNull UidState uidState,
2879 @NonNull String pkgName, boolean isPrivileged) throws NumberFormatException,
2880 XmlPullParserException, IOException {
2881 Op op = new Op(uidState, pkgName,
2882 Integer.parseInt(parser.getAttributeValue(null, "n")));
2883
2884 final int mode = XmlUtils.readIntAttribute(parser, "m",
2885 AppOpsManager.opToDefaultMode(op.op));
2886 op.mode = mode;
2887
2888 int outerDepth = parser.getDepth();
2889 int type;
2890 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2891 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2892 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2893 continue;
2894 }
2895 String tagName = parser.getName();
2896 if (tagName.equals("st")) {
2897 final long key = XmlUtils.readLongAttribute(parser, "n");
2898
2899 final int flags = AppOpsManager.extractFlagsFromKey(key);
2900 final int state = AppOpsManager.extractUidStateFromKey(key);
2901
2902 final long accessTime = XmlUtils.readLongAttribute(parser, "t", 0);
2903 final long rejectTime = XmlUtils.readLongAttribute(parser, "r", 0);
2904 final long accessDuration = XmlUtils.readLongAttribute(parser, "d", 0);
2905 final String proxyPkg = XmlUtils.readStringAttribute(parser, "pp");
2906 final int proxyUid = XmlUtils.readIntAttribute(parser, "pu", 0);
2907
2908 if (accessTime > 0) {
2909 op.accessed(accessTime, proxyUid, proxyPkg, state, flags);
2910 }
2911 if (rejectTime > 0) {
2912 op.rejected(rejectTime, proxyUid, proxyPkg, state, flags);
2913 }
2914 if (accessDuration > 0) {
2915 op.running(accessTime, accessDuration, state, flags);
2916 }
2917 } else {
2918 Slog.w(TAG, "Unknown element under <op>: "
2919 + parser.getName());
2920 XmlUtils.skipCurrentTag(parser);
2921 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07002922 }
Svet Ganovaf189e32019-02-15 18:45:29 -08002923
2924 if (uidState.pkgOps == null) {
2925 uidState.pkgOps = new ArrayMap<>();
2926 }
2927 Ops ops = uidState.pkgOps.get(pkgName);
2928 if (ops == null) {
2929 ops = new Ops(pkgName, uidState, isPrivileged);
2930 uidState.pkgOps.put(pkgName, ops);
2931 }
2932 ops.put(op.op, op);
Dianne Hackborn35654b62013-01-14 17:38:02 -08002933 }
2934
2935 void writeState() {
2936 synchronized (mFile) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08002937 FileOutputStream stream;
2938 try {
2939 stream = mFile.startWrite();
2940 } catch (IOException e) {
2941 Slog.w(TAG, "Failed to write state: " + e);
2942 return;
2943 }
2944
Dianne Hackborne17b4452018-01-10 13:15:40 -08002945 List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null);
2946
Dianne Hackborn35654b62013-01-14 17:38:02 -08002947 try {
2948 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002949 out.setOutput(stream, StandardCharsets.UTF_8.name());
Dianne Hackborn35654b62013-01-14 17:38:02 -08002950 out.startDocument(null, true);
Dianne Hackborn4d34bb82015-08-07 18:26:38 -07002951 out.startTag(null, "app-ops");
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07002952 out.attribute(null, "v", String.valueOf(CURRENT_VERSION));
Svet Ganov2af57082015-07-30 08:44:20 -07002953
2954 final int uidStateCount = mUidStates.size();
2955 for (int i = 0; i < uidStateCount; i++) {
2956 UidState uidState = mUidStates.valueAt(i);
2957 if (uidState.opModes != null && uidState.opModes.size() > 0) {
2958 out.startTag(null, "uid");
2959 out.attribute(null, "n", Integer.toString(uidState.uid));
2960 SparseIntArray uidOpModes = uidState.opModes;
2961 final int opCount = uidOpModes.size();
2962 for (int j = 0; j < opCount; j++) {
2963 final int op = uidOpModes.keyAt(j);
2964 final int mode = uidOpModes.valueAt(j);
2965 out.startTag(null, "op");
2966 out.attribute(null, "n", Integer.toString(op));
2967 out.attribute(null, "m", Integer.toString(mode));
2968 out.endTag(null, "op");
2969 }
2970 out.endTag(null, "uid");
2971 }
2972 }
Dianne Hackborn35654b62013-01-14 17:38:02 -08002973
2974 if (allOps != null) {
2975 String lastPkg = null;
2976 for (int i=0; i<allOps.size(); i++) {
2977 AppOpsManager.PackageOps pkg = allOps.get(i);
2978 if (!pkg.getPackageName().equals(lastPkg)) {
2979 if (lastPkg != null) {
2980 out.endTag(null, "pkg");
2981 }
2982 lastPkg = pkg.getPackageName();
2983 out.startTag(null, "pkg");
2984 out.attribute(null, "n", lastPkg);
2985 }
2986 out.startTag(null, "uid");
2987 out.attribute(null, "n", Integer.toString(pkg.getUid()));
Jason Monk1c7c3192014-06-26 12:52:18 -04002988 synchronized (this) {
Yohei Yukawaa965d652017-10-12 15:02:26 -07002989 Ops ops = getOpsRawLocked(pkg.getUid(), pkg.getPackageName(),
2990 false /* edit */, false /* uidMismatchExpected */);
Jason Monk1c7c3192014-06-26 12:52:18 -04002991 // Should always be present as the list of PackageOps is generated
2992 // from Ops.
2993 if (ops != null) {
2994 out.attribute(null, "p", Boolean.toString(ops.isPrivileged));
2995 } else {
2996 out.attribute(null, "p", Boolean.toString(false));
2997 }
2998 }
Dianne Hackborn35654b62013-01-14 17:38:02 -08002999 List<AppOpsManager.OpEntry> ops = pkg.getOps();
3000 for (int j=0; j<ops.size(); j++) {
3001 AppOpsManager.OpEntry op = ops.get(j);
3002 out.startTag(null, "op");
3003 out.attribute(null, "n", Integer.toString(op.getOp()));
David Braunf5d83192013-09-16 13:43:51 -07003004 if (op.getMode() != AppOpsManager.opToDefaultMode(op.getOp())) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08003005 out.attribute(null, "m", Integer.toString(op.getMode()));
3006 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003007
3008 final LongSparseArray keys = op.collectKeys();
3009 if (keys == null || keys.size() <= 0) {
Svet Ganov8e5bf962019-03-19 23:59:03 -07003010 out.endTag(null, "op");
Svet Ganovaf189e32019-02-15 18:45:29 -08003011 continue;
3012 }
3013
3014 final int keyCount = keys.size();
3015 for (int k = 0; k < keyCount; k++) {
3016 final long key = keys.keyAt(k);
3017
3018 final int uidState = AppOpsManager.extractUidStateFromKey(key);
3019 final int flags = AppOpsManager.extractFlagsFromKey(key);
3020
3021 final long accessTime = op.getLastAccessTime(
3022 uidState, uidState, flags);
3023 final long rejectTime = op.getLastRejectTime(
3024 uidState, uidState, flags);
3025 final long accessDuration = op.getLastDuration(
3026 uidState, uidState, flags);
3027 final String proxyPkg = op.getProxyPackageName(uidState, flags);
3028 final int proxyUid = op.getProxyUid(uidState, flags);
3029
3030 if (accessTime <= 0 && rejectTime <= 0 && accessDuration <= 0
3031 && proxyPkg == null && proxyUid < 0) {
3032 continue;
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003033 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003034
3035 out.startTag(null, "st");
3036 out.attribute(null, "n", Long.toString(key));
3037 if (accessTime > 0) {
3038 out.attribute(null, "t", Long.toString(accessTime));
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003039 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003040 if (rejectTime > 0) {
3041 out.attribute(null, "r", Long.toString(rejectTime));
3042 }
3043 if (accessDuration > 0) {
3044 out.attribute(null, "d", Long.toString(accessDuration));
3045 }
3046 if (proxyPkg != null) {
3047 out.attribute(null, "pp", proxyPkg);
3048 }
3049 if (proxyUid >= 0) {
3050 out.attribute(null, "pu", Integer.toString(proxyUid));
3051 }
3052 out.endTag(null, "st");
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08003053 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003054
Dianne Hackborn35654b62013-01-14 17:38:02 -08003055 out.endTag(null, "op");
3056 }
3057 out.endTag(null, "uid");
3058 }
3059 if (lastPkg != null) {
3060 out.endTag(null, "pkg");
3061 }
3062 }
3063
3064 out.endTag(null, "app-ops");
3065 out.endDocument();
3066 mFile.finishWrite(stream);
3067 } catch (IOException e) {
3068 Slog.w(TAG, "Failed to write state, restoring backup.", e);
3069 mFile.failWrite(stream);
3070 }
3071 }
3072 }
3073
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003074 static class Shell extends ShellCommand {
3075 final IAppOpsService mInterface;
3076 final AppOpsService mInternal;
3077
3078 int userId = UserHandle.USER_SYSTEM;
3079 String packageName;
3080 String opStr;
Dianne Hackborne91f3e72016-03-25 18:48:15 -07003081 String modeStr;
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003082 int op;
Dianne Hackborne91f3e72016-03-25 18:48:15 -07003083 int mode;
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003084 int packageUid;
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003085 int nonpackageUid;
Julia Reynolds6cb5fcc2018-02-27 17:33:52 -05003086 final static Binder sBinder = new Binder();
3087 IBinder mToken;
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003088
3089 Shell(IAppOpsService iface, AppOpsService internal) {
3090 mInterface = iface;
3091 mInternal = internal;
Julia Reynolds6cb5fcc2018-02-27 17:33:52 -05003092 try {
3093 mToken = mInterface.getToken(sBinder);
3094 } catch (RemoteException e) {
3095 }
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003096 }
3097
3098 @Override
3099 public int onCommand(String cmd) {
3100 return onShellCommand(this, cmd);
3101 }
3102
3103 @Override
3104 public void onHelp() {
3105 PrintWriter pw = getOutPrintWriter();
3106 dumpCommandHelp(pw);
3107 }
3108
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003109 static private int strOpToOp(String op, PrintWriter err) {
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003110 try {
3111 return AppOpsManager.strOpToOp(op);
3112 } catch (IllegalArgumentException e) {
3113 }
3114 try {
3115 return Integer.parseInt(op);
3116 } catch (NumberFormatException e) {
3117 }
3118 try {
3119 return AppOpsManager.strDebugOpToOp(op);
3120 } catch (IllegalArgumentException e) {
3121 err.println("Error: " + e.getMessage());
3122 return -1;
3123 }
3124 }
3125
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003126 static int strModeToMode(String modeStr, PrintWriter err) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003127 for (int i = AppOpsManager.MODE_NAMES.length - 1; i >= 0; i--) {
3128 if (AppOpsManager.MODE_NAMES[i].equals(modeStr)) {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003129 return i;
3130 }
Dianne Hackborne91f3e72016-03-25 18:48:15 -07003131 }
3132 try {
3133 return Integer.parseInt(modeStr);
3134 } catch (NumberFormatException e) {
3135 }
3136 err.println("Error: Mode " + modeStr + " is not valid");
3137 return -1;
3138 }
3139
3140 int parseUserOpMode(int defMode, PrintWriter err) throws RemoteException {
3141 userId = UserHandle.USER_CURRENT;
3142 opStr = null;
3143 modeStr = null;
3144 for (String argument; (argument = getNextArg()) != null;) {
3145 if ("--user".equals(argument)) {
3146 userId = UserHandle.parseUserArg(getNextArgRequired());
3147 } else {
3148 if (opStr == null) {
3149 opStr = argument;
3150 } else if (modeStr == null) {
3151 modeStr = argument;
3152 break;
3153 }
3154 }
3155 }
3156 if (opStr == null) {
3157 err.println("Error: Operation not specified.");
3158 return -1;
3159 }
3160 op = strOpToOp(opStr, err);
3161 if (op < 0) {
3162 return -1;
3163 }
3164 if (modeStr != null) {
3165 if ((mode=strModeToMode(modeStr, err)) < 0) {
3166 return -1;
3167 }
3168 } else {
3169 mode = defMode;
3170 }
3171 return 0;
3172 }
3173
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003174 int parseUserPackageOp(boolean reqOp, PrintWriter err) throws RemoteException {
3175 userId = UserHandle.USER_CURRENT;
3176 packageName = null;
3177 opStr = null;
3178 for (String argument; (argument = getNextArg()) != null;) {
3179 if ("--user".equals(argument)) {
3180 userId = UserHandle.parseUserArg(getNextArgRequired());
3181 } else {
3182 if (packageName == null) {
3183 packageName = argument;
3184 } else if (opStr == null) {
3185 opStr = argument;
3186 break;
3187 }
3188 }
3189 }
3190 if (packageName == null) {
3191 err.println("Error: Package name not specified.");
3192 return -1;
3193 } else if (opStr == null && reqOp) {
3194 err.println("Error: Operation not specified.");
3195 return -1;
3196 }
3197 if (opStr != null) {
3198 op = strOpToOp(opStr, err);
3199 if (op < 0) {
3200 return -1;
3201 }
3202 } else {
3203 op = AppOpsManager.OP_NONE;
3204 }
3205 if (userId == UserHandle.USER_CURRENT) {
3206 userId = ActivityManager.getCurrentUser();
3207 }
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003208 nonpackageUid = -1;
3209 try {
3210 nonpackageUid = Integer.parseInt(packageName);
3211 } catch (NumberFormatException e) {
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003212 }
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003213 if (nonpackageUid == -1 && packageName.length() > 1 && packageName.charAt(0) == 'u'
3214 && packageName.indexOf('.') < 0) {
3215 int i = 1;
3216 while (i < packageName.length() && packageName.charAt(i) >= '0'
3217 && packageName.charAt(i) <= '9') {
3218 i++;
3219 }
3220 if (i > 1 && i < packageName.length()) {
3221 String userStr = packageName.substring(1, i);
3222 try {
3223 int user = Integer.parseInt(userStr);
3224 char type = packageName.charAt(i);
3225 i++;
3226 int startTypeVal = i;
3227 while (i < packageName.length() && packageName.charAt(i) >= '0'
3228 && packageName.charAt(i) <= '9') {
3229 i++;
3230 }
3231 if (i > startTypeVal) {
3232 String typeValStr = packageName.substring(startTypeVal, i);
3233 try {
3234 int typeVal = Integer.parseInt(typeValStr);
3235 if (type == 'a') {
3236 nonpackageUid = UserHandle.getUid(user,
3237 typeVal + Process.FIRST_APPLICATION_UID);
3238 } else if (type == 's') {
3239 nonpackageUid = UserHandle.getUid(user, typeVal);
3240 }
3241 } catch (NumberFormatException e) {
3242 }
3243 }
3244 } catch (NumberFormatException e) {
3245 }
3246 }
3247 }
3248 if (nonpackageUid != -1) {
3249 packageName = null;
3250 } else {
Svet Ganov82f09bc2018-01-12 22:08:40 -08003251 packageUid = resolveUid(packageName);
3252 if (packageUid < 0) {
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003253 packageUid = AppGlobals.getPackageManager().getPackageUid(packageName,
3254 PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
3255 }
3256 if (packageUid < 0) {
3257 err.println("Error: No UID for " + packageName + " in user " + userId);
3258 return -1;
3259 }
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003260 }
3261 return 0;
3262 }
3263 }
3264
3265 @Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
Dianne Hackborn354736e2016-08-22 17:00:05 -07003266 FileDescriptor err, String[] args, ShellCallback callback,
3267 ResultReceiver resultReceiver) {
3268 (new Shell(this, this)).exec(this, in, out, err, args, callback, resultReceiver);
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003269 }
3270
3271 static void dumpCommandHelp(PrintWriter pw) {
3272 pw.println("AppOps service (appops) commands:");
3273 pw.println(" help");
3274 pw.println(" Print this help text.");
Julia Reynolds6cb5fcc2018-02-27 17:33:52 -05003275 pw.println(" start [--user <USER_ID>] <PACKAGE | UID> <OP> ");
3276 pw.println(" Starts a given operation for a particular application.");
3277 pw.println(" stop [--user <USER_ID>] <PACKAGE | UID> <OP> ");
3278 pw.println(" Stops a given operation for a particular application.");
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003279 pw.println(" set [--user <USER_ID>] <PACKAGE | UID> <OP> <MODE>");
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003280 pw.println(" Set the mode for a particular application and operation.");
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003281 pw.println(" get [--user <USER_ID>] <PACKAGE | UID> [<OP>]");
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003282 pw.println(" Return the mode for a particular application and optional operation.");
Dianne Hackborne91f3e72016-03-25 18:48:15 -07003283 pw.println(" query-op [--user <USER_ID>] <OP> [<MODE>]");
3284 pw.println(" Print all packages that currently have the given op in the given mode.");
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003285 pw.println(" reset [--user <USER_ID>] [<PACKAGE>]");
3286 pw.println(" Reset the given application or all applications to default modes.");
Dianne Hackborn4d34bb82015-08-07 18:26:38 -07003287 pw.println(" write-settings");
3288 pw.println(" Immediately write pending changes to storage.");
3289 pw.println(" read-settings");
3290 pw.println(" Read the last written settings, replacing current state in RAM.");
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003291 pw.println(" options:");
3292 pw.println(" <PACKAGE> an Android package name.");
3293 pw.println(" <OP> an AppOps operation.");
3294 pw.println(" <MODE> one of allow, ignore, deny, or default");
3295 pw.println(" <USER_ID> the user id under which the package is installed. If --user is not");
3296 pw.println(" specified, the current user is assumed.");
3297 }
3298
3299 static int onShellCommand(Shell shell, String cmd) {
3300 if (cmd == null) {
3301 return shell.handleDefaultCommands(cmd);
3302 }
3303 PrintWriter pw = shell.getOutPrintWriter();
3304 PrintWriter err = shell.getErrPrintWriter();
3305 try {
3306 switch (cmd) {
3307 case "set": {
3308 int res = shell.parseUserPackageOp(true, err);
3309 if (res < 0) {
3310 return res;
3311 }
3312 String modeStr = shell.getNextArg();
3313 if (modeStr == null) {
3314 err.println("Error: Mode not specified.");
3315 return -1;
3316 }
3317
Dianne Hackborne91f3e72016-03-25 18:48:15 -07003318 final int mode = shell.strModeToMode(modeStr, err);
3319 if (mode < 0) {
3320 return -1;
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003321 }
3322
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003323 if (shell.packageName != null) {
3324 shell.mInterface.setMode(shell.op, shell.packageUid, shell.packageName,
3325 mode);
3326 } else {
3327 shell.mInterface.setUidMode(shell.op, shell.nonpackageUid, mode);
3328 }
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003329 return 0;
3330 }
3331 case "get": {
3332 int res = shell.parseUserPackageOp(false, err);
3333 if (res < 0) {
3334 return res;
3335 }
3336
Eugene Suslae4ee2c22018-11-05 12:23:30 -08003337 List<AppOpsManager.PackageOps> ops = new ArrayList<>();
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003338 if (shell.packageName != null) {
Eugene Suslae4ee2c22018-11-05 12:23:30 -08003339 // Uid mode overrides package mode, so make sure it's also reported
3340 List<AppOpsManager.PackageOps> r = shell.mInterface.getUidOps(
3341 shell.packageUid,
3342 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null);
3343 if (r != null) {
3344 ops.addAll(r);
3345 }
3346 r = shell.mInterface.getOpsForPackage(
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003347 shell.packageUid, shell.packageName,
3348 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null);
Eugene Suslae4ee2c22018-11-05 12:23:30 -08003349 if (r != null) {
3350 ops.addAll(r);
3351 }
Dianne Hackbornc7214a32017-04-11 13:32:47 -07003352 } else {
3353 ops = shell.mInterface.getUidOps(
3354 shell.nonpackageUid,
3355 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null);
3356 }
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003357 if (ops == null || ops.size() <= 0) {
3358 pw.println("No operations.");
Svet Ganov82f09bc2018-01-12 22:08:40 -08003359 if (shell.op > AppOpsManager.OP_NONE && shell.op < AppOpsManager._NUM_OP) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003360 pw.println("Default mode: " + AppOpsManager.modeToName(
Svet Ganov82f09bc2018-01-12 22:08:40 -08003361 AppOpsManager.opToDefaultMode(shell.op)));
3362 }
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003363 return 0;
3364 }
3365 final long now = System.currentTimeMillis();
3366 for (int i=0; i<ops.size(); i++) {
Eugene Suslae4ee2c22018-11-05 12:23:30 -08003367 AppOpsManager.PackageOps packageOps = ops.get(i);
3368 if (packageOps.getPackageName() == null) {
3369 pw.print("Uid mode: ");
3370 }
3371 List<AppOpsManager.OpEntry> entries = packageOps.getOps();
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003372 for (int j=0; j<entries.size(); j++) {
3373 AppOpsManager.OpEntry ent = entries.get(j);
3374 pw.print(AppOpsManager.opToName(ent.getOp()));
3375 pw.print(": ");
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003376 pw.print(AppOpsManager.modeToName(ent.getMode()));
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003377 if (ent.getTime() != 0) {
3378 pw.print("; time=");
3379 TimeUtils.formatDuration(now - ent.getTime(), pw);
3380 pw.print(" ago");
3381 }
3382 if (ent.getRejectTime() != 0) {
3383 pw.print("; rejectTime=");
3384 TimeUtils.formatDuration(now - ent.getRejectTime(), pw);
3385 pw.print(" ago");
3386 }
3387 if (ent.getDuration() == -1) {
3388 pw.print(" (running)");
3389 } else if (ent.getDuration() != 0) {
3390 pw.print("; duration=");
3391 TimeUtils.formatDuration(ent.getDuration(), pw);
3392 }
3393 pw.println();
3394 }
3395 }
3396 return 0;
3397 }
Dianne Hackborne91f3e72016-03-25 18:48:15 -07003398 case "query-op": {
3399 int res = shell.parseUserOpMode(AppOpsManager.MODE_IGNORED, err);
3400 if (res < 0) {
3401 return res;
3402 }
3403 List<AppOpsManager.PackageOps> ops = shell.mInterface.getPackagesForOps(
3404 new int[] {shell.op});
3405 if (ops == null || ops.size() <= 0) {
3406 pw.println("No operations.");
3407 return 0;
3408 }
3409 for (int i=0; i<ops.size(); i++) {
3410 final AppOpsManager.PackageOps pkg = ops.get(i);
3411 boolean hasMatch = false;
3412 final List<AppOpsManager.OpEntry> entries = ops.get(i).getOps();
3413 for (int j=0; j<entries.size(); j++) {
3414 AppOpsManager.OpEntry ent = entries.get(j);
3415 if (ent.getOp() == shell.op && ent.getMode() == shell.mode) {
3416 hasMatch = true;
3417 break;
3418 }
3419 }
3420 if (hasMatch) {
3421 pw.println(pkg.getPackageName());
3422 }
3423 }
3424 return 0;
3425 }
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003426 case "reset": {
3427 String packageName = null;
3428 int userId = UserHandle.USER_CURRENT;
3429 for (String argument; (argument = shell.getNextArg()) != null;) {
3430 if ("--user".equals(argument)) {
3431 String userStr = shell.getNextArgRequired();
3432 userId = UserHandle.parseUserArg(userStr);
3433 } else {
3434 if (packageName == null) {
3435 packageName = argument;
3436 } else {
3437 err.println("Error: Unsupported argument: " + argument);
3438 return -1;
3439 }
3440 }
3441 }
3442
3443 if (userId == UserHandle.USER_CURRENT) {
3444 userId = ActivityManager.getCurrentUser();
3445 }
3446
3447 shell.mInterface.resetAllModes(userId, packageName);
3448 pw.print("Reset all modes for: ");
3449 if (userId == UserHandle.USER_ALL) {
3450 pw.print("all users");
3451 } else {
3452 pw.print("user "); pw.print(userId);
3453 }
3454 pw.print(", ");
3455 if (packageName == null) {
3456 pw.println("all packages");
3457 } else {
3458 pw.print("package "); pw.println(packageName);
3459 }
3460 return 0;
3461 }
3462 case "write-settings": {
Dianne Hackbornd5254412018-05-11 18:02:58 -07003463 shell.mInternal.enforceManageAppOpsModes(Binder.getCallingPid(),
3464 Binder.getCallingUid(), -1);
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003465 long token = Binder.clearCallingIdentity();
3466 try {
3467 synchronized (shell.mInternal) {
3468 shell.mInternal.mHandler.removeCallbacks(shell.mInternal.mWriteRunner);
3469 }
3470 shell.mInternal.writeState();
3471 pw.println("Current settings written.");
3472 } finally {
3473 Binder.restoreCallingIdentity(token);
3474 }
3475 return 0;
3476 }
3477 case "read-settings": {
Dianne Hackbornd5254412018-05-11 18:02:58 -07003478 shell.mInternal.enforceManageAppOpsModes(Binder.getCallingPid(),
3479 Binder.getCallingUid(), -1);
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003480 long token = Binder.clearCallingIdentity();
3481 try {
3482 shell.mInternal.readState();
3483 pw.println("Last settings read.");
3484 } finally {
3485 Binder.restoreCallingIdentity(token);
3486 }
3487 return 0;
3488 }
Julia Reynolds6cb5fcc2018-02-27 17:33:52 -05003489 case "start": {
3490 int res = shell.parseUserPackageOp(true, err);
3491 if (res < 0) {
3492 return res;
3493 }
3494
3495 if (shell.packageName != null) {
3496 shell.mInterface.startOperation(shell.mToken,
3497 shell.op, shell.packageUid, shell.packageName, true);
3498 } else {
3499 return -1;
3500 }
3501 return 0;
3502 }
3503 case "stop": {
3504 int res = shell.parseUserPackageOp(true, err);
3505 if (res < 0) {
3506 return res;
3507 }
3508
3509 if (shell.packageName != null) {
3510 shell.mInterface.finishOperation(shell.mToken,
3511 shell.op, shell.packageUid, shell.packageName);
3512 } else {
3513 return -1;
3514 }
3515 return 0;
3516 }
Dianne Hackborn268e4e32015-11-18 16:29:56 -08003517 default:
3518 return shell.handleDefaultCommands(cmd);
3519 }
3520 } catch (RemoteException e) {
3521 pw.println("Remote exception: " + e);
3522 }
3523 return -1;
3524 }
3525
3526 private void dumpHelp(PrintWriter pw) {
3527 pw.println("AppOps service (appops) dump options:");
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003528 pw.println(" -h");
3529 pw.println(" Print this help text.");
3530 pw.println(" --op [OP]");
3531 pw.println(" Limit output to data associated with the given app op code.");
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003532 pw.println(" --mode [MODE]");
3533 pw.println(" Limit output to data associated with the given app op mode.");
3534 pw.println(" --package [PACKAGE]");
3535 pw.println(" Limit output to data associated with the given package name.");
Dianne Hackborn125dc532019-01-09 13:31:48 -08003536 pw.println(" --watchers");
3537 pw.println(" Only output the watcher sections.");
Svet Ganovaf189e32019-02-15 18:45:29 -08003538 pw.println(" --history");
3539 pw.println(" Output the historical data.");
Dianne Hackborn4d34bb82015-08-07 18:26:38 -07003540 }
3541
Svet Ganovaf189e32019-02-15 18:45:29 -08003542 private void dumpStatesLocked(@NonNull PrintWriter pw, @NonNull Op op,
3543 long now, @NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix) {
3544
3545 final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes,
3546 op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames);
3547
3548 final LongSparseArray keys = entry.collectKeys();
3549 if (keys == null || keys.size() <= 0) {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003550 return;
3551 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003552
3553 final int keyCount = keys.size();
3554 for (int k = 0; k < keyCount; k++) {
3555 final long key = keys.keyAt(k);
3556
3557 final int uidState = AppOpsManager.extractUidStateFromKey(key);
3558 final int flags = AppOpsManager.extractFlagsFromKey(key);
3559
3560 final long accessTime = entry.getLastAccessTime(
3561 uidState, uidState, flags);
3562 final long rejectTime = entry.getLastRejectTime(
3563 uidState, uidState, flags);
3564 final long accessDuration = entry.getLastDuration(
3565 uidState, uidState, flags);
3566 final String proxyPkg = entry.getProxyPackageName(uidState, flags);
3567 final int proxyUid = entry.getProxyUid(uidState, flags);
3568
3569 if (accessTime > 0) {
3570 pw.print(prefix);
3571 pw.print("Access: ");
3572 pw.print(AppOpsManager.keyToString(key));
3573 pw.print(" ");
3574 date.setTime(accessTime);
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003575 pw.print(sdf.format(date));
3576 pw.print(" (");
Svet Ganovaf189e32019-02-15 18:45:29 -08003577 TimeUtils.formatDuration(accessTime - now, pw);
3578 pw.print(")");
3579 if (accessDuration > 0) {
3580 pw.print(" duration=");
3581 TimeUtils.formatDuration(accessDuration, pw);
3582 }
3583 if (proxyUid >= 0) {
3584 pw.print(" proxy[");
3585 pw.print("uid=");
3586 pw.print(proxyUid);
3587 pw.print(", pkg=");
3588 pw.print(proxyPkg);
3589 pw.print("]");
3590 }
3591 pw.println();
3592 }
3593
3594 if (rejectTime > 0) {
3595 pw.print(prefix);
3596 pw.print("Reject: ");
3597 pw.print(AppOpsManager.keyToString(key));
3598 date.setTime(rejectTime);
3599 pw.print(sdf.format(date));
3600 pw.print(" (");
3601 TimeUtils.formatDuration(rejectTime - now, pw);
3602 pw.print(")");
3603 if (proxyUid >= 0) {
3604 pw.print(" proxy[");
3605 pw.print("uid=");
3606 pw.print(proxyUid);
3607 pw.print(", pkg=");
3608 pw.print(proxyPkg);
3609 pw.print("]");
3610 }
3611 pw.println();
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003612 }
3613 }
3614 }
3615
Dianne Hackborna06de0f2012-12-11 16:34:47 -08003616 @Override
3617 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkey6df866a2017-03-31 14:08:23 -06003618 if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08003619
Svet Ganov8455ba22019-01-02 13:05:56 -08003620 int dumpOp = OP_NONE;
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003621 String dumpPackage = null;
Svet Ganov8455ba22019-01-02 13:05:56 -08003622 int dumpUid = Process.INVALID_UID;
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003623 int dumpMode = -1;
Dianne Hackborn125dc532019-01-09 13:31:48 -08003624 boolean dumpWatchers = false;
Svet Ganovaf189e32019-02-15 18:45:29 -08003625 boolean dumpHistory = false;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003626
Dianne Hackborn4d34bb82015-08-07 18:26:38 -07003627 if (args != null) {
3628 for (int i=0; i<args.length; i++) {
3629 String arg = args[i];
3630 if ("-h".equals(arg)) {
3631 dumpHelp(pw);
3632 return;
Tim Kilbourn8f1ea832015-08-26 15:07:37 -07003633 } else if ("-a".equals(arg)) {
3634 // dump all data
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003635 } else if ("--op".equals(arg)) {
3636 i++;
3637 if (i >= args.length) {
3638 pw.println("No argument for --op option");
3639 return;
3640 }
3641 dumpOp = Shell.strOpToOp(args[i], pw);
3642 if (dumpOp < 0) {
3643 return;
3644 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003645 } else if ("--package".equals(arg)) {
3646 i++;
3647 if (i >= args.length) {
3648 pw.println("No argument for --package option");
3649 return;
3650 }
3651 dumpPackage = args[i];
3652 try {
3653 dumpUid = AppGlobals.getPackageManager().getPackageUid(dumpPackage,
3654 PackageManager.MATCH_KNOWN_PACKAGES | PackageManager.MATCH_INSTANT,
3655 0);
3656 } catch (RemoteException e) {
3657 }
3658 if (dumpUid < 0) {
3659 pw.println("Unknown package: " + dumpPackage);
3660 return;
3661 }
3662 dumpUid = UserHandle.getAppId(dumpUid);
3663 } else if ("--mode".equals(arg)) {
3664 i++;
3665 if (i >= args.length) {
3666 pw.println("No argument for --mode option");
3667 return;
3668 }
3669 dumpMode = Shell.strModeToMode(args[i], pw);
3670 if (dumpMode < 0) {
3671 return;
3672 }
Dianne Hackborn125dc532019-01-09 13:31:48 -08003673 } else if ("--watchers".equals(arg)) {
3674 dumpWatchers = true;
Svet Ganovaf189e32019-02-15 18:45:29 -08003675 } else if ("--history".equals(arg)) {
3676 dumpHistory = true;
Dianne Hackborn4d34bb82015-08-07 18:26:38 -07003677 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
3678 pw.println("Unknown option: " + arg);
3679 return;
3680 } else {
3681 pw.println("Unknown command: " + arg);
3682 return;
3683 }
3684 }
3685 }
3686
Dianne Hackborna06de0f2012-12-11 16:34:47 -08003687 synchronized (this) {
3688 pw.println("Current AppOps Service state:");
Svet Ganovaf189e32019-02-15 18:45:29 -08003689 if (!dumpHistory && !dumpWatchers) {
3690 mConstants.dump(pw);
3691 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003692 pw.println();
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08003693 final long now = System.currentTimeMillis();
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003694 final long nowElapsed = SystemClock.elapsedRealtime();
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003695 final long nowUptime = SystemClock.uptimeMillis();
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003696 final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
3697 final Date date = new Date();
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003698 boolean needSep = false;
Dianne Hackborn125dc532019-01-09 13:31:48 -08003699 if (dumpOp < 0 && dumpMode < 0 && dumpPackage == null && mProfileOwners != null
Svet Ganovaf189e32019-02-15 18:45:29 -08003700 && !dumpWatchers && !dumpHistory) {
Dianne Hackbornd5254412018-05-11 18:02:58 -07003701 pw.println(" Profile owners:");
3702 for (int poi = 0; poi < mProfileOwners.size(); poi++) {
3703 pw.print(" User #");
3704 pw.print(mProfileOwners.keyAt(poi));
3705 pw.print(": ");
3706 UserHandle.formatUid(pw, mProfileOwners.valueAt(poi));
3707 pw.println();
3708 }
3709 pw.println();
3710 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003711 if (mOpModeWatchers.size() > 0 && !dumpHistory) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003712 boolean printedHeader = false;
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003713 for (int i=0; i<mOpModeWatchers.size(); i++) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003714 if (dumpOp >= 0 && dumpOp != mOpModeWatchers.keyAt(i)) {
3715 continue;
3716 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003717 boolean printedOpHeader = false;
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08003718 ArraySet<ModeCallback> callbacks = mOpModeWatchers.valueAt(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003719 for (int j=0; j<callbacks.size(); j++) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003720 final ModeCallback cb = callbacks.valueAt(j);
Dianne Hackborn125dc532019-01-09 13:31:48 -08003721 if (dumpPackage != null
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003722 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) {
3723 continue;
3724 }
3725 needSep = true;
3726 if (!printedHeader) {
3727 pw.println(" Op mode watchers:");
3728 printedHeader = true;
3729 }
3730 if (!printedOpHeader) {
3731 pw.print(" Op ");
3732 pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i)));
3733 pw.println(":");
3734 printedOpHeader = true;
3735 }
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003736 pw.print(" #"); pw.print(j); pw.print(": ");
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003737 pw.println(cb);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003738 }
3739 }
3740 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003741 if (mPackageModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003742 boolean printedHeader = false;
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003743 for (int i=0; i<mPackageModeWatchers.size(); i++) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003744 if (dumpPackage != null && !dumpPackage.equals(mPackageModeWatchers.keyAt(i))) {
3745 continue;
3746 }
3747 needSep = true;
3748 if (!printedHeader) {
3749 pw.println(" Package mode watchers:");
3750 printedHeader = true;
3751 }
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003752 pw.print(" Pkg "); pw.print(mPackageModeWatchers.keyAt(i));
3753 pw.println(":");
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08003754 ArraySet<ModeCallback> callbacks = mPackageModeWatchers.valueAt(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003755 for (int j=0; j<callbacks.size(); j++) {
3756 pw.print(" #"); pw.print(j); pw.print(": ");
Dianne Hackborn68d76552017-02-27 15:32:03 -08003757 pw.println(callbacks.valueAt(j));
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003758 }
3759 }
3760 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003761 if (mModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003762 boolean printedHeader = false;
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003763 for (int i=0; i<mModeWatchers.size(); i++) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003764 final ModeCallback cb = mModeWatchers.valueAt(i);
Dianne Hackborn125dc532019-01-09 13:31:48 -08003765 if (dumpPackage != null
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003766 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) {
3767 continue;
3768 }
3769 needSep = true;
3770 if (!printedHeader) {
3771 pw.println(" All op mode watchers:");
3772 printedHeader = true;
3773 }
Dianne Hackborn3b563fc2018-04-16 17:17:14 -07003774 pw.print(" ");
3775 pw.print(Integer.toHexString(System.identityHashCode(mModeWatchers.keyAt(i))));
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003776 pw.print(": "); pw.println(cb);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003777 }
3778 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003779 if (mActiveWatchers.size() > 0 && dumpMode < 0) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08003780 needSep = true;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003781 boolean printedHeader = false;
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08003782 for (int i = 0; i < mActiveWatchers.size(); i++) {
3783 final SparseArray<ActiveCallback> activeWatchers = mActiveWatchers.valueAt(i);
3784 if (activeWatchers.size() <= 0) {
3785 continue;
3786 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003787 final ActiveCallback cb = activeWatchers.valueAt(0);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003788 if (dumpOp >= 0 && activeWatchers.indexOfKey(dumpOp) < 0) {
3789 continue;
3790 }
Dianne Hackborn125dc532019-01-09 13:31:48 -08003791 if (dumpPackage != null
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003792 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) {
3793 continue;
3794 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003795 if (!printedHeader) {
3796 pw.println(" All op active watchers:");
3797 printedHeader = true;
3798 }
Dianne Hackborn3b563fc2018-04-16 17:17:14 -07003799 pw.print(" ");
3800 pw.print(Integer.toHexString(System.identityHashCode(
3801 mActiveWatchers.keyAt(i))));
3802 pw.println(" ->");
3803 pw.print(" [");
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08003804 final int opCount = activeWatchers.size();
3805 for (i = 0; i < opCount; i++) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003806 if (i > 0) {
3807 pw.print(' ');
3808 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08003809 pw.print(AppOpsManager.opToName(activeWatchers.keyAt(i)));
3810 if (i < opCount - 1) {
3811 pw.print(',');
3812 }
3813 }
Dianne Hackborn3b563fc2018-04-16 17:17:14 -07003814 pw.println("]");
3815 pw.print(" ");
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003816 pw.println(cb);
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08003817 }
3818 }
Svet Ganovb3d2ae22018-12-17 22:06:15 -08003819 if (mNotedWatchers.size() > 0 && dumpMode < 0) {
3820 needSep = true;
3821 boolean printedHeader = false;
3822 for (int i = 0; i < mNotedWatchers.size(); i++) {
3823 final SparseArray<NotedCallback> notedWatchers = mNotedWatchers.valueAt(i);
3824 if (notedWatchers.size() <= 0) {
3825 continue;
3826 }
3827 final NotedCallback cb = notedWatchers.valueAt(0);
3828 if (dumpOp >= 0 && notedWatchers.indexOfKey(dumpOp) < 0) {
3829 continue;
3830 }
Dianne Hackborn125dc532019-01-09 13:31:48 -08003831 if (dumpPackage != null
Svet Ganovb3d2ae22018-12-17 22:06:15 -08003832 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) {
3833 continue;
3834 }
3835 if (!printedHeader) {
3836 pw.println(" All op noted watchers:");
3837 printedHeader = true;
3838 }
3839 pw.print(" ");
3840 pw.print(Integer.toHexString(System.identityHashCode(
3841 mNotedWatchers.keyAt(i))));
3842 pw.println(" ->");
3843 pw.print(" [");
3844 final int opCount = notedWatchers.size();
3845 for (i = 0; i < opCount; i++) {
3846 if (i > 0) {
3847 pw.print(' ');
3848 }
3849 pw.print(AppOpsManager.opToName(notedWatchers.keyAt(i)));
3850 if (i < opCount - 1) {
3851 pw.print(',');
3852 }
3853 }
3854 pw.println("]");
3855 pw.print(" ");
3856 pw.println(cb);
3857 }
3858 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003859 if (mClients.size() > 0 && dumpMode < 0 && !dumpWatchers && !dumpHistory) {
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003860 needSep = true;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003861 boolean printedHeader = false;
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003862 for (int i=0; i<mClients.size(); i++) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003863 boolean printedClient = false;
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003864 ClientState cs = mClients.valueAt(i);
Svet Ganovf7b47252018-02-26 11:11:27 -08003865 if (cs.mStartedOps.size() > 0) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003866 boolean printedStarted = false;
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003867 for (int j=0; j<cs.mStartedOps.size(); j++) {
3868 Op op = cs.mStartedOps.get(j);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003869 if (dumpOp >= 0 && op.op != dumpOp) {
3870 continue;
3871 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003872 if (dumpPackage != null && !dumpPackage.equals(op.packageName)) {
3873 continue;
3874 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003875 if (!printedHeader) {
3876 pw.println(" Clients:");
3877 printedHeader = true;
3878 }
3879 if (!printedClient) {
3880 pw.print(" "); pw.print(mClients.keyAt(i)); pw.println(":");
3881 pw.print(" "); pw.println(cs);
3882 printedClient = true;
3883 }
3884 if (!printedStarted) {
3885 pw.println(" Started ops:");
3886 printedStarted = true;
3887 }
Svet Ganovaf189e32019-02-15 18:45:29 -08003888 pw.print(" "); pw.print("uid="); pw.print(op.uidState.uid);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003889 pw.print(" pkg="); pw.print(op.packageName);
3890 pw.print(" op="); pw.println(AppOpsManager.opToName(op.op));
3891 }
3892 }
3893 }
3894 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003895 if (mAudioRestrictions.size() > 0 && dumpOp < 0 && dumpPackage != null
Svet Ganovaf189e32019-02-15 18:45:29 -08003896 && dumpMode < 0 && !dumpWatchers && !dumpWatchers) {
John Spurlock1af30c72014-03-10 08:33:35 -04003897 boolean printedHeader = false;
3898 for (int o=0; o<mAudioRestrictions.size(); o++) {
3899 final String op = AppOpsManager.opToName(mAudioRestrictions.keyAt(o));
3900 final SparseArray<Restriction> restrictions = mAudioRestrictions.valueAt(o);
3901 for (int i=0; i<restrictions.size(); i++) {
3902 if (!printedHeader){
3903 pw.println(" Audio Restrictions:");
3904 printedHeader = true;
3905 needSep = true;
3906 }
John Spurlock7b414672014-07-18 13:02:39 -04003907 final int usage = restrictions.keyAt(i);
John Spurlock1af30c72014-03-10 08:33:35 -04003908 pw.print(" "); pw.print(op);
John Spurlock7b414672014-07-18 13:02:39 -04003909 pw.print(" usage="); pw.print(AudioAttributes.usageToString(usage));
John Spurlock1af30c72014-03-10 08:33:35 -04003910 Restriction r = restrictions.valueAt(i);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003911 pw.print(": mode="); pw.println(AppOpsManager.modeToName(r.mode));
John Spurlock1af30c72014-03-10 08:33:35 -04003912 if (!r.exceptionPackages.isEmpty()) {
3913 pw.println(" Exceptions:");
3914 for (int j=0; j<r.exceptionPackages.size(); j++) {
3915 pw.print(" "); pw.println(r.exceptionPackages.valueAt(j));
3916 }
3917 }
3918 }
3919 }
3920 }
Dianne Hackborne98f5db2013-07-17 17:23:25 -07003921 if (needSep) {
3922 pw.println();
3923 }
Svet Ganov2af57082015-07-30 08:44:20 -07003924 for (int i=0; i<mUidStates.size(); i++) {
3925 UidState uidState = mUidStates.valueAt(i);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003926 final SparseIntArray opModes = uidState.opModes;
3927 final ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
3928
Svet Ganovaf189e32019-02-15 18:45:29 -08003929 if (dumpWatchers || dumpHistory) {
Dianne Hackborn125dc532019-01-09 13:31:48 -08003930 continue;
3931 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003932 if (dumpOp >= 0 || dumpPackage != null || dumpMode >= 0) {
3933 boolean hasOp = dumpOp < 0 || (uidState.opModes != null
3934 && uidState.opModes.indexOfKey(dumpOp) >= 0);
3935 boolean hasPackage = dumpPackage == null;
3936 boolean hasMode = dumpMode < 0;
3937 if (!hasMode && opModes != null) {
3938 for (int opi = 0; !hasMode && opi < opModes.size(); opi++) {
3939 if (opModes.valueAt(opi) == dumpMode) {
3940 hasMode = true;
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003941 }
3942 }
3943 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003944 if (pkgOps != null) {
3945 for (int pkgi = 0;
Svet Ganov8455ba22019-01-02 13:05:56 -08003946 (!hasOp || !hasPackage || !hasMode) && pkgi < pkgOps.size();
3947 pkgi++) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003948 Ops ops = pkgOps.valueAt(pkgi);
3949 if (!hasOp && ops != null && ops.indexOfKey(dumpOp) >= 0) {
3950 hasOp = true;
3951 }
3952 if (!hasMode) {
3953 for (int opi = 0; !hasMode && opi < ops.size(); opi++) {
3954 if (ops.valueAt(opi).mode == dumpMode) {
3955 hasMode = true;
3956 }
3957 }
3958 }
3959 if (!hasPackage && dumpPackage.equals(ops.packageName)) {
3960 hasPackage = true;
3961 }
3962 }
3963 }
3964 if (uidState.foregroundOps != null && !hasOp) {
3965 if (uidState.foregroundOps.indexOfKey(dumpOp) > 0) {
3966 hasOp = true;
3967 }
3968 }
3969 if (!hasOp || !hasPackage || !hasMode) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003970 continue;
3971 }
3972 }
Svet Ganov2af57082015-07-30 08:44:20 -07003973
3974 pw.print(" Uid "); UserHandle.formatUid(pw, uidState.uid); pw.println(":");
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003975 pw.print(" state=");
Svet Ganovaf189e32019-02-15 18:45:29 -08003976 pw.println(AppOpsManager.getUidStateName(uidState.state));
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003977 if (uidState.state != uidState.pendingState) {
3978 pw.print(" pendingState=");
Svet Ganovaf189e32019-02-15 18:45:29 -08003979 pw.println(AppOpsManager.getUidStateName(uidState.pendingState));
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003980 }
3981 if (uidState.pendingStateCommitTime != 0) {
3982 pw.print(" pendingStateCommitTime=");
Dianne Hackborn9fb93502018-06-18 12:29:44 -07003983 TimeUtils.formatDuration(uidState.pendingStateCommitTime, nowElapsed, pw);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003984 pw.println();
3985 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07003986 if (uidState.startNesting != 0) {
3987 pw.print(" startNesting=");
3988 pw.println(uidState.startNesting);
3989 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003990 if (uidState.foregroundOps != null && (dumpMode < 0
3991 || dumpMode == AppOpsManager.MODE_FOREGROUND)) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07003992 pw.println(" foregroundOps:");
3993 for (int j = 0; j < uidState.foregroundOps.size(); j++) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07003994 if (dumpOp >= 0 && dumpOp != uidState.foregroundOps.keyAt(j)) {
3995 continue;
3996 }
3997 pw.print(" ");
3998 pw.print(AppOpsManager.opToName(uidState.foregroundOps.keyAt(j)));
3999 pw.print(": ");
4000 pw.println(uidState.foregroundOps.valueAt(j) ? "WATCHER" : "SILENT");
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004001 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07004002 pw.print(" hasForegroundWatchers=");
4003 pw.println(uidState.hasForegroundWatchers);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004004 }
Svet Ganovee438d42017-01-19 18:04:38 -08004005 needSep = true;
Svet Ganov2af57082015-07-30 08:44:20 -07004006
Svet Ganov2af57082015-07-30 08:44:20 -07004007 if (opModes != null) {
4008 final int opModeCount = opModes.size();
4009 for (int j = 0; j < opModeCount; j++) {
4010 final int code = opModes.keyAt(j);
4011 final int mode = opModes.valueAt(j);
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004012 if (dumpOp >= 0 && dumpOp != code) {
4013 continue;
4014 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07004015 if (dumpMode >= 0 && dumpMode != mode) {
4016 continue;
4017 }
Svet Ganov2af57082015-07-30 08:44:20 -07004018 pw.print(" "); pw.print(AppOpsManager.opToName(code));
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004019 pw.print(": mode="); pw.println(AppOpsManager.modeToName(mode));
Svet Ganov2af57082015-07-30 08:44:20 -07004020 }
4021 }
4022
Svet Ganov2af57082015-07-30 08:44:20 -07004023 if (pkgOps == null) {
4024 continue;
4025 }
4026
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004027 for (int pkgi = 0; pkgi < pkgOps.size(); pkgi++) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07004028 final Ops ops = pkgOps.valueAt(pkgi);
4029 if (dumpPackage != null && !dumpPackage.equals(ops.packageName)) {
4030 continue;
4031 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004032 boolean printedPackage = false;
Dianne Hackborna06de0f2012-12-11 16:34:47 -08004033 for (int j=0; j<ops.size(); j++) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07004034 final Op op = ops.valueAt(j);
Svet Ganovaf189e32019-02-15 18:45:29 -08004035 final int opCode = op.op;
4036 if (dumpOp >= 0 && dumpOp != opCode) {
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004037 continue;
4038 }
Dianne Hackborn65a4f252018-05-08 17:30:48 -07004039 if (dumpMode >= 0 && dumpMode != op.mode) {
4040 continue;
4041 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004042 if (!printedPackage) {
4043 pw.print(" Package "); pw.print(ops.packageName); pw.println(":");
4044 printedPackage = true;
4045 }
Svet Ganovaf189e32019-02-15 18:45:29 -08004046 pw.print(" "); pw.print(AppOpsManager.opToName(opCode));
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004047 pw.print(" ("); pw.print(AppOpsManager.modeToName(op.mode));
Svet Ganovaf189e32019-02-15 18:45:29 -08004048 final int switchOp = AppOpsManager.opToSwitch(opCode);
4049 if (switchOp != opCode) {
Dianne Hackborn65a4f252018-05-08 17:30:48 -07004050 pw.print(" / switch ");
4051 pw.print(AppOpsManager.opToName(switchOp));
4052 final Op switchObj = ops.get(switchOp);
Svet Ganovaf189e32019-02-15 18:45:29 -08004053 int mode = switchObj != null ? switchObj.mode
4054 : AppOpsManager.opToDefaultMode(switchOp);
Dianne Hackborn65a4f252018-05-08 17:30:48 -07004055 pw.print("="); pw.print(AppOpsManager.modeToName(mode));
4056 }
Dianne Hackborn2378a4a2018-04-26 13:46:22 -07004057 pw.println("): ");
Svet Ganovaf189e32019-02-15 18:45:29 -08004058 dumpStatesLocked(pw, op, now, sdf, date, " ");
4059 if (op.running) {
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07004060 pw.print(" Running start at: ");
4061 TimeUtils.formatDuration(nowElapsed-op.startRealtime, pw);
4062 pw.println();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08004063 }
Dianne Hackborncd1f30b2018-04-23 17:38:09 -07004064 if (op.startNesting != 0) {
4065 pw.print(" startNesting=");
4066 pw.println(op.startNesting);
4067 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -08004068 }
4069 }
4070 }
Svet Ganovee438d42017-01-19 18:04:38 -08004071 if (needSep) {
4072 pw.println();
4073 }
4074
4075 final int userRestrictionCount = mOpUserRestrictions.size();
4076 for (int i = 0; i < userRestrictionCount; i++) {
4077 IBinder token = mOpUserRestrictions.keyAt(i);
4078 ClientRestrictionState restrictionState = mOpUserRestrictions.valueAt(i);
Dianne Hackborn125dc532019-01-09 13:31:48 -08004079 boolean printedTokenHeader = false;
4080
Svet Ganovaf189e32019-02-15 18:45:29 -08004081 if (dumpMode >= 0 || dumpWatchers || dumpHistory) {
Dianne Hackborn125dc532019-01-09 13:31:48 -08004082 continue;
4083 }
Svet Ganovee438d42017-01-19 18:04:38 -08004084
4085 final int restrictionCount = restrictionState.perUserRestrictions != null
4086 ? restrictionState.perUserRestrictions.size() : 0;
Dianne Hackborn125dc532019-01-09 13:31:48 -08004087 if (restrictionCount > 0 && dumpPackage == null) {
4088 boolean printedOpsHeader = false;
Svet Ganovee438d42017-01-19 18:04:38 -08004089 for (int j = 0; j < restrictionCount; j++) {
4090 int userId = restrictionState.perUserRestrictions.keyAt(j);
4091 boolean[] restrictedOps = restrictionState.perUserRestrictions.valueAt(j);
4092 if (restrictedOps == null) {
4093 continue;
4094 }
Dianne Hackborn125dc532019-01-09 13:31:48 -08004095 if (dumpOp >= 0 && (dumpOp >= restrictedOps.length
4096 || !restrictedOps[dumpOp])) {
4097 continue;
4098 }
4099 if (!printedTokenHeader) {
4100 pw.println(" User restrictions for token " + token + ":");
4101 printedTokenHeader = true;
4102 }
4103 if (!printedOpsHeader) {
4104 pw.println(" Restricted ops:");
4105 printedOpsHeader = true;
4106 }
Svet Ganovee438d42017-01-19 18:04:38 -08004107 StringBuilder restrictedOpsValue = new StringBuilder();
4108 restrictedOpsValue.append("[");
4109 final int restrictedOpCount = restrictedOps.length;
4110 for (int k = 0; k < restrictedOpCount; k++) {
4111 if (restrictedOps[k]) {
4112 if (restrictedOpsValue.length() > 1) {
4113 restrictedOpsValue.append(", ");
4114 }
4115 restrictedOpsValue.append(AppOpsManager.opToName(k));
4116 }
4117 }
4118 restrictedOpsValue.append("]");
4119 pw.print(" "); pw.print("user: "); pw.print(userId);
4120 pw.print(" restricted ops: "); pw.println(restrictedOpsValue);
4121 }
4122 }
4123
4124 final int excludedPackageCount = restrictionState.perUserExcludedPackages != null
4125 ? restrictionState.perUserExcludedPackages.size() : 0;
Dianne Hackborn125dc532019-01-09 13:31:48 -08004126 if (excludedPackageCount > 0 && dumpOp < 0) {
4127 boolean printedPackagesHeader = false;
Svet Ganovee438d42017-01-19 18:04:38 -08004128 for (int j = 0; j < excludedPackageCount; j++) {
4129 int userId = restrictionState.perUserExcludedPackages.keyAt(j);
4130 String[] packageNames = restrictionState.perUserExcludedPackages.valueAt(j);
Dianne Hackborn125dc532019-01-09 13:31:48 -08004131 if (packageNames == null) {
4132 continue;
4133 }
4134 boolean hasPackage;
4135 if (dumpPackage != null) {
4136 hasPackage = false;
4137 for (String pkg : packageNames) {
4138 if (dumpPackage.equals(pkg)) {
4139 hasPackage = true;
4140 break;
4141 }
4142 }
4143 } else {
4144 hasPackage = true;
4145 }
4146 if (!hasPackage) {
4147 continue;
4148 }
4149 if (!printedTokenHeader) {
4150 pw.println(" User restrictions for token " + token + ":");
4151 printedTokenHeader = true;
4152 }
4153 if (!printedPackagesHeader) {
4154 pw.println(" Excluded packages:");
4155 printedPackagesHeader = true;
4156 }
Svet Ganovee438d42017-01-19 18:04:38 -08004157 pw.print(" "); pw.print("user: "); pw.print(userId);
4158 pw.print(" packages: "); pw.println(Arrays.toString(packageNames));
4159 }
4160 }
4161 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -08004162 }
Svet Ganov8455ba22019-01-02 13:05:56 -08004163
4164 // Must not hold the appops lock
Svet Ganovaf189e32019-02-15 18:45:29 -08004165 if (dumpHistory && !dumpWatchers) {
4166 mHistoricalRegistry.dump(" ", pw, dumpUid, dumpPackage, dumpOp);
4167 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -08004168 }
John Spurlock1af30c72014-03-10 08:33:35 -04004169
4170 private static final class Restriction {
4171 private static final ArraySet<String> NO_EXCEPTIONS = new ArraySet<String>();
4172 int mode;
4173 ArraySet<String> exceptionPackages = NO_EXCEPTIONS;
4174 }
Jason Monk62062992014-05-06 09:55:28 -04004175
4176 @Override
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004177 public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) {
Jason Monk62062992014-05-06 09:55:28 -04004178 checkSystemUid("setUserRestrictions");
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00004179 Preconditions.checkNotNull(restrictions);
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004180 Preconditions.checkNotNull(token);
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07004181 for (int i = 0; i < AppOpsManager._NUM_OP; i++) {
Jason Monk62062992014-05-06 09:55:28 -04004182 String restriction = AppOpsManager.opToRestriction(i);
Suprabh Shukla64e0dcb2016-05-24 16:23:11 -07004183 if (restriction != null) {
4184 setUserRestrictionNoCheck(i, restrictions.getBoolean(restriction, false), token,
4185 userHandle, null);
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07004186 }
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004187 }
4188 }
4189
4190 @Override
Ruben Brunk29931bc2016-03-11 00:24:26 -08004191 public void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle,
4192 String[] exceptionPackages) {
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004193 if (Binder.getCallingPid() != Process.myPid()) {
4194 mContext.enforcePermission(Manifest.permission.MANAGE_APP_OPS_RESTRICTIONS,
4195 Binder.getCallingPid(), Binder.getCallingUid(), null);
4196 }
4197 if (userHandle != UserHandle.getCallingUserId()) {
4198 if (mContext.checkCallingOrSelfPermission(Manifest.permission
4199 .INTERACT_ACROSS_USERS_FULL) != PackageManager.PERMISSION_GRANTED
4200 && mContext.checkCallingOrSelfPermission(Manifest.permission
4201 .INTERACT_ACROSS_USERS) != PackageManager.PERMISSION_GRANTED) {
4202 throw new SecurityException("Need INTERACT_ACROSS_USERS_FULL or"
4203 + " INTERACT_ACROSS_USERS to interact cross user ");
Jason Monk62062992014-05-06 09:55:28 -04004204 }
4205 }
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004206 verifyIncomingOp(code);
4207 Preconditions.checkNotNull(token);
Ruben Brunk29931bc2016-03-11 00:24:26 -08004208 setUserRestrictionNoCheck(code, restricted, token, userHandle, exceptionPackages);
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004209 }
4210
4211 private void setUserRestrictionNoCheck(int code, boolean restricted, IBinder token,
Ruben Brunk29931bc2016-03-11 00:24:26 -08004212 int userHandle, String[] exceptionPackages) {
Svet Ganov442ed572016-08-17 17:29:43 -07004213 synchronized (AppOpsService.this) {
4214 ClientRestrictionState restrictionState = mOpUserRestrictions.get(token);
4215
4216 if (restrictionState == null) {
4217 try {
4218 restrictionState = new ClientRestrictionState(token);
4219 } catch (RemoteException e) {
4220 return;
4221 }
4222 mOpUserRestrictions.put(token, restrictionState);
Ruben Brunk29931bc2016-03-11 00:24:26 -08004223 }
Svet Ganov442ed572016-08-17 17:29:43 -07004224
4225 if (restrictionState.setRestriction(code, restricted, exceptionPackages, userHandle)) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08004226 mHandler.sendMessage(PooledLambda.obtainMessage(
Svet Ganov3a95f832018-03-23 17:44:30 -07004227 AppOpsService::notifyWatchersOfChange, this, code, UID_ANY));
Svet Ganov442ed572016-08-17 17:29:43 -07004228 }
4229
4230 if (restrictionState.isDefault()) {
4231 mOpUserRestrictions.remove(token);
4232 restrictionState.destroy();
4233 }
Ruben Brunk29931bc2016-03-11 00:24:26 -08004234 }
Julia Reynoldsbb21c252016-04-05 16:01:49 -04004235 }
4236
Svet Ganov3a95f832018-03-23 17:44:30 -07004237 private void notifyWatchersOfChange(int code, int uid) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08004238 final ArraySet<ModeCallback> clonedCallbacks;
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004239 synchronized (this) {
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08004240 ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code);
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004241 if (callbacks == null) {
4242 return;
4243 }
Dianne Hackborn68d76552017-02-27 15:32:03 -08004244 clonedCallbacks = new ArraySet<>(callbacks);
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004245 }
4246
Svet Ganov3a95f832018-03-23 17:44:30 -07004247 notifyOpChanged(clonedCallbacks, code, uid, null);
Jason Monk62062992014-05-06 09:55:28 -04004248 }
4249
4250 @Override
4251 public void removeUser(int userHandle) throws RemoteException {
4252 checkSystemUid("removeUser");
Svet Ganov442ed572016-08-17 17:29:43 -07004253 synchronized (AppOpsService.this) {
4254 final int tokenCount = mOpUserRestrictions.size();
4255 for (int i = tokenCount - 1; i >= 0; i--) {
4256 ClientRestrictionState opRestrictions = mOpUserRestrictions.valueAt(i);
4257 opRestrictions.removeUser(userHandle);
4258 }
Sudheer Shankabc2fadd2016-09-27 17:36:39 -07004259 removeUidsForUserLocked(userHandle);
4260 }
4261 }
4262
Jeff Sharkey35e46d22017-06-09 10:01:20 -06004263 @Override
4264 public boolean isOperationActive(int code, int uid, String packageName) {
Svet Ganovf7b47252018-02-26 11:11:27 -08004265 if (Binder.getCallingUid() != uid) {
4266 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS)
4267 != PackageManager.PERMISSION_GRANTED) {
4268 return false;
4269 }
4270 }
Jeff Sharkey35e46d22017-06-09 10:01:20 -06004271 verifyIncomingOp(code);
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08004272 final String resolvedPackageName = resolvePackageName(uid, packageName);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06004273 if (resolvedPackageName == null) {
4274 return false;
4275 }
Svetoslav Ganov2d20fb42018-02-08 15:52:10 -08004276 synchronized (AppOpsService.this) {
Jeff Sharkey35e46d22017-06-09 10:01:20 -06004277 for (int i = mClients.size() - 1; i >= 0; i--) {
4278 final ClientState client = mClients.valueAt(i);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06004279 for (int j = client.mStartedOps.size() - 1; j >= 0; j--) {
4280 final Op op = client.mStartedOps.get(j);
Svet Ganovaf189e32019-02-15 18:45:29 -08004281 if (op.op == code && op.uidState.uid == uid) return true;
Jeff Sharkey35e46d22017-06-09 10:01:20 -06004282 }
4283 }
4284 }
4285 return false;
4286 }
4287
Svet Ganov8455ba22019-01-02 13:05:56 -08004288 @Override
4289 public void setHistoryParameters(@AppOpsManager.HistoricalMode int mode,
4290 long baseSnapshotInterval, int compressionStep) {
4291 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
4292 "setHistoryParameters");
4293 // Must not hold the appops lock
4294 mHistoricalRegistry.setHistoryParameters(mode, baseSnapshotInterval, compressionStep);
4295 }
4296
4297 @Override
4298 public void offsetHistory(long offsetMillis) {
4299 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
4300 "offsetHistory");
4301 // Must not hold the appops lock
4302 mHistoricalRegistry.offsetHistory(offsetMillis);
4303 }
4304
4305 @Override
4306 public void addHistoricalOps(HistoricalOps ops) {
4307 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
4308 "addHistoricalOps");
4309 // Must not hold the appops lock
4310 mHistoricalRegistry.addHistoricalOps(ops);
4311 }
4312
4313 @Override
4314 public void resetHistoryParameters() {
4315 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
4316 "resetHistoryParameters");
4317 // Must not hold the appops lock
4318 mHistoricalRegistry.resetHistoryParameters();
4319 }
4320
4321 @Override
4322 public void clearHistory() {
4323 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
4324 "clearHistory");
4325 // Must not hold the appops lock
4326 mHistoricalRegistry.clearHistory();
4327 }
4328
Sudheer Shankabc2fadd2016-09-27 17:36:39 -07004329 private void removeUidsForUserLocked(int userHandle) {
4330 for (int i = mUidStates.size() - 1; i >= 0; --i) {
4331 final int uid = mUidStates.keyAt(i);
4332 if (UserHandle.getUserId(uid) == userHandle) {
4333 mUidStates.removeAt(i);
4334 }
Svet Ganov9cea80cd2016-02-16 11:47:00 -08004335 }
4336 }
4337
Jason Monk62062992014-05-06 09:55:28 -04004338 private void checkSystemUid(String function) {
4339 int uid = Binder.getCallingUid();
4340 if (uid != Process.SYSTEM_UID) {
4341 throw new SecurityException(function + " must by called by the system");
4342 }
4343 }
4344
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00004345 private static String resolvePackageName(int uid, String packageName) {
Svet Ganov82f09bc2018-01-12 22:08:40 -08004346 if (uid == Process.ROOT_UID) {
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00004347 return "root";
4348 } else if (uid == Process.SHELL_UID) {
4349 return "com.android.shell";
Svet Ganov82f09bc2018-01-12 22:08:40 -08004350 } else if (uid == Process.MEDIA_UID) {
4351 return "media";
4352 } else if (uid == Process.AUDIOSERVER_UID) {
4353 return "audioserver";
4354 } else if (uid == Process.CAMERASERVER_UID) {
4355 return "cameraserver";
Svetoslav Ganovf73adb62016-03-29 01:07:06 +00004356 } else if (uid == Process.SYSTEM_UID && packageName == null) {
4357 return "android";
4358 }
4359 return packageName;
4360 }
4361
Svet Ganov82f09bc2018-01-12 22:08:40 -08004362 private static int resolveUid(String packageName) {
4363 if (packageName == null) {
4364 return -1;
4365 }
4366 switch (packageName) {
4367 case "root":
4368 return Process.ROOT_UID;
4369 case "shell":
4370 return Process.SHELL_UID;
4371 case "media":
4372 return Process.MEDIA_UID;
4373 case "audioserver":
4374 return Process.AUDIOSERVER_UID;
4375 case "cameraserver":
4376 return Process.CAMERASERVER_UID;
4377 }
4378 return -1;
4379 }
4380
Svet Ganov2af57082015-07-30 08:44:20 -07004381 private static String[] getPackagesForUid(int uid) {
Svet Ganovf3807aa2015-08-02 10:09:56 -07004382 String[] packageNames = null;
Philip P. Moltmann159d98b2018-12-20 08:30:53 -08004383
4384 // Very early during boot the package manager is not yet or not yet fully started. At this
4385 // time there are no packages yet.
4386 if (AppGlobals.getPackageManager() != null) {
4387 try {
4388 packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid);
4389 } catch (RemoteException e) {
4390 /* ignore - local call */
4391 }
Svet Ganov2af57082015-07-30 08:44:20 -07004392 }
Svet Ganovf3807aa2015-08-02 10:09:56 -07004393 if (packageNames == null) {
4394 return EmptyArray.STRING;
4395 }
4396 return packageNames;
Svet Ganov2af57082015-07-30 08:44:20 -07004397 }
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07004398
4399 private final class ClientRestrictionState implements DeathRecipient {
4400 private final IBinder token;
4401 SparseArray<boolean[]> perUserRestrictions;
4402 SparseArray<String[]> perUserExcludedPackages;
4403
4404 public ClientRestrictionState(IBinder token)
4405 throws RemoteException {
4406 token.linkToDeath(this, 0);
4407 this.token = token;
4408 }
4409
4410 public boolean setRestriction(int code, boolean restricted,
4411 String[] excludedPackages, int userId) {
4412 boolean changed = false;
4413
4414 if (perUserRestrictions == null && restricted) {
4415 perUserRestrictions = new SparseArray<>();
4416 }
4417
Philip P. Moltmanne683f192017-06-23 14:05:04 -07004418 int[] users;
4419 if (userId == UserHandle.USER_ALL) {
4420 List<UserInfo> liveUsers = UserManager.get(mContext).getUsers(false);
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07004421
Philip P. Moltmanne683f192017-06-23 14:05:04 -07004422 users = new int[liveUsers.size()];
4423 for (int i = 0; i < liveUsers.size(); i++) {
4424 users[i] = liveUsers.get(i).id;
4425 }
4426 } else {
4427 users = new int[]{userId};
4428 }
4429
4430 if (perUserRestrictions != null) {
4431 int numUsers = users.length;
4432
4433 for (int i = 0; i < numUsers; i++) {
4434 int thisUserId = users[i];
4435
4436 boolean[] userRestrictions = perUserRestrictions.get(thisUserId);
4437 if (userRestrictions == null && restricted) {
4438 userRestrictions = new boolean[AppOpsManager._NUM_OP];
4439 perUserRestrictions.put(thisUserId, userRestrictions);
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07004440 }
Philip P. Moltmanne683f192017-06-23 14:05:04 -07004441 if (userRestrictions != null && userRestrictions[code] != restricted) {
4442 userRestrictions[code] = restricted;
4443 if (!restricted && isDefault(userRestrictions)) {
4444 perUserRestrictions.remove(thisUserId);
4445 userRestrictions = null;
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07004446 }
4447 changed = true;
4448 }
Philip P. Moltmanne683f192017-06-23 14:05:04 -07004449
4450 if (userRestrictions != null) {
4451 final boolean noExcludedPackages = ArrayUtils.isEmpty(excludedPackages);
4452 if (perUserExcludedPackages == null && !noExcludedPackages) {
4453 perUserExcludedPackages = new SparseArray<>();
4454 }
4455 if (perUserExcludedPackages != null && !Arrays.equals(excludedPackages,
4456 perUserExcludedPackages.get(thisUserId))) {
4457 if (noExcludedPackages) {
4458 perUserExcludedPackages.remove(thisUserId);
4459 if (perUserExcludedPackages.size() <= 0) {
4460 perUserExcludedPackages = null;
4461 }
4462 } else {
4463 perUserExcludedPackages.put(thisUserId, excludedPackages);
4464 }
4465 changed = true;
4466 }
4467 }
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07004468 }
4469 }
4470
4471 return changed;
4472 }
4473
4474 public boolean hasRestriction(int restriction, String packageName, int userId) {
4475 if (perUserRestrictions == null) {
4476 return false;
4477 }
4478 boolean[] restrictions = perUserRestrictions.get(userId);
4479 if (restrictions == null) {
4480 return false;
4481 }
4482 if (!restrictions[restriction]) {
4483 return false;
4484 }
4485 if (perUserExcludedPackages == null) {
4486 return true;
4487 }
4488 String[] perUserExclusions = perUserExcludedPackages.get(userId);
4489 if (perUserExclusions == null) {
4490 return true;
4491 }
4492 return !ArrayUtils.contains(perUserExclusions, packageName);
4493 }
4494
4495 public void removeUser(int userId) {
4496 if (perUserExcludedPackages != null) {
4497 perUserExcludedPackages.remove(userId);
4498 if (perUserExcludedPackages.size() <= 0) {
4499 perUserExcludedPackages = null;
4500 }
4501 }
Sudheer Shankabc2fadd2016-09-27 17:36:39 -07004502 if (perUserRestrictions != null) {
4503 perUserRestrictions.remove(userId);
4504 if (perUserRestrictions.size() <= 0) {
4505 perUserRestrictions = null;
4506 }
4507 }
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07004508 }
4509
4510 public boolean isDefault() {
4511 return perUserRestrictions == null || perUserRestrictions.size() <= 0;
4512 }
4513
4514 @Override
4515 public void binderDied() {
4516 synchronized (AppOpsService.this) {
4517 mOpUserRestrictions.remove(token);
4518 if (perUserRestrictions == null) {
4519 return;
4520 }
4521 final int userCount = perUserRestrictions.size();
4522 for (int i = 0; i < userCount; i++) {
4523 final boolean[] restrictions = perUserRestrictions.valueAt(i);
4524 final int restrictionCount = restrictions.length;
4525 for (int j = 0; j < restrictionCount; j++) {
4526 if (restrictions[j]) {
4527 final int changedCode = j;
Svet Ganov3a95f832018-03-23 17:44:30 -07004528 mHandler.post(() -> notifyWatchersOfChange(changedCode, UID_ANY));
Svetoslav Ganova8bbd762016-05-13 17:08:16 -07004529 }
4530 }
4531 }
4532 destroy();
4533 }
4534 }
4535
4536 public void destroy() {
4537 token.unlinkToDeath(this, 0);
4538 }
4539
4540 private boolean isDefault(boolean[] array) {
4541 if (ArrayUtils.isEmpty(array)) {
4542 return true;
4543 }
4544 for (boolean value : array) {
4545 if (value) {
4546 return false;
4547 }
4548 }
4549 return true;
4550 }
4551 }
Dianne Hackbornd5254412018-05-11 18:02:58 -07004552
4553 private final class AppOpsManagerInternalImpl extends AppOpsManagerInternal {
4554 @Override public void setDeviceAndProfileOwners(SparseIntArray owners) {
4555 synchronized (AppOpsService.this) {
4556 mProfileOwners = owners;
4557 }
4558 }
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07004559
4560 @Override
Philip P. Moltmann159d98b2018-12-20 08:30:53 -08004561 public void setUidMode(int code, int uid, int mode) {
4562 AppOpsService.this.setUidMode(code, uid, mode);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07004563 }
Philip P. Moltmanndde07852019-01-25 16:42:36 -08004564
4565 @Override
4566 public void setAllPkgModesToDefault(int code, int uid) {
4567 AppOpsService.this.setAllPkgModesToDefault(code, uid);
4568 }
Philip P. Moltmann724150d2019-03-11 17:01:05 -07004569
4570 @Override
4571 public @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName) {
4572 return AppOpsService.this.checkOperationUnchecked(code, uid, packageName, true, false);
4573 }
Dianne Hackbornd5254412018-05-11 18:02:58 -07004574 }
Dianne Hackborna06de0f2012-12-11 16:34:47 -08004575}