Merge "Split out NetworkPriorityClassifier and UnderlyingNetworkRecord" am: 42bf9da702 am: 1baad423a7 am: f86fbfb8ba
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1901030 Change-Id: I70c590773fae0298f435ebbba779b171d2212283
This commit is contained in:
@@ -90,7 +90,7 @@ import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscription
|
|||||||
import com.android.server.vcn.Vcn.VcnGatewayStatusCallback;
|
import com.android.server.vcn.Vcn.VcnGatewayStatusCallback;
|
||||||
import com.android.server.vcn.routeselection.UnderlyingNetworkController;
|
import com.android.server.vcn.routeselection.UnderlyingNetworkController;
|
||||||
import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkControllerCallback;
|
import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkControllerCallback;
|
||||||
import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkRecord;
|
import com.android.server.vcn.routeselection.UnderlyingNetworkRecord;
|
||||||
import com.android.server.vcn.util.LogUtils;
|
import com.android.server.vcn.util.LogUtils;
|
||||||
import com.android.server.vcn.util.MtuUtils;
|
import com.android.server.vcn.util.MtuUtils;
|
||||||
import com.android.server.vcn.util.OneWayBoolean;
|
import com.android.server.vcn.util.OneWayBoolean;
|
||||||
|
|||||||
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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.server.vcn.routeselection;
|
||||||
|
|
||||||
|
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
||||||
|
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
||||||
|
|
||||||
|
import static com.android.server.VcnManagementService.LOCAL_LOG;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
|
import android.net.NetworkCapabilities;
|
||||||
|
import android.net.vcn.VcnManager;
|
||||||
|
import android.os.ParcelUuid;
|
||||||
|
import android.os.PersistableBundle;
|
||||||
|
import android.telephony.SubscriptionManager;
|
||||||
|
import android.util.Slog;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
import com.android.internal.annotations.VisibleForTesting.Visibility;
|
||||||
|
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
class NetworkPriorityClassifier {
|
||||||
|
@NonNull private static final String TAG = NetworkPriorityClassifier.class.getSimpleName();
|
||||||
|
/**
|
||||||
|
* Minimum signal strength for a WiFi network to be eligible for switching to
|
||||||
|
*
|
||||||
|
* <p>A network that satisfies this is eligible to become the selected underlying network with
|
||||||
|
* no additional conditions
|
||||||
|
*/
|
||||||
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
|
static final int WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT = -70;
|
||||||
|
/**
|
||||||
|
* Minimum signal strength to continue using a WiFi network
|
||||||
|
*
|
||||||
|
* <p>A network that satisfies the conditions may ONLY continue to be used if it is already
|
||||||
|
* selected as the underlying network. A WiFi network satisfying this condition, but NOT the
|
||||||
|
* prospective-network RSSI threshold CANNOT be switched to.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
|
static final int WIFI_EXIT_RSSI_THRESHOLD_DEFAULT = -74;
|
||||||
|
/** Priority for any cellular network for which the subscription is listed as opportunistic */
|
||||||
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
|
static final int PRIORITY_OPPORTUNISTIC_CELLULAR = 0;
|
||||||
|
/** Priority for any WiFi network which is in use, and satisfies the in-use RSSI threshold */
|
||||||
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
|
static final int PRIORITY_WIFI_IN_USE = 1;
|
||||||
|
/** Priority for any WiFi network which satisfies the prospective-network RSSI threshold */
|
||||||
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
|
static final int PRIORITY_WIFI_PROSPECTIVE = 2;
|
||||||
|
/** Priority for any standard macro cellular network */
|
||||||
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
|
static final int PRIORITY_MACRO_CELLULAR = 3;
|
||||||
|
/** Priority for any other networks (including unvalidated, etc) */
|
||||||
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
|
static final int PRIORITY_ANY = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
private static final SparseArray<String> PRIORITY_TO_STRING_MAP = new SparseArray<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
PRIORITY_TO_STRING_MAP.put(
|
||||||
|
PRIORITY_OPPORTUNISTIC_CELLULAR, "PRIORITY_OPPORTUNISTIC_CELLULAR");
|
||||||
|
PRIORITY_TO_STRING_MAP.put(PRIORITY_WIFI_IN_USE, "PRIORITY_WIFI_IN_USE");
|
||||||
|
PRIORITY_TO_STRING_MAP.put(PRIORITY_WIFI_PROSPECTIVE, "PRIORITY_WIFI_PROSPECTIVE");
|
||||||
|
PRIORITY_TO_STRING_MAP.put(PRIORITY_MACRO_CELLULAR, "PRIORITY_MACRO_CELLULAR");
|
||||||
|
PRIORITY_TO_STRING_MAP.put(PRIORITY_ANY, "PRIORITY_ANY");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gives networks a priority class, based on the following priorities:
|
||||||
|
*
|
||||||
|
* <ol>
|
||||||
|
* <li>Opportunistic cellular
|
||||||
|
* <li>Carrier WiFi, signal strength >= WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT
|
||||||
|
* <li>Carrier WiFi, active network + signal strength >= WIFI_EXIT_RSSI_THRESHOLD_DEFAULT
|
||||||
|
* <li>Macro cellular
|
||||||
|
* <li>Any others
|
||||||
|
* </ol>
|
||||||
|
*/
|
||||||
|
static int calculatePriorityClass(
|
||||||
|
UnderlyingNetworkRecord networkRecord,
|
||||||
|
ParcelUuid subscriptionGroup,
|
||||||
|
TelephonySubscriptionSnapshot snapshot,
|
||||||
|
UnderlyingNetworkRecord currentlySelected,
|
||||||
|
PersistableBundle carrierConfig) {
|
||||||
|
final NetworkCapabilities caps = networkRecord.networkCapabilities;
|
||||||
|
|
||||||
|
// mRouteSelectionNetworkRequest requires a network be both VALIDATED and NOT_SUSPENDED
|
||||||
|
|
||||||
|
if (networkRecord.isBlocked) {
|
||||||
|
logWtf("Network blocked for System Server: " + networkRecord.network);
|
||||||
|
return PRIORITY_ANY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (caps.hasTransport(TRANSPORT_CELLULAR)
|
||||||
|
&& isOpportunistic(snapshot, caps.getSubscriptionIds())) {
|
||||||
|
// If this carrier is the active data provider, ensure that opportunistic is only
|
||||||
|
// ever prioritized if it is also the active data subscription. This ensures that
|
||||||
|
// if an opportunistic subscription is still in the process of being switched to,
|
||||||
|
// or switched away from, the VCN does not attempt to continue using it against the
|
||||||
|
// decision made at the telephony layer. Failure to do so may result in the modem
|
||||||
|
// switching back and forth.
|
||||||
|
//
|
||||||
|
// Allow the following two cases:
|
||||||
|
// 1. Active subId is NOT in the group that this VCN is supporting
|
||||||
|
// 2. This opportunistic subscription is for the active subId
|
||||||
|
if (!snapshot.getAllSubIdsInGroup(subscriptionGroup)
|
||||||
|
.contains(SubscriptionManager.getActiveDataSubscriptionId())
|
||||||
|
|| caps.getSubscriptionIds()
|
||||||
|
.contains(SubscriptionManager.getActiveDataSubscriptionId())) {
|
||||||
|
return PRIORITY_OPPORTUNISTIC_CELLULAR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (caps.hasTransport(TRANSPORT_WIFI)) {
|
||||||
|
if (caps.getSignalStrength() >= getWifiExitRssiThreshold(carrierConfig)
|
||||||
|
&& currentlySelected != null
|
||||||
|
&& networkRecord.network.equals(currentlySelected.network)) {
|
||||||
|
return PRIORITY_WIFI_IN_USE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (caps.getSignalStrength() >= getWifiEntryRssiThreshold(carrierConfig)) {
|
||||||
|
return PRIORITY_WIFI_PROSPECTIVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disallow opportunistic subscriptions from matching PRIORITY_MACRO_CELLULAR, as might
|
||||||
|
// be the case when Default Data SubId (CBRS) != Active Data SubId (MACRO), as might be
|
||||||
|
// the case if the Default Data SubId does not support certain services (eg voice
|
||||||
|
// calling)
|
||||||
|
if (caps.hasTransport(TRANSPORT_CELLULAR)
|
||||||
|
&& !isOpportunistic(snapshot, caps.getSubscriptionIds())) {
|
||||||
|
return PRIORITY_MACRO_CELLULAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PRIORITY_ANY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isOpportunistic(
|
||||||
|
@NonNull TelephonySubscriptionSnapshot snapshot, Set<Integer> subIds) {
|
||||||
|
if (snapshot == null) {
|
||||||
|
logWtf("Got null snapshot");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int subId : subIds) {
|
||||||
|
if (snapshot.isOpportunistic(subId)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getWifiEntryRssiThreshold(@Nullable PersistableBundle carrierConfig) {
|
||||||
|
if (carrierConfig != null) {
|
||||||
|
return carrierConfig.getInt(
|
||||||
|
VcnManager.VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY,
|
||||||
|
WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT);
|
||||||
|
}
|
||||||
|
return WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getWifiExitRssiThreshold(@Nullable PersistableBundle carrierConfig) {
|
||||||
|
if (carrierConfig != null) {
|
||||||
|
return carrierConfig.getInt(
|
||||||
|
VcnManager.VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY,
|
||||||
|
WIFI_EXIT_RSSI_THRESHOLD_DEFAULT);
|
||||||
|
}
|
||||||
|
return WIFI_EXIT_RSSI_THRESHOLD_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String priorityClassToString(int priorityClass) {
|
||||||
|
return PRIORITY_TO_STRING_MAP.get(priorityClass, "unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void logWtf(String msg) {
|
||||||
|
Slog.wtf(TAG, msg);
|
||||||
|
LOCAL_LOG.log(TAG + " WTF: " + msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,11 +16,12 @@
|
|||||||
|
|
||||||
package com.android.server.vcn.routeselection;
|
package com.android.server.vcn.routeselection;
|
||||||
|
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
|
||||||
import static android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener;
|
import static android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener;
|
||||||
|
|
||||||
import static com.android.server.VcnManagementService.LOCAL_LOG;
|
import static com.android.server.VcnManagementService.LOCAL_LOG;
|
||||||
|
import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.getWifiEntryRssiThreshold;
|
||||||
|
import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.getWifiExitRssiThreshold;
|
||||||
|
import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.isOpportunistic;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
@@ -31,28 +32,23 @@ import android.net.Network;
|
|||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
import android.net.NetworkRequest;
|
import android.net.NetworkRequest;
|
||||||
import android.net.TelephonyNetworkSpecifier;
|
import android.net.TelephonyNetworkSpecifier;
|
||||||
import android.net.vcn.VcnManager;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.HandlerExecutor;
|
import android.os.HandlerExecutor;
|
||||||
import android.os.ParcelUuid;
|
import android.os.ParcelUuid;
|
||||||
import android.os.PersistableBundle;
|
import android.os.PersistableBundle;
|
||||||
import android.telephony.CarrierConfigManager;
|
import android.telephony.CarrierConfigManager;
|
||||||
import android.telephony.SubscriptionManager;
|
|
||||||
import android.telephony.TelephonyCallback;
|
import android.telephony.TelephonyCallback;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.SparseArray;
|
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.annotations.VisibleForTesting.Visibility;
|
|
||||||
import com.android.internal.util.IndentingPrintWriter;
|
import com.android.internal.util.IndentingPrintWriter;
|
||||||
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
||||||
import com.android.server.vcn.VcnContext;
|
import com.android.server.vcn.VcnContext;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -71,56 +67,6 @@ import java.util.TreeSet;
|
|||||||
public class UnderlyingNetworkController {
|
public class UnderlyingNetworkController {
|
||||||
@NonNull private static final String TAG = UnderlyingNetworkController.class.getSimpleName();
|
@NonNull private static final String TAG = UnderlyingNetworkController.class.getSimpleName();
|
||||||
|
|
||||||
/**
|
|
||||||
* Minimum signal strength for a WiFi network to be eligible for switching to
|
|
||||||
*
|
|
||||||
* <p>A network that satisfies this is eligible to become the selected underlying network with
|
|
||||||
* no additional conditions
|
|
||||||
*/
|
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
|
||||||
static final int WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT = -70;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Minimum signal strength to continue using a WiFi network
|
|
||||||
*
|
|
||||||
* <p>A network that satisfies the conditions may ONLY continue to be used if it is already
|
|
||||||
* selected as the underlying network. A WiFi network satisfying this condition, but NOT the
|
|
||||||
* prospective-network RSSI threshold CANNOT be switched to.
|
|
||||||
*/
|
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
|
||||||
static final int WIFI_EXIT_RSSI_THRESHOLD_DEFAULT = -74;
|
|
||||||
|
|
||||||
/** Priority for any cellular network for which the subscription is listed as opportunistic */
|
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
|
||||||
static final int PRIORITY_OPPORTUNISTIC_CELLULAR = 0;
|
|
||||||
|
|
||||||
/** Priority for any WiFi network which is in use, and satisfies the in-use RSSI threshold */
|
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
|
||||||
static final int PRIORITY_WIFI_IN_USE = 1;
|
|
||||||
|
|
||||||
/** Priority for any WiFi network which satisfies the prospective-network RSSI threshold */
|
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
|
||||||
static final int PRIORITY_WIFI_PROSPECTIVE = 2;
|
|
||||||
|
|
||||||
/** Priority for any standard macro cellular network */
|
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
|
||||||
static final int PRIORITY_MACRO_CELLULAR = 3;
|
|
||||||
|
|
||||||
/** Priority for any other networks (including unvalidated, etc) */
|
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
|
||||||
static final int PRIORITY_ANY = Integer.MAX_VALUE;
|
|
||||||
|
|
||||||
private static final SparseArray<String> PRIORITY_TO_STRING_MAP = new SparseArray<>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
PRIORITY_TO_STRING_MAP.put(
|
|
||||||
PRIORITY_OPPORTUNISTIC_CELLULAR, "PRIORITY_OPPORTUNISTIC_CELLULAR");
|
|
||||||
PRIORITY_TO_STRING_MAP.put(PRIORITY_WIFI_IN_USE, "PRIORITY_WIFI_IN_USE");
|
|
||||||
PRIORITY_TO_STRING_MAP.put(PRIORITY_WIFI_PROSPECTIVE, "PRIORITY_WIFI_PROSPECTIVE");
|
|
||||||
PRIORITY_TO_STRING_MAP.put(PRIORITY_MACRO_CELLULAR, "PRIORITY_MACRO_CELLULAR");
|
|
||||||
PRIORITY_TO_STRING_MAP.put(PRIORITY_ANY, "PRIORITY_ANY");
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull private final VcnContext mVcnContext;
|
@NonNull private final VcnContext mVcnContext;
|
||||||
@NonNull private final ParcelUuid mSubscriptionGroup;
|
@NonNull private final ParcelUuid mSubscriptionGroup;
|
||||||
@NonNull private final UnderlyingNetworkControllerCallback mCb;
|
@NonNull private final UnderlyingNetworkControllerCallback mCb;
|
||||||
@@ -425,22 +371,6 @@ public class UnderlyingNetworkController {
|
|||||||
mCb.onSelectedUnderlyingNetworkChanged(mCurrentRecord);
|
mCb.onSelectedUnderlyingNetworkChanged(mCurrentRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isOpportunistic(
|
|
||||||
@NonNull TelephonySubscriptionSnapshot snapshot, Set<Integer> subIds) {
|
|
||||||
if (snapshot == null) {
|
|
||||||
logWtf("Got null snapshot");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int subId : subIds) {
|
|
||||||
if (snapshot.isOpportunistic(subId)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NetworkBringupCallback is used to keep background, VCN-managed Networks from being reaped.
|
* NetworkBringupCallback is used to keep background, VCN-managed Networks from being reaped.
|
||||||
*
|
*
|
||||||
@@ -545,230 +475,6 @@ public class UnderlyingNetworkController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getWifiEntryRssiThreshold(@Nullable PersistableBundle carrierConfig) {
|
|
||||||
if (carrierConfig != null) {
|
|
||||||
return carrierConfig.getInt(
|
|
||||||
VcnManager.VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY,
|
|
||||||
WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
return WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int getWifiExitRssiThreshold(@Nullable PersistableBundle carrierConfig) {
|
|
||||||
if (carrierConfig != null) {
|
|
||||||
return carrierConfig.getInt(
|
|
||||||
VcnManager.VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY,
|
|
||||||
WIFI_EXIT_RSSI_THRESHOLD_DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
return WIFI_EXIT_RSSI_THRESHOLD_DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A record of a single underlying network, caching relevant fields. */
|
|
||||||
public static class UnderlyingNetworkRecord {
|
|
||||||
@NonNull public final Network network;
|
|
||||||
@NonNull public final NetworkCapabilities networkCapabilities;
|
|
||||||
@NonNull public final LinkProperties linkProperties;
|
|
||||||
public final boolean isBlocked;
|
|
||||||
|
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
|
||||||
public UnderlyingNetworkRecord(
|
|
||||||
@NonNull Network network,
|
|
||||||
@NonNull NetworkCapabilities networkCapabilities,
|
|
||||||
@NonNull LinkProperties linkProperties,
|
|
||||||
boolean isBlocked) {
|
|
||||||
this.network = network;
|
|
||||||
this.networkCapabilities = networkCapabilities;
|
|
||||||
this.linkProperties = linkProperties;
|
|
||||||
this.isBlocked = isBlocked;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (!(o instanceof UnderlyingNetworkRecord)) return false;
|
|
||||||
final UnderlyingNetworkRecord that = (UnderlyingNetworkRecord) o;
|
|
||||||
|
|
||||||
return network.equals(that.network)
|
|
||||||
&& networkCapabilities.equals(that.networkCapabilities)
|
|
||||||
&& linkProperties.equals(that.linkProperties)
|
|
||||||
&& isBlocked == that.isBlocked;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(network, networkCapabilities, linkProperties, isBlocked);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gives networks a priority class, based on the following priorities:
|
|
||||||
*
|
|
||||||
* <ol>
|
|
||||||
* <li>Opportunistic cellular
|
|
||||||
* <li>Carrier WiFi, signal strength >= WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT
|
|
||||||
* <li>Carrier WiFi, active network + signal strength >= WIFI_EXIT_RSSI_THRESHOLD_DEFAULT
|
|
||||||
* <li>Macro cellular
|
|
||||||
* <li>Any others
|
|
||||||
* </ol>
|
|
||||||
*/
|
|
||||||
private int calculatePriorityClass(
|
|
||||||
ParcelUuid subscriptionGroup,
|
|
||||||
TelephonySubscriptionSnapshot snapshot,
|
|
||||||
UnderlyingNetworkRecord currentlySelected,
|
|
||||||
PersistableBundle carrierConfig) {
|
|
||||||
final NetworkCapabilities caps = networkCapabilities;
|
|
||||||
|
|
||||||
// mRouteSelectionNetworkRequest requires a network be both VALIDATED and NOT_SUSPENDED
|
|
||||||
|
|
||||||
if (isBlocked) {
|
|
||||||
logWtf("Network blocked for System Server: " + network);
|
|
||||||
return PRIORITY_ANY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (caps.hasTransport(TRANSPORT_CELLULAR)
|
|
||||||
&& isOpportunistic(snapshot, caps.getSubscriptionIds())) {
|
|
||||||
// If this carrier is the active data provider, ensure that opportunistic is only
|
|
||||||
// ever prioritized if it is also the active data subscription. This ensures that
|
|
||||||
// if an opportunistic subscription is still in the process of being switched to,
|
|
||||||
// or switched away from, the VCN does not attempt to continue using it against the
|
|
||||||
// decision made at the telephony layer. Failure to do so may result in the modem
|
|
||||||
// switching back and forth.
|
|
||||||
//
|
|
||||||
// Allow the following two cases:
|
|
||||||
// 1. Active subId is NOT in the group that this VCN is supporting
|
|
||||||
// 2. This opportunistic subscription is for the active subId
|
|
||||||
if (!snapshot.getAllSubIdsInGroup(subscriptionGroup)
|
|
||||||
.contains(SubscriptionManager.getActiveDataSubscriptionId())
|
|
||||||
|| caps.getSubscriptionIds()
|
|
||||||
.contains(SubscriptionManager.getActiveDataSubscriptionId())) {
|
|
||||||
return PRIORITY_OPPORTUNISTIC_CELLULAR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (caps.hasTransport(TRANSPORT_WIFI)) {
|
|
||||||
if (caps.getSignalStrength() >= getWifiExitRssiThreshold(carrierConfig)
|
|
||||||
&& currentlySelected != null
|
|
||||||
&& network.equals(currentlySelected.network)) {
|
|
||||||
return PRIORITY_WIFI_IN_USE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (caps.getSignalStrength() >= getWifiEntryRssiThreshold(carrierConfig)) {
|
|
||||||
return PRIORITY_WIFI_PROSPECTIVE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disallow opportunistic subscriptions from matching PRIORITY_MACRO_CELLULAR, as might
|
|
||||||
// be the case when Default Data SubId (CBRS) != Active Data SubId (MACRO), as might be
|
|
||||||
// the case if the Default Data SubId does not support certain services (eg voice
|
|
||||||
// calling)
|
|
||||||
if (caps.hasTransport(TRANSPORT_CELLULAR)
|
|
||||||
&& !isOpportunistic(snapshot, caps.getSubscriptionIds())) {
|
|
||||||
return PRIORITY_MACRO_CELLULAR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return PRIORITY_ANY;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Comparator<UnderlyingNetworkRecord> getComparator(
|
|
||||||
ParcelUuid subscriptionGroup,
|
|
||||||
TelephonySubscriptionSnapshot snapshot,
|
|
||||||
UnderlyingNetworkRecord currentlySelected,
|
|
||||||
PersistableBundle carrierConfig) {
|
|
||||||
return (left, right) -> {
|
|
||||||
return Integer.compare(
|
|
||||||
left.calculatePriorityClass(
|
|
||||||
subscriptionGroup, snapshot, currentlySelected, carrierConfig),
|
|
||||||
right.calculatePriorityClass(
|
|
||||||
subscriptionGroup, snapshot, currentlySelected, carrierConfig));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Dumps the state of this record for logging and debugging purposes. */
|
|
||||||
private void dump(
|
|
||||||
IndentingPrintWriter pw,
|
|
||||||
ParcelUuid subscriptionGroup,
|
|
||||||
TelephonySubscriptionSnapshot snapshot,
|
|
||||||
UnderlyingNetworkRecord currentlySelected,
|
|
||||||
PersistableBundle carrierConfig) {
|
|
||||||
pw.println("UnderlyingNetworkRecord:");
|
|
||||||
pw.increaseIndent();
|
|
||||||
|
|
||||||
final int priorityClass =
|
|
||||||
calculatePriorityClass(
|
|
||||||
subscriptionGroup, snapshot, currentlySelected, carrierConfig);
|
|
||||||
pw.println(
|
|
||||||
"Priority class: " + PRIORITY_TO_STRING_MAP.get(priorityClass) + " ("
|
|
||||||
+ priorityClass + ")");
|
|
||||||
pw.println("mNetwork: " + network);
|
|
||||||
pw.println("mNetworkCapabilities: " + networkCapabilities);
|
|
||||||
pw.println("mLinkProperties: " + linkProperties);
|
|
||||||
|
|
||||||
pw.decreaseIndent();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Builder to incrementally construct an UnderlyingNetworkRecord. */
|
|
||||||
private static class Builder {
|
|
||||||
@NonNull private final Network mNetwork;
|
|
||||||
|
|
||||||
@Nullable private NetworkCapabilities mNetworkCapabilities;
|
|
||||||
@Nullable private LinkProperties mLinkProperties;
|
|
||||||
boolean mIsBlocked;
|
|
||||||
boolean mWasIsBlockedSet;
|
|
||||||
|
|
||||||
@Nullable private UnderlyingNetworkRecord mCached;
|
|
||||||
|
|
||||||
private Builder(@NonNull Network network) {
|
|
||||||
mNetwork = network;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private Network getNetwork() {
|
|
||||||
return mNetwork;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) {
|
|
||||||
mNetworkCapabilities = networkCapabilities;
|
|
||||||
mCached = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private NetworkCapabilities getNetworkCapabilities() {
|
|
||||||
return mNetworkCapabilities;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setLinkProperties(@NonNull LinkProperties linkProperties) {
|
|
||||||
mLinkProperties = linkProperties;
|
|
||||||
mCached = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setIsBlocked(boolean isBlocked) {
|
|
||||||
mIsBlocked = isBlocked;
|
|
||||||
mWasIsBlockedSet = true;
|
|
||||||
mCached = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isValid() {
|
|
||||||
return mNetworkCapabilities != null && mLinkProperties != null && mWasIsBlockedSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
private UnderlyingNetworkRecord build() {
|
|
||||||
if (!isValid()) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Called build before UnderlyingNetworkRecord was valid");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mCached == null) {
|
|
||||||
mCached =
|
|
||||||
new UnderlyingNetworkRecord(
|
|
||||||
mNetwork, mNetworkCapabilities, mLinkProperties, mIsBlocked);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mCached;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void logWtf(String msg) {
|
private static void logWtf(String msg) {
|
||||||
Slog.wtf(TAG, msg);
|
Slog.wtf(TAG, msg);
|
||||||
LOCAL_LOG.log(TAG + " WTF: " + msg);
|
LOCAL_LOG.log(TAG + " WTF: " + msg);
|
||||||
|
|||||||
@@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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.server.vcn.routeselection;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
|
import android.net.LinkProperties;
|
||||||
|
import android.net.Network;
|
||||||
|
import android.net.NetworkCapabilities;
|
||||||
|
import android.os.ParcelUuid;
|
||||||
|
import android.os.PersistableBundle;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
import com.android.internal.annotations.VisibleForTesting.Visibility;
|
||||||
|
import com.android.internal.util.IndentingPrintWriter;
|
||||||
|
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A record of a single underlying network, caching relevant fields.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public class UnderlyingNetworkRecord {
|
||||||
|
@NonNull public final Network network;
|
||||||
|
@NonNull public final NetworkCapabilities networkCapabilities;
|
||||||
|
@NonNull public final LinkProperties linkProperties;
|
||||||
|
public final boolean isBlocked;
|
||||||
|
|
||||||
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
|
public UnderlyingNetworkRecord(
|
||||||
|
@NonNull Network network,
|
||||||
|
@NonNull NetworkCapabilities networkCapabilities,
|
||||||
|
@NonNull LinkProperties linkProperties,
|
||||||
|
boolean isBlocked) {
|
||||||
|
this.network = network;
|
||||||
|
this.networkCapabilities = networkCapabilities;
|
||||||
|
this.linkProperties = linkProperties;
|
||||||
|
this.isBlocked = isBlocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof UnderlyingNetworkRecord)) return false;
|
||||||
|
final UnderlyingNetworkRecord that = (UnderlyingNetworkRecord) o;
|
||||||
|
|
||||||
|
return network.equals(that.network)
|
||||||
|
&& networkCapabilities.equals(that.networkCapabilities)
|
||||||
|
&& linkProperties.equals(that.linkProperties)
|
||||||
|
&& isBlocked == that.isBlocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(network, networkCapabilities, linkProperties, isBlocked);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Comparator<UnderlyingNetworkRecord> getComparator(
|
||||||
|
ParcelUuid subscriptionGroup,
|
||||||
|
TelephonySubscriptionSnapshot snapshot,
|
||||||
|
UnderlyingNetworkRecord currentlySelected,
|
||||||
|
PersistableBundle carrierConfig) {
|
||||||
|
return (left, right) -> {
|
||||||
|
return Integer.compare(
|
||||||
|
NetworkPriorityClassifier.calculatePriorityClass(
|
||||||
|
left, subscriptionGroup, snapshot, currentlySelected, carrierConfig),
|
||||||
|
NetworkPriorityClassifier.calculatePriorityClass(
|
||||||
|
right, subscriptionGroup, snapshot, currentlySelected, carrierConfig));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Dumps the state of this record for logging and debugging purposes. */
|
||||||
|
void dump(
|
||||||
|
IndentingPrintWriter pw,
|
||||||
|
ParcelUuid subscriptionGroup,
|
||||||
|
TelephonySubscriptionSnapshot snapshot,
|
||||||
|
UnderlyingNetworkRecord currentlySelected,
|
||||||
|
PersistableBundle carrierConfig) {
|
||||||
|
pw.println("UnderlyingNetworkRecord:");
|
||||||
|
pw.increaseIndent();
|
||||||
|
|
||||||
|
final int priorityClass =
|
||||||
|
NetworkPriorityClassifier.calculatePriorityClass(
|
||||||
|
this, subscriptionGroup, snapshot, currentlySelected, carrierConfig);
|
||||||
|
pw.println(
|
||||||
|
"Priority class: "
|
||||||
|
+ NetworkPriorityClassifier.priorityClassToString(priorityClass)
|
||||||
|
+ " ("
|
||||||
|
+ priorityClass
|
||||||
|
+ ")");
|
||||||
|
pw.println("mNetwork: " + network);
|
||||||
|
pw.println("mNetworkCapabilities: " + networkCapabilities);
|
||||||
|
pw.println("mLinkProperties: " + linkProperties);
|
||||||
|
|
||||||
|
pw.decreaseIndent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Builder to incrementally construct an UnderlyingNetworkRecord. */
|
||||||
|
static class Builder {
|
||||||
|
@NonNull private final Network mNetwork;
|
||||||
|
|
||||||
|
@Nullable private NetworkCapabilities mNetworkCapabilities;
|
||||||
|
@Nullable private LinkProperties mLinkProperties;
|
||||||
|
boolean mIsBlocked;
|
||||||
|
boolean mWasIsBlockedSet;
|
||||||
|
|
||||||
|
@Nullable private UnderlyingNetworkRecord mCached;
|
||||||
|
|
||||||
|
Builder(@NonNull Network network) {
|
||||||
|
mNetwork = network;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
Network getNetwork() {
|
||||||
|
return mNetwork;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) {
|
||||||
|
mNetworkCapabilities = networkCapabilities;
|
||||||
|
mCached = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
NetworkCapabilities getNetworkCapabilities() {
|
||||||
|
return mNetworkCapabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLinkProperties(@NonNull LinkProperties linkProperties) {
|
||||||
|
mLinkProperties = linkProperties;
|
||||||
|
mCached = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setIsBlocked(boolean isBlocked) {
|
||||||
|
mIsBlocked = isBlocked;
|
||||||
|
mWasIsBlockedSet = true;
|
||||||
|
mCached = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isValid() {
|
||||||
|
return mNetworkCapabilities != null && mLinkProperties != null && mWasIsBlockedSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnderlyingNetworkRecord build() {
|
||||||
|
if (!isValid()) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Called build before UnderlyingNetworkRecord was valid");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCached == null) {
|
||||||
|
mCached =
|
||||||
|
new UnderlyingNetworkRecord(
|
||||||
|
mNetwork, mNetworkCapabilities, mLinkProperties, mIsBlocked);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mCached;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,7 +59,7 @@ import androidx.test.filters.SmallTest;
|
|||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
||||||
import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkRecord;
|
import com.android.server.vcn.routeselection.UnderlyingNetworkRecord;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package com.android.server.vcn;
|
|||||||
import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
|
import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
|
||||||
import static com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent;
|
import static com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent;
|
||||||
import static com.android.server.vcn.VcnTestUtils.setupIpSecManager;
|
import static com.android.server.vcn.VcnTestUtils.setupIpSecManager;
|
||||||
import static com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkRecord;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
@@ -63,6 +62,7 @@ import com.android.server.vcn.Vcn.VcnGatewayStatusCallback;
|
|||||||
import com.android.server.vcn.VcnGatewayConnection.VcnChildSessionCallback;
|
import com.android.server.vcn.VcnGatewayConnection.VcnChildSessionCallback;
|
||||||
import com.android.server.vcn.VcnGatewayConnection.VcnWakeLock;
|
import com.android.server.vcn.VcnGatewayConnection.VcnWakeLock;
|
||||||
import com.android.server.vcn.routeselection.UnderlyingNetworkController;
|
import com.android.server.vcn.routeselection.UnderlyingNetworkController;
|
||||||
|
import com.android.server.vcn.routeselection.UnderlyingNetworkRecord;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
package com.android.server.vcn.routeselection;
|
package com.android.server.vcn.routeselection;
|
||||||
|
|
||||||
import static com.android.server.vcn.VcnTestUtils.setupSystemService;
|
import static com.android.server.vcn.VcnTestUtils.setupSystemService;
|
||||||
|
import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT;
|
||||||
|
import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.WIFI_EXIT_RSSI_THRESHOLD_DEFAULT;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotEquals;
|
import static org.junit.Assert.assertNotEquals;
|
||||||
@@ -53,7 +55,6 @@ import com.android.server.vcn.VcnNetworkProvider;
|
|||||||
import com.android.server.vcn.routeselection.UnderlyingNetworkController.NetworkBringupCallback;
|
import com.android.server.vcn.routeselection.UnderlyingNetworkController.NetworkBringupCallback;
|
||||||
import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkControllerCallback;
|
import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkControllerCallback;
|
||||||
import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkListener;
|
import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkListener;
|
||||||
import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkRecord;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -251,7 +252,7 @@ public class UnderlyingNetworkControllerTest {
|
|||||||
return getExpectedRequestBase()
|
return getExpectedRequestBase()
|
||||||
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
||||||
.setSubscriptionIds(netCapsSubIds)
|
.setSubscriptionIds(netCapsSubIds)
|
||||||
.setSignalStrength(UnderlyingNetworkController.WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT)
|
.setSignalStrength(WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,7 +261,7 @@ public class UnderlyingNetworkControllerTest {
|
|||||||
return getExpectedRequestBase()
|
return getExpectedRequestBase()
|
||||||
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
||||||
.setSubscriptionIds(netCapsSubIds)
|
.setSubscriptionIds(netCapsSubIds)
|
||||||
.setSignalStrength(UnderlyingNetworkController.WIFI_EXIT_RSSI_THRESHOLD_DEFAULT)
|
.setSignalStrength(WIFI_EXIT_RSSI_THRESHOLD_DEFAULT)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user