• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.internal.datatypes;
18 
19 import static android.health.connect.Constants.DEFAULT_INT;
20 import static android.health.connect.Constants.DEFAULT_LONG;
21 
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.health.connect.datatypes.DataOrigin;
25 import android.health.connect.datatypes.Device;
26 import android.health.connect.datatypes.Identifier;
27 import android.health.connect.datatypes.Metadata;
28 import android.health.connect.datatypes.Record;
29 import android.health.connect.datatypes.RecordTypeIdentifier;
30 import android.os.Parcel;
31 
32 import java.time.Instant;
33 import java.time.LocalDate;
34 import java.util.Objects;
35 import java.util.UUID;
36 
37 /**
38  * Base class for all health connect datatype records.
39  *
40  * @hide
41  */
42 public abstract class RecordInternal<T extends Record> {
43     private final int mRecordIdentifier;
44     private UUID mUuid;
45     private String mPackageName;
46     private String mAppName;
47     private long mLastModifiedTime = DEFAULT_LONG;
48     private String mClientRecordId;
49     private long mClientRecordVersion = DEFAULT_LONG;
50     private String mManufacturer;
51     private String mModel;
52     private int mDeviceType;
53     private long mDeviceInfoId = DEFAULT_LONG;
54     private long mAppInfoId = DEFAULT_LONG;
55     private int mRowId = DEFAULT_INT;
56 
57     @Metadata.RecordingMethod private int mRecordingMethod;
58 
RecordInternal()59     RecordInternal() {
60         Identifier annotation = this.getClass().getAnnotation(Identifier.class);
61         Objects.requireNonNull(annotation);
62         mRecordIdentifier = annotation.recordIdentifier();
63     }
64 
65     @RecordTypeIdentifier.RecordType
getRecordType()66     public int getRecordType() {
67         return mRecordIdentifier;
68     }
69 
70     /**
71      * Populates self with the data present in {@code parcel}. Reads should be in the same order as
72      * write
73      */
populateUsing(@onNull Parcel parcel)74     public final void populateUsing(@NonNull Parcel parcel) {
75         String uuidString = parcel.readString();
76         if (uuidString != null && !uuidString.isEmpty()) {
77             mUuid = UUID.fromString(uuidString);
78         }
79         mPackageName = parcel.readString();
80         mAppName = parcel.readString();
81         mLastModifiedTime = parcel.readLong();
82         mClientRecordId = parcel.readString();
83         mClientRecordVersion = parcel.readLong();
84         mManufacturer = parcel.readString();
85         mModel = parcel.readString();
86         mDeviceType = parcel.readInt();
87         mRecordingMethod = parcel.readInt();
88 
89         populateRecordFrom(parcel);
90     }
91 
92     /**
93      * Populates {@code parcel} with the self information, required to reconstructor this object
94      * during IPC
95      */
96     @NonNull
writeToParcel(@onNull Parcel parcel)97     public final void writeToParcel(@NonNull Parcel parcel) {
98         parcel.writeString(mUuid == null ? "" : mUuid.toString());
99         parcel.writeString(mPackageName);
100         parcel.writeString(mAppName);
101         parcel.writeLong(mLastModifiedTime);
102         parcel.writeString(mClientRecordId);
103         parcel.writeLong(mClientRecordVersion);
104         parcel.writeString(mManufacturer);
105         parcel.writeString(mModel);
106         parcel.writeInt(mDeviceType);
107         parcel.writeInt(mRecordingMethod);
108 
109         populateRecordTo(parcel);
110     }
111 
112     @Nullable
getUuid()113     public UUID getUuid() {
114         return mUuid;
115     }
116 
117     @NonNull
setUuid(@ullable UUID uuid)118     public RecordInternal<T> setUuid(@Nullable UUID uuid) {
119         this.mUuid = uuid;
120         return this;
121     }
122 
123     @NonNull
setUuid(@ullable String uuid)124     public RecordInternal<T> setUuid(@Nullable String uuid) {
125         if (uuid == null || uuid.isEmpty()) {
126             mUuid = null;
127             return this;
128         }
129 
130         mUuid = UUID.fromString(uuid);
131         return this;
132     }
133 
134     @Nullable
getPackageName()135     public String getPackageName() {
136         return mPackageName;
137     }
138 
139     @NonNull
setPackageName(@ullable String packageName)140     public RecordInternal<T> setPackageName(@Nullable String packageName) {
141         this.mPackageName = packageName;
142         return this;
143     }
144 
145     /** Gets row id of this record. */
getRowId()146     public int getRowId() {
147         return mRowId;
148     }
149 
150     /** Sets the row id for this record. */
setRowId(int rowId)151     public RecordInternal<T> setRowId(int rowId) {
152         mRowId = rowId;
153         return this;
154     }
155 
156     /**
157      * Returns an application name associated with this record. Currently, it is used for AppInfo
158      * generation when inserting a record. May be {@code null}, in which case the app name may be
159      * missing in AppInfo.
160      */
161     @Nullable
getAppName()162     public String getAppName() {
163         return mAppName;
164     }
165 
166     /** Sets the application name for this record. */
167     @NonNull
setAppName(@ullable String appName)168     public RecordInternal<T> setAppName(@Nullable String appName) {
169         mAppName = appName;
170         return this;
171     }
172 
getLastModifiedTime()173     public long getLastModifiedTime() {
174         return mLastModifiedTime;
175     }
176 
177     @NonNull
setLastModifiedTime(long lastModifiedTime)178     public RecordInternal<T> setLastModifiedTime(long lastModifiedTime) {
179         this.mLastModifiedTime = lastModifiedTime;
180         return this;
181     }
182 
183     @Nullable
getClientRecordId()184     public String getClientRecordId() {
185         return mClientRecordId;
186     }
187 
188     @NonNull
setClientRecordId(@ullable String clientRecordId)189     public RecordInternal<T> setClientRecordId(@Nullable String clientRecordId) {
190         this.mClientRecordId = clientRecordId;
191         return this;
192     }
193 
getClientRecordVersion()194     public long getClientRecordVersion() {
195         return mClientRecordVersion;
196     }
197 
198     @NonNull
setClientRecordVersion(long clientRecordVersion)199     public RecordInternal<T> setClientRecordVersion(long clientRecordVersion) {
200         this.mClientRecordVersion = clientRecordVersion;
201         return this;
202     }
203 
204     @Nullable
getManufacturer()205     public String getManufacturer() {
206         return mManufacturer;
207     }
208 
209     @NonNull
setManufacturer(@ullable String manufacturer)210     public RecordInternal<T> setManufacturer(@Nullable String manufacturer) {
211         this.mManufacturer = manufacturer;
212         return this;
213     }
214 
215     @Nullable
getModel()216     public String getModel() {
217         return mModel;
218     }
219 
220     @NonNull
setModel(@ullable String model)221     public RecordInternal<T> setModel(@Nullable String model) {
222         this.mModel = model;
223         return this;
224     }
225 
226     @Device.DeviceType
getDeviceType()227     public int getDeviceType() {
228         return mDeviceType;
229     }
230 
231     @NonNull
setDeviceType(@evice.DeviceType int deviceType)232     public RecordInternal<T> setDeviceType(@Device.DeviceType int deviceType) {
233         this.mDeviceType = deviceType;
234         return this;
235     }
236 
getDeviceInfoId()237     public long getDeviceInfoId() {
238         return mDeviceInfoId;
239     }
240 
241     @NonNull
setDeviceInfoId(long deviceInfoId)242     public RecordInternal<T> setDeviceInfoId(long deviceInfoId) {
243         this.mDeviceInfoId = deviceInfoId;
244         return this;
245     }
246 
getAppInfoId()247     public long getAppInfoId() {
248         return mAppInfoId;
249     }
250 
251     @NonNull
setAppInfoId(long appInfoId)252     public RecordInternal<T> setAppInfoId(long appInfoId) {
253         this.mAppInfoId = appInfoId;
254         return this;
255     }
256 
257     /** Returns recording method which indicates how data was recorded for the {@link Record} */
258     @Metadata.RecordingMethod
getRecordingMethod()259     public int getRecordingMethod() {
260         return mRecordingMethod;
261     }
262 
263     /** Sets Recording method to know how data was recorded for the {@link Record} */
264     @NonNull
setRecordingMethod(@etadata.RecordingMethod int recordingMethod)265     public RecordInternal<T> setRecordingMethod(@Metadata.RecordingMethod int recordingMethod) {
266         this.mRecordingMethod = recordingMethod;
267         return this;
268     }
269 
270     /** Child class must implement this method and return an external record for this record */
toExternalRecord()271     public abstract T toExternalRecord();
272 
273     @NonNull
buildMetaData()274     Metadata buildMetaData() {
275         return new Metadata.Builder()
276                 .setClientRecordId(getClientRecordId())
277                 .setClientRecordVersion(getClientRecordVersion())
278                 .setDataOrigin(new DataOrigin.Builder().setPackageName(getPackageName()).build())
279                 .setId(getUuid() == null ? null : getUuid().toString())
280                 .setLastModifiedTime(Instant.ofEpochMilli(getLastModifiedTime()))
281                 .setRecordingMethod(getRecordingMethod())
282                 .setDevice(
283                         new Device.Builder()
284                                 .setManufacturer(getManufacturer())
285                                 .setType(getDeviceType())
286                                 .setModel(getModel())
287                                 .build())
288                 .build();
289     }
290 
291     /**
292      * @return the {@link LocalDate} object of this activity start time.
293      */
getLocalDate()294     public abstract LocalDate getLocalDate();
295 
296     /**
297      * Populate {@code bundle} with the data required to un-bundle self. This is used suring IPC
298      * transmissions
299      */
populateRecordTo(@onNull Parcel bundle)300     abstract void populateRecordTo(@NonNull Parcel bundle);
301 
302     /**
303      * Child class must implement this method and populates itself with the data present in {@code
304      * bundle}
305      */
populateRecordFrom(@onNull Parcel bundle)306     abstract void populateRecordFrom(@NonNull Parcel bundle);
307 }
308