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