Merge "Add test coverage for NetworkStats.Bucket#getRoaming()"
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index 751a1e2..9fe6505 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -6,6 +6,8 @@
   }
 
   public class ConnectivityManager {
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void addUidToMeteredNetworkAllowList(int);
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void addUidToMeteredNetworkDenyList(int);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void factoryReset();
     method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public java.util.List<android.net.NetworkStateSnapshot> getAllNetworkStateSnapshots();
     method @Nullable public android.net.ProxyInfo getGlobalProxy();
@@ -14,6 +16,8 @@
     method @Nullable @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public android.net.NetworkCapabilities redactNetworkCapabilitiesForPackage(@NonNull android.net.NetworkCapabilities, int, @NonNull String);
     method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerDefaultNetworkCallbackForUid(int, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
     method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void removeUidFromMeteredNetworkAllowList(int);
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void removeUidFromMeteredNetworkDenyList(int);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void replaceFirewallChain(int, @NonNull int[]);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
     method @Deprecated public boolean requestRouteToHostAddress(int, java.net.InetAddress);
@@ -30,8 +34,6 @@
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void startCaptivePortalApp(@NonNull android.net.Network);
     method public void systemReady();
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void updateFirewallRule(int, int, boolean);
-    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void updateMeteredNetworkAllowList(int, boolean);
-    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void updateMeteredNetworkDenyList(int, boolean);
     field public static final String ACTION_CLEAR_DNS_CACHE = "android.net.action.CLEAR_DNS_CACHE";
     field public static final String ACTION_PROMPT_LOST_VALIDATION = "android.net.action.PROMPT_LOST_VALIDATION";
     field public static final String ACTION_PROMPT_PARTIAL_CONNECTIVITY = "android.net.action.PROMPT_PARTIAL_CONNECTIVITY";
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index 8651f34..68ca46d 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -5706,8 +5706,8 @@
     }
 
     /**
-     * Sets whether the specified UID is allowed to use data on metered networks even when
-     * background data is restricted.
+     * Adds the specified UID to the list of UIds that are allowed to use data on metered networks
+     * even when background data is restricted. The deny list takes precedence over the allow list.
      *
      * @param uid uid of target app
      * @throws IllegalStateException if updating allow list failed.
@@ -5719,17 +5719,40 @@
             android.Manifest.permission.NETWORK_STACK,
             NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
     })
-    public void updateMeteredNetworkAllowList(final int uid, final boolean add) {
+    public void addUidToMeteredNetworkAllowList(final int uid) {
         try {
-            mService.updateMeteredNetworkAllowList(uid, add);
+            mService.updateMeteredNetworkAllowList(uid, true /* add */);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Sets whether the specified UID is prevented from using background data on metered networks.
-     * Takes precedence over {@link #updateMeteredNetworkAllowList}.
+     * Removes the specified UID from the list of UIDs that are allowed to use background data on
+     * metered networks when background data is restricted. The deny list takes precedence over
+     * the allow list.
+     *
+     * @param uid uid of target app
+     * @throws IllegalStateException if updating allow list failed.
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_STACK,
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
+    })
+    public void removeUidFromMeteredNetworkAllowList(final int uid) {
+        try {
+            mService.updateMeteredNetworkAllowList(uid, false /* remove */);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Adds the specified UID to the list of UIDs that are not allowed to use background data on
+     * metered networks. Takes precedence over {@link #addUidToMeteredNetworkAllowList}.
      *
      * @param uid uid of target app
      * @throws IllegalStateException if updating deny list failed.
@@ -5741,9 +5764,32 @@
             android.Manifest.permission.NETWORK_STACK,
             NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
     })
-    public void updateMeteredNetworkDenyList(final int uid, final boolean add) {
+    public void addUidToMeteredNetworkDenyList(final int uid) {
         try {
-            mService.updateMeteredNetworkDenyList(uid, add);
+            mService.updateMeteredNetworkDenyList(uid, true /* add */);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Removes the specified UID from the list of UIds that can use use background data on metered
+     * networks if background data is not restricted. The deny list takes precedence over the
+     * allow list.
+     *
+     * @param uid uid of target app
+     * @throws IllegalStateException if updating deny list failed.
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_STACK,
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
+    })
+    public void removeUidFromMeteredNetworkDenyList(final int uid) {
+        try {
+            mService.updateMeteredNetworkDenyList(uid, false /* remove */);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/nearby/Android.bp b/nearby/Android.bp
index baa0740..b968f5d 100644
--- a/nearby/Android.bp
+++ b/nearby/Android.bp
@@ -31,7 +31,7 @@
 
 java_library {
     name: "service-nearby",
-    srcs: [],
+    srcs: ["service-src/**/*.java"],
     sdk_version: "module_current",
     min_sdk_version: "30",
     apex_available: ["com.android.tethering"],
diff --git a/nearby/service-src/com/android/server/nearby/NearbyService.java b/nearby/service-src/com/android/server/nearby/NearbyService.java
new file mode 100644
index 0000000..88752cc
--- /dev/null
+++ b/nearby/service-src/com/android/server/nearby/NearbyService.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 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.nearby;
+
+import android.content.Context;
+import android.os.Binder;
+
+/**
+ * Stub NearbyService class, used until NearbyService code is available in all branches.
+ *
+ * This can be published as an empty service in branches that use it.
+ */
+public final class NearbyService extends Binder {
+    public NearbyService(Context ctx) {
+        throw new UnsupportedOperationException("This is a stub service");
+    }
+
+    /** Called by the service initializer on each boot phase */
+    public void onBootPhase(int phase) {
+        // Do nothing
+    }
+}
diff --git a/service-t/Android.bp b/service-t/Android.bp
index 159a870..3d9820d 100644
--- a/service-t/Android.bp
+++ b/service-t/Android.bp
@@ -38,6 +38,7 @@
         "framework-connectivity-t-pre-jarjar",
         "framework-tethering.stubs.module_lib",
         "service-connectivity-pre-jarjar",
+        "service-nearby",
         "unsupportedappusage",
     ],
     static_libs: [
diff --git a/service-t/src/com/android/server/ConnectivityServiceInitializer.java b/service-t/src/com/android/server/ConnectivityServiceInitializer.java
index 67757af..25fe5e9 100644
--- a/service-t/src/com/android/server/ConnectivityServiceInitializer.java
+++ b/service-t/src/com/android/server/ConnectivityServiceInitializer.java
@@ -20,16 +20,19 @@
 import android.util.Log;
 
 import com.android.modules.utils.build.SdkLevel;
+import com.android.networkstack.apishim.ConstantsShim;
+import com.android.server.nearby.NearbyService;
 
 /**
  * Connectivity service initializer for core networking. This is called by system server to create
- * a new instance of ConnectivityService.
+ * a new instance of connectivity services.
  */
 public final class ConnectivityServiceInitializer extends SystemService {
     private static final String TAG = ConnectivityServiceInitializer.class.getSimpleName();
     private final ConnectivityService mConnectivity;
     private final IpSecService mIpSecService;
     private final NsdService mNsdService;
+    private final NearbyService mNearbyService;
 
     public ConnectivityServiceInitializer(Context context) {
         super(context);
@@ -38,6 +41,7 @@
         mConnectivity = new ConnectivityService(context);
         mIpSecService = createIpSecService(context);
         mNsdService = createNsdService(context);
+        mNearbyService = createNearbyService(context);
     }
 
     @Override
@@ -55,6 +59,19 @@
             Log.i(TAG, "Registering " + Context.NSD_SERVICE);
             publishBinderService(Context.NSD_SERVICE, mNsdService, /* allowIsolated= */ false);
         }
+
+        if (mNearbyService != null) {
+            Log.i(TAG, "Registering " + ConstantsShim.NEARBY_SERVICE);
+            publishBinderService(ConstantsShim.NEARBY_SERVICE, mNearbyService,
+                    /* allowIsolated= */ false);
+        }
+    }
+
+    @Override
+    public void onBootPhase(int phase) {
+        if (mNearbyService != null) {
+            mNearbyService.onBootPhase(phase);
+        }
     }
 
     /**
@@ -76,4 +93,17 @@
             return null;
         }
     }
+
+    /** Return Nearby service instance or null if current SDK is lower than T */
+    private NearbyService createNearbyService(final Context context) {
+        if (!SdkLevel.isAtLeastT()) return null;
+        try {
+            return new NearbyService(context);
+        } catch (UnsupportedOperationException e) {
+            // Nearby is not yet supported in all branches
+            // TODO: remove catch clause when it is available.
+            Log.i(TAG, "Skipping unsupported service " + ConstantsShim.NEARBY_SERVICE);
+            return null;
+        }
+    }
 }
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index a7f9157..a840242 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -881,6 +881,11 @@
         }
     }
 
+    protected void startActivity() throws Exception {
+        final Intent launchIntent = getIntentForComponent(TYPE_COMPONENT_ACTIVTIY);
+        mContext.startActivity(launchIntent);
+    }
+
     private void startForegroundService() throws Exception {
         final Intent launchIntent = getIntentForComponent(TYPE_COMPONENT_FOREGROUND_SERVICE);
         mContext.startForegroundService(launchIntent);
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataSaverModeTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
index 604a0b6..2f30536 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
@@ -20,6 +20,7 @@
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
 
+import static com.android.compatibility.common.util.FeatureUtil.isTV;
 import static com.android.cts.net.hostside.NetworkPolicyTestUtils.setRestrictBackground;
 import static com.android.cts.net.hostside.Property.DATA_SAVER_MODE;
 import static com.android.cts.net.hostside.Property.METERED_NETWORK;
@@ -27,14 +28,14 @@
 
 import static org.junit.Assert.fail;
 
+import androidx.test.filters.LargeTest;
+
 import com.android.compatibility.common.util.CddTest;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
-import androidx.test.filters.LargeTest;
-
 @RequiredProperties({DATA_SAVER_MODE, METERED_NETWORK})
 @LargeTest
 public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase {
@@ -113,6 +114,11 @@
         turnScreenOff();
         assertBackgroundNetworkAccess(false);
         turnScreenOn();
+        // On some TVs, it is possible that the activity on top may change after the screen is
+        // turned off and on again, so relaunch the activity in the test app again.
+        if (isTV()) {
+            startActivity();
+        }
         assertForegroundNetworkAccess();
 
         // Goes back to background state.
diff --git a/tests/cts/net/AndroidTestTemplate.xml b/tests/cts/net/AndroidTestTemplate.xml
index d605799..48a1c79 100644
--- a/tests/cts/net/AndroidTestTemplate.xml
+++ b/tests/cts/net/AndroidTestTemplate.xml
@@ -30,6 +30,8 @@
     </target_preparer>
     <target_preparer class="com.android.testutils.ConnectivityCheckTargetPreparer">
     </target_preparer>
+    <target_preparer class="com.android.testutils.DisableConfigSyncTargetPreparer">
+    </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.net.cts" />
         <option name="runtime-hint" value="9m4s" />
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index 9313ac2..07dcae3 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -55,6 +55,7 @@
     name: "non-connectivity-module-test",
     srcs: [
         "java/android/app/usage/*.java",
+        "java/android/net/EthernetNetworkUpdateRequestTest.java",
         "java/android/net/Ikev2VpnProfileTest.java",
         "java/android/net/IpMemoryStoreTest.java",
         "java/android/net/IpSecAlgorithmTest.java",
diff --git a/tests/unit/java/android/net/EthernetNetworkUpdateRequestTest.java b/tests/unit/java/android/net/EthernetNetworkUpdateRequestTest.java
new file mode 100644
index 0000000..314fbcf
--- /dev/null
+++ b/tests/unit/java/android/net/EthernetNetworkUpdateRequestTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 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 android.net;
+
+import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
+import static com.android.testutils.ParcelUtils.assertParcelSane;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(SC_V2)
+public class EthernetNetworkUpdateRequestTest {
+    private IpConfiguration buildIpConfiguration() {
+        return new IpConfiguration.Builder().setHttpProxy(
+                new ProxyInfo("test.example.com", 1234, "")).build();
+    }
+
+    private NetworkCapabilities buildNetworkCapabilities() {
+        return new NetworkCapabilities.Builder().addTransportType(
+                NetworkCapabilities.TRANSPORT_ETHERNET).build();
+    }
+
+    @Test
+    public void testParcelUnparcel() {
+        EthernetNetworkUpdateRequest reqWithNonNull =
+                new EthernetNetworkUpdateRequest.Builder().setIpConfiguration(
+                        buildIpConfiguration()).setNetworkCapabilities(
+                        buildNetworkCapabilities()).build();
+        EthernetNetworkUpdateRequest reqWithNullCaps =
+                new EthernetNetworkUpdateRequest.Builder().setIpConfiguration(
+                        buildIpConfiguration()).build();
+
+        assertParcelSane(reqWithNonNull, 2);
+        assertParcelSane(reqWithNullCaps, 2);
+    }
+}
diff --git a/tests/unit/java/com/android/server/NetworkManagementServiceTest.java b/tests/unit/java/com/android/server/NetworkManagementServiceTest.java
index a3b0e7c..7688a6b 100644
--- a/tests/unit/java/com/android/server/NetworkManagementServiceTest.java
+++ b/tests/unit/java/com/android/server/NetworkManagementServiceTest.java
@@ -250,7 +250,7 @@
         mNMService.setUidOnMeteredNetworkDenylist(TEST_UID, true);
         assertTrue("Should be true since mobile data usage is restricted",
                 mNMService.isNetworkRestricted(TEST_UID));
-        verify(mCm).updateMeteredNetworkDenyList(TEST_UID, true /* enabled */);
+        verify(mCm).addUidToMeteredNetworkDenyList(TEST_UID);
 
         mNMService.setDataSaverModeEnabled(true);
         verify(mNetdService).bandwidthEnableDataSaver(true);
@@ -258,16 +258,16 @@
         mNMService.setUidOnMeteredNetworkDenylist(TEST_UID, false);
         assertTrue("Should be true since data saver is on and the uid is not allowlisted",
                 mNMService.isNetworkRestricted(TEST_UID));
-        verify(mCm).updateMeteredNetworkDenyList(TEST_UID, true /* false */);
+        verify(mCm).removeUidFromMeteredNetworkDenyList(TEST_UID);
 
         mNMService.setUidOnMeteredNetworkAllowlist(TEST_UID, true);
         assertFalse("Should be false since data saver is on and the uid is allowlisted",
                 mNMService.isNetworkRestricted(TEST_UID));
-        verify(mCm).updateMeteredNetworkAllowList(TEST_UID, true /* enabled */);
+        verify(mCm).addUidToMeteredNetworkAllowList(TEST_UID);
 
         // remove uid from allowlist and turn datasaver off again
         mNMService.setUidOnMeteredNetworkAllowlist(TEST_UID, false);
-        verify(mCm).updateMeteredNetworkAllowList(TEST_UID, false /* enabled */);
+        verify(mCm).removeUidFromMeteredNetworkAllowList(TEST_UID);
         mNMService.setDataSaverModeEnabled(false);
         verify(mNetdService).bandwidthEnableDataSaver(false);
         assertFalse("Network should not be restricted when data saver is off",