• 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.aidl;
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.AggregateRecordsRequest;
25 import android.health.connect.LocalTimeRangeFilter;
26 import android.health.connect.TimeInstantRangeFilter;
27 import android.health.connect.TimeRangeFilter;
28 import android.health.connect.TimeRangeFilterHelper;
29 import android.health.connect.datatypes.AggregationType;
30 import android.health.connect.datatypes.DataOrigin;
31 import android.os.Parcel;
32 import android.os.Parcelable;
33 
34 import java.time.Duration;
35 import java.time.Instant;
36 import java.time.Period;
37 import java.util.List;
38 import java.util.stream.Collectors;
39 
40 /** @hide */
41 public class AggregateDataRequestParcel implements Parcelable {
42     public static final Creator<AggregateDataRequestParcel> CREATOR =
43             new Creator<>() {
44                 @Override
45                 public AggregateDataRequestParcel createFromParcel(Parcel in) {
46                     return new AggregateDataRequestParcel(in);
47                 }
48 
49                 @Override
50                 public AggregateDataRequestParcel[] newArray(int size) {
51                     return new AggregateDataRequestParcel[size];
52                 }
53             };
54     private final long mStartTime;
55     private final long mEndTime;
56     private final int[] mAggregateIds;
57     private final List<String> mPackageFilters;
58     // If set represents that the aggregations have to be grouped by on {@code mDuration}
59     private Duration mDuration;
60     // If set represents that the aggregations have to be grouped by on {@code mPeriod}. If both are
61     // set the duration takes precedence, but there should not be case when both are set.
62     private Period mPeriod;
63 
64     private final boolean mLocalTimeFilter;
65 
66     @SuppressWarnings("NullAway.Init") // TODO(b/317029272): fix this suppression
AggregateDataRequestParcel(AggregateRecordsRequest<?> request)67     public AggregateDataRequestParcel(AggregateRecordsRequest<?> request) {
68         mStartTime = TimeRangeFilterHelper.getFilterStartTimeMillis(request.getTimeRangeFilter());
69         mEndTime = TimeRangeFilterHelper.getFilterEndTimeMillis(request.getTimeRangeFilter());
70         mAggregateIds = new int[request.getAggregationTypes().size()];
71         mLocalTimeFilter = TimeRangeFilterHelper.isLocalTimeFilter(request.getTimeRangeFilter());
72 
73         int i = 0;
74         for (AggregationType<?> aggregationType : request.getAggregationTypes()) {
75             mAggregateIds[i++] = aggregationType.getAggregationTypeIdentifier();
76         }
77         mPackageFilters =
78                 request.getDataOriginsFilters().stream()
79                         .map(DataOrigin::getPackageName)
80                         .collect(Collectors.toList());
81         // Use durations group by single queries as it support null values
82         mDuration = Duration.ofMillis(mEndTime - mStartTime);
83     }
84 
AggregateDataRequestParcel(AggregateRecordsRequest request, Duration duration)85     public AggregateDataRequestParcel(AggregateRecordsRequest request, Duration duration) {
86         this(request);
87         mDuration = duration;
88     }
89 
90     @SuppressWarnings("NullAway") // TODO(b/317029272): fix this suppression
AggregateDataRequestParcel(AggregateRecordsRequest request, Period period)91     public AggregateDataRequestParcel(AggregateRecordsRequest request, Period period) {
92         this(request);
93         mDuration = null;
94         mPeriod = period;
95 
96         if (!TimeRangeFilterHelper.isLocalTimeFilter(request.getTimeRangeFilter())) {
97             throw new UnsupportedOperationException(
98                     "For period requests should use LocalTimeRangeFilter");
99         }
100     }
101 
102     @SuppressWarnings("NullAway.Init") // TODO(b/317029272): fix this suppression
AggregateDataRequestParcel(Parcel in)103     protected AggregateDataRequestParcel(Parcel in) {
104         mStartTime = in.readLong();
105         mEndTime = in.readLong();
106         mLocalTimeFilter = in.readBoolean();
107         mAggregateIds = in.createIntArray();
108         mPackageFilters = in.createStringArrayList();
109         int periodDays = in.readInt();
110         if (periodDays != DEFAULT_INT) {
111             int periodMonths = in.readInt();
112             int periodYears = in.readInt();
113             mPeriod = Period.of(periodYears, periodMonths, periodDays);
114         }
115 
116         long duration = in.readLong();
117         if (duration != DEFAULT_LONG) {
118             mDuration = Duration.ofMillis(duration);
119         }
120     }
121 
122     @Nullable
getDuration()123     public Duration getDuration() {
124         return mDuration;
125     }
126 
127     @Nullable
getPeriod()128     public Period getPeriod() {
129         return mPeriod;
130     }
131 
132     /** Returns whether this request uses {@link LocalTimeRangeFilter}. */
useLocalTimeFilter()133     public boolean useLocalTimeFilter() {
134         return mLocalTimeFilter;
135     }
136 
137     @Override
describeContents()138     public int describeContents() {
139         return 0;
140     }
141 
142     @Override
writeToParcel(@onNull Parcel dest, int flags)143     public void writeToParcel(@NonNull Parcel dest, int flags) {
144         dest.writeLong(mStartTime);
145         dest.writeLong(mEndTime);
146         dest.writeBoolean(mLocalTimeFilter);
147         dest.writeIntArray(mAggregateIds);
148         dest.writeStringList(mPackageFilters);
149         if (mPeriod != null) {
150             dest.writeInt(mPeriod.getDays());
151             dest.writeInt(mPeriod.getMonths());
152             dest.writeInt(mPeriod.getYears());
153         } else {
154             dest.writeInt(DEFAULT_INT);
155         }
156 
157         if (mDuration != null) {
158             dest.writeLong(mDuration.toMillis());
159         } else {
160             dest.writeLong(DEFAULT_LONG);
161         }
162     }
163 
getStartTime()164     public long getStartTime() {
165         return mStartTime;
166     }
167 
getEndTime()168     public long getEndTime() {
169         return mEndTime;
170     }
171 
getAggregateIds()172     public int[] getAggregateIds() {
173         return mAggregateIds;
174     }
175 
176     @NonNull
getPackageFilters()177     public List<String> getPackageFilters() {
178         return mPackageFilters;
179     }
180 
181     @NonNull
getTimeRangeFilter()182     public TimeRangeFilter getTimeRangeFilter() {
183         if (mLocalTimeFilter) {
184             return new LocalTimeRangeFilter.Builder()
185                     .setStartTime(TimeRangeFilterHelper.getLocalTimeFromMillis(mStartTime))
186                     .setEndTime(TimeRangeFilterHelper.getLocalTimeFromMillis(mEndTime))
187                     .build();
188         } else {
189             return new TimeInstantRangeFilter.Builder()
190                     .setStartTime(Instant.ofEpochMilli(mStartTime))
191                     .setEndTime(Instant.ofEpochMilli(mEndTime))
192                     .build();
193         }
194     }
195 }
196