• 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 com.android.server.healthconnect.logging;
18 
19 import android.health.HealthFitnessStatsLog;
20 
21 import com.android.healthfitness.flags.AconfigFlagHelper;
22 import com.android.server.healthconnect.storage.utils.InternalHealthConnectMappings;
23 
24 import java.util.Map;
25 import java.util.Set;
26 
27 /**
28  * Class to log Health Connect Ecosystem metrics every 24hrs.
29  *
30  * @hide
31  */
32 class EcosystemStatsLogger {
33 
34     private final HealthFitnessStatsLog mStatsLog;
35 
EcosystemStatsLogger(HealthFitnessStatsLog statsLog)36     EcosystemStatsLogger(HealthFitnessStatsLog statsLog) {
37         mStatsLog = statsLog;
38     }
39 
40     /** Write Health Connect Ecosystem stats to statsd. */
log(EcosystemStatsCollector ecosystemStatsCollector)41     void log(EcosystemStatsCollector ecosystemStatsCollector) {
42         if (!AconfigFlagHelper.isEcosystemMetricsEnabled()) {
43             return;
44         }
45         ecosystemStatsCollector.processReadAccessLogs();
46 
47         logDirectionalAppPairings(ecosystemStatsCollector);
48         logDirectionalAppPairingsPerDataType(ecosystemStatsCollector);
49 
50         mStatsLog.write(
51                 HealthFitnessStatsLog.HEALTH_CONNECT_ECOSYSTEM_STATS,
52                 convertRecordTypeIdSetToLoggableArray(
53                         ecosystemStatsCollector.getDataTypesReadOrWritten()),
54                 convertRecordTypeIdSetToLoggableArray(ecosystemStatsCollector.getDataTypesRead()),
55                 convertRecordTypeIdSetToLoggableArray(
56                         ecosystemStatsCollector.getDataTypesWritten()),
57                 convertRecordTypeIdSetToLoggableArray(ecosystemStatsCollector.getDataTypeShared()),
58                 ecosystemStatsCollector.getNumberOfAppPairings());
59     }
60 
logDirectionalAppPairings(EcosystemStatsCollector ecosystemStatsCollector)61     private void logDirectionalAppPairings(EcosystemStatsCollector ecosystemStatsCollector) {
62         Map<String, Set<String>> directionalAppPairings =
63                 ecosystemStatsCollector.getDirectionalAppPairings();
64 
65         for (Map.Entry<String, Set<String>> directionalAppPairing :
66                 directionalAppPairings.entrySet()) {
67             String writerPackageName = directionalAppPairing.getKey();
68             for (String readerPackageName : directionalAppPairing.getValue()) {
69                 mStatsLog.write(
70                         HealthFitnessStatsLog.HEALTH_CONNECT_RESTRICTED_ECOSYSTEM_STATS,
71                         writerPackageName,
72                         readerPackageName,
73                         HealthFitnessStatsLog
74                                 .HEALTH_CONNECT_RESTRICTED_ECOSYSTEM_STATS__DATA_TYPE__DATA_TYPE_UNKNOWN,
75                         HealthFitnessStatsLog
76                                 .HEALTH_CONNECT_RESTRICTED_ECOSYSTEM_STATS__METRIC_TYPE__METRIC_TYPE_DIRECTIONAL_PAIRING);
77             }
78         }
79     }
80 
logDirectionalAppPairingsPerDataType( EcosystemStatsCollector ecosystemStatsCollector)81     private void logDirectionalAppPairingsPerDataType(
82             EcosystemStatsCollector ecosystemStatsCollector) {
83         Map<String, Map<Integer, Set<String>>> directionalAppPairingsForDataTypes =
84                 ecosystemStatsCollector.getDirectionalAppPairingsPerDataType();
85         InternalHealthConnectMappings internalHealthConnectMappings =
86                 InternalHealthConnectMappings.getInstance();
87 
88         for (Map.Entry<String, Map<Integer, Set<String>>> directionalAppPairingsPerDataType :
89                 directionalAppPairingsForDataTypes.entrySet()) {
90             String writerPackageName = directionalAppPairingsPerDataType.getKey();
91             for (Map.Entry<Integer, Set<String>> dataTypeToReaderPackageName :
92                     directionalAppPairingsPerDataType.getValue().entrySet()) {
93                 int dataType =
94                         internalHealthConnectMappings.getLoggingEnumForRecordTypeId(
95                                 dataTypeToReaderPackageName.getKey());
96                 for (String readerPackageName : dataTypeToReaderPackageName.getValue()) {
97                     mStatsLog.write(
98                             HealthFitnessStatsLog.HEALTH_CONNECT_RESTRICTED_ECOSYSTEM_STATS,
99                             writerPackageName,
100                             readerPackageName,
101                             dataType,
102                             HealthFitnessStatsLog
103                                     .HEALTH_CONNECT_RESTRICTED_ECOSYSTEM_STATS__METRIC_TYPE__METRIC_TYPE_DIRECTIONAL_PAIRING_PER_DATA_TYPE);
104                 }
105             }
106         }
107     }
108 
convertRecordTypeIdSetToLoggableArray(Set<Integer> recordTypeIds)109     private static int[] convertRecordTypeIdSetToLoggableArray(Set<Integer> recordTypeIds) {
110         InternalHealthConnectMappings internalHealthConnectMappings =
111                 InternalHealthConnectMappings.getInstance();
112         int[] loggableRecordTypeIds = new int[recordTypeIds.size()];
113 
114         int i = 0;
115         for (Integer recordTyeId : recordTypeIds) {
116             loggableRecordTypeIds[i++] =
117                     internalHealthConnectMappings.getLoggingEnumForRecordTypeId(recordTyeId);
118         }
119         return loggableRecordTypeIds;
120     }
121 }
122