blob: b68bf2db12379d2e552a11c0d9906abc8cca62f9 [file] [log] [blame]
Makoto Onuki2206af32017-11-21 16:25:35 -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
Makoto Onuki15407842018-01-19 14:23:11 -080018import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY;
19
Makoto Onuki2206af32017-11-21 16:25:35 -080020import static com.android.server.ForceAppStandbyTracker.TARGET_OP;
21
22import static org.junit.Assert.assertEquals;
23import static org.junit.Assert.assertFalse;
24import static org.junit.Assert.assertNotNull;
25import static org.junit.Assert.assertTrue;
26import static org.mockito.ArgumentMatchers.any;
27import static org.mockito.ArgumentMatchers.anyInt;
28import static org.mockito.ArgumentMatchers.anyString;
29import static org.mockito.ArgumentMatchers.eq;
30import static org.mockito.ArgumentMatchers.isNull;
31import static org.mockito.Mockito.mock;
32import static org.mockito.Mockito.reset;
33import static org.mockito.Mockito.times;
34import static org.mockito.Mockito.verify;
35import static org.mockito.Mockito.when;
36
37import android.app.ActivityManager;
Makoto Onuki15407842018-01-19 14:23:11 -080038import android.app.ActivityManagerInternal;
Makoto Onuki2206af32017-11-21 16:25:35 -080039import android.app.AppOpsManager;
40import android.app.AppOpsManager.OpEntry;
41import android.app.AppOpsManager.PackageOps;
42import android.app.IActivityManager;
43import android.app.IUidObserver;
44import android.content.BroadcastReceiver;
45import android.content.Context;
46import android.content.Intent;
47import android.content.IntentFilter;
Nancy Zheng525aaa12018-01-12 11:45:37 -080048import android.os.BatteryManager;
Makoto Onuki2206af32017-11-21 16:25:35 -080049import android.os.Handler;
50import android.os.Looper;
51import android.os.PowerManager.ServiceType;
52import android.os.PowerManagerInternal;
53import android.os.PowerSaveState;
54import android.os.Process;
55import android.os.RemoteException;
56import android.os.UserHandle;
Nancy Zhenga18c1f12018-01-18 16:29:59 -080057import android.provider.Settings;
Nancy Zheng525aaa12018-01-12 11:45:37 -080058import android.provider.Settings.Global;
Makoto Onuki2206af32017-11-21 16:25:35 -080059import android.support.test.filters.SmallTest;
60import android.support.test.runner.AndroidJUnit4;
Nancy Zhenga18c1f12018-01-18 16:29:59 -080061import android.test.mock.MockContentResolver;
Makoto Onuki2206af32017-11-21 16:25:35 -080062import android.util.ArraySet;
63import android.util.Pair;
64
65import com.android.internal.app.IAppOpsCallback;
66import com.android.internal.app.IAppOpsService;
Nancy Zhenga18c1f12018-01-18 16:29:59 -080067import com.android.internal.util.test.FakeSettingsProvider;
Makoto Onuki2206af32017-11-21 16:25:35 -080068import com.android.server.ForceAppStandbyTracker.Listener;
69
70import org.junit.Before;
71import org.junit.Test;
72import org.junit.runner.RunWith;
73import org.mockito.ArgumentCaptor;
74import org.mockito.Mock;
75import org.mockito.MockitoAnnotations;
76
77import java.util.ArrayList;
78import java.util.Arrays;
79import java.util.List;
80import java.util.Random;
81import java.util.concurrent.CountDownLatch;
82import java.util.concurrent.TimeUnit;
83import java.util.function.Consumer;
84
85@SmallTest
86@RunWith(AndroidJUnit4.class)
87public class ForceAppStandbyTrackerTest {
88
89 private class ForceAppStandbyTrackerTestable extends ForceAppStandbyTracker {
90 ForceAppStandbyTrackerTestable() {
91 super(mMockContext, Looper.getMainLooper());
92 }
93
94 @Override
95 AppOpsManager injectAppOpsManager() {
96 return mMockAppOpsManager;
97 }
98
99 @Override
100 IAppOpsService injectIAppOpsService() {
101 return mMockIAppOpsService;
102 }
103
104 @Override
105 IActivityManager injectIActivityManager() {
106 return mMockIActivityManager;
107 }
108
109 @Override
110 PowerManagerInternal injectPowerManagerInternal() {
111 return mMockPowerManagerInternal;
112 }
Nancy Zheng525aaa12018-01-12 11:45:37 -0800113
114 @Override
115 boolean isSmallBatteryDevice() { return mIsSmallBatteryDevice; };
Makoto Onuki2206af32017-11-21 16:25:35 -0800116 }
117
118 private static final int UID_1 = Process.FIRST_APPLICATION_UID + 1;
119 private static final int UID_2 = Process.FIRST_APPLICATION_UID + 2;
120 private static final int UID_3 = Process.FIRST_APPLICATION_UID + 3;
121 private static final int UID_10_1 = UserHandle.getUid(10, UID_1);
122 private static final int UID_10_2 = UserHandle.getUid(10, UID_2);
123 private static final int UID_10_3 = UserHandle.getUid(10, UID_3);
124 private static final String PACKAGE_1 = "package1";
125 private static final String PACKAGE_2 = "package2";
126 private static final String PACKAGE_3 = "package3";
127 private static final String PACKAGE_SYSTEM = "android";
128
129 private Handler mMainHandler;
130
131 @Mock
132 private Context mMockContext;
133
134 @Mock
135 private IActivityManager mMockIActivityManager;
136
137 @Mock
138 private AppOpsManager mMockAppOpsManager;
139
140 @Mock
141 private IAppOpsService mMockIAppOpsService;
142
143 @Mock
144 private PowerManagerInternal mMockPowerManagerInternal;
145
146 private IUidObserver mIUidObserver;
147 private IAppOpsCallback.Stub mAppOpsCallback;
148 private Consumer<PowerSaveState> mPowerSaveObserver;
149 private BroadcastReceiver mReceiver;
150
Nancy Zhenga18c1f12018-01-18 16:29:59 -0800151 private MockContentResolver mMockContentResolver;
152 private FakeSettingsProvider mFakeSettingsProvider;
153
Makoto Onuki2206af32017-11-21 16:25:35 -0800154 private boolean mPowerSaveMode;
Nancy Zheng525aaa12018-01-12 11:45:37 -0800155 private boolean mIsSmallBatteryDevice;
Makoto Onuki2206af32017-11-21 16:25:35 -0800156
157 private final ArraySet<Pair<Integer, String>> mRestrictedPackages = new ArraySet();
158
159 @Before
160 public void setUp() {
161 mMainHandler = new Handler(Looper.getMainLooper());
162 }
163
164 private void waitUntilMainHandlerDrain() throws Exception {
165 final CountDownLatch l = new CountDownLatch(1);
166 mMainHandler.post(() -> {
167 l.countDown();
168 });
169 assertTrue(l.await(5, TimeUnit.SECONDS));
170 }
171
172 private PowerSaveState getPowerSaveState() {
173 return new PowerSaveState.Builder().setBatterySaverEnabled(mPowerSaveMode).build();
174 }
175
176 private ForceAppStandbyTrackerTestable newInstance() throws Exception {
177 MockitoAnnotations.initMocks(this);
178
179 when(mMockIAppOpsService.checkOperation(eq(TARGET_OP), anyInt(), anyString()))
180 .thenAnswer(inv -> {
181 return mRestrictedPackages.indexOf(
182 Pair.create(inv.getArgument(1), inv.getArgument(2))) >= 0 ?
183 AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED;
184 });
185
186 final ForceAppStandbyTrackerTestable instance = new ForceAppStandbyTrackerTestable();
187
188 return instance;
189 }
190
191 private void callStart(ForceAppStandbyTrackerTestable instance) throws RemoteException {
Makoto Onuki12391f22018-01-18 21:44:28 +0000192
Makoto Onuki2206af32017-11-21 16:25:35 -0800193 // Set up functions that start() calls.
194 when(mMockPowerManagerInternal.getLowPowerState(eq(ServiceType.FORCE_ALL_APPS_STANDBY)))
195 .thenAnswer(inv -> getPowerSaveState());
196 when(mMockAppOpsManager.getPackagesForOps(
197 any(int[].class)
Makoto Onuki12391f22018-01-18 21:44:28 +0000198 )).thenAnswer(inv -> new ArrayList<AppOpsManager.PackageOps>());
Makoto Onuki2206af32017-11-21 16:25:35 -0800199
Nancy Zhenga18c1f12018-01-18 16:29:59 -0800200 mMockContentResolver = new MockContentResolver();
201 mFakeSettingsProvider = new FakeSettingsProvider();
202 when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
203 mMockContentResolver.addProvider(Settings.AUTHORITY, mFakeSettingsProvider);
204
Makoto Onuki2206af32017-11-21 16:25:35 -0800205 // Call start.
206 instance.start();
207
208 // Capture the listeners.
209 ArgumentCaptor<IUidObserver> uidObserverArgumentCaptor =
210 ArgumentCaptor.forClass(IUidObserver.class);
211 ArgumentCaptor<IAppOpsCallback.Stub> appOpsCallbackCaptor =
212 ArgumentCaptor.forClass(IAppOpsCallback.Stub.class);
213 ArgumentCaptor<Consumer<PowerSaveState>> powerSaveObserverCaptor =
214 ArgumentCaptor.forClass(Consumer.class);
215 ArgumentCaptor<BroadcastReceiver> receiverCaptor =
216 ArgumentCaptor.forClass(BroadcastReceiver.class);
217
218 verify(mMockIActivityManager).registerUidObserver(
219 uidObserverArgumentCaptor.capture(),
220 eq(ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE
221 | ActivityManager.UID_OBSERVER_ACTIVE),
222 eq(ActivityManager.PROCESS_STATE_UNKNOWN),
223 isNull());
224 verify(mMockIAppOpsService).startWatchingMode(
225 eq(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND),
226 isNull(),
227 appOpsCallbackCaptor.capture());
228 verify(mMockPowerManagerInternal).registerLowPowerModeObserver(
229 eq(ServiceType.FORCE_ALL_APPS_STANDBY),
230 powerSaveObserverCaptor.capture());
Makoto Onuki12391f22018-01-18 21:44:28 +0000231
Makoto Onuki2206af32017-11-21 16:25:35 -0800232 verify(mMockContext).registerReceiver(
233 receiverCaptor.capture(), any(IntentFilter.class));
234
235 mIUidObserver = uidObserverArgumentCaptor.getValue();
236 mAppOpsCallback = appOpsCallbackCaptor.getValue();
237 mPowerSaveObserver = powerSaveObserverCaptor.getValue();
238 mReceiver = receiverCaptor.getValue();
239
240 assertNotNull(mIUidObserver);
241 assertNotNull(mAppOpsCallback);
242 assertNotNull(mPowerSaveObserver);
243 assertNotNull(mReceiver);
Nancy Zheng525aaa12018-01-12 11:45:37 -0800244 assertNotNull(instance.mFlagsObserver);
Makoto Onuki2206af32017-11-21 16:25:35 -0800245 }
246
247 private void setAppOps(int uid, String packageName, boolean restrict) throws RemoteException {
248 final Pair p = Pair.create(uid, packageName);
249 if (restrict) {
250 mRestrictedPackages.add(p);
251 } else {
252 mRestrictedPackages.remove(p);
253 }
254 if (mAppOpsCallback != null) {
255 mAppOpsCallback.opChanged(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uid, packageName);
256 }
257 }
258
259 private static final int NONE = 0;
260 private static final int ALARMS_ONLY = 1 << 0;
261 private static final int JOBS_ONLY = 1 << 1;
262 private static final int JOBS_AND_ALARMS = ALARMS_ONLY | JOBS_ONLY;
263
264 private void areRestricted(ForceAppStandbyTrackerTestable instance, int uid, String packageName,
Makoto Onuki15407842018-01-19 14:23:11 -0800265 int restrictionTypes, boolean exemptFromBatterySaver) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800266 assertEquals(((restrictionTypes & JOBS_ONLY) != 0),
Makoto Onuki15407842018-01-19 14:23:11 -0800267 instance.areJobsRestricted(uid, packageName, exemptFromBatterySaver));
Makoto Onuki2206af32017-11-21 16:25:35 -0800268 assertEquals(((restrictionTypes & ALARMS_ONLY) != 0),
Suprabh Shuklac25447d2018-01-19 16:43:35 -0800269 instance.areAlarmsRestricted(uid, packageName, exemptFromBatterySaver));
Makoto Onuki2206af32017-11-21 16:25:35 -0800270 }
271
Makoto Onuki15407842018-01-19 14:23:11 -0800272 private void areRestricted(ForceAppStandbyTrackerTestable instance, int uid, String packageName,
273 int restrictionTypes) {
274 areRestricted(instance, uid, packageName, restrictionTypes,
275 /*exemptFromBatterySaver=*/ false);
276 }
277
Makoto Onuki2206af32017-11-21 16:25:35 -0800278 @Test
279 public void testAll() throws Exception {
280 final ForceAppStandbyTrackerTestable instance = newInstance();
281 callStart(instance);
282
283 assertFalse(instance.isForceAllAppsStandbyEnabled());
284 areRestricted(instance, UID_1, PACKAGE_1, NONE);
285 areRestricted(instance, UID_2, PACKAGE_2, NONE);
286 areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
287
288 mPowerSaveMode = true;
289 mPowerSaveObserver.accept(getPowerSaveState());
290
291 assertTrue(instance.isForceAllAppsStandbyEnabled());
292
293 areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
294 areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
295 areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
296
297 // Toggle the foreground state.
298 mPowerSaveMode = true;
299 mPowerSaveObserver.accept(getPowerSaveState());
300
301 assertFalse(instance.isInForeground(UID_1));
302 assertFalse(instance.isInForeground(UID_2));
303 assertTrue(instance.isInForeground(Process.SYSTEM_UID));
304
305 mIUidObserver.onUidActive(UID_1);
306 areRestricted(instance, UID_1, PACKAGE_1, NONE);
307 areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
308 areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
309 assertTrue(instance.isInForeground(UID_1));
310 assertFalse(instance.isInForeground(UID_2));
311
312 mIUidObserver.onUidGone(UID_1, /*disable=*/ false);
313 areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
314 areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
315 areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
316 assertFalse(instance.isInForeground(UID_1));
317 assertFalse(instance.isInForeground(UID_2));
318
319 mIUidObserver.onUidActive(UID_1);
320 areRestricted(instance, UID_1, PACKAGE_1, NONE);
321 areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
322 areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
323
324 mIUidObserver.onUidIdle(UID_1, /*disable=*/ false);
325 areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
326 areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
327 areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
328 assertFalse(instance.isInForeground(UID_1));
329 assertFalse(instance.isInForeground(UID_2));
330
331 // Toggle the app ops.
332 mPowerSaveMode = false;
333 mPowerSaveObserver.accept(getPowerSaveState());
334
335 assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_1, PACKAGE_1));
336 assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_10_1, PACKAGE_1));
337 assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_2, PACKAGE_2));
338 assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_10_2, PACKAGE_2));
339
340 areRestricted(instance, UID_1, PACKAGE_1, NONE);
341 areRestricted(instance, UID_10_1, PACKAGE_1, NONE);
342 areRestricted(instance, UID_2, PACKAGE_2, NONE);
343 areRestricted(instance, UID_10_2, PACKAGE_2, NONE);
344 areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
345
346 setAppOps(UID_1, PACKAGE_1, true);
347 setAppOps(UID_10_2, PACKAGE_2, true);
348 assertFalse(instance.isRunAnyInBackgroundAppOpsAllowed(UID_1, PACKAGE_1));
349 assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_10_1, PACKAGE_1));
350 assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_2, PACKAGE_2));
351 assertFalse(instance.isRunAnyInBackgroundAppOpsAllowed(UID_10_2, PACKAGE_2));
352
353 areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
354 areRestricted(instance, UID_10_1, PACKAGE_1, NONE);
355 areRestricted(instance, UID_2, PACKAGE_2, NONE);
356 areRestricted(instance, UID_10_2, PACKAGE_2, JOBS_AND_ALARMS);
357 areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
358
359 // Toggle power saver, should still be the same.
360 mPowerSaveMode = true;
361 mPowerSaveObserver.accept(getPowerSaveState());
362
363 mPowerSaveMode = false;
364 mPowerSaveObserver.accept(getPowerSaveState());
365
366 areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
367 areRestricted(instance, UID_10_1, PACKAGE_1, NONE);
368 areRestricted(instance, UID_2, PACKAGE_2, NONE);
369 areRestricted(instance, UID_10_2, PACKAGE_2, JOBS_AND_ALARMS);
370 areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
371
372 // Clear the app ops and update the whitelist.
373 setAppOps(UID_1, PACKAGE_1, false);
374 setAppOps(UID_10_2, PACKAGE_2, false);
375
376 mPowerSaveMode = true;
377 mPowerSaveObserver.accept(getPowerSaveState());
378
379 areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
380 areRestricted(instance, UID_10_1, PACKAGE_1, JOBS_AND_ALARMS);
381 areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
382 areRestricted(instance, UID_10_2, PACKAGE_2, JOBS_AND_ALARMS);
383 areRestricted(instance, UID_3, PACKAGE_3, JOBS_AND_ALARMS);
384 areRestricted(instance, UID_10_3, PACKAGE_3, JOBS_AND_ALARMS);
385 areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
386
387 instance.setPowerSaveWhitelistAppIds(new int[] {UID_1}, new int[] {UID_2});
388
389 areRestricted(instance, UID_1, PACKAGE_1, NONE);
390 areRestricted(instance, UID_10_1, PACKAGE_1, NONE);
391 areRestricted(instance, UID_2, PACKAGE_2, ALARMS_ONLY);
392 areRestricted(instance, UID_10_2, PACKAGE_2, ALARMS_ONLY);
393 areRestricted(instance, UID_3, PACKAGE_3, JOBS_AND_ALARMS);
394 areRestricted(instance, UID_10_3, PACKAGE_3, JOBS_AND_ALARMS);
395 areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
396
397 // Again, make sure toggling the global state doesn't change it.
398 mPowerSaveMode = false;
399 mPowerSaveObserver.accept(getPowerSaveState());
400
401 mPowerSaveMode = true;
402 mPowerSaveObserver.accept(getPowerSaveState());
403
404 areRestricted(instance, UID_1, PACKAGE_1, NONE);
405 areRestricted(instance, UID_10_1, PACKAGE_1, NONE);
406 areRestricted(instance, UID_2, PACKAGE_2, ALARMS_ONLY);
407 areRestricted(instance, UID_10_2, PACKAGE_2, ALARMS_ONLY);
408 areRestricted(instance, UID_3, PACKAGE_3, JOBS_AND_ALARMS);
409 areRestricted(instance, UID_10_3, PACKAGE_3, JOBS_AND_ALARMS);
410 areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
411
412 assertTrue(instance.isUidPowerSaveWhitelisted(UID_1));
413 assertTrue(instance.isUidPowerSaveWhitelisted(UID_10_1));
414 assertFalse(instance.isUidPowerSaveWhitelisted(UID_2));
415 assertFalse(instance.isUidPowerSaveWhitelisted(UID_10_2));
416
417 assertFalse(instance.isUidTempPowerSaveWhitelisted(UID_1));
418 assertFalse(instance.isUidTempPowerSaveWhitelisted(UID_10_1));
419 assertTrue(instance.isUidTempPowerSaveWhitelisted(UID_2));
420 assertTrue(instance.isUidTempPowerSaveWhitelisted(UID_10_2));
421 }
422
423 public void loadPersistedAppOps() throws Exception {
424 final ForceAppStandbyTrackerTestable instance = newInstance();
425
426 final List<PackageOps> ops = new ArrayList<>();
427
428 //--------------------------------------------------
429 List<OpEntry> entries = new ArrayList<>();
430 entries.add(new AppOpsManager.OpEntry(
431 AppOpsManager.OP_ACCESS_NOTIFICATIONS,
432 AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
433 entries.add(new AppOpsManager.OpEntry(
434 ForceAppStandbyTracker.TARGET_OP,
435 AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
436
437 ops.add(new PackageOps(PACKAGE_1, UID_1, entries));
438
439 //--------------------------------------------------
440 entries = new ArrayList<>();
441 entries.add(new AppOpsManager.OpEntry(
442 ForceAppStandbyTracker.TARGET_OP,
443 AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
444
445 ops.add(new PackageOps(PACKAGE_2, UID_2, entries));
446
447 //--------------------------------------------------
448 entries = new ArrayList<>();
449 entries.add(new AppOpsManager.OpEntry(
450 ForceAppStandbyTracker.TARGET_OP,
451 AppOpsManager.MODE_ALLOWED, 0, 0, 0, 0, null));
452
453 ops.add(new PackageOps(PACKAGE_1, UID_10_1, entries));
454
455 //--------------------------------------------------
456 entries = new ArrayList<>();
457 entries.add(new AppOpsManager.OpEntry(
458 ForceAppStandbyTracker.TARGET_OP,
459 AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
460 entries.add(new AppOpsManager.OpEntry(
461 AppOpsManager.OP_ACCESS_NOTIFICATIONS,
462 AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
463
464 ops.add(new PackageOps(PACKAGE_3, UID_10_3, entries));
465
466 callStart(instance);
467
468 assertFalse(instance.isRunAnyInBackgroundAppOpsAllowed(UID_1, PACKAGE_1));
469 assertFalse(instance.isRunAnyInBackgroundAppOpsAllowed(UID_2, PACKAGE_2));
470 assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_3, PACKAGE_3));
471
472 assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_10_1, PACKAGE_1));
473 assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_10_2, PACKAGE_2));
474 assertFalse(instance.isRunAnyInBackgroundAppOpsAllowed(UID_10_3, PACKAGE_3));
475 }
476
477 private void assertNoCallbacks(Listener l) throws Exception {
478 waitUntilMainHandlerDrain();
479 verify(l, times(0)).updateAllJobs();
480 verify(l, times(0)).updateJobsForUid(anyInt());
481 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
482
483 verify(l, times(0)).unblockAllUnrestrictedAlarms();
484 verify(l, times(0)).unblockAlarmsForUid(anyInt());
485 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
486 reset(l);
487 }
488
489 @Test
490 public void testPowerSaveListener() throws Exception {
491 final ForceAppStandbyTrackerTestable instance = newInstance();
492 callStart(instance);
493
494 ForceAppStandbyTracker.Listener l = mock(ForceAppStandbyTracker.Listener.class);
495 instance.addListener(l);
496
497 // Power save on.
498 mPowerSaveMode = true;
499 mPowerSaveObserver.accept(getPowerSaveState());
500
501 waitUntilMainHandlerDrain();
502 verify(l, times(1)).updateAllJobs();
503 verify(l, times(0)).updateJobsForUid(anyInt());
504 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
505
506 verify(l, times(0)).unblockAllUnrestrictedAlarms();
507 verify(l, times(0)).unblockAlarmsForUid(anyInt());
508 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
509 reset(l);
510
511 // Power save off.
512 mPowerSaveMode = false;
513 mPowerSaveObserver.accept(getPowerSaveState());
514
515 waitUntilMainHandlerDrain();
516 verify(l, times(1)).updateAllJobs();
517 verify(l, times(0)).updateJobsForUid(anyInt());
518 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
519
520 verify(l, times(1)).unblockAllUnrestrictedAlarms();
521 verify(l, times(0)).unblockAlarmsForUid(anyInt());
522 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
523 reset(l);
524
Nancy Zhenga18c1f12018-01-18 16:29:59 -0800525 // Updating to the same state should not fire listener
526 mPowerSaveMode = false;
Makoto Onuki2206af32017-11-21 16:25:35 -0800527 mPowerSaveObserver.accept(getPowerSaveState());
528
529 assertNoCallbacks(l);
530 }
531
532 @Test
533 public void testAllListeners() throws Exception {
534 final ForceAppStandbyTrackerTestable instance = newInstance();
535 callStart(instance);
536
537 ForceAppStandbyTracker.Listener l = mock(ForceAppStandbyTracker.Listener.class);
538 instance.addListener(l);
539
540 // -------------------------------------------------------------------------
541 // Test with apppops.
542
543 setAppOps(UID_10_2, PACKAGE_2, true);
544
545 waitUntilMainHandlerDrain();
546 verify(l, times(0)).updateAllJobs();
547 verify(l, times(0)).updateJobsForUid(anyInt());
548 verify(l, times(1)).updateJobsForUidPackage(eq(UID_10_2), eq(PACKAGE_2));
549
550 verify(l, times(0)).unblockAllUnrestrictedAlarms();
551 verify(l, times(0)).unblockAlarmsForUid(anyInt());
552 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
553 reset(l);
554
555 setAppOps(UID_10_2, PACKAGE_2, false);
556
557 waitUntilMainHandlerDrain();
558 verify(l, times(0)).updateAllJobs();
559 verify(l, times(0)).updateJobsForUid(anyInt());
560 verify(l, times(1)).updateJobsForUidPackage(eq(UID_10_2), eq(PACKAGE_2));
561
562 verify(l, times(0)).unblockAllUnrestrictedAlarms();
563 verify(l, times(0)).unblockAlarmsForUid(anyInt());
Nancy Zhenga18c1f12018-01-18 16:29:59 -0800564 verify(l, times(1)).unblockAlarmsForUidPackage(eq(UID_10_2), eq(PACKAGE_2));
Makoto Onuki2206af32017-11-21 16:25:35 -0800565 reset(l);
566
567 setAppOps(UID_10_2, PACKAGE_2, false);
568
569 verify(l, times(0)).updateAllJobs();
570 verify(l, times(0)).updateJobsForUid(anyInt());
Nancy Zhenga18c1f12018-01-18 16:29:59 -0800571 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
Makoto Onuki2206af32017-11-21 16:25:35 -0800572
573 verify(l, times(0)).unblockAllUnrestrictedAlarms();
574 verify(l, times(0)).unblockAlarmsForUid(anyInt());
575 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
576
577 // Unrestrict while battery saver is on. Shouldn't fire.
578 mPowerSaveMode = true;
579 mPowerSaveObserver.accept(getPowerSaveState());
580
581 // Note toggling appops while BS is on will suppress unblockAlarmsForUidPackage().
582 setAppOps(UID_10_2, PACKAGE_2, true);
583
584 waitUntilMainHandlerDrain();
585 verify(l, times(1)).updateAllJobs();
586 verify(l, times(0)).updateJobsForUid(anyInt());
587 verify(l, times(1)).updateJobsForUidPackage(eq(UID_10_2), eq(PACKAGE_2));
588
589 verify(l, times(0)).unblockAllUnrestrictedAlarms();
590 verify(l, times(0)).unblockAlarmsForUid(anyInt());
591 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
592 reset(l);
593
594 // Battery saver off.
595 mPowerSaveMode = false;
596 mPowerSaveObserver.accept(getPowerSaveState());
597
598 waitUntilMainHandlerDrain();
599 verify(l, times(1)).updateAllJobs();
600 verify(l, times(0)).updateJobsForUid(anyInt());
601 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
602
603 verify(l, times(1)).unblockAllUnrestrictedAlarms();
604 verify(l, times(0)).unblockAlarmsForUid(anyInt());
605 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
606 reset(l);
607
608 // -------------------------------------------------------------------------
609 // Tests with system/user/temp whitelist.
610
611 instance.setPowerSaveWhitelistAppIds(new int[] {UID_1, UID_2}, new int[] {});
612
613 waitUntilMainHandlerDrain();
614 verify(l, times(1)).updateAllJobs();
615 verify(l, times(0)).updateJobsForUid(anyInt());
616 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
617
618 verify(l, times(0)).unblockAllUnrestrictedAlarms();
619 verify(l, times(0)).unblockAlarmsForUid(anyInt());
620 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
621 reset(l);
622
623 instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {});
624
625 waitUntilMainHandlerDrain();
626 verify(l, times(1)).updateAllJobs();
627 verify(l, times(0)).updateJobsForUid(anyInt());
628 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
629
630 verify(l, times(1)).unblockAllUnrestrictedAlarms();
631 verify(l, times(0)).unblockAlarmsForUid(anyInt());
632 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
633 reset(l);
634
635 // Update temp whitelist.
636 instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {UID_1, UID_3});
637
638 waitUntilMainHandlerDrain();
639 verify(l, times(1)).updateAllJobs();
640 verify(l, times(0)).updateJobsForUid(anyInt());
641 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
642
643 verify(l, times(0)).unblockAllUnrestrictedAlarms();
644 verify(l, times(0)).unblockAlarmsForUid(anyInt());
645 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
646 reset(l);
647
648 instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {UID_3});
649
650 waitUntilMainHandlerDrain();
651 verify(l, times(1)).updateAllJobs();
652 verify(l, times(0)).updateJobsForUid(anyInt());
653 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
654
655 verify(l, times(0)).unblockAllUnrestrictedAlarms();
656 verify(l, times(0)).unblockAlarmsForUid(anyInt());
657 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
658 reset(l);
659
660 // Do the same thing with battery saver on. (Currently same callbacks are called.)
661 mPowerSaveMode = true;
662 mPowerSaveObserver.accept(getPowerSaveState());
663
Nancy Zhenga18c1f12018-01-18 16:29:59 -0800664 verify(l, times(1)).updateAllJobs();
665 verify(l, times(0)).updateJobsForUid(anyInt());
666 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
667
668 verify(l, times(0)).unblockAllUnrestrictedAlarms();
669 verify(l, times(0)).unblockAlarmsForUid(anyInt());
670 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
671 reset(l);
672
Makoto Onuki2206af32017-11-21 16:25:35 -0800673 instance.setPowerSaveWhitelistAppIds(new int[] {UID_1, UID_2}, new int[] {});
674
675 waitUntilMainHandlerDrain();
Nancy Zhenga18c1f12018-01-18 16:29:59 -0800676 // Called once for updating all whitelist and once for updating temp whitelist
677 verify(l, times(2)).updateAllJobs();
Makoto Onuki2206af32017-11-21 16:25:35 -0800678 verify(l, times(0)).updateJobsForUid(anyInt());
679 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
680
681 verify(l, times(0)).unblockAllUnrestrictedAlarms();
682 verify(l, times(0)).unblockAlarmsForUid(anyInt());
683 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
684 reset(l);
685
686 instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {});
687
688 waitUntilMainHandlerDrain();
689 verify(l, times(1)).updateAllJobs();
690 verify(l, times(0)).updateJobsForUid(anyInt());
691 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
692
693 verify(l, times(1)).unblockAllUnrestrictedAlarms();
694 verify(l, times(0)).unblockAlarmsForUid(anyInt());
695 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
696 reset(l);
697
698 // Update temp whitelist.
699 instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {UID_1, UID_3});
700
701 waitUntilMainHandlerDrain();
702 verify(l, times(1)).updateAllJobs();
703 verify(l, times(0)).updateJobsForUid(anyInt());
704 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
705
706 verify(l, times(0)).unblockAllUnrestrictedAlarms();
707 verify(l, times(0)).unblockAlarmsForUid(anyInt());
708 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
709 reset(l);
710
711 instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {UID_3});
712
713 waitUntilMainHandlerDrain();
714 verify(l, times(1)).updateAllJobs();
715 verify(l, times(0)).updateJobsForUid(anyInt());
716 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
717
718 verify(l, times(0)).unblockAllUnrestrictedAlarms();
719 verify(l, times(0)).unblockAlarmsForUid(anyInt());
720 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
721 reset(l);
722
723
724 // -------------------------------------------------------------------------
725 // Tests with proc state changes.
726
727 // With battery save.
728 mPowerSaveMode = true;
729 mPowerSaveObserver.accept(getPowerSaveState());
730
731 mIUidObserver.onUidActive(UID_10_1);
732
733 waitUntilMainHandlerDrain();
734 verify(l, times(0)).updateAllJobs();
735 verify(l, times(1)).updateJobsForUid(eq(UID_10_1));
736 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
737
738 verify(l, times(0)).unblockAllUnrestrictedAlarms();
Nancy Zhenga18c1f12018-01-18 16:29:59 -0800739 verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
Makoto Onuki2206af32017-11-21 16:25:35 -0800740 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
741 reset(l);
742
743 mIUidObserver.onUidGone(UID_10_1, true);
744
745 waitUntilMainHandlerDrain();
746 verify(l, times(0)).updateAllJobs();
747 verify(l, times(1)).updateJobsForUid(eq(UID_10_1));
748 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
749
750 verify(l, times(0)).unblockAllUnrestrictedAlarms();
751 verify(l, times(0)).unblockAlarmsForUid(anyInt());
752 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
753 reset(l);
754
755 mIUidObserver.onUidActive(UID_10_1);
756
757 waitUntilMainHandlerDrain();
758 verify(l, times(0)).updateAllJobs();
759 verify(l, times(1)).updateJobsForUid(eq(UID_10_1));
760 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
761
762 verify(l, times(0)).unblockAllUnrestrictedAlarms();
Nancy Zhenga18c1f12018-01-18 16:29:59 -0800763 verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
Makoto Onuki2206af32017-11-21 16:25:35 -0800764 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
765 reset(l);
766
767 mIUidObserver.onUidIdle(UID_10_1, true);
768
769 waitUntilMainHandlerDrain();
770 verify(l, times(0)).updateAllJobs();
771 verify(l, times(1)).updateJobsForUid(eq(UID_10_1));
772 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
773
774 verify(l, times(0)).unblockAllUnrestrictedAlarms();
775 verify(l, times(0)).unblockAlarmsForUid(anyInt());
776 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
777 reset(l);
778
779 // Without battery save.
780 mPowerSaveMode = false;
781 mPowerSaveObserver.accept(getPowerSaveState());
782
Nancy Zhenga18c1f12018-01-18 16:29:59 -0800783 verify(l, times(1)).updateAllJobs();
784 verify(l, times(0)).updateJobsForUid(eq(UID_10_1));
785 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
786
787 verify(l, times(1)).unblockAllUnrestrictedAlarms();
788 verify(l, times(0)).unblockAlarmsForUid(anyInt());
789 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
790 reset(l);
791
Makoto Onuki2206af32017-11-21 16:25:35 -0800792 mIUidObserver.onUidActive(UID_10_1);
793
794 waitUntilMainHandlerDrain();
795 verify(l, times(0)).updateAllJobs();
796 verify(l, times(1)).updateJobsForUid(eq(UID_10_1));
797 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
798
799 verify(l, times(0)).unblockAllUnrestrictedAlarms();
Nancy Zhenga18c1f12018-01-18 16:29:59 -0800800 verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
Makoto Onuki2206af32017-11-21 16:25:35 -0800801 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
802 reset(l);
803
804 mIUidObserver.onUidGone(UID_10_1, true);
805
806 waitUntilMainHandlerDrain();
807 verify(l, times(0)).updateAllJobs();
808 verify(l, times(1)).updateJobsForUid(eq(UID_10_1));
809 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
810
811 verify(l, times(0)).unblockAllUnrestrictedAlarms();
812 verify(l, times(0)).unblockAlarmsForUid(anyInt());
813 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
814 reset(l);
815
816 mIUidObserver.onUidActive(UID_10_1);
817
818 waitUntilMainHandlerDrain();
819 verify(l, times(0)).updateAllJobs();
820 verify(l, times(1)).updateJobsForUid(eq(UID_10_1));
821 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
822
823 verify(l, times(0)).unblockAllUnrestrictedAlarms();
Nancy Zhenga18c1f12018-01-18 16:29:59 -0800824 verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
Makoto Onuki2206af32017-11-21 16:25:35 -0800825 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
826 reset(l);
827
828 mIUidObserver.onUidIdle(UID_10_1, true);
829
830 waitUntilMainHandlerDrain();
831 verify(l, times(0)).updateAllJobs();
832 verify(l, times(1)).updateJobsForUid(eq(UID_10_1));
833 verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
834
835 verify(l, times(0)).unblockAllUnrestrictedAlarms();
836 verify(l, times(0)).unblockAlarmsForUid(anyInt());
837 verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
838 reset(l);
839 }
840
841 @Test
842 public void testUserRemoved() throws Exception {
843 final ForceAppStandbyTrackerTestable instance = newInstance();
844 callStart(instance);
845
846 mIUidObserver.onUidActive(UID_1);
847 mIUidObserver.onUidActive(UID_10_1);
848
849 setAppOps(UID_2, PACKAGE_2, true);
850 setAppOps(UID_10_2, PACKAGE_2, true);
851
852 assertTrue(instance.isInForeground(UID_1));
853 assertTrue(instance.isInForeground(UID_10_1));
854
855 assertFalse(instance.isRunAnyInBackgroundAppOpsAllowed(UID_2, PACKAGE_2));
856 assertFalse(instance.isRunAnyInBackgroundAppOpsAllowed(UID_10_2, PACKAGE_2));
857
858 final Intent intent = new Intent(Intent.ACTION_USER_REMOVED);
859 intent.putExtra(Intent.EXTRA_USER_HANDLE, 10);
860 mReceiver.onReceive(mMockContext, intent);
861
862 waitUntilMainHandlerDrain();
863
864 assertTrue(instance.isInForeground(UID_1));
865 assertFalse(instance.isInForeground(UID_10_1));
866
867 assertFalse(instance.isRunAnyInBackgroundAppOpsAllowed(UID_2, PACKAGE_2));
868 assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_10_2, PACKAGE_2));
869 }
870
Nancy Zheng525aaa12018-01-12 11:45:37 -0800871 @Test
872 public void testSmallBatteryAndPluggedIn() throws Exception {
873 // This is a small battery device
874 mIsSmallBatteryDevice = true;
875
876 final ForceAppStandbyTrackerTestable instance = newInstance();
877 callStart(instance);
878 assertFalse(instance.isForceAllAppsStandbyEnabled());
879
880 // Setting/experiment for all app standby for small battery is enabled
881 Global.putInt(mMockContentResolver, Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED, 1);
882 instance.mFlagsObserver.onChange(true,
883 Global.getUriFor(Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED));
884 assertTrue(instance.isForceAllAppsStandbyEnabled());
885
886 // When battery is plugged in, force app standby is disabled
887 Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
888 intent.putExtra(BatteryManager.EXTRA_PLUGGED, BatteryManager.BATTERY_PLUGGED_USB);
889 mReceiver.onReceive(mMockContext, intent);
890 assertFalse(instance.isForceAllAppsStandbyEnabled());
891
892 // When battery stops plugged in, force app standby is enabled
893 mReceiver.onReceive(mMockContext, new Intent(Intent.ACTION_BATTERY_CHANGED));
894 assertTrue(instance.isForceAllAppsStandbyEnabled());
895 }
896
897 @Test
898 public void testNotSmallBatteryAndPluggedIn() throws Exception {
899 // Not a small battery device, so plugged in status should not affect forced app standby
900 mIsSmallBatteryDevice = false;
901
902 final ForceAppStandbyTrackerTestable instance = newInstance();
903 callStart(instance);
904 assertFalse(instance.isForceAllAppsStandbyEnabled());
905
906 mPowerSaveMode = true;
907 mPowerSaveObserver.accept(getPowerSaveState());
908 assertTrue(instance.isForceAllAppsStandbyEnabled());
909
910 // When battery is plugged in, force app standby is unaffected
911 Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
912 intent.putExtra(BatteryManager.EXTRA_PLUGGED, BatteryManager.BATTERY_PLUGGED_USB);
913 mReceiver.onReceive(mMockContext, intent);
914 assertTrue(instance.isForceAllAppsStandbyEnabled());
915
916 // When battery stops plugged in, force app standby is unaffected
917 mReceiver.onReceive(mMockContext, new Intent(Intent.ACTION_BATTERY_CHANGED));
918 assertTrue(instance.isForceAllAppsStandbyEnabled());
919 }
920
Makoto Onuki2206af32017-11-21 16:25:35 -0800921 static int[] array(int... appIds) {
922 Arrays.sort(appIds);
923 return appIds;
924 }
925
926 private final Random mRandom = new Random();
927
928 int[] makeRandomArray() {
929 final ArrayList<Integer> list = new ArrayList<>();
930 for (int i = 0; i < 5; i++) {
931 if (mRandom.nextDouble() < 0.5) {
932 list.add(i);
933 }
934 }
935 return Arrays.stream(list.toArray(new Integer[list.size()]))
936 .mapToInt(Integer::intValue).toArray();
937 }
938
939 static boolean isAnyAppIdUnwhitelistedSlow(int[] prevArray, int[] newArray) {
940 Arrays.sort(newArray); // Just in case...
941 for (int p : prevArray) {
942 if (Arrays.binarySearch(newArray, p) < 0) {
943 return true;
944 }
945 }
946 return false;
947 }
948
949 private void checkAnyAppIdUnwhitelisted(int[] prevArray, int[] newArray, boolean expected) {
950 assertEquals("Input: " + Arrays.toString(prevArray) + " " + Arrays.toString(newArray),
951 expected, ForceAppStandbyTracker.isAnyAppIdUnwhitelisted(prevArray, newArray));
952
953 // Also test isAnyAppIdUnwhitelistedSlow.
954 assertEquals("Input: " + Arrays.toString(prevArray) + " " + Arrays.toString(newArray),
955 expected, isAnyAppIdUnwhitelistedSlow(prevArray, newArray));
956 }
957
958 @Test
959 public void isAnyAppIdUnwhitelisted() {
960 checkAnyAppIdUnwhitelisted(array(), array(), false);
961
962 checkAnyAppIdUnwhitelisted(array(1), array(), true);
963 checkAnyAppIdUnwhitelisted(array(1), array(1), false);
964 checkAnyAppIdUnwhitelisted(array(1), array(0, 1), false);
965 checkAnyAppIdUnwhitelisted(array(1), array(0, 1, 2), false);
966 checkAnyAppIdUnwhitelisted(array(1), array(0, 1, 2), false);
967
968 checkAnyAppIdUnwhitelisted(array(1, 2, 10), array(), true);
969 checkAnyAppIdUnwhitelisted(array(1, 2, 10), array(1, 2), true);
970 checkAnyAppIdUnwhitelisted(array(1, 2, 10), array(1, 2, 10), false);
971 checkAnyAppIdUnwhitelisted(array(1, 2, 10), array(2, 10), true);
972 checkAnyAppIdUnwhitelisted(array(1, 2, 10), array(0, 1, 2, 4, 3, 10), false);
973 checkAnyAppIdUnwhitelisted(array(1, 2, 10), array(0, 0, 1, 2, 10), false);
974
975 // Random test
976 int trueCount = 0;
977 final int count = 10000;
978 for (int i = 0; i < count; i++) {
979 final int[] array1 = makeRandomArray();
980 final int[] array2 = makeRandomArray();
981
982 final boolean expected = isAnyAppIdUnwhitelistedSlow(array1, array2);
983 final boolean actual = ForceAppStandbyTracker.isAnyAppIdUnwhitelisted(array1, array2);
984
985 assertEquals("Input: " + Arrays.toString(array1) + " " + Arrays.toString(array2),
986 expected, actual);
987 if (expected) {
988 trueCount++;
989 }
990 }
991
992 // Make sure makeRandomArray() didn't generate all same arrays by accident.
993 assertTrue(trueCount > 0);
994 assertTrue(trueCount < count);
995 }
996}