Merge "KeySetManagerService: prevent NPE"
am: c66327149a

Change-Id: I09d6fb3e2644ab9330b10bd67c44e61a204e589b
diff --git a/core/java/android/net/IIpConnectivityMetrics.aidl b/core/java/android/net/IIpConnectivityMetrics.aidl
index d36b766..8f634bb 100644
--- a/core/java/android/net/IIpConnectivityMetrics.aidl
+++ b/core/java/android/net/IIpConnectivityMetrics.aidl
@@ -23,8 +23,7 @@
 interface IIpConnectivityMetrics {
 
     /**
-     * @return the number of remaining available slots in buffer,
-     * or -1 if the event was dropped due to rate limiting.
+     * @return number of remaining available slots in buffer.
      */
     int logEvent(in ConnectivityMetricsEvent event);
 }
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index bdac134..21df50e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2725,6 +2725,7 @@
 
   <java-symbol type="bool" name="config_permissionReviewRequired" />
 
+
   <java-symbol type="drawable" name="ic_restart" />
 
   <java-symbol type="drawable" name="emergency_icon" />
diff --git a/core/tests/coretests/src/android/util/TokenBucketTest.java b/core/tests/coretests/src/android/util/TokenBucketTest.java
index f7ac20c..a053ad3 100644
--- a/core/tests/coretests/src/android/util/TokenBucketTest.java
+++ b/core/tests/coretests/src/android/util/TokenBucketTest.java
@@ -177,3 +177,4 @@
 
     interface Fn { void call(); }
 }
+
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 3b3ce07..78b33e5 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -760,8 +760,9 @@
             mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                     "Need BLUETOOTH ADMIN permission");
 
-            if (!isEnabled() && mPermissionReviewRequired) {
-                startConsentUi(packageName, callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE);
+            if (!isEnabled() && mPermissionReviewRequired
+                    && startConsentUiIfNeeded(packageName, callingUid,
+                            BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
                 return false;
             }
         }
@@ -795,8 +796,9 @@
             mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                     "Need BLUETOOTH ADMIN permission");
 
-            if (isEnabled() && mPermissionReviewRequired) {
-                startConsentUi(packageName, callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE);
+            if (isEnabled() && mPermissionReviewRequired
+                    && startConsentUiIfNeeded(packageName, callingUid,
+                            BluetoothAdapter.ACTION_REQUEST_DISABLE)) {
                 return false;
             }
         }
@@ -816,8 +818,8 @@
         return true;
     }
 
-    private void startConsentUi(String packageName, int callingUid, String intentAction)
-            throws RemoteException {
+    private boolean startConsentUiIfNeeded(String packageName,
+            int callingUid, String intentAction) throws RemoteException {
         try {
             // Validate the package only if we are going to use it
             ApplicationInfo applicationInfo = mContext.getPackageManager()
@@ -829,12 +831,16 @@
                         + " not in uid " + callingUid);
             }
 
-            // Permission review mode, trigger a user prompt
-            Intent intent = new Intent(intentAction);
-            mContext.startActivity(intent);
+            // Legacy apps in permission review mode trigger a user prompt
+            if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+                Intent intent = new Intent(intentAction);
+                mContext.startActivity(intent);
+                return true;
+            }
         } catch (PackageManager.NameNotFoundException e) {
             throw new RemoteException(e.getMessage());
         }
+        return false;
     }
 
     public void unbindAndFinish() {
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 97f913e..4405c1b 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -49,6 +49,7 @@
 import android.os.Environment;
 import android.os.FileUtils;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.IDeviceIdleController;
 import android.os.IMaintenanceActivityListener;
 import android.os.Looper;
@@ -1237,7 +1238,7 @@
         }
     }
 
