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 package android.health.connect.datatypes; 17 18 import static android.health.connect.datatypes.AggregationType.AggregationTypeIdentifier.WHEEL_CHAIR_PUSHES_RECORD_COUNT_TOTAL; 19 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_WHEELCHAIR_PUSHES; 20 21 import android.annotation.IntRange; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.health.connect.HealthConnectManager; 25 import android.health.connect.datatypes.validation.ValidationUtils; 26 import android.health.connect.internal.datatypes.WheelchairPushesRecordInternal; 27 28 import java.time.Instant; 29 import java.time.ZoneOffset; 30 import java.util.Objects; 31 32 /** 33 * Captures the number of wheelchair pushes done over a time interval. Each push is only reported 34 * once so records shouldn't have overlapping time. The start time of each record should represent 35 * the start of the interval in which pushes were made. 36 */ 37 @Identifier(recordIdentifier = RECORD_TYPE_WHEELCHAIR_PUSHES) 38 public final class WheelchairPushesRecord extends IntervalRecord { 39 40 private final long mCount; 41 42 /** 43 * Metric identifier to get total wheelchair push count using aggregate APIs in {@link 44 * HealthConnectManager} 45 */ 46 @android.annotation.NonNull 47 public static final AggregationType<Long> WHEEL_CHAIR_PUSHES_COUNT_TOTAL = 48 new AggregationType<>( 49 WHEEL_CHAIR_PUSHES_RECORD_COUNT_TOTAL, 50 AggregationType.SUM, 51 RECORD_TYPE_WHEELCHAIR_PUSHES, 52 Long.class); 53 54 /** 55 * @param metadata Metadata to be associated with the record. See {@link Metadata}. 56 * @param startTime Start time of this activity 57 * @param startZoneOffset Zone offset of the user when the activity started 58 * @param endTime End time of this activity 59 * @param endZoneOffset Zone offset of the user when the activity finished 60 * @param count Count of pushes 61 * @param skipValidation Boolean flag to skip validation of record values. 62 */ WheelchairPushesRecord( @onNull Metadata metadata, @NonNull Instant startTime, @NonNull ZoneOffset startZoneOffset, @NonNull Instant endTime, @NonNull ZoneOffset endZoneOffset, long count, boolean skipValidation)63 private WheelchairPushesRecord( 64 @NonNull Metadata metadata, 65 @NonNull Instant startTime, 66 @NonNull ZoneOffset startZoneOffset, 67 @NonNull Instant endTime, 68 @NonNull ZoneOffset endZoneOffset, 69 long count, 70 boolean skipValidation) { 71 super( 72 metadata, 73 startTime, 74 startZoneOffset, 75 endTime, 76 endZoneOffset, 77 skipValidation, 78 /* enforceFutureTimeRestrictions= */ true); 79 Objects.requireNonNull(metadata); 80 Objects.requireNonNull(startTime); 81 Objects.requireNonNull(startZoneOffset); 82 Objects.requireNonNull(startTime); 83 Objects.requireNonNull(endZoneOffset); 84 if (!skipValidation) { 85 ValidationUtils.requireInRange(count, 0, 1000000, "count"); 86 } 87 mCount = count; 88 } 89 90 /** 91 * @return wheelchair pushes count. 92 */ getCount()93 public long getCount() { 94 return mCount; 95 } 96 97 /** 98 * Indicates whether some other object is "equal to" this one. 99 * 100 * @param object the reference object with which to compare. 101 * @return {@code true} if this object is the same as the object argument; {@code false} 102 * otherwise. 103 */ 104 @Override equals(@ullable Object object)105 public boolean equals(@Nullable Object object) { 106 if (super.equals(object) && object instanceof WheelchairPushesRecord) { 107 WheelchairPushesRecord other = (WheelchairPushesRecord) object; 108 return this.getCount() == other.getCount(); 109 } 110 return false; 111 } 112 113 /** Returns a hash code value for the object. */ 114 @Override hashCode()115 public int hashCode() { 116 return Objects.hash(super.hashCode(), this.getCount()); 117 } 118 119 /** Builder class for {@link WheelchairPushesRecord} */ 120 public static final class Builder { 121 private final Metadata mMetadata; 122 private final Instant mStartTime; 123 private final Instant mEndTime; 124 private ZoneOffset mStartZoneOffset; 125 private ZoneOffset mEndZoneOffset; 126 private final long mCount; 127 128 /** 129 * @param metadata Metadata to be associated with the record. See {@link Metadata}. 130 * @param startTime Start time of this activity 131 * @param endTime End time of this activity 132 * @param count Count of pushes. Required field. Valid range: 1-1000000. 133 */ Builder( @onNull Metadata metadata, @NonNull Instant startTime, @NonNull Instant endTime, @IntRange(from = 1, to = 1000000) long count)134 public Builder( 135 @NonNull Metadata metadata, 136 @NonNull Instant startTime, 137 @NonNull Instant endTime, 138 @IntRange(from = 1, to = 1000000) long count) { 139 Objects.requireNonNull(metadata); 140 Objects.requireNonNull(startTime); 141 Objects.requireNonNull(endTime); 142 mMetadata = metadata; 143 mStartTime = startTime; 144 mEndTime = endTime; 145 mCount = count; 146 mStartZoneOffset = ZoneOffset.systemDefault().getRules().getOffset(startTime); 147 mEndZoneOffset = ZoneOffset.systemDefault().getRules().getOffset(endTime); 148 } 149 150 /** Sets the zone offset of the user when the activity started */ 151 @NonNull setStartZoneOffset(@onNull ZoneOffset startZoneOffset)152 public Builder setStartZoneOffset(@NonNull ZoneOffset startZoneOffset) { 153 Objects.requireNonNull(startZoneOffset); 154 155 mStartZoneOffset = startZoneOffset; 156 return this; 157 } 158 159 /** Sets the zone offset of the user when the activity ended */ 160 @NonNull setEndZoneOffset(@onNull ZoneOffset endZoneOffset)161 public Builder setEndZoneOffset(@NonNull ZoneOffset endZoneOffset) { 162 Objects.requireNonNull(endZoneOffset); 163 164 mEndZoneOffset = endZoneOffset; 165 return this; 166 } 167 168 /** Sets the start zone offset of this record to system default. */ 169 @NonNull clearStartZoneOffset()170 public Builder clearStartZoneOffset() { 171 mStartZoneOffset = RecordUtils.getDefaultZoneOffset(); 172 return this; 173 } 174 175 /** Sets the start zone offset of this record to system default. */ 176 @NonNull clearEndZoneOffset()177 public Builder clearEndZoneOffset() { 178 mEndZoneOffset = RecordUtils.getDefaultZoneOffset(); 179 return this; 180 } 181 182 /** 183 * @return Object of {@link WheelchairPushesRecord} without validating the values. 184 * @hide 185 */ 186 @NonNull buildWithoutValidation()187 public WheelchairPushesRecord buildWithoutValidation() { 188 return new WheelchairPushesRecord( 189 mMetadata, 190 mStartTime, 191 mStartZoneOffset, 192 mEndTime, 193 mEndZoneOffset, 194 mCount, 195 true); 196 } 197 198 /** 199 * @return Object of {@link WheelchairPushesRecord} 200 */ 201 @NonNull build()202 public WheelchairPushesRecord build() { 203 return new WheelchairPushesRecord( 204 mMetadata, 205 mStartTime, 206 mStartZoneOffset, 207 mEndTime, 208 mEndZoneOffset, 209 mCount, 210 false); 211 } 212 } 213 214 /** @hide */ 215 @Override toRecordInternal()216 public WheelchairPushesRecordInternal toRecordInternal() { 217 WheelchairPushesRecordInternal recordInternal = 218 (WheelchairPushesRecordInternal) 219 new WheelchairPushesRecordInternal() 220 .setUuid(getMetadata().getId()) 221 .setPackageName(getMetadata().getDataOrigin().getPackageName()) 222 .setLastModifiedTime( 223 getMetadata().getLastModifiedTime().toEpochMilli()) 224 .setClientRecordId(getMetadata().getClientRecordId()) 225 .setClientRecordVersion(getMetadata().getClientRecordVersion()) 226 .setManufacturer(getMetadata().getDevice().getManufacturer()) 227 .setModel(getMetadata().getDevice().getModel()) 228 .setDeviceType(getMetadata().getDevice().getType()) 229 .setRecordingMethod(getMetadata().getRecordingMethod()); 230 recordInternal.setStartTime(getStartTime().toEpochMilli()); 231 recordInternal.setEndTime(getEndTime().toEpochMilli()); 232 recordInternal.setStartZoneOffset(getStartZoneOffset().getTotalSeconds()); 233 recordInternal.setEndZoneOffset(getEndZoneOffset().getTotalSeconds()); 234 recordInternal.setCount((int) mCount); 235 return recordInternal; 236 } 237 } 238