Implement INetworkMonitorCallbacks#notifyNetworkTestedWithExtras.

INetworkMonitorCallbacks defines notifyNetworkTestedWithExtras() for
notifying ConnectivityService of networks being tested along with a
PersistableBundle of extras. A new event is introduced for
NetworkStateTrackerHandler to notify the ConnectivityDiagnosticsHandler
before continuing with the normal processing for "network tested"
notifications. The event is also used in the
ConnectivityDiagnosticsHandler.

Bug: 143187964
Bug: 147391402
Test: compiles.
Test: atest CtsNetTestCases FrameworksNetTests
Change-Id: Iab29da790c0f5faae68227770bc3a84bbc94f124
Merged-In: Iab29da790c0f5faae68227770bc3a84bbc94f124
This commit is contained in:
Cody Kesting
2020-01-05 14:06:39 -08:00
parent 49c185e487
commit 83bb5fa762
6 changed files with 455 additions and 102 deletions

View File

@@ -23,6 +23,7 @@ import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL;
@@ -119,6 +120,7 @@ import static org.mockito.Mockito.when;
import android.Manifest;
import android.annotation.NonNull;
import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -132,6 +134,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.location.LocationManager;
import android.net.CaptivePortalData;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
@@ -177,6 +180,7 @@ import android.net.shared.PrivateDnsConfig;
import android.net.util.MultinetworkPolicyTracker;
import android.os.BadParcelableException;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.ConditionVariable;
import android.os.Handler;
@@ -187,6 +191,7 @@ import android.os.Looper;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -218,6 +223,7 @@ import com.android.server.connectivity.DefaultNetworkMetrics;
import com.android.server.connectivity.IpConnectivityMetrics;
import com.android.server.connectivity.MockableSystemProperties;
import com.android.server.connectivity.Nat464Xlat;
import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
import com.android.server.connectivity.ProxyTracker;
import com.android.server.connectivity.Vpn;
@@ -292,6 +298,8 @@ public class ConnectivityServiceTest {
private static final int UNREASONABLY_LONG_ALARM_WAIT_MS = 1000;
private static final long TIMESTAMP = 1234L;
private static final String CLAT_PREFIX = "v4-";
private static final String MOBILE_IFNAME = "test_rmnet_data0";
private static final String WIFI_IFNAME = "test_wlan0";
@@ -327,6 +335,8 @@ public class ConnectivityServiceTest {
@Mock AlarmManager mAlarmManager;
@Mock IConnectivityDiagnosticsCallback mConnectivityDiagnosticsCallback;
@Mock IBinder mIBinder;
@Mock LocationManager mLocationManager;
@Mock AppOpsManager mAppOpsManager;
private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
ArgumentCaptor.forClass(ResolverParamsParcel.class);
@@ -412,6 +422,8 @@ public class ConnectivityServiceTest {
if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
if (Context.USER_SERVICE.equals(name)) return mUserManager;
if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager;
if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager;
if (Context.APP_OPS_SERVICE.equals(name)) return mAppOpsManager;
return super.getSystemService(name);
}
@@ -564,6 +576,7 @@ public class ConnectivityServiceTest {
private int mProbesCompleted;
private int mProbesSucceeded;
private String mNmValidationRedirectUrl = null;
private PersistableBundle mValidationExtras = PersistableBundle.EMPTY;
private boolean mNmProvNotificationRequested = false;
private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
@@ -631,8 +644,8 @@ public class ConnectivityServiceTest {
}
mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded);
mNmCallbacks.notifyNetworkTested(
mNmValidationResult, mNmValidationRedirectUrl);
mNmCallbacks.notifyNetworkTestedWithExtras(
mNmValidationResult, mNmValidationRedirectUrl, TIMESTAMP, mValidationExtras);
if (mNmValidationRedirectUrl != null) {
mNmCallbacks.showProvisioningNotification(
@@ -970,6 +983,8 @@ public class ConnectivityServiceTest {
// not inherit from NetworkAgent.
private TestNetworkAgentWrapper mMockNetworkAgent;
private VpnInfo mVpnInfo;
public MockVpn(int userId) {
super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
userId);
@@ -1041,6 +1056,17 @@ public class ConnectivityServiceTest {
mConnected = false;
mConfig = null;
}
@Override
public synchronized VpnInfo getVpnInfo() {
if (mVpnInfo != null) return mVpnInfo;
return super.getVpnInfo();
}
private void setVpnInfo(VpnInfo vpnInfo) {
mVpnInfo = vpnInfo;
}
}
private void mockVpn(int uid) {
@@ -6368,7 +6394,7 @@ public class ConnectivityServiceTest {
new NetworkCapabilities(), TYPE_ETHERNET, 0, NetworkRequest.Type.NONE);
try {
mService.registerConnectivityDiagnosticsCallback(
mConnectivityDiagnosticsCallback, request);
mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
fail("registerConnectivityDiagnosticsCallback should throw on invalid NetworkRequest");
} catch (IllegalArgumentException expected) {
}
@@ -6382,7 +6408,7 @@ public class ConnectivityServiceTest {
when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
mService.registerConnectivityDiagnosticsCallback(
mConnectivityDiagnosticsCallback, wifiRequest);
mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
verify(mIBinder, timeout(TIMEOUT_MS))
.linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
@@ -6406,7 +6432,7 @@ public class ConnectivityServiceTest {
when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
mService.registerConnectivityDiagnosticsCallback(
mConnectivityDiagnosticsCallback, wifiRequest);
mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
verify(mIBinder, timeout(TIMEOUT_MS))
.linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
@@ -6417,7 +6443,7 @@ public class ConnectivityServiceTest {
// Register the same callback again
mService.registerConnectivityDiagnosticsCallback(
mConnectivityDiagnosticsCallback, wifiRequest);
mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
// Block until all other events are done processing.
HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
@@ -6426,4 +6452,145 @@ public class ConnectivityServiceTest {
mService.mConnectivityDiagnosticsCallbacks.containsKey(
mConnectivityDiagnosticsCallback));
}
@Test
public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception {
final NetworkAgentInfo naiWithoutUid =
new NetworkAgentInfo(
null, null, null, null, null, new NetworkCapabilities(), null,
mServiceContext, null, null, mService, null, null, null, 0);
mServiceContext.setPermission(
android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
assertTrue(
"NetworkStack permission not applied",
mService.checkConnectivityDiagnosticsPermissions(
Process.myPid(), Process.myUid(), naiWithoutUid,
mContext.getOpPackageName()));
}
@Test
public void testCheckConnectivityDiagnosticsPermissionsNoLocationPermission() throws Exception {
final NetworkAgentInfo naiWithoutUid =
new NetworkAgentInfo(
null, null, null, null, null, new NetworkCapabilities(), null,
mServiceContext, null, null, mService, null, null, null, 0);
mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
assertFalse(
"ACCESS_FINE_LOCATION permission necessary for Connectivity Diagnostics",
mService.checkConnectivityDiagnosticsPermissions(
Process.myPid(), Process.myUid(), naiWithoutUid,
mContext.getOpPackageName()));
}
@Test
public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception {
final NetworkAgentInfo naiWithoutUid =
new NetworkAgentInfo(
null, null, null, null, null, new NetworkCapabilities(), null,
mServiceContext, null, null, mService, null, null, null, 0);
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
// setUp() calls mockVpn() which adds a VPN with the Test Runner's uid. Configure it to be
// active
final VpnInfo info = new VpnInfo();
info.ownerUid = Process.myUid();
info.vpnIface = "interface";
mMockVpn.setVpnInfo(info);
assertTrue(
"Active VPN permission not applied",
mService.checkConnectivityDiagnosticsPermissions(
Process.myPid(), Process.myUid(), naiWithoutUid,
mContext.getOpPackageName()));
}
@Test
public void testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator() throws Exception {
final NetworkCapabilities nc = new NetworkCapabilities();
nc.setAdministratorUids(Arrays.asList(Process.myUid()));
final NetworkAgentInfo naiWithUid =
new NetworkAgentInfo(
null, null, null, null, null, nc, null, mServiceContext, null, null,
mService, null, null, null, 0);
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
// Disconnect mock vpn so the uid check on NetworkAgentInfo is tested
mMockVpn.disconnect();
assertTrue(
"NetworkCapabilities administrator uid permission not applied",
mService.checkConnectivityDiagnosticsPermissions(
Process.myPid(), Process.myUid(), naiWithUid, mContext.getOpPackageName()));
}
@Test
public void testCheckConnectivityDiagnosticsPermissionsFails() throws Exception {
final NetworkCapabilities nc = new NetworkCapabilities();
nc.setOwnerUid(Process.myUid());
nc.setAdministratorUids(Arrays.asList(Process.myUid()));
final NetworkAgentInfo naiWithUid =
new NetworkAgentInfo(
null, null, null, null, null, nc, null, mServiceContext, null, null,
mService, null, null, null, 0);
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
// Use wrong pid and uid
assertFalse(
"Permissions allowed when they shouldn't be granted",
mService.checkConnectivityDiagnosticsPermissions(
Process.myPid() + 1, Process.myUid() + 1, naiWithUid,
mContext.getOpPackageName()));
}
private void setupLocationPermissions(
int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.targetSdkVersion = targetSdk;
when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
.thenReturn(applicationInfo);
when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle);
when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()), eq(mContext.getPackageName())))
.thenReturn(AppOpsManager.MODE_ALLOWED);
mServiceContext.setPermission(perm, PERMISSION_GRANTED);
}
@Test
public void testConnectivityDiagnosticsCallbackOnConnectivityReport() throws Exception {
final NetworkRequest request = new NetworkRequest.Builder().build();
when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
mServiceContext.setPermission(
android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
mService.registerConnectivityDiagnosticsCallback(
mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
// Block until all other events are done processing.
HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
// Connect the cell agent verify that it notifies TestNetworkCallback that it is available
final TestNetworkCallback callback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(callback);
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
callback.assertNoCallback();
// Wait for onConnectivityReport to fire
verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
.onConnectivityReport(any(ConnectivityReport.class));
}
}