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