Merge "[MS15.1] Remove get/setSubscriberIdMatchRule dependencies"
diff --git a/core/java/android/net/InternalNetworkManagementException.aidl b/core/java/android/net/InternalNetworkManagementException.aidl
new file mode 100644
index 0000000..dcce706
--- /dev/null
+++ b/core/java/android/net/InternalNetworkManagementException.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 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;
+
+ parcelable InternalNetworkManagementException;
\ No newline at end of file
diff --git a/core/java/android/net/InternalNetworkManagementException.java b/core/java/android/net/InternalNetworkManagementException.java
new file mode 100644
index 0000000..7f4e403
--- /dev/null
+++ b/core/java/android/net/InternalNetworkManagementException.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 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 android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/** @hide */
+public final class InternalNetworkManagementException
+        extends RuntimeException implements Parcelable {
+
+    /* @hide */
+    public InternalNetworkManagementException(@NonNull final Throwable t) {
+        super(t);
+    }
+
+    private InternalNetworkManagementException(@NonNull final Parcel source) {
+        super(source.readString());
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString(getCause().getMessage());
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @NonNull
+    public static final Parcelable.Creator<InternalNetworkManagementException> CREATOR =
+            new Parcelable.Creator<InternalNetworkManagementException>() {
+                @Override
+                public InternalNetworkManagementException[] newArray(int size) {
+                    return new InternalNetworkManagementException[size];
+                }
+
+                @Override
+                public InternalNetworkManagementException createFromParcel(@NonNull Parcel source) {
+                    return new InternalNetworkManagementException(source);
+                }
+            };
+}
diff --git a/core/java/android/net/InternalNetworkUpdateRequest.aidl b/core/java/android/net/InternalNetworkUpdateRequest.aidl
new file mode 100644
index 0000000..da00cb9
--- /dev/null
+++ b/core/java/android/net/InternalNetworkUpdateRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 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;
+
+ parcelable InternalNetworkUpdateRequest;
\ No newline at end of file
diff --git a/core/java/android/net/InternalNetworkUpdateRequest.java b/core/java/android/net/InternalNetworkUpdateRequest.java
new file mode 100644
index 0000000..6f09383
--- /dev/null
+++ b/core/java/android/net/InternalNetworkUpdateRequest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2021 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 android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/** @hide */
+public final class InternalNetworkUpdateRequest implements Parcelable {
+    @NonNull
+    private final StaticIpConfiguration mIpConfig;
+    @Nullable
+    private final NetworkCapabilities mNetworkCapabilities;
+
+    @NonNull
+    public StaticIpConfiguration getIpConfig() {
+        return new StaticIpConfiguration(mIpConfig);
+    }
+
+    @NonNull
+    public NetworkCapabilities getNetworkCapabilities() {
+        return mNetworkCapabilities == null
+                ? null : new NetworkCapabilities(mNetworkCapabilities);
+    }
+
+    /** @hide */
+    public InternalNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig,
+            @Nullable final NetworkCapabilities networkCapabilities) {
+        Objects.requireNonNull(ipConfig);
+        mIpConfig = new StaticIpConfiguration(ipConfig);
+        if (null == networkCapabilities) {
+            mNetworkCapabilities = null;
+        } else {
+            mNetworkCapabilities = new NetworkCapabilities(networkCapabilities);
+        }
+    }
+
+    private InternalNetworkUpdateRequest(@NonNull final Parcel source) {
+        Objects.requireNonNull(source);
+        mIpConfig = StaticIpConfiguration.CREATOR.createFromParcel(source);
+        mNetworkCapabilities = NetworkCapabilities.CREATOR.createFromParcel(source);
+    }
+
+    @Override
+    public String toString() {
+        return "InternalNetworkUpdateRequest{"
+                + "mIpConfig=" + mIpConfig
+                + ", mNetworkCapabilities=" + mNetworkCapabilities + '}';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        InternalNetworkUpdateRequest that = (InternalNetworkUpdateRequest) o;
+
+        return Objects.equals(that.getIpConfig(), mIpConfig)
+                && Objects.equals(that.getNetworkCapabilities(), mNetworkCapabilities);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mIpConfig, mNetworkCapabilities);
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        mIpConfig.writeToParcel(dest, flags);
+        mNetworkCapabilities.writeToParcel(dest, flags);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @NonNull
+    public static final Parcelable.Creator<InternalNetworkUpdateRequest> CREATOR =
+            new Parcelable.Creator<InternalNetworkUpdateRequest>() {
+                @Override
+                public InternalNetworkUpdateRequest[] newArray(int size) {
+                    return new InternalNetworkUpdateRequest[size];
+                }
+
+                @Override
+                public InternalNetworkUpdateRequest createFromParcel(@NonNull Parcel source) {
+                    return new InternalNetworkUpdateRequest(source);
+                }
+            };
+}
diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java
index 7cd63ef..ece54df 100644
--- a/framework-t/src/android/net/EthernetManager.java
+++ b/framework-t/src/android/net/EthernetManager.java
@@ -16,7 +16,9 @@
 
 package android.net;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
