DO NOT MERGE: Fixed NetworkPolicyManagerServiceTest.

NetworkPolicyManagerServiceTest had many tests there were @Suppressed
because they were obsolete and harder to fix using Easymocks.

This CL replaced EasyMock by Mockito and re-enabled most tests, although
some tests were removed because:
- It's underlying logic changed too much that.
- It would be hard to mock all external entities they interact with.
- They are covered by CTS tests.

Bug: 30764608
Test: runtest --path
frameworks/base/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java

(cherry picked from commit I53ff86fc9b64cb058846f1aefa244771630d9e1e)

Change-Id: Ia9cdb780cb0917477b310dc38d2e39731d6a7609
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 4405c1b..97f913e 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -49,7 +49,6 @@
 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;
@@ -1238,7 +1237,7 @@
         }
     }
 
-    public final class LocalService {
+    public class LocalService {
         public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync,
                 String reason) {
             addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason);
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 8d36ac9..d890444 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -16,17 +16,12 @@
 
 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;
@@ -34,28 +29,36 @@
 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.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.IProcessObserver;
+import android.app.IUidObserver;
 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;
@@ -69,39 +72,40 @@
 import android.net.NetworkTemplate;
 import android.os.Binder;
 import android.os.INetworkManagementService;
-import android.os.MessageQueue.IdleHandler;
+import android.os.PowerManagerInternal;
 import android.os.UserHandle;
 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.easymock.Capture;
-import org.easymock.EasyMock;
-import org.easymock.IAnswer;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 
 import java.io.File;
-import java.util.Calendar;
+import java.util.ArrayList;
 import java.util.LinkedHashSet;
-import java.util.TimeZone;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
 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}.
  */
-@LargeTest
 public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
     private static final String TAG = "NetworkPolicyManagerServiceTest";
 
@@ -113,20 +117,22 @@
 
     private BroadcastInterceptingContext mServiceContext;
     private File mPolicyDir;
+    private List<Class<?>> mLocalServices = new ArrayList<>();
 
-    private IActivityManager mActivityManager;
-    private INetworkStatsService mStatsService;
-    private INetworkManagementService mNetworkManager;
-    private INetworkPolicyListener mPolicyListener;
-    private TrustedTime mTime;
-    private IConnectivityManager mConnManager;
-    private INotificationManager mNotifManager;
+    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 UsageStatsManagerInternal mUsageStats;
+    private @Mock PackageManager mPackageManager;
 
-    private NetworkPolicyManagerService mService;
-    private IProcessObserver mProcessObserver;
+    private IUidObserver mUidObserver;
     private INetworkManagementEventObserver mNetworkObserver;
 
-    private Binder mStubBinder = new Binder();
+    private NetworkPolicyListenerAnswer mPolicyListener;
+    private NetworkPolicyManagerService mService;
 
     private long mStartTime;
     private long mElapsedRealtime;
@@ -139,39 +145,22 @@
     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 int PID_1 = 400;
-    private static final int PID_2 = 401;
-    private static final int PID_3 = 402;
+    private static final String PKG_NAME_A = "name.is.A,pkg.A";
 
-    public void _setUp() throws Exception {
+    public void setUp() throws Exception {
         super.setUp();
 
+        MockitoAnnotations.initMocks(this);
+
+        final Context context = getContext();
+
         setCurrentTimeMillis(TEST_START);
 
         // intercept various broadcasts, and pretend that uids have packages
-        mServiceContext = new BroadcastInterceptingContext(getContext()) {
+        mServiceContext = new BroadcastInterceptingContext(context) {
             @Override
             public PackageManager getPackageManager() {
-                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;
-                    }
-
-                };
+                return mPackageManager;
             }
 
             @Override
@@ -180,54 +169,69 @@
             }
         };
 
-        mPolicyDir = getContext().getFilesDir();
+        mPolicyDir = context.getFilesDir();
         if (mPolicyDir.exists()) {
             IoUtils.deleteContents(mPolicyDir);
         }
 
-        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);
+        doAnswer(new Answer<Void>() {
 
-        mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager,
-                mStatsService, mNetworkManager, mTime, mPolicyDir, true);
+            @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());
+
+        addLocalServiceMock(PowerManagerInternal.class);
+        addLocalServiceMock(DeviceIdleController.LocalService.class);
+        addLocalServiceMock(UsageStatsManagerInternal.class, mUsageStats);
+
+        mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mStatsService,
+                mNetworkManager, mTime, mPolicyDir, true);
         mService.bindConnectivityManager(mConnManager);
         mService.bindNotificationManager(mNotifManager);
+        mPolicyListener = new NetworkPolicyListenerAnswer(mService);
 
