• 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.changelog;
18 
19 import android.annotation.NonNull;
20 import android.health.connect.HealthConnectManager;
21 import android.health.connect.aidl.RecordsParcel;
22 import android.health.connect.datatypes.Record;
23 import android.health.connect.internal.datatypes.RecordInternal;
24 import android.health.connect.internal.datatypes.utils.InternalExternalRecordConverter;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 
28 import java.time.Instant;
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.Objects;
32 
33 /**
34  * Response class for {@link HealthConnectManager#getChangeLogs} This is the response to clients
35  * fetching changes
36  */
37 public final class ChangeLogsResponse implements Parcelable {
38     private final List<Record> mUpsertedRecords;
39     private final List<DeletedLog> mDeletedLogs;
40     private final String mNextChangesToken;
41     private final boolean mHasMorePages;
42 
43     /**
44      * Response for {@link HealthConnectManager#getChangeLogs}
45      *
46      * @hide
47      */
ChangeLogsResponse( @onNull RecordsParcel upsertedRecords, @NonNull List<DeletedLog> deletedLogs, @NonNull String nextChangesToken, boolean hasMorePages)48     public ChangeLogsResponse(
49             @NonNull RecordsParcel upsertedRecords,
50             @NonNull List<DeletedLog> deletedLogs,
51             @NonNull String nextChangesToken,
52             boolean hasMorePages) {
53         Objects.requireNonNull(upsertedRecords);
54         Objects.requireNonNull(deletedLogs);
55         Objects.requireNonNull(nextChangesToken);
56 
57         mUpsertedRecords =
58                 InternalExternalRecordConverter.getInstance()
59                         .getExternalRecords(upsertedRecords.getRecords());
60         mDeletedLogs = deletedLogs;
61         mNextChangesToken = nextChangesToken;
62         mHasMorePages = hasMorePages;
63     }
64 
ChangeLogsResponse(Parcel in)65     private ChangeLogsResponse(Parcel in) {
66         mUpsertedRecords =
67                 InternalExternalRecordConverter.getInstance()
68                         .getExternalRecords(
69                                 in.readParcelable(
70                                                 RecordsParcel.class.getClassLoader(),
71                                                 RecordsParcel.class)
72                                         .getRecords());
73         int size = in.readInt();
74         List<DeletedLog> deletedLogs = new ArrayList<>(size);
75         for (int i = 0; i < size; i++) {
76             String id = in.readString();
77             long time = in.readLong();
78             deletedLogs.add(new DeletedLog(id, time));
79         }
80         mDeletedLogs = deletedLogs;
81         mNextChangesToken = in.readString();
82         mHasMorePages = in.readBoolean();
83     }
84 
85     @NonNull
86     public static final Creator<ChangeLogsResponse> CREATOR =
87             new Creator<ChangeLogsResponse>() {
88                 @Override
89                 public ChangeLogsResponse createFromParcel(Parcel in) {
90                     return new ChangeLogsResponse(in);
91                 }
92 
93                 @Override
94                 public ChangeLogsResponse[] newArray(int size) {
95                     return new ChangeLogsResponse[size];
96                 }
97             };
98 
99     /**
100      * Returns records that have been updated or inserted post the time when the given token was
101      * generated.
102      *
103      * <p>Clients can use the last modified time of the record to check when the record was
104      * modified.
105      */
106     @NonNull
getUpsertedRecords()107     public List<Record> getUpsertedRecords() {
108         return mUpsertedRecords;
109     }
110 
111     /**
112      * Returns delete logs for records that have been deleted post the time when the token was
113      * requested from {@link HealthConnectManager#getChangeLogToken}
114      *
115      * <p>This contains record id of deleted record and the timestamp when the record was deleted.
116      */
117     @NonNull
getDeletedLogs()118     public List<DeletedLog> getDeletedLogs() {
119         return mDeletedLogs;
120     }
121 
122     /** Returns token for future reads using {@link HealthConnectManager#getChangeLogs} */
123     @NonNull
getNextChangesToken()124     public String getNextChangesToken() {
125         return mNextChangesToken;
126     }
127 
128     /** Returns whether there are more pages available for read */
hasMorePages()129     public boolean hasMorePages() {
130         return mHasMorePages;
131     }
132 
133     @Override
describeContents()134     public int describeContents() {
135         return 0;
136     }
137 
138     @Override
writeToParcel(@onNull Parcel dest, int flags)139     public void writeToParcel(@NonNull Parcel dest, int flags) {
140         List<RecordInternal<?>> recordInternal = new ArrayList<>();
141         for (Record record : mUpsertedRecords) {
142             recordInternal.add(record.toRecordInternal());
143         }
144         dest.writeParcelable(new RecordsParcel(recordInternal), 0);
145         dest.writeInt(mDeletedLogs.size());
146         for (DeletedLog deletedLog : mDeletedLogs) {
147             dest.writeString(deletedLog.getDeletedRecordId());
148             dest.writeLong(deletedLog.getDeletedTime().toEpochMilli());
149         }
150         dest.writeString(mNextChangesToken);
151         dest.writeBoolean(mHasMorePages);
152     }
153 
154     /** A class to represent a delete log in ChangeLogsResponse */
155     public static final class DeletedLog {
156         private final String mDeletedRecordId;
157         private final Instant mDeletedTime;
158 
DeletedLog(@onNull String deletedRecordId, long deletedTime)159         public DeletedLog(@NonNull String deletedRecordId, long deletedTime) {
160             Objects.requireNonNull(deletedRecordId);
161             mDeletedRecordId = deletedRecordId;
162             mDeletedTime = Instant.ofEpochMilli(deletedTime);
163         }
164 
165         /** Returns record id of the record deleted */
166         @NonNull
getDeletedRecordId()167         public String getDeletedRecordId() {
168             return mDeletedRecordId;
169         }
170 
171         /** Returns timestamp when the record was deleted */
172         @NonNull
getDeletedTime()173         public Instant getDeletedTime() {
174             return mDeletedTime;
175         }
176     }
177 }
178