• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 com.android.server.healthconnect.storage.request;
18 
19 import android.annotation.NonNull;
20 import android.health.connect.AggregateRecordsResponse;
21 import android.health.connect.AggregateResult;
22 import android.health.connect.TimeRangeFilter;
23 import android.health.connect.aidl.AggregateDataRequestParcel;
24 import android.health.connect.aidl.AggregateDataResponseParcel;
25 import android.health.connect.datatypes.AggregationType;
26 import android.health.connect.internal.datatypes.utils.AggregationTypeIdMapper;
27 import android.util.ArrayMap;
28 
29 import com.android.server.healthconnect.storage.TransactionManager;
30 import com.android.server.healthconnect.storage.datatypehelpers.RecordHelper;
31 import com.android.server.healthconnect.storage.utils.RecordHelperProvider;
32 
33 import java.time.Duration;
34 import java.time.Period;
35 import java.util.ArrayList;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Objects;
39 
40 /**
41  * Refines aggregate request from what the client sent to a format that makes the most sense for the
42  * TransactionManager.
43  *
44  * @hide
45  */
46 public final class AggregateTransactionRequest {
47     private final String mPackageName;
48     private final List<AggregateTableRequest> mAggregateTableRequests;
49     private final Period mPeriod;
50     private final Duration mDuration;
51     private final TimeRangeFilter mTimeRangeFilter;
52 
AggregateTransactionRequest( @onNull String packageName, @NonNull AggregateDataRequestParcel request, long startDateAccess)53     public AggregateTransactionRequest(
54             @NonNull String packageName,
55             @NonNull AggregateDataRequestParcel request,
56             long startDateAccess) {
57         mPackageName = packageName;
58         mAggregateTableRequests = new ArrayList<>(request.getAggregateIds().length);
59         mPeriod = request.getPeriod();
60         mDuration = request.getDuration();
61         mTimeRangeFilter = request.getTimeRangeFilter();
62 
63         final AggregationTypeIdMapper aggregationTypeIdMapper =
64                 AggregationTypeIdMapper.getInstance();
65         for (int id : request.getAggregateIds()) {
66             AggregationType<?> aggregationType = aggregationTypeIdMapper.getAggregationTypeFor(id);
67             List<Integer> recordTypeIds = aggregationType.getApplicableRecordTypeIds();
68             if (recordTypeIds.size() == 1) {
69                 RecordHelper<?> recordHelper =
70                         RecordHelperProvider.getRecordHelper(recordTypeIds.get(0));
71                 AggregateTableRequest aggregateTableRequest =
72                         recordHelper.getAggregateTableRequest(
73                                 aggregationType,
74                                 packageName,
75                                 request.getPackageFilters(),
76                                 request.getStartTime(),
77                                 request.getEndTime(),
78                                 startDateAccess,
79                                 request.useLocalTimeFilter());
80 
81                 if (mDuration != null || mPeriod != null) {
82                     aggregateTableRequest.setGroupBy(
83                             recordHelper.getDurationGroupByColumnName(),
84                             mPeriod,
85                             mDuration,
86                             mTimeRangeFilter);
87                 }
88                 mAggregateTableRequests.add(aggregateTableRequest);
89             } else {
90                 throw new UnsupportedOperationException();
91             }
92         }
93     }
94 
95     @NonNull
getPackageName()96     public String getPackageName() {
97         return mPackageName;
98     }
99 
100     /**
101      * @return Compute and return aggregations
102      */
getAggregateDataResponseParcel()103     public AggregateDataResponseParcel getAggregateDataResponseParcel() {
104         Map<AggregationType<?>, List<AggregateResult<?>>> results = new ArrayMap<>();
105         for (AggregateTableRequest aggregateTableRequest : mAggregateTableRequests) {
106             // Compute aggregations
107             TransactionManager.getInitialisedInstance()
108                     .populateWithAggregation(aggregateTableRequest);
109             results.put(
110                     aggregateTableRequest.getAggregationType(),
111                     aggregateTableRequest.getAggregateResults());
112         }
113 
114         // Convert DB friendly results to aggregateRecordsResponses
115         int responseSize =
116                 mAggregateTableRequests.isEmpty()
117                         ? 0
118                         : mAggregateTableRequests.get(0).getAggregateResults().size();
119         List<AggregateRecordsResponse<?>> aggregateRecordsResponses = new ArrayList<>(responseSize);
120         for (int i = 0; i < responseSize; i++) {
121             Map<Integer, AggregateResult<?>> aggregateResultMap = new ArrayMap<>();
122             for (AggregationType<?> aggregationType : results.keySet()) {
123                 aggregateResultMap.put(
124                         (AggregationTypeIdMapper.getInstance().getIdFor(aggregationType)),
125                         Objects.requireNonNull(results.get(aggregationType)).get(i));
126             }
127             aggregateRecordsResponses.add(new AggregateRecordsResponse<>(aggregateResultMap));
128         }
129 
130         // Create and return parcel
131         AggregateDataResponseParcel aggregateDataResponseParcel =
132                 new AggregateDataResponseParcel(aggregateRecordsResponses);
133         if (mPeriod != null) {
134             aggregateDataResponseParcel.setPeriod(mPeriod, mTimeRangeFilter);
135         } else if (mDuration != null) {
136             aggregateDataResponseParcel.setDuration(mDuration, mTimeRangeFilter);
137         }
138 
139         return aggregateDataResponseParcel;
140     }
141 }
142