-        // RemoteCallbackList needs a binder to use as key
-        expect(mPolicyListener.asBinder()).andReturn(mStubBinder).atLeastOnce();
-        replay();
-        mService.registerListener(mPolicyListener);
-        verifyAndReset();
+        // Sets some common expectations.
+        when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenAnswer(
+                new Answer<PackageInfo>() {
 
-        // catch IProcessObserver during systemReady()
-        final Capture<IProcessObserver> processObserver = new Capture<IProcessObserver>();
-        mActivityManager.registerProcessObserver(capture(processObserver));
-        expectLastCall().atLeastOnce();
-
-        // catch INetworkManagementEventObserver during systemReady()
-        final Capture<INetworkManagementEventObserver> networkObserver = new Capture<
-                INetworkManagementEventObserver>();
-        mNetworkManager.registerObserver(capture(networkObserver));
-        expectLastCall().atLeastOnce();
-
-        expect(mNetworkManager.isBandwidthControlEnabled()).andReturn(true).atLeastOnce();
+                    @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(mUsageStats.getIdleUidsForUser(anyInt())).thenReturn(new int[]{});
+        when(mNetworkManager.isBandwidthControlEnabled()).thenReturn(true);
         expectCurrentTime();
 
-        replay();
+        // Prepare NPMS.
         mService.systemReady();
-        verifyAndReset();
 
-        mProcessObserver = processObserver.getValue();
+        // catch INetworkManagementEventObserver during systemReady()
+        ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
+              ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
+        verify(mNetworkManager).registerObserver(networkObserver.capture());
         mNetworkObserver = networkObserver.getValue();
-
     }
 
-    public void _tearDown() throws Exception {
+    public void tearDown() throws Exception {
         for (File file : mPolicyDir.listFiles()) {
             file.delete();
         }
@@ -237,170 +241,51 @@
 
         mActivityManager = null;
         mStatsService = null;
-        mPolicyListener = null;
         mTime = null;
 
         mService = null;
-        mProcessObserver = null;
+
+        // TODO: must remove services, otherwise next test will fail.
+        // JUnit4 would avoid that hack by using a static setup.
+        removeLocalServiceMocks();
+
+        // Added by NetworkPolicyManagerService's constructor.
+        LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
 
         super.tearDown();
     }
 
-    @Suppress
-    public void testPolicyChangeTriggersBroadcast() throws Exception {
+    // 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.
+
+    public void testPolicyChangeTriggersListener() throws Exception {
+        mPolicyListener.expect().onRestrictBackgroundBlacklistChanged(anyInt(), anyBoolean());
+
         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);
 
-        backgroundChanged.get();
+        mPolicyListener.waitAndVerify().onRestrictBackgroundBlacklistChanged(APP_ID_A, true);
     }
 
-    @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();
+    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);
         assertFalse(mService.isUidForeground(UID_A));
         assertFalse(mService.isUidForeground(UID_B));
 
-        // push one of the shared pids into foreground
-        idle = expectIdle();
-        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
-        idle.get();
+        // push one of the uids into foreground
+        mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_TOP);
         assertTrue(mService.isUidForeground(UID_A));
         assertFalse(mService.isUidForeground(UID_B));
 
         // and swap another uid into foreground
-        idle = expectIdle();
-        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
-        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, true);
-        idle.get();
+        mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE);
+        mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_TOP);
         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));
-    }
-
-    @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 {
@@ -545,11 +430,9 @@
         assertTimeEquals(expectedCycle, actualCycle);
     }
 
-    @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;
@@ -560,75 +443,39 @@
         // first, pretend that wifi network comes online. no policy active,
         // which means we shouldn't push limit to interface.
         state = new NetworkState[] { buildWifi() };
-        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+        when(mConnManager.getAllNetworkState()).thenReturn(state);
         expectCurrentTime();
-        expectClearNotifications();
-        expectAdvisePersistThreshold();
-        future = expectMeteredIfacesChanged();
 
-        replay();
+        mPolicyListener.expect().onMeteredIfacesChanged(any());
         mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
-        future.get();
-        verifyAndReset();
+        mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any());
 
         // now change cycle to be on 15th, and test in early march, to verify we
         // pick cycle day in previous month.
-        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+        when(mConnManager.getAllNetworkState()).thenReturn(state);
         expectCurrentTime();
 
         // pretend that 512 bytes total have happened
         stats = new NetworkStats(getElapsedRealtime(), 1)
                 .addIfaceValues(TEST_IFACE, 256L, 2L, 256L, 2L);
-        expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
-                .andReturn(stats.getTotalBytes()).atLeastOnce();
-        expectPolicyDataEnable(TYPE_WIFI, true);
+        when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
+                .thenReturn(stats.getTotalBytes());
 
