Merge "Extract test utilities for ConnectivityService"
am: b7d270a73e

Change-Id: I0ac2a480f961bb6fd1d83dedad6a7942ee03858f
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 59ae334..8e40449 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -278,6 +278,12 @@
             return null;
         }
 
+        return querySummary(template, startTime, endTime);
+    }
+
+    /** @hide */
+    public NetworkStats querySummary(NetworkTemplate template, long startTime,
+            long endTime) throws SecurityException, RemoteException {
         NetworkStats result;
         result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
         result.startSummaryEnumeration();
@@ -296,6 +302,13 @@
             NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
     }
 
+    /** @hide */
+    public NetworkStats queryDetailsForUid(NetworkTemplate template,
+            long startTime, long endTime, int uid) throws SecurityException {
+        return queryDetailsForUidTagState(template, startTime, endTime, uid,
+                NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
+    }
+
     /**
      * Query network usage statistics details for a given uid and tag.
      *
@@ -340,6 +353,13 @@
         NetworkTemplate template;
         template = createTemplate(networkType, subscriberId);
 
+        return queryDetailsForUidTagState(template, startTime, endTime, uid, tag, state);
+    }
+
+    /** @hide */
+    public NetworkStats queryDetailsForUidTagState(NetworkTemplate template,
+            long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
+
         NetworkStats result;
         try {
             result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
diff --git a/core/java/android/net/DataUsageRequest.java b/core/java/android/net/DataUsageRequest.java
index ac9a5a3..0ac8f7e 100644
--- a/core/java/android/net/DataUsageRequest.java
+++ b/core/java/android/net/DataUsageRequest.java
@@ -69,7 +69,7 @@
         dest.writeLong(thresholdInBytes);
     }
 
-    public static final Creator<DataUsageRequest> CREATOR =
+    public static final @android.annotation.NonNull Creator<DataUsageRequest> CREATOR =
             new Creator<DataUsageRequest>() {
                 @Override
                 public DataUsageRequest createFromParcel(Parcel in) {
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index 8034bb6..38d9883 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -191,7 +191,7 @@
     }
 
     /** Parcelable Creator */
-    public static final Parcelable.Creator<IpSecAlgorithm> CREATOR =
+    public static final @android.annotation.NonNull Parcelable.Creator<IpSecAlgorithm> CREATOR =
             new Parcelable.Creator<IpSecAlgorithm>() {
                 public IpSecAlgorithm createFromParcel(Parcel in) {
                     final String name = in.readString();
diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java
index 43c8ff2..575c5ed 100644
--- a/core/java/android/net/IpSecConfig.java
+++ b/core/java/android/net/IpSecConfig.java
@@ -323,7 +323,7 @@
         return strBuilder.toString();
     }
 
-    public static final Parcelable.Creator<IpSecConfig> CREATOR =
+    public static final @android.annotation.NonNull Parcelable.Creator<IpSecConfig> CREATOR =
             new Parcelable.Creator<IpSecConfig>() {
                 public IpSecConfig createFromParcel(Parcel in) {
                     return new IpSecConfig(in);
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 889e9bc..83813da 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -19,10 +19,13 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.Binder;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
@@ -720,6 +723,7 @@
      * to create Network objects which are accessible to the Android system.
      * @hide
      */
+    @SystemApi
     public static final class IpSecTunnelInterface implements AutoCloseable {
         private final String mOpPackageName;
         private final IIpSecService mService;
@@ -746,6 +750,8 @@
          * @param prefixLen length of the InetAddress prefix
          * @hide
          */
+        @SystemApi
+        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
         @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
         public void addAddress(@NonNull InetAddress address, int prefixLen) throws IOException {
             try {
@@ -767,6 +773,8 @@
          * @param prefixLen length of the InetAddress prefix
          * @hide
          */
+        @SystemApi
+        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
         @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
         public void removeAddress(@NonNull InetAddress address, int prefixLen) throws IOException {
             try {
@@ -880,7 +888,9 @@
      * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
      * @hide
      */
+    @SystemApi
     @NonNull
+    @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
     @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
     public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress,
             @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork)
@@ -910,6 +920,8 @@
      *         layer failure.
      * @hide
      */
+    @SystemApi
+    @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
     @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
     public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel,
             @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
diff --git a/core/java/android/net/IpSecSpiResponse.java b/core/java/android/net/IpSecSpiResponse.java
index 71dfa03..f99e570 100644
--- a/core/java/android/net/IpSecSpiResponse.java
+++ b/core/java/android/net/IpSecSpiResponse.java
@@ -65,7 +65,7 @@
         spi = in.readInt();
     }
 
-    public static final Parcelable.Creator<IpSecSpiResponse> CREATOR =
+    public static final @android.annotation.NonNull Parcelable.Creator<IpSecSpiResponse> CREATOR =
             new Parcelable.Creator<IpSecSpiResponse>() {
                 public IpSecSpiResponse createFromParcel(Parcel in) {
                     return new IpSecSpiResponse(in);
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index 93ae4f1..44a0a4f 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -21,8 +21,11 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -478,7 +481,9 @@
          * @throws IOException indicating other errors
          * @hide
          */
+        @SystemApi
         @NonNull
+        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
         @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
         public IpSecTransform buildTunnelModeTransform(
                 @NonNull InetAddress sourceAddress,
diff --git a/core/java/android/net/IpSecTransformResponse.java b/core/java/android/net/IpSecTransformResponse.java
index cfc1762..a384889 100644
--- a/core/java/android/net/IpSecTransformResponse.java
+++ b/core/java/android/net/IpSecTransformResponse.java
@@ -60,7 +60,7 @@
         resourceId = in.readInt();
     }
 
-    public static final Parcelable.Creator<IpSecTransformResponse> CREATOR =
+    public static final @android.annotation.NonNull Parcelable.Creator<IpSecTransformResponse> CREATOR =
             new Parcelable.Creator<IpSecTransformResponse>() {
                 public IpSecTransformResponse createFromParcel(Parcel in) {
                     return new IpSecTransformResponse(in);
diff --git a/core/java/android/net/IpSecTunnelInterfaceResponse.java b/core/java/android/net/IpSecTunnelInterfaceResponse.java
index c23d831..e3411e0 100644
--- a/core/java/android/net/IpSecTunnelInterfaceResponse.java
+++ b/core/java/android/net/IpSecTunnelInterfaceResponse.java
@@ -65,7 +65,7 @@
         interfaceName = in.readString();
     }
 
-    public static final Parcelable.Creator<IpSecTunnelInterfaceResponse> CREATOR =
+    public static final @android.annotation.NonNull Parcelable.Creator<IpSecTunnelInterfaceResponse> CREATOR =
             new Parcelable.Creator<IpSecTunnelInterfaceResponse>() {
                 public IpSecTunnelInterfaceResponse createFromParcel(Parcel in) {
                     return new IpSecTunnelInterfaceResponse(in);
diff --git a/core/java/android/net/IpSecUdpEncapResponse.java b/core/java/android/net/IpSecUdpEncapResponse.java
index 4679267..4e7ba9b 100644
--- a/core/java/android/net/IpSecUdpEncapResponse.java
+++ b/core/java/android/net/IpSecUdpEncapResponse.java
@@ -83,7 +83,7 @@
         fileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
     }
 
-    public static final Parcelable.Creator<IpSecUdpEncapResponse> CREATOR =
+    public static final @android.annotation.NonNull Parcelable.Creator<IpSecUdpEncapResponse> CREATOR =
             new Parcelable.Creator<IpSecUdpEncapResponse>() {
                 public IpSecUdpEncapResponse createFromParcel(Parcel in) {
                     return new IpSecUdpEncapResponse(in);
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 14a0cbf..6c7aa13 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -1164,7 +1164,7 @@
     }
 
     @UnsupportedAppUsage
-    public static final Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
+    public static final @android.annotation.NonNull Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
         @Override
         public NetworkStats createFromParcel(Parcel in) {
             return new NetworkStats(in);
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index d53e032..f61260e 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -719,7 +719,7 @@
     }
 
     @UnsupportedAppUsage
-    public static final Creator<NetworkStatsHistory> CREATOR = new Creator<NetworkStatsHistory>() {
+    public static final @android.annotation.NonNull Creator<NetworkStatsHistory> CREATOR = new Creator<NetworkStatsHistory>() {
         @Override
         public NetworkStatsHistory createFromParcel(Parcel in) {
             return new NetworkStatsHistory(in);
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 60ae352..ae421a4 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -495,7 +495,7 @@
     }
 
     @UnsupportedAppUsage
-    public static final Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
+    public static final @android.annotation.NonNull Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
         @Override
         public NetworkTemplate createFromParcel(Parcel in) {
             return new NetworkTemplate(in);
diff --git a/core/java/android/net/nsd/NsdServiceInfo.java b/core/java/android/net/nsd/NsdServiceInfo.java
index 9ba17ed..459b140 100644
--- a/core/java/android/net/nsd/NsdServiceInfo.java
+++ b/core/java/android/net/nsd/NsdServiceInfo.java
@@ -355,7 +355,7 @@
     }
 
     /** Implement the Parcelable interface */
-    public static final Creator<NsdServiceInfo> CREATOR =
+    public static final @android.annotation.NonNull Creator<NsdServiceInfo> CREATOR =
         new Creator<NsdServiceInfo>() {
             public NsdServiceInfo createFromParcel(Parcel in) {
                 NsdServiceInfo info = new NsdServiceInfo();
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index a0946a0..a629b3f 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -1277,7 +1277,7 @@
     public synchronized IpSecTunnelInterfaceResponse createTunnelInterface(
             String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder,
             String callingPackage) {
-        enforceTunnelPermissions(callingPackage);
+        enforceTunnelFeatureAndPermissions(callingPackage);
         checkNotNull(binder, "Null Binder passed to createTunnelInterface");
         checkNotNull(underlyingNetwork, "No underlying network was specified");
         checkInetAddress(localAddr);
@@ -1363,7 +1363,7 @@
     @Override
     public synchronized void addAddressToTunnelInterface(
             int tunnelResourceId, LinkAddress localAddr, String callingPackage) {
-        enforceTunnelPermissions(callingPackage);
+        enforceTunnelFeatureAndPermissions(callingPackage);
         UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
 
         // Get tunnelInterface record; if no such interface is found, will throw
@@ -1392,7 +1392,7 @@
     @Override
     public synchronized void removeAddressFromTunnelInterface(
             int tunnelResourceId, LinkAddress localAddr, String callingPackage) {
-        enforceTunnelPermissions(callingPackage);
+        enforceTunnelFeatureAndPermissions(callingPackage);
 
         UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
         // Get tunnelInterface record; if no such interface is found, will throw
@@ -1421,7 +1421,7 @@
     @Override
     public synchronized void deleteTunnelInterface(
             int resourceId, String callingPackage) throws RemoteException {
-        enforceTunnelPermissions(callingPackage);
+        enforceTunnelFeatureAndPermissions(callingPackage);
         UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
         releaseResource(userRecord.mTunnelInterfaceRecords, resourceId);
     }
@@ -1550,7 +1550,12 @@
 
     private static final String TUNNEL_OP = AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS;
 
-    private void enforceTunnelPermissions(String callingPackage) {
+    private void enforceTunnelFeatureAndPermissions(String callingPackage) {
+        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)) {
+            throw new UnsupportedOperationException(
+                    "IPsec Tunnel Mode requires PackageManager.FEATURE_IPSEC_TUNNELS");
+        }
+
         checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels");
         switch (getAppOpsManager().noteOp(TUNNEL_OP, Binder.getCallingUid(), callingPackage)) {
             case AppOpsManager.MODE_DEFAULT:
@@ -1622,7 +1627,7 @@
             IpSecConfig c, IBinder binder, String callingPackage) throws RemoteException {
         checkNotNull(c);
         if (c.getMode() == IpSecTransform.MODE_TUNNEL) {
-            enforceTunnelPermissions(callingPackage);
+            enforceTunnelFeatureAndPermissions(callingPackage);
         }
         checkIpSecConfig(c);
         checkNotNull(binder, "Null Binder passed to createTransform");
@@ -1730,7 +1735,7 @@
     public synchronized void applyTunnelModeTransform(
             int tunnelResourceId, int direction,
             int transformResourceId, String callingPackage) throws RemoteException {
-        enforceTunnelPermissions(callingPackage);
+        enforceTunnelFeatureAndPermissions(callingPackage);
         checkDirection(direction);
 
         int callingUid = Binder.getCallingUid();
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 90dc700..41806ca 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -105,6 +105,7 @@
 import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.INetworkManagementService;
+import android.os.Looper;
 import android.os.Message;
 import android.os.Messenger;
 import android.os.PowerManager;
@@ -322,6 +323,12 @@
                 Clock.systemUTC());
     }
 
+    private static final class NetworkStatsHandler extends Handler {
+        NetworkStatsHandler(Looper looper, Handler.Callback callback) {
+            super(looper, callback);
+        }
+    }
+
     public static NetworkStatsService create(Context context,
                 INetworkManagementService networkManager) {
         AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
@@ -338,7 +345,7 @@
         HandlerThread handlerThread = new HandlerThread(TAG);
         Handler.Callback callback = new HandlerCallback(service);
         handlerThread.start();
-        Handler handler = new Handler(handlerThread.getLooper(), callback);
+        Handler handler = new NetworkStatsHandler(handlerThread.getLooper(), callback);
         service.setHandler(handler, callback);
         return service;
     }