-    public class LocalService {
+    public final class LocalService {
         public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync,
                 String reason) {
             addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index ae1aef6..10a5388 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -369,7 +369,7 @@
         // we do not start the service and launch a review activity if the calling app
         // is in the foreground passing it a pending intent to start the service when
         // review is completed.
-        if (mAm.mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED) {
+        if (Build.PERMISSIONS_REVIEW_REQUIRED) {
             if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage,
                     callingUid, service, callerFg, userId)) {
                 return null;
@@ -913,7 +913,7 @@
         // we schedule binding to the service but do not start its process, then
         // we launch a review activity to which is passed a callback to invoke
         // when done to start the bound service's process to completing the binding.
-        if (mAm.mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED) {
+        if (Build.PERMISSIONS_REVIEW_REQUIRED) {
             if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(
                     s.packageName, s.userId)) {
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 257ffb4..a9ddb63 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1576,8 +1576,6 @@
     // being called for multiwindow assist in a single session.
     private int mViSessionId = 1000;
 
-    final boolean mPermissionReviewRequired;
-
     final class KillHandler extends Handler {
         static final int KILL_PROCESS_GROUP_MSG = 4000;
 
@@ -2625,9 +2623,6 @@
 
         Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
 
-        mPermissionReviewRequired = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_permissionReviewRequired);
-
         mHandlerThread = new ServiceThread(TAG,
                 android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
         mHandlerThread.start();
@@ -10843,7 +10838,7 @@
                     // If permissions need a review before any of the app components can run,
                     // we return no provider and launch a review activity if the calling app
                     // is in the foreground.
-                    if (mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED) {
+                    if (Build.PERMISSIONS_REVIEW_REQUIRED) {
                         if (!requestTargetProviderPermissionsReviewIfNeededLocked(cpi, r, userId)) {
                             return null;
                         }
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 907394e..115971f 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -416,8 +416,7 @@
         // If permissions need a review before any of the app components can run, we
         // launch the review activity and pass a pending intent to start the activity
         // we are to launching now after the review is completed.
-        if ((mService.mPermissionReviewRequired
-                || Build.PERMISSIONS_REVIEW_REQUIRED) && aInfo != null) {
+        if (Build.PERMISSIONS_REVIEW_REQUIRED && aInfo != null) {
             if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
                     aInfo.packageName, userId)) {
                 IIntentSender target = mService.getIntentSenderLocked(
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index ea901ce..362a347 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -626,7 +626,7 @@
         // the broadcast and if the calling app is in the foreground and the broadcast is
         // explicit we launch the review UI passing it a pending intent to send the skipped
         // broadcast.
-        if (mService.mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED) {
+        if (Build.PERMISSIONS_REVIEW_REQUIRED) {
             if (!requestStartTargetPermissionsReviewIfNeededLocked(r, filter.packageName,
                     filter.owningUserId)) {
                 r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
@@ -1132,8 +1132,7 @@
             // the broadcast and if the calling app is in the foreground and the broadcast is
             // explicit we launch the review UI passing it a pending intent to send the skipped
             // broadcast.
-            if ((mService.mPermissionReviewRequired
-                    || Build.PERMISSIONS_REVIEW_REQUIRED) && !skip) {
+            if (Build.PERMISSIONS_REVIEW_REQUIRED && !skip) {
                 if (!requestStartTargetPermissionsReviewIfNeededLocked(r,
                         info.activityInfo.packageName, UserHandle.getUserId(
                                 info.activityInfo.applicationInfo.uid))) {
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
index be68173..642f2e0 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
@@ -19,19 +19,15 @@
 import android.content.Context;
 import android.net.ConnectivityMetricsEvent;
 import android.net.IIpConnectivityMetrics;
-import android.net.metrics.ApfProgramEvent;
 import android.net.metrics.IpConnectivityLog;
 import android.os.IBinder;
 import android.os.Parcelable;
 import android.provider.Settings;
 import android.text.TextUtils;
-import android.text.format.DateUtils;
-import android.util.ArrayMap;
 import android.util.Base64;
 import android.util.Log;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.TokenBucket;
 import com.android.server.SystemService;
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -60,8 +56,6 @@
     // Maximum size of the event buffer.
     private static final int MAXIMUM_BUFFER_SIZE = DEFAULT_BUFFER_SIZE * 10;
 
-    private static final int ERROR_RATE_LIMITED = -1;
-
     // Lock ensuring that concurrent manipulations of the event buffer are correct.
     // There are three concurrent operations to synchronize:
     //  - appending events to the buffer.
@@ -79,8 +73,6 @@
     private int mDropped;
     @GuardedBy("mLock")
     private int mCapacity;
-    @GuardedBy("mLock")
-    private final ArrayMap<Class<?>, TokenBucket> mBuckets = makeRateLimitingBuckets();
 
     private final ToIntFunction<Context> mCapacityGetter;
 
@@ -130,10 +122,6 @@
             if (event == null) {
                 return left;
             }
-            if (isRateLimited(event)) {
-                // Do not count as a dropped event. TODO: consider adding separate counter
-                return ERROR_RATE_LIMITED;
-            }
             if (left == 0) {
                 mDropped++;
                 return 0;
@@ -143,11 +131,6 @@
         }
     }
 
-    private boolean isRateLimited(ConnectivityMetricsEvent event) {
-        TokenBucket tb = mBuckets.get(event.data.getClass());
-        return (tb != null) && !tb.get();
-    }
-
     private String flushEncodedOutput() {
         final ArrayList<ConnectivityMetricsEvent> events;
         final int dropped;
@@ -273,11 +256,4 @@
         }
         return Math.min(size, MAXIMUM_BUFFER_SIZE);
     };
-
-    private static ArrayMap<Class<?>, TokenBucket> makeRateLimitingBuckets() {
-        ArrayMap<Class<?>, TokenBucket> map = new ArrayMap<>();
-        // one token every minute, 50 tokens max: burst of ~50 events every hour.
-        map.put(ApfProgramEvent.class, new TokenBucket((int)DateUtils.MINUTE_IN_MILLIS, 50));
-        return map;
-    }
 }
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 9ffa40b..c6bf4c5 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -27,7 +27,7 @@
 import android.os.UserHandle;
 import android.telephony.TelephonyManager;
 import android.util.Slog;
-import com.android.internal.annotations.VisibleForTesting;
+
 import com.android.internal.R;
 
 import static android.net.NetworkCapabilities.*;
@@ -37,8 +37,7 @@
 
     public static enum NotificationType { SIGN_IN, NO_INTERNET, LOST_INTERNET, NETWORK_SWITCH };
 
-    @VisibleForTesting
-    static final String NOTIFICATION_ID = "Connectivity.Notification";
+    private static final String NOTIFICATION_ID = "Connectivity.Notification";
 
     private static final String TAG = NetworkNotificationManager.class.getSimpleName();
     private static final boolean DBG = true;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 07dbb17..0e696b3 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1148,8 +1148,6 @@
     final @NonNull String mServicesSystemSharedLibraryPackageName;
     final @NonNull String mSharedSystemSharedLibraryPackageName;
 
-    final boolean mPermissionReviewRequired;
-
     private final PackageUsage mPackageUsage = new PackageUsage();
     private final CompilerStats mCompilerStats = new CompilerStats();
 
@@ -2080,10 +2078,6 @@
         }
 
         mContext = context;
-
-        mPermissionReviewRequired = context.getResources().getBoolean(
-                R.bool.config_permissionReviewRequired);
-
         mFactoryTest = factoryTest;
         mOnlyCore = onlyCore;
         mMetrics = new DisplayMetrics();
@@ -4057,7 +4051,7 @@
             // their permissions as always granted runtime ones since we need
             // to keep the review required permission flag per user while an
             // install permission's state is shared across all users.
-            if ((mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED)
+            if (Build.PERMISSIONS_REVIEW_REQUIRED
                     && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
                     && bp.isRuntime()) {
                 return;
@@ -4168,7 +4162,7 @@
             // their permissions as always granted runtime ones since we need
             // to keep the review required permission flag per user while an
             // install permission's state is shared across all users.
-            if ((mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED)
+            if (Build.PERMISSIONS_REVIEW_REQUIRED
                     && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
                     && bp.isRuntime()) {
                 return;
@@ -10061,8 +10055,7 @@
                     // their permissions as always granted runtime ones since we need
                     // to keep the review required permission flag per user while an
                     // install permission's state is shared across all users.
-                    if (!appSupportsRuntimePermissions && !mPermissionReviewRequired
-                            && !Build.PERMISSIONS_REVIEW_REQUIRED) {
+                    if (!appSupportsRuntimePermissions && !Build.PERMISSIONS_REVIEW_REQUIRED) {
                         // For legacy apps dangerous permissions are install time ones.
                         grant = GRANT_INSTALL;
                     } else if (origPermissions.hasInstallPermission(bp.name)) {
@@ -10148,7 +10141,7 @@
                                             changedRuntimePermissionUserIds, userId);
                                 }
                                 // If the app supports runtime permissions no need for a review.
-                                if ((mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED)
+                                if (Build.PERMISSIONS_REVIEW_REQUIRED
                                         && appSupportsRuntimePermissions
                                         && (flags & PackageManager
                                                 .FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
@@ -10157,8 +10150,7 @@
                                     changedRuntimePermissionUserIds = ArrayUtils.appendInt(
                                             changedRuntimePermissionUserIds, userId);
                                 }
-                            } else if ((mPermissionReviewRequired
-                                        || Build.PERMISSIONS_REVIEW_REQUIRED)
+                            } else if (Build.PERMISSIONS_REVIEW_REQUIRED
                                     && !appSupportsRuntimePermissions) {
                                 // For legacy apps that need a permission review, every new
                                 // runtime permission is granted but it is pending a review.
@@ -16753,7 +16745,7 @@
             // If permission review is enabled and this is a legacy app, mark the
             // permission as requiring a review as this is the initial state.
             int flags = 0;
-            if ((mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED)
+            if (Build.PERMISSIONS_REVIEW_REQUIRED
                     && ps.pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
                 flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
             }
@@ -20623,7 +20615,7 @@
         // permissions to keep per user flag state whether review is needed.
         // Hence, if a new user is added we have to propagate dangerous
         // permission grants for these legacy apps.
-        if (mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED) {
+        if (Build.PERMISSIONS_REVIEW_REQUIRED) {
             updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
                     | UPDATE_PERMISSIONS_REPLACE_ALL);
         }
@@ -21077,7 +21069,7 @@
         public boolean isPermissionsReviewRequired(String packageName, int userId) {
             synchronized (mPackages) {
                 // If we do not support permission review, done.
-                if (!mPermissionReviewRequired && !Build.PERMISSIONS_REVIEW_REQUIRED) {
+                if (!Build.PERMISSIONS_REVIEW_REQUIRED) {
                     return false;
                 }
 
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index a545af9..aeeca79 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -16,12 +16,17 @@
 
 package com.android.server;
 
+import static android.content.Intent.ACTION_UID_REMOVED;
+import static android.content.Intent.EXTRA_UID;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
 import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.NetworkPolicy.CYCLE_NONE;
 import static android.net.NetworkPolicy.LIMIT_DISABLED;
 import static android.net.NetworkPolicy.WARNING_DISABLED;
 import static android.net.NetworkPolicyManager.POLICY_NONE;
 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
+import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
+import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
 import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
 import static android.net.NetworkPolicyManager.computeNextCycleBoundary;
 import static android.net.TrafficStats.KB_IN_BYTES;
@@ -29,42 +34,28 @@
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 import static android.text.format.Time.TIMEZONE_UTC;
-
 import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT;
 import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED;
 import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING;
+import static org.easymock.EasyMock.anyInt;
+import static org.easymock.EasyMock.anyLong;
+import static org.easymock.EasyMock.aryEq;
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.isA;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isA;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.ActivityManager;
 import android.app.IActivityManager;
 import android.app.INotificationManager;
-import android.app.IUidObserver;
+import android.app.IProcessObserver;
 import android.app.Notification;
-import android.app.usage.UsageStatsManagerInternal;
-import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.Signature;
+import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
 import android.net.INetworkManagementEventObserver;
 import android.net.INetworkPolicyListener;
@@ -78,48 +69,40 @@
 import android.net.NetworkTemplate;
 import android.os.Binder;
 import android.os.INetworkManagementService;
-import android.os.PowerManagerInternal;
+import android.os.MessageQueue.IdleHandler;
 import android.os.UserHandle;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+import android.test.AndroidTestCase;
+import android.test.mock.MockPackageManager;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.Suppress;
 import android.text.format.Time;
-import android.util.Log;
 import android.util.TrustedTime;
 
 import com.android.internal.util.test.BroadcastInterceptingContext;
-import com.android.server.net.NetworkPolicyManagerInternal;
 import com.android.server.net.NetworkPolicyManagerService;
-
-import libcore.io.IoUtils;
-
 import com.google.common.util.concurrent.AbstractFuture;
 
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
 
 import java.io.File;
-import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
+import java.util.TimeZone;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.logging.Handler;
+
+import libcore.io.IoUtils;
 
 /**
  * Tests for {@link NetworkPolicyManagerService}.
  */
-@RunWith(AndroidJUnit4.class)
-public class NetworkPolicyManagerServiceTest {
+@LargeTest
+public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
     private static final String TAG = "NetworkPolicyManagerServiceTest";
 
     private static final long TEST_START = 1194220800000L;
@@ -131,19 +114,19 @@
     private BroadcastInterceptingContext mServiceContext;
     private File mPolicyDir;
 
-    private @Mock IActivityManager mActivityManager;
-    private @Mock INetworkStatsService mStatsService;
-    private @Mock INetworkManagementService mNetworkManager;
-    private @Mock TrustedTime mTime;
-    private @Mock IConnectivityManager mConnManager;
-    private @Mock INotificationManager mNotifManager;
-    private @Mock PackageManager mPackageManager;
+    private IActivityManager mActivityManager;
+    private INetworkStatsService mStatsService;
+    private INetworkManagementService mNetworkManager;
+    private INetworkPolicyListener mPolicyListener;
+    private TrustedTime mTime;
+    private IConnectivityManager mConnManager;
+    private INotificationManager mNotifManager;
 
-    private IUidObserver mUidObserver;
+    private NetworkPolicyManagerService mService;
+    private IProcessObserver mProcessObserver;
     private INetworkManagementEventObserver mNetworkObserver;
 
-    private NetworkPolicyListenerAnswer mPolicyListener;
-    private NetworkPolicyManagerService mService;
+    private Binder mStubBinder = new Binder();
 
     private long mStartTime;
     private long mElapsedRealtime;
@@ -156,30 +139,39 @@
     private static final int UID_A = UserHandle.getUid(USER_ID, APP_ID_A);
     private static final int UID_B = UserHandle.getUid(USER_ID, APP_ID_B);
 
-    private static final String PKG_NAME_A = "name.is.A,pkg.A";
+    private static final int PID_1 = 400;
+    private static final int PID_2 = 401;
+    private static final int PID_3 = 402;
 
-    @BeforeClass
-    public static void registerLocalServices() {
-        addLocalServiceMock(PowerManagerInternal.class);
-        addLocalServiceMock(DeviceIdleController.LocalService.class);
-        final UsageStatsManagerInternal usageStats =
-                addLocalServiceMock(UsageStatsManagerInternal.class);
-        when(usageStats.getIdleUidsForUser(anyInt())).thenReturn(new int[]{});
-    }
-
-    @Before
-    public void callSystemReady() throws Exception {
-        MockitoAnnotations.initMocks(this);
-
-        final Context context = InstrumentationRegistry.getContext();
+    public void _setUp() throws Exception {
+        super.setUp();
 
         setCurrentTimeMillis(TEST_START);
 
         // intercept various broadcasts, and pretend that uids have packages
-        mServiceContext = new BroadcastInterceptingContext(context) {
+        mServiceContext = new BroadcastInterceptingContext(getContext()) {
             @Override
             public PackageManager getPackageManager() {
-                return mPackageManager;
+                return new MockPackageManager() {
+                    @Override
+                    public String[] getPackagesForUid(int uid) {
+                        return new String[] { "com.example" };
+                    }
+
+                    @Override
+                    public PackageInfo getPackageInfo(String packageName, int flags) {
+                        final PackageInfo info = new PackageInfo();
+                        final Signature signature;
+                        if ("android".equals(packageName)) {
+                            signature = new Signature("F00D");
+                        } else {
+                            signature = new Signature("DEAD");
+                        }
+                        info.signatures = new Signature[] { signature };
+                        return info;
+                    }
+
+                };
             }
 
             @Override
@@ -188,112 +180,229 @@
             }
         };
 
-        mPolicyDir = context.getFilesDir();
+        mPolicyDir = getContext().getFilesDir();
         if (mPolicyDir.exists()) {
             IoUtils.deleteContents(mPolicyDir);
         }
 
-        doAnswer(new Answer<Void>() {
+        mActivityManager = createMock(IActivityManager.class);
+        mStatsService = createMock(INetworkStatsService.class);
+        mNetworkManager = createMock(INetworkManagementService.class);
+        mPolicyListener = createMock(INetworkPolicyListener.class);
+        mTime = createMock(TrustedTime.class);
+        mConnManager = createMock(IConnectivityManager.class);
+        mNotifManager = createMock(INotificationManager.class);
 
-            @Override
-            public Void answer(InvocationOnMock invocation) throws Throwable {
-                mUidObserver = (IUidObserver) invocation.getArguments()[0];
-                Log.d(TAG, "set mUidObserver to " + mUidObserver);
-                return null;
-            }
-        }).when(mActivityManager).registerUidObserver(any(), anyInt());
-
-        mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mStatsService,
-                mNetworkManager, mTime, mPolicyDir, true);
+        mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager,
+                mStatsService, mNetworkManager, mTime, mPolicyDir, true);
         mService.bindConnectivityManager(mConnManager);
         mService.bindNotificationManager(mNotifManager);
-        mPolicyListener = new NetworkPolicyListenerAnswer(mService);
 
-        // Sets some common expectations.
-        when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenAnswer(
-                new Answer<PackageInfo>() {
+        // RemoteCallbackList needs a binder to use as key
+        expect(mPolicyListener.asBinder()).andReturn(mStubBinder).atLeastOnce();
+        replay();
+        mService.registerListener(mPolicyListener);
+        verifyAndReset();
 
-                    @Override
-                    public PackageInfo answer(InvocationOnMock invocation) throws Throwable {
-                        final String packageName = (String) invocation.getArguments()[0];
-                        final PackageInfo info = new PackageInfo();
-                        final Signature signature;
-                        if ("android".equals(packageName)) {
-                            signature = new Signature("F00D");
-                        } else {
-                            signature = new Signature("DEAD");
-                        }
-                        info.signatures = new Signature[] {
-                            signature
-                        };
-                        return info;
-                    }
-                });
-        when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
-                .thenReturn(new ApplicationInfo());
-        when(mPackageManager.getPackagesForUid(UID_A)).thenReturn(new String[] {PKG_NAME_A});
-        when(mNetworkManager.isBandwidthControlEnabled()).thenReturn(true);
-        expectCurrentTime();
-
-        // Prepare NPMS.
-        mService.systemReady();
+        // catch IProcessObserver during systemReady()
+        final Capture<IProcessObserver> processObserver = new Capture<IProcessObserver>();
+        mActivityManager.registerProcessObserver(capture(processObserver));
+        expectLastCall().atLeastOnce();
 
         // catch INetworkManagementEventObserver during systemReady()
-        ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
-              ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
-        verify(mNetworkManager).registerObserver(networkObserver.capture());
+        final Capture<INetworkManagementEventObserver> networkObserver = new Capture<
+                INetworkManagementEventObserver>();
+        mNetworkManager.registerObserver(capture(networkObserver));
+        expectLastCall().atLeastOnce();
+
+        expect(mNetworkManager.isBandwidthControlEnabled()).andReturn(true).atLeastOnce();
+        expectCurrentTime();
+
+        replay();
+        mService.systemReady();
+        verifyAndReset();
+
+        mProcessObserver = processObserver.getValue();
         mNetworkObserver = networkObserver.getValue();
+
     }
 
-    @After
-    public void removeFiles() throws Exception {
+    public void _tearDown() throws Exception {
         for (File file : mPolicyDir.listFiles()) {
             file.delete();
         }
+
+        mServiceContext = null;
+        mPolicyDir = null;
+
+        mActivityManager = null;
+        mStatsService = null;
+        mPolicyListener = null;
+        mTime = null;
+
+        mService = null;
+        mProcessObserver = null;
+
+        super.tearDown();
     }
 
-    @After
-    public void unregisterLocalServices() throws Exception {
-        // Registered by NetworkPolicyManagerService's constructor.
-        LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
-    }
-
-    // NOTE: testPolicyChangeTriggersListener() and testUidForeground() are too superficial, they
-    // don't check for side-effects (like calls to NetworkManagementService) neither cover all
-    // different modes (Data Saver, Battery Saver, Doze, App idle, etc...).
-    // These scenarios are extensively tested on CTS' HostsideRestrictBackgroundNetworkTests.
-
-    @Test
-    public void testPolicyChangeTriggersListener() throws Exception {
-        mPolicyListener.expect().onRestrictBackgroundBlacklistChanged(anyInt(), anyBoolean());
-
+    @Suppress
+    public void testPolicyChangeTriggersBroadcast() throws Exception {
         mService.setUidPolicy(APP_ID_A, POLICY_NONE);
+
+        // change background policy and expect broadcast
+        final Future<Intent> backgroundChanged = mServiceContext.nextBroadcastIntent(
+                ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
+
         mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
 
-        mPolicyListener.waitAndVerify().onRestrictBackgroundBlacklistChanged(APP_ID_A, true);
+        backgroundChanged.get();
     }
 
-    @Test
-    public void testUidForeground() throws Exception {
-        // push all uids into background
-        mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE);
-        mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_SERVICE);
+    @Suppress
+    public void testPidForegroundCombined() throws Exception {
+        IdleFuture idle;
+
+        // push all uid into background
+        idle = expectIdle();
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
+        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, false);
+        idle.get();
         assertFalse(mService.isUidForeground(UID_A));
         assertFalse(mService.isUidForeground(UID_B));
 
-        // push one of the uids into foreground
-        mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_TOP);
+        // push one of the shared pids into foreground
+        idle = expectIdle();
+        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
+        idle.get();
         assertTrue(mService.isUidForeground(UID_A));
         assertFalse(mService.isUidForeground(UID_B));
 
         // and swap another uid into foreground
-        mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE);
-        mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_TOP);
+        idle = expectIdle();
+        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
+        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, true);
+        idle.get();
         assertFalse(mService.isUidForeground(UID_A));
         assertTrue(mService.isUidForeground(UID_B));
+
+        // push both pid into foreground
+        idle = expectIdle();
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
+        idle.get();
+        assertTrue(mService.isUidForeground(UID_A));
+
+        // pull one out, should still be foreground
+        idle = expectIdle();
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+        idle.get();
+        assertTrue(mService.isUidForeground(UID_A));
+
+        // pull final pid out, should now be background
+        idle = expectIdle();
+        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
+        idle.get();
+        assertFalse(mService.isUidForeground(UID_A));
     }
 
-    @Test
+    @Suppress
+    public void testPolicyNone() throws Exception {
+        Future<Void> future;
+
+        expectSetUidMeteredNetworkBlacklist(UID_A, false);
+        expectSetUidForeground(UID_A, true);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        replay();
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+        future.get();
+        verifyAndReset();
+
+        // POLICY_NONE should RULE_ALLOW in foreground
+        expectSetUidMeteredNetworkBlacklist(UID_A, false);
+        expectSetUidForeground(UID_A, true);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        replay();
+        mService.setUidPolicy(APP_ID_A, POLICY_NONE);
+        future.get();
+        verifyAndReset();
+
+        // POLICY_NONE should RULE_ALLOW in background
+        expectSetUidMeteredNetworkBlacklist(UID_A, false);
+        expectSetUidForeground(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        replay();
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+        future.get();
+        verifyAndReset();
+    }
+
+    @Suppress
+    public void testPolicyReject() throws Exception {
+        Future<Void> future;
+
+        // POLICY_REJECT should RULE_ALLOW in background
+        expectSetUidMeteredNetworkBlacklist(UID_A, true);
+        expectSetUidForeground(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
+        replay();
+        mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
+        future.get();
+        verifyAndReset();
+
+        // POLICY_REJECT should RULE_ALLOW in foreground
+        expectSetUidMeteredNetworkBlacklist(UID_A, false);
+        expectSetUidForeground(UID_A, true);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        replay();
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+        future.get();
+        verifyAndReset();
+
+        // POLICY_REJECT should RULE_REJECT in background
+        expectSetUidMeteredNetworkBlacklist(UID_A, true);
+        expectSetUidForeground(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
+        replay();
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+        future.get();
+        verifyAndReset();
+    }
+
+    @Suppress
+    public void testPolicyRejectAddRemove() throws Exception {
+        Future<Void> future;
+
+        // POLICY_NONE should have RULE_ALLOW in background
+        expectSetUidMeteredNetworkBlacklist(UID_A, false);
+        expectSetUidForeground(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        replay();
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+        mService.setUidPolicy(APP_ID_A, POLICY_NONE);
+        future.get();
+        verifyAndReset();
+
+        // adding POLICY_REJECT should cause RULE_REJECT
+        expectSetUidMeteredNetworkBlacklist(UID_A, true);
+        expectSetUidForeground(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
+        replay();
+        mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
+        future.get();
+        verifyAndReset();
+
+        // removing POLICY_REJECT should return us to RULE_ALLOW
+        expectSetUidMeteredNetworkBlacklist(UID_A, false);
+        expectSetUidForeground(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        replay();
+        mService.setUidPolicy(APP_ID_A, POLICY_NONE);
+        future.get();
+        verifyAndReset();
+    }
+
     public void testLastCycleBoundaryThisMonth() throws Exception {
         // assume cycle day of "5th", which should be in same month
         final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
@@ -305,7 +414,6 @@
         assertTimeEquals(expectedCycle, actualCycle);
     }
 
-    @Test
     public void testLastCycleBoundaryLastMonth() throws Exception {
         // assume cycle day of "20th", which should be in last month
         final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
@@ -317,7 +425,6 @@
         assertTimeEquals(expectedCycle, actualCycle);
     }
 
-    @Test
     public void testLastCycleBoundaryThisMonthFebruary() throws Exception {
         // assume cycle day of "30th" in february; should go to january
         final long currentTime = parseTime("2007-02-14T00:00:00.000Z");
@@ -329,7 +436,6 @@
         assertTimeEquals(expectedCycle, actualCycle);
     }
 
-    @Test
     public void testLastCycleBoundaryLastMonthFebruary() throws Exception {
         // assume cycle day of "30th" in february, which should clamp
         final long currentTime = parseTime("2007-03-14T00:00:00.000Z");
@@ -341,7 +447,6 @@
         assertTimeEquals(expectedCycle, actualCycle);
     }
 
-    @Test
     public void testCycleBoundaryLeapYear() throws Exception {
         final NetworkPolicy policy = new NetworkPolicy(
                 sTemplateWifi, 29, TIMEZONE_UTC, 1024L, 1024L, false);
@@ -365,7 +470,6 @@
                 computeNextCycleBoundary(parseTime("2007-03-14T00:00:00.000Z"), policy));
     }
 
-    @Test
     public void testNextCycleTimezoneAfterUtc() throws Exception {
         // US/Central is UTC-6
         final NetworkPolicy policy = new NetworkPolicy(
@@ -374,7 +478,6 @@
                 computeNextCycleBoundary(parseTime("2012-01-05T00:00:00.000Z"), policy));
     }
 
-    @Test
     public void testNextCycleTimezoneBeforeUtc() throws Exception {
         // Israel is UTC+2
         final NetworkPolicy policy = new NetworkPolicy(
@@ -383,7 +486,6 @@
                 computeNextCycleBoundary(parseTime("2012-01-05T00:00:00.000Z"), policy));
     }
 
-    @Test
     public void testNextCycleSane() throws Exception {
         final NetworkPolicy policy = new NetworkPolicy(
                 sTemplateWifi, 31, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, false);
@@ -399,7 +501,6 @@
         }
     }
 
-    @Test
     public void testLastCycleSane() throws Exception {
         final NetworkPolicy policy = new NetworkPolicy(
                 sTemplateWifi, 31, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, false);
@@ -415,7 +516,6 @@
         }
     }
 
-    @Test
     public void testCycleTodayJanuary() throws Exception {
         final NetworkPolicy policy = new NetworkPolicy(
                 sTemplateWifi, 14, "US/Pacific", 1024L, 1024L, false);
@@ -435,7 +535,6 @@
                 computeLastCycleBoundary(parseTime("2013-01-14T15:11:00.000-08:00"), policy));
     }
 
-    @Test
     public void testLastCycleBoundaryDST() throws Exception {
         final long currentTime = parseTime("1989-01-02T07:30:00.000");
         final long expectedCycle = parseTime("1988-12-03T02:00:00.000Z");
@@ -446,7 +545,6 @@
         assertTimeEquals(expectedCycle, actualCycle);
     }
 
-    @Test
     public void testLastCycleBoundaryJanuaryDST() throws Exception {
         final long currentTime = parseTime("1989-01-26T21:00:00.000Z");
         final long expectedCycle = parseTime("1989-01-01T01:59:59.000Z");
@@ -457,10 +555,11 @@
         assertTimeEquals(expectedCycle, actualCycle);
     }
 
-    @Test
+    @Suppress
     public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
         NetworkState[] state = null;
         NetworkStats stats = null;
+        Future<Void> future;
 
         final long TIME_FEB_15 = 1171497600000L;
         final long TIME_MAR_10 = 1173484800000L;
@@ -471,40 +570,75 @@
         // first, pretend that wifi network comes online. no policy active,
         // which means we shouldn't push limit to interface.
         state = new NetworkState[] { buildWifi() };
-        when(mConnManager.getAllNetworkState()).thenReturn(state);
+        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
         expectCurrentTime();
+        expectClearNotifications();
+        expectAdvisePersistThreshold();
+        future = expectMeteredIfacesChanged();
 
-        mPolicyListener.expect().onMeteredIfacesChanged(any());
+        replay();
         mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
-        mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any());
+        future.get();
+        verifyAndReset();
 
         // now change cycle to be on 15th, and test in early march, to verify we
         // pick cycle day in previous month.
-        when(mConnManager.getAllNetworkState()).thenReturn(state);
+        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
         expectCurrentTime();
 
         // pretend that 512 bytes total have happened
         stats = new NetworkStats(getElapsedRealtime(), 1)
                 .addIfaceValues(TEST_IFACE, 256L, 2L, 256L, 2L);
-        when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
-                .thenReturn(stats.getTotalBytes());
-
-        mPolicyListener.expect().onMeteredIfacesChanged(any());
-        setNetworkPolicies(new NetworkPolicy(
-                sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
-        mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+        expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
+                .andReturn(stats.getTotalBytes()).atLeastOnce();
+        expectPolicyDataEnable(TYPE_WIFI, true);
 
         // TODO: consider making strongly ordered mock
-        verifyPolicyDataEnable(TYPE_WIFI, true);
-        verifyRemoveInterfaceQuota(TEST_IFACE);
-        verifySetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512);
+        expectRemoveInterfaceQuota(TEST_IFACE);
+        expectSetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512);
+
+        expectClearNotifications();
+        expectAdvisePersistThreshold();
+        future = expectMeteredIfacesChanged(TEST_IFACE);
+
+        replay();
+        setNetworkPolicies(new NetworkPolicy(
+                sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
+        future.get();
+        verifyAndReset();
     }
 
-    @Test
+    @Suppress
+    public void testUidRemovedPolicyCleared() throws Exception {
+        Future<Void> future;
+
+        // POLICY_REJECT should RULE_REJECT in background
+        expectSetUidMeteredNetworkBlacklist(UID_A, true);
+        expectSetUidForeground(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
+        replay();
+        mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
+        future.get();
+        verifyAndReset();
+
+        // uninstall should clear RULE_REJECT
+        expectSetUidMeteredNetworkBlacklist(UID_A, false);
+        expectSetUidForeground(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        replay();
+        final Intent intent = new Intent(ACTION_UID_REMOVED);
+        intent.putExtra(EXTRA_UID, UID_A);
+        mServiceContext.sendBroadcast(intent);
+        future.get();
+        verifyAndReset();
+    }
+
+    @Suppress
     public void testOverWarningLimitNotification() throws Exception {
         NetworkState[] state = null;
         NetworkStats stats = null;
-        Future<String> tagFuture = null;
+        Future<Void> future;
+        Future<String> tagFuture;
 
         final long TIME_FEB_15 = 1171497600000L;
         final long TIME_MAR_10 = 1173484800000L;
@@ -519,15 +653,20 @@
 
         {
             expectCurrentTime();
-            when(mConnManager.getAllNetworkState()).thenReturn(state);
-            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
-                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
+            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+                    .andReturn(stats.getTotalBytes()).atLeastOnce();
+            expectPolicyDataEnable(TYPE_WIFI, true);
 
-            mPolicyListener.expect().onMeteredIfacesChanged(any());
+            expectClearNotifications();
+            expectAdvisePersistThreshold();
+            future = expectMeteredIfacesChanged();
+
+            replay();
             setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1
                     * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
-            mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any());
-            verifyPolicyDataEnable(TYPE_WIFI, true);
+            future.get();
+            verifyAndReset();
         }
 
         // bring up wifi network
@@ -538,17 +677,22 @@
 
         {
             expectCurrentTime();
-            when(mConnManager.getAllNetworkState()).thenReturn(state);
-            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
-                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
+            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+                    .andReturn(stats.getTotalBytes()).atLeastOnce();
+            expectPolicyDataEnable(TYPE_WIFI, true);
 
-            mPolicyListener.expect().onMeteredIfacesChanged(any());
+            expectRemoveInterfaceQuota(TEST_IFACE);
+            expectSetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
+
+            expectClearNotifications();
+            expectAdvisePersistThreshold();
+            future = expectMeteredIfacesChanged(TEST_IFACE);
+
+            replay();
             mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
-            mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
-
-            verifyPolicyDataEnable(TYPE_WIFI, true);
-            verifyRemoveInterfaceQuota(TEST_IFACE);
-            verifySetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
+            future.get();
+            verifyAndReset();
         }
 
         // go over warning, which should kick notification
@@ -558,15 +702,18 @@
 
         {
             expectCurrentTime();
-            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
-                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
+            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+                    .andReturn(stats.getTotalBytes()).atLeastOnce();
+            expectPolicyDataEnable(TYPE_WIFI, true);
+
+            expectForceUpdate();
+            expectClearNotifications();
             tagFuture = expectEnqueueNotification();
 
+            replay();
             mNetworkObserver.limitReached(null, TEST_IFACE);
-
             assertNotificationType(TYPE_WARNING, tagFuture.get());
-            verifyPolicyDataEnable(TYPE_WIFI, true);
-
+            verifyAndReset();
         }
 
         // go over limit, which should kick notification and dialog
@@ -576,14 +723,18 @@
 
         {
             expectCurrentTime();
-            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
-                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
+            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+                    .andReturn(stats.getTotalBytes()).atLeastOnce();
+            expectPolicyDataEnable(TYPE_WIFI, false);
+
+            expectForceUpdate();
+            expectClearNotifications();
             tagFuture = expectEnqueueNotification();
 
+            replay();
             mNetworkObserver.limitReached(null, TEST_IFACE);
-
             assertNotificationType(TYPE_LIMIT, tagFuture.get());
-            verifyPolicyDataEnable(TYPE_WIFI, false);
+            verifyAndReset();
         }
 
         // now snooze policy, which should remove quota
@@ -591,28 +742,35 @@
 
         {
             expectCurrentTime();
-            when(mConnManager.getAllNetworkState()).thenReturn(state);
-            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
-                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
-            tagFuture = expectEnqueueNotification();
+            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+                    .andReturn(stats.getTotalBytes()).atLeastOnce();
+            expectPolicyDataEnable(TYPE_WIFI, true);
 
-            mPolicyListener.expect().onMeteredIfacesChanged(any());
-            mService.snoozeLimit(sTemplateWifi);
-            mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
-
-            assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get());
             // snoozed interface still has high quota so background data is
             // still restricted.
-            verifyRemoveInterfaceQuota(TEST_IFACE);
-            verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
-            verifyPolicyDataEnable(TYPE_WIFI, true);
+            expectRemoveInterfaceQuota(TEST_IFACE);
+            expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
+            expectAdvisePersistThreshold();
+            expectMeteredIfacesChanged(TEST_IFACE);
+
+            future = expectClearNotifications();
+            tagFuture = expectEnqueueNotification();
+
+            replay();
+            mService.snoozeLimit(sTemplateWifi);
+            assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get());
+            future.get();
+            verifyAndReset();
         }
     }
 
-    @Test
+    @Suppress
     public void testMeteredNetworkWithoutLimit() throws Exception {
         NetworkState[] state = null;
         NetworkStats stats = null;
+        Future<Void> future;
+        Future<String> tagFuture;
 
         final long TIME_FEB_15 = 1171497600000L;
         final long TIME_MAR_10 = 1173484800000L;
@@ -627,19 +785,24 @@
 
         {
             expectCurrentTime();
-            when(mConnManager.getAllNetworkState()).thenReturn(state);
-            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
-                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
+            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+                    .andReturn(stats.getTotalBytes()).atLeastOnce();
+            expectPolicyDataEnable(TYPE_WIFI, true);
 
-            mPolicyListener.expect().onMeteredIfacesChanged(any());
+            expectRemoveInterfaceQuota(TEST_IFACE);
+            expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
+
+            expectClearNotifications();
+            expectAdvisePersistThreshold();
+            future = expectMeteredIfacesChanged(TEST_IFACE);
+
+            replay();
             setNetworkPolicies(new NetworkPolicy(
                     sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED,
                     true));
-            mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
-
-            verifyPolicyDataEnable(TYPE_WIFI, true);
-            verifyRemoveInterfaceQuota(TEST_IFACE);
-            verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
+            future.get();
+            verifyAndReset();
         }
     }
 
@@ -662,36 +825,87 @@
     }
 
     private void expectCurrentTime() throws Exception {
-        when(mTime.forceRefresh()).thenReturn(false);
-        when(mTime.hasCache()).thenReturn(true);
-        when(mTime.currentTimeMillis()).thenReturn(currentTimeMillis());
-        when(mTime.getCacheAge()).thenReturn(0L);
-        when(mTime.getCacheCertainty()).thenReturn(0L);
+        expect(mTime.forceRefresh()).andReturn(false).anyTimes();
+        expect(mTime.hasCache()).andReturn(true).anyTimes();
+        expect(mTime.currentTimeMillis()).andReturn(currentTimeMillis()).anyTimes();
+        expect(mTime.getCacheAge()).andReturn(0L).anyTimes();
+        expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
+    }
+
+    private void expectForceUpdate() throws Exception {
+        mStatsService.forceUpdate();
+        expectLastCall().atLeastOnce();
+    }
+
+    private Future<Void> expectClearNotifications() throws Exception {
+        final FutureAnswer future = new FutureAnswer();
+        mNotifManager.cancelNotificationWithTag(
+                isA(String.class), isA(String.class), anyInt(), anyInt());
+        expectLastCall().andAnswer(future).anyTimes();
+        return future;
     }
 
     private Future<String> expectEnqueueNotification() throws Exception {
-        final FutureAnswer<String> futureAnswer = new FutureAnswer<String>(2);
-        doAnswer(futureAnswer).when(mNotifManager).enqueueNotificationWithTag(
-                anyString(), anyString(), anyString() /* capture here (index 2)*/,
-                anyInt(), isA(Notification.class), isA(int[].class), anyInt());
-        return futureAnswer;
+        final FutureCapture<String> tag = new FutureCapture<String>();
+        mNotifManager.enqueueNotificationWithTag(isA(String.class), isA(String.class),
+                capture(tag.capture), anyInt(),
+                isA(Notification.class), isA(int[].class), UserHandle.myUserId());
+        return tag;
     }
 
-    private void verifySetInterfaceQuota(String iface, long quotaBytes) throws Exception {
-        verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(iface, quotaBytes);
+    private void expectSetInterfaceQuota(String iface, long quotaBytes) throws Exception {
+        mNetworkManager.setInterfaceQuota(iface, quotaBytes);
+        expectLastCall().atLeastOnce();
     }
 
-    private void verifyRemoveInterfaceQuota(String iface) throws Exception {
-        verify(mNetworkManager, atLeastOnce()).removeInterfaceQuota(iface);
+    private void expectRemoveInterfaceQuota(String iface) throws Exception {
+        mNetworkManager.removeInterfaceQuota(iface);
+        expectLastCall().atLeastOnce();
     }
 
-    private Future<Void> verifyPolicyDataEnable(int type, boolean enabled) throws Exception {
+    private void expectSetInterfaceAlert(String iface, long alertBytes) throws Exception {
+        mNetworkManager.setInterfaceAlert(iface, alertBytes);
+        expectLastCall().atLeastOnce();
+    }
+
+    private void expectRemoveInterfaceAlert(String iface) throws Exception {
+        mNetworkManager.removeInterfaceAlert(iface);
+        expectLastCall().atLeastOnce();
+    }
+
+    private void expectSetUidMeteredNetworkBlacklist(int uid, boolean rejectOnQuotaInterfaces)
+            throws Exception {
+        mNetworkManager.setUidMeteredNetworkBlacklist(uid, rejectOnQuotaInterfaces);
+        expectLastCall().atLeastOnce();
+    }
+
+    private void expectSetUidForeground(int uid, boolean uidForeground) throws Exception {
+        mStatsService.setUidForeground(uid, uidForeground);
+        expectLastCall().atLeastOnce();
+    }
+
+    private Future<Void> expectRulesChanged(int uid, int policy) throws Exception {
+        final FutureAnswer future = new FutureAnswer();
+        mPolicyListener.onUidRulesChanged(eq(uid), eq(policy));
+        expectLastCall().andAnswer(future);
+        return future;
+    }
+
+    private Future<Void> expectMeteredIfacesChanged(String... ifaces) throws Exception {
+        final FutureAnswer future = new FutureAnswer();
+        mPolicyListener.onMeteredIfacesChanged(aryEq(ifaces));
+        expectLastCall().andAnswer(future);
+        return future;
+    }
+
+    private Future<Void> expectPolicyDataEnable(int type, boolean enabled) throws Exception {
         // TODO: bring back this test
         return null;
     }
 
-    private void verifyAdvisePersistThreshold() throws Exception {
-        verify(mStatsService).advisePersistThreshold(anyLong());
+    private void expectAdvisePersistThreshold() throws Exception {
+        mStatsService.advisePersistThreshold(anyLong());
+        expectLastCall().anyTimes();
     }
 
     private static class TestAbstractFuture<T> extends AbstractFuture<T> {
@@ -705,21 +919,50 @@
         }
     }
 
-    private static class FutureAnswer<T> extends TestAbstractFuture<T> implements Answer<Void> {
-        private final int index;
-
-        FutureAnswer(int index) {
-            this.index = index;
-        }
+    private static class FutureAnswer extends TestAbstractFuture<Void> implements IAnswer<Void> {
         @Override
-        public Void answer(InvocationOnMock invocation) throws Throwable {
-            @SuppressWarnings("unchecked")
-            T captured = (T) invocation.getArguments()[index];
-            set(captured);
+        public Void answer() {
+            set(null);
             return null;
         }
     }
 
+    private static class FutureCapture<T> extends TestAbstractFuture<T> {
+        public Capture<T> capture = new Capture<T>() {
+            @Override
+            public void setValue(T value) {
+                super.setValue(value);
+                set(value);
+            }
+        };
+    }
+
+    private static class IdleFuture extends AbstractFuture<Void> implements IdleHandler {
+        @Override
+        public Void get() throws InterruptedException, ExecutionException {
+            try {
+                return get(5, TimeUnit.SECONDS);
+            } catch (TimeoutException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        public boolean queueIdle() {
+            set(null);
+            return false;
+        }
+    }
+
+    /**
+     * Wait until {@link #mService} internal {@link Handler} is idle.
+     */
+    private IdleFuture expectIdle() {
+        final IdleFuture future = new IdleFuture();
+        mService.addIdleHandler(future);
+        return future;
+    }
+
     private static void assertTimeEquals(long expected, long actual) {
         if (expected != actual) {
             fail("expected " + formatTime(expected) + " but was actually " + formatTime(actual));
@@ -747,7 +990,7 @@
     }
 
     private static void assertNotificationType(int expected, String actualTag) {
-        assertEquals("notification type mismatch for '" + actualTag +"'",
+        assertEquals(
                 Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
     }
 
@@ -768,59 +1011,15 @@
         mElapsedRealtime += duration;
     }
 
-    /**
-     * Creates a mock and registers it to {@link LocalServices}.
-     */
-    private static <T> T addLocalServiceMock(Class<T> clazz) {
-        final T mock = mock(clazz);
-        LocalServices.addService(clazz, mock);
-        return mock;
+    private void replay() {
+        EasyMock.replay(mActivityManager, mStatsService, mPolicyListener, mNetworkManager, mTime,
+                mConnManager, mNotifManager);
     }
 
-    /**
-     * Custom Mockito answer used to verify async {@link INetworkPolicyListener} calls.
-     *
-     * <p>Typical usage:
-     * <pre><code>
-     *    mPolicyListener.expect().someCallback(any());
-     *    // do something on objects under test
-     *    mPolicyListener.waitAndVerify().someCallback(eq(expectedValue));
-     * </code></pre>
-     */
-    final class NetworkPolicyListenerAnswer implements Answer<Void> {
-        private CountDownLatch latch;
-        private final INetworkPolicyListener listener;
-
-        NetworkPolicyListenerAnswer(NetworkPolicyManagerService service) {
-            this.listener = mock(INetworkPolicyListener.class);
-            // RemoteCallbackList needs a binder to use as key
-            when(listener.asBinder()).thenReturn(new Binder());
-            service.registerListener(listener);
-        }
-
-        @Override
-        public Void answer(InvocationOnMock invocation) throws Throwable {
-            Log.d(TAG,"counting down on answer: " + invocation);
-            latch.countDown();
-            return null;
-        }
-
-        INetworkPolicyListener expect() {
-            assertNull("expect() called before waitAndVerify()", latch);
-            latch = new CountDownLatch(1);
-            return doAnswer(this).when(listener);
-        }
-
-        INetworkPolicyListener waitAndVerify() {
-            assertNotNull("waitAndVerify() called before expect()", latch);
-            try {
-                assertTrue("callback not called in 5 seconds", latch.await(5, TimeUnit.SECONDS));
-            } catch (InterruptedException e) {
-                fail("Thread interrupted before callback called");
-            } finally {
-                latch = null;
-            }
-            return verify(listener, atLeastOnce());
-        }
+    private void verifyAndReset() {
+        EasyMock.verify(mActivityManager, mStatsService, mPolicyListener, mNetworkManager, mTime,
+                mConnManager, mNotifManager);
+        EasyMock.reset(mActivityManager, mStatsService, mPolicyListener, mNetworkManager, mTime,
+                mConnManager, mNotifManager);
     }
 }
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index aa491bb..14b5cbe 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.net.ConnectivityMetricsEvent;
 import android.net.IIpConnectivityMetrics;
-import android.net.metrics.ApfProgramEvent;
 import android.net.metrics.ApfStats;
 import android.net.metrics.DefaultNetworkEvent;
 import android.net.metrics.DhcpClientEvent;
@@ -113,27 +112,6 @@
         assertEquals("", output3);
     }
 
-    public void testRateLimiting() {
-        final IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
-        final ApfProgramEvent ev = new ApfProgramEvent(0, 0, 0, 0, 0);
-        final long fakeTimestamp = 1;
-
-        int attempt = 100; // More than burst quota, but less than buffer size.
-        for (int i = 0; i < attempt; i++) {
-            logger.log(ev);
-        }
-
-        String output1 = getdump("flush");
-        assertFalse("".equals(output1));
-
-        for (int i = 0; i < attempt; i++) {
-            assertFalse("expected event to be dropped", logger.log(fakeTimestamp, ev));
-        }
-
-        String output2 = getdump("flush");
-        assertEquals("", output2);
-    }
-
     public void testEndToEndLogging() {
         IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
 
diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
deleted file mode 100644
index 813e928..0000000
--- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2016 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 com.android.server.connectivity;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
-import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
-import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import junit.framework.TestCase;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.*;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class NetworkNotificationManagerTest extends TestCase {
-
-    static final String NOTIFICATION_ID = NetworkNotificationManager.NOTIFICATION_ID;
-
-    static final NetworkCapabilities CELL_CAPABILITIES = new NetworkCapabilities();
-    static final NetworkCapabilities WIFI_CAPABILITIES = new NetworkCapabilities();
-    static {
-        CELL_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
-        CELL_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
-
-        WIFI_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
-        WIFI_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
-    }
-
-    @Mock Context mCtx;
-    @Mock Resources mResources;
-    @Mock PackageManager mPm;
-    @Mock TelephonyManager mTelephonyManager;
-    @Mock NotificationManager mNotificationManager;
-    @Mock NetworkAgentInfo mWifiNai;
-    @Mock NetworkAgentInfo mCellNai;
-    @Mock NetworkInfo mNetworkInfo;
-    ArgumentCaptor<Notification> mCaptor;
-
-    NetworkNotificationManager mManager;
-
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mCaptor = ArgumentCaptor.forClass(Notification.class);
-        mWifiNai.networkCapabilities = WIFI_CAPABILITIES;
-        mWifiNai.networkInfo = mNetworkInfo;
-        mCellNai.networkCapabilities = CELL_CAPABILITIES;
-        mCellNai.networkInfo = mNetworkInfo;
-        when(mCtx.getResources()).thenReturn(mResources);
-        when(mCtx.getPackageManager()).thenReturn(mPm);
-        when(mCtx.getApplicationInfo()).thenReturn(new ApplicationInfo());
-        when(mResources.getColor(anyInt(), any())).thenReturn(0xFF607D8B);
-
-        mManager = new NetworkNotificationManager(mCtx, mTelephonyManager, mNotificationManager);
-    }
-
-    @SmallTest
-    public void testNotificationsShownAndCleared() {
-        final int NETWORK_ID_BASE = 100;
-        List<NotificationType> types = Arrays.asList(NotificationType.values());
-        List<Integer> ids = new ArrayList<>(types.size());
-        for (int i = 0; i < ids.size(); i++) {
-            ids.add(NETWORK_ID_BASE + i);
-        }
-        Collections.shuffle(ids);
-        Collections.shuffle(types);
-
-        for (int i = 0; i < ids.size(); i++) {
-            mManager.showNotification(ids.get(i), types.get(i), mWifiNai, mCellNai, null, false);
-        }
-
-        Collections.shuffle(ids);
-        for (int i = 0; i < ids.size(); i++) {
-            mManager.clearNotification(ids.get(i));
-        }
-
-        for (int i = 0; i < ids.size(); i++) {
-            final int expectedId = NETWORK_ID_BASE + i;
-            verify(mNotificationManager, times(1))
-                    .notifyAsUser(eq(NOTIFICATION_ID), eq(expectedId), any(), any());
-            verify(mNotificationManager, times(1))
-                    .cancelAsUser(eq(NOTIFICATION_ID), eq(expectedId), any());
-        }
-    }
-
-    @SmallTest
-    public void testNoInternetNotificationsNotShownForCellular() {
-        mManager.showNotification(100, NO_INTERNET, mCellNai, mWifiNai, null, false);
-        mManager.showNotification(101, LOST_INTERNET, mCellNai, mWifiNai, null, false);
-
-        verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
-
-        mManager.showNotification(102, NO_INTERNET, mWifiNai, mCellNai, null, false);
-
-        verify(mNotificationManager, times(1))
-                .notifyAsUser(eq(NOTIFICATION_ID), eq(102), any(), any());
-    }
-
-    @SmallTest
-    public void testNotificationsNotShownIfNoInternetCapability() {
-        mWifiNai.networkCapabilities = new NetworkCapabilities();
-        mWifiNai.networkCapabilities .addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
-        mManager.showNotification(102, NO_INTERNET, mWifiNai, mCellNai, null, false);
-        mManager.showNotification(103, LOST_INTERNET, mWifiNai, mCellNai, null, false);
-        mManager.showNotification(104, NETWORK_SWITCH, mWifiNai, mCellNai, null, false);
-
-        verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
-    }
-}