-        // TODO: consider making strongly ordered mock
-        expectRemoveInterfaceQuota(TEST_IFACE);
-        expectSetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512);
-
-        expectClearNotifications();
-        expectAdvisePersistThreshold();
-        future = expectMeteredIfacesChanged(TEST_IFACE);
-
-        replay();
+        mPolicyListener.expect().onMeteredIfacesChanged(any());
         setNetworkPolicies(new NetworkPolicy(
                 sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
-        future.get();
-        verifyAndReset();
+        mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
+        // TODO: consider making strongly ordered mock
+        verifyPolicyDataEnable(TYPE_WIFI, true);
+        verifyRemoveInterfaceQuota(TEST_IFACE);
+        verifySetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512);
     }
 
-    @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<Void> future;
-        Future<String> tagFuture;
+        Future<String> tagFuture = null;
 
         final long TIME_FEB_15 = 1171497600000L;
         final long TIME_MAR_10 = 1173484800000L;
@@ -643,20 +490,15 @@
 
         {
             expectCurrentTime();
-            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
-            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
-                    .andReturn(stats.getTotalBytes()).atLeastOnce();
-            expectPolicyDataEnable(TYPE_WIFI, true);
+            when(mConnManager.getAllNetworkState()).thenReturn(state);
+            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
 
-            expectClearNotifications();
-            expectAdvisePersistThreshold();
-            future = expectMeteredIfacesChanged();
-
-            replay();
+            mPolicyListener.expect().onMeteredIfacesChanged(any());
             setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1
                     * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
-            future.get();
-            verifyAndReset();
+            mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any());
+            verifyPolicyDataEnable(TYPE_WIFI, true);
         }
 
         // bring up wifi network
@@ -667,22 +509,17 @@
 
         {
             expectCurrentTime();
-            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
-            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
-                    .andReturn(stats.getTotalBytes()).atLeastOnce();
-            expectPolicyDataEnable(TYPE_WIFI, true);
+            when(mConnManager.getAllNetworkState()).thenReturn(state);
+            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
 
-            expectRemoveInterfaceQuota(TEST_IFACE);
-            expectSetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
-
-            expectClearNotifications();
-            expectAdvisePersistThreshold();
-            future = expectMeteredIfacesChanged(TEST_IFACE);
-
-            replay();
+            mPolicyListener.expect().onMeteredIfacesChanged(any());
             mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
-            future.get();
-            verifyAndReset();
+            mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
+            verifyPolicyDataEnable(TYPE_WIFI, true);
+            verifyRemoveInterfaceQuota(TEST_IFACE);
+            verifySetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
         }
 
         // go over warning, which should kick notification
@@ -692,18 +529,15 @@
 
         {
             expectCurrentTime();
-            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
-                    .andReturn(stats.getTotalBytes()).atLeastOnce();
-            expectPolicyDataEnable(TYPE_WIFI, true);
-
-            expectForceUpdate();
-            expectClearNotifications();
+            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
             tagFuture = expectEnqueueNotification();
 
-            replay();
             mNetworkObserver.limitReached(null, TEST_IFACE);
+
             assertNotificationType(TYPE_WARNING, tagFuture.get());
-            verifyAndReset();
+            verifyPolicyDataEnable(TYPE_WIFI, true);
+
         }
 
         // go over limit, which should kick notification and dialog
@@ -713,18 +547,14 @@
 
         {
             expectCurrentTime();
-            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
-                    .andReturn(stats.getTotalBytes()).atLeastOnce();
-            expectPolicyDataEnable(TYPE_WIFI, false);
-
-            expectForceUpdate();
-            expectClearNotifications();
+            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
             tagFuture = expectEnqueueNotification();
 
-            replay();
             mNetworkObserver.limitReached(null, TEST_IFACE);
+
             assertNotificationType(TYPE_LIMIT, tagFuture.get());
-            verifyAndReset();
+            verifyPolicyDataEnable(TYPE_WIFI, false);
         }
 
         // now snooze policy, which should remove quota
@@ -732,35 +562,27 @@
 
         {
             expectCurrentTime();
-            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
-            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
-                    .andReturn(stats.getTotalBytes()).atLeastOnce();
-            expectPolicyDataEnable(TYPE_WIFI, true);
-
-            // snoozed interface still has high quota so background data is
-            // still restricted.
-            expectRemoveInterfaceQuota(TEST_IFACE);
-            expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
-            expectAdvisePersistThreshold();
-            expectMeteredIfacesChanged(TEST_IFACE);
-
-            future = expectClearNotifications();
+            when(mConnManager.getAllNetworkState()).thenReturn(state);
+            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
             tagFuture = expectEnqueueNotification();
 
-            replay();
+            mPolicyListener.expect().onMeteredIfacesChanged(any());
             mService.snoozeLimit(sTemplateWifi);
+            mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
             assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get());
-            future.get();
-            verifyAndReset();
+            // 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);
         }
     }
 
