1 /*
2  * Copyright (C) 2022 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.systemui.stylus
18 
19 import android.hardware.BatteryState
20 import android.hardware.input.InputManager
21 import android.testing.AndroidTestingRunner
22 import android.view.InputDevice
23 import androidx.test.filters.SmallTest
24 import com.android.systemui.SysuiTestCase
25 import com.android.systemui.flags.FeatureFlags
26 import com.android.systemui.flags.Flags
27 import com.android.systemui.util.mockito.whenever
28 import org.junit.Before
29 import org.junit.Test
30 import org.junit.runner.RunWith
31 import org.mockito.Mock
32 import org.mockito.Mockito.mock
33 import org.mockito.Mockito.times
34 import org.mockito.Mockito.verify
35 import org.mockito.Mockito.verifyNoMoreInteractions
36 import org.mockito.Mockito.verifyZeroInteractions
37 import org.mockito.MockitoAnnotations
38 
39 @RunWith(AndroidTestingRunner::class)
40 @SmallTest
41 class StylusUsiPowerStartableTest : SysuiTestCase() {
42     @Mock lateinit var inputManager: InputManager
43     @Mock lateinit var stylusManager: StylusManager
44     @Mock lateinit var stylusDevice: InputDevice
45     @Mock lateinit var externalDevice: InputDevice
46     @Mock lateinit var featureFlags: FeatureFlags
47     @Mock lateinit var stylusUsiPowerUi: StylusUsiPowerUI
48 
49     lateinit var startable: StylusUsiPowerStartable
50 
51     @Before
setUpnull52     fun setUp() {
53         MockitoAnnotations.initMocks(this)
54 
55         startable =
56             StylusUsiPowerStartable(
57                 stylusManager,
58                 inputManager,
59                 stylusUsiPowerUi,
60                 featureFlags,
61             )
62 
63         whenever(featureFlags.isEnabled(Flags.ENABLE_USI_BATTERY_NOTIFICATIONS)).thenReturn(true)
64 
65         whenever(inputManager.getInputDevice(EXTERNAL_DEVICE_ID)).thenReturn(externalDevice)
66         whenever(inputManager.getInputDevice(STYLUS_DEVICE_ID)).thenReturn(stylusDevice)
67         whenever(inputManager.inputDeviceIds)
68             .thenReturn(intArrayOf(EXTERNAL_DEVICE_ID, STYLUS_DEVICE_ID))
69 
70         whenever(stylusDevice.supportsSource(InputDevice.SOURCE_STYLUS)).thenReturn(true)
71         whenever(stylusDevice.isExternal).thenReturn(false)
72         whenever(stylusDevice.id).thenReturn(STYLUS_DEVICE_ID)
73         whenever(externalDevice.supportsSource(InputDevice.SOURCE_STYLUS)).thenReturn(true)
74         whenever(externalDevice.isExternal).thenReturn(true)
75         whenever(externalDevice.id).thenReturn(EXTERNAL_DEVICE_ID)
76     }
77 
78     @Test
start_hostDeviceDoesNotSupportStylus_doesNotRegisternull79     fun start_hostDeviceDoesNotSupportStylus_doesNotRegister() {
80         whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf(EXTERNAL_DEVICE_ID))
81 
82         startable.start()
83 
84         verifyZeroInteractions(stylusManager)
85     }
86 
87     @Test
start_initStylusUsiPowerUinull88     fun start_initStylusUsiPowerUi() {
89         startable.start()
90 
91         verify(stylusUsiPowerUi, times(1)).init()
92     }
93 
94     @Test
start_registersCallbacksnull95     fun start_registersCallbacks() {
96         startable.start()
97 
98         verify(stylusManager, times(1)).registerCallback(startable)
99     }
100 
101     @Test
onStylusAdded_internal_updatesNotificationSuppressionnull102     fun onStylusAdded_internal_updatesNotificationSuppression() {
103         startable.onStylusAdded(STYLUS_DEVICE_ID)
104 
105         verify(stylusUsiPowerUi, times(1)).updateSuppression(false)
106     }
107 
108     @Test
onStylusAdded_external_noopnull109     fun onStylusAdded_external_noop() {
110         startable.onStylusAdded(EXTERNAL_DEVICE_ID)
111 
112         verifyZeroInteractions(stylusUsiPowerUi)
113     }
114 
115     @Test
onStylusUsiBatteryStateChanged_batteryPresentValidCapacity_refreshesNotificationnull116     fun onStylusUsiBatteryStateChanged_batteryPresentValidCapacity_refreshesNotification() {
117         val batteryState = FixedCapacityBatteryState(0.1f)
118 
119         startable.onStylusUsiBatteryStateChanged(STYLUS_DEVICE_ID, 123, batteryState)
120 
121         verify(stylusUsiPowerUi, times(1)).updateBatteryState(STYLUS_DEVICE_ID, batteryState)
122     }
123 
124     @Test
onStylusUsiBatteryStateChanged_batteryPresentInvalidCapacity_noopnull125     fun onStylusUsiBatteryStateChanged_batteryPresentInvalidCapacity_noop() {
126         val batteryState = FixedCapacityBatteryState(0f)
127 
128         startable.onStylusUsiBatteryStateChanged(STYLUS_DEVICE_ID, 123, batteryState)
129 
130         verifyNoMoreInteractions(stylusUsiPowerUi)
131     }
132 
133     @Test
onStylusUsiBatteryStateChanged_batteryNotPresent_noopnull134     fun onStylusUsiBatteryStateChanged_batteryNotPresent_noop() {
135         val batteryState = mock(BatteryState::class.java)
136         whenever(batteryState.isPresent).thenReturn(false)
137 
138         startable.onStylusUsiBatteryStateChanged(STYLUS_DEVICE_ID, 123, batteryState)
139 
140         verifyNoMoreInteractions(stylusUsiPowerUi)
141     }
142 
143     companion object {
144         private const val EXTERNAL_DEVICE_ID = 0
145         private const val STYLUS_DEVICE_ID = 1
146     }
147 }
148