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.wifi; 18 19 import android.app.StatsManager; 20 import android.content.Context; 21 import android.content.pm.PackageInfo; 22 import android.content.pm.PackageManager; 23 import android.net.wifi.WifiConfiguration; 24 import android.net.wifi.WifiManager; 25 import android.net.wifi.WifiNetworkSuggestion; 26 import android.net.wifi.WifiSsid; 27 import android.os.Handler; 28 import android.os.Process; 29 import android.util.Log; 30 import android.util.StatsEvent; 31 32 import com.android.server.wifi.proto.WifiStatsLog; 33 34 import java.util.List; 35 import java.util.Set; 36 37 /** 38 * This is used to log pulled atoms to StatsD via Callback. 39 */ 40 public class WifiPulledAtomLogger { 41 public static final String WIFI_BUILD_FROM_SOURCE_PACKAGE_NAME = "com.android.wifi"; 42 private static final String WIFI_PACKAGE_NAME_SUFFIX = ".android.wifi"; 43 private int mWifiBuildType = 0; 44 45 private static final String TAG = "WifiPulledAtomLogger"; 46 private final StatsManager mStatsManager; 47 private final Handler mWifiHandler; 48 private final Context mContext; 49 private final WifiInjector mWifiInjector; 50 private StatsManager.StatsPullAtomCallback mStatsPullAtomCallback; 51 52 private int mApexVersionNumber = -1; 53 WifiPulledAtomLogger(StatsManager statsManager, Handler handler, Context context, WifiInjector wifiInjector)54 public WifiPulledAtomLogger(StatsManager statsManager, Handler handler, Context context, 55 WifiInjector wifiInjector) { 56 mStatsManager = statsManager; 57 mWifiHandler = handler; 58 mStatsPullAtomCallback = new WifiPullAtomCallback(); 59 mContext = context; 60 mWifiInjector = wifiInjector; 61 } 62 63 /** 64 * Set up an atom to get pulled. 65 * @param atomTag 66 */ setPullAtomCallback(int atomTag)67 public void setPullAtomCallback(int atomTag) { 68 if (mStatsManager == null) { 69 Log.e(TAG, "StatsManager is null. Failed to set wifi pull atom callback for atomTag=" 70 + atomTag); 71 return; 72 } 73 mStatsManager.setPullAtomCallback( 74 atomTag, 75 null, // use default meta data values 76 command -> mWifiHandler.post(command), // Executor posting to wifi handler thread 77 mStatsPullAtomCallback 78 ); 79 } 80 81 /** 82 * Implementation of StatsPullAtomCallback. This will check the atom tag and log data 83 * correspondingly. 84 */ 85 public class WifiPullAtomCallback implements StatsManager.StatsPullAtomCallback { 86 @Override onPullAtom(int atomTag, List<StatsEvent> data)87 public int onPullAtom(int atomTag, List<StatsEvent> data) { 88 switch (atomTag) { 89 case WifiStatsLog.WIFI_MODULE_INFO: 90 return handleWifiVersionPull(atomTag, data); 91 case WifiStatsLog.WIFI_SETTING_INFO: 92 return handleWifiSettingsPull(atomTag, data); 93 case WifiStatsLog.WIFI_COMPLEX_SETTING_INFO: 94 return handleWifiComplexSettingsPull(atomTag, data); 95 case WifiStatsLog.WIFI_CONFIGURED_NETWORK_INFO: 96 return handleWifiConfiguredNetworkInfoPull(atomTag, data); 97 default: 98 return StatsManager.PULL_SKIP; 99 } 100 } 101 } 102 handleWifiVersionPull(int atomTag, List<StatsEvent> data)103 private int handleWifiVersionPull(int atomTag, List<StatsEvent> data) { 104 if (mWifiBuildType != 0) { 105 // build type already cached. No need to get it again. 106 data.add(WifiStatsLog.buildStatsEvent(atomTag, mApexVersionNumber, mWifiBuildType)); 107 return StatsManager.PULL_SUCCESS; 108 } 109 PackageManager pm = mContext.getPackageManager(); 110 if (pm == null) { 111 Log.e(TAG, "Failed to get package manager"); 112 return StatsManager.PULL_SKIP; 113 } 114 updateBuildTypeAndVersionCode(pm); 115 116 data.add(WifiStatsLog.buildStatsEvent(atomTag, mApexVersionNumber, mWifiBuildType)); 117 return StatsManager.PULL_SUCCESS; 118 } 119 handleWifiSettingsPull(int atomTag, List<StatsEvent> data)120 private int handleWifiSettingsPull(int atomTag, List<StatsEvent> data) { 121 WifiSettingsStore settingsStore = mWifiInjector.getWifiSettingsStore(); 122 data.add(WifiStatsLog.buildStatsEvent(atomTag, 123 WifiStatsLog.WIFI_SETTING_INFO__SETTING_NAME__WIFI_SCAN_ALWAYS_AVAILABLE, 124 settingsStore.isScanAlwaysAvailable())); 125 data.add(WifiStatsLog.buildStatsEvent(atomTag, 126 WifiStatsLog.WIFI_SETTING_INFO__SETTING_NAME__WIFI_SCAN_THROTTLE, 127 settingsStore.isWifiScanThrottleEnabled())); 128 data.add(WifiStatsLog.buildStatsEvent(atomTag, 129 WifiStatsLog.WIFI_SETTING_INFO__SETTING_NAME__WIFI_SCORING, 130 settingsStore.isWifiScoringEnabled())); 131 data.add(WifiStatsLog.buildStatsEvent(atomTag, 132 WifiStatsLog.WIFI_SETTING_INFO__SETTING_NAME__WIFI_PASSPOINT, 133 settingsStore.isWifiPasspointEnabled())); 134 135 boolean nonPersistentMacRandEnabled = mWifiInjector.getFrameworkFacade().getIntegerSetting( 136 mContext, 137 WifiConfigManager.NON_PERSISTENT_MAC_RANDOMIZATION_FEATURE_FORCE_ENABLE_FLAG, 0) 138 == 1 ? true : false; 139 data.add(WifiStatsLog.buildStatsEvent(atomTag, 140 WifiStatsLog.WIFI_SETTING_INFO__SETTING_NAME__WIFI_ENHANCED_MAC_RANDOMIZATION, 141 nonPersistentMacRandEnabled)); 142 143 data.add(WifiStatsLog.buildStatsEvent(atomTag, 144 WifiStatsLog.WIFI_SETTING_INFO__SETTING_NAME__WIFI_WAKE, 145 mWifiInjector.getWakeupController().isEnabled())); 146 data.add(WifiStatsLog.buildStatsEvent(atomTag, 147 WifiStatsLog.WIFI_SETTING_INFO__SETTING_NAME__WIFI_NETWORKS_AVAILABLE_NOTIFICATION, 148 mWifiInjector.getOpenNetworkNotifier().isSettingEnabled())); 149 data.add(WifiStatsLog.buildStatsEvent(atomTag, 150 WifiStatsLog.WIFI_SETTING_INFO__SETTING_NAME__LOCATION_MODE, 151 mWifiInjector.getWifiPermissionsUtil().isLocationModeEnabled())); 152 return StatsManager.PULL_SUCCESS; 153 } 154 frameworkToAtomMultiInternetMode( @ifiManager.WifiMultiInternetMode int mode)155 private static int frameworkToAtomMultiInternetMode( 156 @WifiManager.WifiMultiInternetMode int mode) { 157 switch (mode) { 158 case WifiManager.WIFI_MULTI_INTERNET_MODE_DISABLED: 159 return WifiStatsLog 160 .WIFI_COMPLEX_SETTING_INFO__MULTI_INTERNET_MODE__MULTI_INTERNET_MODE_DISABLED; 161 case WifiManager.WIFI_MULTI_INTERNET_MODE_DBS_AP: 162 return WifiStatsLog 163 .WIFI_COMPLEX_SETTING_INFO__MULTI_INTERNET_MODE__MULTI_INTERNET_MODE_DBS_AP; 164 case WifiManager.WIFI_MULTI_INTERNET_MODE_MULTI_AP: 165 return WifiStatsLog 166 .WIFI_COMPLEX_SETTING_INFO__MULTI_INTERNET_MODE__MULTI_INTERNET_MODE_MULTI_AP; 167 default: 168 Log.i(TAG, "Invalid multi-internet mode: " + mode); 169 return -1; 170 } 171 } 172 handleWifiComplexSettingsPull(int atomTag, List<StatsEvent> data)173 private int handleWifiComplexSettingsPull(int atomTag, List<StatsEvent> data) { 174 int multiInternetMode = frameworkToAtomMultiInternetMode( 175 mWifiInjector.getWifiSettingsStore().getWifiMultiInternetMode()); 176 if (multiInternetMode == -1) { 177 return StatsManager.PULL_SKIP; 178 } 179 data.add(WifiStatsLog.buildStatsEvent(atomTag, multiInternetMode)); 180 return StatsManager.PULL_SUCCESS; 181 } 182 updateBuildTypeAndVersionCode(PackageManager pm)183 private void updateBuildTypeAndVersionCode(PackageManager pm) { 184 // Query build type and cache if not already cached. 185 List<PackageInfo> packageInfos = pm.getInstalledPackages(PackageManager.MATCH_APEX); 186 boolean found = false; 187 String wifiPackageName = null; 188 for (PackageInfo packageInfo : packageInfos) { 189 if (packageInfo.packageName.endsWith(WIFI_PACKAGE_NAME_SUFFIX)) { 190 mApexVersionNumber = (int) packageInfo.getLongVersionCode(); 191 wifiPackageName = packageInfo.packageName; 192 if (packageInfo.packageName.equals(WIFI_BUILD_FROM_SOURCE_PACKAGE_NAME)) { 193 found = true; 194 } 195 break; 196 } 197 } 198 mWifiBuildType = found 199 ? WifiStatsLog.WIFI_MODULE_INFO__BUILD_TYPE__TYPE_BUILT_FROM_SOURCE 200 : WifiStatsLog.WIFI_MODULE_INFO__BUILD_TYPE__TYPE_PREBUILT; 201 Log.i(TAG, "Wifi Module package name is " + wifiPackageName 202 + ", version is " + mApexVersionNumber); 203 } 204 configHasUtf8Ssid(WifiConfiguration config)205 private static boolean configHasUtf8Ssid(WifiConfiguration config) { 206 return WifiSsid.fromString(config.SSID).getUtf8Text() != null; 207 } 208 wifiConfigToStatsEvent( int atomTag, WifiConfiguration config, boolean isSuggestion)209 private StatsEvent wifiConfigToStatsEvent( 210 int atomTag, WifiConfiguration config, boolean isSuggestion) { 211 return WifiStatsLog.buildStatsEvent( 212 atomTag, 213 0, // deprecated network ID field 214 config.isEnterprise(), 215 config.hiddenSSID, 216 config.isPasspoint(), 217 isSuggestion, 218 configHasUtf8Ssid(config), 219 mWifiInjector.getSsidTranslator().isSsidTranslationEnabled(), 220 false, // legacy TOFU field 221 !config.getNetworkSelectionStatus().hasNeverDetectedCaptivePortal(), 222 config.allowAutojoin, 223 WifiMetrics.convertSecurityModeToProto(config), 224 WifiMetrics.convertMacRandomizationToProto(config.getMacRandomizationSetting()), 225 WifiMetrics.convertMeteredOverrideToProto(config.meteredOverride), 226 WifiMetrics.convertEapMethodToProto(config), 227 WifiMetrics.convertEapInnerMethodToProto(config), 228 WifiMetrics.isFreeOpenRoaming(config), 229 WifiMetrics.isSettledOpenRoaming(config), 230 WifiMetrics.convertTofuConnectionStateToProto(config), 231 WifiMetrics.convertTofuDialogStateToProto(config)); 232 } 233 handleWifiConfiguredNetworkInfoPull(int atomTag, List<StatsEvent> data)234 private int handleWifiConfiguredNetworkInfoPull(int atomTag, List<StatsEvent> data) { 235 List<WifiConfiguration> savedConfigs = 236 mWifiInjector.getWifiConfigManager().getSavedNetworks(Process.WIFI_UID); 237 for (WifiConfiguration config : savedConfigs) { 238 if (!config.isPasspoint()) { 239 data.add(wifiConfigToStatsEvent(atomTag, config, false)); 240 } 241 } 242 243 Set<WifiNetworkSuggestion> approvedSuggestions = 244 mWifiInjector.getWifiNetworkSuggestionsManager().getAllApprovedNetworkSuggestions(); 245 for (WifiNetworkSuggestion suggestion : approvedSuggestions) { 246 WifiConfiguration config = suggestion.getWifiConfiguration(); 247 if (!config.isPasspoint()) { 248 data.add(wifiConfigToStatsEvent(atomTag, config, true)); 249 } 250 } 251 252 List<WifiConfiguration> passpointConfigs = 253 mWifiInjector.getPasspointManager().getWifiConfigsForPasspointProfiles(false); 254 for (WifiConfiguration config : passpointConfigs) { 255 data.add(wifiConfigToStatsEvent(atomTag, config, false)); 256 } 257 258 List<WifiConfiguration> passpointSuggestions = 259 mWifiInjector.getWifiNetworkSuggestionsManager() 260 .getAllPasspointScanOptimizationSuggestionNetworks(false); 261 for (WifiConfiguration config : passpointSuggestions) { 262 data.add(wifiConfigToStatsEvent(atomTag, config, true)); 263 } 264 265 return StatsManager.PULL_SUCCESS; 266 } 267 } 268