blob: a1a5fb4d50b1bd61669a0add06f4c7d4c7b4ec2a [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;
20import android.app.AppOpsManager;
21import android.app.AppOpsManager.PackageOps;
Makoto Onuki2206af32017-11-21 16:25:35 -080022import android.app.IActivityManager;
Makoto Onuki9be01402017-11-10 13:22:26 -080023import android.app.IUidObserver;
Makoto Onuki2206af32017-11-21 16:25:35 -080024import android.content.BroadcastReceiver;
Makoto Onuki9be01402017-11-10 13:22:26 -080025import android.content.Context;
Makoto Onuki2206af32017-11-21 16:25:35 -080026import android.content.Intent;
27import android.content.IntentFilter;
Suprabh Shukla4deb8522018-01-08 16:27:10 -080028import android.database.ContentObserver;
Nancy Zheng525aaa12018-01-12 11:45:37 -080029import android.net.Uri;
30import android.os.BatteryManager;
Makoto Onuki9be01402017-11-10 13:22:26 -080031import android.os.Handler;
Makoto Onuki2206af32017-11-21 16:25:35 -080032import android.os.Looper;
33import android.os.Message;
Makoto Onuki9be01402017-11-10 13:22:26 -080034import android.os.PowerManager.ServiceType;
35import android.os.PowerManagerInternal;
36import android.os.RemoteException;
37import android.os.ServiceManager;
38import android.os.UserHandle;
Suprabh Shukla4deb8522018-01-08 16:27:10 -080039import android.provider.Settings;
Makoto Onuki9be01402017-11-10 13:22:26 -080040import android.util.ArraySet;
41import android.util.Pair;
Suprabh Shukla4deb8522018-01-08 16:27:10 -080042import android.util.Slog;
Makoto Onuki9be01402017-11-10 13:22:26 -080043import android.util.SparseBooleanArray;
Makoto Onuki2206af32017-11-21 16:25:35 -080044import android.util.proto.ProtoOutputStream;
Makoto Onuki9be01402017-11-10 13:22:26 -080045
46import com.android.internal.annotations.GuardedBy;
Makoto Onuki2206af32017-11-21 16:25:35 -080047import com.android.internal.annotations.VisibleForTesting;
Makoto Onuki9be01402017-11-10 13:22:26 -080048import com.android.internal.app.IAppOpsCallback;
49import com.android.internal.app.IAppOpsService;
Makoto Onuki2206af32017-11-21 16:25:35 -080050import com.android.internal.util.ArrayUtils;
Makoto Onuki9be01402017-11-10 13:22:26 -080051import com.android.internal.util.Preconditions;
Makoto Onuki2206af32017-11-21 16:25:35 -080052import com.android.server.ForceAppStandbyTrackerProto.RunAnyInBackgroundRestrictedPackages;
Makoto Onuki9be01402017-11-10 13:22:26 -080053
Makoto Onuki2206af32017-11-21 16:25:35 -080054import java.io.PrintWriter;
55import java.util.Arrays;
Makoto Onuki9be01402017-11-10 13:22:26 -080056import java.util.List;
57
58/**
Makoto Onuki2206af32017-11-21 16:25:35 -080059 * Class to keep track of the information related to "force app standby", which includes:
60 * - OP_RUN_ANY_IN_BACKGROUND for each package
61 * - UID foreground state
62 * - User+system power save whitelist
63 * - Temporary power save whitelist
64 * - Global "force all apps standby" mode enforced by battery saver.
Makoto Onuki9be01402017-11-10 13:22:26 -080065 *
Makoto Onuki2206af32017-11-21 16:25:35 -080066 * TODO: In general, we can reduce the number of callbacks by checking all signals before sending
Suprabh Shukla4deb8522018-01-08 16:27:10 -080067 * each callback. For example, even when an UID comes into the foreground, if it wasn't
68 * originally restricted, then there's no need to send an event.
69 * 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 -080070 *
71 * Test:
Suprabh Shukla4deb8522018-01-08 16:27:10 -080072 * atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
Makoto Onuki9be01402017-11-10 13:22:26 -080073 */
74public class ForceAppStandbyTracker {
75 private static final String TAG = "ForceAppStandbyTracker";
Suprabh Shukla4deb8522018-01-08 16:27:10 -080076 private static final boolean DEBUG = false;
Makoto Onuki9be01402017-11-10 13:22:26 -080077
78 @GuardedBy("ForceAppStandbyTracker.class")
79 private static ForceAppStandbyTracker sInstance;
80
81 private final Object mLock = new Object();
82 private final Context mContext;
83
Makoto Onuki2206af32017-11-21 16:25:35 -080084 @VisibleForTesting
85 static final int TARGET_OP = AppOpsManager.OP_RUN_ANY_IN_BACKGROUND;
86
87 IActivityManager mIActivityManager;
Makoto Onuki9be01402017-11-10 13:22:26 -080088 AppOpsManager mAppOpsManager;
89 IAppOpsService mAppOpsService;
90 PowerManagerInternal mPowerManagerInternal;
91
Makoto Onuki2206af32017-11-21 16:25:35 -080092 private final MyHandler mHandler;
Makoto Onuki9be01402017-11-10 13:22:26 -080093
Nancy Zheng525aaa12018-01-12 11:45:37 -080094 @VisibleForTesting
95 FeatureFlagsObserver mFlagsObserver;
96
Makoto Onuki9be01402017-11-10 13:22:26 -080097 /**
98 * Pair of (uid (not user-id), packageName) with OP_RUN_ANY_IN_BACKGROUND *not* allowed.
99 */
100 @GuardedBy("mLock")
Makoto Onuki2206af32017-11-21 16:25:35 -0800101 final ArraySet<Pair<Integer, String>> mRunAnyRestrictedPackages = new ArraySet<>();
Makoto Onuki9be01402017-11-10 13:22:26 -0800102
103 @GuardedBy("mLock")
104 final SparseBooleanArray mForegroundUids = new SparseBooleanArray();
105
Makoto Onuki71755c92018-01-16 14:15:44 -0800106 /**
107 * System except-idle + user whitelist in the device idle controller.
108 */
Makoto Onuki9be01402017-11-10 13:22:26 -0800109 @GuardedBy("mLock")
Makoto Onuki2206af32017-11-21 16:25:35 -0800110 private int[] mPowerWhitelistedAllAppIds = new int[0];
111
112 @GuardedBy("mLock")
113 private int[] mTempWhitelistedAppIds = mPowerWhitelistedAllAppIds;
114
115 @GuardedBy("mLock")
Makoto Onuki9be01402017-11-10 13:22:26 -0800116 final ArraySet<Listener> mListeners = new ArraySet<>();
117
118 @GuardedBy("mLock")
119 boolean mStarted;
120
Nancy Zheng525aaa12018-01-12 11:45:37 -0800121 /**
122 * Only used for small battery use-case.
123 */
Makoto Onuki9be01402017-11-10 13:22:26 -0800124 @GuardedBy("mLock")
Nancy Zheng525aaa12018-01-12 11:45:37 -0800125 boolean mIsPluggedIn;
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800126
127 @GuardedBy("mLock")
Nancy Zheng525aaa12018-01-12 11:45:37 -0800128 boolean mBatterySaverEnabled;
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800129
Nancy Zheng525aaa12018-01-12 11:45:37 -0800130 /**
131 * True if the forced app standby is currently enabled
132 */
133 @GuardedBy("mLock")
134 boolean mForceAllAppsStandby;
135
136 /**
137 * True if the forced app standby for small battery devices feature is enabled in settings
138 */
139 @GuardedBy("mLock")
140 boolean mForceAllAppStandbyForSmallBattery;
141
142 /**
143 * True if the forced app standby feature is enabled in settings
144 */
145 @GuardedBy("mLock")
146 boolean mForcedAppStandbyEnabled;
147
148 @VisibleForTesting
149 class FeatureFlagsObserver extends ContentObserver {
150 FeatureFlagsObserver() {
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800151 super(null);
152 }
153
154 void register() {
155 mContext.getContentResolver().registerContentObserver(
156 Settings.Global.getUriFor(Settings.Global.FORCED_APP_STANDBY_ENABLED),
157 false, this);
Nancy Zheng525aaa12018-01-12 11:45:37 -0800158
159 mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
160 Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED), false, this);
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800161 }
162
163 boolean isForcedAppStandbyEnabled() {
164 return Settings.Global.getInt(mContext.getContentResolver(),
165 Settings.Global.FORCED_APP_STANDBY_ENABLED, 1) == 1;
166 }
167
Nancy Zheng525aaa12018-01-12 11:45:37 -0800168 boolean isForcedAppStandbyForSmallBatteryEnabled() {
169 return Settings.Global.getInt(mContext.getContentResolver(),
170 Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED, 0) == 1;
171 }
172
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800173 @Override
Nancy Zheng525aaa12018-01-12 11:45:37 -0800174 public void onChange(boolean selfChange, Uri uri) {
175 if (Settings.Global.getUriFor(Settings.Global.FORCED_APP_STANDBY_ENABLED).equals(uri)) {
176 final boolean enabled = isForcedAppStandbyEnabled();
177 synchronized (mLock) {
178 if (mForcedAppStandbyEnabled == enabled) {
179 return;
180 }
181 mForcedAppStandbyEnabled = enabled;
182 if (DEBUG) {
183 Slog.d(TAG,"Forced app standby feature flag changed: "
184 + mForcedAppStandbyEnabled);
185 }
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800186 }
Nancy Zheng525aaa12018-01-12 11:45:37 -0800187 mHandler.notifyForcedAppStandbyFeatureFlagChanged();
188 } else if (Settings.Global.getUriFor(
189 Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED).equals(uri)) {
190 final boolean enabled = isForcedAppStandbyForSmallBatteryEnabled();
191 synchronized (mLock) {
192 if (mForceAllAppStandbyForSmallBattery == enabled) {
193 return;
194 }
195 mForceAllAppStandbyForSmallBattery = enabled;
196 if (DEBUG) {
197 Slog.d(TAG, "Forced app standby for small battery feature flag changed: "
198 + mForceAllAppStandbyForSmallBattery);
199 }
200 updateForceAllAppStandbyState();
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800201 }
Nancy Zheng525aaa12018-01-12 11:45:37 -0800202 } else {
203 Slog.w(TAG, "Unexpected feature flag uri encountered: " + uri);
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800204 }
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800205 }
206 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800207
208 public static abstract class Listener {
Makoto Onuki2206af32017-11-21 16:25:35 -0800209 /**
210 * This is called when the OP_RUN_ANY_IN_BACKGROUND appops changed for a package.
211 */
212 private void onRunAnyAppOpsChanged(ForceAppStandbyTracker sender,
213 int uid, @NonNull String packageName) {
214 updateJobsForUidPackage(uid, packageName);
215
216 if (!sender.areAlarmsRestricted(uid, packageName)) {
217 unblockAlarmsForUidPackage(uid, packageName);
218 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800219 }
220
Makoto Onuki2206af32017-11-21 16:25:35 -0800221 /**
222 * This is called when the foreground state changed for a UID.
223 */
224 private void onUidForegroundStateChanged(ForceAppStandbyTracker sender, int uid) {
225 updateJobsForUid(uid);
226
227 if (sender.isInForeground(uid)) {
228 unblockAlarmsForUid(uid);
229 }
230 }
231
232 /**
233 * This is called when an app-id(s) is removed from the power save whitelist.
234 */
235 private void onPowerSaveUnwhitelisted(ForceAppStandbyTracker sender) {
236 updateAllJobs();
237 unblockAllUnrestrictedAlarms();
238 }
239
240 /**
241 * This is called when the power save whitelist changes, excluding the
242 * {@link #onPowerSaveUnwhitelisted} case.
243 */
244 private void onPowerSaveWhitelistedChanged(ForceAppStandbyTracker sender) {
245 updateAllJobs();
246 }
247
248 /**
249 * This is called when the temp whitelist changes.
250 */
251 private void onTempPowerSaveWhitelistChanged(ForceAppStandbyTracker sender) {
252
253 // TODO This case happens rather frequently; consider optimizing and update jobs
254 // only for affected app-ids.
255
256 updateAllJobs();
257 }
258
259 /**
260 * This is called when the global "force all apps standby" flag changes.
261 */
262 private void onForceAllAppsStandbyChanged(ForceAppStandbyTracker sender) {
263 updateAllJobs();
264
265 if (!sender.isForceAllAppsStandbyEnabled()) {
266 unblockAllUnrestrictedAlarms();
267 }
268 }
269
270 /**
271 * Called when the job restrictions for multiple UIDs might have changed, so the job
272 * scheduler should re-evaluate all restrictions for all jobs.
273 */
274 public void updateAllJobs() {
275 }
276
277 /**
278 * Called when the job restrictions for a UID might have changed, so the job
279 * scheduler should re-evaluate all restrictions for all jobs.
280 */
281 public void updateJobsForUid(int uid) {
282 }
283
284 /**
285 * Called when the job restrictions for a UID - package might have changed, so the job
286 * scheduler should re-evaluate all restrictions for all jobs.
287 */
288 public void updateJobsForUidPackage(int uid, String packageName) {
289 }
290
291 /**
292 * Called when the job restrictions for multiple UIDs might have changed, so the alarm
293 * manager should re-evaluate all restrictions for all blocked jobs.
294 */
295 public void unblockAllUnrestrictedAlarms() {
296 }
297
298 /**
299 * Called when all jobs for a specific UID are unblocked.
300 */
301 public void unblockAlarmsForUid(int uid) {
302 }
303
304 /**
305 * Called when all alarms for a specific UID - package are unblocked.
306 */
307 public void unblockAlarmsForUidPackage(int uid, String packageName) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800308 }
309 }
310
Makoto Onuki2206af32017-11-21 16:25:35 -0800311 @VisibleForTesting
312 ForceAppStandbyTracker(Context context, Looper looper) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800313 mContext = context;
Makoto Onuki2206af32017-11-21 16:25:35 -0800314 mHandler = new MyHandler(looper);
315 }
316
317 private ForceAppStandbyTracker(Context context) {
318 this(context, FgThread.get().getLooper());
Makoto Onuki9be01402017-11-10 13:22:26 -0800319 }
320
321 /**
322 * Get the singleton instance.
323 */
324 public static synchronized ForceAppStandbyTracker getInstance(Context context) {
325 if (sInstance == null) {
326 sInstance = new ForceAppStandbyTracker(context);
327 }
328 return sInstance;
329 }
330
331 /**
332 * Call it when the system is ready.
333 */
334 public void start() {
335 synchronized (mLock) {
336 if (mStarted) {
337 return;
338 }
339 mStarted = true;
340
Makoto Onuki2206af32017-11-21 16:25:35 -0800341 mIActivityManager = Preconditions.checkNotNull(injectIActivityManager());
342 mAppOpsManager = Preconditions.checkNotNull(injectAppOpsManager());
343 mAppOpsService = Preconditions.checkNotNull(injectIAppOpsService());
344 mPowerManagerInternal = Preconditions.checkNotNull(injectPowerManagerInternal());
Nancy Zheng525aaa12018-01-12 11:45:37 -0800345 mFlagsObserver = new FeatureFlagsObserver();
346 mFlagsObserver.register();
347 mForcedAppStandbyEnabled = mFlagsObserver.isForcedAppStandbyEnabled();
348 mForceAllAppStandbyForSmallBattery =
349 mFlagsObserver.isForcedAppStandbyForSmallBatteryEnabled();
Makoto Onuki9be01402017-11-10 13:22:26 -0800350
351 try {
Makoto Onuki2206af32017-11-21 16:25:35 -0800352 mIActivityManager.registerUidObserver(new UidObserver(),
Makoto Onuki9be01402017-11-10 13:22:26 -0800353 ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE
354 | ActivityManager.UID_OBSERVER_ACTIVE,
355 ActivityManager.PROCESS_STATE_UNKNOWN, null);
Makoto Onuki2206af32017-11-21 16:25:35 -0800356 mAppOpsService.startWatchingMode(TARGET_OP, null,
Makoto Onuki9be01402017-11-10 13:22:26 -0800357 new AppOpsWatcher());
358 } catch (RemoteException e) {
359 // shouldn't happen.
360 }
361
Makoto Onuki2206af32017-11-21 16:25:35 -0800362 IntentFilter filter = new IntentFilter();
363 filter.addAction(Intent.ACTION_USER_REMOVED);
Nancy Zheng525aaa12018-01-12 11:45:37 -0800364 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
Makoto Onuki2206af32017-11-21 16:25:35 -0800365 mContext.registerReceiver(new MyReceiver(), filter);
Makoto Onuki9be01402017-11-10 13:22:26 -0800366
367 refreshForcedAppStandbyUidPackagesLocked();
Makoto Onuki2206af32017-11-21 16:25:35 -0800368
369 mPowerManagerInternal.registerLowPowerModeObserver(
370 ServiceType.FORCE_ALL_APPS_STANDBY,
Nancy Zheng525aaa12018-01-12 11:45:37 -0800371 (state) -> {
372 synchronized (mLock) {
373 mBatterySaverEnabled = state.batterySaverEnabled;
374 updateForceAllAppStandbyState();
375 }
376 });
Makoto Onuki2206af32017-11-21 16:25:35 -0800377
Nancy Zheng525aaa12018-01-12 11:45:37 -0800378 mBatterySaverEnabled = mPowerManagerInternal.getLowPowerState(
379 ServiceType.FORCE_ALL_APPS_STANDBY).batterySaverEnabled;
380
381 updateForceAllAppStandbyState();
Makoto Onuki9be01402017-11-10 13:22:26 -0800382 }
383 }
384
Makoto Onuki2206af32017-11-21 16:25:35 -0800385 @VisibleForTesting
386 AppOpsManager injectAppOpsManager() {
387 return mContext.getSystemService(AppOpsManager.class);
388 }
389
390 @VisibleForTesting
391 IAppOpsService injectIAppOpsService() {
392 return IAppOpsService.Stub.asInterface(
393 ServiceManager.getService(Context.APP_OPS_SERVICE));
394 }
395
396 @VisibleForTesting
397 IActivityManager injectIActivityManager() {
398 return ActivityManager.getService();
399 }
400
401 @VisibleForTesting
402 PowerManagerInternal injectPowerManagerInternal() {
403 return LocalServices.getService(PowerManagerInternal.class);
404 }
405
Nancy Zheng525aaa12018-01-12 11:45:37 -0800406 @VisibleForTesting
407 boolean isSmallBatteryDevice() {
408 return ActivityManager.isSmallBatteryDevice();
409 }
410
Makoto Onuki9be01402017-11-10 13:22:26 -0800411 /**
Makoto Onuki2206af32017-11-21 16:25:35 -0800412 * Update {@link #mRunAnyRestrictedPackages} with the current app ops state.
Makoto Onuki9be01402017-11-10 13:22:26 -0800413 */
414 private void refreshForcedAppStandbyUidPackagesLocked() {
Makoto Onuki2206af32017-11-21 16:25:35 -0800415 mRunAnyRestrictedPackages.clear();
416 final List<PackageOps> ops = mAppOpsManager.getPackagesForOps(
417 new int[] {TARGET_OP});
Makoto Onuki9be01402017-11-10 13:22:26 -0800418
419 if (ops == null) {
420 return;
421 }
422 final int size = ops.size();
423 for (int i = 0; i < size; i++) {
424 final AppOpsManager.PackageOps pkg = ops.get(i);
425 final List<AppOpsManager.OpEntry> entries = ops.get(i).getOps();
426
427 for (int j = 0; j < entries.size(); j++) {
428 AppOpsManager.OpEntry ent = entries.get(j);
Makoto Onuki2206af32017-11-21 16:25:35 -0800429 if (ent.getOp() != TARGET_OP) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800430 continue;
431 }
432 if (ent.getMode() != AppOpsManager.MODE_ALLOWED) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800433 mRunAnyRestrictedPackages.add(Pair.create(
Makoto Onuki9be01402017-11-10 13:22:26 -0800434 pkg.getUid(), pkg.getPackageName()));
435 }
436 }
437 }
438 }
439
Nancy Zheng525aaa12018-01-12 11:45:37 -0800440 private void updateForceAllAppStandbyState() {
441 synchronized (mLock) {
442 if (mForceAllAppStandbyForSmallBattery && isSmallBatteryDevice()) {
443 toggleForceAllAppsStandbyLocked(!mIsPluggedIn);
444 } else {
445 toggleForceAllAppsStandbyLocked(mBatterySaverEnabled);
446 }
447 }
448 }
449
Makoto Onuki2206af32017-11-21 16:25:35 -0800450 /**
451 * Update {@link #mForceAllAppsStandby} and notifies the listeners.
452 */
Nancy Zheng525aaa12018-01-12 11:45:37 -0800453 private void toggleForceAllAppsStandbyLocked(boolean enable) {
454 if (enable == mForceAllAppsStandby) {
455 return;
Makoto Onuki12391f22018-01-18 21:44:28 +0000456 }
Nancy Zheng525aaa12018-01-12 11:45:37 -0800457 mForceAllAppsStandby = enable;
458
459 mHandler.notifyForceAllAppsStandbyChanged();
Makoto Onuki9be01402017-11-10 13:22:26 -0800460 }
461
462 private int findForcedAppStandbyUidPackageIndexLocked(int uid, @NonNull String packageName) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800463 final int size = mRunAnyRestrictedPackages.size();
464 if (size > 8) {
465 return mRunAnyRestrictedPackages.indexOf(Pair.create(uid, packageName));
466 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800467 for (int i = 0; i < size; i++) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800468 final Pair<Integer, String> pair = mRunAnyRestrictedPackages.valueAt(i);
Makoto Onuki9be01402017-11-10 13:22:26 -0800469
470 if ((pair.first == uid) && packageName.equals(pair.second)) {
471 return i;
472 }
473 }
474 return -1;
475 }
476
477 /**
Makoto Onuki2206af32017-11-21 16:25:35 -0800478 * @return whether a uid package-name pair is in mRunAnyRestrictedPackages.
Makoto Onuki9be01402017-11-10 13:22:26 -0800479 */
Makoto Onuki2206af32017-11-21 16:25:35 -0800480 boolean isRunAnyRestrictedLocked(int uid, @NonNull String packageName) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800481 return findForcedAppStandbyUidPackageIndexLocked(uid, packageName) >= 0;
482 }
483
Makoto Onuki2206af32017-11-21 16:25:35 -0800484 /**
485 * Add to / remove from {@link #mRunAnyRestrictedPackages}.
486 */
487 boolean updateForcedAppStandbyUidPackageLocked(int uid, @NonNull String packageName,
Makoto Onuki9be01402017-11-10 13:22:26 -0800488 boolean restricted) {
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800489 final int index = findForcedAppStandbyUidPackageIndexLocked(uid, packageName);
Makoto Onuki9be01402017-11-10 13:22:26 -0800490 final boolean wasRestricted = index >= 0;
491 if (wasRestricted == restricted) {
492 return false;
493 }
494 if (restricted) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800495 mRunAnyRestrictedPackages.add(Pair.create(uid, packageName));
Makoto Onuki9be01402017-11-10 13:22:26 -0800496 } else {
Makoto Onuki2206af32017-11-21 16:25:35 -0800497 mRunAnyRestrictedPackages.removeAt(index);
Makoto Onuki9be01402017-11-10 13:22:26 -0800498 }
499 return true;
500 }
501
Makoto Onuki2206af32017-11-21 16:25:35 -0800502 /**
503 * Puts a UID to {@link #mForegroundUids}.
504 */
Makoto Onuki9be01402017-11-10 13:22:26 -0800505 void uidToForeground(int uid) {
506 synchronized (mLock) {
Makoto Onuki9cc471c2018-01-23 12:33:56 -0800507 if (UserHandle.isCore(uid)) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800508 return;
509 }
510 // TODO This can be optimized by calling indexOfKey and sharing the index for get and
511 // put.
512 if (mForegroundUids.get(uid)) {
513 return;
514 }
515 mForegroundUids.put(uid, true);
Makoto Onuki2206af32017-11-21 16:25:35 -0800516 mHandler.notifyUidForegroundStateChanged(uid);
Makoto Onuki9be01402017-11-10 13:22:26 -0800517 }
518 }
519
Makoto Onuki2206af32017-11-21 16:25:35 -0800520 /**
521 * Sets false for a UID {@link #mForegroundUids}, or remove it when {@code remove} is true.
522 */
Makoto Onuki9be01402017-11-10 13:22:26 -0800523 void uidToBackground(int uid, boolean remove) {
524 synchronized (mLock) {
Makoto Onuki9cc471c2018-01-23 12:33:56 -0800525 if (UserHandle.isCore(uid)) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800526 return;
527 }
528 // TODO This can be optimized by calling indexOfKey and sharing the index for get and
529 // put.
530 if (!mForegroundUids.get(uid)) {
531 return;
532 }
533 if (remove) {
534 mForegroundUids.delete(uid);
535 } else {
536 mForegroundUids.put(uid, false);
537 }
Makoto Onuki2206af32017-11-21 16:25:35 -0800538 mHandler.notifyUidForegroundStateChanged(uid);
Makoto Onuki9be01402017-11-10 13:22:26 -0800539 }
540 }
541
Makoto Onuki2206af32017-11-21 16:25:35 -0800542 private final class UidObserver extends IUidObserver.Stub {
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800543 @Override
544 public void onUidStateChanged(int uid, int procState, long procStateSeq) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800545 }
546
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800547 @Override
548 public void onUidGone(int uid, boolean disabled) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800549 uidToBackground(uid, /*remove=*/ true);
550 }
551
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800552 @Override
553 public void onUidActive(int uid) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800554 uidToForeground(uid);
555 }
556
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800557 @Override
558 public void onUidIdle(int uid, boolean disabled) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800559 // Just to avoid excessive memcpy, don't remove from the array in this case.
560 uidToBackground(uid, /*remove=*/ false);
561 }
562
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800563 @Override
564 public void onUidCachedChanged(int uid, boolean cached) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800565 }
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800566 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800567
568 private final class AppOpsWatcher extends IAppOpsCallback.Stub {
569 @Override
570 public void opChanged(int op, int uid, String packageName) throws RemoteException {
Makoto Onuki2206af32017-11-21 16:25:35 -0800571 boolean restricted = false;
572 try {
573 restricted = mAppOpsService.checkOperation(TARGET_OP,
574 uid, packageName) != AppOpsManager.MODE_ALLOWED;
575 } catch (RemoteException e) {
576 // Shouldn't happen
577 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800578 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800579 if (updateForcedAppStandbyUidPackageLocked(uid, packageName, restricted)) {
580 mHandler.notifyRunAnyAppOpsChanged(uid, packageName);
581 }
582 }
583 }
584 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800585
Makoto Onuki2206af32017-11-21 16:25:35 -0800586 private final class MyReceiver extends BroadcastReceiver {
587 @Override
588 public void onReceive(Context context, Intent intent) {
589 if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
590 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
591 if (userId > 0) {
592 mHandler.doUserRemoved(userId);
Makoto Onuki9be01402017-11-10 13:22:26 -0800593 }
Nancy Zheng525aaa12018-01-12 11:45:37 -0800594 } else if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
595 synchronized (mLock) {
596 mIsPluggedIn = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0);
597 }
598 updateForceAllAppStandbyState();
Makoto Onuki9be01402017-11-10 13:22:26 -0800599 }
600 }
601 }
602
603 private Listener[] cloneListeners() {
604 synchronized (mLock) {
605 return mListeners.toArray(new Listener[mListeners.size()]);
606 }
607 }
608
Makoto Onuki2206af32017-11-21 16:25:35 -0800609 private class MyHandler extends Handler {
610 private static final int MSG_UID_STATE_CHANGED = 1;
611 private static final int MSG_RUN_ANY_CHANGED = 2;
612 private static final int MSG_ALL_UNWHITELISTED = 3;
613 private static final int MSG_ALL_WHITELIST_CHANGED = 4;
614 private static final int MSG_TEMP_WHITELIST_CHANGED = 5;
615 private static final int MSG_FORCE_ALL_CHANGED = 6;
Makoto Onuki2206af32017-11-21 16:25:35 -0800616 private static final int MSG_USER_REMOVED = 7;
Nancy Zheng525aaa12018-01-12 11:45:37 -0800617 private static final int MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 8;
Makoto Onuki9be01402017-11-10 13:22:26 -0800618
Makoto Onuki2206af32017-11-21 16:25:35 -0800619 public MyHandler(Looper looper) {
620 super(looper);
Makoto Onuki9be01402017-11-10 13:22:26 -0800621 }
Makoto Onuki2206af32017-11-21 16:25:35 -0800622
623 public void notifyUidForegroundStateChanged(int uid) {
624 obtainMessage(MSG_UID_STATE_CHANGED, uid, 0).sendToTarget();
625 }
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800626
Makoto Onuki2206af32017-11-21 16:25:35 -0800627 public void notifyRunAnyAppOpsChanged(int uid, @NonNull String packageName) {
628 obtainMessage(MSG_RUN_ANY_CHANGED, uid, 0, packageName).sendToTarget();
629 }
630
631 public void notifyAllUnwhitelisted() {
632 obtainMessage(MSG_ALL_UNWHITELISTED).sendToTarget();
633 }
634
635 public void notifyAllWhitelistChanged() {
636 obtainMessage(MSG_ALL_WHITELIST_CHANGED).sendToTarget();
637 }
638
639 public void notifyTempWhitelistChanged() {
640 obtainMessage(MSG_TEMP_WHITELIST_CHANGED).sendToTarget();
641 }
642
643 public void notifyForceAllAppsStandbyChanged() {
644 obtainMessage(MSG_FORCE_ALL_CHANGED).sendToTarget();
645 }
646
Nancy Zheng525aaa12018-01-12 11:45:37 -0800647 public void notifyForcedAppStandbyFeatureFlagChanged() {
648 obtainMessage(MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED).sendToTarget();
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800649 }
650
Makoto Onuki2206af32017-11-21 16:25:35 -0800651 public void doUserRemoved(int userId) {
652 obtainMessage(MSG_USER_REMOVED, userId, 0).sendToTarget();
653 }
654
655 @Override
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800656 public void handleMessage(Message msg) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800657 switch (msg.what) {
658 case MSG_USER_REMOVED:
659 handleUserRemoved(msg.arg1);
660 return;
661 }
662
663 // Only notify the listeners when started.
664 synchronized (mLock) {
665 if (!mStarted) {
666 return;
667 }
668 }
669 final ForceAppStandbyTracker sender = ForceAppStandbyTracker.this;
670
671 switch (msg.what) {
672 case MSG_UID_STATE_CHANGED:
673 for (Listener l : cloneListeners()) {
674 l.onUidForegroundStateChanged(sender, msg.arg1);
675 }
676 return;
677 case MSG_RUN_ANY_CHANGED:
678 for (Listener l : cloneListeners()) {
679 l.onRunAnyAppOpsChanged(sender, msg.arg1, (String) msg.obj);
680 }
681 return;
682 case MSG_ALL_UNWHITELISTED:
683 for (Listener l : cloneListeners()) {
684 l.onPowerSaveUnwhitelisted(sender);
685 }
686 return;
687 case MSG_ALL_WHITELIST_CHANGED:
688 for (Listener l : cloneListeners()) {
689 l.onPowerSaveWhitelistedChanged(sender);
690 }
691 return;
692 case MSG_TEMP_WHITELIST_CHANGED:
693 for (Listener l : cloneListeners()) {
694 l.onTempPowerSaveWhitelistChanged(sender);
695 }
696 return;
697 case MSG_FORCE_ALL_CHANGED:
698 for (Listener l : cloneListeners()) {
699 l.onForceAllAppsStandbyChanged(sender);
700 }
701 return;
Nancy Zheng525aaa12018-01-12 11:45:37 -0800702 case MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED:
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800703 // Feature flag for forced app standby changed.
704 final boolean unblockAlarms;
705 synchronized (mLock) {
706 unblockAlarms = !mForcedAppStandbyEnabled && !mForceAllAppsStandby;
707 }
708 for (Listener l: cloneListeners()) {
709 l.updateAllJobs();
710 if (unblockAlarms) {
711 l.unblockAllUnrestrictedAlarms();
712 }
713 }
714 return;
Makoto Onuki2206af32017-11-21 16:25:35 -0800715 case MSG_USER_REMOVED:
716 handleUserRemoved(msg.arg1);
717 return;
718 }
719 }
720 }
721
722 void handleUserRemoved(int removedUserId) {
723 synchronized (mLock) {
724 for (int i = mRunAnyRestrictedPackages.size() - 1; i >= 0; i--) {
725 final Pair<Integer, String> pair = mRunAnyRestrictedPackages.valueAt(i);
726 final int uid = pair.first;
727 final int userId = UserHandle.getUserId(uid);
728
729 if (userId == removedUserId) {
730 mRunAnyRestrictedPackages.removeAt(i);
731 }
732 }
733 for (int i = mForegroundUids.size() - 1; i >= 0; i--) {
734 final int uid = mForegroundUids.keyAt(i);
735 final int userId = UserHandle.getUserId(uid);
736
737 if (userId == removedUserId) {
738 mForegroundUids.removeAt(i);
739 }
740 }
741 }
742 }
743
744 /**
745 * Called by device idle controller to update the power save whitelists.
746 */
747 public void setPowerSaveWhitelistAppIds(
748 int[] powerSaveWhitelistAllAppIdArray, int[] tempWhitelistAppIdArray) {
749 synchronized (mLock) {
750 final int[] previousWhitelist = mPowerWhitelistedAllAppIds;
751 final int[] previousTempWhitelist = mTempWhitelistedAppIds;
752
753 mPowerWhitelistedAllAppIds = powerSaveWhitelistAllAppIdArray;
754 mTempWhitelistedAppIds = tempWhitelistAppIdArray;
755
756 if (isAnyAppIdUnwhitelisted(previousWhitelist, mPowerWhitelistedAllAppIds)) {
757 mHandler.notifyAllUnwhitelisted();
758 } else if (!Arrays.equals(previousWhitelist, mPowerWhitelistedAllAppIds)) {
759 mHandler.notifyAllWhitelistChanged();
760 }
761
762 if (!Arrays.equals(previousTempWhitelist, mTempWhitelistedAppIds)) {
763 mHandler.notifyTempWhitelistChanged();
764 }
765
766 }
767 }
768
769 /**
770 * @retunr true if a sorted app-id array {@code prevArray} has at least one element
771 * that's not in a sorted app-id array {@code newArray}.
772 */
773 @VisibleForTesting
774 static boolean isAnyAppIdUnwhitelisted(int[] prevArray, int[] newArray) {
775 int i1 = 0;
776 int i2 = 0;
777 boolean prevFinished;
778 boolean newFinished;
779
780 for (;;) {
781 prevFinished = i1 >= prevArray.length;
782 newFinished = i2 >= newArray.length;
783 if (prevFinished || newFinished) {
784 break;
785 }
786 int a1 = prevArray[i1];
787 int a2 = newArray[i2];
788
789 if (a1 == a2) {
790 i1++;
791 i2++;
792 continue;
793 }
794 if (a1 < a2) {
795 // prevArray has an element that's not in a2.
796 return true;
797 }
798 i2++;
799 }
800 if (prevFinished) {
801 return false;
802 }
803 return newFinished;
Makoto Onuki9be01402017-11-10 13:22:26 -0800804 }
805
806 // Public interface.
807
808 /**
809 * Register a new listener.
810 */
811 public void addListener(@NonNull Listener listener) {
812 synchronized (mLock) {
813 mListeners.add(listener);
814 }
815 }
816
817 /**
Makoto Onuki2206af32017-11-21 16:25:35 -0800818 * @return whether alarms should be restricted for a UID package-name.
Makoto Onuki9be01402017-11-10 13:22:26 -0800819 */
Makoto Onuki2206af32017-11-21 16:25:35 -0800820 public boolean areAlarmsRestricted(int uid, @NonNull String packageName) {
Makoto Onukieb8cfd12018-01-19 15:43:16 -0800821 return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ false,
822 /* exemptOnBatterySaver =*/ false);
Makoto Onuki2206af32017-11-21 16:25:35 -0800823 }
824
825 /**
826 * @return whether jobs should be restricted for a UID package-name.
827 */
828 public boolean areJobsRestricted(int uid, @NonNull String packageName) {
Makoto Onukieb8cfd12018-01-19 15:43:16 -0800829 return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ true,
830 /* exemptOnBatterySaver =*/ false);
Makoto Onuki2206af32017-11-21 16:25:35 -0800831 }
832
833 /**
834 * @return whether force-app-standby is effective for a UID package-name.
835 */
836 private boolean isRestricted(int uid, @NonNull String packageName,
Makoto Onukieb8cfd12018-01-19 15:43:16 -0800837 boolean useTempWhitelistToo, boolean exemptOnBatterySaver) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800838 if (isInForeground(uid)) {
839 return false;
840 }
841 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800842 // Whitelisted?
843 final int appId = UserHandle.getAppId(uid);
844 if (ArrayUtils.contains(mPowerWhitelistedAllAppIds, appId)) {
845 return false;
846 }
847 if (useTempWhitelistToo &&
848 ArrayUtils.contains(mTempWhitelistedAppIds, appId)) {
849 return false;
850 }
Makoto Onukieb8cfd12018-01-19 15:43:16 -0800851 if (mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName)) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800852 return true;
853 }
Makoto Onukieb8cfd12018-01-19 15:43:16 -0800854 if (exemptOnBatterySaver) {
855 return false;
856 }
857 return mForceAllAppsStandby;
Makoto Onuki9be01402017-11-10 13:22:26 -0800858 }
859 }
860
Makoto Onuki2206af32017-11-21 16:25:35 -0800861 /**
862 * @return whether a UID is in the foreground or not.
863 *
864 * Note clients normally shouldn't need to access it. It's only for dumpsys.
865 */
Makoto Onuki9be01402017-11-10 13:22:26 -0800866 public boolean isInForeground(int uid) {
Makoto Onuki9cc471c2018-01-23 12:33:56 -0800867 if (UserHandle.isCore(uid)) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800868 return true;
869 }
870 synchronized (mLock) {
871 return mForegroundUids.get(uid);
872 }
873 }
874
Makoto Onuki2206af32017-11-21 16:25:35 -0800875 /**
876 * @return whether force all apps standby is enabled or not.
877 *
878 * Note clients normally shouldn't need to access it.
879 */
880 boolean isForceAllAppsStandbyEnabled() {
Makoto Onuki9be01402017-11-10 13:22:26 -0800881 synchronized (mLock) {
882 return mForceAllAppsStandby;
883 }
884 }
885
Makoto Onuki2206af32017-11-21 16:25:35 -0800886 /**
887 * @return whether a UID/package has {@code OP_RUN_ANY_IN_BACKGROUND} allowed or not.
888 *
889 * Note clients normally shouldn't need to access it. It's only for dumpsys.
890 */
Makoto Onuki9be01402017-11-10 13:22:26 -0800891 public boolean isRunAnyInBackgroundAppOpsAllowed(int uid, @NonNull String packageName) {
892 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800893 return !isRunAnyRestrictedLocked(uid, packageName);
Makoto Onuki9be01402017-11-10 13:22:26 -0800894 }
895 }
896
Makoto Onuki2206af32017-11-21 16:25:35 -0800897 /**
898 * @return whether a UID is in the user / system defined power-save whitelist or not.
899 *
900 * Note clients normally shouldn't need to access it. It's only for dumpsys.
901 */
902 public boolean isUidPowerSaveWhitelisted(int uid) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800903 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800904 return ArrayUtils.contains(mPowerWhitelistedAllAppIds, UserHandle.getAppId(uid));
Makoto Onuki9be01402017-11-10 13:22:26 -0800905 }
906 }
907
Makoto Onuki2206af32017-11-21 16:25:35 -0800908 /**
909 * @return whether a UID is in the temp power-save whitelist or not.
910 *
911 * Note clients normally shouldn't need to access it. It's only for dumpsys.
912 */
913 public boolean isUidTempPowerSaveWhitelisted(int uid) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800914 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800915 return ArrayUtils.contains(mTempWhitelistedAppIds, UserHandle.getAppId(uid));
916 }
917 }
918
919 public void dump(PrintWriter pw, String indent) {
920 synchronized (mLock) {
921 pw.print(indent);
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800922 pw.println("Forced App Standby Feature enabled: " + mForcedAppStandbyEnabled);
923
924 pw.print(indent);
Makoto Onuki2206af32017-11-21 16:25:35 -0800925 pw.print("Force all apps standby: ");
926 pw.println(isForceAllAppsStandbyEnabled());
927
928 pw.print(indent);
Nancy Zheng525aaa12018-01-12 11:45:37 -0800929 pw.print("Small Battery Device: ");
930 pw.println(isSmallBatteryDevice());
931
932 pw.print(indent);
933 pw.print("Force all apps standby for small battery device: ");
934 pw.println(mForceAllAppStandbyForSmallBattery);
935
936 pw.print(indent);
937 pw.print("Plugged In: ");
938 pw.println(mIsPluggedIn);
939
940 pw.print(indent);
Makoto Onuki2206af32017-11-21 16:25:35 -0800941 pw.print("Foreground uids: [");
942
943 String sep = "";
944 for (int i = 0; i < mForegroundUids.size(); i++) {
945 if (mForegroundUids.valueAt(i)) {
946 pw.print(sep);
947 pw.print(UserHandle.formatUid(mForegroundUids.keyAt(i)));
948 sep = " ";
949 }
950 }
951 pw.println("]");
952
953 pw.print(indent);
954 pw.print("Whitelist appids: ");
955 pw.println(Arrays.toString(mPowerWhitelistedAllAppIds));
956
957 pw.print(indent);
958 pw.print("Temp whitelist appids: ");
959 pw.println(Arrays.toString(mTempWhitelistedAppIds));
960
961 pw.print(indent);
962 pw.println("Restricted packages:");
963 for (Pair<Integer, String> uidAndPackage : mRunAnyRestrictedPackages) {
964 pw.print(indent);
965 pw.print(" ");
966 pw.print(UserHandle.formatUid(uidAndPackage.first));
967 pw.print(" ");
968 pw.print(uidAndPackage.second);
969 pw.println();
970 }
971 }
972 }
973
974 public void dumpProto(ProtoOutputStream proto, long fieldId) {
975 synchronized (mLock) {
976 final long token = proto.start(fieldId);
977
978 proto.write(ForceAppStandbyTrackerProto.FORCE_ALL_APPS_STANDBY, mForceAllAppsStandby);
Nancy Zheng525aaa12018-01-12 11:45:37 -0800979 proto.write(ForceAppStandbyTrackerProto.IS_SMALL_BATTERY_DEVICE,
980 isSmallBatteryDevice());
981 proto.write(ForceAppStandbyTrackerProto.FORCE_ALL_APPS_STANDBY_FOR_SMALL_BATTERY,
982 mForceAllAppStandbyForSmallBattery);
983 proto.write(ForceAppStandbyTrackerProto.IS_CHARGING, mIsPluggedIn);
Makoto Onuki2206af32017-11-21 16:25:35 -0800984
985 for (int i = 0; i < mForegroundUids.size(); i++) {
986 if (mForegroundUids.valueAt(i)) {
987 proto.write(ForceAppStandbyTrackerProto.FOREGROUND_UIDS,
988 mForegroundUids.keyAt(i));
989 }
990 }
991
992 for (int appId : mPowerWhitelistedAllAppIds) {
993 proto.write(ForceAppStandbyTrackerProto.POWER_SAVE_WHITELIST_APP_IDS, appId);
994 }
995
996 for (int appId : mTempWhitelistedAppIds) {
997 proto.write(ForceAppStandbyTrackerProto.TEMP_POWER_SAVE_WHITELIST_APP_IDS, appId);
998 }
999
1000 for (Pair<Integer, String> uidAndPackage : mRunAnyRestrictedPackages) {
1001 final long token2 = proto.start(
1002 ForceAppStandbyTrackerProto.RUN_ANY_IN_BACKGROUND_RESTRICTED_PACKAGES);
1003 proto.write(RunAnyInBackgroundRestrictedPackages.UID, uidAndPackage.first);
1004 proto.write(RunAnyInBackgroundRestrictedPackages.PACKAGE_NAME,
1005 uidAndPackage.second);
1006 proto.end(token2);
1007 }
1008 proto.end(token);
Makoto Onuki9be01402017-11-10 13:22:26 -08001009 }
1010 }
1011}