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