Merge "Replace NotificationManager @hide APIs"
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 327e42b..44ebff9 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -353,10 +353,11 @@
 
     private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) {
         // The subtype can be changed with (TODO) setLegacySubtype, but it starts
-        // with the type and an empty description.
+        // with 0 (TelephonyManager.NETWORK_TYPE_UNKNOWN) and an empty description.
         final NetworkInfo ni = new NetworkInfo(config.legacyType, 0, config.legacyTypeName, "");
         ni.setIsAvailable(true);
-        ni.setExtraInfo(config.getLegacyExtraInfo());
+        ni.setDetailedState(NetworkInfo.DetailedState.CONNECTING, null /* reason */,
+                config.getLegacyExtraInfo());
         return ni;
     }
 
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index be33f4e..12ddc62 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -170,6 +170,7 @@
             NET_CAPABILITY_MCX,
             NET_CAPABILITY_PARTIAL_CONNECTIVITY,
             NET_CAPABILITY_TEMPORARILY_NOT_METERED,
+            NET_CAPABILITY_OEM_PRIVATE,
     })
     public @interface NetCapability { }
 
@@ -345,8 +346,15 @@
      */
     public static final int NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25;
 
+    /**
+     * Indicates that this network is private to the OEM and meant only for OEM use.
+     * @hide
+     */
+    @SystemApi
+    public static final int NET_CAPABILITY_OEM_PRIVATE = 26;
+
     private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
-    private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_TEMPORARILY_NOT_METERED;
+    private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_OEM_PRIVATE;
 
     /**
      * Network capabilities that are expected to be mutable, i.e., can change while a particular
@@ -404,7 +412,8 @@
      * {@see #maybeMarkCapabilitiesRestricted}.
      */
     private static final long FORCE_RESTRICTED_CAPABILITIES =
