OSDN Git Service

DO NOT MERGE: Fix ConnectivityController meteredness checks
authorBenedict Wong <benedictwong@google.com>
Fri, 4 May 2018 04:07:58 +0000 (21:07 -0700)
committerandroid-build-team Robot <android-build-team-robot@google.com>
Fri, 10 Aug 2018 20:27:41 +0000 (20:27 +0000)
This patch corrects ConnectivityController's meteredness checks to
perform correct meteredness checks while VPNs are running. This fixes a
bug in O-MR1 where any apps using the DownloadProvider with unmetered
network constraints fail to start while the VPN is enabled.

This change adds a bespoke method for ConnectivityController, allowing
it to correctly identify the meteredness without affecting public API
surfaces.

Bug: 78644887
Test: Built, flashed on Walleye, and tested.
Test: Additional test coverage in subsequent patch(es).
Change-Id: Ie1d11d93d51d936ce81cd5984af61bde30325983
(cherry picked from commit d08ab5a641d9d81314c9439724dd34338fa81d58)

core/java/android/net/ConnectivityManager.java
core/java/android/net/IConnectivityManager.aidl
services/core/java/com/android/server/ConnectivityService.java
services/core/java/com/android/server/job/controllers/ConnectivityController.java

index d7ecc81..467eb9b 100644 (file)
@@ -2505,6 +2505,28 @@ public class ConnectivityManager {
     }
 
     /**
+     * Returns if the active data network for the given UID is metered. A network
+     * is classified as metered when the user is sensitive to heavy data usage on
+     * that connection due to monetary costs, data limitations or
+     * battery/performance issues. You should check this before doing large
+     * data transfers, and warn the user or delay the operation until another
+     * network is available.
+     *
+     * @return {@code true} if large transfers should be avoided, otherwise
+     *        {@code false}.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL)
+    public boolean isActiveNetworkMeteredForUid(int uid) {
+        try {
+            return mService.isActiveNetworkMeteredForUid(uid);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * If the LockdownVpn mechanism is enabled, updates the vpn
      * with a reload of its profile.
      *
index a6fe738..f11372c 100644 (file)
@@ -66,6 +66,7 @@ interface IConnectivityManager
 
     NetworkQuotaInfo getActiveNetworkQuotaInfo();
     boolean isActiveNetworkMetered();
+    boolean isActiveNetworkMeteredForUid(int uid);
 
     boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress);
 
index c1801b8..c2b83d9 100644 (file)
@@ -1339,7 +1339,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
     public boolean isActiveNetworkMetered() {
         enforceAccessPermission();
 
-        final int uid = Binder.getCallingUid();
+        return isActiveNetworkMeteredCommon(Binder.getCallingUid());
+    }
+
+    @Override
+    public boolean isActiveNetworkMeteredForUid(int uid) {
+        enforceConnectivityInternalPermission();
+
+        return isActiveNetworkMeteredCommon(uid);
+    }
+
+    private boolean isActiveNetworkMeteredCommon(int uid) {
         final NetworkCapabilities caps = getUnfilteredActiveNetworkState(uid).networkCapabilities;
         if (caps != null) {
             return !caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
index 78367fe..4d5a920 100644 (file)
@@ -112,10 +112,8 @@ public final class ConnectivityController extends StateController implements
         final boolean connected = (info != null) && info.isConnected();
         final boolean connectionUsable = connected && validated;
 
-        final boolean metered = connected && (capabilities != null)
-                && !capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
-        final boolean unmetered = connected && (capabilities != null)
-                && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+        final boolean metered = connected && mConnManager.isActiveNetworkMeteredForUid(jobUid);
+        final boolean unmetered = connected && !mConnManager.isActiveNetworkMeteredForUid(jobUid);
         final boolean notRoaming = connected && (info != null)
                 && !info.isRoaming();