[automerger skipped] Merge "[DU03-4]Add NETWORK_STACK Permission check for NetworkStatsService API" am: 2da74e0820 am: 31180da4cc am: c26752dba8 -s ours

am skip reason: Merged-In I022c34b5af87fe3ff6857ea264bac2f7098eaed4 with SHA-1 c3c367e481 is already in history

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2004530

Change-Id: Ic53c362943a8dfd8fb107d953f2dae9a14b2b5f6
diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java
index a8baa8e..ca080ce 100644
--- a/framework-t/src/android/app/usage/NetworkStatsManager.java
+++ b/framework-t/src/android/app/usage/NetworkStatsManager.java
@@ -744,8 +744,9 @@
      * {@link #unregisterUsageCallback} is called.
      *
      * @param template Template used to match networks. See {@link NetworkTemplate}.
-     * @param thresholdBytes Threshold in bytes to be notified on. The provided value that lower
-     *                       than 2MiB will be clamped for non-privileged callers.
+     * @param thresholdBytes Threshold in bytes to be notified on. Provided values lower than 2MiB
+     *                       will be clamped for callers except callers with the NETWORK_STACK
+     *                       permission.
      * @param executor The executor on which callback will be invoked. The provided {@link Executor}
      *                 must run callback sequentially, otherwise the order of callbacks cannot be
      *                 guaranteed.
@@ -754,6 +755,9 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
+    @RequiresPermission(anyOf = {
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+            android.Manifest.permission.NETWORK_STACK}, conditional = true)
     public void registerUsageCallback(@NonNull NetworkTemplate template, long thresholdBytes,
             @NonNull @CallbackExecutor Executor executor, @NonNull UsageCallback callback) {
         Objects.requireNonNull(template, "NetworkTemplate cannot be null");
diff --git a/framework-t/src/android/net/DataUsageRequest.java b/framework-t/src/android/net/DataUsageRequest.java
index b06d515..f0ff465 100644
--- a/framework-t/src/android/net/DataUsageRequest.java
+++ b/framework-t/src/android/net/DataUsageRequest.java
@@ -75,7 +75,7 @@
                 @Override
                 public DataUsageRequest createFromParcel(Parcel in) {
                     int requestId = in.readInt();
-                    NetworkTemplate template = in.readParcelable(null);
+                    NetworkTemplate template = in.readParcelable(null, android.net.NetworkTemplate.class);
                     long thresholdInBytes = in.readLong();
                     DataUsageRequest result = new DataUsageRequest(requestId, template,
                             thresholdInBytes);
diff --git a/framework-t/src/android/net/IpSecConfig.java b/framework-t/src/android/net/IpSecConfig.java
index 575c5ed..03bb187 100644
--- a/framework-t/src/android/net/IpSecConfig.java
+++ b/framework-t/src/android/net/IpSecConfig.java
@@ -267,14 +267,14 @@
         mMode = in.readInt();
         mSourceAddress = in.readString();
         mDestinationAddress = in.readString();
-        mNetwork = (Network) in.readParcelable(Network.class.getClassLoader());
+        mNetwork = (Network) in.readParcelable(Network.class.getClassLoader(), android.net.Network.class);
         mSpiResourceId = in.readInt();
         mEncryption =
-                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
+                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader(), android.net.IpSecAlgorithm.class);
         mAuthentication =
-                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
+                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader(), android.net.IpSecAlgorithm.class);
         mAuthenticatedEncryption =
-                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
+                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader(), android.net.IpSecAlgorithm.class);
         mEncapType = in.readInt();
         mEncapSocketResourceId = in.readInt();
         mEncapRemotePort = in.readInt();
diff --git a/framework-t/src/android/net/IpSecUdpEncapResponse.java b/framework-t/src/android/net/IpSecUdpEncapResponse.java
index 732cf19..390af82 100644
--- a/framework-t/src/android/net/IpSecUdpEncapResponse.java
+++ b/framework-t/src/android/net/IpSecUdpEncapResponse.java
@@ -81,7 +81,7 @@
         status = in.readInt();
         resourceId = in.readInt();
         port = in.readInt();
-        fileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
+        fileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader(), android.os.ParcelFileDescriptor.class);
     }
 
     @android.annotation.NonNull
diff --git a/framework-t/src/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java
index 4ebaf2b..a48f94b 100644
--- a/framework-t/src/android/net/NetworkIdentity.java
+++ b/framework-t/src/android/net/NetworkIdentity.java
@@ -20,6 +20,7 @@
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_WIFI;
 import static android.net.NetworkTemplate.NETWORK_TYPE_ALL;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -86,6 +87,7 @@
 
     final int mType;
     final int mRatType;
