blob: 339101fa79bb6602625c8b1e53dc36ae58e99cde [file] [log] [blame]
Makoto Onuki9be01402017-11-10 13:22:26 -08001/*
2 * Copyright (C) 2017 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 */
16package com.android.server;
17
18import android.annotation.NonNull;
Makoto Onuki9be01402017-11-10 13:22:26 -080019import android.app.ActivityManager;
Makoto Onuki15407842018-01-19 14:23:11 -080020import android.app.ActivityManagerInternal;
Makoto Onuki9be01402017-11-10 13:22:26 -080021import android.app.AppOpsManager;
22import android.app.AppOpsManager.PackageOps;
Makoto Onuki2206af32017-11-21 16:25:35 -080023import android.app.IActivityManager;
Makoto Onuki9be01402017-11-10 13:22:26 -080024import android.app.IUidObserver;
Makoto Onukieb898f12018-01-23 15:26:27 -080025import android.app.usage.UsageStatsManager;
26import android.app.usage.UsageStatsManagerInternal;
27import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
Makoto Onuki2206af32017-11-21 16:25:35 -080028import android.content.BroadcastReceiver;
Makoto Onuki9be01402017-11-10 13:22:26 -080029import android.content.Context;
Makoto Onuki2206af32017-11-21 16:25:35 -080030import android.content.Intent;
31import android.content.IntentFilter;
Suprabh Shukla4deb8522018-01-08 16:27:10 -080032import android.database.ContentObserver;
Nancy Zheng525aaa12018-01-12 11:45:37 -080033import android.net.Uri;
34import android.os.BatteryManager;
Makoto Onuki9be01402017-11-10 13:22:26 -080035import android.os.Handler;
Makoto Onuki2206af32017-11-21 16:25:35 -080036import android.os.Looper;
37import android.os.Message;
Makoto Onuki9be01402017-11-10 13:22:26 -080038import android.os.PowerManager.ServiceType;
39import android.os.PowerManagerInternal;
40import android.os.RemoteException;
41import android.os.ServiceManager;
42import android.os.UserHandle;
Suprabh Shukla4deb8522018-01-08 16:27:10 -080043import android.provider.Settings;
Makoto Onuki9be01402017-11-10 13:22:26 -080044import android.util.ArraySet;
45import android.util.Pair;
Suprabh Shukla4deb8522018-01-08 16:27:10 -080046import android.util.Slog;
Makoto Onuki9be01402017-11-10 13:22:26 -080047import android.util.SparseBooleanArray;
Makoto Onukieb898f12018-01-23 15:26:27 -080048import android.util.SparseSetArray;
Makoto Onuki2206af32017-11-21 16:25:35 -080049import android.util.proto.ProtoOutputStream;
Makoto Onuki9be01402017-11-10 13:22:26 -080050
51import com.android.internal.annotations.GuardedBy;
Makoto Onuki2206af32017-11-21 16:25:35 -080052import com.android.internal.annotations.VisibleForTesting;
Makoto Onuki9be01402017-11-10 13:22:26 -080053import com.android.internal.app.IAppOpsCallback;
54import com.android.internal.app.IAppOpsService;
Makoto Onuki2206af32017-11-21 16:25:35 -080055import com.android.internal.util.ArrayUtils;
Makoto Onuki9be01402017-11-10 13:22:26 -080056import com.android.internal.util.Preconditions;
Makoto Onukiadb50d82018-01-29 16:20:30 -080057import com.android.server.DeviceIdleController.LocalService;
Makoto Onukieb898f12018-01-23 15:26:27 -080058import com.android.server.ForceAppStandbyTrackerProto.ExemptedPackage;
Makoto Onuki2206af32017-11-21 16:25:35 -080059import com.android.server.ForceAppStandbyTrackerProto.RunAnyInBackgroundRestrictedPackages;
Makoto Onuki9be01402017-11-10 13:22:26 -080060
Makoto Onuki2206af32017-11-21 16:25:35 -080061import java.io.PrintWriter;
62import java.util.Arrays;
Makoto Onuki9be01402017-11-10 13:22:26 -080063import java.util.List;
64
65/**
Makoto Onuki2206af32017-11-21 16:25:35 -080066 * Class to keep track of the information related to "force app standby", which includes:
67 * - OP_RUN_ANY_IN_BACKGROUND for each package
Makoto Onukiadb50d82018-01-29 16:20:30 -080068 * - UID foreground/active state
Makoto Onuki2206af32017-11-21 16:25:35 -080069 * - User+system power save whitelist
70 * - Temporary power save whitelist
71 * - Global "force all apps standby" mode enforced by battery saver.
Makoto Onuki9be01402017-11-10 13:22:26 -080072 *
Makoto Onukiadb50d82018-01-29 16:20:30 -080073 * TODO: Make it a LocalService.
Makoto Onuki2206af32017-11-21 16:25:35 -080074 *
75 * Test:
Makoto Onukiadb50d82018-01-29 16:20:30 -080076 atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
Makoto Onuki9be01402017-11-10 13:22:26 -080077 */
78public class ForceAppStandbyTracker {
79 private static final String TAG = "ForceAppStandbyTracker";
Makoto Onukieb898f12018-01-23 15:26:27 -080080 private static final boolean DEBUG = true;
Makoto Onuki9be01402017-11-10 13:22:26 -080081
82 @GuardedBy("ForceAppStandbyTracker.class")
83 private static ForceAppStandbyTracker sInstance;
84
85 private final Object mLock = new Object();
86 private final Context mContext;
87
Makoto Onuki2206af32017-11-21 16:25:35 -080088 @VisibleForTesting
89 static final int TARGET_OP = AppOpsManager.OP_RUN_ANY_IN_BACKGROUND;
90
91 IActivityManager mIActivityManager;
Makoto Onuki9be01402017-11-10 13:22:26 -080092 AppOpsManager mAppOpsManager;
93 IAppOpsService mAppOpsService;
94 PowerManagerInternal mPowerManagerInternal;
Makoto Onukieb898f12018-01-23 15:26:27 -080095 StandbyTracker mStandbyTracker;
96 UsageStatsManagerInternal mUsageStatsManagerInternal;
Makoto Onuki9be01402017-11-10 13:22:26 -080097
Makoto Onuki2206af32017-11-21 16:25:35 -080098 private final MyHandler mHandler;
Makoto Onuki9be01402017-11-10 13:22:26 -080099
Nancy Zheng525aaa12018-01-12 11:45:37 -0800100 @VisibleForTesting
101 FeatureFlagsObserver mFlagsObserver;
102
Makoto Onuki9be01402017-11-10 13:22:26 -0800103 /**
104 * Pair of (uid (not user-id), packageName) with OP_RUN_ANY_IN_BACKGROUND *not* allowed.
105 */
106 @GuardedBy("mLock")
Makoto Onuki2206af32017-11-21 16:25:35 -0800107 final ArraySet<Pair<Integer, String>> mRunAnyRestrictedPackages = new ArraySet<>();
Makoto Onuki9be01402017-11-10 13:22:26 -0800108
Makoto Onukiadb50d82018-01-29 16:20:30 -0800109 /** UIDs that are active. */
110 @GuardedBy("mLock")
111 final SparseBooleanArray mActiveUids = new SparseBooleanArray();
112
113 /** UIDs that are in the foreground. */
Makoto Onuki9be01402017-11-10 13:22:26 -0800114 @GuardedBy("mLock")
115 final SparseBooleanArray mForegroundUids = new SparseBooleanArray();
116
Makoto Onuki71755c92018-01-16 14:15:44 -0800117 /**
118 * System except-idle + user whitelist in the device idle controller.
119 */
Makoto Onuki9be01402017-11-10 13:22:26 -0800120 @GuardedBy("mLock")
Makoto Onuki2206af32017-11-21 16:25:35 -0800121 private int[] mPowerWhitelistedAllAppIds = new int[0];
122
123 @GuardedBy("mLock")
124 private int[] mTempWhitelistedAppIds = mPowerWhitelistedAllAppIds;
125
Makoto Onukieb898f12018-01-23 15:26:27 -0800126 /**
127 * Per-user packages that are in the EXEMPT bucket.
128 */
129 @GuardedBy("mLock")
130 private final SparseSetArray<String> mExemptedPackages = new SparseSetArray<>();
131
Makoto Onuki2206af32017-11-21 16:25:35 -0800132 @GuardedBy("mLock")
Makoto Onuki9be01402017-11-10 13:22:26 -0800133 final ArraySet<Listener> mListeners = new ArraySet<>();
134
135 @GuardedBy("mLock")
136 boolean mStarted;
137
Nancy Zheng525aaa12018-01-12 11:45:37 -0800138 /**
139 * Only used for small battery use-case.
140 */
Makoto Onuki9be01402017-11-10 13:22:26 -0800141 @GuardedBy("mLock")
Nancy Zheng525aaa12018-01-12 11:45:37 -0800142 boolean mIsPluggedIn;
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800143
144 @GuardedBy("mLock")
Nancy Zheng525aaa12018-01-12 11:45:37 -0800145 boolean mBatterySaverEnabled;
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800146
Nancy Zheng525aaa12018-01-12 11:45:37 -0800147 /**
148 * True if the forced app standby is currently enabled
149 */
150 @GuardedBy("mLock")
151 boolean mForceAllAppsStandby;
152
153 /**
154 * True if the forced app standby for small battery devices feature is enabled in settings
155 */
156 @GuardedBy("mLock")
157 boolean mForceAllAppStandbyForSmallBattery;
158
159 /**
160 * True if the forced app standby feature is enabled in settings
161 */
162 @GuardedBy("mLock")
163 boolean mForcedAppStandbyEnabled;
164
Makoto Onukieb898f12018-01-23 15:26:27 -0800165 interface Stats {
Makoto Onukiadb50d82018-01-29 16:20:30 -0800166 int UID_FG_STATE_CHANGED = 0;
167 int UID_ACTIVE_STATE_CHANGED = 1;
168 int RUN_ANY_CHANGED = 2;
169 int ALL_UNWHITELISTED = 3;
170 int ALL_WHITELIST_CHANGED = 4;
171 int TEMP_WHITELIST_CHANGED = 5;
172 int EXEMPT_CHANGED = 6;
173 int FORCE_ALL_CHANGED = 7;
174 int FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 8;
Makoto Onukieb898f12018-01-23 15:26:27 -0800175 }
176
177 private final StatLogger mStatLogger = new StatLogger(new String[] {
Makoto Onukiadb50d82018-01-29 16:20:30 -0800178 "UID_FG_STATE_CHANGED",
179 "UID_ACTIVE_STATE_CHANGED",
Makoto Onukieb898f12018-01-23 15:26:27 -0800180 "RUN_ANY_CHANGED",
181 "ALL_UNWHITELISTED",
182 "ALL_WHITELIST_CHANGED",
183 "TEMP_WHITELIST_CHANGED",
184 "EXEMPT_CHANGED",
185 "FORCE_ALL_CHANGED",
186 "FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED",
187 });
188
Nancy Zheng525aaa12018-01-12 11:45:37 -0800189 @VisibleForTesting
190 class FeatureFlagsObserver extends ContentObserver {
191 FeatureFlagsObserver() {
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800192 super(null);
193 }
194
195 void register() {
196 mContext.getContentResolver().registerContentObserver(
197 Settings.Global.getUriFor(Settings.Global.FORCED_APP_STANDBY_ENABLED),
198 false, this);
Nancy Zheng525aaa12018-01-12 11:45:37 -0800199
200 mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
201 Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED), false, this);
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800202 }
203
204 boolean isForcedAppStandbyEnabled() {
Makoto Onukieb898f12018-01-23 15:26:27 -0800205 return injectGetGlobalSettingInt(Settings.Global.FORCED_APP_STANDBY_ENABLED, 1) == 1;
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800206 }
207
Nancy Zheng525aaa12018-01-12 11:45:37 -0800208 boolean isForcedAppStandbyForSmallBatteryEnabled() {
Makoto Onukieb898f12018-01-23 15:26:27 -0800209 return injectGetGlobalSettingInt(
Nancy Zheng525aaa12018-01-12 11:45:37 -0800210 Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED, 0) == 1;
211 }
212
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800213 @Override
Nancy Zheng525aaa12018-01-12 11:45:37 -0800214 public void onChange(boolean selfChange, Uri uri) {
215 if (Settings.Global.getUriFor(Settings.Global.FORCED_APP_STANDBY_ENABLED).equals(uri)) {
216 final boolean enabled = isForcedAppStandbyEnabled();
217 synchronized (mLock) {
218 if (mForcedAppStandbyEnabled == enabled) {
219 return;
220 }
221 mForcedAppStandbyEnabled = enabled;
222 if (DEBUG) {
223 Slog.d(TAG,"Forced app standby feature flag changed: "
224 + mForcedAppStandbyEnabled);
225 }
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800226 }
Nancy Zheng525aaa12018-01-12 11:45:37 -0800227 mHandler.notifyForcedAppStandbyFeatureFlagChanged();
228 } else if (Settings.Global.getUriFor(
229 Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED).equals(uri)) {
230 final boolean enabled = isForcedAppStandbyForSmallBatteryEnabled();
231 synchronized (mLock) {
232 if (mForceAllAppStandbyForSmallBattery == enabled) {
233 return;
234 }
235 mForceAllAppStandbyForSmallBattery = enabled;
236 if (DEBUG) {
237 Slog.d(TAG, "Forced app standby for small battery feature flag changed: "
238 + mForceAllAppStandbyForSmallBattery);
239 }
240 updateForceAllAppStandbyState();
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800241 }
Nancy Zheng525aaa12018-01-12 11:45:37 -0800242 } else {
243 Slog.w(TAG, "Unexpected feature flag uri encountered: " + uri);
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800244 }
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800245 }
246 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800247
248 public static abstract class Listener {
Makoto Onuki2206af32017-11-21 16:25:35 -0800249 /**
250 * This is called when the OP_RUN_ANY_IN_BACKGROUND appops changed for a package.
251 */
252 private void onRunAnyAppOpsChanged(ForceAppStandbyTracker sender,
253 int uid, @NonNull String packageName) {
254 updateJobsForUidPackage(uid, packageName);
255
Suprabh Shuklac25447d2018-01-19 16:43:35 -0800256 if (!sender.areAlarmsRestricted(uid, packageName, /*allowWhileIdle=*/ false)) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800257 unblockAlarmsForUidPackage(uid, packageName);
Suprabh Shuklac25447d2018-01-19 16:43:35 -0800258 } else if (!sender.areAlarmsRestricted(uid, packageName, /*allowWhileIdle=*/ true)){
259 // we need to deliver the allow-while-idle alarms for this uid, package
260 unblockAllUnrestrictedAlarms();
Makoto Onuki2206af32017-11-21 16:25:35 -0800261 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800262 }
263
Makoto Onuki2206af32017-11-21 16:25:35 -0800264 /**
265 * This is called when the foreground state changed for a UID.
266 */
267 private void onUidForegroundStateChanged(ForceAppStandbyTracker sender, int uid) {
Makoto Onukiadb50d82018-01-29 16:20:30 -0800268 onUidForeground(uid, sender.isUidInForeground(uid));
269 }
270
271 /**
272 * This is called when the active/idle state changed for a UID.
273 */
274 private void onUidActiveStateChanged(ForceAppStandbyTracker sender, int uid) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800275 updateJobsForUid(uid);
276
Makoto Onukiadb50d82018-01-29 16:20:30 -0800277 if (sender.isUidActive(uid)) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800278 unblockAlarmsForUid(uid);
279 }
280 }
281
282 /**
283 * This is called when an app-id(s) is removed from the power save whitelist.
284 */
285 private void onPowerSaveUnwhitelisted(ForceAppStandbyTracker sender) {
286 updateAllJobs();
287 unblockAllUnrestrictedAlarms();
288 }
289
290 /**
291 * This is called when the power save whitelist changes, excluding the
292 * {@link #onPowerSaveUnwhitelisted} case.
293 */
294 private void onPowerSaveWhitelistedChanged(ForceAppStandbyTracker sender) {
295 updateAllJobs();
296 }
297
298 /**
299 * This is called when the temp whitelist changes.
300 */
301 private void onTempPowerSaveWhitelistChanged(ForceAppStandbyTracker sender) {
302
303 // TODO This case happens rather frequently; consider optimizing and update jobs
304 // only for affected app-ids.
305
306 updateAllJobs();
Makoto Onukieb898f12018-01-23 15:26:27 -0800307
308 // Note when an app is just put in the temp whitelist, we do *not* drain pending alarms.
309 }
310
311 /**
312 * This is called when the EXEMPT bucket is updated.
313 */
314 private void onExemptChanged(ForceAppStandbyTracker sender) {
315 // This doesn't happen very often, so just re-evaluate all jobs / alarms.
316 updateAllJobs();
317 unblockAllUnrestrictedAlarms();
Makoto Onuki2206af32017-11-21 16:25:35 -0800318 }
319
320 /**
321 * This is called when the global "force all apps standby" flag changes.
322 */
323 private void onForceAllAppsStandbyChanged(ForceAppStandbyTracker sender) {
324 updateAllJobs();
325
326 if (!sender.isForceAllAppsStandbyEnabled()) {
327 unblockAllUnrestrictedAlarms();
328 }
329 }
330
331 /**
332 * Called when the job restrictions for multiple UIDs might have changed, so the job
333 * scheduler should re-evaluate all restrictions for all jobs.
334 */
335 public void updateAllJobs() {
336 }
337
338 /**
339 * Called when the job restrictions for a UID might have changed, so the job
340 * scheduler should re-evaluate all restrictions for all jobs.
341 */
342 public void updateJobsForUid(int uid) {
343 }
344
345 /**
346 * Called when the job restrictions for a UID - package might have changed, so the job
347 * scheduler should re-evaluate all restrictions for all jobs.
348 */
349 public void updateJobsForUidPackage(int uid, String packageName) {
350 }
351
352 /**
353 * Called when the job restrictions for multiple UIDs might have changed, so the alarm
354 * manager should re-evaluate all restrictions for all blocked jobs.
355 */
356 public void unblockAllUnrestrictedAlarms() {
357 }
358
359 /**
360 * Called when all jobs for a specific UID are unblocked.
361 */
362 public void unblockAlarmsForUid(int uid) {
363 }
364
365 /**
366 * Called when all alarms for a specific UID - package are unblocked.
367 */
368 public void unblockAlarmsForUidPackage(int uid, String packageName) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800369 }
Makoto Onukiadb50d82018-01-29 16:20:30 -0800370
371 /**
372 * Called when a UID comes into the foreground or the background.
373 *
374 * @see #isUidInForeground(int)
375 */
376 public void onUidForeground(int uid, boolean foreground) {
377 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800378 }
379
Makoto Onuki2206af32017-11-21 16:25:35 -0800380 @VisibleForTesting
381 ForceAppStandbyTracker(Context context, Looper looper) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800382 mContext = context;
Makoto Onuki2206af32017-11-21 16:25:35 -0800383 mHandler = new MyHandler(looper);
384 }
385
386 private ForceAppStandbyTracker(Context context) {
387 this(context, FgThread.get().getLooper());
Makoto Onuki9be01402017-11-10 13:22:26 -0800388 }
389
390 /**
391 * Get the singleton instance.
392 */
393 public static synchronized ForceAppStandbyTracker getInstance(Context context) {
394 if (sInstance == null) {
395 sInstance = new ForceAppStandbyTracker(context);
396 }
397 return sInstance;
398 }
399
400 /**
401 * Call it when the system is ready.
402 */
403 public void start() {
404 synchronized (mLock) {
405 if (mStarted) {
406 return;
407 }
408 mStarted = true;
409
Makoto Onuki2206af32017-11-21 16:25:35 -0800410 mIActivityManager = Preconditions.checkNotNull(injectIActivityManager());
411 mAppOpsManager = Preconditions.checkNotNull(injectAppOpsManager());
412 mAppOpsService = Preconditions.checkNotNull(injectIAppOpsService());
413 mPowerManagerInternal = Preconditions.checkNotNull(injectPowerManagerInternal());
Makoto Onukieb898f12018-01-23 15:26:27 -0800414 mUsageStatsManagerInternal = Preconditions.checkNotNull(
415 injectUsageStatsManagerInternal());
416
Nancy Zheng525aaa12018-01-12 11:45:37 -0800417 mFlagsObserver = new FeatureFlagsObserver();
418 mFlagsObserver.register();
419 mForcedAppStandbyEnabled = mFlagsObserver.isForcedAppStandbyEnabled();
420 mForceAllAppStandbyForSmallBattery =
421 mFlagsObserver.isForcedAppStandbyForSmallBatteryEnabled();
Makoto Onukieb898f12018-01-23 15:26:27 -0800422 mStandbyTracker = new StandbyTracker();
423 mUsageStatsManagerInternal.addAppIdleStateChangeListener(mStandbyTracker);
Makoto Onuki9be01402017-11-10 13:22:26 -0800424
425 try {
Makoto Onuki2206af32017-11-21 16:25:35 -0800426 mIActivityManager.registerUidObserver(new UidObserver(),
Makoto Onukiadb50d82018-01-29 16:20:30 -0800427 ActivityManager.UID_OBSERVER_GONE
428 | ActivityManager.UID_OBSERVER_IDLE
429 | ActivityManager.UID_OBSERVER_ACTIVE
430 | ActivityManager.UID_OBSERVER_PROCSTATE,
Makoto Onuki9be01402017-11-10 13:22:26 -0800431 ActivityManager.PROCESS_STATE_UNKNOWN, null);
Makoto Onuki2206af32017-11-21 16:25:35 -0800432 mAppOpsService.startWatchingMode(TARGET_OP, null,
Makoto Onuki9be01402017-11-10 13:22:26 -0800433 new AppOpsWatcher());
434 } catch (RemoteException e) {
435 // shouldn't happen.
436 }
437
Makoto Onuki2206af32017-11-21 16:25:35 -0800438 IntentFilter filter = new IntentFilter();
439 filter.addAction(Intent.ACTION_USER_REMOVED);
Nancy Zheng525aaa12018-01-12 11:45:37 -0800440 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
Makoto Onuki2206af32017-11-21 16:25:35 -0800441 mContext.registerReceiver(new MyReceiver(), filter);
Makoto Onuki9be01402017-11-10 13:22:26 -0800442
443 refreshForcedAppStandbyUidPackagesLocked();
Makoto Onuki2206af32017-11-21 16:25:35 -0800444
445 mPowerManagerInternal.registerLowPowerModeObserver(
446 ServiceType.FORCE_ALL_APPS_STANDBY,
Nancy Zheng525aaa12018-01-12 11:45:37 -0800447 (state) -> {
448 synchronized (mLock) {
449 mBatterySaverEnabled = state.batterySaverEnabled;
450 updateForceAllAppStandbyState();
451 }
452 });
Makoto Onuki2206af32017-11-21 16:25:35 -0800453
Nancy Zheng525aaa12018-01-12 11:45:37 -0800454 mBatterySaverEnabled = mPowerManagerInternal.getLowPowerState(
455 ServiceType.FORCE_ALL_APPS_STANDBY).batterySaverEnabled;
456
457 updateForceAllAppStandbyState();
Makoto Onuki9be01402017-11-10 13:22:26 -0800458 }
459 }
460
Makoto Onuki2206af32017-11-21 16:25:35 -0800461 @VisibleForTesting
462 AppOpsManager injectAppOpsManager() {
463 return mContext.getSystemService(AppOpsManager.class);
464 }
465
466 @VisibleForTesting
467 IAppOpsService injectIAppOpsService() {
468 return IAppOpsService.Stub.asInterface(
469 ServiceManager.getService(Context.APP_OPS_SERVICE));
470 }
471
472 @VisibleForTesting
473 IActivityManager injectIActivityManager() {
474 return ActivityManager.getService();
475 }
476
477 @VisibleForTesting
478 PowerManagerInternal injectPowerManagerInternal() {
479 return LocalServices.getService(PowerManagerInternal.class);
480 }
481
Nancy Zheng525aaa12018-01-12 11:45:37 -0800482 @VisibleForTesting
Makoto Onukieb898f12018-01-23 15:26:27 -0800483 UsageStatsManagerInternal injectUsageStatsManagerInternal() {
484 return LocalServices.getService(UsageStatsManagerInternal.class);
485 }
486
487 @VisibleForTesting
Nancy Zheng525aaa12018-01-12 11:45:37 -0800488 boolean isSmallBatteryDevice() {
489 return ActivityManager.isSmallBatteryDevice();
490 }
491
Makoto Onukieb898f12018-01-23 15:26:27 -0800492 @VisibleForTesting
493 int injectGetGlobalSettingInt(String key, int def) {
494 return Settings.Global.getInt(mContext.getContentResolver(), key, def);
495 }
496
Makoto Onuki9be01402017-11-10 13:22:26 -0800497 /**
Makoto Onuki2206af32017-11-21 16:25:35 -0800498 * Update {@link #mRunAnyRestrictedPackages} with the current app ops state.
Makoto Onuki9be01402017-11-10 13:22:26 -0800499 */
500 private void refreshForcedAppStandbyUidPackagesLocked() {
Makoto Onuki2206af32017-11-21 16:25:35 -0800501 mRunAnyRestrictedPackages.clear();
502 final List<PackageOps> ops = mAppOpsManager.getPackagesForOps(
503 new int[] {TARGET_OP});
Makoto Onuki9be01402017-11-10 13:22:26 -0800504
505 if (ops == null) {
506 return;
507 }
508 final int size = ops.size();
509 for (int i = 0; i < size; i++) {
510 final AppOpsManager.PackageOps pkg = ops.get(i);
511 final List<AppOpsManager.OpEntry> entries = ops.get(i).getOps();
512
513 for (int j = 0; j < entries.size(); j++) {
514 AppOpsManager.OpEntry ent = entries.get(j);
Makoto Onuki2206af32017-11-21 16:25:35 -0800515 if (ent.getOp() != TARGET_OP) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800516 continue;
517 }
518 if (ent.getMode() != AppOpsManager.MODE_ALLOWED) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800519 mRunAnyRestrictedPackages.add(Pair.create(
Makoto Onuki9be01402017-11-10 13:22:26 -0800520 pkg.getUid(), pkg.getPackageName()));
521 }
522 }
523 }
524 }
525
Nancy Zheng525aaa12018-01-12 11:45:37 -0800526 private void updateForceAllAppStandbyState() {
527 synchronized (mLock) {
528 if (mForceAllAppStandbyForSmallBattery && isSmallBatteryDevice()) {
529 toggleForceAllAppsStandbyLocked(!mIsPluggedIn);
530 } else {
531 toggleForceAllAppsStandbyLocked(mBatterySaverEnabled);
532 }
533 }
534 }
535
Makoto Onuki2206af32017-11-21 16:25:35 -0800536 /**
537 * Update {@link #mForceAllAppsStandby} and notifies the listeners.
538 */
Nancy Zheng525aaa12018-01-12 11:45:37 -0800539 private void toggleForceAllAppsStandbyLocked(boolean enable) {
540 if (enable == mForceAllAppsStandby) {
541 return;
Makoto Onuki12391f22018-01-18 21:44:28 +0000542 }
Nancy Zheng525aaa12018-01-12 11:45:37 -0800543 mForceAllAppsStandby = enable;
544
545 mHandler.notifyForceAllAppsStandbyChanged();
Makoto Onuki9be01402017-11-10 13:22:26 -0800546 }
547
548 private int findForcedAppStandbyUidPackageIndexLocked(int uid, @NonNull String packageName) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800549 final int size = mRunAnyRestrictedPackages.size();
550 if (size > 8) {
551 return mRunAnyRestrictedPackages.indexOf(Pair.create(uid, packageName));
552 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800553 for (int i = 0; i < size; i++) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800554 final Pair<Integer, String> pair = mRunAnyRestrictedPackages.valueAt(i);
Makoto Onuki9be01402017-11-10 13:22:26 -0800555
556 if ((pair.first == uid) && packageName.equals(pair.second)) {
557 return i;
558 }
559 }
560 return -1;
561 }
562
563 /**
Makoto Onuki2206af32017-11-21 16:25:35 -0800564 * @return whether a uid package-name pair is in mRunAnyRestrictedPackages.
Makoto Onuki9be01402017-11-10 13:22:26 -0800565 */
Makoto Onuki2206af32017-11-21 16:25:35 -0800566 boolean isRunAnyRestrictedLocked(int uid, @NonNull String packageName) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800567 return findForcedAppStandbyUidPackageIndexLocked(uid, packageName) >= 0;
568 }
569
Makoto Onuki2206af32017-11-21 16:25:35 -0800570 /**
571 * Add to / remove from {@link #mRunAnyRestrictedPackages}.
572 */
573 boolean updateForcedAppStandbyUidPackageLocked(int uid, @NonNull String packageName,
Makoto Onuki9be01402017-11-10 13:22:26 -0800574 boolean restricted) {
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800575 final int index = findForcedAppStandbyUidPackageIndexLocked(uid, packageName);
Makoto Onuki9be01402017-11-10 13:22:26 -0800576 final boolean wasRestricted = index >= 0;
577 if (wasRestricted == restricted) {
578 return false;
579 }
580 if (restricted) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800581 mRunAnyRestrictedPackages.add(Pair.create(uid, packageName));
Makoto Onuki9be01402017-11-10 13:22:26 -0800582 } else {
Makoto Onuki2206af32017-11-21 16:25:35 -0800583 mRunAnyRestrictedPackages.removeAt(index);
Makoto Onuki9be01402017-11-10 13:22:26 -0800584 }
585 return true;
586 }
587
Makoto Onukiadb50d82018-01-29 16:20:30 -0800588 private static boolean addUidToArray(SparseBooleanArray array, int uid) {
589 if (UserHandle.isCore(uid)) {
590 return false;
Makoto Onuki9be01402017-11-10 13:22:26 -0800591 }
Makoto Onukiadb50d82018-01-29 16:20:30 -0800592 if (array.get(uid)) {
593 return false;
594 }
595 array.put(uid, true);
596 return true;
Makoto Onuki9be01402017-11-10 13:22:26 -0800597 }
598
Makoto Onukiadb50d82018-01-29 16:20:30 -0800599 private static boolean removeUidFromArray(SparseBooleanArray array, int uid, boolean remove) {
600 if (UserHandle.isCore(uid)) {
601 return false;
Makoto Onuki9be01402017-11-10 13:22:26 -0800602 }
Makoto Onukiadb50d82018-01-29 16:20:30 -0800603 if (!array.get(uid)) {
604 return false;
605 }
606 if (remove) {
607 array.delete(uid);
608 } else {
609 array.put(uid, false);
610 }
611 return true;
Makoto Onuki9be01402017-11-10 13:22:26 -0800612 }
613
Makoto Onuki2206af32017-11-21 16:25:35 -0800614 private final class UidObserver extends IUidObserver.Stub {
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800615 @Override
616 public void onUidStateChanged(int uid, int procState, long procStateSeq) {
Makoto Onukiadb50d82018-01-29 16:20:30 -0800617 synchronized (mLock) {
618 if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
619 if (removeUidFromArray(mForegroundUids, uid, false)) {
620 mHandler.notifyUidForegroundStateChanged(uid);
621 }
622 } else {
623 if (addUidToArray(mForegroundUids, uid)) {
624 mHandler.notifyUidForegroundStateChanged(uid);
625 }
626 }
627 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800628 }
629
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800630 @Override
631 public void onUidGone(int uid, boolean disabled) {
Makoto Onukiadb50d82018-01-29 16:20:30 -0800632 removeUid(uid, true);
Makoto Onuki9be01402017-11-10 13:22:26 -0800633 }
634
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800635 @Override
636 public void onUidActive(int uid) {
Makoto Onukiadb50d82018-01-29 16:20:30 -0800637 synchronized (mLock) {
638 if (addUidToArray(mActiveUids, uid)) {
639 mHandler.notifyUidActiveStateChanged(uid);
640 }
641 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800642 }
643
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800644 @Override
645 public void onUidIdle(int uid, boolean disabled) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800646 // Just to avoid excessive memcpy, don't remove from the array in this case.
Makoto Onukiadb50d82018-01-29 16:20:30 -0800647 removeUid(uid, false);
648 }
649
650 private void removeUid(int uid, boolean remove) {
651 synchronized (mLock) {
652 if (removeUidFromArray(mActiveUids, uid, remove)) {
653 mHandler.notifyUidActiveStateChanged(uid);
654 }
655 if (removeUidFromArray(mForegroundUids, uid, remove)) {
656 mHandler.notifyUidForegroundStateChanged(uid);
657 }
658 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800659 }
660
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800661 @Override
662 public void onUidCachedChanged(int uid, boolean cached) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800663 }
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800664 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800665
666 private final class AppOpsWatcher extends IAppOpsCallback.Stub {
667 @Override
668 public void opChanged(int op, int uid, String packageName) throws RemoteException {
Makoto Onuki2206af32017-11-21 16:25:35 -0800669 boolean restricted = false;
670 try {
671 restricted = mAppOpsService.checkOperation(TARGET_OP,
672 uid, packageName) != AppOpsManager.MODE_ALLOWED;
673 } catch (RemoteException e) {
674 // Shouldn't happen
675 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800676 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800677 if (updateForcedAppStandbyUidPackageLocked(uid, packageName, restricted)) {
678 mHandler.notifyRunAnyAppOpsChanged(uid, packageName);
679 }
680 }
681 }
682 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800683
Makoto Onuki2206af32017-11-21 16:25:35 -0800684 private final class MyReceiver extends BroadcastReceiver {
685 @Override
686 public void onReceive(Context context, Intent intent) {
687 if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
688 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
689 if (userId > 0) {
690 mHandler.doUserRemoved(userId);
Makoto Onuki9be01402017-11-10 13:22:26 -0800691 }
Nancy Zheng525aaa12018-01-12 11:45:37 -0800692 } else if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
693 synchronized (mLock) {
694 mIsPluggedIn = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0);
695 }
696 updateForceAllAppStandbyState();
Makoto Onuki9be01402017-11-10 13:22:26 -0800697 }
698 }
699 }
700
Makoto Onukieb898f12018-01-23 15:26:27 -0800701 final class StandbyTracker extends AppIdleStateChangeListener {
702 @Override
703 public void onAppIdleStateChanged(String packageName, int userId, boolean idle,
704 int bucket) {
705 if (DEBUG) {
706 Slog.d(TAG,"onAppIdleStateChanged: " + packageName + " u" + userId
707 + (idle ? " idle" : " active") + " " + bucket);
708 }
709 final boolean changed;
710 if (bucket == UsageStatsManager.STANDBY_BUCKET_EXEMPTED) {
711 changed = mExemptedPackages.add(userId, packageName);
712 } else {
713 changed = mExemptedPackages.remove(userId, packageName);
714 }
715 if (changed) {
716 mHandler.notifyExemptChanged();
717 }
718 }
719
720 @Override
721 public void onParoleStateChanged(boolean isParoleOn) {
722 }
723 }
724
Makoto Onuki9be01402017-11-10 13:22:26 -0800725 private Listener[] cloneListeners() {
726 synchronized (mLock) {
727 return mListeners.toArray(new Listener[mListeners.size()]);
728 }
729 }
730
Makoto Onuki2206af32017-11-21 16:25:35 -0800731 private class MyHandler extends Handler {
Makoto Onukiadb50d82018-01-29 16:20:30 -0800732 private static final int MSG_UID_ACTIVE_STATE_CHANGED = 0;
733 private static final int MSG_UID_FG_STATE_CHANGED = 1;
734 private static final int MSG_RUN_ANY_CHANGED = 3;
735 private static final int MSG_ALL_UNWHITELISTED = 4;
736 private static final int MSG_ALL_WHITELIST_CHANGED = 5;
737 private static final int MSG_TEMP_WHITELIST_CHANGED = 6;
738 private static final int MSG_FORCE_ALL_CHANGED = 7;
739 private static final int MSG_USER_REMOVED = 8;
740 private static final int MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 9;
741 private static final int MSG_EXEMPT_CHANGED = 10;
Makoto Onuki9be01402017-11-10 13:22:26 -0800742
Makoto Onuki2206af32017-11-21 16:25:35 -0800743 public MyHandler(Looper looper) {
744 super(looper);
Makoto Onuki9be01402017-11-10 13:22:26 -0800745 }
Makoto Onuki2206af32017-11-21 16:25:35 -0800746
Makoto Onukiadb50d82018-01-29 16:20:30 -0800747 public void notifyUidActiveStateChanged(int uid) {
748 obtainMessage(MSG_UID_ACTIVE_STATE_CHANGED, uid, 0).sendToTarget();
749 }
750
Makoto Onuki2206af32017-11-21 16:25:35 -0800751 public void notifyUidForegroundStateChanged(int uid) {
Makoto Onukiadb50d82018-01-29 16:20:30 -0800752 obtainMessage(MSG_UID_FG_STATE_CHANGED, uid, 0).sendToTarget();
Makoto Onuki2206af32017-11-21 16:25:35 -0800753 }
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800754
Makoto Onuki2206af32017-11-21 16:25:35 -0800755 public void notifyRunAnyAppOpsChanged(int uid, @NonNull String packageName) {
756 obtainMessage(MSG_RUN_ANY_CHANGED, uid, 0, packageName).sendToTarget();
757 }
758
759 public void notifyAllUnwhitelisted() {
Makoto Onukiadb50d82018-01-29 16:20:30 -0800760 removeMessages(MSG_ALL_UNWHITELISTED);
Makoto Onuki2206af32017-11-21 16:25:35 -0800761 obtainMessage(MSG_ALL_UNWHITELISTED).sendToTarget();
762 }
763
764 public void notifyAllWhitelistChanged() {
Makoto Onukiadb50d82018-01-29 16:20:30 -0800765 removeMessages(MSG_ALL_WHITELIST_CHANGED);
Makoto Onuki2206af32017-11-21 16:25:35 -0800766 obtainMessage(MSG_ALL_WHITELIST_CHANGED).sendToTarget();
767 }
768
769 public void notifyTempWhitelistChanged() {
Makoto Onukiadb50d82018-01-29 16:20:30 -0800770 removeMessages(MSG_TEMP_WHITELIST_CHANGED);
Makoto Onuki2206af32017-11-21 16:25:35 -0800771 obtainMessage(MSG_TEMP_WHITELIST_CHANGED).sendToTarget();
772 }
773
774 public void notifyForceAllAppsStandbyChanged() {
Makoto Onukiadb50d82018-01-29 16:20:30 -0800775 removeMessages(MSG_FORCE_ALL_CHANGED);
Makoto Onuki2206af32017-11-21 16:25:35 -0800776 obtainMessage(MSG_FORCE_ALL_CHANGED).sendToTarget();
777 }
778
Nancy Zheng525aaa12018-01-12 11:45:37 -0800779 public void notifyForcedAppStandbyFeatureFlagChanged() {
Makoto Onukiadb50d82018-01-29 16:20:30 -0800780 removeMessages(MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED);
Nancy Zheng525aaa12018-01-12 11:45:37 -0800781 obtainMessage(MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED).sendToTarget();
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800782 }
783
Makoto Onukieb898f12018-01-23 15:26:27 -0800784 public void notifyExemptChanged() {
Makoto Onukiadb50d82018-01-29 16:20:30 -0800785 removeMessages(MSG_EXEMPT_CHANGED);
Makoto Onukieb898f12018-01-23 15:26:27 -0800786 obtainMessage(MSG_EXEMPT_CHANGED).sendToTarget();
787 }
788
Makoto Onuki2206af32017-11-21 16:25:35 -0800789 public void doUserRemoved(int userId) {
790 obtainMessage(MSG_USER_REMOVED, userId, 0).sendToTarget();
791 }
792
793 @Override
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800794 public void handleMessage(Message msg) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800795 switch (msg.what) {
796 case MSG_USER_REMOVED:
797 handleUserRemoved(msg.arg1);
798 return;
799 }
800
801 // Only notify the listeners when started.
802 synchronized (mLock) {
803 if (!mStarted) {
804 return;
805 }
806 }
807 final ForceAppStandbyTracker sender = ForceAppStandbyTracker.this;
808
Makoto Onukieb898f12018-01-23 15:26:27 -0800809 long start = mStatLogger.getTime();
Makoto Onuki2206af32017-11-21 16:25:35 -0800810 switch (msg.what) {
Makoto Onukiadb50d82018-01-29 16:20:30 -0800811 case MSG_UID_ACTIVE_STATE_CHANGED:
812 for (Listener l : cloneListeners()) {
813 l.onUidActiveStateChanged(sender, msg.arg1);
814 }
815 mStatLogger.logDurationStat(Stats.UID_ACTIVE_STATE_CHANGED, start);
816 return;
817
818 case MSG_UID_FG_STATE_CHANGED:
Makoto Onuki2206af32017-11-21 16:25:35 -0800819 for (Listener l : cloneListeners()) {
820 l.onUidForegroundStateChanged(sender, msg.arg1);
821 }
Makoto Onukiadb50d82018-01-29 16:20:30 -0800822 mStatLogger.logDurationStat(Stats.UID_FG_STATE_CHANGED, start);
Makoto Onuki2206af32017-11-21 16:25:35 -0800823 return;
Makoto Onukieb898f12018-01-23 15:26:27 -0800824
Makoto Onuki2206af32017-11-21 16:25:35 -0800825 case MSG_RUN_ANY_CHANGED:
826 for (Listener l : cloneListeners()) {
827 l.onRunAnyAppOpsChanged(sender, msg.arg1, (String) msg.obj);
828 }
Makoto Onukieb898f12018-01-23 15:26:27 -0800829 mStatLogger.logDurationStat(Stats.RUN_ANY_CHANGED, start);
Makoto Onuki2206af32017-11-21 16:25:35 -0800830 return;
Makoto Onukieb898f12018-01-23 15:26:27 -0800831
Makoto Onuki2206af32017-11-21 16:25:35 -0800832 case MSG_ALL_UNWHITELISTED:
833 for (Listener l : cloneListeners()) {
834 l.onPowerSaveUnwhitelisted(sender);
835 }
Makoto Onukieb898f12018-01-23 15:26:27 -0800836 mStatLogger.logDurationStat(Stats.ALL_UNWHITELISTED, start);
Makoto Onuki2206af32017-11-21 16:25:35 -0800837 return;
Makoto Onukieb898f12018-01-23 15:26:27 -0800838
Makoto Onuki2206af32017-11-21 16:25:35 -0800839 case MSG_ALL_WHITELIST_CHANGED:
840 for (Listener l : cloneListeners()) {
841 l.onPowerSaveWhitelistedChanged(sender);
842 }
Makoto Onukieb898f12018-01-23 15:26:27 -0800843 mStatLogger.logDurationStat(Stats.ALL_WHITELIST_CHANGED, start);
Makoto Onuki2206af32017-11-21 16:25:35 -0800844 return;
Makoto Onukieb898f12018-01-23 15:26:27 -0800845
Makoto Onuki2206af32017-11-21 16:25:35 -0800846 case MSG_TEMP_WHITELIST_CHANGED:
847 for (Listener l : cloneListeners()) {
848 l.onTempPowerSaveWhitelistChanged(sender);
849 }
Makoto Onukieb898f12018-01-23 15:26:27 -0800850 mStatLogger.logDurationStat(Stats.TEMP_WHITELIST_CHANGED, start);
Makoto Onuki2206af32017-11-21 16:25:35 -0800851 return;
Makoto Onukieb898f12018-01-23 15:26:27 -0800852
853 case MSG_EXEMPT_CHANGED:
854 for (Listener l : cloneListeners()) {
855 l.onExemptChanged(sender);
856 }
857 mStatLogger.logDurationStat(Stats.EXEMPT_CHANGED, start);
858 return;
859
Makoto Onuki2206af32017-11-21 16:25:35 -0800860 case MSG_FORCE_ALL_CHANGED:
861 for (Listener l : cloneListeners()) {
862 l.onForceAllAppsStandbyChanged(sender);
863 }
Makoto Onukieb898f12018-01-23 15:26:27 -0800864 mStatLogger.logDurationStat(Stats.FORCE_ALL_CHANGED, start);
Makoto Onuki2206af32017-11-21 16:25:35 -0800865 return;
Makoto Onukieb898f12018-01-23 15:26:27 -0800866
Nancy Zheng525aaa12018-01-12 11:45:37 -0800867 case MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED:
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800868 // Feature flag for forced app standby changed.
869 final boolean unblockAlarms;
870 synchronized (mLock) {
871 unblockAlarms = !mForcedAppStandbyEnabled && !mForceAllAppsStandby;
872 }
Suprabh Shuklac25447d2018-01-19 16:43:35 -0800873 for (Listener l : cloneListeners()) {
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800874 l.updateAllJobs();
875 if (unblockAlarms) {
876 l.unblockAllUnrestrictedAlarms();
877 }
878 }
Makoto Onukieb898f12018-01-23 15:26:27 -0800879 mStatLogger.logDurationStat(
880 Stats.FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED, start);
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800881 return;
Makoto Onukieb898f12018-01-23 15:26:27 -0800882
Makoto Onuki2206af32017-11-21 16:25:35 -0800883 case MSG_USER_REMOVED:
884 handleUserRemoved(msg.arg1);
885 return;
886 }
887 }
888 }
889
890 void handleUserRemoved(int removedUserId) {
891 synchronized (mLock) {
892 for (int i = mRunAnyRestrictedPackages.size() - 1; i >= 0; i--) {
893 final Pair<Integer, String> pair = mRunAnyRestrictedPackages.valueAt(i);
894 final int uid = pair.first;
895 final int userId = UserHandle.getUserId(uid);
896
897 if (userId == removedUserId) {
898 mRunAnyRestrictedPackages.removeAt(i);
899 }
900 }
Makoto Onukiadb50d82018-01-29 16:20:30 -0800901 cleanUpArrayForUser(mActiveUids, removedUserId);
902 cleanUpArrayForUser(mForegroundUids, removedUserId);
Makoto Onukieb898f12018-01-23 15:26:27 -0800903 mExemptedPackages.remove(removedUserId);
Makoto Onuki2206af32017-11-21 16:25:35 -0800904 }
905 }
906
Makoto Onukiadb50d82018-01-29 16:20:30 -0800907 private void cleanUpArrayForUser(SparseBooleanArray array, int removedUserId) {
908 for (int i = array.size() - 1; i >= 0; i--) {
909 final int uid = array.keyAt(i);
910 final int userId = UserHandle.getUserId(uid);
911
912 if (userId == removedUserId) {
913 array.removeAt(i);
914 }
915 }
916 }
917
Makoto Onuki2206af32017-11-21 16:25:35 -0800918 /**
919 * Called by device idle controller to update the power save whitelists.
920 */
921 public void setPowerSaveWhitelistAppIds(
922 int[] powerSaveWhitelistAllAppIdArray, int[] tempWhitelistAppIdArray) {
923 synchronized (mLock) {
924 final int[] previousWhitelist = mPowerWhitelistedAllAppIds;
925 final int[] previousTempWhitelist = mTempWhitelistedAppIds;
926
927 mPowerWhitelistedAllAppIds = powerSaveWhitelistAllAppIdArray;
928 mTempWhitelistedAppIds = tempWhitelistAppIdArray;
929
930 if (isAnyAppIdUnwhitelisted(previousWhitelist, mPowerWhitelistedAllAppIds)) {
931 mHandler.notifyAllUnwhitelisted();
932 } else if (!Arrays.equals(previousWhitelist, mPowerWhitelistedAllAppIds)) {
933 mHandler.notifyAllWhitelistChanged();
934 }
935
936 if (!Arrays.equals(previousTempWhitelist, mTempWhitelistedAppIds)) {
937 mHandler.notifyTempWhitelistChanged();
938 }
939
940 }
941 }
942
943 /**
944 * @retunr true if a sorted app-id array {@code prevArray} has at least one element
945 * that's not in a sorted app-id array {@code newArray}.
946 */
947 @VisibleForTesting
948 static boolean isAnyAppIdUnwhitelisted(int[] prevArray, int[] newArray) {
949 int i1 = 0;
950 int i2 = 0;
951 boolean prevFinished;
952 boolean newFinished;
953
954 for (;;) {
955 prevFinished = i1 >= prevArray.length;
956 newFinished = i2 >= newArray.length;
957 if (prevFinished || newFinished) {
958 break;
959 }
960 int a1 = prevArray[i1];
961 int a2 = newArray[i2];
962
963 if (a1 == a2) {
964 i1++;
965 i2++;
966 continue;
967 }
968 if (a1 < a2) {
969 // prevArray has an element that's not in a2.
970 return true;
971 }
972 i2++;
973 }
974 if (prevFinished) {
975 return false;
976 }
977 return newFinished;
Makoto Onuki9be01402017-11-10 13:22:26 -0800978 }
979
980 // Public interface.
981
982 /**
983 * Register a new listener.
984 */
985 public void addListener(@NonNull Listener listener) {
986 synchronized (mLock) {
987 mListeners.add(listener);
988 }
989 }
990
991 /**
Makoto Onuki2206af32017-11-21 16:25:35 -0800992 * @return whether alarms should be restricted for a UID package-name.
Makoto Onuki9be01402017-11-10 13:22:26 -0800993 */
Suprabh Shuklac25447d2018-01-19 16:43:35 -0800994 public boolean areAlarmsRestricted(int uid, @NonNull String packageName,
995 boolean allowWhileIdle) {
Makoto Onukieb8cfd12018-01-19 15:43:16 -0800996 return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ false,
Suprabh Shuklac25447d2018-01-19 16:43:35 -0800997 /* exemptOnBatterySaver =*/ allowWhileIdle);
Makoto Onuki2206af32017-11-21 16:25:35 -0800998 }
999
1000 /**
1001 * @return whether jobs should be restricted for a UID package-name.
1002 */
Makoto Onuki15407842018-01-19 14:23:11 -08001003 public boolean areJobsRestricted(int uid, @NonNull String packageName,
1004 boolean hasForegroundExemption) {
Makoto Onukieb8cfd12018-01-19 15:43:16 -08001005 return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ true,
Makoto Onuki15407842018-01-19 14:23:11 -08001006 hasForegroundExemption);
Makoto Onuki2206af32017-11-21 16:25:35 -08001007 }
1008
1009 /**
1010 * @return whether force-app-standby is effective for a UID package-name.
1011 */
1012 private boolean isRestricted(int uid, @NonNull String packageName,
Makoto Onukieb8cfd12018-01-19 15:43:16 -08001013 boolean useTempWhitelistToo, boolean exemptOnBatterySaver) {
Makoto Onukiadb50d82018-01-29 16:20:30 -08001014 if (isUidActive(uid)) {
Makoto Onuki9be01402017-11-10 13:22:26 -08001015 return false;
1016 }
1017 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -08001018 // Whitelisted?
1019 final int appId = UserHandle.getAppId(uid);
1020 if (ArrayUtils.contains(mPowerWhitelistedAllAppIds, appId)) {
1021 return false;
1022 }
1023 if (useTempWhitelistToo &&
1024 ArrayUtils.contains(mTempWhitelistedAppIds, appId)) {
1025 return false;
1026 }
Makoto Onukieb8cfd12018-01-19 15:43:16 -08001027 if (mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName)) {
Makoto Onuki9be01402017-11-10 13:22:26 -08001028 return true;
1029 }
Makoto Onukieb8cfd12018-01-19 15:43:16 -08001030 if (exemptOnBatterySaver) {
1031 return false;
1032 }
Makoto Onukieb898f12018-01-23 15:26:27 -08001033 final int userId = UserHandle.getUserId(uid);
1034 if (mExemptedPackages.contains(userId, packageName)) {
1035 return false;
1036 }
Makoto Onukieb8cfd12018-01-19 15:43:16 -08001037 return mForceAllAppsStandby;
Makoto Onuki9be01402017-11-10 13:22:26 -08001038 }
1039 }
1040
Makoto Onuki2206af32017-11-21 16:25:35 -08001041 /**
Makoto Onukiadb50d82018-01-29 16:20:30 -08001042 * @return whether a UID is in active or not.
1043 *
1044 * Note this information is based on the UID proc state callback, meaning it's updated
1045 * asynchronously and may subtly be stale. If the fresh data is needed, use
1046 * {@link ActivityManagerInternal#getUidProcessState} instead.
1047 */
1048 public boolean isUidActive(int uid) {
1049 if (UserHandle.isCore(uid)) {
1050 return true;
1051 }
1052 synchronized (mLock) {
1053 return mActiveUids.get(uid);
1054 }
1055 }
1056
1057 /**
Makoto Onuki2206af32017-11-21 16:25:35 -08001058 * @return whether a UID is in the foreground or not.
1059 *
Makoto Onuki15407842018-01-19 14:23:11 -08001060 * Note this information is based on the UID proc state callback, meaning it's updated
1061 * asynchronously and may subtly be stale. If the fresh data is needed, use
1062 * {@link ActivityManagerInternal#getUidProcessState} instead.
Makoto Onuki2206af32017-11-21 16:25:35 -08001063 */
Makoto Onukiadb50d82018-01-29 16:20:30 -08001064 public boolean isUidInForeground(int uid) {
Makoto Onuki9cc471c2018-01-23 12:33:56 -08001065 if (UserHandle.isCore(uid)) {
Makoto Onuki9be01402017-11-10 13:22:26 -08001066 return true;
1067 }
1068 synchronized (mLock) {
1069 return mForegroundUids.get(uid);
1070 }
1071 }
1072
Makoto Onuki2206af32017-11-21 16:25:35 -08001073 /**
1074 * @return whether force all apps standby is enabled or not.
1075 *
Makoto Onuki2206af32017-11-21 16:25:35 -08001076 */
1077 boolean isForceAllAppsStandbyEnabled() {
Makoto Onuki9be01402017-11-10 13:22:26 -08001078 synchronized (mLock) {
1079 return mForceAllAppsStandby;
1080 }
1081 }
1082
Makoto Onuki2206af32017-11-21 16:25:35 -08001083 /**
1084 * @return whether a UID/package has {@code OP_RUN_ANY_IN_BACKGROUND} allowed or not.
1085 *
1086 * Note clients normally shouldn't need to access it. It's only for dumpsys.
1087 */
Makoto Onuki9be01402017-11-10 13:22:26 -08001088 public boolean isRunAnyInBackgroundAppOpsAllowed(int uid, @NonNull String packageName) {
1089 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -08001090 return !isRunAnyRestrictedLocked(uid, packageName);
Makoto Onuki9be01402017-11-10 13:22:26 -08001091 }
1092 }
1093
Makoto Onuki2206af32017-11-21 16:25:35 -08001094 /**
1095 * @return whether a UID is in the user / system defined power-save whitelist or not.
1096 *
1097 * Note clients normally shouldn't need to access it. It's only for dumpsys.
1098 */
1099 public boolean isUidPowerSaveWhitelisted(int uid) {
Makoto Onuki9be01402017-11-10 13:22:26 -08001100 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -08001101 return ArrayUtils.contains(mPowerWhitelistedAllAppIds, UserHandle.getAppId(uid));
Makoto Onuki9be01402017-11-10 13:22:26 -08001102 }
1103 }
1104
Makoto Onuki2206af32017-11-21 16:25:35 -08001105 /**
1106 * @return whether a UID is in the temp power-save whitelist or not.
1107 *
1108 * Note clients normally shouldn't need to access it. It's only for dumpsys.
1109 */
1110 public boolean isUidTempPowerSaveWhitelisted(int uid) {
Makoto Onuki9be01402017-11-10 13:22:26 -08001111 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -08001112 return ArrayUtils.contains(mTempWhitelistedAppIds, UserHandle.getAppId(uid));
1113 }
1114 }
1115
1116 public void dump(PrintWriter pw, String indent) {
1117 synchronized (mLock) {
1118 pw.print(indent);
Suprabh Shukla4deb8522018-01-08 16:27:10 -08001119 pw.println("Forced App Standby Feature enabled: " + mForcedAppStandbyEnabled);
1120
1121 pw.print(indent);
Makoto Onuki2206af32017-11-21 16:25:35 -08001122 pw.print("Force all apps standby: ");
1123 pw.println(isForceAllAppsStandbyEnabled());
1124
1125 pw.print(indent);
Nancy Zheng525aaa12018-01-12 11:45:37 -08001126 pw.print("Small Battery Device: ");
1127 pw.println(isSmallBatteryDevice());
1128
1129 pw.print(indent);
1130 pw.print("Force all apps standby for small battery device: ");
1131 pw.println(mForceAllAppStandbyForSmallBattery);
1132
1133 pw.print(indent);
1134 pw.print("Plugged In: ");
1135 pw.println(mIsPluggedIn);
1136
1137 pw.print(indent);
Makoto Onukiadb50d82018-01-29 16:20:30 -08001138 pw.print("Active uids: ");
1139 dumpUids(pw, mActiveUids);
Makoto Onuki2206af32017-11-21 16:25:35 -08001140
Makoto Onukiadb50d82018-01-29 16:20:30 -08001141 pw.print(indent);
1142 pw.print("Foreground uids: ");
1143 dumpUids(pw, mForegroundUids);
Makoto Onuki2206af32017-11-21 16:25:35 -08001144
1145 pw.print(indent);
1146 pw.print("Whitelist appids: ");
1147 pw.println(Arrays.toString(mPowerWhitelistedAllAppIds));
1148
1149 pw.print(indent);
1150 pw.print("Temp whitelist appids: ");
1151 pw.println(Arrays.toString(mTempWhitelistedAppIds));
1152
1153 pw.print(indent);
Makoto Onukieb898f12018-01-23 15:26:27 -08001154 pw.println("Exempted packages:");
1155 for (int i = 0; i < mExemptedPackages.size(); i++) {
1156 pw.print(indent);
1157 pw.print(" User ");
1158 pw.print(mExemptedPackages.keyAt(i));
1159 pw.println();
1160
1161 for (int j = 0; j < mExemptedPackages.sizeAt(i); j++) {
1162 pw.print(indent);
1163 pw.print(" ");
1164 pw.print(mExemptedPackages.valueAt(i, j));
1165 pw.println();
1166 }
1167 }
1168 pw.println();
1169
1170 pw.print(indent);
Makoto Onuki2206af32017-11-21 16:25:35 -08001171 pw.println("Restricted packages:");
1172 for (Pair<Integer, String> uidAndPackage : mRunAnyRestrictedPackages) {
1173 pw.print(indent);
1174 pw.print(" ");
1175 pw.print(UserHandle.formatUid(uidAndPackage.first));
1176 pw.print(" ");
1177 pw.print(uidAndPackage.second);
1178 pw.println();
1179 }
Makoto Onukieb898f12018-01-23 15:26:27 -08001180
1181 mStatLogger.dump(pw, indent);
Makoto Onuki2206af32017-11-21 16:25:35 -08001182 }
1183 }
1184
Makoto Onukiadb50d82018-01-29 16:20:30 -08001185 private void dumpUids(PrintWriter pw, SparseBooleanArray array) {
1186 pw.print("[");
1187
1188 String sep = "";
1189 for (int i = 0; i < array.size(); i++) {
1190 if (array.valueAt(i)) {
1191 pw.print(sep);
1192 pw.print(UserHandle.formatUid(array.keyAt(i)));
1193 sep = " ";
1194 }
1195 }
1196 pw.println("]");
1197 }
1198
Makoto Onuki2206af32017-11-21 16:25:35 -08001199 public void dumpProto(ProtoOutputStream proto, long fieldId) {
1200 synchronized (mLock) {
1201 final long token = proto.start(fieldId);
1202
1203 proto.write(ForceAppStandbyTrackerProto.FORCE_ALL_APPS_STANDBY, mForceAllAppsStandby);
Nancy Zheng525aaa12018-01-12 11:45:37 -08001204 proto.write(ForceAppStandbyTrackerProto.IS_SMALL_BATTERY_DEVICE,
1205 isSmallBatteryDevice());
1206 proto.write(ForceAppStandbyTrackerProto.FORCE_ALL_APPS_STANDBY_FOR_SMALL_BATTERY,
1207 mForceAllAppStandbyForSmallBattery);
Makoto Onukieb898f12018-01-23 15:26:27 -08001208 proto.write(ForceAppStandbyTrackerProto.IS_PLUGGED_IN, mIsPluggedIn);
Makoto Onuki2206af32017-11-21 16:25:35 -08001209
Makoto Onukiadb50d82018-01-29 16:20:30 -08001210 for (int i = 0; i < mActiveUids.size(); i++) {
1211 if (mActiveUids.valueAt(i)) {
1212 proto.write(ForceAppStandbyTrackerProto.ACTIVE_UIDS,
1213 mActiveUids.keyAt(i));
1214 }
1215 }
1216
Makoto Onuki2206af32017-11-21 16:25:35 -08001217 for (int i = 0; i < mForegroundUids.size(); i++) {
1218 if (mForegroundUids.valueAt(i)) {
1219 proto.write(ForceAppStandbyTrackerProto.FOREGROUND_UIDS,
1220 mForegroundUids.keyAt(i));
1221 }
1222 }
1223
1224 for (int appId : mPowerWhitelistedAllAppIds) {
1225 proto.write(ForceAppStandbyTrackerProto.POWER_SAVE_WHITELIST_APP_IDS, appId);
1226 }
1227
1228 for (int appId : mTempWhitelistedAppIds) {
1229 proto.write(ForceAppStandbyTrackerProto.TEMP_POWER_SAVE_WHITELIST_APP_IDS, appId);
1230 }
1231
Makoto Onukieb898f12018-01-23 15:26:27 -08001232 for (int i = 0; i < mExemptedPackages.size(); i++) {
1233 for (int j = 0; j < mExemptedPackages.sizeAt(i); j++) {
1234 final long token2 = proto.start(
1235 ForceAppStandbyTrackerProto.EXEMPTED_PACKAGES);
1236
1237 proto.write(ExemptedPackage.USER_ID, mExemptedPackages.keyAt(i));
1238 proto.write(ExemptedPackage.PACKAGE_NAME, mExemptedPackages.valueAt(i, j));
1239
1240 proto.end(token2);
1241 }
1242 }
1243
Makoto Onuki2206af32017-11-21 16:25:35 -08001244 for (Pair<Integer, String> uidAndPackage : mRunAnyRestrictedPackages) {
1245 final long token2 = proto.start(
1246 ForceAppStandbyTrackerProto.RUN_ANY_IN_BACKGROUND_RESTRICTED_PACKAGES);
1247 proto.write(RunAnyInBackgroundRestrictedPackages.UID, uidAndPackage.first);
1248 proto.write(RunAnyInBackgroundRestrictedPackages.PACKAGE_NAME,
1249 uidAndPackage.second);
1250 proto.end(token2);
1251 }
Makoto Onukieb898f12018-01-23 15:26:27 -08001252
1253 mStatLogger.dumpProto(proto, ForceAppStandbyTrackerProto.STATS);
1254
Makoto Onuki2206af32017-11-21 16:25:35 -08001255 proto.end(token);
Makoto Onuki9be01402017-11-10 13:22:26 -08001256 }
1257 }
1258}