summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Charlotte Lu <charlottelu@google.com> 2024-02-27 11:56:56 +0800
committer Charlotte Lu <charlottelu@google.com> 2024-02-29 07:24:21 +0000
commitef6c5ea0fb733a0a8f1170d7cdb19e1119e72f08 (patch)
treec85b3c81ccfd1910608702073831d7272bef59e0
parentf909a8f54159cc6db8cc1e7558543dedc28a22fa (diff)
Change WifiUtils.java into kotlin.
Test: Visual Test Fix: 327067271 Change-Id: Ieee2fe30080185fce458b1d331f1baf288c012c3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java447
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt462
2 files changed, 462 insertions, 447 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
deleted file mode 100644
index 69f83a4dfa3c..000000000000
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settingslib.wifi;
-
-import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED;
-import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.getMaxNetworkSelectionDisableReason;
-
-import static com.android.settingslib.flags.Flags.newStatusBarIcons;
-
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.drawable.Drawable;
-import android.icu.text.MessageFormat;
-import android.net.wifi.ScanResult;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
-import android.net.wifi.WifiInfo;
-import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo;
-import android.os.Bundle;
-import android.os.SystemClock;
-import android.util.Log;
-
-import androidx.annotation.VisibleForTesting;
-
-import com.android.settingslib.R;
-
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-public class WifiUtils {
-
- private static final String TAG = "WifiUtils";
-
- private static final int INVALID_RSSI = -127;
-
- /**
- * The intent action shows Wi-Fi dialog to connect Wi-Fi network.
- * <p>
- * Input: The calling package should put the chosen
- * com.android.wifitrackerlib.WifiEntry#getKey() to a string extra in the request bundle into
- * the {@link #EXTRA_CHOSEN_WIFI_ENTRY_KEY}.
- * <p>
- * Output: Nothing.
- */
- @VisibleForTesting
- static final String ACTION_WIFI_DIALOG = "com.android.settings.WIFI_DIALOG";
-
- /**
- * Specify a key that indicates the WifiEntry to be configured.
- */
- @VisibleForTesting
- static final String EXTRA_CHOSEN_WIFI_ENTRY_KEY = "key_chosen_wifientry_key";
-
- /**
- * The lookup key for a boolean that indicates whether a chosen WifiEntry request to connect to.
- * {@code true} means a chosen WifiEntry request to connect to.
- */
- @VisibleForTesting
- static final String EXTRA_CONNECT_FOR_CALLER = "connect_for_caller";
-
- /**
- * The intent action shows network details settings to allow configuration of Wi-Fi.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: The calling package should put the chosen
- * com.android.wifitrackerlib.WifiEntry#getKey() to a string extra in the request bundle into
- * the {@link #KEY_CHOSEN_WIFIENTRY_KEY}.
- * <p>
- * Output: Nothing.
- */
- public static final String ACTION_WIFI_DETAILS_SETTINGS =
- "android.settings.WIFI_DETAILS_SETTINGS";
- public static final String KEY_CHOSEN_WIFIENTRY_KEY = "key_chosen_wifientry_key";
- public static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":settings:show_fragment_args";
-
- static final int[] WIFI_PIE = getIconsBasedOnFlag();
-
- private static int[] getIconsBasedOnFlag() {
- if (newStatusBarIcons()) {
- return new int[] {
- R.drawable.ic_wifi_0,
- R.drawable.ic_wifi_1,
- R.drawable.ic_wifi_2,
- R.drawable.ic_wifi_3,
- R.drawable.ic_wifi_4
- };
- } else {
- return new int[] {
- com.android.internal.R.drawable.ic_wifi_signal_0,
- com.android.internal.R.drawable.ic_wifi_signal_1,
- com.android.internal.R.drawable.ic_wifi_signal_2,
- com.android.internal.R.drawable.ic_wifi_signal_3,
- com.android.internal.R.drawable.ic_wifi_signal_4
- };
- }
- }
-
- static final int[] NO_INTERNET_WIFI_PIE = getErrorIconsBasedOnFlag();
-
- private static int [] getErrorIconsBasedOnFlag() {
- if (newStatusBarIcons()) {
- return new int[] {
- R.drawable.ic_wifi_0_error,
- R.drawable.ic_wifi_1_error,
- R.drawable.ic_wifi_2_error,
- R.drawable.ic_wifi_3_error,
- R.drawable.ic_wifi_4_error
- };
- } else {
- return new int[] {
- R.drawable.ic_no_internet_wifi_signal_0,
- R.drawable.ic_no_internet_wifi_signal_1,
- R.drawable.ic_no_internet_wifi_signal_2,
- R.drawable.ic_no_internet_wifi_signal_3,
- R.drawable.ic_no_internet_wifi_signal_4
- };
- }
- }
-
- public static String buildLoggingSummary(AccessPoint accessPoint, WifiConfiguration config) {
- final StringBuilder summary = new StringBuilder();
- final WifiInfo info = accessPoint.getInfo();
- // Add RSSI/band information for this config, what was seen up to 6 seconds ago
- // verbose WiFi Logging is only turned on thru developers settings
- if (accessPoint.isActive() && info != null) {
- summary.append(" f=" + Integer.toString(info.getFrequency()));
- }
- summary.append(" " + getVisibilityStatus(accessPoint));
- if (config != null
- && (config.getNetworkSelectionStatus().getNetworkSelectionStatus()
- != NETWORK_SELECTION_ENABLED)) {
- summary.append(" (" + config.getNetworkSelectionStatus().getNetworkStatusString());
- if (config.getNetworkSelectionStatus().getDisableTime() > 0) {
- long now = System.currentTimeMillis();
- long diff = (now - config.getNetworkSelectionStatus().getDisableTime()) / 1000;
- long sec = diff % 60; //seconds
- long min = (diff / 60) % 60; //minutes
- long hour = (min / 60) % 60; //hours
- summary.append(", ");
- if (hour > 0) summary.append(Long.toString(hour) + "h ");
- summary.append(Long.toString(min) + "m ");
- summary.append(Long.toString(sec) + "s ");
- }
- summary.append(")");
- }
-
- if (config != null) {
- NetworkSelectionStatus networkStatus = config.getNetworkSelectionStatus();
- for (int reason = 0; reason <= getMaxNetworkSelectionDisableReason(); reason++) {
- if (networkStatus.getDisableReasonCounter(reason) != 0) {
- summary.append(" ")
- .append(NetworkSelectionStatus
- .getNetworkSelectionDisableReasonString(reason))
- .append("=")
- .append(networkStatus.getDisableReasonCounter(reason));
- }
- }
- }
-
- return summary.toString();
- }
-
- /**
- * Returns the visibility status of the WifiConfiguration.
- *
- * @return autojoin debugging information
- * TODO: use a string formatter
- * ["rssi 5Ghz", "num results on 5GHz" / "rssi 5Ghz", "num results on 5GHz"]
- * For instance [-40,5/-30,2]
- */
- @VisibleForTesting
- static String getVisibilityStatus(AccessPoint accessPoint) {
- final WifiInfo info = accessPoint.getInfo();
- StringBuilder visibility = new StringBuilder();
- StringBuilder scans24GHz = new StringBuilder();
- StringBuilder scans5GHz = new StringBuilder();
- StringBuilder scans60GHz = new StringBuilder();
- String bssid = null;
-
- if (accessPoint.isActive() && info != null) {
- bssid = info.getBSSID();
- if (bssid != null) {
- visibility.append(" ").append(bssid);
- }
- visibility.append(" standard = ").append(info.getWifiStandard());
- visibility.append(" rssi=").append(info.getRssi());
- visibility.append(" ");
- visibility.append(" score=").append(info.getScore());
- if (accessPoint.getSpeed() != AccessPoint.Speed.NONE) {
- visibility.append(" speed=").append(accessPoint.getSpeedLabel());
- }
- visibility.append(String.format(" tx=%.1f,", info.getSuccessfulTxPacketsPerSecond()));
- visibility.append(String.format("%.1f,", info.getRetriedTxPacketsPerSecond()));
- visibility.append(String.format("%.1f ", info.getLostTxPacketsPerSecond()));
- visibility.append(String.format("rx=%.1f", info.getSuccessfulRxPacketsPerSecond()));
- }
-
- int maxRssi5 = INVALID_RSSI;
- int maxRssi24 = INVALID_RSSI;
- int maxRssi60 = INVALID_RSSI;
- final int maxDisplayedScans = 4;
- int num5 = 0; // number of scanned BSSID on 5GHz band
- int num24 = 0; // number of scanned BSSID on 2.4Ghz band
- int num60 = 0; // number of scanned BSSID on 60Ghz band
- int numBlockListed = 0;
-
- // TODO: sort list by RSSI or age
- long nowMs = SystemClock.elapsedRealtime();
- for (ScanResult result : accessPoint.getScanResults()) {
- if (result == null) {
- continue;
- }
- if (result.frequency >= AccessPoint.LOWER_FREQ_5GHZ
- && result.frequency <= AccessPoint.HIGHER_FREQ_5GHZ) {
- // Strictly speaking: [4915, 5825]
- num5++;
-
- if (result.level > maxRssi5) {
- maxRssi5 = result.level;
- }
- if (num5 <= maxDisplayedScans) {
- scans5GHz.append(
- verboseScanResultSummary(accessPoint, result, bssid,
- nowMs));
- }
- } else if (result.frequency >= AccessPoint.LOWER_FREQ_24GHZ
- && result.frequency <= AccessPoint.HIGHER_FREQ_24GHZ) {
- // Strictly speaking: [2412, 2482]
- num24++;
-
- if (result.level > maxRssi24) {
- maxRssi24 = result.level;
- }
- if (num24 <= maxDisplayedScans) {
- scans24GHz.append(
- verboseScanResultSummary(accessPoint, result, bssid,
- nowMs));
- }
- } else if (result.frequency >= AccessPoint.LOWER_FREQ_60GHZ
- && result.frequency <= AccessPoint.HIGHER_FREQ_60GHZ) {
- // Strictly speaking: [60000, 61000]
- num60++;
-
- if (result.level > maxRssi60) {
- maxRssi60 = result.level;
- }
- if (num60 <= maxDisplayedScans) {
- scans60GHz.append(
- verboseScanResultSummary(accessPoint, result, bssid,
- nowMs));
- }
- }
- }
- visibility.append(" [");
- if (num24 > 0) {
- visibility.append("(").append(num24).append(")");
- if (num24 > maxDisplayedScans) {
- visibility.append("max=").append(maxRssi24).append(",");
- }
- visibility.append(scans24GHz.toString());
- }
- visibility.append(";");
- if (num5 > 0) {
- visibility.append("(").append(num5).append(")");
- if (num5 > maxDisplayedScans) {
- visibility.append("max=").append(maxRssi5).append(",");
- }
- visibility.append(scans5GHz.toString());
- }
- visibility.append(";");
- if (num60 > 0) {
- visibility.append("(").append(num60).append(")");
- if (num60 > maxDisplayedScans) {
- visibility.append("max=").append(maxRssi60).append(",");
- }
- visibility.append(scans60GHz.toString());
- }
- if (numBlockListed > 0) {
- visibility.append("!").append(numBlockListed);
- }
- visibility.append("]");
-
- return visibility.toString();
- }
-
- @VisibleForTesting
- /* package */ static String verboseScanResultSummary(AccessPoint accessPoint, ScanResult result,
- String bssid, long nowMs) {
- StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.append(" \n{").append(result.BSSID);
- if (result.BSSID.equals(bssid)) {
- stringBuilder.append("*");
- }
- stringBuilder.append("=").append(result.frequency);
- stringBuilder.append(",").append(result.level);
- int speed = getSpecificApSpeed(result, accessPoint.getScoredNetworkCache());
- if (speed != AccessPoint.Speed.NONE) {
- stringBuilder.append(",")
- .append(accessPoint.getSpeedLabel(speed));
- }
- int ageSeconds = (int) (nowMs - result.timestamp / 1000) / 1000;
- stringBuilder.append(",").append(ageSeconds).append("s");
- stringBuilder.append("}");
- return stringBuilder.toString();
- }
-
- @AccessPoint.Speed
- private static int getSpecificApSpeed(ScanResult result,
- Map<String, TimestampedScoredNetwork> scoredNetworkCache) {
- TimestampedScoredNetwork timedScore = scoredNetworkCache.get(result.BSSID);
- if (timedScore == null) {
- return AccessPoint.Speed.NONE;
- }
- // For debugging purposes we may want to use mRssi rather than result.level as the average
- // speed wil be determined by mRssi
- return timedScore.getScore().calculateBadge(result.level);
- }
-
- public static String getMeteredLabel(Context context, WifiConfiguration config) {
- // meteredOverride is whether the user manually set the metered setting or not.
- // meteredHint is whether the network itself is telling us that it is metered
- if (config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_METERED
- || (config.meteredHint && !isMeteredOverridden(config))) {
- return context.getString(R.string.wifi_metered_label);
- }
- return context.getString(R.string.wifi_unmetered_label);
- }
-
- /**
- * Returns the Internet icon resource for a given RSSI level.
- *
- * @param level The number of bars to show (0-4)
- * @param noInternet True if a connected Wi-Fi network cannot access the Internet
- */
- public static int getInternetIconResource(int level, boolean noInternet) {
- int wifiLevel = level;
- if (wifiLevel < 0) {
- Log.e(TAG, "Wi-Fi level is out of range! level:" + level);
- wifiLevel = 0;
- } else if (level >= WIFI_PIE.length) {
- Log.e(TAG, "Wi-Fi level is out of range! level:" + level);
- wifiLevel = WIFI_PIE.length - 1;
- }
- return noInternet ? NO_INTERNET_WIFI_PIE[wifiLevel] : WIFI_PIE[wifiLevel];
- }
-
- /**
- * Returns the Hotspot network icon resource.
- *
- * @param deviceType The device type of Hotspot network
- */
- public static int getHotspotIconResource(int deviceType) {
- return switch (deviceType) {
- case NetworkProviderInfo.DEVICE_TYPE_PHONE -> R.drawable.ic_hotspot_phone;
- case NetworkProviderInfo.DEVICE_TYPE_TABLET -> R.drawable.ic_hotspot_tablet;
- case NetworkProviderInfo.DEVICE_TYPE_LAPTOP -> R.drawable.ic_hotspot_laptop;
- case NetworkProviderInfo.DEVICE_TYPE_WATCH -> R.drawable.ic_hotspot_watch;
- case NetworkProviderInfo.DEVICE_TYPE_AUTO -> R.drawable.ic_hotspot_auto;
- default -> R.drawable.ic_hotspot_phone; // Return phone icon as default.
- };
- }
-
- /**
- * Wrapper the {@link #getInternetIconResource} for testing compatibility.
- */
- public static class InternetIconInjector {
-
- protected final Context mContext;
-
- public InternetIconInjector(Context context) {
- mContext = context;
- }
-
- /**
- * Returns the Internet icon for a given RSSI level.
- *
- * @param noInternet True if a connected Wi-Fi network cannot access the Internet
- * @param level The number of bars to show (0-4)
- */
- public Drawable getIcon(boolean noInternet, int level) {
- return mContext.getDrawable(WifiUtils.getInternetIconResource(level, noInternet));
- }
- }
-
- public static boolean isMeteredOverridden(WifiConfiguration config) {
- return config.meteredOverride != WifiConfiguration.METERED_OVERRIDE_NONE;
- }
-
- /**
- * Returns the Intent for Wi-Fi dialog.
- *
- * @param key The Wi-Fi entry key
- * @param connectForCaller True if a chosen WifiEntry request to connect to
- */
- public static Intent getWifiDialogIntent(String key, boolean connectForCaller) {
- final Intent intent = new Intent(ACTION_WIFI_DIALOG);
- intent.putExtra(EXTRA_CHOSEN_WIFI_ENTRY_KEY, key);
- intent.putExtra(EXTRA_CONNECT_FOR_CALLER, connectForCaller);
- return intent;
- }
-
- /**
- * Returns the Intent for Wi-Fi network details settings.
- *
- * @param key The Wi-Fi entry key
- */
- public static Intent getWifiDetailsSettingsIntent(String key) {
- final Intent intent = new Intent(ACTION_WIFI_DETAILS_SETTINGS);
- final Bundle bundle = new Bundle();
- bundle.putString(KEY_CHOSEN_WIFIENTRY_KEY, key);
- intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, bundle);
- return intent;
- }
-
- /**
- * Returns the string of Wi-Fi tethering summary for connected devices.
- *
- * @param context The application context
- * @param connectedDevices The count of connected devices
- */
- public static String getWifiTetherSummaryForConnectedDevices(Context context,
- int connectedDevices) {
- MessageFormat msgFormat = new MessageFormat(
- context.getResources().getString(R.string.wifi_tether_connected_summary),
- Locale.getDefault());
- Map<String, Object> arguments = new HashMap<>();
- arguments.put("count", connectedDevices);
- return msgFormat.format(arguments);
- }
-}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt
new file mode 100644
index 000000000000..7d614f0e4d39
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt
@@ -0,0 +1,462 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.wifi
+
+import android.content.Context
+import android.content.Intent
+import android.graphics.drawable.Drawable
+import android.icu.text.MessageFormat
+import android.net.wifi.ScanResult
+import android.net.wifi.WifiConfiguration
+import android.net.wifi.WifiConfiguration.NetworkSelectionStatus
+import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo
+import android.os.Bundle
+import android.os.SystemClock
+import android.util.Log
+import androidx.annotation.VisibleForTesting
+import com.android.settingslib.R
+import com.android.settingslib.flags.Flags.newStatusBarIcons
+import java.util.Locale
+
+
+open class WifiUtils {
+ /**
+ * Wrapper the [.getInternetIconResource] for testing compatibility.
+ */
+ class InternetIconInjector(protected val context: Context) {
+ /**
+ * Returns the Internet icon for a given RSSI level.
+ *
+ * @param noInternet True if a connected Wi-Fi network cannot access the Internet
+ * @param level The number of bars to show (0-4)
+ */
+ fun getIcon(noInternet: Boolean, level: Int): Drawable? {
+ return context.getDrawable(getInternetIconResource(level, noInternet))
+ }
+ }
+
+ companion object {
+ private const val TAG = "WifiUtils"
+ private const val INVALID_RSSI = -127
+
+ /**
+ * The intent action shows Wi-Fi dialog to connect Wi-Fi network.
+ *
+ *
+ * Input: The calling package should put the chosen
+ * com.android.wifitrackerlib.WifiEntry#getKey() to a string extra in the request bundle into
+ * the [.EXTRA_CHOSEN_WIFI_ENTRY_KEY].
+ *
+ *
+ * Output: Nothing.
+ */
+ @JvmField
+ @VisibleForTesting
+ val ACTION_WIFI_DIALOG = "com.android.settings.WIFI_DIALOG"
+
+ /**
+ * Specify a key that indicates the WifiEntry to be configured.
+ */
+ @JvmField
+ @VisibleForTesting
+ val EXTRA_CHOSEN_WIFI_ENTRY_KEY = "key_chosen_wifientry_key"
+
+ /**
+ * The lookup key for a boolean that indicates whether a chosen WifiEntry request to connect to.
+ * `true` means a chosen WifiEntry request to connect to.
+ */
+ @JvmField
+ @VisibleForTesting
+ val EXTRA_CONNECT_FOR_CALLER = "connect_for_caller"
+
+ /**
+ * The intent action shows network details settings to allow configuration of Wi-Fi.
+ *
+ *
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ *
+ *
+ * Input: The calling package should put the chosen
+ * com.android.wifitrackerlib.WifiEntry#getKey() to a string extra in the request bundle into
+ * the [.KEY_CHOSEN_WIFIENTRY_KEY].
+ *
+ *
+ * Output: Nothing.
+ */
+ const val ACTION_WIFI_DETAILS_SETTINGS = "android.settings.WIFI_DETAILS_SETTINGS"
+ const val KEY_CHOSEN_WIFIENTRY_KEY = "key_chosen_wifientry_key"
+ const val EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":settings:show_fragment_args"
+
+ @JvmField
+ val WIFI_PIE = getIconsBasedOnFlag()
+
+ private fun getIconsBasedOnFlag(): IntArray {
+ return if (newStatusBarIcons()) {
+ intArrayOf(
+ R.drawable.ic_wifi_0,
+ R.drawable.ic_wifi_1,
+ R.drawable.ic_wifi_2,
+ R.drawable.ic_wifi_3,
+ R.drawable.ic_wifi_4
+ )
+ } else {
+ intArrayOf(
+ com.android.internal.R.drawable.ic_wifi_signal_0,
+ com.android.internal.R.drawable.ic_wifi_signal_1,
+ com.android.internal.R.drawable.ic_wifi_signal_2,
+ com.android.internal.R.drawable.ic_wifi_signal_3,
+ com.android.internal.R.drawable.ic_wifi_signal_4
+ )
+ }
+ }
+
+ val NO_INTERNET_WIFI_PIE = getErrorIconsBasedOnFlag()
+
+ private fun getErrorIconsBasedOnFlag(): IntArray {
+ return if (newStatusBarIcons()) {
+ intArrayOf(
+ R.drawable.ic_wifi_0_error,
+ R.drawable.ic_wifi_1_error,
+ R.drawable.ic_wifi_2_error,
+ R.drawable.ic_wifi_3_error,
+ R.drawable.ic_wifi_4_error
+ )
+ } else {
+ intArrayOf(
+ R.drawable.ic_no_internet_wifi_signal_0,
+ R.drawable.ic_no_internet_wifi_signal_1,
+ R.drawable.ic_no_internet_wifi_signal_2,
+ R.drawable.ic_no_internet_wifi_signal_3,
+ R.drawable.ic_no_internet_wifi_signal_4
+ )
+ }
+ }
+
+
+ @JvmStatic
+ fun buildLoggingSummary(accessPoint: AccessPoint, config: WifiConfiguration?): String {
+ val summary = StringBuilder()
+ val info = accessPoint.info
+ // Add RSSI/band information for this config, what was seen up to 6 seconds ago
+ // verbose WiFi Logging is only turned on thru developers settings
+ if (accessPoint.isActive && info != null) {
+ summary.append(" f=" + info.frequency.toString())
+ }
+ summary.append(" " + getVisibilityStatus(accessPoint))
+ if (config != null && (config.networkSelectionStatus.networkSelectionStatus
+ != NetworkSelectionStatus.NETWORK_SELECTION_ENABLED)
+ ) {
+ summary.append(" (" + config.networkSelectionStatus.networkStatusString)
+ if (config.networkSelectionStatus.disableTime > 0) {
+ val now = System.currentTimeMillis()
+ val diff = (now - config.networkSelectionStatus.disableTime) / 1000
+ val sec = diff % 60 // seconds
+ val min = diff / 60 % 60 // minutes
+ val hour = min / 60 % 60 // hours
+ summary.append(", ")
+ if (hour > 0) summary.append(hour.toString() + "h ")
+ summary.append(min.toString() + "m ")
+ summary.append(sec.toString() + "s ")
+ }
+ summary.append(")")
+ }
+ if (config != null) {
+ val networkStatus = config.networkSelectionStatus
+ for (reason in 0..NetworkSelectionStatus.getMaxNetworkSelectionDisableReason()) {
+ if (networkStatus.getDisableReasonCounter(reason) != 0) {
+ summary.append(" ")
+ .append(
+ NetworkSelectionStatus
+ .getNetworkSelectionDisableReasonString(reason)
+ )
+ .append("=")
+ .append(networkStatus.getDisableReasonCounter(reason))
+ }
+ }
+ }
+ return summary.toString()
+ }
+
+ /**
+ * Returns the visibility status of the WifiConfiguration.
+ *
+ * @return autojoin debugging information
+ * TODO: use a string formatter
+ * ["rssi 5Ghz", "num results on 5GHz" / "rssi 5Ghz", "num results on 5GHz"]
+ * For instance [-40,5/-30,2]
+ */
+ @JvmStatic
+ @VisibleForTesting
+ fun getVisibilityStatus(accessPoint: AccessPoint): String {
+ val info = accessPoint.info
+ val visibility = StringBuilder()
+ val scans24GHz = StringBuilder()
+ val scans5GHz = StringBuilder()
+ val scans60GHz = StringBuilder()
+ var bssid: String? = null
+ if (accessPoint.isActive && info != null) {
+ bssid = info.bssid
+ if (bssid != null) {
+ visibility.append(" ").append(bssid)
+ }
+ visibility.append(" standard = ").append(info.wifiStandard)
+ visibility.append(" rssi=").append(info.rssi)
+ visibility.append(" ")
+ visibility.append(" score=").append(info.getScore())
+ if (accessPoint.speed != AccessPoint.Speed.NONE) {
+ visibility.append(" speed=").append(accessPoint.speedLabel)
+ }
+ visibility.append(String.format(" tx=%.1f,", info.successfulTxPacketsPerSecond))
+ visibility.append(String.format("%.1f,", info.retriedTxPacketsPerSecond))
+ visibility.append(String.format("%.1f ", info.lostTxPacketsPerSecond))
+ visibility.append(String.format("rx=%.1f", info.successfulRxPacketsPerSecond))
+ }
+ var maxRssi5 = INVALID_RSSI
+ var maxRssi24 = INVALID_RSSI
+ var maxRssi60 = INVALID_RSSI
+ val maxDisplayedScans = 4
+ var num5 = 0 // number of scanned BSSID on 5GHz band
+ var num24 = 0 // number of scanned BSSID on 2.4Ghz band
+ var num60 = 0 // number of scanned BSSID on 60Ghz band
+ val numBlockListed = 0
+
+ // TODO: sort list by RSSI or age
+ val nowMs = SystemClock.elapsedRealtime()
+ for (result in accessPoint.getScanResults()) {
+ if (result == null) {
+ continue
+ }
+ if (result.frequency >= AccessPoint.LOWER_FREQ_5GHZ &&
+ result.frequency <= AccessPoint.HIGHER_FREQ_5GHZ
+ ) {
+ // Strictly speaking: [4915, 5825]
+ num5++
+ if (result.level > maxRssi5) {
+ maxRssi5 = result.level
+ }
+ if (num5 <= maxDisplayedScans) {
+ scans5GHz.append(
+ verboseScanResultSummary(
+ accessPoint, result, bssid,
+ nowMs
+ )
+ )
+ }
+ } else if (result.frequency >= AccessPoint.LOWER_FREQ_24GHZ &&
+ result.frequency <= AccessPoint.HIGHER_FREQ_24GHZ
+ ) {
+ // Strictly speaking: [2412, 2482]
+ num24++
+ if (result.level > maxRssi24) {
+ maxRssi24 = result.level
+ }
+ if (num24 <= maxDisplayedScans) {
+ scans24GHz.append(
+ verboseScanResultSummary(
+ accessPoint, result, bssid,
+ nowMs
+ )
+ )
+ }
+ } else if (result.frequency >= AccessPoint.LOWER_FREQ_60GHZ &&
+ result.frequency <= AccessPoint.HIGHER_FREQ_60GHZ
+ ) {
+ // Strictly speaking: [60000, 61000]
+ num60++
+ if (result.level > maxRssi60) {
+ maxRssi60 = result.level
+ }
+ if (num60 <= maxDisplayedScans) {
+ scans60GHz.append(
+ verboseScanResultSummary(
+ accessPoint, result, bssid,
+ nowMs
+ )
+ )
+ }
+ }
+ }
+ visibility.append(" [")
+ if (num24 > 0) {
+ visibility.append("(").append(num24).append(")")
+ if (num24 > maxDisplayedScans) {
+ visibility.append("max=").append(maxRssi24).append(",")
+ }
+ visibility.append(scans24GHz.toString())
+ }
+ visibility.append(";")
+ if (num5 > 0) {
+ visibility.append("(").append(num5).append(")")
+ if (num5 > maxDisplayedScans) {
+ visibility.append("max=").append(maxRssi5).append(",")
+ }
+ visibility.append(scans5GHz.toString())
+ }
+ visibility.append(";")
+ if (num60 > 0) {
+ visibility.append("(").append(num60).append(")")
+ if (num60 > maxDisplayedScans) {
+ visibility.append("max=").append(maxRssi60).append(",")
+ }
+ visibility.append(scans60GHz.toString())
+ }
+ if (numBlockListed > 0) {
+ visibility.append("!").append(numBlockListed)
+ }
+ visibility.append("]")
+ return visibility.toString()
+ }
+
+ @JvmStatic
+ @VisibleForTesting /* package */ fun verboseScanResultSummary(
+ accessPoint: AccessPoint,
+ result: ScanResult,
+ bssid: String?,
+ nowMs: Long
+ ): String {
+ val stringBuilder = StringBuilder()
+ stringBuilder.append(" \n{").append(result.BSSID)
+ if (result.BSSID == bssid) {
+ stringBuilder.append("*")
+ }
+ stringBuilder.append("=").append(result.frequency)
+ stringBuilder.append(",").append(result.level)
+ val speed = getSpecificApSpeed(result, accessPoint.scoredNetworkCache)
+ if (speed != AccessPoint.Speed.NONE) {
+ stringBuilder.append(",")
+ .append(accessPoint.getSpeedLabel(speed))
+ }
+ val ageSeconds = (nowMs - result.timestamp / 1000).toInt() / 1000
+ stringBuilder.append(",").append(ageSeconds).append("s")
+ stringBuilder.append("}")
+ return stringBuilder.toString()
+ }
+
+ @AccessPoint.Speed
+ private fun getSpecificApSpeed(
+ result: ScanResult,
+ scoredNetworkCache: Map<String, TimestampedScoredNetwork>
+ ): Int {
+ val timedScore = scoredNetworkCache[result.BSSID] ?: return AccessPoint.Speed.NONE
+ // For debugging purposes we may want to use mRssi rather than result.level as the average
+ // speed wil be determined by mRssi
+ return timedScore.score.calculateBadge(result.level)
+ }
+
+ @JvmStatic
+ fun getMeteredLabel(context: Context, config: WifiConfiguration): String {
+ // meteredOverride is whether the user manually set the metered setting or not.
+ // meteredHint is whether the network itself is telling us that it is metered
+ return if (config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_METERED ||
+ config.meteredHint && !isMeteredOverridden(
+ config
+ )
+ ) {
+ context.getString(R.string.wifi_metered_label)
+ } else context.getString(R.string.wifi_unmetered_label)
+ }
+
+ /**
+ * Returns the Internet icon resource for a given RSSI level.
+ *
+ * @param level The number of bars to show (0-4)
+ * @param noInternet True if a connected Wi-Fi network cannot access the Internet
+ */
+ @JvmStatic
+ fun getInternetIconResource(level: Int, noInternet: Boolean): Int {
+ var wifiLevel = level
+ if (wifiLevel < 0) {
+ Log.e(TAG, "Wi-Fi level is out of range! level:$level")
+ wifiLevel = 0
+ } else if (level >= WIFI_PIE.size) {
+ Log.e(TAG, "Wi-Fi level is out of range! level:$level")
+ wifiLevel = WIFI_PIE.size - 1
+ }
+ return if (noInternet) NO_INTERNET_WIFI_PIE[wifiLevel] else WIFI_PIE[wifiLevel]
+ }
+
+ /**
+ * Returns the Hotspot network icon resource.
+ *
+ * @param deviceType The device type of Hotspot network
+ */
+ @JvmStatic
+ fun getHotspotIconResource(deviceType: Int): Int {
+ return when (deviceType) {
+ NetworkProviderInfo.DEVICE_TYPE_PHONE -> R.drawable.ic_hotspot_phone
+ NetworkProviderInfo.DEVICE_TYPE_TABLET -> R.drawable.ic_hotspot_tablet
+ NetworkProviderInfo.DEVICE_TYPE_LAPTOP -> R.drawable.ic_hotspot_laptop
+ NetworkProviderInfo.DEVICE_TYPE_WATCH -> R.drawable.ic_hotspot_watch
+ NetworkProviderInfo.DEVICE_TYPE_AUTO -> R.drawable.ic_hotspot_auto
+ else -> R.drawable.ic_hotspot_phone
+ }
+ }
+
+ @JvmStatic
+ fun isMeteredOverridden(config: WifiConfiguration): Boolean {
+ return config.meteredOverride != WifiConfiguration.METERED_OVERRIDE_NONE
+ }
+
+ /**
+ * Returns the Intent for Wi-Fi dialog.
+ *
+ * @param key The Wi-Fi entry key
+ * @param connectForCaller True if a chosen WifiEntry request to connect to
+ */
+ @JvmStatic
+ fun getWifiDialogIntent(key: String?, connectForCaller: Boolean): Intent {
+ val intent = Intent(ACTION_WIFI_DIALOG)
+ intent.putExtra(EXTRA_CHOSEN_WIFI_ENTRY_KEY, key)
+ intent.putExtra(EXTRA_CONNECT_FOR_CALLER, connectForCaller)
+ return intent
+ }
+
+ /**
+ * Returns the Intent for Wi-Fi network details settings.
+ *
+ * @param key The Wi-Fi entry key
+ */
+ @JvmStatic
+ fun getWifiDetailsSettingsIntent(key: String?): Intent {
+ val intent = Intent(ACTION_WIFI_DETAILS_SETTINGS)
+ val bundle = Bundle()
+ bundle.putString(KEY_CHOSEN_WIFIENTRY_KEY, key)
+ intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, bundle)
+ return intent
+ }
+
+ /**
+ * Returns the string of Wi-Fi tethering summary for connected devices.
+ *
+ * @param context The application context
+ * @param connectedDevices The count of connected devices
+ */
+ @JvmStatic
+ fun getWifiTetherSummaryForConnectedDevices(
+ context: Context,
+ connectedDevices: Int
+ ): String {
+ val msgFormat = MessageFormat(
+ context.resources.getString(R.string.wifi_tether_connected_summary),
+ Locale.getDefault()
+ )
+ val arguments: MutableMap<String, Any> = HashMap()
+ arguments["count"] = connectedDevices
+ return msgFormat.format(arguments)
+ }
+ }
+}