+    final int mSubId;
     final String mSubscriberId;
     final String mWifiNetworkKey;
     final boolean mRoaming;
@@ -96,7 +98,7 @@
     /** @hide */
     public NetworkIdentity(
             int type, int ratType, @Nullable String subscriberId, @Nullable String wifiNetworkKey,
-            boolean roaming, boolean metered, boolean defaultNetwork, int oemManaged) {
+            boolean roaming, boolean metered, boolean defaultNetwork, int oemManaged, int subId) {
         mType = type;
         mRatType = ratType;
         mSubscriberId = subscriberId;
@@ -105,12 +107,13 @@
         mMetered = metered;
         mDefaultNetwork = defaultNetwork;
         mOemManaged = oemManaged;
+        mSubId = subId;
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(mType, mRatType, mSubscriberId, mWifiNetworkKey, mRoaming, mMetered,
-                mDefaultNetwork, mOemManaged);
+                mDefaultNetwork, mOemManaged, mSubId);
     }
 
     @Override
@@ -122,7 +125,8 @@
                     && Objects.equals(mWifiNetworkKey, ident.mWifiNetworkKey)
                     && mMetered == ident.mMetered
                     && mDefaultNetwork == ident.mDefaultNetwork
-                    && mOemManaged == ident.mOemManaged;
+                    && mOemManaged == ident.mOemManaged
+                    && mSubId == ident.mSubId;
         }
         return false;
     }
@@ -150,6 +154,7 @@
         builder.append(", metered=").append(mMetered);
         builder.append(", defaultNetwork=").append(mDefaultNetwork);
         builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged));
+        builder.append(", subId=").append(mSubId);
         return builder.append("}").toString();
     }
 
@@ -256,6 +261,11 @@
         return mOemManaged;
     }
 
+    /** Get the SubId of this instance. */
+    public int getSubId() {
+        return mSubId;
+    }
+
     /**
      * Assemble a {@link NetworkIdentity} from the passed arguments.
      *
@@ -276,7 +286,8 @@
     public static NetworkIdentity buildNetworkIdentity(Context context,
             @NonNull NetworkStateSnapshot snapshot, boolean defaultNetwork, int ratType) {
         final NetworkIdentity.Builder builder = new NetworkIdentity.Builder()
-                .setNetworkStateSnapshot(snapshot).setDefaultNetwork(defaultNetwork);
+                .setNetworkStateSnapshot(snapshot).setDefaultNetwork(defaultNetwork)
+                .setSubId(snapshot.getSubId());
         if (snapshot.getLegacyType() == TYPE_MOBILE && ratType != NETWORK_TYPE_ALL) {
             builder.setRatType(ratType);
         }
@@ -325,6 +336,9 @@
         if (res == 0) {
             res = Integer.compare(left.mOemManaged, right.mOemManaged);
         }
+        if (res == 0) {
+            res = Integer.compare(left.mSubId, right.mSubId);
+        }
         return res;
     }
 
@@ -345,6 +359,7 @@
         private boolean mMetered;
         private boolean mDefaultNetwork;
         private int mOemManaged;
+        private int mSubId;
 
         /**
          * Creates a new Builder.
@@ -359,6 +374,7 @@
             mMetered = false;
             mDefaultNetwork = false;
             mOemManaged = NetworkTemplate.OEM_MANAGED_NO;
+            mSubId = INVALID_SUBSCRIPTION_ID;
         }
 
         /**
@@ -537,6 +553,19 @@
             return this;
         }
 
+        /**
+         * Set the Subscription Id.
+         *
+         * @param subId the Subscription Id of the network. Or INVALID_SUBSCRIPTION_ID if not
+         *              applicable.
+         * @return this builder.
+         */
+        @NonNull
+        public Builder setSubId(int subId) {
+            mSubId = subId;
+            return this;
+        }
+
         private void ensureValidParameters() {
             // Assert non-mobile network cannot have a ratType.
             if (mType != TYPE_MOBILE && mRatType != NetworkTemplate.NETWORK_TYPE_ALL) {
@@ -559,7 +588,7 @@
         public NetworkIdentity build() {
             ensureValidParameters();
             return new NetworkIdentity(mType, mRatType, mSubscriberId, mWifiNetworkKey,
-                    mRoaming, mMetered, mDefaultNetwork, mOemManaged);
+                    mRoaming, mMetered, mDefaultNetwork, mOemManaged, mSubId);
         }
     }
 }
