Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef6c5ea0 authored by Charlotte Lu's avatar Charlotte Lu
Browse files

Change WifiUtils.java into kotlin.

Test: Visual Test
Fix: 327067271
Change-Id: Ieee2fe30080185fce458b1d331f1baf288c012c3
parent f909a8f5
Loading
Loading
Loading
Loading
+0 −447
Original line number Original line Diff line number Diff line
/*
 * 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);
    }
}
+462 −0

File added.

Preview size limit exceeded, changes collapsed.