Merge "[SB Refactor] Account for underlying wifi networks in old pipeline." into udc-dev

This commit is contained in:
Caitlin Shkuratov
2023-04-25 18:50:13 +00:00
committed by Android (Google) Code Review
2 changed files with 276 additions and 39 deletions

View File

@@ -14,7 +14,9 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
@@ -26,6 +28,8 @@ import android.net.NetworkKey;
import android.net.NetworkRequest;
import android.net.NetworkScoreManager;
import android.net.ScoredNetwork;
import android.net.TransportInfo;
import android.net.vcn.VcnTransportInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiNetworkScoreCache;
@@ -34,8 +38,9 @@ import android.os.HandlerThread;
import android.os.Looper;
import android.provider.Settings;
import androidx.annotation.Nullable;
import com.android.settingslib.R;
import com.android.settingslib.Utils;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
@@ -46,6 +51,7 @@ import java.util.Set;
/**
* Track status of Wi-Fi for the Sys UI.
*/
@SuppressLint("MissingPermission")
public class WifiStatusTracker {
private static final int HISTORY_SIZE = 32;
private static final SimpleDateFormat SSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
@@ -66,8 +72,9 @@ public class WifiStatusTracker {
private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder()
.clearCapabilities()
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build();
.addTransportType(TRANSPORT_WIFI)
.addTransportType(TRANSPORT_CELLULAR)
.build();
private final NetworkCallback mNetworkCallback =
new NetworkCallback(NetworkCallback.FLAG_INCLUDE_LOCATION_INFO) {
// Note: onCapabilitiesChanged is guaranteed to be called "immediately" after onAvailable
@@ -75,18 +82,10 @@ public class WifiStatusTracker {
@Override
public void onCapabilitiesChanged(
Network network, NetworkCapabilities networkCapabilities) {
boolean isVcnOverWifi = false;
boolean isWifi = false;
WifiInfo wifiInfo = null;
if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
wifiInfo = Utils.tryGetWifiInfoForVcn(networkCapabilities);
isVcnOverWifi = (wifiInfo != null);
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
wifiInfo = (WifiInfo) networkCapabilities.getTransportInfo();
isWifi = true;
}
WifiInfo wifiInfo = getMainOrUnderlyingWifiInfo(networkCapabilities);
boolean isWifi = connectionIsWifi(networkCapabilities, wifiInfo);
// As long as it is a WiFi network, we will log it in the dumpsys for debugging.
if (isVcnOverWifi || isWifi) {
if (isWifi) {
String log = new StringBuilder()
.append(SSDF.format(System.currentTimeMillis())).append(",")
.append("onCapabilitiesChanged: ")
@@ -303,17 +302,8 @@ public class WifiStatusTracker {
return;
}
NetworkCapabilities networkCapabilities;
isDefaultNetwork = false;
if (mDefaultNetworkCapabilities != null) {
boolean isWifi = mDefaultNetworkCapabilities.hasTransport(
NetworkCapabilities.TRANSPORT_WIFI);
boolean isVcnOverWifi = mDefaultNetworkCapabilities.hasTransport(
NetworkCapabilities.TRANSPORT_CELLULAR)
&& (Utils.tryGetWifiInfoForVcn(mDefaultNetworkCapabilities) != null);
if (isWifi || isVcnOverWifi) {
isDefaultNetwork = true;
}
}
isDefaultNetwork = mDefaultNetworkCapabilities != null
&& connectionIsWifi(mDefaultNetworkCapabilities);
if (isDefaultNetwork) {
// Wifi is connected and the default network.
networkCapabilities = mDefaultNetworkCapabilities;
@@ -352,6 +342,70 @@ public class WifiStatusTracker {
? null : AccessPoint.getSpeedLabel(mContext, scoredNetwork, rssi);
}
@Nullable
private WifiInfo getMainOrUnderlyingWifiInfo(NetworkCapabilities networkCapabilities) {
WifiInfo mainWifiInfo = getMainWifiInfo(networkCapabilities);
if (mainWifiInfo != null) {
return mainWifiInfo;
}
// Only CELLULAR networks may have underlying wifi information that's relevant to SysUI,
// so skip the underlying network check if it's not CELLULAR.
if (!networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
return mainWifiInfo;
}
List<Network> underlyingNetworks = networkCapabilities.getUnderlyingNetworks();
if (underlyingNetworks == null) {
return null;
}
// Some connections, like VPN connections, may have underlying networks that are
// eventually traced to a wifi or carrier merged connection. So, check those underlying
// networks for possible wifi information as well. See b/225902574.
for (Network underlyingNetwork : underlyingNetworks) {
NetworkCapabilities underlyingNetworkCapabilities =
mConnectivityManager.getNetworkCapabilities(underlyingNetwork);
WifiInfo underlyingWifiInfo = getMainWifiInfo(underlyingNetworkCapabilities);
if (underlyingWifiInfo != null) {
return underlyingWifiInfo;
}
}
return null;
}
@Nullable
private WifiInfo getMainWifiInfo(NetworkCapabilities networkCapabilities) {
boolean canHaveWifiInfo = networkCapabilities.hasTransport(TRANSPORT_WIFI)
|| networkCapabilities.hasTransport(TRANSPORT_CELLULAR);
if (!canHaveWifiInfo) {
return null;
}
TransportInfo transportInfo = networkCapabilities.getTransportInfo();
if (transportInfo instanceof VcnTransportInfo) {
// This VcnTransportInfo logic is copied from
// [com.android.settingslib.Utils.tryGetWifiInfoForVcn]. It's copied instead of
// re-used because it makes the logic here clearer.
return ((VcnTransportInfo) transportInfo).getWifiInfo();
} else if (transportInfo instanceof WifiInfo) {
return (WifiInfo) transportInfo;
} else {
return null;
}
}
private boolean connectionIsWifi(NetworkCapabilities networkCapabilities) {
return connectionIsWifi(
networkCapabilities,
getMainOrUnderlyingWifiInfo(networkCapabilities));
}
private boolean connectionIsWifi(NetworkCapabilities networkCapabilities, WifiInfo wifiInfo) {
return wifiInfo != null || networkCapabilities.hasTransport(TRANSPORT_WIFI);
}
/** Refresh the status label on Locale changed. */
public void refreshLocale() {
updateStatusLabel();

View File

@@ -40,6 +40,8 @@ import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import java.util.Arrays;
@RunWith(RobolectricTestRunner.class)
public class WifiStatusTrackerTest {
@Mock Context mContext;
@@ -48,13 +50,32 @@ public class WifiStatusTrackerTest {
@Mock ConnectivityManager mConnectivityManager;
@Mock Runnable mCallback;
private WifiStatusTracker mWifiStatusTracker;
private final ArgumentCaptor<ConnectivityManager.NetworkCallback>
mNetworkCallbackCaptor =
ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
private final ArgumentCaptor<ConnectivityManager.NetworkCallback>
mDefaultNetworkCallbackCaptor =
ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mWifiStatusTracker = new WifiStatusTracker(
mContext,
mWifiManager,
mNetworkScoreManager,
mConnectivityManager,
mCallback);
mWifiStatusTracker.setListening(true);
verify(mConnectivityManager)
.registerNetworkCallback(any(), mNetworkCallbackCaptor.capture(), any());
verify(mConnectivityManager)
.registerDefaultNetworkCallback(mDefaultNetworkCallbackCaptor.capture(), any());
}
/**
@@ -62,13 +83,6 @@ public class WifiStatusTrackerTest {
*/
@Test
public void testWifiInfoClearedOnPrimaryNetworkLost() {
WifiStatusTracker wifiStatusTracker = new WifiStatusTracker(mContext, mWifiManager,
mNetworkScoreManager, mConnectivityManager, mCallback);
wifiStatusTracker.setListening(true);
verify(mConnectivityManager)
.registerNetworkCallback(any(), mNetworkCallbackCaptor.capture(), any());
// Trigger a validation callback for the primary Wifi network.
WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
when(primaryWifiInfo.makeCopy(anyLong())).thenReturn(primaryWifiInfo);
@@ -86,8 +100,8 @@ public class WifiStatusTrackerTest {
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
// Verify primary wifi info is the one being used.
assertThat(wifiStatusTracker.connected).isTrue();
assertThat(wifiStatusTracker.rssi).isEqualTo(primaryRssi);
assertThat(mWifiStatusTracker.connected).isTrue();
assertThat(mWifiStatusTracker.rssi).isEqualTo(primaryRssi);
// Trigger a validation callback for the non-primary Wifi network.
WifiInfo nonPrimaryWifiInfo = Mockito.mock(WifiInfo.class);
@@ -106,20 +120,189 @@ public class WifiStatusTrackerTest {
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(nonPrimaryNetwork, nonPrimaryCap);
// Verify primary wifi info is still the one being used.
assertThat(wifiStatusTracker.connected).isTrue();
assertThat(wifiStatusTracker.rssi).isEqualTo(primaryRssi);
assertThat(mWifiStatusTracker.connected).isTrue();
assertThat(mWifiStatusTracker.rssi).isEqualTo(primaryRssi);
// Lose the non-primary network.
mNetworkCallbackCaptor.getValue().onLost(nonPrimaryNetwork);
// Verify primary wifi info is still the one being used.
assertThat(wifiStatusTracker.connected).isTrue();
assertThat(wifiStatusTracker.rssi).isEqualTo(primaryRssi);
assertThat(mWifiStatusTracker.connected).isTrue();
assertThat(mWifiStatusTracker.rssi).isEqualTo(primaryRssi);
// Lose the primary network.
mNetworkCallbackCaptor.getValue().onLost(primaryNetwork);
// Verify we aren't connected anymore.
assertThat(wifiStatusTracker.connected).isFalse();
assertThat(mWifiStatusTracker.connected).isFalse();
}
@Test
public void isCarrierMerged_typicalWifi_false() {
WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
when(primaryWifiInfo.isPrimary()).thenReturn(true);
NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)).thenReturn(true);
when(primaryCap.getTransportInfo()).thenReturn(primaryWifiInfo);
Network primaryNetwork = Mockito.mock(Network.class);
int primaryNetworkId = 1;
when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
assertThat(mWifiStatusTracker.isCarrierMerged).isFalse();
}
@Test
public void isCarrierMerged_typicalCellular_false() {
NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
Network primaryNetwork = Mockito.mock(Network.class);
int primaryNetworkId = 1;
when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
assertThat(mWifiStatusTracker.isCarrierMerged).isFalse();
}
@Test
public void isCarrierMerged_cellularCarrierMergedWifi_true() {
WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
when(primaryWifiInfo.isPrimary()).thenReturn(true);
when(primaryWifiInfo.isCarrierMerged()).thenReturn(true);
NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
when(primaryCap.getTransportInfo()).thenReturn(primaryWifiInfo);
Network primaryNetwork = Mockito.mock(Network.class);
int primaryNetworkId = 1;
when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
assertThat(mWifiStatusTracker.isCarrierMerged).isTrue();
}
/** Test for b/225902574. */
@Test
public void isCarrierMerged_cellularWithUnderlyingCarrierMergedWifi_true() {
WifiInfo underlyingCarrierMergedInfo = Mockito.mock(WifiInfo.class);
when(underlyingCarrierMergedInfo.isPrimary()).thenReturn(true);
when(underlyingCarrierMergedInfo.isCarrierMerged()).thenReturn(true);
NetworkCapabilities underlyingNetworkCapabilities = Mockito.mock(NetworkCapabilities.class);
when(underlyingNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
.thenReturn(true);
when(underlyingNetworkCapabilities.getTransportInfo())
.thenReturn(underlyingCarrierMergedInfo);
Network underlyingNetwork = Mockito.mock(Network.class);
when(mConnectivityManager.getNetworkCapabilities(underlyingNetwork))
.thenReturn(underlyingNetworkCapabilities);
NetworkCapabilities mainCapabilities = Mockito.mock(NetworkCapabilities.class);
when(mainCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
.thenReturn(true);
when(mainCapabilities.getTransportInfo()).thenReturn(null);
when(mainCapabilities.getUnderlyingNetworks())
.thenReturn(Arrays.asList(underlyingNetwork));
Network primaryNetwork = Mockito.mock(Network.class);
int primaryNetworkId = 1;
when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, mainCapabilities);
assertThat(mWifiStatusTracker.isCarrierMerged).isTrue();
}
@Test
public void isDefaultNetwork_typicalWifi_true() {
WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
when(primaryWifiInfo.isPrimary()).thenReturn(true);
NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)).thenReturn(true);
when(primaryCap.getTransportInfo()).thenReturn(primaryWifiInfo);
Network primaryNetwork = Mockito.mock(Network.class);
int primaryNetworkId = 1;
when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
assertThat(mWifiStatusTracker.isDefaultNetwork).isTrue();
}
@Test
public void isDefaultNetwork_typicalCellular_false() {
NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
Network primaryNetwork = Mockito.mock(Network.class);
int primaryNetworkId = 1;
when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
assertThat(mWifiStatusTracker.isDefaultNetwork).isFalse();
}
@Test
public void isDefaultNetwork_cellularCarrierMergedWifi_true() {
WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
when(primaryWifiInfo.isPrimary()).thenReturn(true);
when(primaryWifiInfo.isCarrierMerged()).thenReturn(true);
NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
when(primaryCap.getTransportInfo()).thenReturn(primaryWifiInfo);
Network primaryNetwork = Mockito.mock(Network.class);
int primaryNetworkId = 1;
when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
assertThat(mWifiStatusTracker.isDefaultNetwork).isTrue();
}
/** Test for b/225902574. */
@Test
public void isDefaultNetwork_cellularWithUnderlyingCarrierMergedWifi_true() {
WifiInfo underlyingCarrierMergedInfo = Mockito.mock(WifiInfo.class);
when(underlyingCarrierMergedInfo.isPrimary()).thenReturn(true);
when(underlyingCarrierMergedInfo.isCarrierMerged()).thenReturn(true);
NetworkCapabilities underlyingNetworkCapabilities = Mockito.mock(NetworkCapabilities.class);
when(underlyingNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
.thenReturn(true);
when(underlyingNetworkCapabilities.getTransportInfo())
.thenReturn(underlyingCarrierMergedInfo);
Network underlyingNetwork = Mockito.mock(Network.class);
when(mConnectivityManager.getNetworkCapabilities(underlyingNetwork))
.thenReturn(underlyingNetworkCapabilities);
NetworkCapabilities mainCapabilities = Mockito.mock(NetworkCapabilities.class);
when(mainCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
.thenReturn(true);
when(mainCapabilities.getTransportInfo()).thenReturn(null);
when(mainCapabilities.getUnderlyingNetworks())
.thenReturn(Arrays.asList(underlyingNetwork));
Network primaryNetwork = Mockito.mock(Network.class);
int primaryNetworkId = 1;
when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
mDefaultNetworkCallbackCaptor.getValue()
.onCapabilitiesChanged(primaryNetwork, mainCapabilities);
assertThat(mWifiStatusTracker.isDefaultNetwork).isTrue();
}
}