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