1 /* 2 * Copyright (C) 2019 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.attention; 18 19 import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE; 20 21 import static com.android.server.attention.AttentionManagerService.ATTENTION_CACHE_BUFFER_SIZE; 22 import static com.android.server.attention.AttentionManagerService.DEFAULT_STALE_AFTER_MILLIS; 23 import static com.android.server.attention.AttentionManagerService.KEY_STALE_AFTER_MILLIS; 24 25 import static com.google.common.truth.Truth.assertThat; 26 27 import static junit.framework.Assert.fail; 28 29 import static org.mockito.ArgumentMatchers.any; 30 import static org.mockito.ArgumentMatchers.anyInt; 31 import static org.mockito.ArgumentMatchers.anyLong; 32 import static org.mockito.Mockito.doNothing; 33 import static org.mockito.Mockito.doReturn; 34 import static org.mockito.Mockito.times; 35 import static org.mockito.Mockito.verify; 36 import static org.mockito.Mockito.verifyNoMoreInteractions; 37 import static org.mockito.Mockito.verifyZeroInteractions; 38 39 import android.attention.AttentionManagerInternal.AttentionCallbackInternal; 40 import android.attention.AttentionManagerInternal.ProximityUpdateCallbackInternal; 41 import android.content.ComponentName; 42 import android.content.Context; 43 import android.os.IBinder; 44 import android.os.IPowerManager; 45 import android.os.IThermalService; 46 import android.os.PowerManager; 47 import android.os.RemoteException; 48 import android.provider.DeviceConfig; 49 import android.service.attention.IAttentionCallback; 50 import android.service.attention.IAttentionService; 51 import android.service.attention.IProximityUpdateCallback; 52 53 import androidx.test.filters.SmallTest; 54 55 import com.android.server.attention.AttentionManagerService.AttentionCheck; 56 import com.android.server.attention.AttentionManagerService.AttentionCheckCache; 57 import com.android.server.attention.AttentionManagerService.AttentionCheckCacheBuffer; 58 import com.android.server.attention.AttentionManagerService.AttentionHandler; 59 import com.android.server.attention.AttentionManagerService.ProximityUpdate; 60 61 import org.junit.Before; 62 import org.junit.Test; 63 import org.mockito.Mock; 64 import org.mockito.Mockito; 65 import org.mockito.MockitoAnnotations; 66 67 /** 68 * Tests for {@link com.android.server.attention.AttentionManagerService} 69 */ 70 @SuppressWarnings("GuardedBy") 71 @SmallTest 72 public class AttentionManagerServiceTest { 73 private static final double PROXIMITY_SUCCESS_STATE = 1.0; 74 private AttentionManagerService mSpyAttentionManager; 75 private final int mTimeout = 1000; 76 private final Object mLock = new Object(); 77 @Mock 78 private AttentionCallbackInternal mMockAttentionCallbackInternal; 79 @Mock 80 private AttentionHandler mMockHandler; 81 @Mock 82 private IPowerManager mMockIPowerManager; 83 @Mock 84 private IThermalService mMockIThermalService; 85 @Mock 86 Context mContext; 87 @Mock 88 private ProximityUpdateCallbackInternal mMockProximityUpdateCallbackInternal; 89 90 @Before setUp()91 public void setUp() throws RemoteException { 92 MockitoAnnotations.initMocks(this); 93 // setup context mock 94 doReturn(true).when(mContext).bindServiceAsUser(any(), any(), anyInt(), any()); 95 // setup power manager mock 96 PowerManager mPowerManager; 97 doReturn(true).when(mMockIPowerManager).isInteractive(); 98 mPowerManager = new PowerManager(mContext, mMockIPowerManager, mMockIThermalService, null); 99 100 // setup a spy on attention manager 101 AttentionManagerService attentionManager = new AttentionManagerService( 102 mContext, 103 mPowerManager, 104 mLock, 105 mMockHandler); 106 mSpyAttentionManager = Mockito.spy(attentionManager); 107 // setup a spy on user state 108 ComponentName componentName = new ComponentName("a", "b"); 109 mSpyAttentionManager.mComponentName = componentName; 110 111 AttentionCheck attentionCheck = new AttentionCheck(mMockAttentionCallbackInternal, 112 mSpyAttentionManager); 113 mSpyAttentionManager.mCurrentAttentionCheck = attentionCheck; 114 mSpyAttentionManager.mService = new MockIAttentionService(); 115 doNothing().when(mSpyAttentionManager).freeIfInactiveLocked(); 116 } 117 118 @Test testRegisterProximityUpdates_returnFalseWhenServiceDisabled()119 public void testRegisterProximityUpdates_returnFalseWhenServiceDisabled() { 120 mSpyAttentionManager.mIsServiceEnabled = false; 121 122 assertThat(mSpyAttentionManager.onStartProximityUpdates( 123 mMockProximityUpdateCallbackInternal)) 124 .isFalse(); 125 } 126 127 @Test testRegisterProximityUpdates_returnFalseWhenServiceUnavailable()128 public void testRegisterProximityUpdates_returnFalseWhenServiceUnavailable() { 129 mSpyAttentionManager.mIsServiceEnabled = true; 130 doReturn(false).when(mSpyAttentionManager).isServiceAvailable(); 131 132 assertThat(mSpyAttentionManager.onStartProximityUpdates( 133 mMockProximityUpdateCallbackInternal)) 134 .isFalse(); 135 } 136 137 @Test testRegisterProximityUpdates_returnFalseWhenPowerManagerNotInteract()138 public void testRegisterProximityUpdates_returnFalseWhenPowerManagerNotInteract() 139 throws RemoteException { 140 mSpyAttentionManager.mIsServiceEnabled = true; 141 doReturn(true).when(mSpyAttentionManager).isServiceAvailable(); 142 doReturn(false).when(mMockIPowerManager).isInteractive(); 143 144 assertThat(mSpyAttentionManager.onStartProximityUpdates( 145 mMockProximityUpdateCallbackInternal)) 146 .isFalse(); 147 } 148 149 @Test testRegisterProximityUpdates_callOnSuccess()150 public void testRegisterProximityUpdates_callOnSuccess() throws RemoteException { 151 mSpyAttentionManager.mIsServiceEnabled = true; 152 doReturn(true).when(mSpyAttentionManager).isServiceAvailable(); 153 doReturn(true).when(mMockIPowerManager).isInteractive(); 154 155 assertThat(mSpyAttentionManager.onStartProximityUpdates( 156 mMockProximityUpdateCallbackInternal)) 157 .isTrue(); 158 verify(mMockProximityUpdateCallbackInternal, times(1)) 159 .onProximityUpdate(PROXIMITY_SUCCESS_STATE); 160 } 161 162 @Test testRegisterProximityUpdates_callOnSuccessTwiceInARow()163 public void testRegisterProximityUpdates_callOnSuccessTwiceInARow() throws RemoteException { 164 mSpyAttentionManager.mIsServiceEnabled = true; 165 doReturn(true).when(mSpyAttentionManager).isServiceAvailable(); 166 doReturn(true).when(mMockIPowerManager).isInteractive(); 167 168 assertThat(mSpyAttentionManager.onStartProximityUpdates( 169 mMockProximityUpdateCallbackInternal)) 170 .isTrue(); 171 172 ProximityUpdate prevProximityUpdate = mSpyAttentionManager.mCurrentProximityUpdate; 173 assertThat(mSpyAttentionManager.onStartProximityUpdates( 174 mMockProximityUpdateCallbackInternal)) 175 .isTrue(); 176 assertThat(mSpyAttentionManager.mCurrentProximityUpdate).isEqualTo(prevProximityUpdate); 177 verify(mMockProximityUpdateCallbackInternal, times(1)) 178 .onProximityUpdate(PROXIMITY_SUCCESS_STATE); 179 } 180 181 @Test testUnregisterProximityUpdates_noCrashWhenNoCallbackIsRegistered()182 public void testUnregisterProximityUpdates_noCrashWhenNoCallbackIsRegistered() { 183 mSpyAttentionManager.onStopProximityUpdates(mMockProximityUpdateCallbackInternal); 184 verifyZeroInteractions(mMockProximityUpdateCallbackInternal); 185 } 186 187 @Test testUnregisterProximityUpdates_noCrashWhenCallbackMismatched()188 public void testUnregisterProximityUpdates_noCrashWhenCallbackMismatched() 189 throws RemoteException { 190 mSpyAttentionManager.mIsServiceEnabled = true; 191 doReturn(true).when(mSpyAttentionManager).isServiceAvailable(); 192 doReturn(true).when(mMockIPowerManager).isInteractive(); 193 mSpyAttentionManager.onStartProximityUpdates(mMockProximityUpdateCallbackInternal); 194 verify(mMockProximityUpdateCallbackInternal, times(1)) 195 .onProximityUpdate(PROXIMITY_SUCCESS_STATE); 196 197 ProximityUpdateCallbackInternal mismatchedCallback = new ProximityUpdateCallbackInternal() { 198 @Override 199 public void onProximityUpdate(double distance) { 200 fail("Callback shouldn't have responded."); 201 } 202 }; 203 mSpyAttentionManager.onStopProximityUpdates(mismatchedCallback); 204 205 verifyNoMoreInteractions(mMockProximityUpdateCallbackInternal); 206 } 207 208 @Test testUnregisterProximityUpdates_cancelRegistrationWhenMatched()209 public void testUnregisterProximityUpdates_cancelRegistrationWhenMatched() 210 throws RemoteException { 211 mSpyAttentionManager.mIsServiceEnabled = true; 212 doReturn(true).when(mSpyAttentionManager).isServiceAvailable(); 213 doReturn(true).when(mMockIPowerManager).isInteractive(); 214 mSpyAttentionManager.onStartProximityUpdates(mMockProximityUpdateCallbackInternal); 215 mSpyAttentionManager.onStopProximityUpdates(mMockProximityUpdateCallbackInternal); 216 217 assertThat(mSpyAttentionManager.mCurrentProximityUpdate).isNull(); 218 } 219 220 @Test testUnregisterProximityUpdates_noCrashWhenTwiceInARow()221 public void testUnregisterProximityUpdates_noCrashWhenTwiceInARow() throws RemoteException { 222 // Attention Service registers proximity updates. 223 mSpyAttentionManager.mIsServiceEnabled = true; 224 doReturn(true).when(mSpyAttentionManager).isServiceAvailable(); 225 doReturn(true).when(mMockIPowerManager).isInteractive(); 226 mSpyAttentionManager.onStartProximityUpdates(mMockProximityUpdateCallbackInternal); 227 verify(mMockProximityUpdateCallbackInternal, times(1)) 228 .onProximityUpdate(PROXIMITY_SUCCESS_STATE); 229 230 // Attention Service unregisters the proximity update twice in a row. 231 mSpyAttentionManager.onStopProximityUpdates(mMockProximityUpdateCallbackInternal); 232 mSpyAttentionManager.onStopProximityUpdates(mMockProximityUpdateCallbackInternal); 233 verifyNoMoreInteractions(mMockProximityUpdateCallbackInternal); 234 } 235 236 @Test testCancelAttentionCheck_noCrashWhenCallbackMismatched()237 public void testCancelAttentionCheck_noCrashWhenCallbackMismatched() { 238 assertThat(mMockAttentionCallbackInternal).isNotNull(); 239 mSpyAttentionManager.cancelAttentionCheck(null); 240 } 241 242 @Test testCancelAttentionCheck_cancelCallbackWhenMatched()243 public void testCancelAttentionCheck_cancelCallbackWhenMatched() { 244 mSpyAttentionManager.cancelAttentionCheck(mMockAttentionCallbackInternal); 245 verify(mSpyAttentionManager).cancel(); 246 } 247 248 @Test testCheckAttention_returnFalseWhenPowerManagerNotInteract()249 public void testCheckAttention_returnFalseWhenPowerManagerNotInteract() throws RemoteException { 250 mSpyAttentionManager.mIsServiceEnabled = true; 251 doReturn(false).when(mMockIPowerManager).isInteractive(); 252 AttentionCallbackInternal callback = Mockito.mock(AttentionCallbackInternal.class); 253 assertThat(mSpyAttentionManager.checkAttention(mTimeout, callback)).isFalse(); 254 } 255 256 @Test testCheckAttention_callOnSuccess()257 public void testCheckAttention_callOnSuccess() throws RemoteException { 258 mSpyAttentionManager.mIsServiceEnabled = true; 259 doReturn(true).when(mSpyAttentionManager).isServiceAvailable(); 260 doReturn(true).when(mMockIPowerManager).isInteractive(); 261 mSpyAttentionManager.mCurrentAttentionCheck = null; 262 263 AttentionCallbackInternal callback = Mockito.mock(AttentionCallbackInternal.class); 264 mSpyAttentionManager.checkAttention(mTimeout, callback); 265 verify(callback).onSuccess(anyInt(), anyLong()); 266 } 267 268 @Test testAttentionCheckCacheBuffer_getLast_returnTheLastElement()269 public void testAttentionCheckCacheBuffer_getLast_returnTheLastElement() { 270 AttentionCheckCacheBuffer buffer = new AttentionCheckCacheBuffer(); 271 buffer.add(new AttentionCheckCache(0, 0, 1L)); 272 AttentionCheckCache cache = new AttentionCheckCache(0, 0, 2L); 273 buffer.add(cache); 274 assertThat(buffer.getLast()).isEqualTo(cache); 275 } 276 277 @Test testAttentionCheckCacheBuffer_get_returnNullWhenOutOfBoundary()278 public void testAttentionCheckCacheBuffer_get_returnNullWhenOutOfBoundary() { 279 AttentionCheckCacheBuffer buffer = new AttentionCheckCacheBuffer(); 280 assertThat(buffer.get(1)).isNull(); 281 } 282 283 @Test testAttentionCheckCacheBuffer_get_handleCircularIndexing()284 public void testAttentionCheckCacheBuffer_get_handleCircularIndexing() { 285 AttentionCheckCacheBuffer buffer = new AttentionCheckCacheBuffer(); 286 AttentionCheckCache cache = new AttentionCheckCache(0L, 0, 1L); 287 // Insert SIZE+1 elements. 288 for (int i = 0; i <= ATTENTION_CACHE_BUFFER_SIZE; i++) { 289 if (i == 1) { 290 buffer.add(cache); 291 } else { 292 buffer.add(new AttentionCheckCache(0L, 0, i)); 293 } 294 } 295 // The element that was at index 1 should be at index 0 after inserting SIZE + 1 elements. 296 assertThat(buffer.get(0)).isEqualTo(cache); 297 } 298 299 @Test testGetStaleAfterMillis_handlesGoodFlagValue()300 public void testGetStaleAfterMillis_handlesGoodFlagValue() { 301 DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, 302 KEY_STALE_AFTER_MILLIS, "123", false); 303 assertThat(mSpyAttentionManager.getStaleAfterMillis()).isEqualTo(123); 304 } 305 306 @Test testGetStaleAfterMillis_handlesBadFlagValue_1()307 public void testGetStaleAfterMillis_handlesBadFlagValue_1() { 308 DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, 309 KEY_STALE_AFTER_MILLIS, "-123", false); 310 assertThat(mSpyAttentionManager.getStaleAfterMillis()).isEqualTo( 311 DEFAULT_STALE_AFTER_MILLIS); 312 } 313 314 @Test testGetStaleAfterMillis_handlesBadFlagValue_2()315 public void testGetStaleAfterMillis_handlesBadFlagValue_2() { 316 DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, 317 KEY_STALE_AFTER_MILLIS, "15000", false); 318 assertThat(mSpyAttentionManager.getStaleAfterMillis()).isEqualTo( 319 DEFAULT_STALE_AFTER_MILLIS); 320 } 321 322 @Test testGetStaleAfterMillis_handlesBadFlagValue_3()323 public void testGetStaleAfterMillis_handlesBadFlagValue_3() { 324 DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, 325 KEY_STALE_AFTER_MILLIS, "abracadabra", false); 326 assertThat(mSpyAttentionManager.getStaleAfterMillis()).isEqualTo( 327 DEFAULT_STALE_AFTER_MILLIS); 328 } 329 330 @Test testGetStaleAfterMillis_handlesBadFlagValue_4()331 public void testGetStaleAfterMillis_handlesBadFlagValue_4() { 332 DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, 333 KEY_STALE_AFTER_MILLIS, "15_000L", false); 334 assertThat(mSpyAttentionManager.getStaleAfterMillis()).isEqualTo( 335 DEFAULT_STALE_AFTER_MILLIS); 336 } 337 338 private class MockIAttentionService implements IAttentionService { checkAttention(IAttentionCallback callback)339 public void checkAttention(IAttentionCallback callback) throws RemoteException { 340 callback.onSuccess(0, 0); 341 } 342 cancelAttentionCheck(IAttentionCallback callback)343 public void cancelAttentionCheck(IAttentionCallback callback) { 344 } 345 onStartProximityUpdates(IProximityUpdateCallback callback)346 public void onStartProximityUpdates(IProximityUpdateCallback callback) 347 throws RemoteException { 348 callback.onProximityUpdate(PROXIMITY_SUCCESS_STATE); 349 } 350 onStopProximityUpdates()351 public void onStopProximityUpdates() throws RemoteException { 352 } 353 asBinder()354 public IBinder asBinder() { 355 return null; 356 } 357 } 358 } 359