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_LONG;
20 
21 import android.annotation.NonNull;
22 import android.health.connect.DeleteUsingFiltersRequest;
23 import android.health.connect.TimeRangeFilterHelper;
24 import android.health.connect.datatypes.DataOrigin;
25 import android.health.connect.internal.datatypes.utils.RecordMapper;
26 import android.os.Parcel;
27 import android.os.Parcelable;
28 
29 import java.util.Arrays;
30 import java.util.Collections;
31 import java.util.List;
32 import java.util.Objects;
33 import java.util.stream.Collectors;
34 
35 /**
36  * @see DeleteUsingFiltersRequest
37  * @hide
38  */
39 public class DeleteUsingFiltersRequestParcel implements Parcelable {
40     public static final Creator<DeleteUsingFiltersRequestParcel> CREATOR =
41             new Creator<>() {
42                 @Override
43                 public DeleteUsingFiltersRequestParcel createFromParcel(Parcel in) {
44                     return new DeleteUsingFiltersRequestParcel(in);
45                 }
46 
47                 @Override
48                 public DeleteUsingFiltersRequestParcel[] newArray(int size) {
49                     return new DeleteUsingFiltersRequestParcel[size];
50                 }
51             };
52     private List<String> mPackageNameFilters;
53     private final int[] mRecordTypeFilters;
54     private final long mStartTime;
55     private final long mEndTime;
56     private final RecordIdFiltersParcel mRecordIdFiltersParcel;
57     private final boolean mLocalTimeFilter;
58 
DeleteUsingFiltersRequestParcel(Parcel in)59     protected DeleteUsingFiltersRequestParcel(Parcel in) {
60         mPackageNameFilters = in.createStringArrayList();
61         mRecordTypeFilters = in.createIntArray();
62         mStartTime = in.readLong();
63         mEndTime = in.readLong();
64         mLocalTimeFilter = in.readBoolean();
65         mRecordIdFiltersParcel =
66                 in.readParcelable(
67                         RecordIdFiltersParcel.class.getClassLoader(), RecordIdFiltersParcel.class);
68     }
69 
70     @SuppressWarnings("NullAway") // TODO(b/317029272): fix this suppression
DeleteUsingFiltersRequestParcel(DeleteUsingFiltersRequest request)71     public DeleteUsingFiltersRequestParcel(DeleteUsingFiltersRequest request) {
72         mPackageNameFilters =
73                 request.getDataOrigins().stream()
74                         .map(DataOrigin::getPackageName)
75                         .collect(Collectors.toList());
76         mRecordTypeFilters =
77                 request.getRecordTypes().stream()
78                         .mapToInt(
79                                 recordType -> RecordMapper.getInstance().getRecordType(recordType))
80                         .toArray();
81 
82         if (request.getTimeRangeFilter() == null) {
83             // Use defaults values to signal filters not set
84             mStartTime = DEFAULT_LONG;
85             mEndTime = DEFAULT_LONG;
86         } else {
87             mStartTime =
88                     TimeRangeFilterHelper.getFilterStartTimeMillis(request.getTimeRangeFilter());
89             mEndTime = TimeRangeFilterHelper.getFilterEndTimeMillis(request.getTimeRangeFilter());
90         }
91         mLocalTimeFilter = TimeRangeFilterHelper.isLocalTimeFilter(request.getTimeRangeFilter());
92         mRecordIdFiltersParcel = new RecordIdFiltersParcel(Collections.emptyList());
93     }
94 
DeleteUsingFiltersRequestParcel( RecordIdFiltersParcel recordIdFiltersParcel, String packageName)95     public DeleteUsingFiltersRequestParcel(
96             RecordIdFiltersParcel recordIdFiltersParcel, String packageName) {
97         mPackageNameFilters = Collections.singletonList(packageName);
98         // Not required with ids
99         mRecordTypeFilters = new int[0];
100         mStartTime = DEFAULT_LONG;
101         mEndTime = DEFAULT_LONG;
102         mLocalTimeFilter = false;
103         mRecordIdFiltersParcel = recordIdFiltersParcel;
104     }
105 
getRecordIdFiltersParcel()106     public RecordIdFiltersParcel getRecordIdFiltersParcel() {
107         return mRecordIdFiltersParcel;
108     }
109 
getPackageNameFilters()110     public List<String> getPackageNameFilters() {
111         return mPackageNameFilters;
112     }
113 
setPackageNameFilters(@onNull List<String> packages)114     public void setPackageNameFilters(@NonNull List<String> packages) {
115         Objects.requireNonNull(packages);
116         mPackageNameFilters = packages;
117     }
118 
getRecordTypeFilters()119     public List<Integer> getRecordTypeFilters() {
120         if (mRecordIdFiltersParcel != null
121                 && !mRecordIdFiltersParcel.getRecordIdFilters().isEmpty()) {
122             return mRecordIdFiltersParcel.getRecordIdFilters().stream()
123                     .map(
124                             (recordIdFilter) ->
125                                     RecordMapper.getInstance()
126                                             .getRecordType(recordIdFilter.getRecordType()))
127                     .toList()
128                     .stream()
129                     .distinct()
130                     .toList();
131         }
132 
133         return Arrays.stream(mRecordTypeFilters).boxed().toList();
134     }
135 
getStartTime()136     public long getStartTime() {
137         return mStartTime;
138     }
139 
getEndTime()140     public long getEndTime() {
141         return mEndTime;
142     }
143 
usesIdFilters()144     public boolean usesIdFilters() {
145         return mRecordIdFiltersParcel.getRecordIdFilters() != null
146                 && !mRecordIdFiltersParcel.getRecordIdFilters().isEmpty();
147     }
148 
149     @Override
describeContents()150     public int describeContents() {
151         return 0;
152     }
153 
154     @Override
writeToParcel(@onNull Parcel dest, int flags)155     public void writeToParcel(@NonNull Parcel dest, int flags) {
156         dest.writeStringList(mPackageNameFilters);
157         dest.writeIntArray(mRecordTypeFilters);
158         dest.writeLong(mStartTime);
159         dest.writeLong(mEndTime);
160         dest.writeBoolean(mLocalTimeFilter);
161         dest.writeParcelable(mRecordIdFiltersParcel, 0);
162     }
163 
isLocalTimeFilter()164     public boolean isLocalTimeFilter() {
165         return mLocalTimeFilter;
166     }
167 
usesNonIdFilters()168     public boolean usesNonIdFilters() {
169         return mRecordTypeFilters.length != 0
170                 || mStartTime != DEFAULT_LONG
171                 || mEndTime != DEFAULT_LONG;
172     }
173 }
174