Listen to permission changes in permission monitor
Bug: 369646309
Test: atest
ConnectivityCoverageTests:android.net.connectivity.com.android.server.connectivity.PermissionMonitorTest
Change-Id: I23c524baaee6b9b06a855fb811906e5189ef03fd
diff --git a/common/flags.aconfig b/common/flags.aconfig
index 60a827b..5f279fa 100644
--- a/common/flags.aconfig
+++ b/common/flags.aconfig
@@ -165,3 +165,12 @@
bug: "372936361"
is_fixed_read_only: true
}
+
+flag {
+ name: "restrict_local_network"
+ is_exported: true
+ namespace: "android_core_networking"
+ description: "Flag for controlling access to the local network behind a new runtime permission. Requires ConnectivityCompatChanges.RESTRICT_LOCAL_NETWORK to enable feature."
+ bug: "365139289"
+ is_fixed_read_only: true
+}
diff --git a/service/src/com/android/server/connectivity/PermissionMonitor.java b/service/src/com/android/server/connectivity/PermissionMonitor.java
index beaa174..0d388e8 100755
--- a/service/src/com/android/server/connectivity/PermissionMonitor.java
+++ b/service/src/com/android/server/connectivity/PermissionMonitor.java
@@ -31,6 +31,7 @@
import static android.net.INetd.PERMISSION_UNINSTALLED;
import static android.net.INetd.PERMISSION_UPDATE_DEVICE_STATS;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
+import static android.net.connectivity.ConnectivityCompatChanges.RESTRICT_LOCAL_NETWORK;
import static android.os.Process.INVALID_UID;
import static android.os.Process.SYSTEM_UID;
@@ -38,6 +39,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.compat.CompatChanges;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -70,6 +72,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.modules.utils.build.SdkLevel;
+import com.android.net.flags.Flags;
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.SharedLog;
import com.android.networkstack.apishim.ProcessShimImpl;
@@ -279,6 +282,12 @@
mContext = context;
mBpfNetMaps = bpfNetMaps;
mThread = thread;
+ if (Flags.restrictLocalNetwork()) {
+ // This listener should finish registration by the time the system has completed
+ // boot setup such that any changes to runtime permissions for local network
+ // restrictions can only occur after this registration has completed.
+ mPackageManager.addOnPermissionsChangeListener(new PermissionChangeListener());
+ }
}
private void ensureRunningOnHandlerThread() {
@@ -1311,4 +1320,19 @@
private static void loge(String s, Throwable e) {
Log.e(TAG, s, e);
}
+
+ private class PermissionChangeListener implements PackageManager.OnPermissionsChangedListener {
+ @Override
+ public void onPermissionsChanged(int uid) {
+ // RESTRICT_LOCAL_NETWORK is a compat change that is enabled when developers manually
+ // opt-in to this change, or when the app's targetSdkVersion is greater than 36.
+ // The RESTRICT_LOCAL_NETWORK compat change is used here instead of the
+ // Flags.restrictLocalNetwork() is used to offer the feature to devices, but it will
+ // only be enforced when develoeprs choose to enable it.
+ // TODO(b/394567896): Update compat change checks
+ if (CompatChanges.isChangeEnabled(RESTRICT_LOCAL_NETWORK, uid)) {
+ // TODO(b/388803658): Update network permissions and record change
+ }
+ }
+ }
}
diff --git a/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
index 06bdca6..375d604 100644
--- a/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
+++ b/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
@@ -16,6 +16,7 @@
package com.android.server.net.integrationtests
+import android.Manifest.permission
import android.app.usage.NetworkStatsManager
import android.content.ComponentName
import android.content.Context
@@ -66,6 +67,7 @@
import com.android.testutils.DeviceInfoUtils
import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
import com.android.testutils.TestableNetworkCallback
+import com.android.testutils.runAsShell
import com.android.testutils.tryTest
import java.util.function.BiConsumer
import java.util.function.Consumer
@@ -208,7 +210,9 @@
networkStackClient = TestNetworkStackClient(realContext)
networkStackClient.start()
- service = TestConnectivityService(TestDependencies())
+ service = runAsShell(permission.OBSERVE_GRANT_REVOKE_PERMISSIONS) {
+ TestConnectivityService(TestDependencies())
+ }
cm = ConnectivityManager(context, service)
context.addMockSystemService(Context.CONNECTIVITY_SERVICE, cm)
context.addMockSystemService(Context.NETWORK_STATS_SERVICE, statsManager)
diff --git a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
index 5bde31a..55c68b7 100644
--- a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -22,6 +22,7 @@
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
import static android.Manifest.permission.INTERNET;
import static android.Manifest.permission.NETWORK_STACK;
+import static android.Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS;
import static android.Manifest.permission.UPDATE_DEVICE_STATS;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_OEM;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRODUCT;
@@ -41,6 +42,7 @@
import static android.os.Process.SYSTEM_UID;
import static com.android.server.connectivity.PermissionMonitor.isHigherNetworkPermission;
+import static com.android.testutils.TestPermissionUtil.runAsShell;
import static junit.framework.Assert.fail;
@@ -1235,8 +1237,10 @@
// Use the real context as this test must ensure the *real* system package holds the
// necessary permission.
final Context realContext = InstrumentationRegistry.getContext();
- final PermissionMonitor monitor = new PermissionMonitor(
- realContext, mNetdService, mBpfNetMaps, mHandlerThread);
+ final PermissionMonitor monitor = runAsShell(
+ OBSERVE_GRANT_REVOKE_PERMISSIONS,
+ () -> new PermissionMonitor(realContext, mNetdService, mBpfNetMaps, mHandlerThread)
+ );
final PackageManager manager = realContext.getPackageManager();
final PackageInfo systemInfo = manager.getPackageInfo(REAL_SYSTEM_PACKAGE_NAME,
GET_PERMISSIONS | MATCH_ANY_USER);