-            (1 << NET_CAPABILITY_OEM_PAID);
+            (1 << NET_CAPABILITY_OEM_PAID)
+            | (1 << NET_CAPABILITY_OEM_PRIVATE);
 
     /**
      * Capabilities that suggest that a network is unrestricted.
@@ -1910,6 +1919,7 @@
             case NET_CAPABILITY_MCX:                  return "MCX";
             case NET_CAPABILITY_PARTIAL_CONNECTIVITY: return "PARTIAL_CONNECTIVITY";
             case NET_CAPABILITY_TEMPORARILY_NOT_METERED:    return "TEMPORARILY_NOT_METERED";
+            case NET_CAPABILITY_OEM_PRIVATE:          return "OEM_PRIVATE";
             default:                                  return Integer.toString(capability);
         }
     }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index ce3522a..da2a3de 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2435,9 +2435,9 @@
 
         try {
             if (VDBG || DDBG) log("Setting MTU size: " + iface + ", " + mtu);
-            mNMS.setMtu(iface, mtu);
-        } catch (Exception e) {
-            Slog.e(TAG, "exception in setMtu()" + e);
+            mNetd.interfaceSetMtu(iface, mtu);
+        } catch (RemoteException | ServiceSpecificException e) {
+            Slog.e(TAG, "exception in interfaceSetMtu()" + e);
         }
     }
 
@@ -6082,7 +6082,7 @@
             for (final String iface : interfaceDiff.added) {
                 try {
                     if (DBG) log("Adding iface " + iface + " to network " + netId);
-                    mNMS.addInterfaceToNetwork(iface, netId);
+                    mNetd.networkAddInterface(netId, iface);
                     wakeupModifyInterface(iface, caps, true);
                     bs.noteNetworkInterfaceType(iface, legacyType);
                 } catch (Exception e) {
@@ -6094,7 +6094,7 @@
             try {
                 if (DBG) log("Removing iface " + iface + " from network " + netId);
                 wakeupModifyInterface(iface, caps, false);
-                mNMS.removeInterfaceFromNetwork(iface, netId);
+                mNetd.networkRemoveInterface(netId, iface);
             } catch (Exception e) {
                 loge("Exception removing interface: " + e);
             }
@@ -6260,9 +6260,9 @@
         final int newPermission = getNetworkPermission(newNc);
         if (oldPermission != newPermission && nai.created && !nai.isVPN()) {
             try {
-                mNMS.setNetworkPermission(nai.network.netId, newPermission);
-            } catch (RemoteException e) {
-                loge("Exception in setNetworkPermission: " + e);
+                mNetd.networkSetPermissionForNetwork(nai.network.netId, newPermission);
+            } catch (RemoteException | ServiceSpecificException e) {
+                loge("Exception in networkSetPermissionForNetwork: " + e);
             }
         }
     }
@@ -6704,11 +6704,11 @@
 
         try {
             if (null != newNetwork) {
-                mNMS.setDefaultNetId(newNetwork.network.netId);
+                mNetd.networkSetDefault(newNetwork.network.netId);
             } else {
-                mNMS.clearDefaultNetId();
+                mNetd.networkClearDefault();
             }
-        } catch (Exception e) {
+        } catch (RemoteException | ServiceSpecificException e) {
             loge("Exception setting default network :" + e);
         }
 
diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index e169312..11a83eb 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
@@ -30,6 +30,7 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
@@ -359,6 +360,33 @@
     }
 
     @Test
+    public void testOemPrivate() {
+        NetworkCapabilities nc = new NetworkCapabilities();
+        // By default OEM_PRIVATE is neither in the unwanted or required lists and the network is
+        // not restricted.
+        assertFalse(nc.hasUnwantedCapability(NET_CAPABILITY_OEM_PRIVATE));
+        assertFalse(nc.hasCapability(NET_CAPABILITY_OEM_PRIVATE));
+        nc.maybeMarkCapabilitiesRestricted();
+        assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+
+        // Adding OEM_PRIVATE to capability list should make network restricted.
+        nc.addCapability(NET_CAPABILITY_OEM_PRIVATE);
+        nc.addCapability(NET_CAPABILITY_INTERNET);  // Combine with unrestricted capability.
+        nc.maybeMarkCapabilitiesRestricted();
+        assertTrue(nc.hasCapability(NET_CAPABILITY_OEM_PRIVATE));
+        assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+
+        // Now let's make request for OEM_PRIVATE network.
+        NetworkCapabilities nr = new NetworkCapabilities();
+        nr.addCapability(NET_CAPABILITY_OEM_PRIVATE);
+        nr.maybeMarkCapabilitiesRestricted();
+        assertTrue(nr.satisfiedByNetworkCapabilities(nc));
+
+        // Request fails for network with the default capabilities.
+        assertFalse(nr.satisfiedByNetworkCapabilities(new NetworkCapabilities()));
+    }
+
+    @Test
     public void testUnwantedCapabilities() {
         NetworkCapabilities network = new NetworkCapabilities();
 
diff --git a/tests/net/java/android/net/ipmemorystore/ParcelableTests.java b/tests/net/java/android/net/ipmemorystore/ParcelableTests.java
index 02f5286..603c875 100644
--- a/tests/net/java/android/net/ipmemorystore/ParcelableTests.java
+++ b/tests/net/java/android/net/ipmemorystore/ParcelableTests.java
@@ -19,6 +19,8 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import android.net.networkstack.aidl.quirks.IPv6ProvisioningLossQuirk;
+import android.net.networkstack.aidl.quirks.IPv6ProvisioningLossQuirkParcelable;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -46,7 +48,7 @@
         builder.setAssignedV4Address((Inet4Address) Inet4Address.getByName("1.2.3.4"));
         // lease will expire in two hours
         builder.setAssignedV4AddressExpiry(System.currentTimeMillis() + 7_200_000);
-        // groupHint stays null this time around
+        // cluster stays null this time around
         builder.setDnsAddresses(Collections.emptyList());
         builder.setMtu(18);
         in = builder.build();
@@ -69,7 +71,7 @@
         // Verify that this test does not miss any new field added later.
         // If any field is added to NetworkAttributes it must be tested here for parceling
         // roundtrip.
-        assertEquals(5, Arrays.stream(NetworkAttributes.class.getDeclaredFields())
+        assertEquals(6, Arrays.stream(NetworkAttributes.class.getDeclaredFields())
                 .filter(f -> !Modifier.isStatic(f.getModifiers())).count());
     }
 
@@ -104,6 +106,22 @@
         assertEquals(in.confidence, out.confidence, 0.01f /* delta */);
     }
 
+    @Test
+    public void testIPv6ProvisioningLossQuirkParceling() throws Exception {
+        final NetworkAttributes.Builder builder = new NetworkAttributes.Builder();
+        final IPv6ProvisioningLossQuirkParcelable parcelable =
+                new IPv6ProvisioningLossQuirkParcelable();
+        final long expiry = System.currentTimeMillis() + 7_200_000;
+
+        parcelable.detectionCount = 3;
+        parcelable.quirkExpiry = expiry; // quirk info will expire in two hours
+        builder.setIpv6ProvLossQuirk(IPv6ProvisioningLossQuirk.fromStableParcelable(parcelable));
+        final NetworkAttributes in = builder.build();
+
+        final NetworkAttributes out = new NetworkAttributes(parcelingRoundTrip(in.toParcelable()));
+        assertEquals(out.ipv6ProvisioningLossQuirk, in.ipv6ProvisioningLossQuirk);
+    }
+
     private <T extends Parcelable> T parcelingRoundTrip(final T in) throws Exception {
         final Parcel p = Parcel.obtain();
         in.writeToParcel(p, /* flags */ 0);
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 9e7d4ad..3a46291 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -6031,23 +6031,23 @@
         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
         mCellNetworkAgent.connect(true);
         trustedCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        verify(mNetworkManagementService).setDefaultNetId(eq(mCellNetworkAgent.getNetwork().netId));
-        reset(mNetworkManagementService);
+        verify(mMockNetd).networkSetDefault(eq(mCellNetworkAgent.getNetwork().netId));
+        reset(mMockNetd);
 
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(true);
         trustedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
-        verify(mNetworkManagementService).setDefaultNetId(eq(mWiFiNetworkAgent.getNetwork().netId));
-        reset(mNetworkManagementService);
+        verify(mMockNetd).networkSetDefault(eq(mWiFiNetworkAgent.getNetwork().netId));
+        reset(mMockNetd);
 
         mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED);
         trustedCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