diff --git a/framework-t/src/android/net/NetworkIdentitySet.java b/framework-t/src/android/net/NetworkIdentitySet.java
index 2236d70..56461ba 100644
--- a/framework-t/src/android/net/NetworkIdentitySet.java
+++ b/framework-t/src/android/net/NetworkIdentitySet.java
@@ -17,6 +17,7 @@
 package android.net;
 
 import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
 import android.annotation.NonNull;
 import android.service.NetworkIdentitySetProto;
@@ -42,6 +43,7 @@
     private static final int VERSION_ADD_METERED = 4;
     private static final int VERSION_ADD_DEFAULT_NETWORK = 5;
     private static final int VERSION_ADD_OEM_MANAGED_NETWORK = 6;
+    private static final int VERSION_ADD_SUB_ID = 7;
 
     /**
      * Construct a {@link NetworkIdentitySet} object.
@@ -103,8 +105,15 @@
                 oemNetCapabilities = NetworkIdentity.OEM_NONE;
             }
 
+            final int subId;
+            if (version >= VERSION_ADD_SUB_ID) {
+                subId = in.readInt();
+            } else {
+                subId = INVALID_SUBSCRIPTION_ID;
+            }
+
             add(new NetworkIdentity(type, ratType, subscriberId, networkId, roaming, metered,
-                    defaultNetwork, oemNetCapabilities));
+                    defaultNetwork, oemNetCapabilities, subId));
         }
     }
 
@@ -113,7 +122,7 @@
      * @hide
      */
     public void writeToStream(DataOutput out) throws IOException {
-        out.writeInt(VERSION_ADD_OEM_MANAGED_NETWORK);
+        out.writeInt(VERSION_ADD_SUB_ID);
         out.writeInt(size());
         for (NetworkIdentity ident : this) {
             out.writeInt(ident.getType());
@@ -124,6 +133,7 @@
             out.writeBoolean(ident.isMetered());
             out.writeBoolean(ident.isDefaultNetwork());
             out.writeInt(ident.getOemManaged());
+            out.writeInt(ident.getSubId());
         }
     }
 
diff --git a/framework-t/src/android/net/NetworkStateSnapshot.java b/framework-t/src/android/net/NetworkStateSnapshot.java
index 3915634..c018e91 100644
--- a/framework-t/src/android/net/NetworkStateSnapshot.java
+++ b/framework-t/src/android/net/NetworkStateSnapshot.java
@@ -17,6 +17,8 @@
 package android.net;
 
 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -73,9 +75,9 @@
 
     /** @hide */
     public NetworkStateSnapshot(@NonNull Parcel in) {
-        mNetwork = in.readParcelable(null);
-        mNetworkCapabilities = in.readParcelable(null);
-        mLinkProperties = in.readParcelable(null);
+        mNetwork = in.readParcelable(null, android.net.Network.class);
+        mNetworkCapabilities = in.readParcelable(null, android.net.NetworkCapabilities.class);
+        mLinkProperties = in.readParcelable(null, android.net.LinkProperties.class);
         mSubscriberId = in.readString();
         mLegacyType = in.readInt();
     }
@@ -98,12 +100,29 @@
         return mLinkProperties;
     }
 
-    /** Get the Subscriber Id of the network associated with this snapshot. */
+    /**
+     * Get the Subscriber Id of the network associated with this snapshot.
+     * @deprecated Please use #getSubId, which doesn't return personally identifiable
+     * information.
+     */
+    @Deprecated
     @Nullable
     public String getSubscriberId() {
         return mSubscriberId;
     }
 
+    /** Get the subId of the network associated with this snapshot. */
+    public int getSubId() {
+        if (mNetworkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
+            final NetworkSpecifier spec = mNetworkCapabilities.getNetworkSpecifier();
+            if (spec instanceof TelephonyNetworkSpecifier) {
+                return ((TelephonyNetworkSpecifier) spec).getSubscriptionId();
+            }
+        }
+        return INVALID_SUBSCRIPTION_ID;
+    }
+
+
     /**
      * Get the legacy type of the network associated with this snapshot.
      * @return the legacy network type. See {@code ConnectivityManager#TYPE_*}.
diff --git a/framework-t/src/android/net/UnderlyingNetworkInfo.java b/framework-t/src/android/net/UnderlyingNetworkInfo.java
index 33f9375..7ab53b1 100644
--- a/framework-t/src/android/net/UnderlyingNetworkInfo.java
+++ b/framework-t/src/android/net/UnderlyingNetworkInfo.java
@@ -60,7 +60,7 @@
         mOwnerUid = in.readInt();
         mIface = in.readString();
         List<String> underlyingIfaces = new ArrayList<>();
-        in.readList(underlyingIfaces, null /*classLoader*/);
+        in.readList(underlyingIfaces, null /*classLoader*/, java.lang.String.class);
         mUnderlyingIfaces = Collections.unmodifiableList(underlyingIfaces);
     }
 
