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

Commit b4299df5 authored by Quang Luong's avatar Quang Luong Committed by Android (Google) Code Review
Browse files

Merge "Added special constructors for Passpoint and OSU AccessPoints"

parents ab5598df 8123f771
Loading
Loading
Loading
Loading
+96 −68
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ import android.util.Log;
import androidx.annotation.NonNull;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.CollectionUtils;
import com.android.settingslib.R;
import com.android.settingslib.utils.ThreadUtils;

@@ -132,6 +133,12 @@ public class AccessPoint implements Comparable<AccessPoint> {
    /** The underlying set of scan results comprising this AccessPoint. */
    private final ArraySet<ScanResult> mScanResults = new ArraySet<>();

    /**
     * Extra set of unused scan results corresponding to this AccessPoint for verbose logging
     * purposes, such as a set of Passpoint roaming scan results when home scans are available.
     */
    private final ArraySet<ScanResult> mExtraScanResults = new ArraySet<>();

    /**
     * Map of BSSIDs to scored networks for individual bssids.
     *
@@ -216,6 +223,7 @@ public class AccessPoint implements Comparable<AccessPoint> {
     */
    private String mFqdn;
    private String mProviderFriendlyName;
    private boolean mIsRoaming = false;

    private boolean mIsCarrierAp = false;

@@ -289,15 +297,12 @@ public class AccessPoint implements Comparable<AccessPoint> {

        // Calculate required fields
        updateKey();
        updateRssi();
        updateBestRssiInfo();
    }

    /**
     * Creates an AccessPoint with only a WifiConfiguration. This is used for the saved networks
     * page.
     *
     * Passpoint Credential AccessPoints should be created with this.
     * Make sure to call setScanResults after constructing with this.
     */
    public AccessPoint(Context context, WifiConfiguration config) {
        mContext = context;
@@ -314,40 +319,34 @@ public class AccessPoint implements Comparable<AccessPoint> {
        mProviderFriendlyName = config.getHomeSp().getFriendlyName();
    }

    /**
     * Initialize an AccessPoint object for a Passpoint network.
     */
    public AccessPoint(@NonNull Context context, @NonNull WifiConfiguration config,
            @Nullable Collection<ScanResult> homeScans,
            @Nullable Collection<ScanResult> roamingScans) {
        mContext = context;
        networkId = config.networkId;
        mConfig = config;
        setScanResultsPasspoint(homeScans, roamingScans);
        updateKey();
    }

    /**
     * Initialize an AccessPoint object for a Passpoint OSU Provider.
     * Make sure to call setScanResults after constructing with this.
     */
    public AccessPoint(Context context, OsuProvider provider) {
    public AccessPoint(@NonNull Context context, @NonNull OsuProvider provider,
            @NonNull Collection<ScanResult> results) {
        mContext = context;
        mOsuProvider = provider;
        ssid = provider.getFriendlyName();
        setScanResults(results);
        updateKey();
    }

    AccessPoint(Context context, Collection<ScanResult> results) {
        mContext = context;

        if (results.isEmpty()) {
            throw new IllegalArgumentException("Cannot construct with an empty ScanResult list");
        }
        mScanResults.addAll(results);

        // Information derived from scan results
        ScanResult firstResult = results.iterator().next();
        ssid = firstResult.SSID;
        bssid = firstResult.BSSID;
        security = getSecurity(firstResult);
        if (security == SECURITY_PSK) {
            pskType = getPskType(firstResult);
        }
        setScanResults(results);
        updateKey();
        updateRssi();

        // Passpoint Info
        mIsCarrierAp = firstResult.isCarrierAp;
        mCarrierApEapType = firstResult.carrierApEapType;
        mCarrierName = firstResult.carrierName;
    }

    @VisibleForTesting void loadConfig(WifiConfiguration config) {
@@ -468,7 +467,8 @@ public class AccessPoint implements Comparable<AccessPoint> {

        if (isVerboseLoggingEnabled()) {
            builder.append(",rssi=").append(mRssi);
            builder.append(",scan cache size=").append(mScanResults.size());
            builder.append(",scan cache size=").append(mScanResults.size()
                    + mExtraScanResults.size());
        }

        return builder.append(')').toString();
@@ -703,14 +703,19 @@ public class AccessPoint implements Comparable<AccessPoint> {
     *
     * <p>Callers should not modify this set.
     */
    public Set<ScanResult> getScanResults() { return mScanResults; }
    public Set<ScanResult> getScanResults() {
        Set<ScanResult> allScans = new ArraySet<>();
        allScans.addAll(mScanResults);
        allScans.addAll(mExtraScanResults);
        return allScans;
    }

    public Map<String, TimestampedScoredNetwork> getScoredNetworkCache() {
        return mScoredNetworkCache;
    }

    /**
     * Updates {@link #mRssi}.
     * Updates {@link #mRssi} and sets scan result information to that of the best RSSI scan result.
     *
     * <p>If the given connection is active, the existing value of {@link #mRssi} will be returned.
     * If the given AccessPoint is not active, a value will be calculated from previous scan
@@ -718,22 +723,41 @@ public class AccessPoint implements Comparable<AccessPoint> {
     * value. If the access point is not connected and there are no scan results, the rssi will be
     * set to {@link #UNREACHABLE_RSSI}.
     */
    private void updateRssi() {
    private void updateBestRssiInfo() {
        if (this.isActive()) {
            return;
        }

        int rssi = UNREACHABLE_RSSI;
        ScanResult bestResult = null;
        int bestRssi = UNREACHABLE_RSSI;
        for (ScanResult result : mScanResults) {
            if (result.level > rssi) {
                rssi = result.level;
            if (result.level > bestRssi) {
                bestRssi = result.level;
                bestResult = result;
            }
        }

        if (rssi != UNREACHABLE_RSSI && mRssi != UNREACHABLE_RSSI) {
            mRssi = (mRssi + rssi) / 2; // half-life previous value
        // Set the rssi to the average of the current rssi and the previous rssi.
        if (bestRssi != UNREACHABLE_RSSI && mRssi != UNREACHABLE_RSSI) {
            mRssi = (mRssi + bestRssi) / 2;
        } else {
            mRssi = rssi;
            mRssi = bestRssi;
        }

        if (bestResult != null) {
            ssid = bestResult.SSID;
            bssid = bestResult.BSSID;
            security = getSecurity(bestResult);
            if (security == SECURITY_PSK) {
                pskType = getPskType(bestResult);
            }
            mIsCarrierAp = bestResult.isCarrierAp;
            mCarrierApEapType = bestResult.carrierApEapType;
            mCarrierName = bestResult.carrierName;
        }
        // Update the config SSID of a Passpoint network to that of the best RSSI
        if (isPasspoint()) {
            mConfig.SSID = convertToQuotedString(ssid);
        }
    }

@@ -897,18 +921,12 @@ public class AccessPoint implements Comparable<AccessPoint> {
                summary.append(mContext.getString(R.string.tap_to_sign_up));
            }
        } else if (isActive()) {
            if (isPasspoint()) {
                // This is the active connection on passpoint
                summary.append(getSummary(mContext, /* ssid */ null, getDetailedState(),
                        /* isEphemeral */ false,
                        /* suggestionOrSpecifierPackageName */ null));
            } else if (mConfig != null && getDetailedState() == DetailedState.CONNECTED
            if (mConfig != null && getDetailedState() == DetailedState.CONNECTED
                    && mIsCarrierAp) {
                // This is the active connection on a carrier AP
                summary.append(String.format(mContext.getString(R.string.connected_via_carrier),
                        mCarrierName));
            } else {
                // This is the active connection on non-passpoint network
                summary.append(getSummary(mContext, /* ssid */ null, getDetailedState(),
                        mInfo != null && mInfo.isEphemeral(),
                        mInfo != null ? mInfo.getNetworkSuggestionOrSpecifierPackageName() : null));
@@ -1107,7 +1125,8 @@ public class AccessPoint implements Comparable<AccessPoint> {
        if (mConfig != null) savedState.putParcelable(KEY_CONFIG, mConfig);
        savedState.putParcelable(KEY_WIFIINFO, mInfo);
        savedState.putParcelableArray(KEY_SCANRESULTS,
                mScanResults.toArray(new Parcelable[mScanResults.size()]));
                mScanResults.toArray(new Parcelable[mScanResults.size()
                        + mExtraScanResults.size()]));
        savedState.putParcelableArrayList(KEY_SCOREDNETWORKCACHE,
                new ArrayList<>(mScoredNetworkCache.values()));
        if (mNetworkInfo != null) {
@@ -1129,24 +1148,27 @@ public class AccessPoint implements Comparable<AccessPoint> {
    }

    /**
     * Sets {@link #mScanResults} to the given collection.
     * Sets {@link #mScanResults} to the given collection and updates info based on the best RSSI
     * scan result.
     *
     * @param scanResults a collection of scan results to add to the internal set
     * @throws IllegalArgumentException if any of the given ScanResults did not belong to this AP
     */
    void setScanResults(Collection<ScanResult> scanResults) {
        if (CollectionUtils.isEmpty(scanResults)) {
            Log.d(TAG, "Cannot set scan results to empty list");
            return;
        }

        // Validate scan results are for current AP only by matching SSID/BSSID
        // Passpoint networks are not bound to a specific SSID/BSSID, so skip this for passpoint.
        if (!isPasspoint() && !isOsuProvider()) {
            String key = getKey();
        if (mKey != null && !isPasspoint() && !isOsuProvider()) {
            for (ScanResult result : scanResults) {
                String scanResultKey = AccessPoint.getKey(result);
                if (!mKey.equals(scanResultKey)) {
                    throw new IllegalArgumentException(
                            String.format(
                if (mKey != null && !mKey.equals(scanResultKey)) {
                    Log.d(TAG, String.format(
                                    "ScanResult %s\nkey of %s did not match current AP key %s",
                                    result, scanResultKey, key));
                                    result, scanResultKey, mKey));
                    return;
                }
            }
        }
@@ -1154,7 +1176,7 @@ public class AccessPoint implements Comparable<AccessPoint> {
        int oldLevel = getLevel();
        mScanResults.clear();
        mScanResults.addAll(scanResults);
        updateRssi();
        updateBestRssiInfo();
        int newLevel = getLevel();

        // If newLevel is 0, there will be no displayed Preference since the AP is unreachable
@@ -1174,20 +1196,26 @@ public class AccessPoint implements Comparable<AccessPoint> {
                mAccessPointListener.onAccessPointChanged(this);
            }
        });

        if (!scanResults.isEmpty()) {
            ScanResult result = scanResults.iterator().next();

            // This flag only comes from scans, is not easily saved in config
            if (security == SECURITY_PSK) {
                pskType = getPskType(result);
    }

            // The carrier info in the ScanResult is set by the platform based on the SSID and will
            // always be the same for all matching scan results.
            mIsCarrierAp = result.isCarrierAp;
            mCarrierApEapType = result.carrierApEapType;
            mCarrierName = result.carrierName;
    /**
     * Sets the internal scan result cache to the list of home scans.
     * If there are no home scans, then the roaming scan list is used, and the AccessPoint is
     * marked as roaming.
     */
    void setScanResultsPasspoint(
            @Nullable Collection<ScanResult> homeScans,
            @Nullable Collection<ScanResult> roamingScans) {
        mExtraScanResults.clear();
        if (!CollectionUtils.isEmpty(homeScans)) {
            if (!CollectionUtils.isEmpty(roamingScans)) {
                mExtraScanResults.addAll(roamingScans);
            }
            mIsRoaming = false;
            setScanResults(homeScans);
        } else if (!CollectionUtils.isEmpty(roamingScans)) {
            mIsRoaming = true;
            setScanResults(roamingScans);
        }
    }

@@ -1204,7 +1232,6 @@ public class AccessPoint implements Comparable<AccessPoint> {
     */
    public boolean update(
            @Nullable WifiConfiguration config, WifiInfo info, NetworkInfo networkInfo) {

        boolean updated = false;
        final int oldLevel = getLevel();
        if (info != null && isInfoForThisAccessPoint(config, info)) {
@@ -1538,7 +1565,8 @@ public class AccessPoint implements Comparable<AccessPoint> {
     *
     * All methods are invoked on the Main Thread
     */
    private class AccessPointProvisioningCallback extends ProvisioningCallback {
    @VisibleForTesting
    class AccessPointProvisioningCallback extends ProvisioningCallback {
        @Override
        @MainThread public void onProvisioningFailure(int status) {
            if (TextUtils.equals(mOsuStatus, mContext.getString(R.string.osu_completing_sign_up))) {
+16 −30
Original line number Diff line number Diff line
@@ -53,7 +53,6 @@ import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;

import com.android.internal.util.CollectionUtils;
import com.android.settingslib.R;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -646,30 +645,14 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
                Map<Integer, List<ScanResult>>> pairing : passpointConfigsAndScans) {
            WifiConfiguration config = pairing.first;
            if (seenFQDNs.add(config.FQDN)) {
                List<ScanResult> apScanResults = new ArrayList<>();

                List<ScanResult> homeScans =
                        pairing.second.get(WifiManager.PASSPOINT_HOME_NETWORK);
                List<ScanResult> roamingScans =
                        pairing.second.get(WifiManager.PASSPOINT_ROAMING_NETWORK);

                // TODO(b/118705403): Differentiate home network vs roaming network for summary info
                if (!CollectionUtils.isEmpty(homeScans)) {
                    apScanResults.addAll(homeScans);
                } else if (!CollectionUtils.isEmpty(roamingScans)) {
                    apScanResults.addAll(roamingScans);
                }

                int bestRssi = Integer.MIN_VALUE;
                for (ScanResult result : apScanResults) {
                    if (result.level >= bestRssi) {
                        bestRssi = result.level;
                        config.SSID = AccessPoint.convertToQuotedString(result.SSID);
                    }
                }

                AccessPoint accessPoint =
                        getCachedOrCreatePasspoint(apScanResults, accessPointCache, config);
                        getCachedOrCreatePasspoint(config, homeScans, roamingScans,
                                accessPointCache);
                accessPoints.add(accessPoint);
            }
        }
@@ -688,8 +671,8 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
        for (OsuProvider provider : providersAndScans.keySet()) {
            if (!alreadyProvisioned.contains(provider)) {
                AccessPoint accessPointOsu =
                        getCachedOrCreateOsu(providersAndScans.get(provider),
                                accessPointCache, provider);
                        getCachedOrCreateOsu(provider, providersAndScans.get(provider),
                                accessPointCache);
                accessPoints.add(accessPointOsu);
            }
        }
@@ -709,26 +692,29 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
    }

    private AccessPoint getCachedOrCreatePasspoint(
            List<ScanResult> scanResults,
            List<AccessPoint> cache,
            WifiConfiguration config) {
            WifiConfiguration config,
            List<ScanResult> homeScans,
            List<ScanResult> roamingScans,
            List<AccessPoint> cache) {
        AccessPoint accessPoint = getCachedByKey(cache, AccessPoint.getKey(config));
        if (accessPoint == null) {
            accessPoint = new AccessPoint(mContext, config);
            accessPoint = new AccessPoint(mContext, config, homeScans, roamingScans);
        } else {
            accessPoint.setScanResultsPasspoint(homeScans, roamingScans);
        }
        accessPoint.setScanResults(scanResults);
        return accessPoint;
    }

    private AccessPoint getCachedOrCreateOsu(
            OsuProvider provider,
            List<ScanResult> scanResults,
            List<AccessPoint> cache,
            OsuProvider provider) {
            List<AccessPoint> cache) {
        AccessPoint accessPoint = getCachedByKey(cache, AccessPoint.getKey(provider));
        if (accessPoint == null) {
            accessPoint = new AccessPoint(mContext, provider);
        }
            accessPoint = new AccessPoint(mContext, provider, scanResults);
        } else {
            accessPoint.setScanResults(scanResults);
        }
        return accessPoint;
    }

+200 −14

File changed.

Preview size limit exceeded, changes collapsed.

+1 −2
Original line number Diff line number Diff line
@@ -1155,8 +1155,7 @@ public class WifiTrackerTest {
                providersAndScans, cachedAccessPoints);

        // Verify second update AP is the same object as the first update AP
        assertTrue(osuAccessPointsFirstUpdate.get(0)
                == osuAccessPointsSecondUpdate.get(0));
        assertThat(osuAccessPointsFirstUpdate.get(0)).isSameAs(osuAccessPointsSecondUpdate.get(0));
        // Verify second update AP has the average of the first and second update RSSIs
        assertThat(osuAccessPointsSecondUpdate.get(0).getRssi())
                .isEqualTo((prevRssi + newRssi) / 2);