blob: d01685564223ab621dc0bba12b4a8c58059882ca [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 Onuki2206af32017-11-21 16:25:35 -080025import android.content.BroadcastReceiver;
Makoto Onuki9be01402017-11-10 13:22:26 -080026import android.content.Context;
Makoto Onuki2206af32017-11-21 16:25:35 -080027import android.content.Intent;
28import android.content.IntentFilter;
Suprabh Shukla4deb8522018-01-08 16:27:10 -080029import android.database.ContentObserver;
Nancy Zheng525aaa12018-01-12 11:45:37 -080030import android.net.Uri;
31import android.os.BatteryManager;
Makoto Onuki9be01402017-11-10 13:22:26 -080032import android.os.Handler;
Makoto Onuki2206af32017-11-21 16:25:35 -080033import android.os.Looper;
34import android.os.Message;
Makoto Onuki9be01402017-11-10 13:22:26 -080035import android.os.PowerManager.ServiceType;
36import android.os.PowerManagerInternal;
37import android.os.RemoteException;
38import android.os.ServiceManager;
39import android.os.UserHandle;
Suprabh Shukla4deb8522018-01-08 16:27:10 -080040import android.provider.Settings;
Makoto Onuki9be01402017-11-10 13:22:26 -080041import android.util.ArraySet;
42import android.util.Pair;
Suprabh Shukla4deb8522018-01-08 16:27:10 -080043import android.util.Slog;
Makoto Onuki9be01402017-11-10 13:22:26 -080044import android.util.SparseBooleanArray;
Makoto Onuki2206af32017-11-21 16:25:35 -080045import android.util.proto.ProtoOutputStream;
Makoto Onuki9be01402017-11-10 13:22:26 -080046
47import com.android.internal.annotations.GuardedBy;
Makoto Onuki2206af32017-11-21 16:25:35 -080048import com.android.internal.annotations.VisibleForTesting;
Makoto Onuki9be01402017-11-10 13:22:26 -080049import com.android.internal.app.IAppOpsCallback;
50import com.android.internal.app.IAppOpsService;
Makoto Onuki2206af32017-11-21 16:25:35 -080051import com.android.internal.util.ArrayUtils;
Makoto Onuki9be01402017-11-10 13:22:26 -080052import com.android.internal.util.Preconditions;
Makoto Onuki2206af32017-11-21 16:25:35 -080053import com.android.server.ForceAppStandbyTrackerProto.RunAnyInBackgroundRestrictedPackages;
Makoto Onuki9be01402017-11-10 13:22:26 -080054
Makoto Onuki2206af32017-11-21 16:25:35 -080055import java.io.PrintWriter;
56import java.util.Arrays;
Makoto Onuki9be01402017-11-10 13:22:26 -080057import java.util.List;
58
59/**
Makoto Onuki2206af32017-11-21 16:25:35 -080060 * Class to keep track of the information related to "force app standby", which includes:
61 * - OP_RUN_ANY_IN_BACKGROUND for each package
62 * - UID foreground state
63 * - User+system power save whitelist
64 * - Temporary power save whitelist
65 * - Global "force all apps standby" mode enforced by battery saver.
Makoto Onuki9be01402017-11-10 13:22:26 -080066 *
Makoto Onuki2206af32017-11-21 16:25:35 -080067 * TODO: In general, we can reduce the number of callbacks by checking all signals before sending
Suprabh Shukla4deb8522018-01-08 16:27:10 -080068 * each callback. For example, even when an UID comes into the foreground, if it wasn't
69 * originally restricted, then there's no need to send an event.
70 * Doing this would be error-prone, so we punt it for now, but we should revisit it later.
Makoto Onuki2206af32017-11-21 16:25:35 -080071 *
72 * Test:
Suprabh Shukla4deb8522018-01-08 16:27:10 -080073 * atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
Makoto Onuki9be01402017-11-10 13:22:26 -080074 */
75public class ForceAppStandbyTracker {
76 private static final String TAG = "ForceAppStandbyTracker";
Suprabh Shukla4deb8522018-01-08 16:27:10 -080077 private static final boolean DEBUG = false;
Makoto Onuki9be01402017-11-10 13:22:26 -080078
79 @GuardedBy("ForceAppStandbyTracker.class")
80 private static ForceAppStandbyTracker sInstance;
81
82 private final Object mLock = new Object();
83 private final Context mContext;
84
Makoto Onuki2206af32017-11-21 16:25:35 -080085 @VisibleForTesting
86 static final int TARGET_OP = AppOpsManager.OP_RUN_ANY_IN_BACKGROUND;
87
88 IActivityManager mIActivityManager;
Makoto Onuki9be01402017-11-10 13:22:26 -080089 AppOpsManager mAppOpsManager;
90 IAppOpsService mAppOpsService;
91 PowerManagerInternal mPowerManagerInternal;
92
Makoto Onuki2206af32017-11-21 16:25:35 -080093 private final MyHandler mHandler;
Makoto Onuki9be01402017-11-10 13:22:26 -080094
Nancy Zheng525aaa12018-01-12 11:45:37 -080095 @VisibleForTesting
96 FeatureFlagsObserver mFlagsObserver;
97
Makoto Onuki9be01402017-11-10 13:22:26 -080098 /**
99 * Pair of (uid (not user-id), packageName) with OP_RUN_ANY_IN_BACKGROUND *not* allowed.
100 */
101 @GuardedBy("mLock")
Makoto Onuki2206af32017-11-21 16:25:35 -0800102 final ArraySet<Pair<Integer, String>> mRunAnyRestrictedPackages = new ArraySet<>();
Makoto Onuki9be01402017-11-10 13:22:26 -0800103
104 @GuardedBy("mLock")
105 final SparseBooleanArray mForegroundUids = new SparseBooleanArray();
106
Makoto Onuki71755c92018-01-16 14:15:44 -0800107 /**
108 * System except-idle + user whitelist in the device idle controller.
109 */
Makoto Onuki9be01402017-11-10 13:22:26 -0800110 @GuardedBy("mLock")
Makoto Onuki2206af32017-11-21 16:25:35 -0800111 private int[] mPowerWhitelistedAllAppIds = new int[0];
112
113 @GuardedBy("mLock")
114 private int[] mTempWhitelistedAppIds = mPowerWhitelistedAllAppIds;
115
116 @GuardedBy("mLock")
Makoto Onuki9be01402017-11-10 13:22:26 -0800117 final ArraySet<Listener> mListeners = new ArraySet<>();
118
119 @GuardedBy("mLock")
120 boolean mStarted;
121
Nancy Zheng525aaa12018-01-12 11:45:37 -0800122 /**
123 * Only used for small battery use-case.
124 */
Makoto Onuki9be01402017-11-10 13:22:26 -0800125 @GuardedBy("mLock")
Nancy Zheng525aaa12018-01-12 11:45:37 -0800126 boolean mIsPluggedIn;
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800127
128 @GuardedBy("mLock")
Nancy Zheng525aaa12018-01-12 11:45:37 -0800129 boolean mBatterySaverEnabled;
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800130
Nancy Zheng525aaa12018-01-12 11:45:37 -0800131 /**
132 * True if the forced app standby is currently enabled
133 */
134 @GuardedBy("mLock")
135 boolean mForceAllAppsStandby;
136
137 /**
138 * True if the forced app standby for small battery devices feature is enabled in settings
139 */
140 @GuardedBy("mLock")
141 boolean mForceAllAppStandbyForSmallBattery;
142
143 /**
144 * True if the forced app standby feature is enabled in settings
145 */
146 @GuardedBy("mLock")
147 boolean mForcedAppStandbyEnabled;
148
149 @VisibleForTesting
150 class FeatureFlagsObserver extends ContentObserver {
151 FeatureFlagsObserver() {
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800152 super(null);
153 }
154
155 void register() {
156 mContext.getContentResolver().registerContentObserver(
157 Settings.Global.getUriFor(Settings.Global.FORCED_APP_STANDBY_ENABLED),
158 false, this);
Nancy Zheng525aaa12018-01-12 11:45:37 -0800159
160 mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
161 Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED), false, this);
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800162 }
163
164 boolean isForcedAppStandbyEnabled() {
165 return Settings.Global.getInt(mContext.getContentResolver(),
166 Settings.Global.FORCED_APP_STANDBY_ENABLED, 1) == 1;
167 }
168
Nancy Zheng525aaa12018-01-12 11:45:37 -0800169 boolean isForcedAppStandbyForSmallBatteryEnabled() {
170 return Settings.Global.getInt(mContext.getContentResolver(),
171 Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED, 0) == 1;
172 }
173
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800174 @Override
Nancy Zheng525aaa12018-01-12 11:45:37 -0800175 public void onChange(boolean selfChange, Uri uri) {
176 if (Settings.Global.getUriFor(Settings.Global.FORCED_APP_STANDBY_ENABLED).equals(uri)) {
177 final boolean enabled = isForcedAppStandbyEnabled();
178 synchronized (mLock) {
179 if (mForcedAppStandbyEnabled == enabled) {
180 return;
181 }
182 mForcedAppStandbyEnabled = enabled;
183 if (DEBUG) {
184 Slog.d(TAG,"Forced app standby feature flag changed: "
185 + mForcedAppStandbyEnabled);
186 }
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800187 }
Nancy Zheng525aaa12018-01-12 11:45:37 -0800188 mHandler.notifyForcedAppStandbyFeatureFlagChanged();
189 } else if (Settings.Global.getUriFor(
190 Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED).equals(uri)) {
191 final boolean enabled = isForcedAppStandbyForSmallBatteryEnabled();
192 synchronized (mLock) {
193 if (mForceAllAppStandbyForSmallBattery == enabled) {
194 return;
195 }
196 mForceAllAppStandbyForSmallBattery = enabled;
197 if (DEBUG) {
198 Slog.d(TAG, "Forced app standby for small battery feature flag changed: "
199 + mForceAllAppStandbyForSmallBattery);
200 }
201 updateForceAllAppStandbyState();
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800202 }
Nancy Zheng525aaa12018-01-12 11:45:37 -0800203 } else {
204 Slog.w(TAG, "Unexpected feature flag uri encountered: " + uri);
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800205 }
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800206 }
207 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800208
209 public static abstract class Listener {
Makoto Onuki2206af32017-11-21 16:25:35 -0800210 /**
211 * This is called when the OP_RUN_ANY_IN_BACKGROUND appops changed for a package.
212 */
213 private void onRunAnyAppOpsChanged(ForceAppStandbyTracker sender,
214 int uid, @NonNull String packageName) {
215 updateJobsForUidPackage(uid, packageName);
216
217 if (!sender.areAlarmsRestricted(uid, packageName)) {
218 unblockAlarmsForUidPackage(uid, packageName);
219 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800220 }
221
Makoto Onuki2206af32017-11-21 16:25:35 -0800222 /**
223 * This is called when the foreground state changed for a UID.
224 */
225 private void onUidForegroundStateChanged(ForceAppStandbyTracker sender, int uid) {
226 updateJobsForUid(uid);
227
228 if (sender.isInForeground(uid)) {
229 unblockAlarmsForUid(uid);
230 }
231 }
232
233 /**
234 * This is called when an app-id(s) is removed from the power save whitelist.
235 */
236 private void onPowerSaveUnwhitelisted(ForceAppStandbyTracker sender) {
237 updateAllJobs();
238 unblockAllUnrestrictedAlarms();
239 }
240
241 /**
242 * This is called when the power save whitelist changes, excluding the
243 * {@link #onPowerSaveUnwhitelisted} case.
244 */
245 private void onPowerSaveWhitelistedChanged(ForceAppStandbyTracker sender) {
246 updateAllJobs();
247 }
248
249 /**
250 * This is called when the temp whitelist changes.
251 */
252 private void onTempPowerSaveWhitelistChanged(ForceAppStandbyTracker sender) {
253
254 // TODO This case happens rather frequently; consider optimizing and update jobs
255 // only for affected app-ids.
256
257 updateAllJobs();
258 }
259
260 /**
261 * This is called when the global "force all apps standby" flag changes.
262 */
263 private void onForceAllAppsStandbyChanged(ForceAppStandbyTracker sender) {
264 updateAllJobs();
265
266 if (!sender.isForceAllAppsStandbyEnabled()) {
267 unblockAllUnrestrictedAlarms();
268 }
269 }
270
271 /**
272 * Called when the job restrictions for multiple UIDs might have changed, so the job
273 * scheduler should re-evaluate all restrictions for all jobs.
274 */
275 public void updateAllJobs() {
276 }
277
278 /**
279 * Called when the job restrictions for a UID might have changed, so the job
280 * scheduler should re-evaluate all restrictions for all jobs.
281 */
282 public void updateJobsForUid(int uid) {
283 }
284
285 /**
286 * Called when the job restrictions for a UID - package might have changed, so the job
287 * scheduler should re-evaluate all restrictions for all jobs.
288 */
289 public void updateJobsForUidPackage(int uid, String packageName) {
290 }
291
292 /**
293 * Called when the job restrictions for multiple UIDs might have changed, so the alarm
294 * manager should re-evaluate all restrictions for all blocked jobs.
295 */
296 public void unblockAllUnrestrictedAlarms() {
297 }
298
299 /**
300 * Called when all jobs for a specific UID are unblocked.
301 */
302 public void unblockAlarmsForUid(int uid) {
303 }
304
305 /**
306 * Called when all alarms for a specific UID - package are unblocked.
307 */
308 public void unblockAlarmsForUidPackage(int uid, String packageName) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800309 }
310 }
311
Makoto Onuki2206af32017-11-21 16:25:35 -0800312 @VisibleForTesting
313 ForceAppStandbyTracker(Context context, Looper looper) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800314 mContext = context;
Makoto Onuki2206af32017-11-21 16:25:35 -0800315 mHandler = new MyHandler(looper);
316 }
317
318 private ForceAppStandbyTracker(Context context) {
319 this(context, FgThread.get().getLooper());
Makoto Onuki9be01402017-11-10 13:22:26 -0800320 }
321
322 /**
323 * Get the singleton instance.
324 */
325 public static synchronized ForceAppStandbyTracker getInstance(Context context) {
326 if (sInstance == null) {
327 sInstance = new ForceAppStandbyTracker(context);
328 }
329 return sInstance;
330 }
331
332 /**
333 * Call it when the system is ready.
334 */
335 public void start() {
336 synchronized (mLock) {
337 if (mStarted) {
338 return;
339 }
340 mStarted = true;
341
Makoto Onuki2206af32017-11-21 16:25:35 -0800342 mIActivityManager = Preconditions.checkNotNull(injectIActivityManager());
343 mAppOpsManager = Preconditions.checkNotNull(injectAppOpsManager());
344 mAppOpsService = Preconditions.checkNotNull(injectIAppOpsService());
345 mPowerManagerInternal = Preconditions.checkNotNull(injectPowerManagerInternal());
Nancy Zheng525aaa12018-01-12 11:45:37 -0800346 mFlagsObserver = new FeatureFlagsObserver();
347 mFlagsObserver.register();
348 mForcedAppStandbyEnabled = mFlagsObserver.isForcedAppStandbyEnabled();
349 mForceAllAppStandbyForSmallBattery =
350 mFlagsObserver.isForcedAppStandbyForSmallBatteryEnabled();
Makoto Onuki9be01402017-11-10 13:22:26 -0800351
352 try {
Makoto Onuki2206af32017-11-21 16:25:35 -0800353 mIActivityManager.registerUidObserver(new UidObserver(),
Makoto Onuki9be01402017-11-10 13:22:26 -0800354 ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE
355 | ActivityManager.UID_OBSERVER_ACTIVE,
356 ActivityManager.PROCESS_STATE_UNKNOWN, null);
Makoto Onuki2206af32017-11-21 16:25:35 -0800357 mAppOpsService.startWatchingMode(TARGET_OP, null,
Makoto Onuki9be01402017-11-10 13:22:26 -0800358 new AppOpsWatcher());
359 } catch (RemoteException e) {
360 // shouldn't happen.
361 }
362
Makoto Onuki2206af32017-11-21 16:25:35 -0800363 IntentFilter filter = new IntentFilter();
364 filter.addAction(Intent.ACTION_USER_REMOVED);
Nancy Zheng525aaa12018-01-12 11:45:37 -0800365 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
Makoto Onuki2206af32017-11-21 16:25:35 -0800366 mContext.registerReceiver(new MyReceiver(), filter);
Makoto Onuki9be01402017-11-10 13:22:26 -0800367
368 refreshForcedAppStandbyUidPackagesLocked();
Makoto Onuki2206af32017-11-21 16:25:35 -0800369
370 mPowerManagerInternal.registerLowPowerModeObserver(
371 ServiceType.FORCE_ALL_APPS_STANDBY,
Nancy Zheng525aaa12018-01-12 11:45:37 -0800372 (state) -> {
373 synchronized (mLock) {
374 mBatterySaverEnabled = state.batterySaverEnabled;
375 updateForceAllAppStandbyState();
376 }
377 });
Makoto Onuki2206af32017-11-21 16:25:35 -0800378
Nancy Zheng525aaa12018-01-12 11:45:37 -0800379 mBatterySaverEnabled = mPowerManagerInternal.getLowPowerState(
380 ServiceType.FORCE_ALL_APPS_STANDBY).batterySaverEnabled;
381
382 updateForceAllAppStandbyState();
Makoto Onuki9be01402017-11-10 13:22:26 -0800383 }
384 }
385
Makoto Onuki2206af32017-11-21 16:25:35 -0800386 @VisibleForTesting
387 AppOpsManager injectAppOpsManager() {
388 return mContext.getSystemService(AppOpsManager.class);
389 }
390
391 @VisibleForTesting
392 IAppOpsService injectIAppOpsService() {
393 return IAppOpsService.Stub.asInterface(
394 ServiceManager.getService(Context.APP_OPS_SERVICE));
395 }
396
397 @VisibleForTesting
398 IActivityManager injectIActivityManager() {
399 return ActivityManager.getService();
400 }
401
402 @VisibleForTesting
403 PowerManagerInternal injectPowerManagerInternal() {
404 return LocalServices.getService(PowerManagerInternal.class);
405 }
406
Nancy Zheng525aaa12018-01-12 11:45:37 -0800407 @VisibleForTesting
408 boolean isSmallBatteryDevice() {
409 return ActivityManager.isSmallBatteryDevice();
410 }
411
Makoto Onuki9be01402017-11-10 13:22:26 -0800412 /**
Makoto Onuki2206af32017-11-21 16:25:35 -0800413 * Update {@link #mRunAnyRestrictedPackages} with the current app ops state.
Makoto Onuki9be01402017-11-10 13:22:26 -0800414 */
415 private void refreshForcedAppStandbyUidPackagesLocked() {
Makoto Onuki2206af32017-11-21 16:25:35 -0800416 mRunAnyRestrictedPackages.clear();
417 final List<PackageOps> ops = mAppOpsManager.getPackagesForOps(
418 new int[] {TARGET_OP});
Makoto Onuki9be01402017-11-10 13:22:26 -0800419
420 if (ops == null) {
421 return;
422 }
423 final int size = ops.size();
424 for (int i = 0; i < size; i++) {
425 final AppOpsManager.PackageOps pkg = ops.get(i);
426 final List<AppOpsManager.OpEntry> entries = ops.get(i).getOps();
427
428 for (int j = 0; j < entries.size(); j++) {
429 AppOpsManager.OpEntry ent = entries.get(j);
Makoto Onuki2206af32017-11-21 16:25:35 -0800430 if (ent.getOp() != TARGET_OP) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800431 continue;
432 }
433 if (ent.getMode() != AppOpsManager.MODE_ALLOWED) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800434 mRunAnyRestrictedPackages.add(Pair.create(
Makoto Onuki9be01402017-11-10 13:22:26 -0800435 pkg.getUid(), pkg.getPackageName()));
436 }
437 }
438 }
439 }
440
Nancy Zheng525aaa12018-01-12 11:45:37 -0800441 private void updateForceAllAppStandbyState() {
442 synchronized (mLock) {
443 if (mForceAllAppStandbyForSmallBattery && isSmallBatteryDevice()) {
444 toggleForceAllAppsStandbyLocked(!mIsPluggedIn);
445 } else {
446 toggleForceAllAppsStandbyLocked(mBatterySaverEnabled);
447 }
448 }
449 }
450
Makoto Onuki2206af32017-11-21 16:25:35 -0800451 /**
452 * Update {@link #mForceAllAppsStandby} and notifies the listeners.
453 */
Nancy Zheng525aaa12018-01-12 11:45:37 -0800454 private void toggleForceAllAppsStandbyLocked(boolean enable) {
455 if (enable == mForceAllAppsStandby) {
456 return;
Makoto Onuki12391f22018-01-18 21:44:28 +0000457 }
Nancy Zheng525aaa12018-01-12 11:45:37 -0800458 mForceAllAppsStandby = enable;
459
460 mHandler.notifyForceAllAppsStandbyChanged();
Makoto Onuki9be01402017-11-10 13:22:26 -0800461 }
462
463 private int findForcedAppStandbyUidPackageIndexLocked(int uid, @NonNull String packageName) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800464 final int size = mRunAnyRestrictedPackages.size();
465 if (size > 8) {
466 return mRunAnyRestrictedPackages.indexOf(Pair.create(uid, packageName));
467 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800468 for (int i = 0; i < size; i++) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800469 final Pair<Integer, String> pair = mRunAnyRestrictedPackages.valueAt(i);
Makoto Onuki9be01402017-11-10 13:22:26 -0800470
471 if ((pair.first == uid) && packageName.equals(pair.second)) {
472 return i;
473 }
474 }
475 return -1;
476 }
477
478 /**
Makoto Onuki2206af32017-11-21 16:25:35 -0800479 * @return whether a uid package-name pair is in mRunAnyRestrictedPackages.
Makoto Onuki9be01402017-11-10 13:22:26 -0800480 */
Makoto Onuki2206af32017-11-21 16:25:35 -0800481 boolean isRunAnyRestrictedLocked(int uid, @NonNull String packageName) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800482 return findForcedAppStandbyUidPackageIndexLocked(uid, packageName) >= 0;
483 }
484
Makoto Onuki2206af32017-11-21 16:25:35 -0800485 /**
486 * Add to / remove from {@link #mRunAnyRestrictedPackages}.
487 */
488 boolean updateForcedAppStandbyUidPackageLocked(int uid, @NonNull String packageName,
Makoto Onuki9be01402017-11-10 13:22:26 -0800489 boolean restricted) {
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800490 final int index = findForcedAppStandbyUidPackageIndexLocked(uid, packageName);
Makoto Onuki9be01402017-11-10 13:22:26 -0800491 final boolean wasRestricted = index >= 0;
492 if (wasRestricted == restricted) {
493 return false;
494 }
495 if (restricted) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800496 mRunAnyRestrictedPackages.add(Pair.create(uid, packageName));
Makoto Onuki9be01402017-11-10 13:22:26 -0800497 } else {
Makoto Onuki2206af32017-11-21 16:25:35 -0800498 mRunAnyRestrictedPackages.removeAt(index);
Makoto Onuki9be01402017-11-10 13:22:26 -0800499 }
500 return true;
501 }
502
Makoto Onuki2206af32017-11-21 16:25:35 -0800503 /**
504 * Puts a UID to {@link #mForegroundUids}.
505 */
Makoto Onuki9be01402017-11-10 13:22:26 -0800506 void uidToForeground(int uid) {
507 synchronized (mLock) {
508 if (!UserHandle.isApp(uid)) {
509 return;
510 }
511 // TODO This can be optimized by calling indexOfKey and sharing the index for get and
512 // put.
513 if (mForegroundUids.get(uid)) {
514 return;
515 }
516 mForegroundUids.put(uid, true);
Makoto Onuki2206af32017-11-21 16:25:35 -0800517 mHandler.notifyUidForegroundStateChanged(uid);
Makoto Onuki9be01402017-11-10 13:22:26 -0800518 }
519 }
520
Makoto Onuki2206af32017-11-21 16:25:35 -0800521 /**
522 * Sets false for a UID {@link #mForegroundUids}, or remove it when {@code remove} is true.
523 */
Makoto Onuki9be01402017-11-10 13:22:26 -0800524 void uidToBackground(int uid, boolean remove) {
525 synchronized (mLock) {
526 if (!UserHandle.isApp(uid)) {
527 return;
528 }
529 // TODO This can be optimized by calling indexOfKey and sharing the index for get and
530 // put.
531 if (!mForegroundUids.get(uid)) {
532 return;
533 }
534 if (remove) {
535 mForegroundUids.delete(uid);
536 } else {
537 mForegroundUids.put(uid, false);
538 }
Makoto Onuki2206af32017-11-21 16:25:35 -0800539 mHandler.notifyUidForegroundStateChanged(uid);
Makoto Onuki9be01402017-11-10 13:22:26 -0800540 }
541 }
542
Makoto Onuki2206af32017-11-21 16:25:35 -0800543 private final class UidObserver extends IUidObserver.Stub {
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800544 @Override
545 public void onUidStateChanged(int uid, int procState, long procStateSeq) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800546 }
547
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800548 @Override
549 public void onUidGone(int uid, boolean disabled) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800550 uidToBackground(uid, /*remove=*/ true);
551 }
552
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800553 @Override
554 public void onUidActive(int uid) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800555 uidToForeground(uid);
556 }
557
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800558 @Override
559 public void onUidIdle(int uid, boolean disabled) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800560 // Just to avoid excessive memcpy, don't remove from the array in this case.
561 uidToBackground(uid, /*remove=*/ false);
562 }
563
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800564 @Override
565 public void onUidCachedChanged(int uid, boolean cached) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800566 }
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800567 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800568
569 private final class AppOpsWatcher extends IAppOpsCallback.Stub {
570 @Override
571 public void opChanged(int op, int uid, String packageName) throws RemoteException {
Makoto Onuki2206af32017-11-21 16:25:35 -0800572 boolean restricted = false;
573 try {
574 restricted = mAppOpsService.checkOperation(TARGET_OP,
575 uid, packageName) != AppOpsManager.MODE_ALLOWED;
576 } catch (RemoteException e) {
577 // Shouldn't happen
578 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800579 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800580 if (updateForcedAppStandbyUidPackageLocked(uid, packageName, restricted)) {
581 mHandler.notifyRunAnyAppOpsChanged(uid, packageName);
582 }
583 }
584 }
585 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800586
Makoto Onuki2206af32017-11-21 16:25:35 -0800587 private final class MyReceiver extends BroadcastReceiver {
588 @Override
589 public void onReceive(Context context, Intent intent) {
590 if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
591 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
592 if (userId > 0) {
593 mHandler.doUserRemoved(userId);
Makoto Onuki9be01402017-11-10 13:22:26 -0800594 }
Nancy Zheng525aaa12018-01-12 11:45:37 -0800595 } else if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
596 synchronized (mLock) {
597 mIsPluggedIn = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0);
598 }
599 updateForceAllAppStandbyState();
Makoto Onuki9be01402017-11-10 13:22:26 -0800600 }
601 }
602 }
603
604 private Listener[] cloneListeners() {
605 synchronized (mLock) {
606 return mListeners.toArray(new Listener[mListeners.size()]);
607 }
608 }
609
Makoto Onuki2206af32017-11-21 16:25:35 -0800610 private class MyHandler extends Handler {
611 private static final int MSG_UID_STATE_CHANGED = 1;
612 private static final int MSG_RUN_ANY_CHANGED = 2;
613 private static final int MSG_ALL_UNWHITELISTED = 3;
614 private static final int MSG_ALL_WHITELIST_CHANGED = 4;
615 private static final int MSG_TEMP_WHITELIST_CHANGED = 5;
616 private static final int MSG_FORCE_ALL_CHANGED = 6;
Makoto Onuki2206af32017-11-21 16:25:35 -0800617 private static final int MSG_USER_REMOVED = 7;
Nancy Zheng525aaa12018-01-12 11:45:37 -0800618 private static final int MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 8;
Makoto Onuki9be01402017-11-10 13:22:26 -0800619
Makoto Onuki2206af32017-11-21 16:25:35 -0800620 public MyHandler(Looper looper) {
621 super(looper);
Makoto Onuki9be01402017-11-10 13:22:26 -0800622 }
Makoto Onuki2206af32017-11-21 16:25:35 -0800623
624 public void notifyUidForegroundStateChanged(int uid) {
625 obtainMessage(MSG_UID_STATE_CHANGED, uid, 0).sendToTarget();
626 }
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800627
Makoto Onuki2206af32017-11-21 16:25:35 -0800628 public void notifyRunAnyAppOpsChanged(int uid, @NonNull String packageName) {
629 obtainMessage(MSG_RUN_ANY_CHANGED, uid, 0, packageName).sendToTarget();
630 }
631
632 public void notifyAllUnwhitelisted() {
633 obtainMessage(MSG_ALL_UNWHITELISTED).sendToTarget();
634 }
635
636 public void notifyAllWhitelistChanged() {
637 obtainMessage(MSG_ALL_WHITELIST_CHANGED).sendToTarget();
638 }
639
640 public void notifyTempWhitelistChanged() {
641 obtainMessage(MSG_TEMP_WHITELIST_CHANGED).sendToTarget();
642 }
643
644 public void notifyForceAllAppsStandbyChanged() {
645 obtainMessage(MSG_FORCE_ALL_CHANGED).sendToTarget();
646 }
647
Nancy Zheng525aaa12018-01-12 11:45:37 -0800648 public void notifyForcedAppStandbyFeatureFlagChanged() {
649 obtainMessage(MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED).sendToTarget();
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800650 }
651
Makoto Onuki2206af32017-11-21 16:25:35 -0800652 public void doUserRemoved(int userId) {
653 obtainMessage(MSG_USER_REMOVED, userId, 0).sendToTarget();
654 }
655
656 @Override
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800657 public void handleMessage(Message msg) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800658 switch (msg.what) {
659 case MSG_USER_REMOVED:
660 handleUserRemoved(msg.arg1);
661 return;
662 }
663
664 // Only notify the listeners when started.
665 synchronized (mLock) {
666 if (!mStarted) {
667 return;
668 }
669 }
670 final ForceAppStandbyTracker sender = ForceAppStandbyTracker.this;
671
672 switch (msg.what) {
673 case MSG_UID_STATE_CHANGED:
674 for (Listener l : cloneListeners()) {
675 l.onUidForegroundStateChanged(sender, msg.arg1);
676 }
677 return;
678 case MSG_RUN_ANY_CHANGED:
679 for (Listener l : cloneListeners()) {
680 l.onRunAnyAppOpsChanged(sender, msg.arg1, (String) msg.obj);
681 }
682 return;
683 case MSG_ALL_UNWHITELISTED:
684 for (Listener l : cloneListeners()) {
685 l.onPowerSaveUnwhitelisted(sender);
686 }
687 return;
688 case MSG_ALL_WHITELIST_CHANGED:
689 for (Listener l : cloneListeners()) {
690 l.onPowerSaveWhitelistedChanged(sender);
691 }
692 return;
693 case MSG_TEMP_WHITELIST_CHANGED:
694 for (Listener l : cloneListeners()) {
695 l.onTempPowerSaveWhitelistChanged(sender);
696 }
697 return;
698 case MSG_FORCE_ALL_CHANGED:
699 for (Listener l : cloneListeners()) {
700 l.onForceAllAppsStandbyChanged(sender);
701 }
702 return;
Nancy Zheng525aaa12018-01-12 11:45:37 -0800703 case MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED:
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800704 // Feature flag for forced app standby changed.
705 final boolean unblockAlarms;
706 synchronized (mLock) {
707 unblockAlarms = !mForcedAppStandbyEnabled && !mForceAllAppsStandby;
708 }
709 for (Listener l: cloneListeners()) {
710 l.updateAllJobs();
711 if (unblockAlarms) {
712 l.unblockAllUnrestrictedAlarms();
713 }
714 }
715 return;
Makoto Onuki2206af32017-11-21 16:25:35 -0800716 case MSG_USER_REMOVED:
717 handleUserRemoved(msg.arg1);
718 return;
719 }
720 }
721 }
722
723 void handleUserRemoved(int removedUserId) {
724 synchronized (mLock) {
725 for (int i = mRunAnyRestrictedPackages.size() - 1; i >= 0; i--) {
726 final Pair<Integer, String> pair = mRunAnyRestrictedPackages.valueAt(i);
727 final int uid = pair.first;
728 final int userId = UserHandle.getUserId(uid);
729
730 if (userId == removedUserId) {
731 mRunAnyRestrictedPackages.removeAt(i);
732 }
733 }
734 for (int i = mForegroundUids.size() - 1; i >= 0; i--) {
735 final int uid = mForegroundUids.keyAt(i);
736 final int userId = UserHandle.getUserId(uid);
737
738 if (userId == removedUserId) {
739 mForegroundUids.removeAt(i);
740 }
741 }
742 }
743 }
744
745 /**
746 * Called by device idle controller to update the power save whitelists.
747 */
748 public void setPowerSaveWhitelistAppIds(
749 int[] powerSaveWhitelistAllAppIdArray, int[] tempWhitelistAppIdArray) {
750 synchronized (mLock) {
751 final int[] previousWhitelist = mPowerWhitelistedAllAppIds;
752 final int[] previousTempWhitelist = mTempWhitelistedAppIds;
753
754 mPowerWhitelistedAllAppIds = powerSaveWhitelistAllAppIdArray;
755 mTempWhitelistedAppIds = tempWhitelistAppIdArray;
756
757 if (isAnyAppIdUnwhitelisted(previousWhitelist, mPowerWhitelistedAllAppIds)) {
758 mHandler.notifyAllUnwhitelisted();
759 } else if (!Arrays.equals(previousWhitelist, mPowerWhitelistedAllAppIds)) {
760 mHandler.notifyAllWhitelistChanged();
761 }
762
763 if (!Arrays.equals(previousTempWhitelist, mTempWhitelistedAppIds)) {
764 mHandler.notifyTempWhitelistChanged();
765 }
766
767 }
768 }
769
770 /**
771 * @retunr true if a sorted app-id array {@code prevArray} has at least one element
772 * that's not in a sorted app-id array {@code newArray}.
773 */
774 @VisibleForTesting
775 static boolean isAnyAppIdUnwhitelisted(int[] prevArray, int[] newArray) {
776 int i1 = 0;
777 int i2 = 0;
778 boolean prevFinished;
779 boolean newFinished;
780
781 for (;;) {
782 prevFinished = i1 >= prevArray.length;
783 newFinished = i2 >= newArray.length;
784 if (prevFinished || newFinished) {
785 break;
786 }
787 int a1 = prevArray[i1];
788 int a2 = newArray[i2];
789
790 if (a1 == a2) {
791 i1++;
792 i2++;
793 continue;
794 }
795 if (a1 < a2) {
796 // prevArray has an element that's not in a2.
797 return true;
798 }
799 i2++;
800 }
801 if (prevFinished) {
802 return false;
803 }
804 return newFinished;
Makoto Onuki9be01402017-11-10 13:22:26 -0800805 }
806
807 // Public interface.
808
809 /**
810 * Register a new listener.
811 */
812 public void addListener(@NonNull Listener listener) {
813 synchronized (mLock) {
814 mListeners.add(listener);
815 }
816 }
817
818 /**
Makoto Onuki2206af32017-11-21 16:25:35 -0800819 * @return whether alarms should be restricted for a UID package-name.
Makoto Onuki9be01402017-11-10 13:22:26 -0800820 */
Makoto Onuki2206af32017-11-21 16:25:35 -0800821 public boolean areAlarmsRestricted(int uid, @NonNull String packageName) {
Makoto Onukieb8cfd12018-01-19 15:43:16 -0800822 return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ false,
823 /* exemptOnBatterySaver =*/ false);
Makoto Onuki2206af32017-11-21 16:25:35 -0800824 }
825
826 /**
827 * @return whether jobs should be restricted for a UID package-name.
828 */
Makoto Onuki15407842018-01-19 14:23:11 -0800829 public boolean areJobsRestricted(int uid, @NonNull String packageName,
830 boolean hasForegroundExemption) {
Makoto Onukieb8cfd12018-01-19 15:43:16 -0800831 return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ true,
Makoto Onuki15407842018-01-19 14:23:11 -0800832 hasForegroundExemption);
Makoto Onuki2206af32017-11-21 16:25:35 -0800833 }
834
835 /**
836 * @return whether force-app-standby is effective for a UID package-name.
837 */
838 private boolean isRestricted(int uid, @NonNull String packageName,
Makoto Onukieb8cfd12018-01-19 15:43:16 -0800839 boolean useTempWhitelistToo, boolean exemptOnBatterySaver) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800840 if (isInForeground(uid)) {
841 return false;
842 }
843 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800844 // Whitelisted?
845 final int appId = UserHandle.getAppId(uid);
846 if (ArrayUtils.contains(mPowerWhitelistedAllAppIds, appId)) {
847 return false;
848 }
849 if (useTempWhitelistToo &&
850 ArrayUtils.contains(mTempWhitelistedAppIds, appId)) {
851 return false;
852 }
Makoto Onukieb8cfd12018-01-19 15:43:16 -0800853 if (mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName)) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800854 return true;
855 }
Makoto Onukieb8cfd12018-01-19 15:43:16 -0800856 if (exemptOnBatterySaver) {
857 return false;
858 }
859 return mForceAllAppsStandby;
Makoto Onuki9be01402017-11-10 13:22:26 -0800860 }
861 }
862
Makoto Onuki2206af32017-11-21 16:25:35 -0800863 /**
864 * @return whether a UID is in the foreground or not.
865 *
Makoto Onuki15407842018-01-19 14:23:11 -0800866 * Note this information is based on the UID proc state callback, meaning it's updated
867 * asynchronously and may subtly be stale. If the fresh data is needed, use
868 * {@link ActivityManagerInternal#getUidProcessState} instead.
Makoto Onuki2206af32017-11-21 16:25:35 -0800869 */
Makoto Onuki9be01402017-11-10 13:22:26 -0800870 public boolean isInForeground(int uid) {
871 if (!UserHandle.isApp(uid)) {
872 return true;
873 }
874 synchronized (mLock) {
875 return mForegroundUids.get(uid);
876 }
877 }
878
Makoto Onuki2206af32017-11-21 16:25:35 -0800879 /**
880 * @return whether force all apps standby is enabled or not.
881 *
882 * Note clients normally shouldn't need to access it.
883 */
884 boolean isForceAllAppsStandbyEnabled() {
Makoto Onuki9be01402017-11-10 13:22:26 -0800885 synchronized (mLock) {
886 return mForceAllAppsStandby;
887 }
888 }
889
Makoto Onuki2206af32017-11-21 16:25:35 -0800890 /**
891 * @return whether a UID/package has {@code OP_RUN_ANY_IN_BACKGROUND} allowed or not.
892 *
893 * Note clients normally shouldn't need to access it. It's only for dumpsys.
894 */
Makoto Onuki9be01402017-11-10 13:22:26 -0800895 public boolean isRunAnyInBackgroundAppOpsAllowed(int uid, @NonNull String packageName) {
896 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800897 return !isRunAnyRestrictedLocked(uid, packageName);
Makoto Onuki9be01402017-11-10 13:22:26 -0800898 }
899 }
900
Makoto Onuki2206af32017-11-21 16:25:35 -0800901 /**
902 * @return whether a UID is in the user / system defined power-save whitelist or not.
903 *
904 * Note clients normally shouldn't need to access it. It's only for dumpsys.
905 */
906 public boolean isUidPowerSaveWhitelisted(int uid) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800907 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800908 return ArrayUtils.contains(mPowerWhitelistedAllAppIds, UserHandle.getAppId(uid));
Makoto Onuki9be01402017-11-10 13:22:26 -0800909 }
910 }
911
Makoto Onuki2206af32017-11-21 16:25:35 -0800912 /**
913 * @return whether a UID is in the temp power-save whitelist or not.
914 *
915 * Note clients normally shouldn't need to access it. It's only for dumpsys.
916 */
917 public boolean isUidTempPowerSaveWhitelisted(int uid) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800918 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800919 return ArrayUtils.contains(mTempWhitelistedAppIds, UserHandle.getAppId(uid));
920 }
921 }
922
923 public void dump(PrintWriter pw, String indent) {
924 synchronized (mLock) {
925 pw.print(indent);
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800926 pw.println("Forced App Standby Feature enabled: " + mForcedAppStandbyEnabled);
927
928 pw.print(indent);
Makoto Onuki2206af32017-11-21 16:25:35 -0800929 pw.print("Force all apps standby: ");
930 pw.println(isForceAllAppsStandbyEnabled());
931
932 pw.print(indent);
Nancy Zheng525aaa12018-01-12 11:45:37 -0800933 pw.print("Small Battery Device: ");
934 pw.println(isSmallBatteryDevice());
935
936 pw.print(indent);
937 pw.print("Force all apps standby for small battery device: ");
938 pw.println(mForceAllAppStandbyForSmallBattery);
939
940 pw.print(indent);
941 pw.print("Plugged In: ");
942 pw.println(mIsPluggedIn);
943
944 pw.print(indent);
Makoto Onuki2206af32017-11-21 16:25:35 -0800945 pw.print("Foreground uids: [");
946
947 String sep = "";
948 for (int i = 0; i < mForegroundUids.size(); i++) {
949 if (mForegroundUids.valueAt(i)) {
950 pw.print(sep);
951 pw.print(UserHandle.formatUid(mForegroundUids.keyAt(i)));
952 sep = " ";
953 }
954 }
955 pw.println("]");
956
957 pw.print(indent);
958 pw.print("Whitelist appids: ");
959 pw.println(Arrays.toString(mPowerWhitelistedAllAppIds));
960
961 pw.print(indent);
962 pw.print("Temp whitelist appids: ");
963 pw.println(Arrays.toString(mTempWhitelistedAppIds));
964
965 pw.print(indent);
966 pw.println("Restricted packages:");
967 for (Pair<Integer, String> uidAndPackage : mRunAnyRestrictedPackages) {
968 pw.print(indent);
969 pw.print(" ");
970 pw.print(UserHandle.formatUid(uidAndPackage.first));
971 pw.print(" ");
972 pw.print(uidAndPackage.second);
973 pw.println();
974 }
975 }
976 }
977
978 public void dumpProto(ProtoOutputStream proto, long fieldId) {
979 synchronized (mLock) {
980 final long token = proto.start(fieldId);
981
982 proto.write(ForceAppStandbyTrackerProto.FORCE_ALL_APPS_STANDBY, mForceAllAppsStandby);
Nancy Zheng525aaa12018-01-12 11:45:37 -0800983 proto.write(ForceAppStandbyTrackerProto.IS_SMALL_BATTERY_DEVICE,
984 isSmallBatteryDevice());
985 proto.write(ForceAppStandbyTrackerProto.FORCE_ALL_APPS_STANDBY_FOR_SMALL_BATTERY,
986 mForceAllAppStandbyForSmallBattery);
987 proto.write(ForceAppStandbyTrackerProto.IS_CHARGING, mIsPluggedIn);
Makoto Onuki2206af32017-11-21 16:25:35 -0800988
989 for (int i = 0; i < mForegroundUids.size(); i++) {
990 if (mForegroundUids.valueAt(i)) {
991 proto.write(ForceAppStandbyTrackerProto.FOREGROUND_UIDS,
992 mForegroundUids.keyAt(i));
993 }
994 }
995
996 for (int appId : mPowerWhitelistedAllAppIds) {
997 proto.write(ForceAppStandbyTrackerProto.POWER_SAVE_WHITELIST_APP_IDS, appId);
998 }
999
1000 for (int appId : mTempWhitelistedAppIds) {
1001 proto.write(ForceAppStandbyTrackerProto.TEMP_POWER_SAVE_WHITELIST_APP_IDS, appId);
1002 }
1003
1004 for (Pair<Integer, String> uidAndPackage : mRunAnyRestrictedPackages) {
1005 final long token2 = proto.start(
1006 ForceAppStandbyTrackerProto.RUN_ANY_IN_BACKGROUND_RESTRICTED_PACKAGES);
1007 proto.write(RunAnyInBackgroundRestrictedPackages.UID, uidAndPackage.first);
1008 proto.write(RunAnyInBackgroundRestrictedPackages.PACKAGE_NAME,
1009 uidAndPackage.second);
1010 proto.end(token2);
1011 }
1012 proto.end(token);
Makoto Onuki9be01402017-11-10 13:22:26 -08001013 }
1014 }
1015}