-        verify(mNetworkManagementService).setDefaultNetId(eq(mCellNetworkAgent.getNetwork().netId));
-        reset(mNetworkManagementService);
+        verify(mMockNetd).networkSetDefault(eq(mCellNetworkAgent.getNetwork().netId));
+        reset(mMockNetd);
 
         mCellNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED);
         trustedCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
-        verify(mNetworkManagementService).clearDefaultNetId();
+        verify(mMockNetd).networkClearDefault();
 
         mCm.unregisterNetworkCallback(trustedCallback);
     }
@@ -6151,6 +6151,7 @@
         verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
         assertRoutesAdded(cellNetId, ipv6Subnet, defaultRoute);
         verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
+        verify(mMockNetd, times(1)).networkAddInterface(cellNetId, MOBILE_IFNAME);
         verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
                 TYPE_MOBILE);
 
@@ -6207,7 +6208,7 @@
                 .getStackedLinks();
         assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
         assertRoutesAdded(cellNetId, stackedDefault);
-
+        verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME);
         // Change trivial linkproperties and see if stacked link is preserved.
         cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
         mCellNetworkAgent.sendLinkProperties(cellLp);
@@ -6238,6 +6239,7 @@
                 (lp) -> lp.getStackedLinks().size() == 0);
         verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
         assertRoutesRemoved(cellNetId, stackedDefault);
+        verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME);
 
         verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kOtherNat64Prefix.toString());
         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
@@ -6246,6 +6248,7 @@
         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
                 (lp) -> lp.getStackedLinks().size() == 1);
         assertRoutesAdded(cellNetId, stackedDefault);
+        verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME);
         reset(mMockNetd);
 
         // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
@@ -6270,7 +6273,7 @@
         // The interface removed callback happens but has no effect after stop is called.
         clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
         networkCallback.assertNoCallback();
-
+        verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME);
         verifyNoMoreInteractions(mMockNetd);
         verifyNoMoreInteractions(mMockDnsResolver);
         reset(mNetworkManagementService);
@@ -6303,6 +6306,7 @@
         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
                 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null);
         assertRoutesAdded(cellNetId, stackedDefault);
+        verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME);
 
         // NAT64 prefix is removed. Expect that clat is stopped.
         mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
@@ -6315,8 +6319,8 @@
         verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
                 (lp) -> lp.getStackedLinks().size() == 0);
+        verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME);
         verifyNoMoreInteractions(mMockNetd);
-
         // Clean up.
         mCellNetworkAgent.disconnect();
         networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
diff --git a/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java b/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
index fb84611..ebbc0ef 100644
--- a/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
+++ b/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertEquals;
 
 import android.net.ipmemorystore.NetworkAttributes;
+import android.net.networkstack.aidl.quirks.IPv6ProvisioningLossQuirk;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -52,6 +53,8 @@
         }
         assertEquals(sum, NetworkAttributes.TOTAL_WEIGHT, EPSILON);
 
+        final IPv6ProvisioningLossQuirk ipv6ProvisioningLossQuirk =
+                new IPv6ProvisioningLossQuirk(3, System.currentTimeMillis() + 7_200_000);
         // Use directly the constructor with all attributes, and make sure that when compared
         // to itself the score is a clean 1.0f.
         final NetworkAttributes na =
@@ -61,7 +64,7 @@
                         "some hint",
                         Arrays.asList(Inet4Address.getByAddress(new byte[] {5, 6, 7, 8}),
                                 Inet4Address.getByAddress(new byte[] {9, 0, 1, 2})),
-                        98);
+                        98, ipv6ProvisioningLossQuirk);
         assertEquals(1.0f, na.getNetworkGroupSamenessConfidence(na), EPSILON);
     }
 }