1 /* 2 * Copyright (C) 2022 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 android.healthconnect.cts; 18 19 import static android.health.connect.datatypes.PowerRecord.POWER_AVG; 20 import static android.health.connect.datatypes.PowerRecord.POWER_MAX; 21 import static android.health.connect.datatypes.PowerRecord.POWER_MIN; 22 23 import static com.google.common.truth.Truth.assertThat; 24 25 import android.content.Context; 26 import android.health.connect.AggregateRecordsRequest; 27 import android.health.connect.AggregateRecordsResponse; 28 import android.health.connect.DeleteUsingFiltersRequest; 29 import android.health.connect.HealthConnectException; 30 import android.health.connect.ReadRecordsRequestUsingFilters; 31 import android.health.connect.ReadRecordsRequestUsingIds; 32 import android.health.connect.RecordIdFilter; 33 import android.health.connect.TimeInstantRangeFilter; 34 import android.health.connect.changelog.ChangeLogTokenRequest; 35 import android.health.connect.changelog.ChangeLogTokenResponse; 36 import android.health.connect.changelog.ChangeLogsRequest; 37 import android.health.connect.changelog.ChangeLogsResponse; 38 import android.health.connect.datatypes.DataOrigin; 39 import android.health.connect.datatypes.Device; 40 import android.health.connect.datatypes.Metadata; 41 import android.health.connect.datatypes.PowerRecord; 42 import android.health.connect.datatypes.Record; 43 import android.health.connect.datatypes.units.Power; 44 import android.platform.test.annotations.AppModeFull; 45 46 import androidx.test.core.app.ApplicationProvider; 47 import androidx.test.runner.AndroidJUnit4; 48 49 import org.junit.After; 50 import org.junit.Assert; 51 import org.junit.Before; 52 import org.junit.Test; 53 import org.junit.runner.RunWith; 54 55 import java.time.Instant; 56 import java.time.ZoneOffset; 57 import java.time.temporal.ChronoUnit; 58 import java.util.ArrayList; 59 import java.util.Arrays; 60 import java.util.Collections; 61 import java.util.List; 62 import java.util.Set; 63 import java.util.UUID; 64 65 @AppModeFull(reason = "HealthConnectManager is not accessible to instant apps") 66 @RunWith(AndroidJUnit4.class) 67 public class PowerRecordTest { 68 private static final String TAG = "PowerRecordTest"; 69 70 @Before setUp()71 public void setUp() { 72 // TODO(b/283737434): Update the HC code to use user aware context on permission change. 73 // Temporary fix to set firstGrantTime for the correct user in HSUM. 74 TestUtils.deleteAllStagedRemoteData(); 75 } 76 77 @After tearDown()78 public void tearDown() throws InterruptedException { 79 TestUtils.verifyDeleteRecords( 80 PowerRecord.class, 81 new TimeInstantRangeFilter.Builder() 82 .setStartTime(Instant.EPOCH) 83 .setEndTime(Instant.now()) 84 .build()); 85 TestUtils.deleteAllStagedRemoteData(); 86 } 87 88 @Test testInsertPowerRecord()89 public void testInsertPowerRecord() throws InterruptedException { 90 TestUtils.insertRecords(Arrays.asList(getBasePowerRecord(), getCompletePowerRecord())); 91 } 92 93 @Test testReadPowerRecord_usingIds()94 public void testReadPowerRecord_usingIds() throws InterruptedException { 95 testReadPowerRecordIds(); 96 } 97 98 @Test testReadPowerRecord_invalidIds()99 public void testReadPowerRecord_invalidIds() throws InterruptedException { 100 ReadRecordsRequestUsingIds<PowerRecord> request = 101 new ReadRecordsRequestUsingIds.Builder<>(PowerRecord.class) 102 .addId(UUID.randomUUID().toString()) 103 .build(); 104 List<PowerRecord> result = TestUtils.readRecords(request); 105 assertThat(result.size()).isEqualTo(0); 106 } 107 108 @Test testReadPowerRecord_usingClientRecordIds()109 public void testReadPowerRecord_usingClientRecordIds() throws InterruptedException { 110 List<Record> recordList = Arrays.asList(getCompletePowerRecord(), getCompletePowerRecord()); 111 List<Record> insertedRecords = TestUtils.insertRecords(recordList); 112 readPowerRecordUsingClientId(insertedRecords); 113 } 114 115 @Test testReadPowerRecord_invalidClientRecordIds()116 public void testReadPowerRecord_invalidClientRecordIds() throws InterruptedException { 117 ReadRecordsRequestUsingIds<PowerRecord> request = 118 new ReadRecordsRequestUsingIds.Builder<>(PowerRecord.class) 119 .addClientRecordId("abc") 120 .build(); 121 List<PowerRecord> result = TestUtils.readRecords(request); 122 assertThat(result.size()).isEqualTo(0); 123 } 124 125 @Test testReadPowerRecordUsingFilters_default()126 public void testReadPowerRecordUsingFilters_default() throws InterruptedException { 127 List<PowerRecord> oldPowerRecords = 128 TestUtils.readRecords( 129 new ReadRecordsRequestUsingFilters.Builder<>(PowerRecord.class).build()); 130 PowerRecord testRecord = getCompletePowerRecord(); 131 TestUtils.insertRecords(Collections.singletonList(testRecord)); 132 List<PowerRecord> newPowerRecords = 133 TestUtils.readRecords( 134 new ReadRecordsRequestUsingFilters.Builder<>(PowerRecord.class).build()); 135 assertThat(newPowerRecords.size()).isEqualTo(oldPowerRecords.size() + 1); 136 assertThat(newPowerRecords.get(newPowerRecords.size() - 1).equals(testRecord)).isTrue(); 137 } 138 139 @Test testReadPowerRecordUsingFilters_timeFilter()140 public void testReadPowerRecordUsingFilters_timeFilter() throws InterruptedException { 141 TimeInstantRangeFilter filter = 142 new TimeInstantRangeFilter.Builder() 143 .setStartTime(Instant.now()) 144 .setEndTime(Instant.now().plusMillis(3000)) 145 .build(); 146 PowerRecord testRecord = getCompletePowerRecord(); 147 TestUtils.insertRecords(Collections.singletonList(testRecord)); 148 List<PowerRecord> newPowerRecords = 149 TestUtils.readRecords( 150 new ReadRecordsRequestUsingFilters.Builder<>(PowerRecord.class) 151 .setTimeRangeFilter(filter) 152 .build()); 153 assertThat(newPowerRecords.get(newPowerRecords.size() - 1).equals(testRecord)).isTrue(); 154 } 155 156 @Test testReadPowerRecordUsingFilters_dataFilter_correct()157 public void testReadPowerRecordUsingFilters_dataFilter_correct() throws InterruptedException { 158 Context context = ApplicationProvider.getApplicationContext(); 159 List<PowerRecord> oldPowerRecords = 160 TestUtils.readRecords( 161 new ReadRecordsRequestUsingFilters.Builder<>(PowerRecord.class) 162 .addDataOrigins( 163 new DataOrigin.Builder() 164 .setPackageName(context.getPackageName()) 165 .build()) 166 .build()); 167 PowerRecord testRecord = getCompletePowerRecord(); 168 TestUtils.insertRecords(Collections.singletonList(testRecord)); 169 List<PowerRecord> newPowerRecords = 170 TestUtils.readRecords( 171 new ReadRecordsRequestUsingFilters.Builder<>(PowerRecord.class) 172 .addDataOrigins( 173 new DataOrigin.Builder() 174 .setPackageName(context.getPackageName()) 175 .build()) 176 .build()); 177 assertThat(newPowerRecords.size() - oldPowerRecords.size()).isEqualTo(1); 178 assertThat(newPowerRecords.get(newPowerRecords.size() - 1).equals(testRecord)).isTrue(); 179 PowerRecord newRecord = newPowerRecords.get(newPowerRecords.size() - 1); 180 assertThat(newRecord.equals(testRecord)).isTrue(); 181 for (int idx = 0; idx < newRecord.getSamples().size(); idx++) { 182 assertThat(newRecord.getSamples().get(idx).getTime().toEpochMilli()) 183 .isEqualTo(testRecord.getSamples().get(idx).getTime().toEpochMilli()); 184 assertThat(newRecord.getSamples().get(idx).getPower()) 185 .isEqualTo(testRecord.getSamples().get(idx).getPower()); 186 } 187 } 188 189 @Test testReadPowerRecordUsingFilters_dataFilter_incorrect()190 public void testReadPowerRecordUsingFilters_dataFilter_incorrect() throws InterruptedException { 191 TestUtils.insertRecords(Collections.singletonList(getCompletePowerRecord())); 192 List<PowerRecord> newPowerRecords = 193 TestUtils.readRecords( 194 new ReadRecordsRequestUsingFilters.Builder<>(PowerRecord.class) 195 .addDataOrigins( 196 new DataOrigin.Builder().setPackageName("abc").build()) 197 .build()); 198 assertThat(newPowerRecords.size()).isEqualTo(0); 199 } 200 201 @Test testDeletePowerRecord_no_filters()202 public void testDeletePowerRecord_no_filters() throws InterruptedException { 203 String id = TestUtils.insertRecordAndGetId(getCompletePowerRecord()); 204 TestUtils.verifyDeleteRecords(new DeleteUsingFiltersRequest.Builder().build()); 205 TestUtils.assertRecordNotFound(id, PowerRecord.class); 206 } 207 208 @Test testDeletePowerRecord_time_filters()209 public void testDeletePowerRecord_time_filters() throws InterruptedException { 210 TimeInstantRangeFilter timeRangeFilter = 211 new TimeInstantRangeFilter.Builder() 212 .setStartTime(Instant.now()) 213 .setEndTime(Instant.now().plusMillis(1000)) 214 .build(); 215 String id = TestUtils.insertRecordAndGetId(getCompletePowerRecord()); 216 TestUtils.verifyDeleteRecords( 217 new DeleteUsingFiltersRequest.Builder() 218 .addRecordType(PowerRecord.class) 219 .setTimeRangeFilter(timeRangeFilter) 220 .build()); 221 TestUtils.assertRecordNotFound(id, PowerRecord.class); 222 } 223 224 @Test testDeletePowerRecord_recordId_filters()225 public void testDeletePowerRecord_recordId_filters() throws InterruptedException { 226 List<Record> records = List.of(getBasePowerRecord(), getCompletePowerRecord()); 227 TestUtils.insertRecords(records); 228 229 for (Record record : records) { 230 TestUtils.verifyDeleteRecords( 231 new DeleteUsingFiltersRequest.Builder() 232 .addRecordType(record.getClass()) 233 .build()); 234 TestUtils.assertRecordNotFound(record.getMetadata().getId(), record.getClass()); 235 } 236 } 237 238 @Test testDeletePowerRecord_dataOrigin_filters()239 public void testDeletePowerRecord_dataOrigin_filters() throws InterruptedException { 240 Context context = ApplicationProvider.getApplicationContext(); 241 String id = TestUtils.insertRecordAndGetId(getCompletePowerRecord()); 242 TestUtils.verifyDeleteRecords( 243 new DeleteUsingFiltersRequest.Builder() 244 .addDataOrigin( 245 new DataOrigin.Builder() 246 .setPackageName(context.getPackageName()) 247 .build()) 248 .build()); 249 TestUtils.assertRecordNotFound(id, PowerRecord.class); 250 } 251 252 @Test testDeletePowerRecord_dataOrigin_filter_incorrect()253 public void testDeletePowerRecord_dataOrigin_filter_incorrect() throws InterruptedException { 254 String id = TestUtils.insertRecordAndGetId(getCompletePowerRecord()); 255 TestUtils.verifyDeleteRecords( 256 new DeleteUsingFiltersRequest.Builder() 257 .addDataOrigin(new DataOrigin.Builder().setPackageName("abc").build()) 258 .build()); 259 TestUtils.assertRecordFound(id, PowerRecord.class); 260 } 261 262 @Test testDeletePowerRecord_usingIds()263 public void testDeletePowerRecord_usingIds() throws InterruptedException { 264 List<Record> records = List.of(getBasePowerRecord(), getCompletePowerRecord()); 265 List<Record> insertedRecord = TestUtils.insertRecords(records); 266 List<RecordIdFilter> recordIds = new ArrayList<>(records.size()); 267 for (Record record : insertedRecord) { 268 recordIds.add(RecordIdFilter.fromId(record.getClass(), record.getMetadata().getId())); 269 } 270 271 TestUtils.verifyDeleteRecords(recordIds); 272 for (Record record : records) { 273 TestUtils.assertRecordNotFound(record.getMetadata().getId(), record.getClass()); 274 } 275 } 276 277 @Test testDeletePowerRecord_time_range()278 public void testDeletePowerRecord_time_range() throws InterruptedException { 279 TimeInstantRangeFilter timeRangeFilter = 280 new TimeInstantRangeFilter.Builder() 281 .setStartTime(Instant.now()) 282 .setEndTime(Instant.now().plusMillis(1000)) 283 .build(); 284 String id = TestUtils.insertRecordAndGetId(getCompletePowerRecord()); 285 TestUtils.verifyDeleteRecords(PowerRecord.class, timeRangeFilter); 286 TestUtils.assertRecordNotFound(id, PowerRecord.class); 287 } 288 289 @Test testAggregation_power()290 public void testAggregation_power() throws Exception { 291 Context context = ApplicationProvider.getApplicationContext(); 292 List<Record> records = 293 Arrays.asList(getPowerRecord(5.0), getPowerRecord(10.0), getPowerRecord(15.0)); 294 AggregateRecordsResponse<Power> response = 295 TestUtils.getAggregateResponse( 296 new AggregateRecordsRequest.Builder<Power>( 297 new TimeInstantRangeFilter.Builder() 298 .setStartTime(Instant.ofEpochMilli(0)) 299 .setEndTime(Instant.now().plus(1, ChronoUnit.DAYS)) 300 .build()) 301 .addAggregationType(POWER_MAX) 302 .addAggregationType(POWER_MIN) 303 .addAggregationType(POWER_AVG) 304 .addDataOriginsFilter( 305 new DataOrigin.Builder() 306 .setPackageName(context.getPackageName()) 307 .build()) 308 .build(), 309 records); 310 Power maxPower = response.get(POWER_MAX); 311 Power minPower = response.get(POWER_MIN); 312 Power avgPower = response.get(POWER_AVG); 313 assertThat(maxPower).isNotNull(); 314 assertThat(maxPower.getInWatts()).isEqualTo(15.0); 315 assertThat(minPower).isNotNull(); 316 assertThat(minPower.getInWatts()).isEqualTo(5.0); 317 assertThat(avgPower).isNotNull(); 318 assertThat(avgPower.getInWatts()).isEqualTo(10.0); 319 Set<DataOrigin> newDataOrigin = response.getDataOrigins(POWER_AVG); 320 for (DataOrigin itr : newDataOrigin) { 321 assertThat(itr.getPackageName()).isEqualTo("android.healthconnect.cts"); 322 } 323 } 324 325 @Test testZoneOffsets()326 public void testZoneOffsets() { 327 final ZoneOffset defaultZoneOffset = 328 ZoneOffset.systemDefault().getRules().getOffset(Instant.now()); 329 final ZoneOffset startZoneOffset = ZoneOffset.UTC; 330 final ZoneOffset endZoneOffset = ZoneOffset.MAX; 331 PowerRecord.Builder builder = 332 new PowerRecord.Builder( 333 new Metadata.Builder().build(), 334 Instant.now(), 335 Instant.now().plusMillis(1000), 336 Collections.emptyList()); 337 338 assertThat(builder.setStartZoneOffset(startZoneOffset).build().getStartZoneOffset()) 339 .isEqualTo(startZoneOffset); 340 assertThat(builder.setEndZoneOffset(endZoneOffset).build().getEndZoneOffset()) 341 .isEqualTo(endZoneOffset); 342 assertThat(builder.clearStartZoneOffset().build().getStartZoneOffset()) 343 .isEqualTo(defaultZoneOffset); 344 assertThat(builder.clearEndZoneOffset().build().getEndZoneOffset()) 345 .isEqualTo(defaultZoneOffset); 346 } 347 348 @Test testUpdateRecords_validInput_dataBaseUpdatedSuccessfully()349 public void testUpdateRecords_validInput_dataBaseUpdatedSuccessfully() 350 throws InterruptedException { 351 352 List<Record> insertedRecords = 353 TestUtils.insertRecords( 354 Arrays.asList(getCompletePowerRecord(), getCompletePowerRecord())); 355 356 // read inserted records and verify that the data is same as inserted. 357 readPowerRecordUsingIds(insertedRecords); 358 359 // Generate a new set of records that will be used to perform the update operation. 360 List<Record> updateRecords = 361 Arrays.asList(getCompletePowerRecord(), getCompletePowerRecord()); 362 363 // Modify the uid of the updateRecords to the uuid that was present in the insert records. 364 for (int itr = 0; itr < updateRecords.size(); itr++) { 365 updateRecords.set( 366 itr, 367 getPowerRecord_update( 368 updateRecords.get(itr), 369 insertedRecords.get(itr).getMetadata().getId(), 370 insertedRecords.get(itr).getMetadata().getClientRecordId())); 371 } 372 373 TestUtils.updateRecords(updateRecords); 374 375 // assert the inserted data has been modified by reading the data. 376 readPowerRecordUsingIds(updateRecords); 377 } 378 379 @Test testUpdateRecords_invalidInputRecords_noChangeInDataBase()380 public void testUpdateRecords_invalidInputRecords_noChangeInDataBase() 381 throws InterruptedException { 382 List<Record> insertedRecords = 383 TestUtils.insertRecords( 384 Arrays.asList(getCompletePowerRecord(), getCompletePowerRecord())); 385 386 // read inserted records and verify that the data is same as inserted. 387 readPowerRecordUsingIds(insertedRecords); 388 389 // Generate a second set of records that will be used to perform the update operation. 390 List<Record> updateRecords = 391 Arrays.asList(getCompletePowerRecord(), getCompletePowerRecord()); 392 393 // Modify the Uid of the updateRecords to the UUID that was present in the insert records, 394 // leaving out alternate records so that they have a new UUID which is not present in the 395 // dataBase. 396 for (int itr = 0; itr < updateRecords.size(); itr++) { 397 updateRecords.set( 398 itr, 399 getPowerRecord_update( 400 updateRecords.get(itr), 401 itr % 2 == 0 402 ? insertedRecords.get(itr).getMetadata().getId() 403 : UUID.randomUUID().toString(), 404 itr % 2 == 0 405 ? insertedRecords.get(itr).getMetadata().getId() 406 : UUID.randomUUID().toString())); 407 } 408 409 try { 410 TestUtils.updateRecords(updateRecords); 411 Assert.fail("Expected to fail due to invalid records ids."); 412 } catch (HealthConnectException exception) { 413 assertThat(exception.getErrorCode()) 414 .isEqualTo(HealthConnectException.ERROR_INVALID_ARGUMENT); 415 } 416 417 // assert the inserted data has not been modified by reading the data. 418 readPowerRecordUsingIds(insertedRecords); 419 } 420 421 @Test testUpdateRecords_recordWithInvalidPackageName_noChangeInDataBase()422 public void testUpdateRecords_recordWithInvalidPackageName_noChangeInDataBase() 423 throws InterruptedException { 424 List<Record> insertedRecords = 425 TestUtils.insertRecords( 426 Arrays.asList(getCompletePowerRecord(), getCompletePowerRecord())); 427 428 // read inserted records and verify that the data is same as inserted. 429 readPowerRecordUsingIds(insertedRecords); 430 431 // Generate a second set of records that will be used to perform the update operation. 432 List<Record> updateRecords = 433 Arrays.asList(getCompletePowerRecord(), getCompletePowerRecord()); 434 435 // Modify the Uuid of the updateRecords to the uuid that was present in the insert records. 436 for (int itr = 0; itr < updateRecords.size(); itr++) { 437 updateRecords.set( 438 itr, 439 getPowerRecord_update( 440 updateRecords.get(itr), 441 insertedRecords.get(itr).getMetadata().getId(), 442 insertedRecords.get(itr).getMetadata().getClientRecordId())); 443 // adding an entry with invalid packageName. 444 updateRecords.set(itr, getCompletePowerRecord()); 445 } 446 447 try { 448 TestUtils.updateRecords(updateRecords); 449 Assert.fail("Expected to fail due to invalid package."); 450 } catch (Exception exception) { 451 // verify that the testcase failed due to invalid argument exception. 452 assertThat(exception).isNotNull(); 453 } 454 455 // assert the inserted data has not been modified by reading the data. 456 readPowerRecordUsingIds(insertedRecords); 457 } 458 459 @Test testInsertAndDeleteRecord_changelogs()460 public void testInsertAndDeleteRecord_changelogs() throws InterruptedException { 461 Context context = ApplicationProvider.getApplicationContext(); 462 ChangeLogTokenResponse tokenResponse = 463 TestUtils.getChangeLogToken( 464 new ChangeLogTokenRequest.Builder() 465 .addDataOriginFilter( 466 new DataOrigin.Builder() 467 .setPackageName(context.getPackageName()) 468 .build()) 469 .addRecordType(PowerRecord.class) 470 .build()); 471 ChangeLogsRequest changeLogsRequest = 472 new ChangeLogsRequest.Builder(tokenResponse.getToken()).build(); 473 ChangeLogsResponse response = TestUtils.getChangeLogs(changeLogsRequest); 474 assertThat(response.getUpsertedRecords().size()).isEqualTo(0); 475 assertThat(response.getDeletedLogs().size()).isEqualTo(0); 476 477 List<Record> testRecord = Collections.singletonList(getCompletePowerRecord()); 478 TestUtils.insertRecords(testRecord); 479 response = TestUtils.getChangeLogs(changeLogsRequest); 480 assertThat(response.getUpsertedRecords().size()).isEqualTo(1); 481 assertThat( 482 response.getUpsertedRecords().stream() 483 .map(Record::getMetadata) 484 .map(Metadata::getId) 485 .toList()) 486 .containsExactlyElementsIn( 487 testRecord.stream().map(Record::getMetadata).map(Metadata::getId).toList()); 488 assertThat(response.getDeletedLogs().size()).isEqualTo(0); 489 490 TestUtils.verifyDeleteRecords( 491 new DeleteUsingFiltersRequest.Builder().addRecordType(PowerRecord.class).build()); 492 response = TestUtils.getChangeLogs(changeLogsRequest); 493 assertThat(response.getDeletedLogs()).isEmpty(); 494 } 495 testReadPowerRecordIds()496 private void testReadPowerRecordIds() throws InterruptedException { 497 List<Record> recordList = Arrays.asList(getCompletePowerRecord(), getCompletePowerRecord()); 498 readPowerRecordUsingIds(recordList); 499 } 500 readPowerRecordUsingClientId(List<Record> insertedRecord)501 private void readPowerRecordUsingClientId(List<Record> insertedRecord) 502 throws InterruptedException { 503 ReadRecordsRequestUsingIds.Builder<PowerRecord> request = 504 new ReadRecordsRequestUsingIds.Builder<>(PowerRecord.class); 505 for (Record record : insertedRecord) { 506 request.addClientRecordId(record.getMetadata().getClientRecordId()); 507 } 508 List<PowerRecord> result = TestUtils.readRecords(request.build()); 509 assertThat(result.size()).isEqualTo(insertedRecord.size()); 510 assertThat(result).containsExactlyElementsIn(insertedRecord); 511 } 512 readPowerRecordUsingIds(List<Record> recordList)513 private void readPowerRecordUsingIds(List<Record> recordList) throws InterruptedException { 514 List<Record> insertedRecords = TestUtils.insertRecords(recordList); 515 ReadRecordsRequestUsingIds.Builder<PowerRecord> request = 516 new ReadRecordsRequestUsingIds.Builder<>(PowerRecord.class); 517 for (Record record : insertedRecords) { 518 request.addId(record.getMetadata().getId()); 519 } 520 ReadRecordsRequestUsingIds requestUsingIds = request.build(); 521 assertThat(requestUsingIds.getRecordType()).isEqualTo(PowerRecord.class); 522 assertThat(requestUsingIds.getRecordIdFilters()).isNotNull(); 523 List<PowerRecord> result = TestUtils.readRecords(requestUsingIds); 524 assertThat(result).hasSize(insertedRecords.size()); 525 assertThat(result.containsAll(insertedRecords)).isTrue(); 526 } 527 528 @Test(expected = IllegalArgumentException.class) testCreatePowerRecord_invalidValue()529 public void testCreatePowerRecord_invalidValue() { 530 new PowerRecord.PowerRecordSample(Power.fromWatts(100001.0), Instant.now().plusMillis(100)); 531 } 532 getPowerRecord_update(Record record, String id, String clientRecordId)533 PowerRecord getPowerRecord_update(Record record, String id, String clientRecordId) { 534 Metadata metadata = record.getMetadata(); 535 Metadata metadataWithId = 536 new Metadata.Builder() 537 .setId(id) 538 .setClientRecordId(clientRecordId) 539 .setClientRecordVersion(metadata.getClientRecordVersion()) 540 .setDataOrigin(metadata.getDataOrigin()) 541 .setDevice(metadata.getDevice()) 542 .setLastModifiedTime(metadata.getLastModifiedTime()) 543 .build(); 544 545 PowerRecord.PowerRecordSample powerRecordSample = 546 new PowerRecord.PowerRecordSample( 547 Power.fromWatts(8.0), Instant.now().plusMillis(100)); 548 549 return new PowerRecord.Builder( 550 metadataWithId, 551 Instant.now(), 552 Instant.now().plusMillis(2000), 553 List.of(powerRecordSample, powerRecordSample)) 554 .setStartZoneOffset(ZoneOffset.systemDefault().getRules().getOffset(Instant.now())) 555 .setEndZoneOffset(ZoneOffset.systemDefault().getRules().getOffset(Instant.now())) 556 .build(); 557 } 558 getBasePowerRecord()559 private static PowerRecord getBasePowerRecord() { 560 PowerRecord.PowerRecordSample powerRecord = 561 new PowerRecord.PowerRecordSample( 562 Power.fromWatts(10.0), Instant.now().plusMillis(100)); 563 ArrayList<PowerRecord.PowerRecordSample> powerRecords = new ArrayList<>(); 564 powerRecords.add(powerRecord); 565 powerRecords.add(powerRecord); 566 567 return new PowerRecord.Builder( 568 new Metadata.Builder().build(), 569 Instant.now(), 570 Instant.now().plusMillis(1000), 571 powerRecords) 572 .build(); 573 } 574 getPowerRecord(double power)575 static PowerRecord getPowerRecord(double power) { 576 PowerRecord.PowerRecordSample powerRecord = 577 new PowerRecord.PowerRecordSample( 578 Power.fromWatts(power), Instant.now().plusMillis(100)); 579 ArrayList<PowerRecord.PowerRecordSample> powerRecords = new ArrayList<>(); 580 powerRecords.add(powerRecord); 581 powerRecords.add(powerRecord); 582 583 return new PowerRecord.Builder( 584 new Metadata.Builder().setClientRecordId("PR" + Math.random()).build(), 585 Instant.now(), 586 Instant.now().plusMillis(1000), 587 powerRecords) 588 .build(); 589 } 590 getCompletePowerRecord()591 private static PowerRecord getCompletePowerRecord() { 592 593 Device device = 594 new Device.Builder() 595 .setManufacturer("google") 596 .setModel("Pixel4a") 597 .setType(2) 598 .build(); 599 DataOrigin dataOrigin = 600 new DataOrigin.Builder().setPackageName("android.healthconnect.cts").build(); 601 Metadata.Builder testMetadataBuilder = new Metadata.Builder(); 602 testMetadataBuilder.setDevice(device).setDataOrigin(dataOrigin); 603 testMetadataBuilder.setClientRecordId("PR" + Math.random()); 604 testMetadataBuilder.setRecordingMethod(Metadata.RECORDING_METHOD_ACTIVELY_RECORDED); 605 606 PowerRecord.PowerRecordSample powerRecord = 607 new PowerRecord.PowerRecordSample( 608 Power.fromWatts(10.0), Instant.now().plusMillis(100)); 609 610 ArrayList<PowerRecord.PowerRecordSample> powerRecords = new ArrayList<>(); 611 powerRecords.add(powerRecord); 612 powerRecords.add(powerRecord); 613 614 return new PowerRecord.Builder( 615 testMetadataBuilder.build(), 616 Instant.now(), 617 Instant.now().plusMillis(1000), 618 powerRecords) 619 .build(); 620 } 621 } 622