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.internal.datatypes;
17 
18 import android.annotation.NonNull;
19 import android.health.connect.datatypes.IntervalRecord;
20 import android.os.Parcel;
21 
22 import java.time.Instant;
23 import java.time.LocalDate;
24 import java.time.ZoneOffset;
25 
26 /**
27  * Base class for all health connect datatype records that require a start and end time.
28  *
29  * @hide
30  */
31 public abstract class IntervalRecordInternal<T extends IntervalRecord> extends RecordInternal<T> {
32     private long mStartTime;
33     private int mStartZoneOffset;
34     private long mEndTime;
35     private int mEndZoneOffset;
36 
IntervalRecordInternal()37     IntervalRecordInternal() {
38         super();
39     }
40 
getStartTimeInMillis()41     public long getStartTimeInMillis() {
42         return mStartTime;
43     }
44 
getStartZoneOffsetInSeconds()45     public int getStartZoneOffsetInSeconds() {
46         return mStartZoneOffset;
47     }
48 
getEndTimeInMillis()49     public long getEndTimeInMillis() {
50         return mEndTime;
51     }
52 
getEndZoneOffsetInSeconds()53     public int getEndZoneOffsetInSeconds() {
54         return mEndZoneOffset;
55     }
56 
57     @Override
populateRecordTo(@onNull Parcel parcel)58     void populateRecordTo(@NonNull Parcel parcel) {
59         parcel.writeLong(mStartTime);
60         parcel.writeInt(mStartZoneOffset);
61         parcel.writeLong(mEndTime);
62         parcel.writeInt(mEndZoneOffset);
63 
64         populateIntervalRecordTo(parcel);
65     }
66 
67     @Override
populateRecordFrom(@onNull Parcel parcel)68     void populateRecordFrom(@NonNull Parcel parcel) {
69         mStartTime = parcel.readLong();
70         mStartZoneOffset = parcel.readInt();
71         mEndTime = parcel.readLong();
72         mEndZoneOffset = parcel.readInt();
73 
74         populateIntervalRecordFrom(parcel);
75     }
76 
getStartTime()77     Instant getStartTime() {
78         return Instant.ofEpochMilli(mStartTime);
79     }
80 
81     @NonNull
setStartTime(long startTime)82     public IntervalRecordInternal<T> setStartTime(long startTime) {
83         mStartTime = startTime;
84         return this;
85     }
86 
getStartZoneOffset()87     ZoneOffset getStartZoneOffset() {
88         return ZoneOffset.ofTotalSeconds(mStartZoneOffset);
89     }
90 
91     @NonNull
setStartZoneOffset(int startZoneOffset)92     public IntervalRecordInternal<T> setStartZoneOffset(int startZoneOffset) {
93         mStartZoneOffset = startZoneOffset;
94         return this;
95     }
96 
getEndTime()97     Instant getEndTime() {
98         return Instant.ofEpochMilli(mEndTime);
99     }
100 
101     @NonNull
setEndTime(long endTime)102     public IntervalRecordInternal<T> setEndTime(long endTime) {
103         mEndTime = endTime;
104         return this;
105     }
106 
getEndZoneOffset()107     ZoneOffset getEndZoneOffset() {
108         return ZoneOffset.ofTotalSeconds(mEndZoneOffset);
109     }
110 
111     @NonNull
setEndZoneOffset(int endZoneOffset)112     public IntervalRecordInternal<T> setEndZoneOffset(int endZoneOffset) {
113         mEndZoneOffset = endZoneOffset;
114         return this;
115     }
116 
117     /**
118      * @return the {@link LocalDate} object of this activity start time.
119      */
120     @Override
121     @NonNull
getLocalDate()122     public LocalDate getLocalDate() {
123         return LocalDate.ofInstant(this.getStartTime(), this.getStartZoneOffset());
124     }
125 
126     /**
127      * Child class must implement this method and populates itself with the data present in {@param
128      * bundle}. Reads should be in the same order as write
129      */
populateIntervalRecordFrom(@onNull Parcel parcel)130     abstract void populateIntervalRecordFrom(@NonNull Parcel parcel);
131 
132     /**
133      * Populate {@param bundle} with the data required to un-bundle self. This is used during IPC
134      * transmissions
135      */
populateIntervalRecordTo(@onNull Parcel parcel)136     abstract void populateIntervalRecordTo(@NonNull Parcel parcel);
137 }
138