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