diff --git a/service-t/src/com/android/server/net/NetworkStatsObservers.java b/service-t/src/com/android/server/net/NetworkStatsObservers.java
index 1953624..fdfc893 100644
--- a/service-t/src/com/android/server/net/NetworkStatsObservers.java
+++ b/service-t/src/com/android/server/net/NetworkStatsObservers.java
@@ -19,8 +19,11 @@
 import static android.app.usage.NetworkStatsManager.MIN_THRESHOLD_BYTES;
 
 import android.app.usage.NetworkStatsManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
 import android.net.DataUsageRequest;
 import android.net.NetworkIdentitySet;
+import android.net.NetworkStack;
 import android.net.NetworkStats;
 import android.net.NetworkStatsAccess;
 import android.net.NetworkStatsCollection;
@@ -74,9 +77,9 @@
      *
      * @return the normalized request wrapped within {@link RequestInfo}.
      */
-    public DataUsageRequest register(DataUsageRequest inputRequest, IUsageCallback callback,
-            int callingUid, @NetworkStatsAccess.Level int accessLevel) {
-        DataUsageRequest request = buildRequest(inputRequest, callingUid);
+    public DataUsageRequest register(Context context, DataUsageRequest inputRequest,
+            IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) {
+        DataUsageRequest request = buildRequest(context, inputRequest, callingUid);
         RequestInfo requestInfo = buildRequestInfo(request, callback, callingUid,
                 accessLevel);
 
@@ -194,10 +197,13 @@
         }
     }
 
-    private DataUsageRequest buildRequest(DataUsageRequest request, int callingUid) {
-        // For non-system uid, cap the minimum threshold to a safe default to avoid too
-        // many callbacks.
-        long thresholdInBytes = (callingUid == Process.SYSTEM_UID ? request.thresholdInBytes
+    private DataUsageRequest buildRequest(Context context, DataUsageRequest request,
+                int callingUid) {
+        // For non-NETWORK_STACK permission uid, cap the minimum threshold to a safe default to
+        // avoid too many callbacks.
+        final long thresholdInBytes = (context.checkPermission(
+                NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, Process.myPid(), callingUid)
+                == PackageManager.PERMISSION_GRANTED ? request.thresholdInBytes
                 : Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes));
         if (thresholdInBytes > request.thresholdInBytes) {
             Log.w(TAG, "Threshold was too low for " + request
diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
index 0b5a85f..ef6f39a 100644
--- a/service-t/src/com/android/server/net/NetworkStatsService.java
+++ b/service-t/src/com/android/server/net/NetworkStatsService.java
@@ -1285,7 +1285,7 @@
         DataUsageRequest normalizedRequest;
         final long token = Binder.clearCallingIdentity();
         try {
-            normalizedRequest = mStatsObservers.register(
+            normalizedRequest = mStatsObservers.register(mContext,
                     request, callback, callingUid, accessLevel);
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -1540,10 +1540,15 @@
                         NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.isMetered()) {
 
                     // Copy the identify from IMS one but mark it as metered.
-                    NetworkIdentity vtIdent = new NetworkIdentity(ident.getType(),
-                            ident.getRatType(), ident.getSubscriberId(), ident.getWifiNetworkKey(),
-                            ident.isRoaming(), true /* metered */,
-                            true /* onDefaultNetwork */, ident.getOemManaged());
+                    NetworkIdentity vtIdent = new NetworkIdentity.Builder()
+                            .setType(ident.getType())
+                            .setRatType(ident.getRatType())
+                            .setSubscriberId(ident.getSubscriberId())
+                            .setWifiNetworkKey(ident.getWifiNetworkKey())
+                            .setRoaming(ident.isRoaming()).setMetered(true)
+                            .setDefaultNetwork(true)
+                            .setOemManaged(ident.getOemManaged())
+                            .setSubId(ident.getSubId()).build();
                     final String ifaceVt = IFACE_VT + getSubIdForMobile(snapshot);
                     findOrCreateNetworkIdentitySet(mActiveIfaces, ifaceVt).add(vtIdent);
                     findOrCreateNetworkIdentitySet(mActiveUidIfaces, ifaceVt).add(vtIdent);