• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.power;
18 
19 import static android.os.PowerManager.SCREEN_TIMEOUT_KEEP_DISPLAY_ON;
20 import static android.os.PowerManager.SCREEN_TIMEOUT_ACTIVE;
21 import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
22 import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
23 
24 import static com.google.common.truth.Truth.assertThat;
25 
26 import static org.junit.Assert.assertEquals;
27 import static org.junit.Assert.assertNotNull;
28 import static org.junit.Assert.assertNull;
29 import static org.mockito.ArgumentMatchers.any;
30 import static org.mockito.ArgumentMatchers.anyInt;
31 import static org.mockito.ArgumentMatchers.anyString;
32 import static org.mockito.ArgumentMatchers.eq;
33 import static org.mockito.Mockito.atLeast;
34 import static org.mockito.Mockito.clearInvocations;
35 import static org.mockito.Mockito.doThrow;
36 import static org.mockito.Mockito.inOrder;
37 import static org.mockito.Mockito.never;
38 import static org.mockito.Mockito.spy;
39 import static org.mockito.Mockito.times;
40 import static org.mockito.Mockito.verify;
41 import static org.mockito.Mockito.verifyNoMoreInteractions;
42 import static org.mockito.Mockito.when;
43 
44 import android.annotation.NonNull;
45 import android.app.ActivityManagerInternal;
46 import android.app.AppOpsManager;
47 import android.content.Context;
48 import android.content.res.Resources;
49 import android.hardware.SensorManager;
50 import android.hardware.display.AmbientDisplayConfiguration;
51 import android.hardware.display.DisplayManagerInternal;
52 import android.os.BatteryStats;
53 import android.os.BatteryStatsInternal;
54 import android.os.Handler;
55 import android.os.IBinder;
56 import android.os.IScreenTimeoutPolicyListener;
57 import android.os.IWakeLockCallback;
58 import android.os.Looper;
59 import android.os.PowerManager;
60 import android.os.RemoteException;
61 import android.os.VibrationAttributes;
62 import android.os.Vibrator;
63 import android.os.WorkSource;
64 import android.os.WorkSource.WorkChain;
65 import android.os.test.TestLooper;
66 import android.provider.Settings;
67 import android.testing.TestableContext;
68 import android.util.IntArray;
69 import android.util.SparseArray;
70 import android.util.SparseBooleanArray;
71 import android.view.Display;
72 import android.view.DisplayAddress;
73 import android.view.DisplayInfo;
74 
75 import androidx.test.InstrumentationRegistry;
76 
77 import com.android.internal.app.IBatteryStats;
78 import com.android.server.LocalServices;
79 import com.android.server.input.InputManagerInternal;
80 import com.android.server.inputmethod.InputMethodManagerInternal;
81 import com.android.server.policy.WindowManagerPolicy;
82 import com.android.server.power.FrameworkStatsLogger.WakelockEventType;
83 import com.android.server.power.batterysaver.BatterySaverStateMachine;
84 import com.android.server.power.feature.PowerManagerFlags;
85 import com.android.server.statusbar.StatusBarManagerInternal;
86 
87 import org.junit.Before;
88 import org.junit.Test;
89 import org.mockito.ArgumentCaptor;
90 import org.mockito.InOrder;
91 import org.mockito.Mock;
92 import org.mockito.Mockito;
93 import org.mockito.MockitoAnnotations;
94 
95 import java.util.concurrent.Executor;
96 
97 /**
98  * Tests for {@link com.android.server.power.Notifier}
99  */
100 public class NotifierTest {
101     private static final String SYSTEM_PROPERTY_QUIESCENT = "ro.boot.quiescent";
102     private static final int USER_ID = 0;
103     private static final int DISPLAY_PORT = 0xFF;
104     private static final long DISPLAY_MODEL = 0xEEEEEEEEL;
105 
106     private static final int UID = 1234;
107     private static final int OWNER_UID = 1235;
108     private static final int WORK_SOURCE_UID_1 = 2345;
109     private static final int WORK_SOURCE_UID_2 = 2346;
110     private static final int OWNER_WORK_SOURCE_UID_1 = 3456;
111     private static final int OWNER_WORK_SOURCE_UID_2 = 3457;
112     private static final int PID = 5678;
113 
114     @Mock private BatterySaverStateMachine mBatterySaverStateMachineMock;
115     @Mock private PowerManagerService.NativeWrapper mNativeWrapperMock;
116     @Mock private Notifier mNotifierMock;
117     @Mock private WirelessChargerDetector mWirelessChargerDetectorMock;
118     @Mock private AmbientDisplayConfiguration mAmbientDisplayConfigurationMock;
119     @Mock private SystemPropertiesWrapper mSystemPropertiesMock;
120     @Mock private InattentiveSleepWarningController mInattentiveSleepWarningControllerMock;
121     @Mock private Vibrator mVibrator;
122     @Mock private StatusBarManagerInternal mStatusBarManagerInternal;
123     @Mock private InputManagerInternal mInputManagerInternal;
124     @Mock private InputMethodManagerInternal mInputMethodManagerInternal;
125     @Mock private DisplayManagerInternal mDisplayManagerInternal;
126     @Mock private ActivityManagerInternal mActivityManagerInternal;
127     @Mock private WakeLockLog mWakeLockLog;
128 
129     @Mock private IBatteryStats mBatteryStats;
130 
131     @Mock private WindowManagerPolicy mPolicy;
132 
133     @Mock private PowerManagerFlags mPowerManagerFlags;
134 
135     @Mock private AppOpsManager mAppOpsManager;
136 
137     @Mock private BatteryStatsInternal mBatteryStatsInternal;
138     @Mock private FrameworkStatsLogger mLogger;
139 
140     private PowerManagerService mService;
141     private Context mContextSpy;
142     private Resources mResourcesSpy;
143     private TestLooper mTestLooper = new TestLooper();
144     private FakeExecutor mTestExecutor = new FakeExecutor();
145     private Notifier mNotifier;
146     private DisplayInfo mDefaultDisplayInfo = new DisplayInfo();
147 
148     @Before
setUp()149     public void setUp() {
150         MockitoAnnotations.initMocks(this);
151 
152         LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
153         LocalServices.addService(StatusBarManagerInternal.class, mStatusBarManagerInternal);
154 
155         LocalServices.removeServiceForTest(InputManagerInternal.class);
156         LocalServices.addService(InputManagerInternal.class, mInputManagerInternal);
157         LocalServices.removeServiceForTest(InputMethodManagerInternal.class);
158         LocalServices.addService(InputMethodManagerInternal.class, mInputMethodManagerInternal);
159 
160         LocalServices.removeServiceForTest(ActivityManagerInternal.class);
161         LocalServices.addService(ActivityManagerInternal.class, mActivityManagerInternal);
162 
163         mDefaultDisplayInfo.address = DisplayAddress.fromPortAndModel(DISPLAY_PORT, DISPLAY_MODEL);
164         LocalServices.removeServiceForTest(DisplayManagerInternal.class);
165         LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternal);
166 
167         mContextSpy = spy(new TestableContext(InstrumentationRegistry.getContext()));
168         mResourcesSpy = spy(mContextSpy.getResources());
169         when(mContextSpy.getResources()).thenReturn(mResourcesSpy);
170         when(mSystemPropertiesMock.get(eq(SYSTEM_PROPERTY_QUIESCENT), anyString())).thenReturn("");
171         when(mContextSpy.getSystemService(Vibrator.class)).thenReturn(mVibrator);
172         when(mDisplayManagerInternal.getDisplayInfo(Display.DEFAULT_DISPLAY)).thenReturn(
173                 mDefaultDisplayInfo);
174 
175         mService = new PowerManagerService(mContextSpy, mInjector);
176     }
177 
178     @Test
testVibrateEnabled_wiredCharging()179     public void testVibrateEnabled_wiredCharging() {
180         createNotifier();
181 
182         // GIVEN the charging vibration is enabled
183         enableChargingVibration(true);
184 
185         // WHEN wired charging starts
186         mNotifier.onWiredChargingStarted(USER_ID);
187         mTestLooper.dispatchAll();
188         mTestExecutor.simulateAsyncExecutionOfLastCommand();
189 
190         // THEN the device vibrates once
191         verify(mVibrator, times(1)).vibrate(anyInt(), any(), any(), any(),
192                 any(VibrationAttributes.class));
193     }
194 
195     @Test
testVibrateDisabled_wiredCharging()196     public void testVibrateDisabled_wiredCharging() {
197         createNotifier();
198 
199         // GIVEN the charging vibration is disabled
200         enableChargingVibration(false);
201 
202         // WHEN wired charging starts
203         mNotifier.onWiredChargingStarted(USER_ID);
204         mTestLooper.dispatchAll();
205         mTestExecutor.simulateAsyncExecutionOfLastCommand();
206 
207         // THEN the device doesn't vibrate
208         verifyNoMoreInteractions(mVibrator);
209     }
210 
211     @Test
testVibrateEnabled_wirelessCharging()212     public void testVibrateEnabled_wirelessCharging() {
213         createNotifier();
214 
215         // GIVEN the charging vibration is enabled
216         enableChargingVibration(true);
217 
218         // WHEN wireless charging starts
219         mNotifier.onWirelessChargingStarted(5, USER_ID);
220         mTestLooper.dispatchAll();
221         mTestExecutor.simulateAsyncExecutionOfLastCommand();
222 
223         // THEN the device vibrates once
224         verify(mVibrator, times(1)).vibrate(anyInt(), any(), any(), any(),
225                 any(VibrationAttributes.class));
226     }
227 
228     @Test
testVibrateDisabled_wirelessCharging()229     public void testVibrateDisabled_wirelessCharging() {
230         createNotifier();
231 
232         // GIVEN the charging vibration is disabled
233         enableChargingVibration(false);
234 
235         // WHEN wireless charging starts
236         mNotifier.onWirelessChargingStarted(5, USER_ID);
237         mTestLooper.dispatchAll();
238         mTestExecutor.simulateAsyncExecutionOfLastCommand();
239 
240         // THEN the device doesn't vibrate
241         verifyNoMoreInteractions(mVibrator);
242     }
243 
244     @Test
testVibrateEnabled_dndOn()245     public void testVibrateEnabled_dndOn() {
246         createNotifier();
247 
248         // GIVEN the charging vibration is enabled but dnd is on
249         enableChargingVibration(true);
250         enableChargingFeedback(
251                 /* chargingFeedbackEnabled */ true,
252                 /* dndOn */ true);
253 
254         // WHEN wired charging starts
255         mNotifier.onWiredChargingStarted(USER_ID);
256         mTestLooper.dispatchAll();
257         mTestExecutor.simulateAsyncExecutionOfLastCommand();
258 
259         // THEN the device doesn't vibrate
260         verify(mVibrator, never()).vibrate(any(), any(VibrationAttributes.class));
261     }
262 
263     @Test
testWirelessAnimationEnabled()264     public void testWirelessAnimationEnabled() {
265         // GIVEN the wireless charging animation is enabled
266         when(mResourcesSpy.getBoolean(
267                 com.android.internal.R.bool.config_showBuiltinWirelessChargingAnim))
268                 .thenReturn(true);
269         createNotifier();
270 
271         // WHEN wireless charging starts
272         mNotifier.onWirelessChargingStarted(5, USER_ID);
273         mTestLooper.dispatchAll();
274         mTestExecutor.simulateAsyncExecutionOfLastCommand();
275 
276         // THEN the charging animation is triggered
277         verify(mStatusBarManagerInternal, times(1)).showChargingAnimation(5);
278     }
279 
280     @Test
testWirelessAnimationDisabled()281     public void testWirelessAnimationDisabled() {
282         // GIVEN the wireless charging animation is disabled
283         when(mResourcesSpy.getBoolean(
284                 com.android.internal.R.bool.config_showBuiltinWirelessChargingAnim))
285                 .thenReturn(false);
286         createNotifier();
287 
288         // WHEN wireless charging starts
289         mNotifier.onWirelessChargingStarted(5, USER_ID);
290         mTestLooper.dispatchAll();
291         mTestExecutor.simulateAsyncExecutionOfLastCommand();
292 
293         // THEN the charging animation never gets called
294         verify(mStatusBarManagerInternal, never()).showChargingAnimation(anyInt());
295     }
296 
297     @Test
testOnGlobalWakefulnessChangeStarted()298     public void testOnGlobalWakefulnessChangeStarted() {
299         createNotifier();
300         // GIVEN system is currently non-interactive
301         when(mPowerManagerFlags.isPerDisplayWakeByTouchEnabled()).thenReturn(false);
302         final int displayId1 = 101;
303         final int displayId2 = 102;
304         final int[] displayIds = new int[]{displayId1, displayId2};
305         when(mDisplayManagerInternal.getDisplayIds()).thenReturn(IntArray.wrap(displayIds));
306         mNotifier.onGlobalWakefulnessChangeStarted(WAKEFULNESS_ASLEEP,
307                 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, /* eventTime= */ 1000);
308         mTestLooper.dispatchAll();
309 
310         // WHEN a global wakefulness change to interactive starts
311         mNotifier.onGlobalWakefulnessChangeStarted(WAKEFULNESS_AWAKE,
312                 PowerManager.WAKE_REASON_TAP, /* eventTime= */ 2000);
313         mTestLooper.dispatchAll();
314 
315         // THEN input is notified of all displays being interactive
316         final SparseBooleanArray expectedDisplayInteractivities = new SparseBooleanArray();
317         expectedDisplayInteractivities.put(displayId1, true);
318         expectedDisplayInteractivities.put(displayId2, true);
319         verify(mInputManagerInternal).setDisplayInteractivities(expectedDisplayInteractivities);
320         verify(mInputMethodManagerInternal).setInteractive(/* interactive= */ true);
321     }
322 
323     @Test
testOnGroupWakefulnessChangeStarted_newPowerGroup_perDisplayWakeDisabled()324     public void testOnGroupWakefulnessChangeStarted_newPowerGroup_perDisplayWakeDisabled() {
325         createNotifier();
326         // GIVEN power group is not yet known to Notifier and per-display wake by touch is disabled
327         final int groupId = 123;
328         final int changeReason = PowerManager.WAKE_REASON_TAP;
329         when(mPowerManagerFlags.isPerDisplayWakeByTouchEnabled()).thenReturn(false);
330 
331         // WHEN a power group wakefulness change starts
332         mNotifier.onGroupWakefulnessChangeStarted(
333                 groupId, WAKEFULNESS_AWAKE, changeReason, /* eventTime= */ 999);
334         mTestLooper.dispatchAll();
335 
336         // THEN window manager policy is informed that device has started waking up
337         verify(mPolicy).startedWakingUp(groupId, changeReason);
338         verify(mDisplayManagerInternal, never()).getDisplayIds();
339         verify(mInputManagerInternal, never()).setDisplayInteractivities(any());
340     }
341 
342     @Test
testOnGroupWakefulnessChangeStarted_interactivityNoChange_perDisplayWakeDisabled()343     public void testOnGroupWakefulnessChangeStarted_interactivityNoChange_perDisplayWakeDisabled() {
344         createNotifier();
345         // GIVEN power group is not interactive and per-display wake by touch is disabled
346         final int groupId = 234;
347         final int changeReason = PowerManager.GO_TO_SLEEP_REASON_TIMEOUT;
348         when(mPowerManagerFlags.isPerDisplayWakeByTouchEnabled()).thenReturn(false);
349         mNotifier.onGroupWakefulnessChangeStarted(
350                 groupId, WAKEFULNESS_ASLEEP, changeReason, /* eventTime= */ 999);
351         mTestLooper.dispatchAll();
352         verify(mPolicy, times(1)).startedGoingToSleep(groupId, changeReason);
353 
354         // WHEN a power wakefulness change to not interactive starts
355         mNotifier.onGroupWakefulnessChangeStarted(
356                 groupId, WAKEFULNESS_ASLEEP, changeReason, /* eventTime= */ 999);
357         mTestLooper.dispatchAll();
358 
359         // THEN policy is only informed once of non-interactive wakefulness change
360         verify(mPolicy, times(1)).startedGoingToSleep(groupId, changeReason);
361         verify(mDisplayManagerInternal, never()).getDisplayIds();
362         verify(mInputManagerInternal, never()).setDisplayInteractivities(any());
363     }
364 
365     @Test
testOnGroupWakefulnessChangeStarted_interactivityChange_perDisplayWakeDisabled()366     public void testOnGroupWakefulnessChangeStarted_interactivityChange_perDisplayWakeDisabled() {
367         createNotifier();
368         // GIVEN power group is not interactive and per-display wake by touch is disabled
369         final int groupId = 345;
370         final int firstChangeReason = PowerManager.GO_TO_SLEEP_REASON_TIMEOUT;
371         when(mPowerManagerFlags.isPerDisplayWakeByTouchEnabled()).thenReturn(false);
372         mNotifier.onGroupWakefulnessChangeStarted(
373                 groupId, WAKEFULNESS_ASLEEP, firstChangeReason, /* eventTime= */ 999);
374         mTestLooper.dispatchAll();
375 
376         // WHEN a power wakefulness change to interactive starts
377         final int secondChangeReason = PowerManager.WAKE_REASON_TAP;
378         mNotifier.onGroupWakefulnessChangeStarted(
379                 groupId, WAKEFULNESS_AWAKE, secondChangeReason, /* eventTime= */ 999);
380         mTestLooper.dispatchAll();
381 
382         // THEN policy is informed of the change
383         verify(mPolicy).startedWakingUp(groupId, secondChangeReason);
384         verify(mDisplayManagerInternal, never()).getDisplayIds();
385         verify(mInputManagerInternal, never()).setDisplayInteractivities(any());
386     }
387 
388     @Test
testOnGroupWakefulnessChangeStarted_perDisplayWakeByTouchEnabled()389     public void testOnGroupWakefulnessChangeStarted_perDisplayWakeByTouchEnabled() {
390         createNotifier();
391         // GIVEN per-display wake by touch flag is enabled
392         when(mPowerManagerFlags.isPerDisplayWakeByTouchEnabled()).thenReturn(true);
393         final int groupId = 456;
394         final int displayId1 = 1001;
395         final int displayId2 = 1002;
396         final int[] displays = new int[]{displayId1, displayId2};
397         when(mDisplayManagerInternal.getDisplayIds()).thenReturn(IntArray.wrap(displays));
398         when(mDisplayManagerInternal.getDisplayIdsForGroup(groupId)).thenReturn(displays);
399         final int changeReason = PowerManager.WAKE_REASON_TAP;
400 
401         // WHEN power group wakefulness change started
402         mNotifier.onGroupWakefulnessChangeStarted(
403                 groupId, WAKEFULNESS_AWAKE, changeReason, /* eventTime= */ 999);
404         mTestLooper.dispatchAll();
405 
406         // THEN native input manager is updated that the displays are interactive
407         final SparseBooleanArray expectedDisplayInteractivities = new SparseBooleanArray();
408         expectedDisplayInteractivities.put(displayId1, true);
409         expectedDisplayInteractivities.put(displayId2, true);
410         verify(mInputManagerInternal).setDisplayInteractivities(expectedDisplayInteractivities);
411     }
412 
413     @Test
testOnGroupRemoved_perDisplayWakeByTouchEnabled()414     public void testOnGroupRemoved_perDisplayWakeByTouchEnabled() {
415         createNotifier();
416         // GIVEN per-display wake by touch is enabled and one display group has been defined
417         when(mPowerManagerFlags.isPerDisplayWakeByTouchEnabled()).thenReturn(true);
418         final int groupId = 313;
419         final int displayId1 = 3113;
420         final int displayId2 = 4114;
421         final int[] displays = new int[]{displayId1, displayId2};
422         when(mDisplayManagerInternal.getDisplayIds()).thenReturn(IntArray.wrap(displays));
423         when(mDisplayManagerInternal.getDisplayIdsForGroup(groupId)).thenReturn(displays);
424         mNotifier.onGroupWakefulnessChangeStarted(
425                 groupId, WAKEFULNESS_AWAKE, PowerManager.WAKE_REASON_TAP, /* eventTime= */ 1000);
426         final SparseBooleanArray expectedDisplayInteractivities = new SparseBooleanArray();
427         expectedDisplayInteractivities.put(displayId1, true);
428         expectedDisplayInteractivities.put(displayId2, true);
429         verify(mInputManagerInternal).setDisplayInteractivities(expectedDisplayInteractivities);
430 
431         // WHEN display group is removed
432         when(mDisplayManagerInternal.getDisplayIdsByGroupsIds()).thenReturn(new SparseArray<>());
433         mNotifier.onGroupRemoved(groupId);
434 
435         // THEN native input manager is informed that displays in that group no longer exist
436         verify(mInputManagerInternal).setDisplayInteractivities(new SparseBooleanArray());
437     }
438 
439     @Test
testOnGroupChanged_perDisplayWakeByTouchEnabled()440     public void testOnGroupChanged_perDisplayWakeByTouchEnabled() {
441         createNotifier();
442         // GIVEN per-display wake by touch is enabled and one display group has been defined with
443         // two displays
444         when(mPowerManagerFlags.isPerDisplayWakeByTouchEnabled()).thenReturn(true);
445         final int groupId = 121;
446         final int displayId1 = 1221;
447         final int displayId2 = 1222;
448         final int[] displays = new int[]{displayId1, displayId2};
449         when(mDisplayManagerInternal.getDisplayIds()).thenReturn(IntArray.wrap(displays));
450         when(mDisplayManagerInternal.getDisplayIdsForGroup(groupId)).thenReturn(displays);
451         SparseArray<int[]> displayIdsByGroupId = new SparseArray<>();
452         displayIdsByGroupId.put(groupId, displays);
453         when(mDisplayManagerInternal.getDisplayIdsByGroupsIds()).thenReturn(displayIdsByGroupId);
454         mNotifier.onGroupWakefulnessChangeStarted(
455                 groupId, WAKEFULNESS_AWAKE, PowerManager.WAKE_REASON_TAP, /* eventTime= */ 1000);
456         final SparseBooleanArray expectedDisplayInteractivities = new SparseBooleanArray();
457         expectedDisplayInteractivities.put(displayId1, true);
458         expectedDisplayInteractivities.put(displayId2, true);
459         verify(mInputManagerInternal).setDisplayInteractivities(expectedDisplayInteractivities);
460 
461         // WHEN display group is changed to only contain one display
462         SparseArray<int[]> newDisplayIdsByGroupId = new SparseArray<>();
463         newDisplayIdsByGroupId.put(groupId, new int[]{displayId1});
464         when(mDisplayManagerInternal.getDisplayIdsByGroupsIds()).thenReturn(newDisplayIdsByGroupId);
465         mNotifier.onGroupChanged();
466 
467         // THEN native input manager is informed that the displays in the group have changed
468         final SparseBooleanArray expectedDisplayInteractivitiesAfterChange =
469             new SparseBooleanArray();
470         expectedDisplayInteractivitiesAfterChange.put(displayId1, true);
471         verify(mInputManagerInternal).setDisplayInteractivities(
472             expectedDisplayInteractivitiesAfterChange);
473     }
474 
475     @Test
testOnWakeLockReleased_FrameworkStatsLogged_NoChains()476     public void testOnWakeLockReleased_FrameworkStatsLogged_NoChains() {
477         when(mPowerManagerFlags.isMoveWscLoggingToNotifierEnabled()).thenReturn(true);
478         createNotifier();
479 
480         clearInvocations(mLogger, mWakeLockLog, mBatteryStats, mAppOpsManager);
481 
482         when(mBatteryStatsInternal.getOwnerUid(UID)).thenReturn(OWNER_UID);
483         when(mBatteryStatsInternal.getOwnerUid(WORK_SOURCE_UID_1))
484                 .thenReturn(OWNER_WORK_SOURCE_UID_1);
485 
486         mNotifier.onWakeLockAcquired(
487                 PowerManager.PARTIAL_WAKE_LOCK,
488                 "wakelockTag",
489                 "my.package.name",
490                 UID,
491                 PID,
492                 /* workSource= */ null,
493                 /* historyTag= */ null,
494                 /* callback= */ null);
495 
496         WorkSource ws = new WorkSource(WORK_SOURCE_UID_1);
497 
498         mNotifier.onWakeLockChanging(
499                 /* existing WakeLock params */
500                 PowerManager.PARTIAL_WAKE_LOCK,
501                 "wakelockTag",
502                 "my.package.name",
503                 UID,
504                 PID,
505                 /* workSource= */ null,
506                 /* historyTag= */ null,
507                 /* callback= */ null,
508                 /* updated WakeLock params */
509                 PowerManager.PARTIAL_WAKE_LOCK,
510                 "wakelockTag",
511                 "my.package.name",
512                 UID,
513                 PID,
514                 ws,
515                 /* historyTag= */ null,
516                 /* callback= */ null);
517 
518         mNotifier.onWakeLockReleased(
519                 PowerManager.PARTIAL_WAKE_LOCK,
520                 "wakelockTag",
521                 "my.package.name",
522                 UID,
523                 PID,
524                 ws,
525                 /* historyTag= */ null,
526                 /* callback= */ null);
527 
528         verify(mBatteryStatsInternal, atLeast(1)).getOwnerUid(eq(UID));
529         verify(mBatteryStatsInternal, atLeast(1)).getOwnerUid(eq(WORK_SOURCE_UID_1));
530 
531         // ACQUIRE before RELEASE
532         InOrder inOrder1 = inOrder(mLogger);
533         inOrder1.verify(mLogger)
534                 .wakelockStateChanged(
535                         eq(OWNER_UID),
536                         eq("wakelockTag"),
537                         eq(PowerManager.PARTIAL_WAKE_LOCK),
538                         eq(WakelockEventType.ACQUIRE));
539         inOrder1.verify(mLogger)
540                 .wakelockStateChanged(
541                         eq(OWNER_UID),
542                         eq("wakelockTag"),
543                         eq(PowerManager.PARTIAL_WAKE_LOCK),
544                         eq(WakelockEventType.RELEASE));
545 
546         InOrder inOrder2 = inOrder(mLogger);
547         inOrder2.verify(mLogger)
548                 .wakelockStateChanged(
549                         eq(OWNER_WORK_SOURCE_UID_1),
550                         eq("wakelockTag"),
551                         eq(PowerManager.PARTIAL_WAKE_LOCK),
552                         eq(WakelockEventType.ACQUIRE));
553         inOrder2.verify(mLogger)
554                 .wakelockStateChanged(
555                         eq(OWNER_WORK_SOURCE_UID_1),
556                         eq("wakelockTag"),
557                         eq(PowerManager.PARTIAL_WAKE_LOCK),
558                         eq(WakelockEventType.RELEASE));
559     }
560 
561     @Test
testOnWakeLockReleased_FrameworkStatsLogged_MultipleWorkSourceUids()562     public void testOnWakeLockReleased_FrameworkStatsLogged_MultipleWorkSourceUids() {
563         // UIDs stored directly in WorkSource
564         WorkSource ws = new WorkSource(WORK_SOURCE_UID_1);
565         ws.add(WORK_SOURCE_UID_2);
566         testWorkSource(ws);
567 
568         InOrder inOrder = inOrder(mLogger);
569         ArgumentCaptor<Integer> captorInt = ArgumentCaptor.forClass(int.class);
570 
571         // ACQUIRE
572         inOrder.verify(mLogger, times(2))
573                 .wakelockStateChanged(
574                         /* uid= */ captorInt.capture(),
575                         eq("wakelockTag"),
576                         eq(PowerManager.PARTIAL_WAKE_LOCK),
577                         eq(WakelockEventType.ACQUIRE));
578         assertThat(captorInt.getAllValues())
579                 .containsExactly(OWNER_WORK_SOURCE_UID_1, OWNER_WORK_SOURCE_UID_2);
580 
581         // RELEASE
582         captorInt = ArgumentCaptor.forClass(int.class);
583         inOrder.verify(mLogger, times(2))
584                 .wakelockStateChanged(
585                         /* uid= */ captorInt.capture(),
586                         eq("wakelockTag"),
587                         eq(PowerManager.PARTIAL_WAKE_LOCK),
588                         eq(WakelockEventType.RELEASE));
589         assertThat(captorInt.getAllValues())
590                 .containsExactly(OWNER_WORK_SOURCE_UID_1, OWNER_WORK_SOURCE_UID_2);
591     }
592 
593     @Test
testOnWakeLockReleased_FrameworkStatsLogged_OneChain()594     public void testOnWakeLockReleased_FrameworkStatsLogged_OneChain() {
595         // UIDs stored in a WorkChain of the WorkSource
596         WorkSource ws = new WorkSource();
597         WorkChain wc = ws.createWorkChain();
598         wc.addNode(WORK_SOURCE_UID_1, "tag1");
599         wc.addNode(WORK_SOURCE_UID_2, "tag2");
600         testWorkSource(ws);
601 
602         WorkChain expectedWorkChain = new WorkChain();
603         expectedWorkChain.addNode(OWNER_WORK_SOURCE_UID_1, "tag1");
604         expectedWorkChain.addNode(OWNER_WORK_SOURCE_UID_2, "tag2");
605 
606         InOrder inOrder = inOrder(mLogger);
607 
608         // ACQUIRE
609         inOrder.verify(mLogger)
610                 .wakelockStateChanged(
611                         eq("wakelockTag"),
612                         eq(expectedWorkChain),
613                         eq(PowerManager.PARTIAL_WAKE_LOCK),
614                         eq(WakelockEventType.ACQUIRE));
615         // RELEASE
616         inOrder.verify(mLogger)
617                 .wakelockStateChanged(
618                         eq("wakelockTag"),
619                         eq(expectedWorkChain),
620                         eq(PowerManager.PARTIAL_WAKE_LOCK),
621                         eq(WakelockEventType.RELEASE));
622     }
623 
624     @Test
testOnWakeLockReleased_FrameworkStatsLogged_OneUid_OneChain()625     public void testOnWakeLockReleased_FrameworkStatsLogged_OneUid_OneChain() {
626         WorkSource ws = new WorkSource(WORK_SOURCE_UID_1);
627         WorkChain wc = ws.createWorkChain();
628         wc.addNode(WORK_SOURCE_UID_2, "someTag");
629         testWorkSource(ws);
630 
631         WorkChain expectedWorkChain = new WorkChain();
632         expectedWorkChain.addNode(OWNER_WORK_SOURCE_UID_2, "someTag");
633 
634         InOrder inOrder1 = inOrder(mLogger);
635         InOrder inOrder2 = inOrder(mLogger);
636 
637         // ACQUIRE
638         inOrder1.verify(mLogger)
639                 .wakelockStateChanged(
640                         eq(OWNER_WORK_SOURCE_UID_1),
641                         eq("wakelockTag"),
642                         eq(PowerManager.PARTIAL_WAKE_LOCK),
643                         eq(WakelockEventType.ACQUIRE));
644         inOrder2.verify(mLogger)
645                 .wakelockStateChanged(
646                         eq("wakelockTag"),
647                         eq(expectedWorkChain),
648                         eq(PowerManager.PARTIAL_WAKE_LOCK),
649                         eq(WakelockEventType.ACQUIRE));
650         // RELEASE
651         inOrder1.verify(mLogger)
652                 .wakelockStateChanged(
653                         eq(OWNER_WORK_SOURCE_UID_1),
654                         eq("wakelockTag"),
655                         eq(PowerManager.PARTIAL_WAKE_LOCK),
656                         eq(WakelockEventType.RELEASE));
657         inOrder2.verify(mLogger)
658                 .wakelockStateChanged(
659                         eq("wakelockTag"),
660                         eq(expectedWorkChain),
661                         eq(PowerManager.PARTIAL_WAKE_LOCK),
662                         eq(WakelockEventType.RELEASE));
663     }
664 
665     @Test
testOnWakeLockReleased_FrameworkStatsLogged_TwoChains()666     public void testOnWakeLockReleased_FrameworkStatsLogged_TwoChains() {
667         // UIDs stored in a WorkChain of the WorkSource
668         WorkSource ws = new WorkSource();
669         WorkChain wc1 = ws.createWorkChain();
670         wc1.addNode(WORK_SOURCE_UID_1, "tag1");
671 
672         WorkChain wc2 = ws.createWorkChain();
673         wc2.addNode(WORK_SOURCE_UID_2, "tag2");
674 
675         testWorkSource(ws);
676 
677         WorkChain expectedWorkChain1 = new WorkChain();
678         expectedWorkChain1.addNode(OWNER_WORK_SOURCE_UID_1, "tag1");
679 
680         WorkChain expectedWorkChain2 = new WorkChain();
681         expectedWorkChain2.addNode(OWNER_WORK_SOURCE_UID_2, "tag2");
682 
683         InOrder inOrder1 = inOrder(mLogger);
684         InOrder inOrder2 = inOrder(mLogger);
685 
686         // ACQUIRE
687         inOrder1.verify(mLogger)
688                 .wakelockStateChanged(
689                         eq("wakelockTag"),
690                         eq(expectedWorkChain1),
691                         eq(PowerManager.PARTIAL_WAKE_LOCK),
692                         eq(WakelockEventType.ACQUIRE));
693         inOrder2.verify(mLogger)
694                 .wakelockStateChanged(
695                         eq("wakelockTag"),
696                         eq(expectedWorkChain2),
697                         eq(PowerManager.PARTIAL_WAKE_LOCK),
698                         eq(WakelockEventType.ACQUIRE));
699 
700         // RELEASE
701         inOrder1.verify(mLogger)
702                 .wakelockStateChanged(
703                         eq("wakelockTag"),
704                         eq(expectedWorkChain1),
705                         eq(PowerManager.PARTIAL_WAKE_LOCK),
706                         eq(WakelockEventType.RELEASE));
707         inOrder2.verify(mLogger)
708                 .wakelockStateChanged(
709                         eq("wakelockTag"),
710                         eq(expectedWorkChain2),
711                         eq(PowerManager.PARTIAL_WAKE_LOCK),
712                         eq(WakelockEventType.RELEASE));
713     }
714 
715     @Test
testOnWakeLockListener_RemoteException_NoRethrow()716     public void testOnWakeLockListener_RemoteException_NoRethrow() throws RemoteException {
717         when(mPowerManagerFlags.improveWakelockLatency()).thenReturn(true);
718         createNotifier();
719         clearInvocations(mWakeLockLog, mBatteryStats, mAppOpsManager);
720         IWakeLockCallback exceptingCallback = new IWakeLockCallback.Stub() {
721             @Override public void onStateChanged(boolean enabled) throws RemoteException {
722                 throw new RemoteException("Just testing");
723             }
724         };
725 
726         final int uid = 1234;
727         final int pid = 5678;
728 
729         mNotifier.onWakeLockReleased(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag",
730                 "my.package.name", uid, pid, /* workSource= */ null, /* historyTag= */ null,
731                 exceptingCallback);
732         verifyNoMoreInteractions(mWakeLockLog);
733         mTestLooper.dispatchAll();
734         verify(mWakeLockLog).onWakeLockReleased("wakelockTag", uid, 1);
735         clearInvocations(mBatteryStats);
736         mNotifier.onWakeLockAcquired(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag",
737                 "my.package.name", uid, pid, /* workSource= */ null, /* historyTag= */ null,
738                 exceptingCallback);
739 
740         verifyNoMoreInteractions(mWakeLockLog, mBatteryStats);
741         mTestLooper.dispatchAll();
742         verify(mWakeLockLog).onWakeLockAcquired("wakelockTag", uid,
743                 PowerManager.PARTIAL_WAKE_LOCK, 1);
744         verify(mBatteryStats).noteStartWakelock(uid, pid, "wakelockTag", /* historyTag= */ null,
745                 BatteryStats.WAKE_TYPE_PARTIAL, false);
746 
747         verifyNoMoreInteractions(mWakeLockLog, mBatteryStats);
748         WorkSource worksourceOld = new WorkSource(/*uid=*/ 1);
749         WorkSource worksourceNew = new WorkSource(/*uid=*/ 2);
750 
751         mNotifier.onWakeLockChanging(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag",
752                 "my.package.name", uid, pid, worksourceOld, /* historyTag= */ null,
753                 exceptingCallback,
754                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "wakelockTag",
755                 "my.package.name", uid, pid, worksourceNew, /* newHistoryTag= */ null,
756                 exceptingCallback);
757         mTestLooper.dispatchAll();
758         verify(mBatteryStats).noteChangeWakelockFromSource(worksourceOld, pid, "wakelockTag",
759                 null, BatteryStats.WAKE_TYPE_PARTIAL, worksourceNew, pid, "wakelockTag",
760                 null, BatteryStats.WAKE_TYPE_FULL, false);
761         // If we didn't throw, we're good!
762 
763         // Test with improveWakelockLatency flag false, hence the wakelock log will run on the same
764         // thread
765         clearInvocations(mWakeLockLog, mBatteryStats);
766         when(mPowerManagerFlags.improveWakelockLatency()).thenReturn(false);
767 
768         // Acquire the wakelock
769         mNotifier.onWakeLockAcquired(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag",
770                 "my.package.name", uid, pid, /* workSource= */ null, /* historyTag= */ null,
771                 exceptingCallback);
772         verify(mWakeLockLog).onWakeLockAcquired("wakelockTag", uid,
773                 PowerManager.PARTIAL_WAKE_LOCK, -1);
774 
775         // Update the wakelock
776         mNotifier.onWakeLockChanging(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag",
777                 "my.package.name", uid, pid, worksourceOld, /* historyTag= */ null,
778                 exceptingCallback,
779                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "wakelockTag",
780                 "my.package.name", uid, pid, worksourceNew, /* newHistoryTag= */ null,
781                 exceptingCallback);
782         verify(mBatteryStats).noteChangeWakelockFromSource(worksourceOld, pid, "wakelockTag",
783                 null, BatteryStats.WAKE_TYPE_PARTIAL, worksourceNew, pid, "wakelockTag",
784                 null, BatteryStats.WAKE_TYPE_FULL, false);
785 
786         // Release the wakelock
787         mNotifier.onWakeLockReleased(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag",
788                 "my.package.name", uid, pid, /* workSource= */ null, /* historyTag= */ null,
789                 exceptingCallback);
790         verify(mWakeLockLog).onWakeLockReleased("wakelockTag", uid, -1);
791     }
792 
793     @Test
test_wakeLockLogUsesWorkSource()794     public void test_wakeLockLogUsesWorkSource() {
795         createNotifier();
796         clearInvocations(mWakeLockLog);
797         IWakeLockCallback exceptingCallback = new IWakeLockCallback.Stub() {
798             @Override public void onStateChanged(boolean enabled) throws RemoteException {
799                 throw new RemoteException("Just testing");
800             }
801         };
802 
803         final int uid = 1234;
804         final int pid = 5678;
805         WorkSource worksource = new WorkSource(1212);
806         WorkSource worksource2 = new WorkSource(3131);
807 
808         mNotifier.onWakeLockAcquired(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag",
809                 "my.package.name", uid, pid, worksource, /* historyTag= */ null,
810                 exceptingCallback);
811         verify(mWakeLockLog).onWakeLockAcquired("wakelockTag", 1212,
812                 PowerManager.PARTIAL_WAKE_LOCK, -1);
813 
814         // Release the wakelock
815         mNotifier.onWakeLockReleased(PowerManager.FULL_WAKE_LOCK, "wakelockTag2",
816                 "my.package.name", uid, pid, worksource2, /* historyTag= */ null,
817                 exceptingCallback);
818         verify(mWakeLockLog).onWakeLockReleased("wakelockTag2", 3131, -1);
819 
820         // clear the handler
821         mTestLooper.dispatchAll();
822 
823         // Now test with improveWakelockLatency flag true
824         clearInvocations(mWakeLockLog);
825         when(mPowerManagerFlags.improveWakelockLatency()).thenReturn(true);
826 
827         mNotifier.onWakeLockAcquired(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag",
828                 "my.package.name", uid, pid, worksource, /* historyTag= */ null,
829                 exceptingCallback);
830         mTestLooper.dispatchAll();
831         verify(mWakeLockLog).onWakeLockAcquired("wakelockTag", 1212,
832                 PowerManager.PARTIAL_WAKE_LOCK, 1);
833 
834         // Release the wakelock
835         mNotifier.onWakeLockReleased(PowerManager.FULL_WAKE_LOCK, "wakelockTag2",
836                 "my.package.name", uid, pid, worksource2, /* historyTag= */ null,
837                 exceptingCallback);
838         mTestLooper.dispatchAll();
839         verify(mWakeLockLog).onWakeLockReleased("wakelockTag2", 3131, 1);
840     }
841 
842     @Test
843     public void
test_notifierProcessesWorkSourceDeepCopy_OnWakelockChanging()844             test_notifierProcessesWorkSourceDeepCopy_OnWakelockChanging() throws RemoteException {
845         when(mPowerManagerFlags.improveWakelockLatency()).thenReturn(true);
846         createNotifier();
847         clearInvocations(mWakeLockLog, mBatteryStats, mAppOpsManager);
848         IWakeLockCallback exceptingCallback = new IWakeLockCallback.Stub() {
849             @Override public void onStateChanged(boolean enabled) throws RemoteException {
850                 throw new RemoteException("Just testing");
851             }
852         };
853 
854         final int uid = 1234;
855         final int pid = 5678;
856         mTestLooper.dispatchAll();
857         WorkSource worksourceOld = new WorkSource(/*uid=*/ 1);
858         WorkSource worksourceNew =  new WorkSource(/*uid=*/ 2);
859 
860         mNotifier.onWakeLockChanging(PowerManager.PARTIAL_WAKE_LOCK, "wakelockTag",
861                 "my.package.name", uid, pid, worksourceOld, /* historyTag= */ null,
862                 exceptingCallback,
863                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "wakelockTag",
864                 "my.package.name", uid, pid, worksourceNew, /* newHistoryTag= */ null,
865                 exceptingCallback);
866         // The newWorksource is modified before notifier could process it.
867         worksourceNew.set(/*uid=*/ 3);
868 
869         mTestLooper.dispatchAll();
870         verify(mBatteryStats).noteChangeWakelockFromSource(worksourceOld, pid,
871                 "wakelockTag", null, BatteryStats.WAKE_TYPE_PARTIAL,
872                 new WorkSource(/*uid=*/ 2), pid, "wakelockTag", null,
873                 BatteryStats.WAKE_TYPE_FULL, false);
874     }
875 
876 
877     @Test
testOnWakeLockListener_FullWakeLock_ProcessesOnHandler()878     public void testOnWakeLockListener_FullWakeLock_ProcessesOnHandler() throws RemoteException {
879         when(mPowerManagerFlags.improveWakelockLatency()).thenReturn(true);
880         createNotifier();
881 
882         IWakeLockCallback exceptingCallback = new IWakeLockCallback.Stub() {
883             @Override public void onStateChanged(boolean enabled) throws RemoteException {
884                 throw new RemoteException("Just testing");
885             }
886         };
887         clearInvocations(mWakeLockLog, mBatteryStats, mAppOpsManager);
888 
889         final int uid = 1234;
890         final int pid = 5678;
891 
892         // Release the wakelock
893         mNotifier.onWakeLockReleased(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "wakelockTag",
894                 "my.package.name", uid, pid, /* workSource= */ null, /* historyTag= */ null,
895                 exceptingCallback);
896 
897         // No interaction because we expect that to happen in async
898         verifyNoMoreInteractions(mWakeLockLog, mBatteryStats, mAppOpsManager);
899 
900         // Progressing the looper, and validating all the interactions
901         mTestLooper.dispatchAll();
902         verify(mWakeLockLog).onWakeLockReleased("wakelockTag", uid, 1);
903         verify(mBatteryStats).noteStopWakelock(uid, pid, "wakelockTag", /* historyTag= */ null,
904                 BatteryStats.WAKE_TYPE_FULL);
905         verify(mAppOpsManager).finishOp(AppOpsManager.OP_WAKE_LOCK, uid,
906                 "my.package.name", null);
907 
908         clearInvocations(mWakeLockLog, mBatteryStats, mAppOpsManager);
909 
910         // Acquire the wakelock
911         mNotifier.onWakeLockAcquired(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "wakelockTag",
912                 "my.package.name", uid, pid, /* workSource= */ null, /* historyTag= */ null,
913                 exceptingCallback);
914 
915         // No interaction because we expect that to happen in async
916         verifyNoMoreInteractions(mWakeLockLog, mBatteryStats, mAppOpsManager);
917 
918         // Progressing the looper, and validating all the interactions
919         mTestLooper.dispatchAll();
920         verify(mWakeLockLog).onWakeLockAcquired("wakelockTag", uid,
921                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK, 1);
922         verify(mBatteryStats).noteStartWakelock(uid, pid, "wakelockTag", /* historyTag= */ null,
923                 BatteryStats.WAKE_TYPE_FULL, false);
924         verify(mAppOpsManager).startOpNoThrow(AppOpsManager.OP_WAKE_LOCK, uid,
925                 "my.package.name", false, null, null);
926 
927         // Test with improveWakelockLatency flag false, hence the wakelock log will run on the same
928         // thread
929         clearInvocations(mWakeLockLog, mBatteryStats, mAppOpsManager);
930         when(mPowerManagerFlags.improveWakelockLatency()).thenReturn(false);
931 
932         mNotifier.onWakeLockAcquired(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "wakelockTag",
933                 "my.package.name", uid, pid, /* workSource= */ null, /* historyTag= */ null,
934                 exceptingCallback);
935         verify(mWakeLockLog).onWakeLockAcquired("wakelockTag", uid,
936                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK, -1);
937 
938         mNotifier.onWakeLockReleased(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "wakelockTag",
939                 "my.package.name", uid, pid, /* workSource= */ null, /* historyTag= */ null,
940                 exceptingCallback);
941         verify(mWakeLockLog).onWakeLockReleased("wakelockTag", uid, -1);
942     }
943 
944     @Test
testOnWakeLockListener_FullWakeLock_ProcessesInSync()945     public void testOnWakeLockListener_FullWakeLock_ProcessesInSync() throws RemoteException {
946         createNotifier();
947 
948         IWakeLockCallback exceptingCallback = new IWakeLockCallback.Stub() {
949             @Override public void onStateChanged(boolean enabled) throws RemoteException {
950                 throw new RemoteException("Just testing");
951             }
952         };
953         clearInvocations(mWakeLockLog, mBatteryStats, mAppOpsManager);
954 
955         final int uid = 1234;
956         final int pid = 5678;
957 
958         // Release the wakelock
959         mNotifier.onWakeLockReleased(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "wakelockTag",
960                 "my.package.name", uid, pid, /* workSource= */ null, /* historyTag= */ null,
961                 exceptingCallback);
962 
963         verify(mWakeLockLog).onWakeLockReleased("wakelockTag", uid, -1);
964         verify(mBatteryStats).noteStopWakelock(uid, pid, "wakelockTag", /* historyTag= */ null,
965                 BatteryStats.WAKE_TYPE_FULL);
966         verify(mAppOpsManager).finishOp(AppOpsManager.OP_WAKE_LOCK, uid,
967                 "my.package.name", null);
968 
969         clearInvocations(mWakeLockLog, mBatteryStats, mAppOpsManager);
970 
971         // Acquire the wakelock
972         mNotifier.onWakeLockAcquired(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "wakelockTag",
973                 "my.package.name", uid, pid, /* workSource= */ null, /* historyTag= */ null,
974                 exceptingCallback);
975 
976         mTestLooper.dispatchAll();
977         verify(mWakeLockLog).onWakeLockAcquired("wakelockTag", uid,
978                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK, -1);
979         verify(mBatteryStats).noteStartWakelock(uid, pid, "wakelockTag", /* historyTag= */ null,
980                 BatteryStats.WAKE_TYPE_FULL, false);
981         verify(mAppOpsManager).startOpNoThrow(AppOpsManager.OP_WAKE_LOCK, uid,
982                 "my.package.name", false, null, null);
983     }
984 
985     @Test
getWakelockMonitorTypeForLogging_evaluatesWakelockLevel()986     public void getWakelockMonitorTypeForLogging_evaluatesWakelockLevel() {
987         createNotifier();
988         assertEquals(mNotifier.getWakelockMonitorTypeForLogging(PowerManager.SCREEN_DIM_WAKE_LOCK),
989                 PowerManager.FULL_WAKE_LOCK);
990         assertEquals(mNotifier.getWakelockMonitorTypeForLogging(
991                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK), PowerManager.FULL_WAKE_LOCK);
992         assertEquals(mNotifier.getWakelockMonitorTypeForLogging(PowerManager.DRAW_WAKE_LOCK),
993                 PowerManager.DRAW_WAKE_LOCK);
994         assertEquals(mNotifier.getWakelockMonitorTypeForLogging(PowerManager.PARTIAL_WAKE_LOCK),
995                 PowerManager.PARTIAL_WAKE_LOCK);
996         assertEquals(mNotifier.getWakelockMonitorTypeForLogging(
997                         PowerManager.DOZE_WAKE_LOCK), -1);
998     }
999 
1000     @Test
getWakelockMonitorTypeForLogging_evaluateProximityLevel()1001     public void getWakelockMonitorTypeForLogging_evaluateProximityLevel() {
1002         // How proximity wakelock is evaluated depends on boolean configuration. Test both.
1003         when(mResourcesSpy.getBoolean(
1004                 com.android.internal.R.bool.config_suspendWhenScreenOffDueToProximity))
1005                 .thenReturn(false);
1006         createNotifier();
1007         assertEquals(mNotifier.getWakelockMonitorTypeForLogging(
1008                         PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK),
1009                 PowerManager.PARTIAL_WAKE_LOCK);
1010 
1011         when(mResourcesSpy.getBoolean(
1012                 com.android.internal.R.bool.config_suspendWhenScreenOffDueToProximity))
1013                 .thenReturn(true);
1014         createNotifier();
1015         assertEquals(mNotifier.getWakelockMonitorTypeForLogging(
1016                         PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK), -1);
1017     }
1018 
1019     @Test
testScreenTimeoutListener_reportsScreenTimeoutPolicyChange()1020     public void testScreenTimeoutListener_reportsScreenTimeoutPolicyChange() throws Exception {
1021         createNotifier();
1022         final IScreenTimeoutPolicyListener listener = Mockito.mock(
1023                 IScreenTimeoutPolicyListener.class);
1024         final IBinder listenerBinder = Mockito.mock(IBinder.class);
1025         when(listener.asBinder()).thenReturn(listenerBinder);
1026         mNotifier.addScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY,
1027                 SCREEN_TIMEOUT_ACTIVE, listener);
1028         mTestLooper.dispatchAll();
1029         clearInvocations(listener);
1030 
1031         mNotifier.notifyScreenTimeoutPolicyChanges(Display.DEFAULT_DISPLAY_GROUP,
1032                 /* hasScreenWakeLock= */ SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
1033 
1034         // Verify that the event is sent asynchronously on a handler
1035         verify(listener, never()).onScreenTimeoutPolicyChanged(anyInt());
1036         mTestLooper.dispatchAll();
1037         verify(listener).onScreenTimeoutPolicyChanged(SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
1038     }
1039 
1040     @Test
testScreenTimeoutListener_addAndRemoveListener_doesNotInvokeListener()1041     public void testScreenTimeoutListener_addAndRemoveListener_doesNotInvokeListener()
1042             throws Exception {
1043         createNotifier();
1044         final IScreenTimeoutPolicyListener listener = Mockito.mock(
1045                 IScreenTimeoutPolicyListener.class);
1046         final IBinder listenerBinder = Mockito.mock(IBinder.class);
1047         when(listener.asBinder()).thenReturn(listenerBinder);
1048         mNotifier.addScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY,
1049                 SCREEN_TIMEOUT_ACTIVE, listener);
1050         mTestLooper.dispatchAll();
1051         clearInvocations(listener);
1052         mNotifier.removeScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY, listener);
1053 
1054         mNotifier.notifyScreenTimeoutPolicyChanges(Display.DEFAULT_DISPLAY_GROUP,
1055                 SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
1056         mTestLooper.dispatchAll();
1057 
1058         // Callback should not be fired as listener is removed
1059         verify(listener, never()).onScreenTimeoutPolicyChanged(anyInt());
1060     }
1061 
1062     @Test
testScreenTimeoutListener_addAndClearListeners_doesNotInvokeListener()1063     public void testScreenTimeoutListener_addAndClearListeners_doesNotInvokeListener()
1064             throws Exception {
1065         createNotifier();
1066         final IScreenTimeoutPolicyListener listener = Mockito.mock(
1067                 IScreenTimeoutPolicyListener.class);
1068         final IBinder listenerBinder = Mockito.mock(IBinder.class);
1069         when(listener.asBinder()).thenReturn(listenerBinder);
1070         mNotifier.addScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY,
1071                 SCREEN_TIMEOUT_ACTIVE, listener);
1072         mTestLooper.dispatchAll();
1073         clearInvocations(listener);
1074         mNotifier.clearScreenTimeoutPolicyListeners(Display.DEFAULT_DISPLAY);
1075 
1076         mNotifier.notifyScreenTimeoutPolicyChanges(Display.DEFAULT_DISPLAY_GROUP,
1077                 SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
1078         mTestLooper.dispatchAll();
1079 
1080         // Callback should not be fired as listener is removed
1081         verify(listener, never()).onScreenTimeoutPolicyChanged(anyInt());
1082     }
1083 
1084     @Test
testScreenTimeoutListener_subscribedToAnotherDisplay_listenerNotFired()1085     public void testScreenTimeoutListener_subscribedToAnotherDisplay_listenerNotFired()
1086             throws Exception {
1087         createNotifier();
1088 
1089         final IScreenTimeoutPolicyListener listener = Mockito.mock(
1090                 IScreenTimeoutPolicyListener.class);
1091         final IBinder listenerBinder = Mockito.mock(IBinder.class);
1092         when(listener.asBinder()).thenReturn(listenerBinder);
1093         mNotifier.addScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY,
1094                 SCREEN_TIMEOUT_ACTIVE, listener);
1095         mTestLooper.dispatchAll();
1096         clearInvocations(listener);
1097 
1098         mNotifier.notifyScreenTimeoutPolicyChanges(/* displayGroupId= */ 123,
1099                 SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
1100         mTestLooper.dispatchAll();
1101 
1102         // Callback should not be fired as we subscribed only to the DEFAULT_DISPLAY
1103         verify(listener, never()).onScreenTimeoutPolicyChanged(anyInt());
1104     }
1105 
1106     @Test
testScreenTimeoutListener_listenerDied_listenerNotFired()1107     public void testScreenTimeoutListener_listenerDied_listenerNotFired()
1108             throws Exception {
1109         createNotifier();
1110 
1111         final IScreenTimeoutPolicyListener listener = Mockito.mock(
1112                 IScreenTimeoutPolicyListener.class);
1113         final IBinder listenerBinder = Mockito.mock(IBinder.class);
1114         when(listener.asBinder()).thenReturn(listenerBinder);
1115 
1116         mNotifier.addScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY,
1117                 SCREEN_TIMEOUT_ACTIVE, listener);
1118         mTestLooper.dispatchAll();
1119 
1120         ArgumentCaptor<IBinder.DeathRecipient> captor =
1121                 ArgumentCaptor.forClass(IBinder.DeathRecipient.class);
1122         verify(listenerBinder).linkToDeath(captor.capture(), anyInt());
1123         mTestLooper.dispatchAll();
1124         captor.getValue().binderDied();
1125         clearInvocations(listener);
1126 
1127         mNotifier.notifyScreenTimeoutPolicyChanges(Display.DEFAULT_DISPLAY,
1128                 SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
1129         mTestLooper.dispatchAll();
1130 
1131         // Callback should not be fired as binder died
1132         verify(listener, never()).onScreenTimeoutPolicyChanged(anyInt());
1133     }
1134 
1135     @Test
testScreenTimeoutListener_listenerThrowsException_listenerNotFiredSecondTime()1136     public void testScreenTimeoutListener_listenerThrowsException_listenerNotFiredSecondTime()
1137             throws Exception {
1138         createNotifier();
1139 
1140         final IScreenTimeoutPolicyListener listener = Mockito.mock(
1141                 IScreenTimeoutPolicyListener.class);
1142         final IBinder listenerBinder = Mockito.mock(IBinder.class);
1143         when(listener.asBinder()).thenReturn(listenerBinder);
1144         doThrow(RuntimeException.class).when(listener).onScreenTimeoutPolicyChanged(anyInt());
1145         mNotifier.addScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY_GROUP,
1146                 SCREEN_TIMEOUT_ACTIVE, listener);
1147         mTestLooper.dispatchAll();
1148         clearInvocations(listener);
1149 
1150         mNotifier.notifyScreenTimeoutPolicyChanges(Display.DEFAULT_DISPLAY,
1151                 SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
1152         mTestLooper.dispatchAll();
1153 
1154         // Callback should not be fired as it has thrown an exception once
1155         verify(listener, never()).onScreenTimeoutPolicyChanged(anyInt());
1156     }
1157 
1158     @Test
testScreenTimeoutListener_nonDefaultDisplay_stillReportsPolicyCorrectly()1159     public void testScreenTimeoutListener_nonDefaultDisplay_stillReportsPolicyCorrectly()
1160             throws Exception {
1161         createNotifier();
1162         final int otherDisplayId = 123;
1163         final int otherDisplayGroupId = 123_00;
1164         when(mDisplayManagerInternal.getGroupIdForDisplay(otherDisplayId)).thenReturn(
1165                 otherDisplayGroupId);
1166         final IScreenTimeoutPolicyListener listener = Mockito.mock(
1167                 IScreenTimeoutPolicyListener.class);
1168         final IBinder listenerBinder = Mockito.mock(IBinder.class);
1169         when(listener.asBinder()).thenReturn(listenerBinder);
1170         mNotifier.addScreenTimeoutPolicyListener(otherDisplayId,
1171                 SCREEN_TIMEOUT_ACTIVE, listener);
1172         mTestLooper.dispatchAll();
1173         clearInvocations(listener);
1174 
1175         mNotifier.notifyScreenTimeoutPolicyChanges(otherDisplayGroupId,
1176                 SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
1177         mTestLooper.dispatchAll();
1178 
1179         verify(listener).onScreenTimeoutPolicyChanged(SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
1180     }
1181 
1182     @Test
testScreenTimeoutListener_timeoutPolicyTimeout_reportsTimeoutOnSubscription()1183     public void testScreenTimeoutListener_timeoutPolicyTimeout_reportsTimeoutOnSubscription()
1184             throws Exception {
1185         createNotifier();
1186         final IScreenTimeoutPolicyListener listener = Mockito.mock(
1187                 IScreenTimeoutPolicyListener.class);
1188         final IBinder listenerBinder = Mockito.mock(IBinder.class);
1189         when(listener.asBinder()).thenReturn(listenerBinder);
1190 
1191         mNotifier.addScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY,
1192                 SCREEN_TIMEOUT_ACTIVE, listener);
1193         mTestLooper.dispatchAll();
1194 
1195         verify(listener).onScreenTimeoutPolicyChanged(SCREEN_TIMEOUT_ACTIVE);
1196     }
1197 
1198     @Test
testScreenTimeoutListener_policyHeld_reportsHeldOnSubscription()1199     public void testScreenTimeoutListener_policyHeld_reportsHeldOnSubscription()
1200             throws Exception {
1201         createNotifier();
1202         final IScreenTimeoutPolicyListener listener = Mockito.mock(
1203                 IScreenTimeoutPolicyListener.class);
1204         final IBinder listenerBinder = Mockito.mock(IBinder.class);
1205         when(listener.asBinder()).thenReturn(listenerBinder);
1206 
1207         mNotifier.addScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY,
1208                 SCREEN_TIMEOUT_KEEP_DISPLAY_ON, listener);
1209         mTestLooper.dispatchAll();
1210 
1211         verify(listener).onScreenTimeoutPolicyChanged(SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
1212     }
1213 
1214     private final PowerManagerService.Injector mInjector = new PowerManagerService.Injector() {
1215         @Override
1216         Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
1217                 SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
1218                 FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector,
1219                 Executor backgroundExecutor, PowerManagerFlags powerManagerFlags) {
1220             return mNotifierMock;
1221         }
1222 
1223         @Override
1224         SuspendBlocker createSuspendBlocker(PowerManagerService service, String name) {
1225             return super.createSuspendBlocker(service, name);
1226         }
1227 
1228         @Override
1229         BatterySaverStateMachine createBatterySaverStateMachine(Object lock, Context context) {
1230             return mBatterySaverStateMachineMock;
1231         }
1232 
1233         @Override
1234         PowerManagerService.NativeWrapper createNativeWrapper() {
1235             return mNativeWrapperMock;
1236         }
1237 
1238         @Override
1239         WirelessChargerDetector createWirelessChargerDetector(
1240                 SensorManager sensorManager, SuspendBlocker suspendBlocker, Handler handler) {
1241             return mWirelessChargerDetectorMock;
1242         }
1243 
1244         @Override
1245         AmbientDisplayConfiguration createAmbientDisplayConfiguration(Context context) {
1246             return mAmbientDisplayConfigurationMock;
1247         }
1248 
1249         @Override
1250         InattentiveSleepWarningController createInattentiveSleepWarningController() {
1251             return mInattentiveSleepWarningControllerMock;
1252         }
1253 
1254         @Override
1255         public SystemPropertiesWrapper createSystemPropertiesWrapper() {
1256             return mSystemPropertiesMock;
1257         }
1258 
1259         @Override
1260         void invalidateIsInteractiveCaches() {
1261             // Avoids an SELinux denial.
1262         }
1263     };
1264 
enableChargingFeedback(boolean chargingFeedbackEnabled, boolean dndOn)1265     private void enableChargingFeedback(boolean chargingFeedbackEnabled, boolean dndOn) {
1266         // enable/disable charging feedback
1267         Settings.Secure.putIntForUser(
1268                 mContextSpy.getContentResolver(),
1269                 Settings.Secure.CHARGING_SOUNDS_ENABLED,
1270                 chargingFeedbackEnabled ? 1 : 0,
1271                 USER_ID);
1272 
1273         // toggle on/off dnd
1274         Settings.Global.putInt(
1275                 mContextSpy.getContentResolver(),
1276                 Settings.Global.ZEN_MODE,
1277                 dndOn ? Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1278                         : Settings.Global.ZEN_MODE_OFF);
1279     }
1280 
enableChargingVibration(boolean enable)1281     private void enableChargingVibration(boolean enable) {
1282         enableChargingFeedback(true, false);
1283 
1284         Settings.Secure.putIntForUser(
1285                 mContextSpy.getContentResolver(),
1286                 Settings.Secure.CHARGING_VIBRATION_ENABLED,
1287                 enable ? 1 : 0,
1288                 USER_ID);
1289     }
1290 
createNotifier()1291     private void createNotifier() {
1292         Notifier.Injector injector =
1293                 new Notifier.Injector() {
1294                     @Override
1295                     public long currentTimeMillis() {
1296                         return 1;
1297                     }
1298 
1299                     @Override
1300                     public @NonNull WakeLockLog getWakeLockLog(Context context) {
1301                         return mWakeLockLog;
1302                     }
1303 
1304                     @Override
1305                     public AppOpsManager getAppOpsManager(Context context) {
1306                         return mAppOpsManager;
1307                     }
1308 
1309                     @Override
1310                     public FrameworkStatsLogger getFrameworkStatsLogger() {
1311                         return mLogger;
1312                     }
1313 
1314                     @Override
1315                     public BatteryStatsInternal getBatteryStatsInternal() {
1316                         return mBatteryStatsInternal;
1317                     }
1318                 };
1319 
1320         mNotifier = new Notifier(
1321                 mTestLooper.getLooper(),
1322                 mContextSpy,
1323                 mBatteryStats,
1324                 mInjector.createSuspendBlocker(mService, "testBlocker"),
1325                 mPolicy,
1326                 null,
1327                 null,
1328                 mTestExecutor, mPowerManagerFlags, injector);
1329     }
1330 
1331     private static class FakeExecutor implements Executor {
1332         private Runnable mLastCommand;
1333 
1334         @Override
execute(Runnable command)1335         public void execute(Runnable command) {
1336             assertNull(mLastCommand);
1337             assertNotNull(command);
1338             mLastCommand = command;
1339         }
1340 
getAndResetLastCommand()1341         public Runnable getAndResetLastCommand() {
1342             Runnable toReturn = mLastCommand;
1343             mLastCommand = null;
1344             return toReturn;
1345         }
1346 
simulateAsyncExecutionOfLastCommand()1347         public void simulateAsyncExecutionOfLastCommand() {
1348             Runnable toRun = getAndResetLastCommand();
1349             if (toRun != null) {
1350                 toRun.run();
1351             }
1352         }
1353     }
1354 
testWorkSource(WorkSource ws)1355     private void testWorkSource(WorkSource ws) {
1356         when(mPowerManagerFlags.isMoveWscLoggingToNotifierEnabled()).thenReturn(true);
1357         createNotifier();
1358         clearInvocations(
1359                 mBatteryStatsInternal, mLogger, mWakeLockLog, mBatteryStats, mAppOpsManager);
1360 
1361         when(mBatteryStatsInternal.getOwnerUid(WORK_SOURCE_UID_1))
1362                 .thenReturn(OWNER_WORK_SOURCE_UID_1);
1363         when(mBatteryStatsInternal.getOwnerUid(WORK_SOURCE_UID_2))
1364                 .thenReturn(OWNER_WORK_SOURCE_UID_2);
1365 
1366         mNotifier.onWakeLockAcquired(
1367                 PowerManager.PARTIAL_WAKE_LOCK,
1368                 "wakelockTag",
1369                 "my.package.name",
1370                 UID,
1371                 PID,
1372                 ws,
1373                 /* historyTag= */ null,
1374                 /* callback= */ null);
1375 
1376         mNotifier.onWakeLockReleased(
1377                 PowerManager.PARTIAL_WAKE_LOCK,
1378                 "wakelockTag",
1379                 "my.package.name",
1380                 UID,
1381                 PID,
1382                 ws,
1383                 /* historyTag= */ null,
1384                 /* callback= */ null);
1385 
1386         verify(mBatteryStatsInternal, atLeast(1)).getOwnerUid(eq(WORK_SOURCE_UID_1));
1387         verify(mBatteryStatsInternal, atLeast(1)).getOwnerUid(eq(WORK_SOURCE_UID_2));
1388     }
1389 }
1390