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 boolean mLocalTimeFilter; 65 AggregateDataRequestParcel(AggregateRecordsRequest<?> request)66 public AggregateDataRequestParcel(AggregateRecordsRequest<?> request) { 67 mStartTime = TimeRangeFilterHelper.getFilterStartTimeMillis(request.getTimeRangeFilter()); 68 mEndTime = TimeRangeFilterHelper.getFilterEndTimeMillis(request.getTimeRangeFilter()); 69 mAggregateIds = new int[request.getAggregationTypes().size()]; 70 mLocalTimeFilter = TimeRangeFilterHelper.isLocalTimeFilter(request.getTimeRangeFilter()); 71 72 int i = 0; 73 for (AggregationType<?> aggregationType : request.getAggregationTypes()) { 74 mAggregateIds[i++] = aggregationType.getAggregationTypeIdentifier(); 75 } 76 mPackageFilters = 77 request.getDataOriginsFilters().stream() 78 .map(DataOrigin::getPackageName) 79 .collect(Collectors.toList()); 80 // Use durations group by single queries as it support null values 81 mDuration = Duration.ofMillis(mEndTime - mStartTime); 82 } 83 AggregateDataRequestParcel(AggregateRecordsRequest request, Duration duration)84 public AggregateDataRequestParcel(AggregateRecordsRequest request, Duration duration) { 85 this(request); 86 mDuration = duration; 87 } 88 AggregateDataRequestParcel(AggregateRecordsRequest request, Period period)89 public AggregateDataRequestParcel(AggregateRecordsRequest request, Period period) { 90 this(request); 91 mDuration = null; 92 mPeriod = period; 93 94 if (!TimeRangeFilterHelper.isLocalTimeFilter(request.getTimeRangeFilter())) { 95 throw new UnsupportedOperationException( 96 "For period requests should use LocalTimeRangeFilter"); 97 } 98 } 99 AggregateDataRequestParcel(Parcel in)100 protected AggregateDataRequestParcel(Parcel in) { 101 mStartTime = in.readLong(); 102 mEndTime = in.readLong(); 103 mLocalTimeFilter = in.readBoolean(); 104 mAggregateIds = in.createIntArray(); 105 mPackageFilters = in.createStringArrayList(); 106 int periodDays = in.readInt(); 107 if (periodDays != DEFAULT_INT) { 108 int periodMonths = in.readInt(); 109 int periodYears = in.readInt(); 110 mPeriod = Period.of(periodYears, periodMonths, periodDays); 111 } 112 113 long duration = in.readLong(); 114 if (duration != DEFAULT_LONG) { 115 mDuration = Duration.ofMillis(duration); 116 } 117 } 118 119 @Nullable getDuration()120 public Duration getDuration() { 121 return mDuration; 122 } 123 124 @Nullable getPeriod()125 public Period getPeriod() { 126 return mPeriod; 127 } 128 129 @Override describeContents()130 public int describeContents() { 131 return 0; 132 } 133 134 @Override writeToParcel(@onNull Parcel dest, int flags)135 public void writeToParcel(@NonNull Parcel dest, int flags) { 136 dest.writeLong(mStartTime); 137 dest.writeLong(mEndTime); 138 dest.writeBoolean(mLocalTimeFilter); 139 dest.writeIntArray(mAggregateIds); 140 dest.writeStringList(mPackageFilters); 141 if (mPeriod != null) { 142 dest.writeInt(mPeriod.getDays()); 143 dest.writeInt(mPeriod.getMonths()); 144 dest.writeInt(mPeriod.getYears()); 145 } else { 146 dest.writeInt(DEFAULT_INT); 147 } 148 149 if (mDuration != null) { 150 dest.writeLong(mDuration.toMillis()); 151 } else { 152 dest.writeLong(DEFAULT_LONG); 153 } 154 } 155 getStartTime()156 public long getStartTime() { 157 return mStartTime; 158 } 159 getEndTime()160 public long getEndTime() { 161 return mEndTime; 162 } 163 getAggregateIds()164 public int[] getAggregateIds() { 165 return mAggregateIds; 166 } 167 168 @NonNull getPackageFilters()169 public List<String> getPackageFilters() { 170 return mPackageFilters; 171 } 172 173 @NonNull getTimeRangeFilter()174 public TimeRangeFilter getTimeRangeFilter() { 175 if (mLocalTimeFilter) { 176 return new LocalTimeRangeFilter.Builder() 177 .setStartTime(TimeRangeFilterHelper.getLocalTimeFromMillis(mStartTime)) 178 .setEndTime(TimeRangeFilterHelper.getLocalTimeFromMillis(mEndTime)) 179 .build(); 180 } else { 181 return new TimeInstantRangeFilter.Builder() 182 .setStartTime(Instant.ofEpochMilli(mStartTime)) 183 .setEndTime(Instant.ofEpochMilli(mEndTime)) 184 .build(); 185 } 186 } 187 } 188