1 /* 2 * Copyright (C) 2018 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 com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assert.assertArrayEquals; 22 import static org.junit.Assert.assertEquals; 23 import static org.junit.Assert.assertFalse; 24 import static org.junit.Assert.assertNotNull; 25 import static org.junit.Assert.assertTrue; 26 import static org.mockito.AdditionalMatchers.aryEq; 27 import static org.mockito.ArgumentMatchers.any; 28 import static org.mockito.ArgumentMatchers.anyFloat; 29 import static org.mockito.ArgumentMatchers.anyInt; 30 import static org.mockito.ArgumentMatchers.eq; 31 import static org.mockito.Mockito.doReturn; 32 import static org.mockito.Mockito.mock; 33 import static org.mockito.Mockito.reset; 34 import static org.mockito.Mockito.timeout; 35 import static org.mockito.Mockito.times; 36 import static org.mockito.Mockito.verify; 37 import static org.mockito.Mockito.when; 38 39 import android.content.Context; 40 import android.content.pm.PackageManager; 41 import android.hardware.thermal.TemperatureThreshold; 42 import android.hardware.thermal.ThrottlingSeverity; 43 import android.os.CoolingDevice; 44 import android.os.Flags; 45 import android.os.IBinder; 46 import android.os.IPowerManager; 47 import android.os.IThermalEventListener; 48 import android.os.IThermalHeadroomListener; 49 import android.os.IThermalService; 50 import android.os.IThermalStatusListener; 51 import android.os.PowerManager; 52 import android.os.RemoteException; 53 import android.os.Temperature; 54 import android.platform.test.annotations.DisableFlags; 55 import android.platform.test.annotations.EnableFlags; 56 import android.platform.test.flag.junit.SetFlagsRule; 57 58 import androidx.test.filters.SmallTest; 59 import androidx.test.runner.AndroidJUnit4; 60 61 import com.android.server.SystemService; 62 import com.android.server.power.ThermalManagerService.TemperatureWatcher; 63 import com.android.server.power.ThermalManagerService.ThermalHalWrapper; 64 65 import org.junit.Before; 66 import org.junit.ClassRule; 67 import org.junit.Rule; 68 import org.junit.Test; 69 import org.junit.runner.RunWith; 70 import org.mockito.ArgumentCaptor; 71 import org.mockito.Mock; 72 import org.mockito.MockitoAnnotations; 73 74 import java.io.FileDescriptor; 75 import java.io.PrintWriter; 76 import java.io.StringWriter; 77 import java.util.ArrayList; 78 import java.util.Arrays; 79 import java.util.HashSet; 80 import java.util.List; 81 import java.util.Map; 82 import java.util.concurrent.atomic.AtomicInteger; 83 84 /** 85 * atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server 86 * /power/ThermalManagerServiceTest.java 87 */ 88 @SmallTest 89 @RunWith(AndroidJUnit4.class) 90 public class ThermalManagerServiceTest { 91 @ClassRule 92 public static final SetFlagsRule.ClassRule mSetFlagsClassRule = new SetFlagsRule.ClassRule(); 93 @Rule 94 public final SetFlagsRule mSetFlagsRule = mSetFlagsClassRule.createSetFlagsRule(); 95 96 private static final long CALLBACK_TIMEOUT_MILLI_SEC = 5000; 97 private ThermalManagerService mService; 98 private ThermalHalFake mFakeHal; 99 private PowerManager mPowerManager; 100 @Mock 101 private Context mContext; 102 @Mock 103 private IPowerManager mIPowerManagerMock; 104 @Mock 105 private IThermalService mIThermalServiceMock; 106 @Mock 107 private IThermalHeadroomListener mHeadroomListener; 108 @Mock 109 private IThermalEventListener mEventListener1; 110 @Mock 111 private IThermalEventListener mEventListener2; 112 @Mock 113 private IThermalStatusListener mStatusListener1; 114 @Mock 115 private IThermalStatusListener mStatusListener2; 116 117 /** 118 * Fake Hal class. 119 */ 120 private class ThermalHalFake extends ThermalHalWrapper { 121 private static final int INIT_STATUS = Temperature.THROTTLING_NONE; 122 private final List<Temperature> mTemperatureList = new ArrayList<>(); 123 private AtomicInteger mGetCurrentTemperaturesCalled = new AtomicInteger(); 124 private List<CoolingDevice> mCoolingDeviceList = new ArrayList<>(); 125 private List<TemperatureThreshold> mTemperatureThresholdList = initializeThresholds(); 126 127 private Temperature mSkin1 = new Temperature(28, Temperature.TYPE_SKIN, "skin1", 128 INIT_STATUS); 129 private Temperature mSkin2 = new Temperature(31, Temperature.TYPE_SKIN, "skin2", 130 INIT_STATUS); 131 private Temperature mBattery = new Temperature(34, Temperature.TYPE_BATTERY, "batt", 132 INIT_STATUS); 133 private Temperature mUsbPort = new Temperature(37, Temperature.TYPE_USB_PORT, "usbport", 134 INIT_STATUS); 135 private CoolingDevice mCpu = new CoolingDevice(40, CoolingDevice.TYPE_BATTERY, "cpu"); 136 private CoolingDevice mGpu = new CoolingDevice(43, CoolingDevice.TYPE_BATTERY, "gpu"); 137 private Map<Integer, Float> mForecastSkinTemperatures = null; 138 private int mForecastSkinTemperaturesCalled = 0; 139 private boolean mForecastSkinTemperaturesError = false; 140 initializeThresholds()141 private List<TemperatureThreshold> initializeThresholds() { 142 ArrayList<TemperatureThreshold> thresholds = new ArrayList<>(); 143 144 TemperatureThreshold skinThreshold = new TemperatureThreshold(); 145 skinThreshold.type = Temperature.TYPE_SKIN; 146 skinThreshold.name = "skin1"; 147 skinThreshold.hotThrottlingThresholds = new float[7 /*ThrottlingSeverity#len*/]; 148 skinThreshold.coldThrottlingThresholds = new float[7 /*ThrottlingSeverity#len*/]; 149 for (int i = 0; i < skinThreshold.hotThrottlingThresholds.length; ++i) { 150 // Sets NONE to 25.0f, SEVERE to 40.0f, and SHUTDOWN to 55.0f 151 skinThreshold.hotThrottlingThresholds[i] = 25.0f + 5.0f * i; 152 } 153 thresholds.add(skinThreshold); 154 155 TemperatureThreshold cpuThreshold = new TemperatureThreshold(); 156 cpuThreshold.type = Temperature.TYPE_CPU; 157 cpuThreshold.name = "cpu"; 158 cpuThreshold.hotThrottlingThresholds = new float[7 /*ThrottlingSeverity#len*/]; 159 cpuThreshold.coldThrottlingThresholds = new float[7 /*ThrottlingSeverity#len*/]; 160 for (int i = 0; i < cpuThreshold.hotThrottlingThresholds.length; ++i) { 161 if (i == ThrottlingSeverity.SEVERE) { 162 cpuThreshold.hotThrottlingThresholds[i] = 95.0f; 163 } else { 164 cpuThreshold.hotThrottlingThresholds[i] = Float.NaN; 165 } 166 } 167 thresholds.add(cpuThreshold); 168 169 return thresholds; 170 } 171 ThermalHalFake()172 ThermalHalFake() { 173 mTemperatureList.add(mSkin1); 174 mTemperatureList.add(mSkin2); 175 mTemperatureList.add(mBattery); 176 mTemperatureList.add(mUsbPort); 177 mCoolingDeviceList.add(mCpu); 178 mCoolingDeviceList.add(mGpu); 179 mGetCurrentTemperaturesCalled.set(0); 180 } 181 enableForecastSkinTemperature()182 void enableForecastSkinTemperature() { 183 mForecastSkinTemperatures = Map.of(0, 22.0f, 10, 25.0f, 20, 28.0f, 184 30, 31.0f, 40, 34.0f, 50, 37.0f, 60, 40.0f); 185 } 186 disableForecastSkinTemperature()187 void disableForecastSkinTemperature() { 188 mForecastSkinTemperatures = null; 189 } 190 failForecastSkinTemperature()191 void failForecastSkinTemperature() { 192 mForecastSkinTemperaturesError = true; 193 } 194 updateTemperatureList(Temperature... temperatures)195 void updateTemperatureList(Temperature... temperatures) { 196 synchronized (mTemperatureList) { 197 mTemperatureList.clear(); 198 mTemperatureList.addAll(Arrays.asList(temperatures)); 199 } 200 } 201 202 @Override getCurrentTemperatures(boolean shouldFilter, int type)203 protected List<Temperature> getCurrentTemperatures(boolean shouldFilter, int type) { 204 List<Temperature> ret = new ArrayList<>(); 205 synchronized (mTemperatureList) { 206 mGetCurrentTemperaturesCalled.incrementAndGet(); 207 for (Temperature temperature : mTemperatureList) { 208 if (shouldFilter && type != temperature.getType()) { 209 continue; 210 } 211 ret.add(temperature); 212 } 213 } 214 return ret; 215 } 216 217 @Override getCurrentCoolingDevices(boolean shouldFilter, int type)218 protected List<CoolingDevice> getCurrentCoolingDevices(boolean shouldFilter, int type) { 219 List<CoolingDevice> ret = new ArrayList<>(); 220 for (CoolingDevice cdev : mCoolingDeviceList) { 221 if (shouldFilter && type != cdev.getType()) { 222 continue; 223 } 224 ret.add(cdev); 225 } 226 return ret; 227 } 228 229 @Override getTemperatureThresholds(boolean shouldFilter, int type)230 protected List<TemperatureThreshold> getTemperatureThresholds(boolean shouldFilter, 231 int type) { 232 List<TemperatureThreshold> ret = new ArrayList<>(); 233 for (TemperatureThreshold threshold : mTemperatureThresholdList) { 234 if (shouldFilter && type != threshold.type) { 235 continue; 236 } 237 ret.add(threshold); 238 } 239 return ret; 240 } 241 242 @Override forecastSkinTemperature(int forecastSeconds)243 protected float forecastSkinTemperature(int forecastSeconds) { 244 mForecastSkinTemperaturesCalled++; 245 if (mForecastSkinTemperaturesError) { 246 throw new RuntimeException(); 247 } 248 if (mForecastSkinTemperatures == null) { 249 throw new UnsupportedOperationException(); 250 } 251 return mForecastSkinTemperatures.get(forecastSeconds); 252 } 253 254 @Override connectToHal()255 protected boolean connectToHal() { 256 return true; 257 } 258 259 @Override dump(PrintWriter pw, String prefix)260 protected void dump(PrintWriter pw, String prefix) { 261 pw.print(prefix); 262 pw.println("ThermalHAL AIDL 1 connected: yes"); 263 } 264 } 265 assertListEqualsIgnoringOrder(List<?> actual, List<?> expected)266 private void assertListEqualsIgnoringOrder(List<?> actual, List<?> expected) { 267 HashSet<?> actualSet = new HashSet<>(actual); 268 HashSet<?> expectedSet = new HashSet<>(expected); 269 assertEquals(expectedSet, actualSet); 270 } 271 272 @Before setUp()273 public void setUp() throws RemoteException { 274 MockitoAnnotations.initMocks(this); 275 mFakeHal = new ThermalHalFake(); 276 mPowerManager = new PowerManager(mContext, mIPowerManagerMock, mIThermalServiceMock, null); 277 when(mContext.getSystemServiceName(PowerManager.class)).thenReturn(Context.POWER_SERVICE); 278 when(mContext.getSystemService(PowerManager.class)).thenReturn(mPowerManager); 279 resetListenerMock(); 280 mService = new ThermalManagerService(mContext, mFakeHal); 281 mService.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY); 282 } 283 resetListenerMock()284 private void resetListenerMock() { 285 reset(mEventListener1); 286 reset(mStatusListener1); 287 reset(mEventListener2); 288 reset(mStatusListener2); 289 reset(mHeadroomListener); 290 doReturn(mock(IBinder.class)).when(mEventListener1).asBinder(); 291 doReturn(mock(IBinder.class)).when(mStatusListener1).asBinder(); 292 doReturn(mock(IBinder.class)).when(mEventListener2).asBinder(); 293 doReturn(mock(IBinder.class)).when(mStatusListener2).asBinder(); 294 doReturn(mock(IBinder.class)).when(mHeadroomListener).asBinder(); 295 } 296 297 @Test testRegister()298 public void testRegister() throws Exception { 299 mService = new ThermalManagerService(mContext, mFakeHal); 300 // Register callbacks before AMS ready and verify they are called after AMS is ready 301 assertTrue(mService.mService.registerThermalEventListener(mEventListener1)); 302 assertTrue(mService.mService.registerThermalStatusListener(mStatusListener1)); 303 assertTrue(mService.mService.registerThermalEventListenerWithType(mEventListener2, 304 Temperature.TYPE_SKIN)); 305 assertTrue(mService.mService.registerThermalStatusListener(mStatusListener2)); 306 Thread.sleep(CALLBACK_TIMEOUT_MILLI_SEC); 307 resetListenerMock(); 308 mService.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY); 309 assertTrue(mService.mService.registerThermalHeadroomListener(mHeadroomListener)); 310 311 ArgumentCaptor<Temperature> captor = ArgumentCaptor.forClass(Temperature.class); 312 verify(mEventListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 313 .times(4)).notifyThrottling(captor.capture()); 314 assertListEqualsIgnoringOrder(mFakeHal.mTemperatureList, captor.getAllValues()); 315 verify(mStatusListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 316 .times(0)).onStatusChange(Temperature.THROTTLING_NONE); 317 captor = ArgumentCaptor.forClass(Temperature.class); 318 verify(mEventListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 319 .times(2)).notifyThrottling(captor.capture()); 320 assertListEqualsIgnoringOrder( 321 new ArrayList<>(Arrays.asList(mFakeHal.mSkin1, mFakeHal.mSkin2)), 322 captor.getAllValues()); 323 verify(mStatusListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 324 .times(0)).onStatusChange(Temperature.THROTTLING_NONE); 325 resetListenerMock(); 326 327 // Register callbacks after AMS ready and verify they are called 328 assertTrue(mService.mService.registerThermalEventListener(mEventListener1)); 329 assertTrue(mService.mService.registerThermalStatusListener(mStatusListener1)); 330 captor = ArgumentCaptor.forClass(Temperature.class); 331 verify(mEventListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 332 .times(4)).notifyThrottling(captor.capture()); 333 assertListEqualsIgnoringOrder(mFakeHal.mTemperatureList, captor.getAllValues()); 334 verify(mStatusListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 335 .times(1)).onStatusChange(Temperature.THROTTLING_NONE); 336 337 // Register new callbacks and verify old ones are not called (remained same) while new 338 // ones are called 339 assertTrue(mService.mService.registerThermalEventListenerWithType(mEventListener2, 340 Temperature.TYPE_SKIN)); 341 assertTrue(mService.mService.registerThermalStatusListener(mStatusListener2)); 342 verify(mEventListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 343 .times(4)).notifyThrottling(any(Temperature.class)); 344 verify(mStatusListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 345 .times(1)).onStatusChange(Temperature.THROTTLING_NONE); 346 captor = ArgumentCaptor.forClass(Temperature.class); 347 verify(mEventListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 348 .times(2)).notifyThrottling(captor.capture()); 349 assertListEqualsIgnoringOrder( 350 new ArrayList<>(Arrays.asList(mFakeHal.mSkin1, mFakeHal.mSkin2)), 351 captor.getAllValues()); 352 verify(mStatusListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 353 .times(1)).onStatusChange(Temperature.THROTTLING_NONE); 354 } 355 356 @Test testNotifyThrottling()357 public void testNotifyThrottling() throws Exception { 358 assertTrue(mService.mService.registerThermalEventListener(mEventListener1)); 359 assertTrue(mService.mService.registerThermalStatusListener(mStatusListener1)); 360 assertTrue(mService.mService.registerThermalEventListenerWithType(mEventListener2, 361 Temperature.TYPE_SKIN)); 362 assertTrue(mService.mService.registerThermalStatusListener(mStatusListener2)); 363 Thread.sleep(CALLBACK_TIMEOUT_MILLI_SEC); 364 resetListenerMock(); 365 366 int status = Temperature.THROTTLING_SEVERE; 367 // Should only notify event not status 368 Temperature newBattery = new Temperature(50, Temperature.TYPE_BATTERY, "batt", status); 369 mFakeHal.mCallback.onTemperatureChanged(newBattery); 370 verify(mEventListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 371 .times(1)).notifyThrottling(newBattery); 372 verify(mStatusListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 373 .times(0)).onStatusChange(anyInt()); 374 verify(mEventListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 375 .times(0)).notifyThrottling(newBattery); 376 verify(mStatusListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 377 .times(0)).onStatusChange(anyInt()); 378 resetListenerMock(); 379 // Notify both event and status 380 Temperature newSkin = new Temperature(50, Temperature.TYPE_SKIN, "skin1", status); 381 mFakeHal.mCallback.onTemperatureChanged(newSkin); 382 verify(mEventListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 383 .times(1)).notifyThrottling(newSkin); 384 verify(mStatusListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 385 .times(1)).onStatusChange(status); 386 verify(mEventListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 387 .times(1)).notifyThrottling(newSkin); 388 verify(mStatusListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 389 .times(1)).onStatusChange(status); 390 resetListenerMock(); 391 // Back to None, should only notify event not status 392 status = Temperature.THROTTLING_NONE; 393 newBattery = new Temperature(50, Temperature.TYPE_BATTERY, "batt", status); 394 mFakeHal.mCallback.onTemperatureChanged(newBattery); 395 verify(mEventListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 396 .times(1)).notifyThrottling(newBattery); 397 verify(mStatusListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 398 .times(0)).onStatusChange(anyInt()); 399 verify(mEventListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 400 .times(0)).notifyThrottling(newBattery); 401 verify(mStatusListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 402 .times(0)).onStatusChange(anyInt()); 403 resetListenerMock(); 404 // Should also notify status 405 newSkin = new Temperature(50, Temperature.TYPE_SKIN, "skin1", status); 406 mFakeHal.mCallback.onTemperatureChanged(newSkin); 407 verify(mEventListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 408 .times(1)).notifyThrottling(newSkin); 409 verify(mStatusListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 410 .times(1)).onStatusChange(status); 411 verify(mEventListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 412 .times(1)).notifyThrottling(newSkin); 413 verify(mStatusListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 414 .times(1)).onStatusChange(status); 415 } 416 417 @Test 418 @EnableFlags({Flags.FLAG_ALLOW_THERMAL_THRESHOLDS_CALLBACK}) testNotifyThrottling_headroomCallback()419 public void testNotifyThrottling_headroomCallback() throws Exception { 420 assertTrue(mService.mService.registerThermalHeadroomListener(mHeadroomListener)); 421 Thread.sleep(CALLBACK_TIMEOUT_MILLI_SEC); 422 resetListenerMock(); 423 int status = Temperature.THROTTLING_SEVERE; 424 mFakeHal.updateTemperatureList(); 425 426 // Should not notify on non-skin type 427 Temperature newBattery = new Temperature(37, Temperature.TYPE_BATTERY, "batt", status); 428 mFakeHal.mCallback.onTemperatureChanged(newBattery); 429 verify(mHeadroomListener, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 430 .times(0)).onHeadroomChange(anyFloat(), anyFloat(), anyInt(), any()); 431 resetListenerMock(); 432 433 // Notify headroom on skin temperature change 434 Temperature newSkin = new Temperature(37, Temperature.TYPE_SKIN, "skin1", status); 435 mFakeHal.mCallback.onTemperatureChanged(newSkin); 436 verify(mHeadroomListener, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 437 .times(1)).onHeadroomChange(eq(0.9f), anyFloat(), anyInt(), 438 eq(new float[]{Float.NaN, 0.6666667f, 0.8333333f, 1.0f, 1.1666666f, 1.3333334f, 439 1.5f})); 440 resetListenerMock(); 441 442 // Same or similar temperature should not trigger in a short period 443 mFakeHal.mCallback.onTemperatureChanged(newSkin); 444 newSkin = new Temperature(36.9f, Temperature.TYPE_SKIN, "skin1", status); 445 mFakeHal.mCallback.onTemperatureChanged(newSkin); 446 newSkin = new Temperature(37.1f, Temperature.TYPE_SKIN, "skin1", status); 447 mFakeHal.mCallback.onTemperatureChanged(newSkin); 448 verify(mHeadroomListener, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 449 .times(0)).onHeadroomChange(anyFloat(), anyFloat(), anyInt(), any()); 450 resetListenerMock(); 451 452 // Significant temperature should trigger in a short period 453 newSkin = new Temperature(34f, Temperature.TYPE_SKIN, "skin1", status); 454 mFakeHal.mCallback.onTemperatureChanged(newSkin); 455 verify(mHeadroomListener, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 456 .times(1)).onHeadroomChange(eq(0.8f), anyFloat(), anyInt(), 457 eq(new float[]{Float.NaN, 0.6666667f, 0.8333333f, 1.0f, 1.1666666f, 1.3333334f, 458 1.5f})); 459 resetListenerMock(); 460 newSkin = new Temperature(40f, Temperature.TYPE_SKIN, "skin1", status); 461 mFakeHal.mCallback.onTemperatureChanged(newSkin); 462 verify(mHeadroomListener, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 463 .times(1)).onHeadroomChange(eq(1.0f), anyFloat(), anyInt(), 464 eq(new float[]{Float.NaN, 0.6666667f, 0.8333333f, 1.0f, 1.1666666f, 1.3333334f, 465 1.5f})); 466 } 467 468 @Test testGetCurrentTemperatures()469 public void testGetCurrentTemperatures() throws RemoteException { 470 assertListEqualsIgnoringOrder(mFakeHal.getCurrentTemperatures(false, 0), 471 Arrays.asList(mService.mService.getCurrentTemperatures())); 472 assertListEqualsIgnoringOrder( 473 mFakeHal.getCurrentTemperatures(true, Temperature.TYPE_SKIN), 474 Arrays.asList(mService.mService.getCurrentTemperaturesWithType( 475 Temperature.TYPE_SKIN))); 476 } 477 478 @Test testGetCurrentStatus()479 public void testGetCurrentStatus() throws RemoteException { 480 int status = Temperature.THROTTLING_SEVERE; 481 Temperature newSkin = new Temperature(100, Temperature.TYPE_SKIN, "skin1", status); 482 mFakeHal.mCallback.onTemperatureChanged(newSkin); 483 assertEquals(status, mService.mService.getCurrentThermalStatus()); 484 int battStatus = Temperature.THROTTLING_EMERGENCY; 485 Temperature newBattery = new Temperature(60, Temperature.TYPE_BATTERY, "batt", battStatus); 486 assertEquals(status, mService.mService.getCurrentThermalStatus()); 487 } 488 489 @Test testThermalShutdown()490 public void testThermalShutdown() throws RemoteException { 491 int status = Temperature.THROTTLING_SHUTDOWN; 492 Temperature newSkin = new Temperature(100, Temperature.TYPE_SKIN, "skin1", status); 493 mFakeHal.mCallback.onTemperatureChanged(newSkin); 494 verify(mIPowerManagerMock, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 495 .times(1)).shutdown(false, PowerManager.SHUTDOWN_THERMAL_STATE, false); 496 Temperature newBattery = new Temperature(60, Temperature.TYPE_BATTERY, "batt", status); 497 mFakeHal.mCallback.onTemperatureChanged(newBattery); 498 verify(mIPowerManagerMock, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 499 .times(1)).shutdown(false, PowerManager.SHUTDOWN_BATTERY_THERMAL_STATE, false); 500 } 501 502 @Test testNoHal()503 public void testNoHal() throws RemoteException { 504 mService = new ThermalManagerService(mContext); 505 // Do no call onActivityManagerReady to skip connect HAL 506 assertTrue(mService.mService.registerThermalEventListener(mEventListener1)); 507 assertTrue(mService.mService.registerThermalStatusListener(mStatusListener1)); 508 assertTrue(mService.mService.registerThermalEventListenerWithType(mEventListener2, 509 Temperature.TYPE_SKIN)); 510 assertFalse(mService.mService.registerThermalHeadroomListener(mHeadroomListener)); 511 verify(mEventListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 512 .times(0)).notifyThrottling(any(Temperature.class)); 513 verify(mStatusListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 514 .times(1)).onStatusChange(Temperature.THROTTLING_NONE); 515 verify(mEventListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 516 .times(0)).notifyThrottling(any(Temperature.class)); 517 verify(mHeadroomListener, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 518 .times(0)).onHeadroomChange(anyFloat(), anyFloat(), anyInt(), any()); 519 520 assertEquals(0, Arrays.asList(mService.mService.getCurrentTemperatures()).size()); 521 assertEquals(0, Arrays.asList(mService.mService.getCurrentTemperaturesWithType( 522 Temperature.TYPE_SKIN)).size()); 523 assertEquals(Temperature.THROTTLING_NONE, mService.mService.getCurrentThermalStatus()); 524 assertTrue(Float.isNaN(mService.mService.getThermalHeadroom(0))); 525 526 assertTrue(mService.mService.unregisterThermalEventListener(mEventListener1)); 527 assertTrue(mService.mService.unregisterThermalEventListener(mEventListener2)); 528 assertTrue(mService.mService.unregisterThermalStatusListener(mStatusListener1)); 529 assertFalse(mService.mService.unregisterThermalHeadroomListener(mHeadroomListener)); 530 } 531 532 @Test testGetCurrentCoolingDevices()533 public void testGetCurrentCoolingDevices() throws RemoteException { 534 assertListEqualsIgnoringOrder(mFakeHal.getCurrentCoolingDevices(false, 0), 535 Arrays.asList(mService.mService.getCurrentCoolingDevices())); 536 assertListEqualsIgnoringOrder( 537 mFakeHal.getCurrentCoolingDevices(false, CoolingDevice.TYPE_BATTERY), 538 Arrays.asList(mService.mService.getCurrentCoolingDevices())); 539 assertListEqualsIgnoringOrder( 540 mFakeHal.getCurrentCoolingDevices(true, CoolingDevice.TYPE_CPU), 541 Arrays.asList(mService.mService.getCurrentCoolingDevicesWithType( 542 CoolingDevice.TYPE_CPU))); 543 } 544 545 @Test testGetThermalHeadroomInputRange()546 public void testGetThermalHeadroomInputRange() throws RemoteException { 547 assertTrue(Float.isNaN(mService.mService.getThermalHeadroom( 548 ThermalManagerService.MIN_FORECAST_SEC - 1))); 549 assertTrue(Float.isNaN(mService.mService.getThermalHeadroom( 550 ThermalManagerService.MAX_FORECAST_SEC + 1))); 551 } 552 553 @Test 554 @DisableFlags({Flags.FLAG_ALLOW_THERMAL_HAL_SKIN_FORECAST}) testGetThermalHeadroom_handlerUpdateTemperatures()555 public void testGetThermalHeadroom_handlerUpdateTemperatures() 556 throws RemoteException, InterruptedException { 557 // test that handler will at least enqueue one message to periodically read temperatures 558 // even if there is sample seeded from HAL temperature callback 559 String temperatureName = "skin1"; 560 Temperature temperature = new Temperature(100, Temperature.TYPE_SKIN, temperatureName, 561 Temperature.THROTTLING_NONE); 562 mFakeHal.mCallback.onTemperatureChanged(temperature); 563 float headroom = mService.mService.getThermalHeadroom(0); 564 // the callback temperature 100C (headroom > 1.0f) sample should have been appended by the 565 // immediately scheduled fake HAL current temperatures read (mSkin1, mSkin2), and because 566 // there are less samples for prediction, the latest temperature mSkin1 is used to calculate 567 // headroom (mSkin2 has no threshold), which is 0.6f (28C vs threshold 40C). 568 assertEquals(0.6f, headroom, 0.01f); 569 // one called by service onActivityManagerReady, one called by handler on headroom call 570 assertEquals(2, mFakeHal.mGetCurrentTemperaturesCalled.get()); 571 // periodic read should update the samples history, so the headroom should increase 0.1f 572 // as current temperature goes up by 3C every 1100ms. 573 for (int i = 1; i < 5; i++) { 574 Temperature newTemperature = new Temperature(mFakeHal.mSkin1.getValue() + 3 * i, 575 Temperature.TYPE_SKIN, 576 temperatureName, 577 Temperature.THROTTLING_NONE); 578 mFakeHal.updateTemperatureList(newTemperature); 579 // wait for handler to update temperature 580 Thread.sleep(1100); 581 // assert that only one callback was scheduled to query HAL when making multiple 582 // headroom calls 583 assertEquals(2 + i, mFakeHal.mGetCurrentTemperaturesCalled.get()); 584 headroom = mService.mService.getThermalHeadroom(0); 585 assertEquals(0.6f + 0.1f * i, headroom, 0.01f); 586 } 587 } 588 589 @Test 590 @EnableFlags({Flags.FLAG_ALLOW_THERMAL_HAL_SKIN_FORECAST}) testGetThermalHeadroom_halForecast()591 public void testGetThermalHeadroom_halForecast() throws RemoteException { 592 mFakeHal.mForecastSkinTemperaturesCalled = 0; 593 mFakeHal.enableForecastSkinTemperature(); 594 mService = new ThermalManagerService(mContext, mFakeHal); 595 mService.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY); 596 assertTrue(mService.mIsHalSkinForecastSupported.get()); 597 assertEquals(1, mFakeHal.mForecastSkinTemperaturesCalled); 598 mFakeHal.mForecastSkinTemperaturesCalled = 0; 599 600 assertEquals(1.0f, mService.mService.getThermalHeadroom(60), 0.01f); 601 assertEquals(0.9f, mService.mService.getThermalHeadroom(50), 0.01f); 602 assertEquals(0.8f, mService.mService.getThermalHeadroom(40), 0.01f); 603 assertEquals(0.7f, mService.mService.getThermalHeadroom(30), 0.01f); 604 assertEquals(0.6f, mService.mService.getThermalHeadroom(20), 0.01f); 605 assertEquals(0.5f, mService.mService.getThermalHeadroom(10), 0.01f); 606 assertEquals(0.4f, mService.mService.getThermalHeadroom(0), 0.01f); 607 assertEquals(7, mFakeHal.mForecastSkinTemperaturesCalled); 608 } 609 610 @Test 611 @EnableFlags({Flags.FLAG_ALLOW_THERMAL_HAL_SKIN_FORECAST}) testGetThermalHeadroom_halForecast_disabledOnMultiThresholds()612 public void testGetThermalHeadroom_halForecast_disabledOnMultiThresholds() 613 throws RemoteException { 614 mFakeHal.mForecastSkinTemperaturesCalled = 0; 615 List<TemperatureThreshold> thresholds = mFakeHal.initializeThresholds(); 616 TemperatureThreshold skinThreshold = new TemperatureThreshold(); 617 skinThreshold.type = Temperature.TYPE_SKIN; 618 skinThreshold.name = "skin2"; 619 skinThreshold.hotThrottlingThresholds = new float[7 /*ThrottlingSeverity#len*/]; 620 skinThreshold.coldThrottlingThresholds = new float[7 /*ThrottlingSeverity#len*/]; 621 for (int i = 0; i < skinThreshold.hotThrottlingThresholds.length; ++i) { 622 // Sets NONE to 45.0f, SEVERE to 60.0f, and SHUTDOWN to 75.0f 623 skinThreshold.hotThrottlingThresholds[i] = 45.0f + 5.0f * i; 624 } 625 thresholds.add(skinThreshold); 626 mFakeHal.mTemperatureThresholdList = thresholds; 627 mFakeHal.enableForecastSkinTemperature(); 628 mService = new ThermalManagerService(mContext, mFakeHal); 629 mService.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY); 630 assertFalse("HAL skin forecast should be disabled on multiple SKIN thresholds", 631 mService.mIsHalSkinForecastSupported.get()); 632 mService.mService.getThermalHeadroom(10); 633 assertEquals(0, mFakeHal.mForecastSkinTemperaturesCalled); 634 } 635 636 @Test 637 @EnableFlags({Flags.FLAG_ALLOW_THERMAL_HAL_SKIN_FORECAST, 638 Flags.FLAG_ALLOW_THERMAL_THRESHOLDS_CALLBACK}) testGetThermalHeadroom_halForecast_disabledOnMultiThresholdsCallback()639 public void testGetThermalHeadroom_halForecast_disabledOnMultiThresholdsCallback() 640 throws RemoteException { 641 mFakeHal.mForecastSkinTemperaturesCalled = 0; 642 mFakeHal.enableForecastSkinTemperature(); 643 mService = new ThermalManagerService(mContext, mFakeHal); 644 mService.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY); 645 assertTrue(mService.mIsHalSkinForecastSupported.get()); 646 assertEquals(1, mFakeHal.mForecastSkinTemperaturesCalled); 647 mFakeHal.mForecastSkinTemperaturesCalled = 0; 648 649 TemperatureThreshold newThreshold = new TemperatureThreshold(); 650 newThreshold.name = "skin2"; 651 newThreshold.type = Temperature.TYPE_SKIN; 652 newThreshold.hotThrottlingThresholds = new float[]{ 653 Float.NaN, 43.0f, 46.0f, 49.0f, Float.NaN, Float.NaN, Float.NaN 654 }; 655 mFakeHal.mCallback.onThresholdChanged(newThreshold); 656 mService.mService.getThermalHeadroom(10); 657 assertEquals(0, mFakeHal.mForecastSkinTemperaturesCalled); 658 } 659 660 @Test 661 @EnableFlags({Flags.FLAG_ALLOW_THERMAL_HAL_SKIN_FORECAST}) testGetThermalHeadroom_halForecast_errorOnHal()662 public void testGetThermalHeadroom_halForecast_errorOnHal() throws RemoteException { 663 mFakeHal.mForecastSkinTemperaturesCalled = 0; 664 mFakeHal.enableForecastSkinTemperature(); 665 mService = new ThermalManagerService(mContext, mFakeHal); 666 mService.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY); 667 assertTrue(mService.mIsHalSkinForecastSupported.get()); 668 assertEquals(1, mFakeHal.mForecastSkinTemperaturesCalled); 669 mFakeHal.mForecastSkinTemperaturesCalled = 0; 670 671 mFakeHal.disableForecastSkinTemperature(); 672 assertTrue(Float.isNaN(mService.mService.getThermalHeadroom(10))); 673 assertEquals(1, mFakeHal.mForecastSkinTemperaturesCalled); 674 mFakeHal.enableForecastSkinTemperature(); 675 assertFalse(Float.isNaN(mService.mService.getThermalHeadroom(10))); 676 assertEquals(2, mFakeHal.mForecastSkinTemperaturesCalled); 677 mFakeHal.failForecastSkinTemperature(); 678 assertTrue(Float.isNaN(mService.mService.getThermalHeadroom(10))); 679 assertEquals(3, mFakeHal.mForecastSkinTemperaturesCalled); 680 } 681 682 @Test 683 @EnableFlags({Flags.FLAG_ALLOW_THERMAL_THRESHOLDS_CALLBACK, 684 Flags.FLAG_ALLOW_THERMAL_HEADROOM_THRESHOLDS}) testTemperatureWatcherUpdateSevereThresholds()685 public void testTemperatureWatcherUpdateSevereThresholds() throws Exception { 686 assertTrue(mService.mService.registerThermalHeadroomListener(mHeadroomListener)); 687 verify(mHeadroomListener, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 688 .times(1)).onHeadroomChange(eq(0.6f), eq(0.6f), anyInt(), 689 aryEq(new float[]{Float.NaN, 0.6666667f, 0.8333333f, 1.0f, 1.1666666f, 1.3333334f, 690 1.5f})); 691 resetListenerMock(); 692 TemperatureWatcher watcher = mService.mTemperatureWatcher; 693 TemperatureThreshold newThreshold = new TemperatureThreshold(); 694 newThreshold.name = "skin1"; 695 newThreshold.type = Temperature.TYPE_SKIN; 696 // significant change in threshold (> 0.3C) should trigger a callback 697 newThreshold.hotThrottlingThresholds = new float[]{ 698 Float.NaN, 43.0f, 46.0f, 49.0f, Float.NaN, Float.NaN, Float.NaN 699 }; 700 mFakeHal.mCallback.onThresholdChanged(newThreshold); 701 synchronized (watcher.mSamples) { 702 Float threshold = watcher.mSevereThresholds.get("skin1"); 703 assertNotNull(threshold); 704 assertEquals(49.0f, threshold, 0.0f); 705 assertArrayEquals("Got" + Arrays.toString(watcher.mHeadroomThresholds), 706 new float[]{Float.NaN, 0.8f, 0.9f, 1.0f, Float.NaN, Float.NaN, Float.NaN}, 707 watcher.mHeadroomThresholds, 0.01f); 708 } 709 verify(mHeadroomListener, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 710 .times(1)).onHeadroomChange(eq(0.3f), eq(0.3f), anyInt(), 711 aryEq(new float[]{Float.NaN, 0.8f, 0.9f, 1.0f, Float.NaN, Float.NaN, Float.NaN})); 712 resetListenerMock(); 713 714 // same or similar threshold callback data within a second should not trigger callback 715 mFakeHal.mCallback.onThresholdChanged(newThreshold); 716 newThreshold.hotThrottlingThresholds = new float[]{ 717 Float.NaN, 43.1f, 45.9f, 49.0f, Float.NaN, Float.NaN, Float.NaN 718 }; 719 mFakeHal.mCallback.onThresholdChanged(newThreshold); 720 verify(mHeadroomListener, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 721 .times(0)).onHeadroomChange(anyFloat(), anyFloat(), anyInt(), any()); 722 } 723 724 @Test testTemperatureWatcherUpdateHeadroomThreshold()725 public void testTemperatureWatcherUpdateHeadroomThreshold() { 726 TemperatureWatcher watcher = mService.mTemperatureWatcher; 727 synchronized (watcher.mSamples) { 728 Arrays.fill(watcher.mHeadroomThresholds, Float.NaN); 729 } 730 TemperatureThreshold threshold = new TemperatureThreshold(); 731 threshold.hotThrottlingThresholds = new float[]{Float.NaN, 40, 46, 49, 64, 70, 79}; 732 synchronized (watcher.mSamples) { 733 watcher.updateTemperatureThresholdLocked(threshold, false /*override*/); 734 assertArrayEquals(new float[]{Float.NaN, 0.7f, 0.9f, 1.0f, 1.5f, 1.7f, 2.0f}, 735 watcher.mHeadroomThresholds, 0.01f); 736 } 737 738 // when another sensor reports different threshold, we expect to see smaller one to be used 739 threshold = new TemperatureThreshold(); 740 threshold.hotThrottlingThresholds = new float[]{Float.NaN, 37, 46, 52, 64, 100, 200}; 741 synchronized (watcher.mSamples) { 742 watcher.updateTemperatureThresholdLocked(threshold, false /*override*/); 743 assertArrayEquals(new float[]{Float.NaN, 0.5f, 0.8f, 1.0f, 1.4f, 1.7f, 2.0f}, 744 watcher.mHeadroomThresholds, 0.01f); 745 } 746 } 747 748 @Test testGetThermalHeadroomThresholds()749 public void testGetThermalHeadroomThresholds() throws Exception { 750 float[] expected = new float[]{Float.NaN, 0.1f, 0.2f, 0.3f, 0.4f, Float.NaN, 0.6f}; 751 when(mIThermalServiceMock.getThermalHeadroomThresholds()).thenReturn(expected); 752 Map<Integer, Float> thresholds1 = mPowerManager.getThermalHeadroomThresholds(); 753 verify(mIThermalServiceMock, times(1)).getThermalHeadroomThresholds(); 754 checkHeadroomThresholds(expected, thresholds1); 755 756 reset(mIThermalServiceMock); 757 expected = new float[]{Float.NaN, 0.2f, 0.3f, 0.4f, 0.4f, Float.NaN, 0.6f}; 758 when(mIThermalServiceMock.getThermalHeadroomThresholds()).thenReturn(expected); 759 Map<Integer, Float> thresholds2 = mPowerManager.getThermalHeadroomThresholds(); 760 verify(mIThermalServiceMock, times(1)).getThermalHeadroomThresholds(); 761 checkHeadroomThresholds(expected, thresholds2); 762 } 763 checkHeadroomThresholds(float[] expected, Map<Integer, Float> thresholds)764 private void checkHeadroomThresholds(float[] expected, Map<Integer, Float> thresholds) { 765 for (int status = PowerManager.THERMAL_STATUS_LIGHT; 766 status <= PowerManager.THERMAL_STATUS_SHUTDOWN; status++) { 767 if (Float.isNaN(expected[status])) { 768 assertFalse(thresholds.containsKey(status)); 769 } else { 770 assertEquals(expected[status], thresholds.get(status), 0.01f); 771 } 772 } 773 } 774 775 @Test testGetThermalHeadroomThresholdsOnDefaultHalResult()776 public void testGetThermalHeadroomThresholdsOnDefaultHalResult() throws Exception { 777 TemperatureWatcher watcher = mService.mTemperatureWatcher; 778 ArrayList<TemperatureThreshold> thresholds = new ArrayList<>(); 779 mFakeHal.mTemperatureThresholdList = thresholds; 780 watcher.getAndUpdateThresholds(); 781 synchronized (watcher.mSamples) { 782 assertArrayEquals( 783 new float[]{Float.NaN, Float.NaN, Float.NaN, Float.NaN, Float.NaN, Float.NaN, 784 Float.NaN}, 785 watcher.mHeadroomThresholds, 0.01f); 786 } 787 TemperatureThreshold nanThresholds = new TemperatureThreshold(); 788 nanThresholds.name = "nan"; 789 nanThresholds.type = Temperature.TYPE_SKIN; 790 nanThresholds.hotThrottlingThresholds = new float[ThrottlingSeverity.SHUTDOWN + 1]; 791 nanThresholds.coldThrottlingThresholds = new float[ThrottlingSeverity.SHUTDOWN + 1]; 792 Arrays.fill(nanThresholds.hotThrottlingThresholds, Float.NaN); 793 Arrays.fill(nanThresholds.coldThrottlingThresholds, Float.NaN); 794 thresholds.add(nanThresholds); 795 watcher.getAndUpdateThresholds(); 796 synchronized (watcher.mSamples) { 797 assertArrayEquals( 798 new float[]{Float.NaN, Float.NaN, Float.NaN, Float.NaN, Float.NaN, Float.NaN, 799 Float.NaN}, 800 watcher.mHeadroomThresholds, 0.01f); 801 } 802 } 803 804 @Test testTemperatureWatcherGetSlopeOf()805 public void testTemperatureWatcherGetSlopeOf() throws RemoteException { 806 TemperatureWatcher watcher = mService.mTemperatureWatcher; 807 List<TemperatureWatcher.Sample> samples = new ArrayList<>(); 808 for (int i = 0; i < 30; ++i) { 809 samples.add(watcher.createSampleForTesting(i, (float) (i / 2 * 2))); 810 } 811 assertEquals(1.0f, watcher.getSlopeOf(samples), 0.01f); 812 } 813 814 @Test testTemperatureWatcherNormalizeTemperature()815 public void testTemperatureWatcherNormalizeTemperature() throws RemoteException { 816 assertEquals(0.5f, 817 TemperatureWatcher.normalizeTemperature(25.0f, 40.0f), 0.0f); 818 819 // Temperatures more than 30 degrees below the SEVERE threshold should be clamped to 0.0f 820 assertEquals(0.0f, 821 TemperatureWatcher.normalizeTemperature(0.0f, 40.0f), 0.0f); 822 823 // Temperatures above the SEVERE threshold should not be clamped 824 assertEquals(2.0f, 825 TemperatureWatcher.normalizeTemperature(70.0f, 40.0f), 0.0f); 826 } 827 828 @Test testTemperatureWatcherGetForecast()829 public void testTemperatureWatcherGetForecast() throws RemoteException { 830 TemperatureWatcher watcher = mService.mTemperatureWatcher; 831 832 ArrayList<TemperatureWatcher.Sample> samples = new ArrayList<>(); 833 834 // Add a single sample 835 samples.add(watcher.createSampleForTesting(0, 25.0f)); 836 watcher.mSamples.put("skin1", samples); 837 838 // Because there are not enough samples to compute the linear regression, 839 // no matter how far ahead we forecast, we should receive the same value 840 assertEquals(0.5f, watcher.getForecast(0), 0.0f); 841 assertEquals(0.5f, watcher.getForecast(5), 0.0f); 842 843 // Add some time-series data 844 for (int i = 1; i < 20; ++i) { 845 samples.add(watcher.createSampleForTesting(1000 * i, 25.0f + 0.5f * i)); 846 } 847 848 // Now the forecast should vary depending on how far ahead we are trying to predict 849 assertEquals(0.9f, watcher.getForecast(4), 0.02f); 850 assertEquals(1.0f, watcher.getForecast(10), 0.02f); 851 852 // If there are no thresholds, then we shouldn't receive a headroom value 853 watcher.mSevereThresholds.erase(); 854 assertTrue(Float.isNaN(watcher.getForecast(0))); 855 } 856 857 @Test testTemperatureWatcherGetForecastUpdate()858 public void testTemperatureWatcherGetForecastUpdate() throws Exception { 859 TemperatureWatcher watcher = mService.mTemperatureWatcher; 860 861 // Reduce the inactivity threshold to speed up testing 862 watcher.mInactivityThresholdMillis = 2000; 863 864 // Make sure mSamples is empty before updateTemperature 865 assertTrue(isWatcherSamplesEmpty(watcher)); 866 867 // Call getForecast once to trigger updateTemperature 868 watcher.getForecast(0); 869 870 // After 1 second, the samples should be updated 871 Thread.sleep(1000); 872 assertFalse(isWatcherSamplesEmpty(watcher)); 873 874 // After mInactivityThresholdMillis, the samples should be cleared 875 Thread.sleep(watcher.mInactivityThresholdMillis); 876 assertTrue(isWatcherSamplesEmpty(watcher)); 877 } 878 879 // Helper function to hold mSamples lock, avoid GuardedBy lint errors isWatcherSamplesEmpty(TemperatureWatcher watcher)880 private boolean isWatcherSamplesEmpty(TemperatureWatcher watcher) { 881 synchronized (watcher.mSamples) { 882 return watcher.mSamples.isEmpty(); 883 } 884 } 885 886 @Test testDump()887 public void testDump() throws Exception { 888 assertTrue(mService.mService.registerThermalEventListener(mEventListener1)); 889 assertTrue(mService.mService.registerThermalStatusListener(mStatusListener1)); 890 assertTrue(mService.mService.registerThermalEventListenerWithType(mEventListener2, 891 Temperature.TYPE_SKIN)); 892 assertTrue(mService.mService.registerThermalStatusListener(mStatusListener2)); 893 894 when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)) 895 .thenReturn(PackageManager.PERMISSION_GRANTED); 896 final StringWriter out = new StringWriter(); 897 PrintWriter pw = new PrintWriter(out); 898 mService.dumpInternal(new FileDescriptor(), pw, null); 899 final String dumpStr = out.toString(); 900 assertThat(dumpStr).contains("IsStatusOverride: false"); 901 assertThat(dumpStr).contains( 902 "ThermalEventListeners:\n" 903 + "\tcallbacks: 2\n" 904 + "\tkilled: false\n" 905 + "\tbroadcasts count: -1"); 906 assertThat(dumpStr).contains( 907 "ThermalStatusListeners:\n" 908 + "\tcallbacks: 2\n" 909 + "\tkilled: false\n" 910 + "\tbroadcasts count: -1"); 911 assertThat(dumpStr).contains("Thermal Status: 0"); 912 assertThat(dumpStr).contains( 913 "Cached temperatures:\n" 914 + "\tTemperature{mValue=37.0, mType=4, mName=usbport, mStatus=0}\n" 915 + "\tTemperature{mValue=34.0, mType=2, mName=batt, mStatus=0}\n" 916 + "\tTemperature{mValue=28.0, mType=3, mName=skin1, mStatus=0}\n" 917 + "\tTemperature{mValue=31.0, mType=3, mName=skin2, mStatus=0}" 918 ); 919 assertThat(dumpStr).contains("HAL Ready: true\n" 920 + "HAL connection:\n" 921 + "\tThermalHAL AIDL 1 connected: yes"); 922 assertThat(dumpStr).contains("Current temperatures from HAL:\n" 923 + "\tTemperature{mValue=28.0, mType=3, mName=skin1, mStatus=0}\n" 924 + "\tTemperature{mValue=31.0, mType=3, mName=skin2, mStatus=0}\n" 925 + "\tTemperature{mValue=34.0, mType=2, mName=batt, mStatus=0}\n" 926 + "\tTemperature{mValue=37.0, mType=4, mName=usbport, mStatus=0}\n"); 927 assertThat(dumpStr).contains("Current cooling devices from HAL:\n" 928 + "\tCoolingDevice{mValue=40, mType=1, mName=cpu}\n" 929 + "\tCoolingDevice{mValue=43, mType=1, mName=gpu}\n"); 930 assertThat(dumpStr).contains("Temperature static thresholds from HAL:\n" 931 + "\tTemperatureThreshold{mType=3, mName=skin1, mHotThrottlingThresholds=[25.0, " 932 + "30.0, 35.0, 40.0, 45.0, 50.0, 55.0], mColdThrottlingThresholds=[0.0, 0.0, 0.0," 933 + " 0.0, 0.0, 0.0, 0.0]}\n" 934 + "\tTemperatureThreshold{mType=0, mName=cpu, mHotThrottlingThresholds=[NaN, NaN," 935 + " NaN, 95.0, NaN, NaN, NaN], mColdThrottlingThresholds=[0.0, 0.0, 0.0, 0.0, 0" 936 + ".0, 0.0, 0.0]}"); 937 } 938 } 939