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.assertEquals; 22 import static org.junit.Assert.assertFalse; 23 import static org.junit.Assert.assertNotNull; 24 import static org.junit.Assert.assertTrue; 25 import static org.mockito.ArgumentMatchers.any; 26 import static org.mockito.ArgumentMatchers.anyInt; 27 import static org.mockito.Mockito.doReturn; 28 import static org.mockito.Mockito.mock; 29 import static org.mockito.Mockito.reset; 30 import static org.mockito.Mockito.timeout; 31 import static org.mockito.Mockito.verify; 32 import static org.mockito.Mockito.when; 33 34 import android.content.Context; 35 import android.content.pm.PackageManager; 36 import android.hardware.thermal.TemperatureThreshold; 37 import android.hardware.thermal.ThrottlingSeverity; 38 import android.os.CoolingDevice; 39 import android.os.IBinder; 40 import android.os.IPowerManager; 41 import android.os.IThermalEventListener; 42 import android.os.IThermalService; 43 import android.os.IThermalStatusListener; 44 import android.os.PowerManager; 45 import android.os.RemoteException; 46 import android.os.Temperature; 47 48 import androidx.test.filters.SmallTest; 49 import androidx.test.runner.AndroidJUnit4; 50 51 import com.android.server.SystemService; 52 import com.android.server.power.ThermalManagerService.ThermalHalWrapper; 53 54 import org.junit.Before; 55 import org.junit.Test; 56 import org.junit.runner.RunWith; 57 import org.mockito.ArgumentCaptor; 58 import org.mockito.Mock; 59 import org.mockito.MockitoAnnotations; 60 61 import java.io.FileDescriptor; 62 import java.io.PrintWriter; 63 import java.io.StringWriter; 64 import java.util.ArrayList; 65 import java.util.Arrays; 66 import java.util.HashSet; 67 import java.util.List; 68 69 /** 70 * atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server 71 * /power/ThermalManagerServiceTest.java 72 */ 73 @SmallTest 74 @RunWith(AndroidJUnit4.class) 75 public class ThermalManagerServiceTest { 76 private static final long CALLBACK_TIMEOUT_MILLI_SEC = 5000; 77 private ThermalManagerService mService; 78 private ThermalHalFake mFakeHal; 79 private PowerManager mPowerManager; 80 @Mock 81 private Context mContext; 82 @Mock 83 private IPowerManager mIPowerManagerMock; 84 @Mock 85 private IThermalService mIThermalServiceMock; 86 @Mock 87 private IThermalEventListener mEventListener1; 88 @Mock 89 private IThermalEventListener mEventListener2; 90 @Mock 91 private IThermalStatusListener mStatusListener1; 92 @Mock 93 private IThermalStatusListener mStatusListener2; 94 95 /** 96 * Fake Hal class. 97 */ 98 private class ThermalHalFake extends ThermalHalWrapper { 99 private static final int INIT_STATUS = Temperature.THROTTLING_NONE; 100 private ArrayList<Temperature> mTemperatureList = new ArrayList<>(); 101 private ArrayList<CoolingDevice> mCoolingDeviceList = new ArrayList<>(); 102 private ArrayList<TemperatureThreshold> mTemperatureThresholdList = initializeThresholds(); 103 104 private Temperature mSkin1 = new Temperature(0, Temperature.TYPE_SKIN, "skin1", 105 INIT_STATUS); 106 private Temperature mSkin2 = new Temperature(0, Temperature.TYPE_SKIN, "skin2", 107 INIT_STATUS); 108 private Temperature mBattery = new Temperature(0, Temperature.TYPE_BATTERY, "batt", 109 INIT_STATUS); 110 private Temperature mUsbPort = new Temperature(0, Temperature.TYPE_USB_PORT, "usbport", 111 INIT_STATUS); 112 private CoolingDevice mCpu = new CoolingDevice(0, CoolingDevice.TYPE_BATTERY, "cpu"); 113 private CoolingDevice mGpu = new CoolingDevice(0, CoolingDevice.TYPE_BATTERY, "gpu"); 114 initializeThresholds()115 private ArrayList<TemperatureThreshold> initializeThresholds() { 116 ArrayList<TemperatureThreshold> thresholds = new ArrayList<>(); 117 118 TemperatureThreshold skinThreshold = new TemperatureThreshold(); 119 skinThreshold.type = Temperature.TYPE_SKIN; 120 skinThreshold.name = "skin1"; 121 skinThreshold.hotThrottlingThresholds = new float[7 /*ThrottlingSeverity#len*/]; 122 skinThreshold.coldThrottlingThresholds = new float[7 /*ThrottlingSeverity#len*/]; 123 for (int i = 0; i < skinThreshold.hotThrottlingThresholds.length; ++i) { 124 // Sets NONE to 25.0f, SEVERE to 40.0f, and SHUTDOWN to 55.0f 125 skinThreshold.hotThrottlingThresholds[i] = 25.0f + 5.0f * i; 126 } 127 thresholds.add(skinThreshold); 128 129 TemperatureThreshold cpuThreshold = new TemperatureThreshold(); 130 cpuThreshold.type = Temperature.TYPE_CPU; 131 cpuThreshold.name = "cpu"; 132 cpuThreshold.hotThrottlingThresholds = new float[7 /*ThrottlingSeverity#len*/]; 133 cpuThreshold.coldThrottlingThresholds = new float[7 /*ThrottlingSeverity#len*/]; 134 for (int i = 0; i < cpuThreshold.hotThrottlingThresholds.length; ++i) { 135 if (i == ThrottlingSeverity.SEVERE) { 136 cpuThreshold.hotThrottlingThresholds[i] = 95.0f; 137 } else { 138 cpuThreshold.hotThrottlingThresholds[i] = Float.NaN; 139 } 140 } 141 thresholds.add(cpuThreshold); 142 143 return thresholds; 144 } 145 ThermalHalFake()146 ThermalHalFake() { 147 mTemperatureList.add(mSkin1); 148 mTemperatureList.add(mSkin2); 149 mTemperatureList.add(mBattery); 150 mTemperatureList.add(mUsbPort); 151 mCoolingDeviceList.add(mCpu); 152 mCoolingDeviceList.add(mGpu); 153 } 154 155 @Override getCurrentTemperatures(boolean shouldFilter, int type)156 protected List<Temperature> getCurrentTemperatures(boolean shouldFilter, int type) { 157 List<Temperature> ret = new ArrayList<>(); 158 for (Temperature temperature : mTemperatureList) { 159 if (shouldFilter && type != temperature.getType()) { 160 continue; 161 } 162 ret.add(temperature); 163 } 164 return ret; 165 } 166 167 @Override getCurrentCoolingDevices(boolean shouldFilter, int type)168 protected List<CoolingDevice> getCurrentCoolingDevices(boolean shouldFilter, int type) { 169 List<CoolingDevice> ret = new ArrayList<>(); 170 for (CoolingDevice cdev : mCoolingDeviceList) { 171 if (shouldFilter && type != cdev.getType()) { 172 continue; 173 } 174 ret.add(cdev); 175 } 176 return ret; 177 } 178 179 @Override getTemperatureThresholds(boolean shouldFilter, int type)180 protected List<TemperatureThreshold> getTemperatureThresholds(boolean shouldFilter, 181 int type) { 182 List<TemperatureThreshold> ret = new ArrayList<>(); 183 for (TemperatureThreshold threshold : mTemperatureThresholdList) { 184 if (shouldFilter && type != threshold.type) { 185 continue; 186 } 187 ret.add(threshold); 188 } 189 return ret; 190 } 191 192 @Override connectToHal()193 protected boolean connectToHal() { 194 return true; 195 } 196 197 @Override dump(PrintWriter pw, String prefix)198 protected void dump(PrintWriter pw, String prefix) { 199 pw.print(prefix); 200 pw.println("ThermalHAL AIDL 1 connected: yes"); 201 } 202 } 203 assertListEqualsIgnoringOrder(List<?> actual, List<?> expected)204 private void assertListEqualsIgnoringOrder(List<?> actual, List<?> expected) { 205 HashSet<?> actualSet = new HashSet<>(actual); 206 HashSet<?> expectedSet = new HashSet<>(expected); 207 assertEquals(expectedSet, actualSet); 208 } 209 210 @Before setUp()211 public void setUp() throws RemoteException { 212 MockitoAnnotations.initMocks(this); 213 mFakeHal = new ThermalHalFake(); 214 mPowerManager = new PowerManager(mContext, mIPowerManagerMock, mIThermalServiceMock, null); 215 when(mContext.getSystemServiceName(PowerManager.class)).thenReturn(Context.POWER_SERVICE); 216 when(mContext.getSystemService(PowerManager.class)).thenReturn(mPowerManager); 217 resetListenerMock(); 218 mService = new ThermalManagerService(mContext, mFakeHal); 219 // Register callbacks before AMS ready and no callback sent 220 assertTrue(mService.mService.registerThermalEventListener(mEventListener1)); 221 assertTrue(mService.mService.registerThermalStatusListener(mStatusListener1)); 222 assertTrue(mService.mService.registerThermalEventListenerWithType(mEventListener2, 223 Temperature.TYPE_SKIN)); 224 assertTrue(mService.mService.registerThermalStatusListener(mStatusListener2)); 225 verify(mEventListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 226 .times(0)).notifyThrottling(any(Temperature.class)); 227 verify(mStatusListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 228 .times(1)).onStatusChange(Temperature.THROTTLING_NONE); 229 verify(mEventListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 230 .times(0)).notifyThrottling(any(Temperature.class)); 231 verify(mStatusListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 232 .times(1)).onStatusChange(Temperature.THROTTLING_NONE); 233 resetListenerMock(); 234 mService.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY); 235 ArgumentCaptor<Temperature> captor = ArgumentCaptor.forClass(Temperature.class); 236 verify(mEventListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 237 .times(4)).notifyThrottling(captor.capture()); 238 assertListEqualsIgnoringOrder(mFakeHal.mTemperatureList, captor.getAllValues()); 239 verify(mStatusListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 240 .times(0)).onStatusChange(Temperature.THROTTLING_NONE); 241 captor = ArgumentCaptor.forClass(Temperature.class); 242 verify(mEventListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 243 .times(2)).notifyThrottling(captor.capture()); 244 assertListEqualsIgnoringOrder( 245 new ArrayList<>(Arrays.asList(mFakeHal.mSkin1, mFakeHal.mSkin2)), 246 captor.getAllValues()); 247 verify(mStatusListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 248 .times(0)).onStatusChange(Temperature.THROTTLING_NONE); 249 } 250 resetListenerMock()251 private void resetListenerMock() { 252 reset(mEventListener1); 253 reset(mStatusListener1); 254 reset(mEventListener2); 255 reset(mStatusListener2); 256 doReturn(mock(IBinder.class)).when(mEventListener1).asBinder(); 257 doReturn(mock(IBinder.class)).when(mStatusListener1).asBinder(); 258 doReturn(mock(IBinder.class)).when(mEventListener2).asBinder(); 259 doReturn(mock(IBinder.class)).when(mStatusListener2).asBinder(); 260 } 261 262 @Test testRegister()263 public void testRegister() throws RemoteException { 264 resetListenerMock(); 265 // Register callbacks and verify they are called 266 assertTrue(mService.mService.registerThermalEventListener(mEventListener1)); 267 assertTrue(mService.mService.registerThermalStatusListener(mStatusListener1)); 268 ArgumentCaptor<Temperature> captor = ArgumentCaptor.forClass(Temperature.class); 269 verify(mEventListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 270 .times(4)).notifyThrottling(captor.capture()); 271 assertListEqualsIgnoringOrder(mFakeHal.mTemperatureList, captor.getAllValues()); 272 verify(mStatusListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 273 .times(1)).onStatusChange(Temperature.THROTTLING_NONE); 274 // Register new callbacks and verify old ones are not called (remained same) while new 275 // ones are called 276 assertTrue(mService.mService.registerThermalEventListenerWithType(mEventListener2, 277 Temperature.TYPE_SKIN)); 278 assertTrue(mService.mService.registerThermalStatusListener(mStatusListener2)); 279 verify(mEventListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 280 .times(4)).notifyThrottling(any(Temperature.class)); 281 verify(mStatusListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 282 .times(1)).onStatusChange(Temperature.THROTTLING_NONE); 283 captor = ArgumentCaptor.forClass(Temperature.class); 284 verify(mEventListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 285 .times(2)).notifyThrottling(captor.capture()); 286 assertListEqualsIgnoringOrder( 287 new ArrayList<>(Arrays.asList(mFakeHal.mSkin1, mFakeHal.mSkin2)), 288 captor.getAllValues()); 289 verify(mStatusListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 290 .times(1)).onStatusChange(Temperature.THROTTLING_NONE); 291 } 292 293 @Test testNotify()294 public void testNotify() throws RemoteException { 295 int status = Temperature.THROTTLING_SEVERE; 296 // Should only notify event not status 297 Temperature newBattery = new Temperature(50, Temperature.TYPE_BATTERY, "batt", status); 298 mFakeHal.mCallback.onValues(newBattery); 299 verify(mEventListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 300 .times(1)).notifyThrottling(newBattery); 301 verify(mStatusListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 302 .times(0)).onStatusChange(anyInt()); 303 verify(mEventListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 304 .times(0)).notifyThrottling(newBattery); 305 verify(mStatusListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 306 .times(0)).onStatusChange(anyInt()); 307 resetListenerMock(); 308 // Notify both event and status 309 Temperature newSkin = new Temperature(50, Temperature.TYPE_SKIN, "skin1", status); 310 mFakeHal.mCallback.onValues(newSkin); 311 verify(mEventListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 312 .times(1)).notifyThrottling(newSkin); 313 verify(mStatusListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 314 .times(1)).onStatusChange(status); 315 verify(mEventListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 316 .times(1)).notifyThrottling(newSkin); 317 verify(mStatusListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 318 .times(1)).onStatusChange(status); 319 resetListenerMock(); 320 // Back to None, should only notify event not status 321 status = Temperature.THROTTLING_NONE; 322 newBattery = new Temperature(50, Temperature.TYPE_BATTERY, "batt", status); 323 mFakeHal.mCallback.onValues(newBattery); 324 verify(mEventListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 325 .times(1)).notifyThrottling(newBattery); 326 verify(mStatusListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 327 .times(0)).onStatusChange(anyInt()); 328 verify(mEventListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 329 .times(0)).notifyThrottling(newBattery); 330 verify(mStatusListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 331 .times(0)).onStatusChange(anyInt()); 332 resetListenerMock(); 333 // Should also notify status 334 newSkin = new Temperature(50, Temperature.TYPE_SKIN, "skin1", status); 335 mFakeHal.mCallback.onValues(newSkin); 336 verify(mEventListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 337 .times(1)).notifyThrottling(newSkin); 338 verify(mStatusListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 339 .times(1)).onStatusChange(status); 340 verify(mEventListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 341 .times(1)).notifyThrottling(newSkin); 342 verify(mStatusListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 343 .times(1)).onStatusChange(status); 344 } 345 346 @Test testGetCurrentTemperatures()347 public void testGetCurrentTemperatures() throws RemoteException { 348 assertListEqualsIgnoringOrder(mFakeHal.getCurrentTemperatures(false, 0), 349 Arrays.asList(mService.mService.getCurrentTemperatures())); 350 assertListEqualsIgnoringOrder( 351 mFakeHal.getCurrentTemperatures(true, Temperature.TYPE_SKIN), 352 Arrays.asList(mService.mService.getCurrentTemperaturesWithType( 353 Temperature.TYPE_SKIN))); 354 } 355 356 @Test testGetCurrentStatus()357 public void testGetCurrentStatus() throws RemoteException { 358 int status = Temperature.THROTTLING_SEVERE; 359 Temperature newSkin = new Temperature(100, Temperature.TYPE_SKIN, "skin1", status); 360 mFakeHal.mCallback.onValues(newSkin); 361 assertEquals(status, mService.mService.getCurrentThermalStatus()); 362 int battStatus = Temperature.THROTTLING_EMERGENCY; 363 Temperature newBattery = new Temperature(60, Temperature.TYPE_BATTERY, "batt", battStatus); 364 assertEquals(status, mService.mService.getCurrentThermalStatus()); 365 } 366 367 @Test testThermalShutdown()368 public void testThermalShutdown() throws RemoteException { 369 int status = Temperature.THROTTLING_SHUTDOWN; 370 Temperature newSkin = new Temperature(100, Temperature.TYPE_SKIN, "skin1", status); 371 mFakeHal.mCallback.onValues(newSkin); 372 verify(mIPowerManagerMock, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 373 .times(1)).shutdown(false, PowerManager.SHUTDOWN_THERMAL_STATE, false); 374 Temperature newBattery = new Temperature(60, Temperature.TYPE_BATTERY, "batt", status); 375 mFakeHal.mCallback.onValues(newBattery); 376 verify(mIPowerManagerMock, timeout(CALLBACK_TIMEOUT_MILLI_SEC) 377 .times(1)).shutdown(false, PowerManager.SHUTDOWN_BATTERY_THERMAL_STATE, false); 378 } 379 380 @Test testNoHal()381 public void testNoHal() throws RemoteException { 382 mService = new ThermalManagerService(mContext); 383 // Do no call onActivityManagerReady to skip connect HAL 384 assertTrue(mService.mService.registerThermalEventListener(mEventListener1)); 385 assertTrue(mService.mService.registerThermalStatusListener(mStatusListener1)); 386 assertTrue(mService.mService.unregisterThermalEventListener(mEventListener1)); 387 assertTrue(mService.mService.unregisterThermalStatusListener(mStatusListener1)); 388 assertEquals(0, Arrays.asList(mService.mService.getCurrentTemperatures()).size()); 389 assertEquals(0, Arrays.asList(mService.mService.getCurrentTemperaturesWithType( 390 Temperature.TYPE_SKIN)).size()); 391 assertEquals(Temperature.THROTTLING_NONE, mService.mService.getCurrentThermalStatus()); 392 assertTrue(Float.isNaN(mService.mService.getThermalHeadroom(0))); 393 } 394 395 @Test testGetCurrentCoolingDevices()396 public void testGetCurrentCoolingDevices() throws RemoteException { 397 assertListEqualsIgnoringOrder(mFakeHal.getCurrentCoolingDevices(false, 0), 398 Arrays.asList(mService.mService.getCurrentCoolingDevices())); 399 assertListEqualsIgnoringOrder( 400 mFakeHal.getCurrentCoolingDevices(false, CoolingDevice.TYPE_BATTERY), 401 Arrays.asList(mService.mService.getCurrentCoolingDevices())); 402 assertListEqualsIgnoringOrder( 403 mFakeHal.getCurrentCoolingDevices(true, CoolingDevice.TYPE_CPU), 404 Arrays.asList(mService.mService.getCurrentCoolingDevicesWithType( 405 CoolingDevice.TYPE_CPU))); 406 } 407 408 @Test testGetThermalHeadroomInputRange()409 public void testGetThermalHeadroomInputRange() throws RemoteException { 410 assertTrue(Float.isNaN(mService.mService.getThermalHeadroom( 411 ThermalManagerService.MIN_FORECAST_SEC - 1))); 412 assertTrue(Float.isNaN(mService.mService.getThermalHeadroom( 413 ThermalManagerService.MAX_FORECAST_SEC + 1))); 414 } 415 416 @Test testTemperatureWatcherUpdateSevereThresholds()417 public void testTemperatureWatcherUpdateSevereThresholds() throws RemoteException { 418 ThermalManagerService.TemperatureWatcher watcher = mService.mTemperatureWatcher; 419 watcher.mSevereThresholds.erase(); 420 watcher.updateSevereThresholds(); 421 assertEquals(1, watcher.mSevereThresholds.size()); 422 assertEquals("skin1", watcher.mSevereThresholds.keyAt(0)); 423 Float threshold = watcher.mSevereThresholds.get("skin1"); 424 assertNotNull(threshold); 425 assertEquals(40.0f, threshold, 0.0f); 426 } 427 428 @Test testTemperatureWatcherGetSlopeOf()429 public void testTemperatureWatcherGetSlopeOf() throws RemoteException { 430 ThermalManagerService.TemperatureWatcher watcher = mService.mTemperatureWatcher; 431 List<ThermalManagerService.TemperatureWatcher.Sample> samples = new ArrayList<>(); 432 for (int i = 0; i < 30; ++i) { 433 samples.add(watcher.createSampleForTesting(i, (float) (i / 2 * 2))); 434 } 435 assertEquals(1.0f, watcher.getSlopeOf(samples), 0.01f); 436 } 437 438 @Test testTemperatureWatcherNormalizeTemperature()439 public void testTemperatureWatcherNormalizeTemperature() throws RemoteException { 440 ThermalManagerService.TemperatureWatcher watcher = mService.mTemperatureWatcher; 441 assertEquals(0.5f, watcher.normalizeTemperature(25.0f, 40.0f), 0.0f); 442 443 // Temperatures more than 30 degrees below the SEVERE threshold should be clamped to 0.0f 444 assertEquals(0.0f, watcher.normalizeTemperature(0.0f, 40.0f), 0.0f); 445 446 // Temperatures above the SEVERE threshold should not be clamped 447 assertEquals(2.0f, watcher.normalizeTemperature(70.0f, 40.0f), 0.0f); 448 } 449 450 @Test testTemperatureWatcherGetForecast()451 public void testTemperatureWatcherGetForecast() throws RemoteException { 452 ThermalManagerService.TemperatureWatcher watcher = mService.mTemperatureWatcher; 453 454 ArrayList<ThermalManagerService.TemperatureWatcher.Sample> samples = new ArrayList<>(); 455 456 // Add a single sample 457 samples.add(watcher.createSampleForTesting(0, 25.0f)); 458 watcher.mSamples.put("skin1", samples); 459 460 // Because there are not enough samples to compute the linear regression, 461 // no matter how far ahead we forecast, we should receive the same value 462 assertEquals(0.5f, watcher.getForecast(0), 0.0f); 463 assertEquals(0.5f, watcher.getForecast(5), 0.0f); 464 465 // Add some time-series data 466 for (int i = 1; i < 20; ++i) { 467 samples.add(0, watcher.createSampleForTesting(1000 * i, 25.0f + 0.5f * i)); 468 } 469 470 // Now the forecast should vary depending on how far ahead we are trying to predict 471 assertEquals(0.9f, watcher.getForecast(4), 0.02f); 472 assertEquals(1.0f, watcher.getForecast(10), 0.02f); 473 474 // If there are no thresholds, then we shouldn't receive a headroom value 475 watcher.mSevereThresholds.erase(); 476 assertTrue(Float.isNaN(watcher.getForecast(0))); 477 } 478 479 @Test testTemperatureWatcherGetForecastUpdate()480 public void testTemperatureWatcherGetForecastUpdate() throws Exception { 481 ThermalManagerService.TemperatureWatcher watcher = mService.mTemperatureWatcher; 482 483 // Reduce the inactivity threshold to speed up testing 484 watcher.mInactivityThresholdMillis = 2000; 485 486 // Make sure mSamples is empty before updateTemperature 487 assertTrue(isWatcherSamplesEmpty(watcher)); 488 489 // Call getForecast once to trigger updateTemperature 490 watcher.getForecast(0); 491 492 // After 1 second, the samples should be updated 493 Thread.sleep(1000); 494 assertFalse(isWatcherSamplesEmpty(watcher)); 495 496 // After mInactivityThresholdMillis, the samples should be cleared 497 Thread.sleep(watcher.mInactivityThresholdMillis); 498 assertTrue(isWatcherSamplesEmpty(watcher)); 499 } 500 501 // Helper function to hold mSamples lock, avoid GuardedBy lint errors isWatcherSamplesEmpty(ThermalManagerService.TemperatureWatcher watcher)502 private boolean isWatcherSamplesEmpty(ThermalManagerService.TemperatureWatcher watcher) { 503 synchronized (watcher.mSamples) { 504 return watcher.mSamples.isEmpty(); 505 } 506 } 507 508 @Test testDump()509 public void testDump() { 510 when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)) 511 .thenReturn(PackageManager.PERMISSION_GRANTED); 512 final StringWriter out = new StringWriter(); 513 PrintWriter pw = new PrintWriter(out); 514 mService.dumpInternal(new FileDescriptor(), pw, null); 515 final String dumpStr = out.toString(); 516 assertThat(dumpStr).contains("IsStatusOverride: false"); 517 assertThat(dumpStr).contains( 518 "ThermalEventListeners:\n" 519 + "\tcallbacks: 2\n" 520 + "\tkilled: false\n" 521 + "\tbroadcasts count: -1"); 522 assertThat(dumpStr).contains( 523 "ThermalStatusListeners:\n" 524 + "\tcallbacks: 2\n" 525 + "\tkilled: false\n" 526 + "\tbroadcasts count: -1"); 527 assertThat(dumpStr).contains("Thermal Status: 0"); 528 assertThat(dumpStr).contains( 529 "Cached temperatures:\n" 530 + "\tTemperature{mValue=0.0, mType=4, mName=usbport, mStatus=0}\n" 531 + "\tTemperature{mValue=0.0, mType=2, mName=batt, mStatus=0}\n" 532 + "\tTemperature{mValue=0.0, mType=3, mName=skin1, mStatus=0}\n" 533 + "\tTemperature{mValue=0.0, mType=3, mName=skin2, mStatus=0}" 534 ); 535 assertThat(dumpStr).contains("HAL Ready: true\n" 536 + "HAL connection:\n" 537 + "\tThermalHAL AIDL 1 connected: yes"); 538 assertThat(dumpStr).contains("Current temperatures from HAL:\n" 539 + "\tTemperature{mValue=0.0, mType=3, mName=skin1, mStatus=0}\n" 540 + "\tTemperature{mValue=0.0, mType=3, mName=skin2, mStatus=0}\n" 541 + "\tTemperature{mValue=0.0, mType=2, mName=batt, mStatus=0}\n" 542 + "\tTemperature{mValue=0.0, mType=4, mName=usbport, mStatus=0}\n"); 543 assertThat(dumpStr).contains("Current cooling devices from HAL:\n" 544 + "\tCoolingDevice{mValue=0, mType=1, mName=cpu}\n" 545 + "\tCoolingDevice{mValue=0, mType=1, mName=gpu}\n"); 546 assertThat(dumpStr).contains("Temperature static thresholds from HAL:\n" 547 + "\tTemperatureThreshold{mType=3, mName=skin1, mHotThrottlingThresholds=[25.0, " 548 + "30.0, 35.0, 40.0, 45.0, 50.0, 55.0], mColdThrottlingThresholds=[0.0, 0.0, 0.0," 549 + " 0.0, 0.0, 0.0, 0.0]}\n" 550 + "\tTemperatureThreshold{mType=0, mName=cpu, mHotThrottlingThresholds=[NaN, NaN," 551 + " NaN, 95.0, NaN, NaN, NaN], mColdThrottlingThresholds=[0.0, 0.0, 0.0, 0.0, 0" 552 + ".0, 0.0, 0.0]}"); 553 } 554 } 555