@@ -32,6 +34,7 @@
 import java.util.ArrayList;
 import java.util.Objects;
 import java.util.concurrent.Executor;
+import java.util.function.BiConsumer;
 
 /**
  * A class representing the IP configuration of the Ethernet network.
@@ -315,4 +318,83 @@
         }
         return new TetheredInterfaceRequest(mService, cbInternal);
     }
+
+    private static final class InternalNetworkManagementListener
+            extends IInternalNetworkManagementListener.Stub {
+        @NonNull
+        private final Executor mExecutor;
+        @NonNull
+        private final BiConsumer<Network, InternalNetworkManagementException> mListener;
+
+        InternalNetworkManagementListener(
+                @NonNull final Executor executor,
+                @NonNull final BiConsumer<Network, InternalNetworkManagementException> listener) {
+            Objects.requireNonNull(executor, "Pass a non-null executor");
+            Objects.requireNonNull(listener, "Pass a non-null listener");
+            mExecutor = executor;
+            mListener = listener;
+        }
+
+        @Override
+        public void onComplete(
+                @Nullable final Network network,
+                @Nullable final InternalNetworkManagementException e) {
+            mExecutor.execute(() -> mListener.accept(network, e));
+        }
+    }
+
+    private InternalNetworkManagementListener getInternalNetworkManagementListener(
+            @Nullable final Executor executor,
+            @Nullable final BiConsumer<Network, InternalNetworkManagementException> listener) {
+        if (null != listener) {
+            Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener");
+        }
+        final InternalNetworkManagementListener proxy;
+        if (null == listener) {
+            proxy = null;
+        } else {
+            proxy = new InternalNetworkManagementListener(executor, listener);
+        }
+        return proxy;
+    }
+
+    private void updateConfiguration(
+            @NonNull String iface,
+            @NonNull InternalNetworkUpdateRequest request,
+            @Nullable @CallbackExecutor Executor executor,
+            @Nullable BiConsumer<Network, InternalNetworkManagementException> listener) {
+        final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
+                executor, listener);
+        try {
+            mService.updateConfiguration(iface, request, proxy);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    private void connectNetwork(
+            @NonNull String iface,
+            @Nullable @CallbackExecutor Executor executor,
+            @Nullable BiConsumer<Network, InternalNetworkManagementException> listener) {
+        final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
+                executor, listener);
+        try {
+            mService.connectNetwork(iface, proxy);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    private void disconnectNetwork(
+            @NonNull String iface,
+            @Nullable @CallbackExecutor Executor executor,
+            @Nullable BiConsumer<Network, InternalNetworkManagementException> listener) {
+        final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
+                executor, listener);
+        try {
+            mService.disconnectNetwork(iface, proxy);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/framework-t/src/android/net/IEthernetManager.aidl b/framework-t/src/android/net/IEthernetManager.aidl
index e058e5a..e688bea 100644
--- a/framework-t/src/android/net/IEthernetManager.aidl
+++ b/framework-t/src/android/net/IEthernetManager.aidl
@@ -18,6 +18,8 @@
 
 import android.net.IpConfiguration;
 import android.net.IEthernetServiceListener;
+import android.net.IInternalNetworkManagementListener;
+import android.net.InternalNetworkUpdateRequest;
 import android.net.ITetheredInterfaceCallback;
 
 /**
@@ -36,4 +38,8 @@
     void setIncludeTestInterfaces(boolean include);
     void requestTetheredInterface(in ITetheredInterfaceCallback callback);
     void releaseTetheredInterface(in ITetheredInterfaceCallback callback);
+    void updateConfiguration(String iface, in InternalNetworkUpdateRequest request,
+        in IInternalNetworkManagementListener listener);
+    void connectNetwork(String iface, in IInternalNetworkManagementListener listener);
+    void disconnectNetwork(String iface, in IInternalNetworkManagementListener listener);
 }
diff --git a/framework-t/src/android/net/IpSecManager.java b/framework-t/src/android/net/IpSecManager.java
index 0b266b2..0d15dff 100644
--- a/framework-t/src/android/net/IpSecManager.java
+++ b/framework-t/src/android/net/IpSecManager.java
@@ -17,8 +17,6 @@
 
 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-
 import android.annotation.NonNull;
 import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
@@ -46,6 +44,7 @@
 import java.net.DatagramSocket;
 import java.net.InetAddress;
 import java.net.Socket;
+import java.util.Objects;
 
 /**
  * This class contains methods for managing IPsec sessions. Once configured, the kernel will apply
@@ -989,7 +988,7 @@
      */
     public IpSecManager(Context ctx, IIpSecService service) {
         mContext = ctx;
-        mService = checkNotNull(service, "missing service");
+        mService = Objects.requireNonNull(service, "missing service");
     }
 
     private static void maybeHandleServiceSpecificException(ServiceSpecificException sse) {
diff --git a/framework-t/src/android/net/IpSecTransform.java b/framework-t/src/android/net/IpSecTransform.java
index b48c1fd..36199a0 100644
--- a/framework-t/src/android/net/IpSecTransform.java
+++ b/framework-t/src/android/net/IpSecTransform.java
@@ -33,7 +33,6 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
 
 import dalvik.system.CloseGuard;
 
@@ -41,6 +40,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.net.InetAddress;
+import java.util.Objects;
 
 /**
  * This class represents a transform, which roughly corresponds to an IPsec Security Association.
@@ -255,7 +255,7 @@
         @NonNull
         public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) {
             // TODO: throw IllegalArgumentException if algo is not an encryption algorithm.
-            Preconditions.checkNotNull(algo);
+            Objects.requireNonNull(algo);
             mConfig.setEncryption(algo);
             return this;
         }
@@ -270,7 +270,7 @@
         @NonNull
         public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) {
             // TODO: throw IllegalArgumentException if algo is not an authentication algorithm.
-            Preconditions.checkNotNull(algo);
+            Objects.requireNonNull(algo);
             mConfig.setAuthentication(algo);
             return this;
         }
@@ -290,7 +290,7 @@
          */
         @NonNull
         public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) {
-            Preconditions.checkNotNull(algo);
+            Objects.requireNonNull(algo);
             mConfig.setAuthenticatedEncryption(algo);
             return this;
         }
