1 /* 2 * Copyright (C) 2023 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.health.connect.datatypes; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.health.connect.datatypes.units.Length; 22 import android.health.connect.datatypes.validation.ValidationUtils; 23 import android.health.connect.internal.datatypes.ExerciseLapInternal; 24 25 import java.time.Instant; 26 import java.util.Objects; 27 28 /** 29 * Captures the time of a lap within exercise session. Part of {@link ExerciseSessionRecord}. 30 * 31 * <p>Each record contains the start and end time and optional {@link Length} of the lap (e.g. pool 32 * length while swimming or a track lap while running). There may or may not be direct correlation 33 * with {@link ExerciseSegment} start and end times, e.g. {@link ExerciseSessionRecord} of type 34 * running without any segments can be divided as laps of different lengths. 35 */ 36 public final class ExerciseLap implements TimeInterval.TimeIntervalHolder { 37 private static final int MAX_LAP_LENGTH_METRES = 1000000; 38 39 private final TimeInterval mInterval; 40 private final Length mLength; 41 ExerciseLap( @onNull TimeInterval interval, @Nullable Length length, boolean skipValidation)42 private ExerciseLap( 43 @NonNull TimeInterval interval, @Nullable Length length, boolean skipValidation) { 44 Objects.requireNonNull(interval); 45 if (!skipValidation) { 46 ValidationUtils.requireInRangeIfExists( 47 length, 48 Length.fromMeters(0.0), 49 Length.fromMeters(MAX_LAP_LENGTH_METRES), 50 "length"); 51 } 52 mInterval = interval; 53 mLength = length; 54 } 55 56 /* 57 * Returns Length of the lap. 58 */ 59 @Nullable getLength()60 public Length getLength() { 61 return mLength; 62 } 63 64 /* 65 * Returns start time of the lap. 66 */ 67 @NonNull getStartTime()68 public Instant getStartTime() { 69 return mInterval.getStartTime(); 70 } 71 72 /* 73 * Returns end time of the lap. 74 */ 75 @NonNull getEndTime()76 public Instant getEndTime() { 77 return mInterval.getEndTime(); 78 } 79 80 /** @hide */ 81 @Override getInterval()82 public TimeInterval getInterval() { 83 return mInterval; 84 } 85 86 /** @hide */ getType()87 public int getType() { 88 return 0; 89 } 90 91 @Override equals(Object o)92 public boolean equals(Object o) { 93 if (this == o) return true; 94 if (!(o instanceof ExerciseLap)) return false; 95 ExerciseLap that = (ExerciseLap) o; 96 return Objects.equals(mInterval, that.mInterval) 97 && Objects.equals(getLength(), that.getLength()); 98 } 99 100 @Override hashCode()101 public int hashCode() { 102 return Objects.hash(mInterval, getLength()); 103 } 104 105 /** @hide */ 106 @NonNull toExerciseLapInternal()107 public ExerciseLapInternal toExerciseLapInternal() { 108 ExerciseLapInternal internalLap = 109 new ExerciseLapInternal() 110 .setStarTime(getStartTime().toEpochMilli()) 111 .setEndTime(getEndTime().toEpochMilli()); 112 if (getLength() != null) { 113 internalLap.setLength(getLength().getInMeters()); 114 } 115 116 return internalLap; 117 } 118 119 /** Builder class for {@link ExerciseLap} */ 120 public static final class Builder { 121 private final TimeInterval mInterval; 122 private Length mLength; 123 Builder(@onNull Instant startTime, @NonNull Instant endTime)124 public Builder(@NonNull Instant startTime, @NonNull Instant endTime) { 125 mInterval = new TimeInterval(startTime, endTime); 126 } 127 128 /** 129 * Sets the length of this lap 130 * 131 * @param length Length of the lap, in {@link Length} unit. Optional field. Valid range: 132 * 0-1000000 meters. 133 */ 134 @NonNull setLength(@onNull Length length)135 public ExerciseLap.Builder setLength(@NonNull Length length) { 136 Objects.requireNonNull(length); 137 mLength = length; 138 return this; 139 } 140 141 /** 142 * @return Object of {@link ExerciseLap} without validating the values. 143 * @hide 144 */ 145 @NonNull buildWithoutValidation()146 public ExerciseLap buildWithoutValidation() { 147 return new ExerciseLap(mInterval, mLength, true); 148 } 149 150 /** Builds {@link ExerciseLap} instance. */ 151 @NonNull build()152 public ExerciseLap build() { 153 return new ExerciseLap(mInterval, mLength, false); 154 } 155 } 156 } 157