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.view.InputDevice
22 import androidx.test.ext.junit.runners.AndroidJUnit4
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.MockitoAnnotations
37 
38 @RunWith(AndroidJUnit4::class)
39 @SmallTest
40 class StylusUsiPowerStartableTest : SysuiTestCase() {
41     @Mock lateinit var inputManager: InputManager
42     @Mock lateinit var stylusManager: StylusManager
43     @Mock lateinit var stylusDevice: InputDevice
44     @Mock lateinit var externalDevice: InputDevice
45     @Mock lateinit var featureFlags: FeatureFlags
46     @Mock lateinit var stylusUsiPowerUi: StylusUsiPowerUI
47 
48     lateinit var startable: StylusUsiPowerStartable
49 
50     @Before
setUpnull51     fun setUp() {
52         MockitoAnnotations.initMocks(this)
53 
54         startable =
55             StylusUsiPowerStartable(
56                 stylusManager,
57                 inputManager,
58                 stylusUsiPowerUi,
59                 featureFlags,
60             )
61 
62         whenever(featureFlags.isEnabled(Flags.ENABLE_USI_BATTERY_NOTIFICATIONS)).thenReturn(true)
63 
64         whenever(inputManager.getInputDevice(EXTERNAL_DEVICE_ID)).thenReturn(externalDevice)
65         whenever(inputManager.getInputDevice(STYLUS_DEVICE_ID)).thenReturn(stylusDevice)
66         whenever(inputManager.inputDeviceIds)
67             .thenReturn(intArrayOf(EXTERNAL_DEVICE_ID, STYLUS_DEVICE_ID))
68 
69         whenever(stylusDevice.supportsSource(InputDevice.SOURCE_STYLUS)).thenReturn(true)
70         whenever(stylusDevice.isExternal).thenReturn(false)
71         whenever(stylusDevice.id).thenReturn(STYLUS_DEVICE_ID)
72         whenever(externalDevice.supportsSource(InputDevice.SOURCE_STYLUS)).thenReturn(true)
73         whenever(externalDevice.isExternal).thenReturn(true)
74         whenever(externalDevice.id).thenReturn(EXTERNAL_DEVICE_ID)
75     }
76 
77     @Test
start_hostDeviceDoesNotSupportStylus_doesNotRegisternull78     fun start_hostDeviceDoesNotSupportStylus_doesNotRegister() {
79         whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf(EXTERNAL_DEVICE_ID))
80 
81         startable.start()
82 
83         verifyNoMoreInteractions(stylusManager)
84     }
85 
86     @Test
start_initStylusUsiPowerUinull87     fun start_initStylusUsiPowerUi() {
88         startable.start()
89 
90         verify(stylusUsiPowerUi, times(1)).init()
91     }
92 
93     @Test
start_registersCallbacksnull94     fun start_registersCallbacks() {
95         startable.start()
96 
97         verify(stylusManager, times(1)).registerCallback(startable)
98     }
99 
100     @Test
onStylusAdded_internal_updatesNotificationSuppressionnull101     fun onStylusAdded_internal_updatesNotificationSuppression() {
102         startable.onStylusAdded(STYLUS_DEVICE_ID)
103 
104         verify(stylusUsiPowerUi, times(1)).updateSuppression(false)
105     }
106 
107     @Test
onStylusAdded_external_noopnull108     fun onStylusAdded_external_noop() {
109         startable.onStylusAdded(EXTERNAL_DEVICE_ID)
110 
111         verifyNoMoreInteractions(stylusUsiPowerUi)
112     }
113 
114     @Test
onStylusUsiBatteryStateChanged_batteryPresentValidCapacity_refreshesNotificationnull115     fun onStylusUsiBatteryStateChanged_batteryPresentValidCapacity_refreshesNotification() {
116         val batteryState = FixedCapacityBatteryState(0.1f)
117 
118         startable.onStylusUsiBatteryStateChanged(STYLUS_DEVICE_ID, 123, batteryState)
119 
120         verify(stylusUsiPowerUi, times(1)).updateBatteryState(STYLUS_DEVICE_ID, batteryState)
121     }
122 
123     @Test
onStylusUsiBatteryStateChanged_batteryPresentInvalidCapacity_noopnull124     fun onStylusUsiBatteryStateChanged_batteryPresentInvalidCapacity_noop() {
125         val batteryState = FixedCapacityBatteryState(0f)
126 
127         startable.onStylusUsiBatteryStateChanged(STYLUS_DEVICE_ID, 123, batteryState)
128 
129         verifyNoMoreInteractions(stylusUsiPowerUi)
130     }
131 
132     @Test
onStylusUsiBatteryStateChanged_batteryNotPresent_noopnull133     fun onStylusUsiBatteryStateChanged_batteryNotPresent_noop() {
134         val batteryState = mock(BatteryState::class.java)
135         whenever(batteryState.isPresent).thenReturn(false)
136 
137         startable.onStylusUsiBatteryStateChanged(STYLUS_DEVICE_ID, 123, batteryState)
138 
139         verifyNoMoreInteractions(stylusUsiPowerUi)
140     }
141 
142     companion object {
143         private const val EXTERNAL_DEVICE_ID = 0
144         private const val STYLUS_DEVICE_ID = 1
145     }
146 }
147