@@ -311,7 +311,7 @@
         @NonNull
         public IpSecTransform.Builder setIpv4Encapsulation(
                 @NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
-            Preconditions.checkNotNull(localSocket);
+            Objects.requireNonNull(localSocket);
             mConfig.setEncapType(ENCAP_ESPINUDP);
             if (localSocket.getResourceId() == INVALID_RESOURCE_ID) {
                 throw new IllegalArgumentException("Invalid UdpEncapsulationSocket");
@@ -348,8 +348,8 @@
                 @NonNull IpSecManager.SecurityParameterIndex spi)
                 throws IpSecManager.ResourceUnavailableException,
                         IpSecManager.SpiUnavailableException, IOException {
-            Preconditions.checkNotNull(sourceAddress);
-            Preconditions.checkNotNull(spi);
+            Objects.requireNonNull(sourceAddress);
+            Objects.requireNonNull(spi);
             if (spi.getResourceId() == INVALID_RESOURCE_ID) {
                 throw new IllegalArgumentException("Invalid SecurityParameterIndex");
             }
@@ -387,8 +387,8 @@
                 @NonNull IpSecManager.SecurityParameterIndex spi)
                 throws IpSecManager.ResourceUnavailableException,
                         IpSecManager.SpiUnavailableException, IOException {
-            Preconditions.checkNotNull(sourceAddress);
-            Preconditions.checkNotNull(spi);
+            Objects.requireNonNull(sourceAddress);
+            Objects.requireNonNull(spi);
             if (spi.getResourceId() == INVALID_RESOURCE_ID) {
                 throw new IllegalArgumentException("Invalid SecurityParameterIndex");
             }
@@ -404,7 +404,7 @@
          * @param context current context
          */
         public Builder(@NonNull Context context) {
-            Preconditions.checkNotNull(context);
+            Objects.requireNonNull(context);
             mContext = context;
             mConfig = new IpSecConfig();
         }
diff --git a/framework-t/src/android/net/NetworkStatsAccess.java b/framework-t/src/android/net/NetworkStatsAccess.java
index 3885a9e..591605d 100644
--- a/framework-t/src/android/net/NetworkStatsAccess.java
+++ b/framework-t/src/android/net/NetworkStatsAccess.java
@@ -24,7 +24,7 @@
 import android.Manifest;
 import android.annotation.IntDef;
 import android.app.AppOpsManager;
-import android.app.admin.DevicePolicyManagerInternal;
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.Binder;
@@ -32,8 +32,6 @@
 import android.os.UserHandle;
 import android.telephony.TelephonyManager;
 
-import com.android.server.LocalServices;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -109,8 +107,7 @@
     /** Returns the {@link NetworkStatsAccess.Level} for the given caller. */
     public static @NetworkStatsAccess.Level int checkAccessLevel(
             Context context, int callingUid, String callingPackage) {
-        final DevicePolicyManagerInternal dpmi = LocalServices.getService(
-                DevicePolicyManagerInternal.class);
+        final DevicePolicyManager mDpm = context.getSystemService(DevicePolicyManager.class);
         final TelephonyManager tm = (TelephonyManager)
                 context.getSystemService(Context.TELEPHONY_SERVICE);
         boolean hasCarrierPrivileges;
@@ -123,8 +120,9 @@
             Binder.restoreCallingIdentity(token);
         }
 
-        final boolean isDeviceOwner = dpmi != null && dpmi.isActiveDeviceOwner(callingUid);
+        final boolean isDeviceOwner = mDpm != null && mDpm.isDeviceOwnerApp(callingPackage);
         final int appId = UserHandle.getAppId(callingUid);
+
         if (hasCarrierPrivileges || isDeviceOwner
                 || appId == Process.SYSTEM_UID || appId == Process.NETWORK_STACK_UID) {
             // Carrier-privileged apps and device owners, and the system (including the
@@ -139,8 +137,8 @@
         }
 
         //TODO(b/169395065) Figure out if this flow makes sense in Device Owner mode.
-        boolean isProfileOwner = dpmi != null && (dpmi.isActiveProfileOwner(callingUid)
-                || dpmi.isActiveDeviceOwner(callingUid));
+        boolean isProfileOwner = mDpm != null && (mDpm.isProfileOwnerApp(callingPackage)
+                || mDpm.isDeviceOwnerApp(callingPackage));
         if (isProfileOwner) {
             // Apps with the AppOps permission, profile owners, and apps with the privileged
             // permission can access data usage for all apps in this user/profile.