1 /* 2 * Copyright (C) 2020 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.powerstats; 18 19 import static org.junit.Assert.assertFalse; 20 import static org.junit.Assert.assertTrue; 21 import static org.junit.Assert.fail; 22 23 import android.content.Context; 24 import android.hardware.power.stats.Channel; 25 import android.hardware.power.stats.EnergyConsumer; 26 import android.hardware.power.stats.EnergyConsumerAttribution; 27 import android.hardware.power.stats.EnergyConsumerResult; 28 import android.hardware.power.stats.EnergyMeasurement; 29 import android.hardware.power.stats.PowerEntity; 30 import android.hardware.power.stats.State; 31 import android.hardware.power.stats.StateResidency; 32 import android.hardware.power.stats.StateResidencyResult; 33 import android.os.Looper; 34 35 import androidx.test.InstrumentationRegistry; 36 37 import com.android.server.SystemService; 38 import com.android.server.powerstats.PowerStatsHALWrapper.IPowerStatsHALWrapper; 39 import com.android.server.powerstats.ProtoStreamUtils.ChannelUtils; 40 import com.android.server.powerstats.ProtoStreamUtils.EnergyConsumerUtils; 41 import com.android.server.powerstats.ProtoStreamUtils.PowerEntityUtils; 42 import com.android.server.powerstats.nano.PowerEntityProto; 43 import com.android.server.powerstats.nano.PowerStatsServiceMeterProto; 44 import com.android.server.powerstats.nano.PowerStatsServiceModelProto; 45 import com.android.server.powerstats.nano.PowerStatsServiceResidencyProto; 46 import com.android.server.powerstats.nano.StateProto; 47 import com.android.server.powerstats.nano.StateResidencyProto; 48 import com.android.server.powerstats.nano.StateResidencyResultProto; 49 50 import org.junit.Before; 51 import org.junit.Test; 52 53 import java.io.ByteArrayOutputStream; 54 import java.io.File; 55 import java.io.FileInputStream; 56 import java.io.FileOutputStream; 57 import java.io.IOException; 58 import java.nio.ByteBuffer; 59 import java.nio.file.Files; 60 import java.util.Arrays; 61 import java.util.Random; 62 63 /** 64 * Tests for {@link com.android.server.powerstats.PowerStatsService}. 65 * 66 * Build/Install/Run: 67 * atest FrameworksServicesTests:PowerStatsServiceTest 68 */ 69 public class PowerStatsServiceTest { 70 private static final String TAG = PowerStatsServiceTest.class.getSimpleName(); 71 private static final String DATA_STORAGE_SUBDIR = "powerstatstest"; 72 private static final String METER_FILENAME = "log.powerstats.metertest.0"; 73 private static final String MODEL_FILENAME = "log.powerstats.modeltest.0"; 74 private static final String RESIDENCY_FILENAME = "log.powerstats.residencytest.0"; 75 private static final String PROTO_OUTPUT_FILENAME = "powerstats.proto"; 76 private static final String CHANNEL_NAME = "channelname"; 77 private static final String CHANNEL_SUBSYSTEM = "channelsubsystem"; 78 private static final String POWER_ENTITY_NAME = "powerentityinfo"; 79 private static final String STATE_NAME = "stateinfo"; 80 private static final String ENERGY_CONSUMER_NAME = "energyconsumer"; 81 private static final String METER_CACHE_FILENAME = "meterCacheTest"; 82 private static final String MODEL_CACHE_FILENAME = "modelCacheTest"; 83 private static final String RESIDENCY_CACHE_FILENAME = "residencyCacheTest"; 84 private static final int ENERGY_METER_COUNT = 8; 85 private static final int ENERGY_CONSUMER_COUNT = 2; 86 private static final int ENERGY_CONSUMER_ATTRIBUTION_COUNT = 5; 87 private static final int POWER_ENTITY_COUNT = 3; 88 private static final int STATE_INFO_COUNT = 5; 89 private static final int STATE_RESIDENCY_COUNT = 4; 90 91 private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext(); 92 private PowerStatsService mService; 93 private File mDataStorageDir; 94 private TimerTrigger mTimerTrigger; 95 private BatteryTrigger mBatteryTrigger; 96 private PowerStatsLogger mPowerStatsLogger; 97 98 private final PowerStatsService.Injector mInjector = new PowerStatsService.Injector() { 99 private TestPowerStatsHALWrapper mTestPowerStatsHALWrapper = new TestPowerStatsHALWrapper(); 100 @Override 101 File createDataStoragePath() { 102 if (mDataStorageDir == null) { 103 try { 104 mDataStorageDir = Files.createTempDirectory(DATA_STORAGE_SUBDIR).toFile(); 105 } catch (IOException e) { 106 fail("Could not create temp directory."); 107 } 108 } 109 110 return mDataStorageDir; 111 } 112 113 @Override 114 String createMeterFilename() { 115 return METER_FILENAME; 116 } 117 118 @Override 119 String createModelFilename() { 120 return MODEL_FILENAME; 121 } 122 123 @Override 124 String createResidencyFilename() { 125 return RESIDENCY_FILENAME; 126 } 127 128 @Override 129 String createMeterCacheFilename() { 130 return METER_CACHE_FILENAME; 131 } 132 133 @Override 134 String createModelCacheFilename() { 135 return MODEL_CACHE_FILENAME; 136 } 137 138 @Override 139 String createResidencyCacheFilename() { 140 return RESIDENCY_CACHE_FILENAME; 141 } 142 143 @Override 144 IPowerStatsHALWrapper getPowerStatsHALWrapperImpl() { 145 return mTestPowerStatsHALWrapper; 146 } 147 148 @Override 149 PowerStatsLogger createPowerStatsLogger(Context context, Looper looper, 150 File dataStoragePath, String meterFilename, String meterCacheFilename, 151 String modelFilename, String modelCacheFilename, 152 String residencyFilename, String residencyCacheFilename, 153 IPowerStatsHALWrapper powerStatsHALWrapper) { 154 mPowerStatsLogger = new PowerStatsLogger(context, looper, dataStoragePath, 155 meterFilename, meterCacheFilename, 156 modelFilename, modelCacheFilename, 157 residencyFilename, residencyCacheFilename, 158 powerStatsHALWrapper); 159 return mPowerStatsLogger; 160 } 161 162 @Override 163 BatteryTrigger createBatteryTrigger(Context context, PowerStatsLogger powerStatsLogger) { 164 mBatteryTrigger = new BatteryTrigger(context, powerStatsLogger, 165 false /* trigger enabled */); 166 return mBatteryTrigger; 167 } 168 169 @Override 170 TimerTrigger createTimerTrigger(Context context, PowerStatsLogger powerStatsLogger) { 171 mTimerTrigger = new TimerTrigger(context, powerStatsLogger, 172 false /* trigger enabled */); 173 return mTimerTrigger; 174 } 175 }; 176 177 public static final class TestPowerStatsHALWrapper implements IPowerStatsHALWrapper { 178 @Override getPowerEntityInfo()179 public PowerEntity[] getPowerEntityInfo() { 180 PowerEntity[] powerEntityList = new PowerEntity[POWER_ENTITY_COUNT]; 181 for (int i = 0; i < powerEntityList.length; i++) { 182 powerEntityList[i] = new PowerEntity(); 183 powerEntityList[i].id = i; 184 powerEntityList[i].name = new String(POWER_ENTITY_NAME + i); 185 powerEntityList[i].states = new State[STATE_INFO_COUNT]; 186 for (int j = 0; j < powerEntityList[i].states.length; j++) { 187 powerEntityList[i].states[j] = new State(); 188 powerEntityList[i].states[j].id = j; 189 powerEntityList[i].states[j].name = new String(STATE_NAME + j); 190 } 191 } 192 return powerEntityList; 193 } 194 195 @Override getStateResidency(int[] powerEntityIds)196 public StateResidencyResult[] getStateResidency(int[] powerEntityIds) { 197 StateResidencyResult[] stateResidencyResultList = 198 new StateResidencyResult[POWER_ENTITY_COUNT]; 199 for (int i = 0; i < stateResidencyResultList.length; i++) { 200 stateResidencyResultList[i] = new StateResidencyResult(); 201 stateResidencyResultList[i].id = i; 202 stateResidencyResultList[i].stateResidencyData = 203 new StateResidency[STATE_RESIDENCY_COUNT]; 204 for (int j = 0; j < stateResidencyResultList[i].stateResidencyData.length; j++) { 205 stateResidencyResultList[i].stateResidencyData[j] = new StateResidency(); 206 stateResidencyResultList[i].stateResidencyData[j].id = j; 207 stateResidencyResultList[i].stateResidencyData[j].totalTimeInStateMs = j; 208 stateResidencyResultList[i].stateResidencyData[j].totalStateEntryCount = j; 209 stateResidencyResultList[i].stateResidencyData[j].lastEntryTimestampMs = j; 210 } 211 } 212 213 return stateResidencyResultList; 214 } 215 216 @Override getEnergyConsumerInfo()217 public EnergyConsumer[] getEnergyConsumerInfo() { 218 EnergyConsumer[] energyConsumerList = new EnergyConsumer[ENERGY_CONSUMER_COUNT]; 219 for (int i = 0; i < energyConsumerList.length; i++) { 220 energyConsumerList[i] = new EnergyConsumer(); 221 energyConsumerList[i].id = i; 222 energyConsumerList[i].ordinal = i; 223 energyConsumerList[i].type = (byte) i; 224 energyConsumerList[i].name = new String(ENERGY_CONSUMER_NAME + i); 225 } 226 return energyConsumerList; 227 } 228 229 @Override getEnergyConsumed(int[] energyConsumerIds)230 public EnergyConsumerResult[] getEnergyConsumed(int[] energyConsumerIds) { 231 EnergyConsumerResult[] energyConsumedList = 232 new EnergyConsumerResult[ENERGY_CONSUMER_COUNT]; 233 for (int i = 0; i < energyConsumedList.length; i++) { 234 energyConsumedList[i] = new EnergyConsumerResult(); 235 energyConsumedList[i].id = i; 236 energyConsumedList[i].timestampMs = i; 237 energyConsumedList[i].energyUWs = i; 238 energyConsumedList[i].attribution = 239 new EnergyConsumerAttribution[ENERGY_CONSUMER_ATTRIBUTION_COUNT]; 240 for (int j = 0; j < energyConsumedList[i].attribution.length; j++) { 241 energyConsumedList[i].attribution[j] = new EnergyConsumerAttribution(); 242 energyConsumedList[i].attribution[j].uid = j; 243 energyConsumedList[i].attribution[j].energyUWs = j; 244 } 245 } 246 return energyConsumedList; 247 } 248 249 @Override getEnergyMeterInfo()250 public Channel[] getEnergyMeterInfo() { 251 Channel[] energyMeterList = new Channel[ENERGY_METER_COUNT]; 252 for (int i = 0; i < energyMeterList.length; i++) { 253 energyMeterList[i] = new Channel(); 254 energyMeterList[i].id = i; 255 energyMeterList[i].name = new String(CHANNEL_NAME + i); 256 energyMeterList[i].subsystem = new String(CHANNEL_SUBSYSTEM + i); 257 } 258 return energyMeterList; 259 } 260 261 @Override readEnergyMeter(int[] channelIds)262 public EnergyMeasurement[] readEnergyMeter(int[] channelIds) { 263 EnergyMeasurement[] energyMeasurementList = new EnergyMeasurement[ENERGY_METER_COUNT]; 264 for (int i = 0; i < energyMeasurementList.length; i++) { 265 energyMeasurementList[i] = new EnergyMeasurement(); 266 energyMeasurementList[i].id = i; 267 energyMeasurementList[i].timestampMs = i; 268 energyMeasurementList[i].durationMs = i; 269 energyMeasurementList[i].energyUWs = i; 270 } 271 return energyMeasurementList; 272 } 273 274 @Override isInitialized()275 public boolean isInitialized() { 276 return true; 277 } 278 } 279 280 @Before setUp()281 public void setUp() { 282 mService = new PowerStatsService(mContext, mInjector); 283 } 284 285 @Test testWrittenMeterDataMatchesReadIncidentReportData()286 public void testWrittenMeterDataMatchesReadIncidentReportData() 287 throws InterruptedException, IOException { 288 mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 289 290 // Write data to on-device storage. 291 mTimerTrigger.logPowerStatsData(PowerStatsLogger.MSG_LOG_TO_DATA_STORAGE_HIGH_FREQUENCY); 292 293 // The above call puts a message on a handler. Wait for 294 // it to be processed. 295 Thread.sleep(100); 296 297 // Write on-device storage to an incident report. 298 File incidentReport = new File(mDataStorageDir, PROTO_OUTPUT_FILENAME); 299 FileOutputStream fos = new FileOutputStream(incidentReport); 300 mPowerStatsLogger.writeMeterDataToFile(fos.getFD()); 301 302 // Read the incident report in to a byte array. 303 FileInputStream fis = new FileInputStream(incidentReport); 304 byte[] fileContent = new byte[(int) incidentReport.length()]; 305 fis.read(fileContent); 306 307 // Parse the incident data into a PowerStatsServiceMeterProto object. 308 PowerStatsServiceMeterProto pssProto = PowerStatsServiceMeterProto.parseFrom(fileContent); 309 310 // Validate the channel array matches what was written to on-device storage. 311 assertTrue(pssProto.channel.length == ENERGY_METER_COUNT); 312 for (int i = 0; i < pssProto.channel.length; i++) { 313 assertTrue(pssProto.channel[i].id == i); 314 assertTrue(pssProto.channel[i].name.equals(CHANNEL_NAME + i)); 315 assertTrue(pssProto.channel[i].subsystem.equals(CHANNEL_SUBSYSTEM + i)); 316 } 317 318 // Validate the energyMeasurement array matches what was written to on-device storage. 319 assertTrue(pssProto.energyMeasurement.length == ENERGY_METER_COUNT); 320 for (int i = 0; i < pssProto.energyMeasurement.length; i++) { 321 assertTrue(pssProto.energyMeasurement[i].id == i); 322 assertTrue(pssProto.energyMeasurement[i].timestampMs == 323 i + mPowerStatsLogger.getStartWallTime()); 324 assertTrue(pssProto.energyMeasurement[i].durationMs == i); 325 assertTrue(pssProto.energyMeasurement[i].energyUws == i); 326 } 327 } 328 329 @Test testWrittenModelDataMatchesReadIncidentReportData()330 public void testWrittenModelDataMatchesReadIncidentReportData() 331 throws InterruptedException, IOException { 332 mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 333 334 // Write data to on-device storage. 335 mTimerTrigger.logPowerStatsData(PowerStatsLogger.MSG_LOG_TO_DATA_STORAGE_LOW_FREQUENCY); 336 337 // The above call puts a message on a handler. Wait for 338 // it to be processed. 339 Thread.sleep(100); 340 341 // Write on-device storage to an incident report. 342 File incidentReport = new File(mDataStorageDir, PROTO_OUTPUT_FILENAME); 343 FileOutputStream fos = new FileOutputStream(incidentReport); 344 mPowerStatsLogger.writeModelDataToFile(fos.getFD()); 345 346 // Read the incident report in to a byte array. 347 FileInputStream fis = new FileInputStream(incidentReport); 348 byte[] fileContent = new byte[(int) incidentReport.length()]; 349 fis.read(fileContent); 350 351 // Parse the incident data into a PowerStatsServiceModelProto object. 352 PowerStatsServiceModelProto pssProto = PowerStatsServiceModelProto.parseFrom(fileContent); 353 354 // Validate the energyConsumer array matches what was written to on-device storage. 355 assertTrue(pssProto.energyConsumer.length == ENERGY_CONSUMER_COUNT); 356 for (int i = 0; i < pssProto.energyConsumer.length; i++) { 357 assertTrue(pssProto.energyConsumer[i].id == i); 358 } 359 360 // Validate the energyConsumerResult array matches what was written to on-device storage. 361 assertTrue(pssProto.energyConsumerResult.length == ENERGY_CONSUMER_COUNT); 362 for (int i = 0; i < pssProto.energyConsumerResult.length; i++) { 363 assertTrue(pssProto.energyConsumerResult[i].id == i); 364 assertTrue(pssProto.energyConsumerResult[i].timestampMs == 365 i + mPowerStatsLogger.getStartWallTime()); 366 assertTrue(pssProto.energyConsumerResult[i].energyUws == i); 367 assertTrue(pssProto.energyConsumerResult[i].attribution.length 368 == ENERGY_CONSUMER_ATTRIBUTION_COUNT); 369 for (int j = 0; j < pssProto.energyConsumerResult[i].attribution.length; j++) { 370 assertTrue(pssProto.energyConsumerResult[i].attribution[j].uid == j); 371 assertTrue(pssProto.energyConsumerResult[i].attribution[j].energyUws == j); 372 } 373 } 374 } 375 376 @Test testWrittenResidencyDataMatchesReadIncidentReportData()377 public void testWrittenResidencyDataMatchesReadIncidentReportData() 378 throws InterruptedException, IOException { 379 mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 380 381 // Write data to on-device storage. 382 mBatteryTrigger.logPowerStatsData(PowerStatsLogger.MSG_LOG_TO_DATA_STORAGE_BATTERY_DROP); 383 384 // The above call puts a message on a handler. Wait for 385 // it to be processed. 386 Thread.sleep(100); 387 388 // Write on-device storage to an incident report. 389 File incidentReport = new File(mDataStorageDir, PROTO_OUTPUT_FILENAME); 390 FileOutputStream fos = new FileOutputStream(incidentReport); 391 mPowerStatsLogger.writeResidencyDataToFile(fos.getFD()); 392 393 // Read the incident report in to a byte array. 394 FileInputStream fis = new FileInputStream(incidentReport); 395 byte[] fileContent = new byte[(int) incidentReport.length()]; 396 fis.read(fileContent); 397 398 // Parse the incident data into a PowerStatsServiceResidencyProto object. 399 PowerStatsServiceResidencyProto pssProto = 400 PowerStatsServiceResidencyProto.parseFrom(fileContent); 401 402 // Validate the powerEntity array matches what was written to on-device storage. 403 assertTrue(pssProto.powerEntity.length == POWER_ENTITY_COUNT); 404 for (int i = 0; i < pssProto.powerEntity.length; i++) { 405 PowerEntityProto powerEntity = pssProto.powerEntity[i]; 406 assertTrue(powerEntity.id == i); 407 assertTrue(powerEntity.name.equals(POWER_ENTITY_NAME + i)); 408 for (int j = 0; j < powerEntity.states.length; j++) { 409 StateProto state = powerEntity.states[j]; 410 assertTrue(state.id == j); 411 assertTrue(state.name.equals(STATE_NAME + j)); 412 } 413 } 414 415 // Validate the stateResidencyResult array matches what was written to on-device storage. 416 assertTrue(pssProto.stateResidencyResult.length == POWER_ENTITY_COUNT); 417 for (int i = 0; i < pssProto.stateResidencyResult.length; i++) { 418 StateResidencyResultProto stateResidencyResult = pssProto.stateResidencyResult[i]; 419 assertTrue(stateResidencyResult.id == i); 420 assertTrue(stateResidencyResult.stateResidencyData.length == STATE_RESIDENCY_COUNT); 421 for (int j = 0; j < stateResidencyResult.stateResidencyData.length; j++) { 422 StateResidencyProto stateResidency = stateResidencyResult.stateResidencyData[j]; 423 assertTrue(stateResidency.id == j); 424 assertTrue(stateResidency.totalTimeInStateMs == j); 425 assertTrue(stateResidency.totalStateEntryCount == j); 426 assertTrue(stateResidency.lastEntryTimestampMs == 427 j + mPowerStatsLogger.getStartWallTime()); 428 } 429 } 430 } 431 432 @Test testCorruptOnDeviceMeterStorage()433 public void testCorruptOnDeviceMeterStorage() throws IOException { 434 mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 435 436 // Generate random array of bytes to emulate corrupt data. 437 Random rd = new Random(); 438 byte[] bytes = new byte[100]; 439 rd.nextBytes(bytes); 440 441 // Store corrupt data in on-device storage. Add fake timestamp to filename 442 // to match format expected by FileRotator. 443 File onDeviceStorageFile = new File(mDataStorageDir, METER_FILENAME + ".1234-2234"); 444 FileOutputStream onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile); 445 onDeviceStorageFos.write(bytes); 446 onDeviceStorageFos.close(); 447 448 // Write on-device storage to an incident report. 449 File incidentReport = new File(mDataStorageDir, PROTO_OUTPUT_FILENAME); 450 FileOutputStream incidentReportFos = new FileOutputStream(incidentReport); 451 mPowerStatsLogger.writeMeterDataToFile(incidentReportFos.getFD()); 452 453 // Read the incident report in to a byte array. 454 FileInputStream fis = new FileInputStream(incidentReport); 455 byte[] fileContent = new byte[(int) incidentReport.length()]; 456 fis.read(fileContent); 457 458 // Parse the incident data into a PowerStatsServiceMeterProto object. 459 PowerStatsServiceMeterProto pssProto = PowerStatsServiceMeterProto.parseFrom(fileContent); 460 461 // Valid channel data is written to the incident report in the call to 462 // mPowerStatsLogger.writeMeterDataToFile(). 463 assertTrue(pssProto.channel.length == ENERGY_METER_COUNT); 464 for (int i = 0; i < pssProto.channel.length; i++) { 465 assertTrue(pssProto.channel[i].id == i); 466 assertTrue(pssProto.channel[i].name.equals(CHANNEL_NAME + i)); 467 assertTrue(pssProto.channel[i].subsystem.equals(CHANNEL_SUBSYSTEM + i)); 468 } 469 470 // No energyMeasurements should be written to the incident report since it 471 // is all corrupt (random bytes generated above). 472 assertTrue(pssProto.energyMeasurement.length == 0); 473 } 474 475 @Test testCorruptOnDeviceModelStorage()476 public void testCorruptOnDeviceModelStorage() throws IOException { 477 mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 478 479 // Generate random array of bytes to emulate corrupt data. 480 Random rd = new Random(); 481 byte[] bytes = new byte[100]; 482 rd.nextBytes(bytes); 483 484 // Store corrupt data in on-device storage. Add fake timestamp to filename 485 // to match format expected by FileRotator. 486 File onDeviceStorageFile = new File(mDataStorageDir, MODEL_FILENAME + ".1234-2234"); 487 FileOutputStream onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile); 488 onDeviceStorageFos.write(bytes); 489 onDeviceStorageFos.close(); 490 491 // Write on-device storage to an incident report. 492 File incidentReport = new File(mDataStorageDir, PROTO_OUTPUT_FILENAME); 493 FileOutputStream incidentReportFos = new FileOutputStream(incidentReport); 494 mPowerStatsLogger.writeModelDataToFile(incidentReportFos.getFD()); 495 496 // Read the incident report in to a byte array. 497 FileInputStream fis = new FileInputStream(incidentReport); 498 byte[] fileContent = new byte[(int) incidentReport.length()]; 499 fis.read(fileContent); 500 501 // Parse the incident data into a PowerStatsServiceModelProto object. 502 PowerStatsServiceModelProto pssProto = PowerStatsServiceModelProto.parseFrom(fileContent); 503 504 // Valid energyConsumer data is written to the incident report in the call to 505 // mPowerStatsLogger.writeModelDataToFile(). 506 assertTrue(pssProto.energyConsumer.length == ENERGY_CONSUMER_COUNT); 507 for (int i = 0; i < pssProto.energyConsumer.length; i++) { 508 assertTrue(pssProto.energyConsumer[i].id == i); 509 } 510 511 // No energyConsumerResults should be written to the incident report since it 512 // is all corrupt (random bytes generated above). 513 assertTrue(pssProto.energyConsumerResult.length == 0); 514 } 515 516 @Test testCorruptOnDeviceResidencyStorage()517 public void testCorruptOnDeviceResidencyStorage() throws IOException { 518 mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 519 520 // Generate random array of bytes to emulate corrupt data. 521 Random rd = new Random(); 522 byte[] bytes = new byte[100]; 523 rd.nextBytes(bytes); 524 525 // Store corrupt data in on-device storage. Add fake timestamp to filename 526 // to match format expected by FileRotator. 527 File onDeviceStorageFile = new File(mDataStorageDir, RESIDENCY_FILENAME + ".1234-2234"); 528 FileOutputStream onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile); 529 onDeviceStorageFos.write(bytes); 530 onDeviceStorageFos.close(); 531 532 // Write on-device storage to an incident report. 533 File incidentReport = new File(mDataStorageDir, PROTO_OUTPUT_FILENAME); 534 FileOutputStream incidentReportFos = new FileOutputStream(incidentReport); 535 mPowerStatsLogger.writeResidencyDataToFile(incidentReportFos.getFD()); 536 537 // Read the incident report in to a byte array. 538 FileInputStream fis = new FileInputStream(incidentReport); 539 byte[] fileContent = new byte[(int) incidentReport.length()]; 540 fis.read(fileContent); 541 542 // Parse the incident data into a PowerStatsServiceResidencyProto object. 543 PowerStatsServiceResidencyProto pssProto = 544 PowerStatsServiceResidencyProto.parseFrom(fileContent); 545 546 // Valid powerEntity data is written to the incident report in the call to 547 // mPowerStatsLogger.writeResidencyDataToFile(). 548 assertTrue(pssProto.powerEntity.length == POWER_ENTITY_COUNT); 549 for (int i = 0; i < pssProto.powerEntity.length; i++) { 550 PowerEntityProto powerEntity = pssProto.powerEntity[i]; 551 assertTrue(powerEntity.id == i); 552 assertTrue(powerEntity.name.equals(POWER_ENTITY_NAME + i)); 553 for (int j = 0; j < powerEntity.states.length; j++) { 554 StateProto state = powerEntity.states[j]; 555 assertTrue(state.id == j); 556 assertTrue(state.name.equals(STATE_NAME + j)); 557 } 558 } 559 560 // No stateResidencyResults should be written to the incident report since it 561 // is all corrupt (random bytes generated above). 562 assertTrue(pssProto.stateResidencyResult.length == 0); 563 } 564 565 @Test testNotEnoughBytesAfterMeterLengthField()566 public void testNotEnoughBytesAfterMeterLengthField() throws IOException { 567 mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 568 569 // Create corrupt data. 570 // Length field is correct, but there is no data following the length. 571 ByteArrayOutputStream data = new ByteArrayOutputStream(); 572 data.write(ByteBuffer.allocate(4).putInt(50).array()); 573 byte[] test = data.toByteArray(); 574 575 // Store corrupt data in on-device storage. Add fake timestamp to filename 576 // to match format expected by FileRotator. 577 File onDeviceStorageFile = new File(mDataStorageDir, METER_FILENAME + ".1234-2234"); 578 FileOutputStream onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile); 579 onDeviceStorageFos.write(data.toByteArray()); 580 onDeviceStorageFos.close(); 581 582 // Write on-device storage to an incident report. 583 File incidentReport = new File(mDataStorageDir, PROTO_OUTPUT_FILENAME); 584 FileOutputStream incidentReportFos = new FileOutputStream(incidentReport); 585 mPowerStatsLogger.writeMeterDataToFile(incidentReportFos.getFD()); 586 587 // Read the incident report in to a byte array. 588 FileInputStream fis = new FileInputStream(incidentReport); 589 byte[] fileContent = new byte[(int) incidentReport.length()]; 590 fis.read(fileContent); 591 592 // Parse the incident data into a PowerStatsServiceMeterProto object. 593 PowerStatsServiceMeterProto pssProto = PowerStatsServiceMeterProto.parseFrom(fileContent); 594 595 // Valid channel data is written to the incident report in the call to 596 // mPowerStatsLogger.writeMeterDataToFile(). 597 assertTrue(pssProto.channel.length == ENERGY_METER_COUNT); 598 for (int i = 0; i < pssProto.channel.length; i++) { 599 assertTrue(pssProto.channel[i].id == i); 600 assertTrue(pssProto.channel[i].name.equals(CHANNEL_NAME + i)); 601 assertTrue(pssProto.channel[i].subsystem.equals(CHANNEL_SUBSYSTEM + i)); 602 } 603 604 // No energyMeasurements should be written to the incident report since the 605 // input buffer had only length and no data. 606 assertTrue(pssProto.energyMeasurement.length == 0); 607 } 608 609 @Test testNotEnoughBytesAfterModelLengthField()610 public void testNotEnoughBytesAfterModelLengthField() throws IOException { 611 mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 612 613 // Create corrupt data. 614 // Length field is correct, but there is no data following the length. 615 ByteArrayOutputStream data = new ByteArrayOutputStream(); 616 data.write(ByteBuffer.allocate(4).putInt(50).array()); 617 byte[] test = data.toByteArray(); 618 619 // Store corrupt data in on-device storage. Add fake timestamp to filename 620 // to match format expected by FileRotator. 621 File onDeviceStorageFile = new File(mDataStorageDir, MODEL_FILENAME + ".1234-2234"); 622 FileOutputStream onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile); 623 onDeviceStorageFos.write(data.toByteArray()); 624 onDeviceStorageFos.close(); 625 626 // Write on-device storage to an incident report. 627 File incidentReport = new File(mDataStorageDir, PROTO_OUTPUT_FILENAME); 628 FileOutputStream incidentReportFos = new FileOutputStream(incidentReport); 629 mPowerStatsLogger.writeModelDataToFile(incidentReportFos.getFD()); 630 631 // Read the incident report in to a byte array. 632 FileInputStream fis = new FileInputStream(incidentReport); 633 byte[] fileContent = new byte[(int) incidentReport.length()]; 634 fis.read(fileContent); 635 636 // Parse the incident data into a PowerStatsServiceModelProto object. 637 PowerStatsServiceModelProto pssProto = PowerStatsServiceModelProto.parseFrom(fileContent); 638 639 // Valid energyConsumer data is written to the incident report in the call to 640 // mPowerStatsLogger.writeModelDataToFile(). 641 assertTrue(pssProto.energyConsumer.length == ENERGY_CONSUMER_COUNT); 642 for (int i = 0; i < pssProto.energyConsumer.length; i++) { 643 assertTrue(pssProto.energyConsumer[i].id == i); 644 } 645 646 // No energyConsumerResults should be written to the incident report since the 647 // input buffer had only length and no data. 648 assertTrue(pssProto.energyConsumerResult.length == 0); 649 } 650 651 @Test testNotEnoughBytesAfterResidencyLengthField()652 public void testNotEnoughBytesAfterResidencyLengthField() throws IOException { 653 mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 654 655 // Create corrupt data. 656 // Length field is correct, but there is no data following the length. 657 ByteArrayOutputStream data = new ByteArrayOutputStream(); 658 data.write(ByteBuffer.allocate(4).putInt(50).array()); 659 byte[] test = data.toByteArray(); 660 661 // Store corrupt data in on-device storage. Add fake timestamp to filename 662 // to match format expected by FileRotator. 663 File onDeviceStorageFile = new File(mDataStorageDir, RESIDENCY_FILENAME + ".1234-2234"); 664 FileOutputStream onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile); 665 onDeviceStorageFos.write(data.toByteArray()); 666 onDeviceStorageFos.close(); 667 668 // Write on-device storage to an incident report. 669 File incidentReport = new File(mDataStorageDir, PROTO_OUTPUT_FILENAME); 670 FileOutputStream incidentReportFos = new FileOutputStream(incidentReport); 671 mPowerStatsLogger.writeResidencyDataToFile(incidentReportFos.getFD()); 672 673 // Read the incident report in to a byte array. 674 FileInputStream fis = new FileInputStream(incidentReport); 675 byte[] fileContent = new byte[(int) incidentReport.length()]; 676 fis.read(fileContent); 677 678 // Parse the incident data into a PowerStatsServiceResidencyProto object. 679 PowerStatsServiceResidencyProto pssProto = 680 PowerStatsServiceResidencyProto.parseFrom(fileContent); 681 682 // Valid powerEntity data is written to the incident report in the call to 683 // mPowerStatsLogger.writeResidencyDataToFile(). 684 assertTrue(pssProto.powerEntity.length == POWER_ENTITY_COUNT); 685 for (int i = 0; i < pssProto.powerEntity.length; i++) { 686 PowerEntityProto powerEntity = pssProto.powerEntity[i]; 687 assertTrue(powerEntity.id == i); 688 assertTrue(powerEntity.name.equals(POWER_ENTITY_NAME + i)); 689 for (int j = 0; j < powerEntity.states.length; j++) { 690 StateProto state = powerEntity.states[j]; 691 assertTrue(state.id == j); 692 assertTrue(state.name.equals(STATE_NAME + j)); 693 } 694 } 695 696 // No stateResidencyResults should be written to the incident report since the 697 // input buffer had only length and no data. 698 assertTrue(pssProto.stateResidencyResult.length == 0); 699 } 700 701 @Test testDataStorageDeletedMeterMismatch()702 public void testDataStorageDeletedMeterMismatch() throws IOException { 703 // Create the directory where cached data will be stored. 704 mInjector.createDataStoragePath(); 705 706 // In order to create cached data that will match the current data read by the 707 // PowerStatsService we need to write valid data from the TestPowerStatsHALWrapper that is 708 // returned from the Injector. 709 IPowerStatsHALWrapper powerStatsHALWrapper = mInjector.getPowerStatsHALWrapperImpl(); 710 711 // Generate random array of bytes to emulate cached meter data. Store to file. 712 Random rd = new Random(); 713 byte[] bytes = new byte[100]; 714 rd.nextBytes(bytes); 715 File onDeviceStorageFile = new File(mDataStorageDir, mInjector.createMeterCacheFilename()); 716 FileOutputStream onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile); 717 onDeviceStorageFos.write(bytes); 718 onDeviceStorageFos.close(); 719 720 // Create cached energy consumer data and write to file. 721 EnergyConsumer[] energyConsumers = powerStatsHALWrapper.getEnergyConsumerInfo(); 722 bytes = EnergyConsumerUtils.getProtoBytes(energyConsumers); 723 onDeviceStorageFile = new File(mDataStorageDir, mInjector.createModelCacheFilename()); 724 onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile); 725 onDeviceStorageFos.write(bytes); 726 onDeviceStorageFos.close(); 727 728 // Create cached power entity info data and write to file. 729 PowerEntity[] powerEntityInfo = powerStatsHALWrapper.getPowerEntityInfo(); 730 bytes = PowerEntityUtils.getProtoBytes(powerEntityInfo); 731 onDeviceStorageFile = new File(mDataStorageDir, mInjector.createResidencyCacheFilename()); 732 onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile); 733 onDeviceStorageFos.write(bytes); 734 onDeviceStorageFos.close(); 735 736 // Create log files. 737 File meterFile = new File(mDataStorageDir, mInjector.createMeterFilename()); 738 File modelFile = new File(mDataStorageDir, mInjector.createModelFilename()); 739 File residencyFile = new File(mDataStorageDir, mInjector.createResidencyFilename()); 740 meterFile.createNewFile(); 741 modelFile.createNewFile(); 742 residencyFile.createNewFile(); 743 744 // Verify log files exist. 745 assertTrue(meterFile.exists()); 746 assertTrue(modelFile.exists()); 747 assertTrue(residencyFile.exists()); 748 749 // Boot device after creating old cached data. 750 mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 751 752 // Since cached meter data is just random bytes it won't match the data read from the HAL. 753 // This mismatch of cached and current HAL data should force a delete. 754 assertTrue(mService.getDeleteMeterDataOnBoot()); 755 assertFalse(mService.getDeleteModelDataOnBoot()); 756 assertFalse(mService.getDeleteResidencyDataOnBoot()); 757 758 // Verify log files were deleted. 759 assertFalse(meterFile.exists()); 760 assertTrue(modelFile.exists()); 761 assertTrue(residencyFile.exists()); 762 763 // Verify cached meter data was updated to new HAL output. 764 Channel[] channels = powerStatsHALWrapper.getEnergyMeterInfo(); 765 byte[] bytesExpected = ChannelUtils.getProtoBytes(channels); 766 onDeviceStorageFile = new File(mDataStorageDir, mInjector.createMeterCacheFilename()); 767 byte[] bytesActual = new byte[(int) onDeviceStorageFile.length()]; 768 FileInputStream onDeviceStorageFis = new FileInputStream(onDeviceStorageFile); 769 onDeviceStorageFis.read(bytesActual); 770 assertTrue(Arrays.equals(bytesExpected, bytesActual)); 771 } 772 773 @Test testDataStorageDeletedModelMismatch()774 public void testDataStorageDeletedModelMismatch() throws IOException { 775 // Create the directory where cached data will be stored. 776 mInjector.createDataStoragePath(); 777 778 // In order to create cached data that will match the current data read by the 779 // PowerStatsService we need to write valid data from the TestPowerStatsHALWrapper that is 780 // returned from the Injector. 781 IPowerStatsHALWrapper powerStatsHALWrapper = mInjector.getPowerStatsHALWrapperImpl(); 782 783 // Create cached channel data and write to file. 784 Channel[] channels = powerStatsHALWrapper.getEnergyMeterInfo(); 785 byte[] bytes = ChannelUtils.getProtoBytes(channels); 786 File onDeviceStorageFile = new File(mDataStorageDir, mInjector.createMeterCacheFilename()); 787 FileOutputStream onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile); 788 onDeviceStorageFos.write(bytes); 789 onDeviceStorageFos.close(); 790 791 // Generate random array of bytes to emulate cached energy consumer data. Store to file. 792 Random rd = new Random(); 793 bytes = new byte[100]; 794 rd.nextBytes(bytes); 795 onDeviceStorageFile = new File(mDataStorageDir, mInjector.createModelCacheFilename()); 796 onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile); 797 onDeviceStorageFos.write(bytes); 798 onDeviceStorageFos.close(); 799 800 // Create cached power entity info data and write to file. 801 PowerEntity[] powerEntityInfo = powerStatsHALWrapper.getPowerEntityInfo(); 802 bytes = PowerEntityUtils.getProtoBytes(powerEntityInfo); 803 onDeviceStorageFile = new File(mDataStorageDir, mInjector.createResidencyCacheFilename()); 804 onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile); 805 onDeviceStorageFos.write(bytes); 806 onDeviceStorageFos.close(); 807 808 // Create log files. 809 File meterFile = new File(mDataStorageDir, mInjector.createMeterFilename()); 810 File modelFile = new File(mDataStorageDir, mInjector.createModelFilename()); 811 File residencyFile = new File(mDataStorageDir, mInjector.createResidencyFilename()); 812 meterFile.createNewFile(); 813 modelFile.createNewFile(); 814 residencyFile.createNewFile(); 815 816 // Verify log files exist. 817 assertTrue(meterFile.exists()); 818 assertTrue(modelFile.exists()); 819 assertTrue(residencyFile.exists()); 820 821 // Boot device after creating old cached data. 822 mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 823 824 // Since cached energy consumer data is just random bytes it won't match the data read from 825 // the HAL. This mismatch of cached and current HAL data should force a delete. 826 assertFalse(mService.getDeleteMeterDataOnBoot()); 827 assertTrue(mService.getDeleteModelDataOnBoot()); 828 assertFalse(mService.getDeleteResidencyDataOnBoot()); 829 830 // Verify log files were deleted. 831 assertTrue(meterFile.exists()); 832 assertFalse(modelFile.exists()); 833 assertTrue(residencyFile.exists()); 834 835 // Verify cached energy consumer data was updated to new HAL output. 836 EnergyConsumer[] energyConsumers = powerStatsHALWrapper.getEnergyConsumerInfo(); 837 byte[] bytesExpected = EnergyConsumerUtils.getProtoBytes(energyConsumers); 838 onDeviceStorageFile = new File(mDataStorageDir, mInjector.createModelCacheFilename()); 839 byte[] bytesActual = new byte[(int) onDeviceStorageFile.length()]; 840 FileInputStream onDeviceStorageFis = new FileInputStream(onDeviceStorageFile); 841 onDeviceStorageFis.read(bytesActual); 842 assertTrue(Arrays.equals(bytesExpected, bytesActual)); 843 } 844 845 @Test testDataStorageDeletedResidencyMismatch()846 public void testDataStorageDeletedResidencyMismatch() throws IOException { 847 // Create the directory where cached data will be stored. 848 mInjector.createDataStoragePath(); 849 850 // In order to create cached data that will match the current data read by the 851 // PowerStatsService we need to write valid data from the TestPowerStatsHALWrapper that is 852 // returned from the Injector. 853 IPowerStatsHALWrapper powerStatsHALWrapper = mInjector.getPowerStatsHALWrapperImpl(); 854 855 // Create cached channel data and write to file. 856 Channel[] channels = powerStatsHALWrapper.getEnergyMeterInfo(); 857 byte[] bytes = ChannelUtils.getProtoBytes(channels); 858 File onDeviceStorageFile = new File(mDataStorageDir, mInjector.createMeterCacheFilename()); 859 FileOutputStream onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile); 860 onDeviceStorageFos.write(bytes); 861 onDeviceStorageFos.close(); 862 863 // Create cached energy consumer data and write to file. 864 EnergyConsumer[] energyConsumers = powerStatsHALWrapper.getEnergyConsumerInfo(); 865 bytes = EnergyConsumerUtils.getProtoBytes(energyConsumers); 866 onDeviceStorageFile = new File(mDataStorageDir, mInjector.createModelCacheFilename()); 867 onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile); 868 onDeviceStorageFos.write(bytes); 869 onDeviceStorageFos.close(); 870 871 // Generate random array of bytes to emulate cached power entity info data. Store to file. 872 Random rd = new Random(); 873 bytes = new byte[100]; 874 rd.nextBytes(bytes); 875 onDeviceStorageFile = new File(mDataStorageDir, mInjector.createResidencyCacheFilename()); 876 onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile); 877 onDeviceStorageFos.write(bytes); 878 onDeviceStorageFos.close(); 879 880 // Create log files. 881 File meterFile = new File(mDataStorageDir, mInjector.createMeterFilename()); 882 File modelFile = new File(mDataStorageDir, mInjector.createModelFilename()); 883 File residencyFile = new File(mDataStorageDir, mInjector.createResidencyFilename()); 884 meterFile.createNewFile(); 885 modelFile.createNewFile(); 886 residencyFile.createNewFile(); 887 888 // Verify log files exist. 889 assertTrue(meterFile.exists()); 890 assertTrue(modelFile.exists()); 891 assertTrue(residencyFile.exists()); 892 893 // Boot device after creating old cached data. 894 mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 895 896 // Since cached power entity info data is just random bytes it won't match the data read 897 // from the HAL. This mismatch of cached and current HAL data should force a delete. 898 assertFalse(mService.getDeleteMeterDataOnBoot()); 899 assertFalse(mService.getDeleteModelDataOnBoot()); 900 assertTrue(mService.getDeleteResidencyDataOnBoot()); 901 902 // Verify log files were deleted. 903 assertTrue(meterFile.exists()); 904 assertTrue(modelFile.exists()); 905 assertFalse(residencyFile.exists()); 906 907 // Verify cached power entity data was updated to new HAL output. 908 PowerEntity[] powerEntityInfo = powerStatsHALWrapper.getPowerEntityInfo(); 909 byte[] bytesExpected = PowerEntityUtils.getProtoBytes(powerEntityInfo); 910 onDeviceStorageFile = new File(mDataStorageDir, mInjector.createResidencyCacheFilename()); 911 byte[] bytesActual = new byte[(int) onDeviceStorageFile.length()]; 912 FileInputStream onDeviceStorageFis = new FileInputStream(onDeviceStorageFile); 913 onDeviceStorageFis.read(bytesActual); 914 assertTrue(Arrays.equals(bytesExpected, bytesActual)); 915 } 916 917 @Test testDataStorageNotDeletedNoCachedData()918 public void testDataStorageNotDeletedNoCachedData() throws IOException { 919 // Create the directory where log files will be stored. 920 mInjector.createDataStoragePath(); 921 922 // Create log files. 923 File meterFile = new File(mDataStorageDir, mInjector.createMeterFilename()); 924 File modelFile = new File(mDataStorageDir, mInjector.createModelFilename()); 925 File residencyFile = new File(mDataStorageDir, mInjector.createResidencyFilename()); 926 meterFile.createNewFile(); 927 modelFile.createNewFile(); 928 residencyFile.createNewFile(); 929 930 // Verify log files exist. 931 assertTrue(meterFile.exists()); 932 assertTrue(modelFile.exists()); 933 assertTrue(residencyFile.exists()); 934 935 // This test mimics the device's first boot where there is no cached data. 936 mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 937 938 // Since there is no cached data on the first boot any log files that happen to exist 939 // should be deleted. 940 assertTrue(mService.getDeleteMeterDataOnBoot()); 941 assertTrue(mService.getDeleteModelDataOnBoot()); 942 assertTrue(mService.getDeleteResidencyDataOnBoot()); 943 944 // Verify log files were deleted. 945 assertFalse(meterFile.exists()); 946 assertFalse(modelFile.exists()); 947 assertFalse(residencyFile.exists()); 948 } 949 950 @Test testDataStorageNotDeletedAllDataMatches()951 public void testDataStorageNotDeletedAllDataMatches() throws IOException { 952 // Create the directory where cached data will be stored. 953 mInjector.createDataStoragePath(); 954 955 // In order to create cached data that will match the current data read by the 956 // PowerStatsService we need to write valid data from the TestPowerStatsHALWrapper that is 957 // returned from the Injector. 958 IPowerStatsHALWrapper powerStatsHALWrapper = mInjector.getPowerStatsHALWrapperImpl(); 959 960 // Create cached channel data and write to file. 961 Channel[] channels = powerStatsHALWrapper.getEnergyMeterInfo(); 962 byte[] bytes = ChannelUtils.getProtoBytes(channels); 963 File onDeviceStorageFile = new File(mDataStorageDir, mInjector.createMeterCacheFilename()); 964 FileOutputStream onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile); 965 onDeviceStorageFos.write(bytes); 966 onDeviceStorageFos.close(); 967 968 // Create cached energy consumer data and write to file. 969 EnergyConsumer[] energyConsumers = powerStatsHALWrapper.getEnergyConsumerInfo(); 970 bytes = EnergyConsumerUtils.getProtoBytes(energyConsumers); 971 onDeviceStorageFile = new File(mDataStorageDir, mInjector.createModelCacheFilename()); 972 onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile); 973 onDeviceStorageFos.write(bytes); 974 onDeviceStorageFos.close(); 975 976 // Create cached power entity info data and write to file. 977 PowerEntity[] powerEntityInfo = powerStatsHALWrapper.getPowerEntityInfo(); 978 bytes = PowerEntityUtils.getProtoBytes(powerEntityInfo); 979 onDeviceStorageFile = new File(mDataStorageDir, mInjector.createResidencyCacheFilename()); 980 onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile); 981 onDeviceStorageFos.write(bytes); 982 onDeviceStorageFos.close(); 983 984 // Create log files. 985 File meterFile = new File(mDataStorageDir, mInjector.createMeterFilename()); 986 File modelFile = new File(mDataStorageDir, mInjector.createModelFilename()); 987 File residencyFile = new File(mDataStorageDir, mInjector.createResidencyFilename()); 988 meterFile.createNewFile(); 989 modelFile.createNewFile(); 990 residencyFile.createNewFile(); 991 992 // Verify log files exist. 993 assertTrue(meterFile.exists()); 994 assertTrue(modelFile.exists()); 995 assertTrue(residencyFile.exists()); 996 997 // Boot device after creating old cached data. 998 mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 999 1000 // All cached data created above should match current data read in PowerStatsService so we 1001 // expect the data not to be deleted. 1002 assertFalse(mService.getDeleteMeterDataOnBoot()); 1003 assertFalse(mService.getDeleteModelDataOnBoot()); 1004 assertFalse(mService.getDeleteResidencyDataOnBoot()); 1005 1006 // Verify log files were not deleted. 1007 assertTrue(meterFile.exists()); 1008 assertTrue(modelFile.exists()); 1009 assertTrue(residencyFile.exists()); 1010 } 1011 } 1012