-    @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;
@@ -775,24 +597,19 @@
 
         {
             expectCurrentTime();
-            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
-            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
-                    .andReturn(stats.getTotalBytes()).atLeastOnce();
-            expectPolicyDataEnable(TYPE_WIFI, true);
+            when(mConnManager.getAllNetworkState()).thenReturn(state);
+            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
 
-            expectRemoveInterfaceQuota(TEST_IFACE);
-            expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
-
-            expectClearNotifications();
-            expectAdvisePersistThreshold();
-            future = expectMeteredIfacesChanged(TEST_IFACE);
-
-            replay();
+            mPolicyListener.expect().onMeteredIfacesChanged(any());
             setNetworkPolicies(new NetworkPolicy(
                     sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED,
                     true));
-            future.get();
-            verifyAndReset();
+            mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
+            verifyPolicyDataEnable(TYPE_WIFI, true);
+            verifyRemoveInterfaceQuota(TEST_IFACE);
+            verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
         }
     }
 
@@ -815,87 +632,36 @@
     }
 
     private void expectCurrentTime() throws Exception {
-        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;
+        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);
     }
 
     private Future<String> expectEnqueueNotification() throws Exception {
-        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;
+        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;
     }
 
-    private void expectSetInterfaceQuota(String iface, long quotaBytes) throws Exception {
-        mNetworkManager.setInterfaceQuota(iface, quotaBytes);
-        expectLastCall().atLeastOnce();
+    private void verifySetInterfaceQuota(String iface, long quotaBytes) throws Exception {
+        verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(iface, quotaBytes);
     }
 
-    private void expectRemoveInterfaceQuota(String iface) throws Exception {
-        mNetworkManager.removeInterfaceQuota(iface);
-        expectLastCall().atLeastOnce();
+    private void verifyRemoveInterfaceQuota(String iface) throws Exception {
+        verify(mNetworkManager, atLeastOnce()).removeInterfaceQuota(iface);
     }
 
-    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 {
+    private Future<Void> verifyPolicyDataEnable(int type, boolean enabled) throws Exception {
         // TODO: bring back this test
         return null;
     }
 
-    private void expectAdvisePersistThreshold() throws Exception {
-        mStatsService.advisePersistThreshold(anyLong());
-        expectLastCall().anyTimes();
+    private void verifyAdvisePersistThreshold() throws Exception {
+        verify(mStatsService).advisePersistThreshold(anyLong());
     }
 
     private static class TestAbstractFuture<T> extends AbstractFuture<T> {
@@ -909,50 +675,21 @@
         }
     }
 
-    private static class FutureAnswer extends TestAbstractFuture<Void> implements IAnswer<Void> {
+    private static class FutureAnswer<T> extends TestAbstractFuture<T> implements Answer<Void> {
+        private final int index;
+
+        FutureAnswer(int index) {
+            this.index = index;
+        }
         @Override
-        public Void answer() {
-            set(null);
+        public Void answer(InvocationOnMock invocation) throws Throwable {
+            @SuppressWarnings("unchecked")
+            T captured = (T) invocation.getArguments()[index];
+            set(captured);
             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));
@@ -980,7 +717,7 @@
     }
 
     private static void assertNotificationType(int expected, String actualTag) {
-        assertEquals(
+        assertEquals("notification type mismatch for '" + actualTag +"'",
                 Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
     }
 
@@ -1001,15 +738,78 @@
         mElapsedRealtime += duration;
     }
 
-    private void replay() {
-        EasyMock.replay(mActivityManager, mStatsService, mPolicyListener, mNetworkManager, mTime,
-                mConnManager, mNotifManager);
+    /**
+     * Creates a mock and registers it to {@link LocalServices}.
+     */
+    private <T> T addLocalServiceMock(Class<T> clazz) {
+        final T mock = mock(clazz);
+        return addLocalServiceMock(clazz, mock);
     }
 
-    private void verifyAndReset() {
-        EasyMock.verify(mActivityManager, mStatsService, mPolicyListener, mNetworkManager, mTime,
-                mConnManager, mNotifManager);
-        EasyMock.reset(mActivityManager, mStatsService, mPolicyListener, mNetworkManager, mTime,
-                mConnManager, mNotifManager);
+    /**
+     * Registers a mock to {@link LocalServices}.
+     */
+    private <T> T addLocalServiceMock(Class<T> clazz, T mock) {
+        LocalServices.addService(clazz, mock);
+        mLocalServices.add(clazz);
+        return mock;
+    }
+
+    /**
+     * Unregisters all mocks from {@link LocalServices}.
+     */
+    private void removeLocalServiceMocks() {
+        for (Class<?> clazz : mLocalServices) {
+            Log.d(TAG, "removeLocalServiceMock(): " + clazz.getName());
+            LocalServices.removeServiceForTest(clazz);
+        }
+        mLocalServices.clear();
+    }
+
+    /**
+     * 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());
+        }
     }
 }