Remove ConnectivityServiceTest signature perms use
To allow unit tests to run without platform certificates, remove
signature permission usage in ConnectivityServiceTest.
This mocks permission checks done in ConnectivityService for which the
test assumed that the permission was held, and mocks calls to
BatteryStatsManager. Calls to ActivityManagerService (through
PendingIntent) are done with shell permissions as the test uses real
PendingIntent mechanics.
Bug: 187935317
Test: atest FrameworksNetTests
Change-Id: If309d653ac2e9bbcf1b94bcee6336367289df359
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index b9076e9..8b91a45 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -1273,6 +1273,20 @@
public boolean getCellular464XlatEnabled() {
return NetworkProperties.isCellular464XlatEnabled().orElse(true);
}
+
+ /**
+ * @see PendingIntent#intentFilterEquals
+ */
+ public boolean intentFilterEquals(PendingIntent a, PendingIntent b) {
+ return a.intentFilterEquals(b);
+ }
+
+ /**
+ * @see LocationPermissionChecker
+ */
+ public LocationPermissionChecker makeLocationPermissionChecker(Context context) {
+ return new LocationPermissionChecker(context);
+ }
}
public ConnectivityService(Context context) {
@@ -1340,7 +1354,7 @@
mNetd = netd;
mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
- mLocationPermissionChecker = new LocationPermissionChecker(mContext);
+ mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext);
// To ensure uid state is synchronized with Network Policy, register for
// NetworkPolicyManagerService events must happen prior to NetworkPolicyManagerService
@@ -3918,7 +3932,7 @@
for (Map.Entry<NetworkRequest, NetworkRequestInfo> entry : mNetworkRequests.entrySet()) {
PendingIntent existingPendingIntent = entry.getValue().mPendingIntent;
if (existingPendingIntent != null &&
- existingPendingIntent.intentFilterEquals(pendingIntent)) {
+ mDeps.intentFilterEquals(existingPendingIntent, pendingIntent)) {
return entry.getValue();
}
}
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index 6c4bb90..5eb43f3 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -56,7 +56,6 @@
"java/**/*.kt",
],
test_suites: ["device-tests"],
- certificate: "platform",
jarjar_rules: "jarjar-rules.txt",
static_libs: [
"androidx.test.rules",
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index b0d849a..eae599d 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -18,10 +18,15 @@
import static android.Manifest.permission.CHANGE_NETWORK_STATE;
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
+import static android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE;
+import static android.Manifest.permission.CREATE_USERS;
import static android.Manifest.permission.DUMP;
+import static android.Manifest.permission.GET_INTENT_SENDER_INTENT;
import static android.Manifest.permission.LOCAL_MAC_ADDRESS;
import static android.Manifest.permission.NETWORK_FACTORY;
import static android.Manifest.permission.NETWORK_SETTINGS;
+import static android.Manifest.permission.NETWORK_STACK;
+import static android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.content.Intent.ACTION_PACKAGE_ADDED;
import static android.content.Intent.ACTION_PACKAGE_REMOVED;
@@ -132,6 +137,7 @@
import static com.android.testutils.MiscAsserts.assertRunsInAtMost;
import static com.android.testutils.MiscAsserts.assertSameElements;
import static com.android.testutils.MiscAsserts.assertThrows;
+import static com.android.testutils.TestPermissionUtil.runAsShell;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -257,6 +263,7 @@
import android.net.shared.PrivateDnsConfig;
import android.net.util.MultinetworkPolicyTracker;
import android.os.BadParcelableException;
+import android.os.BatteryStatsManager;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -295,6 +302,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.connectivity.resources.R;
+import com.android.internal.app.IBatteryStats;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnProfile;
import com.android.internal.util.ArrayUtils;
@@ -303,6 +311,7 @@
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.net.module.util.ArrayTrackRecord;
import com.android.net.module.util.CollectionUtils;
+import com.android.net.module.util.LocationPermissionChecker;
import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
import com.android.server.ConnectivityService.NetworkRequestInfo;
import com.android.server.connectivity.MockableSystemProperties;
@@ -486,6 +495,11 @@
@Mock Resources mResources;
@Mock ProxyTracker mProxyTracker;
+ // BatteryStatsManager is final and cannot be mocked with regular mockito, so just mock the
+ // underlying binder calls.
+ final BatteryStatsManager mBatteryStatsManager =
+ new BatteryStatsManager(mock(IBatteryStats.class));
+
private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
ArgumentCaptor.forClass(ResolverParamsParcel.class);
@@ -577,6 +591,7 @@
if (Context.NETWORK_POLICY_SERVICE.equals(name)) return mNetworkPolicyManager;
if (Context.SYSTEM_CONFIG_SERVICE.equals(name)) return mSystemConfigManager;
if (Context.NETWORK_STATS_SERVICE.equals(name)) return mStatsManager;
+ if (Context.BATTERY_STATS_SERVICE.equals(name)) return mBatteryStatsManager;
return super.getSystemService(name);
}
@@ -657,6 +672,15 @@
public void setPermission(String permission, Integer granted) {
mMockedPermissions.put(permission, granted);
}
+
+ @Override
+ public Intent registerReceiverForAllUsers(@Nullable BroadcastReceiver receiver,
+ @NonNull IntentFilter filter, @Nullable String broadcastPermission,
+ @Nullable Handler scheduler) {
+ // TODO: ensure MultinetworkPolicyTracker's BroadcastReceiver is tested; just returning
+ // null should not pass the test
+ return null;
+ }
}
private void waitForIdle() {
@@ -1206,7 +1230,24 @@
return mDeviceIdleInternal;
}
},
- mNetworkManagementService, mMockNetd, userId, mVpnProfileStore);
+ mNetworkManagementService, mMockNetd, userId, mVpnProfileStore,
+ new SystemServices(mServiceContext) {
+ @Override
+ public String settingsSecureGetStringForUser(String key, int userId) {
+ switch (key) {
+ // Settings keys not marked as @Readable are not readable from
+ // non-privileged apps, unless marked as testOnly=true
+ // (atest refuses to install testOnly=true apps), even if mocked
+ // in the content provider, because
+ // Settings.Secure.NameValueCache#getStringForUser checks the key
+ // before querying the mock settings provider.
+ case Settings.Secure.ALWAYS_ON_VPN_APP:
+ return null;
+ default:
+ return super.settingsSecureGetStringForUser(key, userId);
+ }
+ }
+ }, new Ikev2SessionCreator());
}
public void setUids(Set<UidRange> uids) {
@@ -1590,6 +1631,11 @@
mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
new FakeSettingsProvider());
mServiceContext.setUseRegisteredHandlers(true);
+ mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
+ mServiceContext.setPermission(CONTROL_OEM_PAID_NETWORK_PREFERENCE, PERMISSION_GRANTED);
+ mServiceContext.setPermission(PACKET_KEEPALIVE_OFFLOAD, PERMISSION_GRANTED);
+ mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_GRANTED);
mAlarmManagerThread = new HandlerThread("TestAlarmManager");
mAlarmManagerThread.start();
@@ -1649,6 +1695,13 @@
return mPolicyTracker;
}).when(deps).makeMultinetworkPolicyTracker(any(), any(), any());
doReturn(true).when(deps).getCellular464XlatEnabled();
+ doAnswer(inv ->
+ new LocationPermissionChecker(inv.getArgument(0)) {
+ @Override
+ protected int getCurrentUser() {
+ return runAsShell(CREATE_USERS, () -> super.getCurrentUser());
+ }
+ }).when(deps).makeLocationPermissionChecker(any());
doReturn(60000).when(mResources).getInteger(R.integer.config_networkTransitionTimeout);
doReturn("").when(mResources).getString(R.string.config_networkCaptivePortalServerUrl);
@@ -1678,6 +1731,12 @@
doReturn(mResources).when(mockResContext).getResources();
ConnectivityResources.setResourcesContextForTest(mockResContext);
+ doAnswer(inv -> {
+ final PendingIntent a = inv.getArgument(0);
+ final PendingIntent b = inv.getArgument(1);
+ return runAsShell(GET_INTENT_SENDER_INTENT, () -> a.intentFilterEquals(b));
+ }).when(deps).intentFilterEquals(any(), any());
+
return deps;
}
@@ -9237,8 +9296,7 @@
mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
PERMISSION_DENIED);
mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
- mServiceContext.setPermission(Manifest.permission.NETWORK_STACK,
- PERMISSION_DENIED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
mServiceContext.setPermission(Manifest.permission.NETWORK_SETUP_WIZARD,
PERMISSION_DENIED);
}
@@ -9679,7 +9737,7 @@
setupConnectionOwnerUid(vpnOwnerUid, vpnType);
// Test as VPN app
- mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
mServiceContext.setPermission(
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED);
}
@@ -9719,8 +9777,7 @@
public void testGetConnectionOwnerUidVpnServiceNetworkStackDoesNotThrow() throws Exception {
final int myUid = Process.myUid();
setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
- mServiceContext.setPermission(
- android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo()));
}
@@ -9888,8 +9945,7 @@
public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception {
final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
- mServiceContext.setPermission(
- android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
assertTrue(
"NetworkStack permission not applied",
mService.checkConnectivityDiagnosticsPermissions(
@@ -9905,7 +9961,7 @@
nc.setAdministratorUids(new int[] {wrongUid});
final NetworkAgentInfo naiWithUid = fakeWifiNai(nc);
- mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
assertFalse(
"Mismatched uid/package name should not pass the location permission check",
@@ -9915,7 +9971,7 @@
private void verifyConnectivityDiagnosticsPermissionsWithNetworkAgentInfo(
NetworkAgentInfo info, boolean expectPermission) {
- mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
assertEquals(
"Unexpected ConnDiags permission",
@@ -9983,7 +10039,7 @@
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
- mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
assertTrue(
"NetworkCapabilities administrator uid permission not applied",
@@ -10000,7 +10056,7 @@
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
- mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
// Use wrong pid and uid
assertFalse(
@@ -10026,8 +10082,7 @@
final NetworkRequest request = new NetworkRequest.Builder().build();
when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
- mServiceContext.setPermission(
- android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
mService.registerConnectivityDiagnosticsCallback(
mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
@@ -10046,8 +10101,7 @@
final NetworkRequest request = new NetworkRequest.Builder().build();
when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
- mServiceContext.setPermission(
- android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
mService.registerConnectivityDiagnosticsCallback(
mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
index 0ba5f7d..3dd6598 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -16,12 +16,17 @@
package com.android.server.net;
+import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
+import static android.Manifest.permission.UPDATE_DEVICE_STATS;
import static android.content.Intent.ACTION_UID_REMOVED;
import static android.content.Intent.EXTRA_UID;
+import static android.content.pm.PackageManager.PERMISSION_DENIED;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.NetworkIdentity.OEM_PAID;
import static android.net.NetworkIdentity.OEM_PRIVATE;
+import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
@@ -106,6 +111,7 @@
import android.provider.Settings;
import android.telephony.TelephonyManager;
+import androidx.annotation.Nullable;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -199,6 +205,26 @@
if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
return mBaseContext.getSystemService(name);
}
+
+ @Override
+ public void enforceCallingOrSelfPermission(String permission, @Nullable String message) {
+ if (checkCallingOrSelfPermission(permission) != PERMISSION_GRANTED) {
+ throw new SecurityException("Test does not have mocked permission " + permission);
+ }
+ }
+
+ @Override
+ public int checkCallingOrSelfPermission(String permission) {
+ switch (permission) {
+ case PERMISSION_MAINLINE_NETWORK_STACK:
+ case READ_NETWORK_USAGE_HISTORY:
+ case UPDATE_DEVICE_STATS:
+ return PERMISSION_GRANTED;
+ default:
+ return PERMISSION_DENIED;
+ }
+
+ }
}
private final Clock mClock = new SimpleClock(ZoneOffset.UTC) {