1 /* 2 * Copyright (C) 2024 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.utils; 18 19 import static android.health.connect.datatypes.Metadata.RECORDING_METHOD_ACTIVELY_RECORDED; 20 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_BASAL_METABOLIC_RATE; 21 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_HEART_RATE; 22 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_STEPS; 23 24 import static com.google.common.truth.Truth.assertThat; 25 26 import android.content.Context; 27 import android.health.connect.changelog.ChangeLogTokenRequest; 28 import android.health.connect.datatypes.BasalMetabolicRateRecord; 29 import android.health.connect.datatypes.DataOrigin; 30 import android.health.connect.datatypes.Device; 31 import android.health.connect.datatypes.DistanceRecord; 32 import android.health.connect.datatypes.ExerciseCompletionGoal; 33 import android.health.connect.datatypes.ExerciseLap; 34 import android.health.connect.datatypes.ExerciseRoute; 35 import android.health.connect.datatypes.ExerciseSegment; 36 import android.health.connect.datatypes.ExerciseSegmentType; 37 import android.health.connect.datatypes.ExerciseSessionRecord; 38 import android.health.connect.datatypes.ExerciseSessionType; 39 import android.health.connect.datatypes.HeartRateRecord; 40 import android.health.connect.datatypes.Metadata; 41 import android.health.connect.datatypes.PlannedExerciseBlock; 42 import android.health.connect.datatypes.PlannedExerciseSessionRecord; 43 import android.health.connect.datatypes.PlannedExerciseStep; 44 import android.health.connect.datatypes.Record; 45 import android.health.connect.datatypes.SleepSessionRecord; 46 import android.health.connect.datatypes.StepsRecord; 47 import android.health.connect.datatypes.TotalCaloriesBurnedRecord; 48 import android.health.connect.datatypes.WeightRecord; 49 import android.health.connect.datatypes.units.Energy; 50 import android.health.connect.datatypes.units.Length; 51 import android.health.connect.datatypes.units.Mass; 52 import android.health.connect.datatypes.units.Power; 53 import android.healthconnect.cts.utils.TestUtils.RecordAndIdentifier; 54 55 import androidx.annotation.Nullable; 56 import androidx.test.core.app.ApplicationProvider; 57 58 import java.time.Instant; 59 import java.time.ZoneOffset; 60 import java.time.temporal.ChronoUnit; 61 import java.util.ArrayList; 62 import java.util.Arrays; 63 import java.util.List; 64 import java.util.UUID; 65 66 public final class DataFactory { 67 // truncate to MILLIS because HC does, so reduce flakiness in some tests. 68 public static final Instant NOW = Instant.now().truncatedTo(ChronoUnit.MILLIS); 69 public static final Instant SESSION_START_TIME = NOW.minus(10, ChronoUnit.DAYS); 70 public static final Instant SESSION_END_TIME = SESSION_START_TIME.plus(1, ChronoUnit.HOURS); 71 public static final long DEFAULT_LONG = -1; 72 public static final int DEFAULT_PAGE_SIZE = 1000; 73 public static final int MINIMUM_PAGE_SIZE = 1; 74 public static final int MAXIMUM_PAGE_SIZE = 5000; 75 buildDevice()76 public static Device buildDevice() { 77 return new Device.Builder() 78 .setManufacturer("google") 79 .setModel("Pixel4a") 80 .setType(2) 81 .build(); 82 } 83 generateMetadata()84 public static Metadata generateMetadata() { 85 return generateMetadata(UUID.randomUUID().toString()); 86 } 87 88 /** Generates a {@link Metadata} with specific {@code id}. */ generateMetadata(String id)89 public static Metadata generateMetadata(String id) { 90 return generateMetadata(id, "clientRecordId" + Math.random()); 91 } 92 93 /** Generates a {@link Metadata} with specific {@code id} and {@code clientId}. */ generateMetadata(String id, String clientId)94 public static Metadata generateMetadata(String id, String clientId) { 95 Context context = ApplicationProvider.getApplicationContext(); 96 return new Metadata.Builder() 97 .setDevice(buildDevice()) 98 .setId(id) 99 .setClientRecordId(clientId) 100 .setDataOrigin( 101 new DataOrigin.Builder().setPackageName(context.getPackageName()).build()) 102 .setRecordingMethod(Metadata.RECORDING_METHOD_UNKNOWN) 103 .build(); 104 } 105 106 /** Generates a {@link Metadata} with a specific {@code clientId}. */ generateMetadataWithClientId(String clientId)107 public static Metadata generateMetadataWithClientId(String clientId) { 108 return generateMetadata(UUID.randomUUID().toString(), clientId); 109 } 110 getEmptyMetadata()111 public static Metadata getEmptyMetadata() { 112 return new Metadata.Builder().build(); 113 } 114 115 /** Creates a {@link Metadata} with the given record id. */ getMetadataForId(String id)116 public static Metadata getMetadataForId(String id) { 117 return new Metadata.Builder().setId(id).build(); 118 } 119 120 /** Creates a {@link Metadata} with the given record id and data origin. */ getMetadataForId(String id, DataOrigin dataOrigin)121 public static Metadata getMetadataForId(String id, DataOrigin dataOrigin) { 122 return new Metadata.Builder().setId(id).setDataOrigin(dataOrigin).build(); 123 } 124 125 /** Creates a {@link Metadata} with the given client record id. */ getMetadataForClientId(String clientId)126 public static Metadata getMetadataForClientId(String clientId) { 127 return new Metadata.Builder().setClientRecordId(clientId).build(); 128 } 129 130 /** Creates a {@link Metadata} with the given client record id. */ getMetadataForClientId(String clientId, DataOrigin dataOrigin)131 public static Metadata getMetadataForClientId(String clientId, DataOrigin dataOrigin) { 132 return new Metadata.Builder().setClientRecordId(clientId).setDataOrigin(dataOrigin).build(); 133 } 134 135 /** Creates a {@link Metadata} with the given client record id. */ getMetadataForClientIdAndVersion(String clientId, long clientVersion)136 public static Metadata getMetadataForClientIdAndVersion(String clientId, long clientVersion) { 137 return new Metadata.Builder() 138 .setClientRecordId(clientId) 139 .setClientRecordVersion(clientVersion) 140 .build(); 141 } 142 143 /** Creates a {@link Metadata} with the given data origin. */ getMetadata(DataOrigin dataOrigin)144 public static Metadata getMetadata(DataOrigin dataOrigin) { 145 return new Metadata.Builder().setDataOrigin(dataOrigin).build(); 146 } 147 148 /** Creates a {@link DataOrigin} with the given package name. */ getDataOrigin(String packageName)149 public static DataOrigin getDataOrigin(String packageName) { 150 return new DataOrigin.Builder().setPackageName(packageName).build(); 151 } 152 153 /** Creates a list of {@link DataOrigin} from a list of package names. */ getDataOrigins(String... packageNames)154 public static List<DataOrigin> getDataOrigins(String... packageNames) { 155 return Arrays.stream(packageNames).map(DataFactory::getDataOrigin).toList(); 156 } 157 buildSleepSession()158 public static SleepSessionRecord buildSleepSession() { 159 return buildSleepSession(generateMetadata()); 160 } 161 162 /** Builds a {@link SleepSessionRecord} with a specific {@code clientId}. */ buildSleepSessionWithClientId(String clientId)163 public static SleepSessionRecord buildSleepSessionWithClientId(String clientId) { 164 return buildSleepSession(generateMetadataWithClientId(clientId)); 165 } 166 167 /** Builds a {@link SleepSessionRecord} with empty {@link Metadata}. */ buildSleepSessionWithEmptyMetadata()168 public static SleepSessionRecord buildSleepSessionWithEmptyMetadata() { 169 return buildSleepSession(getEmptyMetadata()); 170 } 171 172 /** Builds a {@link SleepSessionRecord} with a specific {@link Metadata}. */ buildSleepSession(Metadata metadata)173 public static SleepSessionRecord buildSleepSession(Metadata metadata) { 174 return new SleepSessionRecord.Builder(metadata, SESSION_START_TIME, SESSION_END_TIME) 175 .setNotes("warm") 176 .setTitle("Afternoon nap") 177 .setStages( 178 List.of( 179 new SleepSessionRecord.Stage( 180 SESSION_START_TIME, 181 SESSION_START_TIME.plusSeconds(300), 182 SleepSessionRecord.StageType.STAGE_TYPE_SLEEPING_LIGHT), 183 new SleepSessionRecord.Stage( 184 SESSION_START_TIME.plusSeconds(300), 185 SESSION_START_TIME.plusSeconds(600), 186 SleepSessionRecord.StageType.STAGE_TYPE_SLEEPING_REM), 187 new SleepSessionRecord.Stage( 188 SESSION_START_TIME.plusSeconds(900), 189 SESSION_START_TIME.plusSeconds(1200), 190 SleepSessionRecord.StageType.STAGE_TYPE_SLEEPING_DEEP))) 191 .build(); 192 } 193 194 /** Builds a {@link ExerciseSessionRecord} with {@link #generateMetadata()}. */ buildExerciseSession()195 public static ExerciseSessionRecord buildExerciseSession() { 196 return buildExerciseSession(generateMetadata()); 197 } 198 199 /** Builds a {@link ExerciseSessionRecord} with an empty {@link Metadata}. */ buildExerciseSessionWithEmptyMetadata()200 public static ExerciseSessionRecord buildExerciseSessionWithEmptyMetadata() { 201 return buildExerciseSession(getEmptyMetadata()); 202 } 203 204 /** Builds a {@link ExerciseSessionRecord} with a specific {@code clientId}. */ buildExerciseSessionWithClientId(String clientId)205 public static ExerciseSessionRecord buildExerciseSessionWithClientId(String clientId) { 206 return buildExerciseSession(generateMetadataWithClientId(clientId)); 207 } 208 209 /** Builds a {@link ExerciseSessionRecord} with a specific {@link Metadata}. */ buildExerciseSession(Metadata metadata)210 public static ExerciseSessionRecord buildExerciseSession(Metadata metadata) { 211 return new ExerciseSessionRecord.Builder( 212 metadata, 213 SESSION_START_TIME, 214 SESSION_END_TIME, 215 ExerciseSessionType.EXERCISE_SESSION_TYPE_OTHER_WORKOUT) 216 .setRoute(buildExerciseRoute()) 217 .setLaps( 218 List.of( 219 new ExerciseLap.Builder( 220 SESSION_START_TIME, 221 SESSION_START_TIME.plusSeconds(20)) 222 .setLength(Length.fromMeters(10)) 223 .build(), 224 new ExerciseLap.Builder( 225 SESSION_END_TIME.minusSeconds(20), SESSION_END_TIME) 226 .build())) 227 .setSegments( 228 List.of( 229 new ExerciseSegment.Builder( 230 SESSION_START_TIME.plusSeconds(1), 231 SESSION_START_TIME.plusSeconds(10), 232 ExerciseSegmentType 233 .EXERCISE_SEGMENT_TYPE_BENCH_PRESS) 234 .build(), 235 new ExerciseSegment.Builder( 236 SESSION_START_TIME.plusSeconds(21), 237 SESSION_START_TIME.plusSeconds(124), 238 ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_BURPEE) 239 .setRepetitionsCount(15) 240 .build())) 241 .setEndZoneOffset(ZoneOffset.MAX) 242 .setStartZoneOffset(ZoneOffset.MIN) 243 .setNotes("rain") 244 .setTitle("Morning training") 245 .build(); 246 } 247 buildExerciseRoute()248 public static ExerciseRoute buildExerciseRoute() { 249 return new ExerciseRoute( 250 List.of( 251 buildLocationTimePoint(SESSION_START_TIME), 252 buildLocationTimePoint(SESSION_START_TIME), 253 buildLocationTimePoint(SESSION_START_TIME))); 254 } 255 buildLocationTimePoint(Instant startTime)256 public static ExerciseRoute.Location buildLocationTimePoint(Instant startTime) { 257 return new ExerciseRoute.Location.Builder( 258 Instant.ofEpochMilli( 259 (long) (startTime.toEpochMilli() + 10 + Math.random() * 50)), 260 Math.random() * 50, 261 Math.random() * 50) 262 .build(); 263 } 264 265 /** Returns a training plan builder, prepopulated with test data. */ plannedExerciseSession(Metadata metadata)266 public static PlannedExerciseSessionRecord.Builder plannedExerciseSession(Metadata metadata) { 267 PlannedExerciseSessionRecord.Builder sessionBuilder = 268 new PlannedExerciseSessionRecord.Builder( 269 metadata, 270 ExerciseSessionType.EXERCISE_SESSION_TYPE_BIKING, 271 SESSION_START_TIME, 272 SESSION_END_TIME); 273 sessionBuilder.setNotes("Some notes"); 274 sessionBuilder.setTitle("Some training plan"); 275 sessionBuilder.setStartZoneOffset(ZoneOffset.UTC); 276 sessionBuilder.setEndZoneOffset(ZoneOffset.UTC); 277 var stepBuilder = 278 new PlannedExerciseStep.Builder( 279 ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_BIKING, 280 PlannedExerciseStep.EXERCISE_CATEGORY_ACTIVE, 281 new ExerciseCompletionGoal.DistanceGoal(Length.fromMeters(100))); 282 var blockBuilder = new PlannedExerciseBlock.Builder(3).setDescription("Main set"); 283 blockBuilder.setSteps(List.of(stepBuilder.build())); 284 sessionBuilder.setBlocks(List.of(blockBuilder.build())); 285 286 return sessionBuilder; 287 } 288 289 /** Gets a {@link HeartRateRecord} with an empty {@link Metadata}. */ getHeartRateRecordWithEmptyMetadata()290 public static HeartRateRecord getHeartRateRecordWithEmptyMetadata() { 291 return getHeartRateRecord(72, getEmptyMetadata()); 292 } 293 294 /** Gets a {@link HeartRateRecord} with a specific heart rate and {@link Metadata}. */ getHeartRateRecord(int heartRate, Metadata metadata)295 public static HeartRateRecord getHeartRateRecord(int heartRate, Metadata metadata) { 296 Instant instant = NOW; 297 HeartRateRecord.HeartRateSample heartRateSample = 298 new HeartRateRecord.HeartRateSample(heartRate, instant.plusMillis(10)); 299 return new HeartRateRecord.Builder( 300 metadata, instant, instant.plusMillis(1000), List.of(heartRateSample)) 301 .build(); 302 } 303 getHeartRateRecord()304 public static HeartRateRecord getHeartRateRecord() { 305 return getHeartRateRecord(72); 306 } 307 getHeartRateRecord(int heartRate, String clientId)308 public static HeartRateRecord getHeartRateRecord(int heartRate, String clientId) { 309 return getHeartRateRecord(heartRate, NOW.plusMillis(100), clientId); 310 } 311 getHeartRateRecord(int heartRate)312 public static HeartRateRecord getHeartRateRecord(int heartRate) { 313 return getHeartRateRecord(heartRate, NOW.plusMillis(100)); 314 } 315 getHeartRateRecord(int heartRate, Instant instant)316 public static HeartRateRecord getHeartRateRecord(int heartRate, Instant instant) { 317 return getHeartRateRecord(heartRate, instant, "HR" + Math.random()); 318 } 319 getHeartRateRecord( List<HeartRateRecord.HeartRateSample> samples, Instant start, Instant end)320 public static HeartRateRecord getHeartRateRecord( 321 List<HeartRateRecord.HeartRateSample> samples, Instant start, Instant end) { 322 return new HeartRateRecord.Builder(getEmptyMetadata(), start, end, samples).build(); 323 } 324 getHeartRateRecord( int heartRate, Instant instant, String clientId)325 public static HeartRateRecord getHeartRateRecord( 326 int heartRate, Instant instant, String clientId) { 327 String packageName = ApplicationProvider.getApplicationContext().getPackageName(); 328 HeartRateRecord.HeartRateSample heartRateSample = 329 new HeartRateRecord.HeartRateSample(heartRate, instant); 330 ArrayList<HeartRateRecord.HeartRateSample> heartRateSamples = new ArrayList<>(); 331 heartRateSamples.add(heartRateSample); 332 heartRateSamples.add(heartRateSample); 333 Device device = buildDevice(); 334 DataOrigin dataOrigin = new DataOrigin.Builder().setPackageName(packageName).build(); 335 336 return new HeartRateRecord.Builder( 337 new Metadata.Builder() 338 .setDevice(device) 339 .setDataOrigin(dataOrigin) 340 .setClientRecordId(clientId) 341 .build(), 342 instant.minusMillis(100), 343 instant.plusMillis(100), 344 heartRateSamples) 345 .build(); 346 } 347 348 /** Creates and returns a {@link WeightRecord} with the specified arguments. */ getWeightRecord(double grams, Instant time)349 public static WeightRecord getWeightRecord(double grams, Instant time) { 350 return new WeightRecord.Builder(new Metadata.Builder().build(), time, Mass.fromGrams(grams)) 351 .build(); 352 } 353 getWeightRecord(double weight, Instant time, ZoneOffset offset)354 public static WeightRecord getWeightRecord(double weight, Instant time, ZoneOffset offset) { 355 return new WeightRecord.Builder(getEmptyMetadata(), time, Mass.fromGrams(weight)) 356 .setZoneOffset(offset) 357 .build(); 358 } 359 getStepsRecordWithEmptyMetaData()360 public static StepsRecord getStepsRecordWithEmptyMetaData() { 361 return getStepsRecord(10, getEmptyMetadata()); 362 } 363 getStepsRecord()364 public static StepsRecord getStepsRecord() { 365 return getStepsRecord(10); 366 } 367 368 /** Creates and returns a {@link StepsRecord} with the specified arguments. */ getStepsRecord(long steps)369 public static StepsRecord getStepsRecord(long steps) { 370 return getStepsRecord(steps, generateMetadata()); 371 } 372 373 /** Creates and returns a {@link StepsRecord} with the specified arguments. */ getStepsRecord(long steps, String clientId)374 public static StepsRecord getStepsRecord(long steps, String clientId) { 375 return getStepsRecord(steps, getMetadataForClientId(clientId)); 376 } 377 378 /** Creates and returns a {@link StepsRecord} with the specified metadata. */ getStepsRecord(long steps, Metadata metadata)379 public static StepsRecord getStepsRecord(long steps, Metadata metadata) { 380 return new StepsRecord.Builder(metadata, NOW, NOW.plusMillis(1000), steps).build(); 381 } 382 383 /** Creates and returns a {@link StepsRecord} with the specified arguments. */ getStepsRecord(long steps, Instant start, Instant end)384 public static StepsRecord getStepsRecord(long steps, Instant start, Instant end) { 385 return new StepsRecord.Builder(getEmptyMetadata(), start, end, steps).build(); 386 } 387 388 /** Creates and returns a {@link StepsRecord} with the specified arguments. */ getStepsRecord( long steps, Instant start, Instant end, String clientId)389 public static StepsRecord getStepsRecord( 390 long steps, Instant start, Instant end, String clientId) { 391 return new StepsRecord.Builder(getMetadataForClientId(clientId), start, end, steps).build(); 392 } 393 getStepsRecord(String id)394 public static StepsRecord getStepsRecord(String id) { 395 return new StepsRecord.Builder(generateMetadata(id), NOW, NOW.plusMillis(1000), 10).build(); 396 } 397 398 /** Creates and returns a {@link StepsRecord} with default arguments. */ getCompleteStepsRecord()399 public static StepsRecord getCompleteStepsRecord() { 400 return getCompleteStepsRecord( 401 NOW, NOW.plusMillis(1000), /* clientRecordId= */ "SR" + Math.random()); 402 } 403 404 /** Creates and returns a {@link StepsRecord} with the specified arguments. */ getCompleteStepsRecord( Instant startTime, Instant endTime, String clientRecordId)405 public static StepsRecord getCompleteStepsRecord( 406 Instant startTime, Instant endTime, String clientRecordId) { 407 return getCompleteStepsRecord(startTime, endTime, clientRecordId, /* count= */ 10); 408 } 409 410 /** Creates and returns a {@link StepsRecord} with the specified arguments. */ getCompleteStepsRecord( String id, Instant startTime, Instant endTime, long count)411 public static StepsRecord getCompleteStepsRecord( 412 String id, Instant startTime, Instant endTime, long count) { 413 return getCompleteStepsRecord( 414 id, 415 startTime, 416 endTime, 417 /* clientRecordId= */ null, 418 /* clientRecordVersion= */ 0L, 419 count); 420 } 421 422 /** Creates and returns a {@link StepsRecord} with the specified arguments. */ getCompleteStepsRecord( Instant startTime, Instant endTime, long count)423 public static StepsRecord getCompleteStepsRecord( 424 Instant startTime, Instant endTime, long count) { 425 return getCompleteStepsRecord( 426 startTime, 427 endTime, 428 /* clientRecordId= */ null, 429 /* clientRecordVersion= */ 0L, 430 count); 431 } 432 433 /** Creates and returns a {@link StepsRecord} with the specified arguments. */ getCompleteStepsRecord( Instant startTime, Instant endTime, String clientRecordId, long count)434 public static StepsRecord getCompleteStepsRecord( 435 Instant startTime, Instant endTime, String clientRecordId, long count) { 436 return getCompleteStepsRecord( 437 startTime, endTime, clientRecordId, /* clientRecordVersion= */ 0L, count); 438 } 439 440 /** Creates and returns a {@link StepsRecord} with the specified arguments. */ getCompleteStepsRecord( Instant startTime, Instant endTime, String clientRecordId, long clientRecordVersion, long count)441 public static StepsRecord getCompleteStepsRecord( 442 Instant startTime, 443 Instant endTime, 444 String clientRecordId, 445 long clientRecordVersion, 446 long count) { 447 return getCompleteStepsRecord( 448 /* id= */ null, startTime, endTime, clientRecordId, clientRecordVersion, count); 449 } 450 451 /** Creates and returns a {@link StepsRecord} with the specified arguments. */ getCompleteStepsRecord( String id, Instant startTime, Instant endTime, String clientRecordId, long clientRecordVersion, long count)452 public static StepsRecord getCompleteStepsRecord( 453 String id, 454 Instant startTime, 455 Instant endTime, 456 String clientRecordId, 457 long clientRecordVersion, 458 long count) { 459 Device device = 460 new Device.Builder().setManufacturer("google").setModel("Pixel").setType(1).build(); 461 DataOrigin dataOrigin = 462 new DataOrigin.Builder().setPackageName("android.healthconnect.cts").build(); 463 464 Metadata.Builder testMetadataBuilder = new Metadata.Builder(); 465 if (id != null) { 466 testMetadataBuilder.setId(id); 467 } 468 testMetadataBuilder.setDevice(device).setDataOrigin(dataOrigin); 469 testMetadataBuilder.setClientRecordId(clientRecordId); 470 testMetadataBuilder.setClientRecordVersion(clientRecordVersion); 471 testMetadataBuilder.setRecordingMethod(RECORDING_METHOD_ACTIVELY_RECORDED); 472 Metadata testMetaData = testMetadataBuilder.build(); 473 assertThat(testMetaData.getRecordingMethod()).isEqualTo(RECORDING_METHOD_ACTIVELY_RECORDED); 474 return new StepsRecord.Builder(testMetaData, startTime, endTime, count).build(); 475 } 476 getUpdatedStepsRecord( Record record, String id, String clientRecordId)477 public static StepsRecord getUpdatedStepsRecord( 478 Record record, String id, String clientRecordId) { 479 Metadata metadata = record.getMetadata(); 480 Metadata metadataWithId = 481 new Metadata.Builder() 482 .setId(id) 483 .setClientRecordId(clientRecordId) 484 .setClientRecordVersion(metadata.getClientRecordVersion()) 485 .setDataOrigin(metadata.getDataOrigin()) 486 .setDevice(metadata.getDevice()) 487 .setLastModifiedTime(metadata.getLastModifiedTime()) 488 .build(); 489 return new StepsRecord.Builder(metadataWithId, NOW, NOW.plusMillis(2000), 20) 490 .setStartZoneOffset(ZoneOffset.systemDefault().getRules().getOffset(NOW)) 491 .setEndZoneOffset(ZoneOffset.systemDefault().getRules().getOffset(NOW)) 492 .build(); 493 } 494 495 /** Creates a {@link DistanceRecord}. */ getDistanceRecord()496 public static DistanceRecord getDistanceRecord() { 497 return getDistanceRecord(10.0, NOW, NOW.plusMillis(1000)); 498 } 499 500 /** Creates a {@link DistanceRecord} with a specified {@code clientId}. */ getDistanceRecordWithClientId(String clientId)501 public static DistanceRecord getDistanceRecordWithClientId(String clientId) { 502 return getDistanceRecord( 503 10, 504 NOW, 505 NOW.plusMillis(1000), 506 /* startZoneOffset= */ null, 507 /* endZoneOffset= */ null, 508 generateMetadataWithClientId(clientId)); 509 } 510 511 /** Create a {@link DistanceRecord} with non empty record ID. */ getDistanceRecordWithNonEmptyId()512 public static DistanceRecord getDistanceRecordWithNonEmptyId() { 513 return getDistanceRecord( 514 10, 515 NOW, 516 NOW.plusMillis(1000), 517 /* startZoneOffset= */ null, 518 /* endZoneOffset= */ null, 519 generateMetadata()); 520 } 521 522 /** Create a {@link DistanceRecord} with empty {@link Metadata}. */ getDistanceRecordWithEmptyMetadata()523 public static DistanceRecord getDistanceRecordWithEmptyMetadata() { 524 return getDistanceRecord( 525 10, 526 NOW, 527 NOW.plusMillis(1000), 528 /* startZoneOffset= */ null, 529 /* endZoneOffset= */ null, 530 getEmptyMetadata()); 531 } 532 533 /** Create a {@link DistanceRecord} with the specified arguments. */ getDistanceRecord(double distance, Instant start, Instant end)534 public static DistanceRecord getDistanceRecord(double distance, Instant start, Instant end) { 535 return getDistanceRecord( 536 distance, 537 start, 538 end, 539 /* startZoneOffset= */ null, 540 /* endZoneOffset= */ null, 541 getEmptyMetadata()); 542 } 543 544 /** Create a {@link DistanceRecord} with the specified arguments. */ getDistanceRecord( double distance, Instant start, Instant end, ZoneOffset offset)545 public static DistanceRecord getDistanceRecord( 546 double distance, Instant start, Instant end, ZoneOffset offset) { 547 return getDistanceRecord(distance, start, end, offset, offset, getEmptyMetadata()); 548 } 549 550 /** Create a {@link DistanceRecord} with the specified arguments. */ getDistanceRecord( double distance, Instant start, Instant end, String clientId)551 public static DistanceRecord getDistanceRecord( 552 double distance, Instant start, Instant end, String clientId) { 553 return getDistanceRecord( 554 distance, 555 start, 556 end, 557 /* startZoneOffset= */ null, 558 /* endZoneOffset= */ null, 559 getMetadataForClientId(clientId)); 560 } 561 562 /** Create a {@link DistanceRecord} with the specified arguments. */ getDistanceRecord( double distance, Instant start, Instant end, @Nullable ZoneOffset startZoneOffset, @Nullable ZoneOffset endZoneOffset, Metadata metadata)563 public static DistanceRecord getDistanceRecord( 564 double distance, 565 Instant start, 566 Instant end, 567 @Nullable ZoneOffset startZoneOffset, 568 @Nullable ZoneOffset endZoneOffset, 569 Metadata metadata) { 570 DistanceRecord.Builder builder = 571 new DistanceRecord.Builder(metadata, start, end, Length.fromMeters(distance)); 572 if (startZoneOffset != null) { 573 builder.setStartZoneOffset(startZoneOffset); 574 } 575 if (endZoneOffset != null) { 576 builder.setEndZoneOffset(endZoneOffset); 577 } 578 return builder.build(); 579 } 580 581 /** Gets a {@link TotalCaloriesBurnedRecord} with a specific {@code clientId}. */ getTotalCaloriesBurnedRecord(String clientId)582 public static TotalCaloriesBurnedRecord getTotalCaloriesBurnedRecord(String clientId) { 583 return getTotalCaloriesBurnedRecord(getMetadataForClientId(clientId)); 584 } 585 586 /** Gets a {@link TotalCaloriesBurnedRecord} with a specific {@link Metadata}. */ getTotalCaloriesBurnedRecord(Metadata metadata)587 public static TotalCaloriesBurnedRecord getTotalCaloriesBurnedRecord(Metadata metadata) { 588 return new TotalCaloriesBurnedRecord.Builder( 589 metadata, NOW, NOW.plusMillis(1000), Energy.fromCalories(10.0)) 590 .build(); 591 } 592 getTotalCaloriesBurnedRecordWithEmptyMetadata()593 public static TotalCaloriesBurnedRecord getTotalCaloriesBurnedRecordWithEmptyMetadata() { 594 return getTotalCaloriesBurnedRecord(getEmptyMetadata()); 595 } 596 getTestRecords()597 public static List<Record> getTestRecords() { 598 return Arrays.asList( 599 getStepsRecord(), 600 getHeartRateRecord(), 601 getBasalMetabolicRateRecord(), 602 buildExerciseSession()); 603 } 604 getChangeLogTokenRequestForTestRecordTypes()605 public static ChangeLogTokenRequest.Builder getChangeLogTokenRequestForTestRecordTypes() { 606 return new ChangeLogTokenRequest.Builder() 607 .addRecordType(StepsRecord.class) 608 .addRecordType(HeartRateRecord.class) 609 .addRecordType(BasalMetabolicRateRecord.class) 610 .addRecordType(ExerciseSessionRecord.class); 611 } 612 getRecordsAndIdentifiers()613 public static List<RecordAndIdentifier> getRecordsAndIdentifiers() { 614 return Arrays.asList( 615 new RecordAndIdentifier(RECORD_TYPE_STEPS, getStepsRecord()), 616 new RecordAndIdentifier(RECORD_TYPE_HEART_RATE, getHeartRateRecord()), 617 new RecordAndIdentifier( 618 RECORD_TYPE_BASAL_METABOLIC_RATE, getBasalMetabolicRateRecord())); 619 } 620 getBasalMetabolicRateRecord()621 public static BasalMetabolicRateRecord getBasalMetabolicRateRecord() { 622 return new BasalMetabolicRateRecord.Builder(generateMetadata(), NOW, Power.fromWatts(100.0)) 623 .build(); 624 } 625 } 626