OSDN Git Service

Polished rapid data usage alerting.
authorJeff Sharkey <jsharkey@android.com>
Sat, 3 Feb 2018 19:08:16 +0000 (12:08 -0700)
committerJeff Sharkey <jsharkey@android.com>
Sat, 3 Feb 2018 19:49:30 +0000 (12:49 -0700)
Switch to reading limit information from NetworkPolicy, which is
typically populated from SubscriptionPlan.  This lets users have
direct control over the limits we're using to trigger rapid usage
alerts, and makes the feature work without requiring that the carrier
wire up SubscriptionPlan information.

Let the user "snooze" the rapid usage alerting for a day at a time,
so we're less annoying to them.  Send the snooze broadcasts as
foreground, so that we don't re-post notifications while working
through a long background broadcast queue.

Fix notifications to use the "ALERTS" channel, since these alerts
really are higher priority than simple "STATUS" updates; this also
gives us HUN behavior when in full-screen apps.

Update both service and unit tests to work directly with
NotificationManager, instead of the raw AIDL.

Test: bit FrameworksServicesTests:com.android.server.NetworkPolicyManagerServiceTest
Bug: 7244463872436702
Change-Id: I8d9138522a7779cc68eb9fa4777b50facb6567b7

core/java/android/net/NetworkPolicy.java
core/res/AndroidManifest.xml
services/core/java/com/android/server/net/NetworkPolicyManagerService.java
services/java/com/android/server/SystemServer.java
services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java

index 5df742c..9f47f62 100644 (file)
@@ -42,6 +42,7 @@ import java.util.Objects;
 public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
     private static final int VERSION_INIT = 1;
     private static final int VERSION_RULE = 2;
+    private static final int VERSION_RAPID = 3;
 
     public static final int CYCLE_NONE = -1;
     public static final long WARNING_DISABLED = -1;
@@ -54,6 +55,7 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
     public long limitBytes = LIMIT_DISABLED;
     public long lastWarningSnooze = SNOOZE_NEVER;
     public long lastLimitSnooze = SNOOZE_NEVER;
+    public long lastRapidSnooze = SNOOZE_NEVER;
     @Deprecated public boolean metered = true;
     public boolean inferred = false;
 
@@ -82,15 +84,24 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
                 limitBytes, lastWarningSnooze, lastLimitSnooze, metered, inferred);
     }
 
+    @Deprecated
     public NetworkPolicy(NetworkTemplate template, RecurrenceRule cycleRule, long warningBytes,
             long limitBytes, long lastWarningSnooze, long lastLimitSnooze, boolean metered,
             boolean inferred) {
+        this(template, cycleRule, warningBytes, limitBytes, lastWarningSnooze, lastLimitSnooze,
+                SNOOZE_NEVER, metered, inferred);
+    }
+
+    public NetworkPolicy(NetworkTemplate template, RecurrenceRule cycleRule, long warningBytes,
+            long limitBytes, long lastWarningSnooze, long lastLimitSnooze, long lastRapidSnooze,
+            boolean metered, boolean inferred) {
         this.template = Preconditions.checkNotNull(template, "missing NetworkTemplate");
         this.cycleRule = Preconditions.checkNotNull(cycleRule, "missing RecurrenceRule");
         this.warningBytes = warningBytes;
         this.limitBytes = limitBytes;
         this.lastWarningSnooze = lastWarningSnooze;
         this.lastLimitSnooze = lastLimitSnooze;
+        this.lastRapidSnooze = lastRapidSnooze;
         this.metered = metered;
         this.inferred = inferred;
     }
@@ -102,6 +113,7 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
         limitBytes = source.readLong();
         lastWarningSnooze = source.readLong();
         lastLimitSnooze = source.readLong();
+        lastRapidSnooze = source.readLong();
         metered = source.readInt() != 0;
         inferred = source.readInt() != 0;
     }
@@ -114,6 +126,7 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
         dest.writeLong(limitBytes);
         dest.writeLong(lastWarningSnooze);
         dest.writeLong(lastLimitSnooze);
+        dest.writeLong(lastRapidSnooze);
         dest.writeInt(metered ? 1 : 0);
         dest.writeInt(inferred ? 1 : 0);
     }
@@ -151,6 +164,7 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
     public void clearSnooze() {
         lastWarningSnooze = SNOOZE_NEVER;
         lastLimitSnooze = SNOOZE_NEVER;
+        lastRapidSnooze = SNOOZE_NEVER;
     }
 
     /**
@@ -176,7 +190,7 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
     @Override
     public int hashCode() {
         return Objects.hash(template, cycleRule, warningBytes, limitBytes,
-                lastWarningSnooze, lastLimitSnooze, metered, inferred);
+                lastWarningSnooze, lastLimitSnooze, lastRapidSnooze, metered, inferred);
     }
 
     @Override
@@ -186,7 +200,9 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
             return warningBytes == other.warningBytes
                     && limitBytes == other.limitBytes
                     && lastWarningSnooze == other.lastWarningSnooze
-                    && lastLimitSnooze == other.lastLimitSnooze && metered == other.metered
+                    && lastLimitSnooze == other.lastLimitSnooze
+                    && lastRapidSnooze == other.lastRapidSnooze
+                    && metered == other.metered
                     && inferred == other.inferred
                     && Objects.equals(template, other.template)
                     && Objects.equals(cycleRule, other.cycleRule);
@@ -203,6 +219,7 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
                 .append(" limitBytes=").append(limitBytes)
                 .append(" lastWarningSnooze=").append(lastWarningSnooze)
                 .append(" lastLimitSnooze=").append(lastLimitSnooze)
+                .append(" lastRapidSnooze=").append(lastRapidSnooze)
                 .append(" metered=").append(metered)
                 .append(" inferred=").append(inferred)
                 .append("}").toString();
@@ -224,13 +241,14 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         DataOutputStream out = new DataOutputStream(baos);
 
-        out.writeInt(VERSION_RULE);
+        out.writeInt(VERSION_RAPID);
         out.write(template.getBytesForBackup());
         cycleRule.writeToStream(out);
         out.writeLong(warningBytes);
         out.writeLong(limitBytes);
         out.writeLong(lastWarningSnooze);
         out.writeLong(lastLimitSnooze);
+        out.writeLong(lastRapidSnooze);
         out.writeInt(metered ? 1 : 0);
         out.writeInt(inferred ? 1 : 0);
         return baos.toByteArray();
@@ -239,35 +257,32 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
     public static NetworkPolicy getNetworkPolicyFromBackup(DataInputStream in) throws IOException,
             BackupUtils.BadVersionException {
         final int version = in.readInt();
-        switch (version) {
-            case VERSION_INIT: {
-                NetworkTemplate template = NetworkTemplate.getNetworkTemplateFromBackup(in);
-                int cycleDay = in.readInt();
-                String cycleTimeZone = BackupUtils.readString(in);
-                long warningBytes = in.readLong();
-                long limitBytes = in.readLong();
-                long lastWarningSnooze = in.readLong();
-                long lastLimitSnooze = in.readLong();
-                boolean metered = in.readInt() == 1;
-                boolean inferred = in.readInt() == 1;
-                return new NetworkPolicy(template, cycleDay, cycleTimeZone, warningBytes,
-                        limitBytes, lastWarningSnooze, lastLimitSnooze, metered, inferred);
-            }
-            case VERSION_RULE: {
-                NetworkTemplate template = NetworkTemplate.getNetworkTemplateFromBackup(in);
-                RecurrenceRule cycleRule = new RecurrenceRule(in);
-                long warningBytes = in.readLong();
-                long limitBytes = in.readLong();
-                long lastWarningSnooze = in.readLong();
-                long lastLimitSnooze = in.readLong();
-                boolean metered = in.readInt() == 1;
-                boolean inferred = in.readInt() == 1;
-                return new NetworkPolicy(template, cycleRule, warningBytes,
-                        limitBytes, lastWarningSnooze, lastLimitSnooze, metered, inferred);
-            }
-            default: {
-                throw new BackupUtils.BadVersionException("Unknown backup version: " + version);
-            }
+        if (version > VERSION_RAPID) {
+            throw new BackupUtils.BadVersionException("Unknown backup version: " + version);
+        }
+
+        final NetworkTemplate template = NetworkTemplate.getNetworkTemplateFromBackup(in);
+        final RecurrenceRule cycleRule;
+        if (version >= VERSION_RULE) {
+            cycleRule = new RecurrenceRule(in);
+        } else {
+            final int cycleDay = in.readInt();
+            final String cycleTimezone = BackupUtils.readString(in);
+            cycleRule = buildRule(cycleDay, ZoneId.of(cycleTimezone));
+        }
+        final long warningBytes = in.readLong();
+        final long limitBytes = in.readLong();
+        final long lastWarningSnooze = in.readLong();
+        final long lastLimitSnooze = in.readLong();
+        final long lastRapidSnooze;
+        if (version >= VERSION_RAPID) {
+            lastRapidSnooze = in.readLong();
+        } else {
+            lastRapidSnooze = SNOOZE_NEVER;
         }
+        final boolean metered = in.readInt() == 1;
+        final boolean inferred = in.readInt() == 1;
+        return new NetworkPolicy(template, cycleRule, warningBytes, limitBytes, lastWarningSnooze,
+                lastLimitSnooze, lastRapidSnooze, metered, inferred);
     }
 }
index d58b95a..770385e 100644 (file)
     <protected-broadcast android:name="com.android.server.usb.ACTION_OPEN_IN_APPS" />
     <protected-broadcast android:name="com.android.server.am.DELETE_DUMPHEAP" />
     <protected-broadcast android:name="com.android.server.net.action.SNOOZE_WARNING" />
+    <protected-broadcast android:name="com.android.server.net.action.SNOOZE_RAPID" />
     <protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.USER_DISMISSED_NOTIFICATION" />
     <protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.CONNECT_TO_NETWORK" />
     <protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.PICK_WIFI_NETWORK" />
index f09de52..a6f049e 100644 (file)
@@ -106,9 +106,9 @@ import android.app.ActivityManagerInternal;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
-import android.app.INotificationManager;
 import android.app.IUidObserver;
 import android.app.Notification;
+import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.BroadcastReceiver;
@@ -175,6 +175,7 @@ import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionPlan;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+import android.text.format.DateUtils;
 import android.text.format.Formatter;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -208,10 +209,8 @@ import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
 import com.android.server.SystemConfig;
-import com.android.server.SystemService;
 
 import libcore.io.IoUtils;
-import libcore.util.EmptyArray;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlSerializer;
@@ -332,6 +331,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
             "com.android.server.net.action.ALLOW_BACKGROUND";
     private static final String ACTION_SNOOZE_WARNING =
             "com.android.server.net.action.SNOOZE_WARNING";
+    private static final String ACTION_SNOOZE_RAPID =
+            "com.android.server.net.action.SNOOZE_RAPID";
 
     private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
 
@@ -365,7 +366,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
     private final CarrierConfigManager mCarrierConfigManager;
 
     private IConnectivityManager mConnManager;
-    private INotificationManager mNotifManager;
     private PowerManagerInternal mPowerManagerInternal;
     private IDeviceIdleController mDeviceIdleController;
     @GuardedBy("mUidRulesFirstLock")
@@ -564,10 +564,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
         mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
     }
 
-    public void bindNotificationManager(INotificationManager notifManager) {
-        mNotifManager = checkNotNull(notifManager, "missing INotificationManager");
-    }
-
     void updatePowerSaveWhitelistUL() {
         try {
             int[] whitelist = mDeviceIdleController.getAppIdWhitelistExceptIdle();
@@ -772,10 +768,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
             final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND);
             mContext.registerReceiver(mAllowReceiver, allowFilter, MANAGE_NETWORK_POLICY, mHandler);
 
-            // listen for snooze warning from notifications
-            final IntentFilter snoozeWarningFilter = new IntentFilter(ACTION_SNOOZE_WARNING);
-            mContext.registerReceiver(mSnoozeWarningReceiver, snoozeWarningFilter,
-                    MANAGE_NETWORK_POLICY, mHandler);
+            // Listen for snooze from notifications
+            mContext.registerReceiver(mSnoozeReceiver,
+                    new IntentFilter(ACTION_SNOOZE_WARNING), MANAGE_NETWORK_POLICY, mHandler);
+            mContext.registerReceiver(mSnoozeReceiver,
+                    new IntentFilter(ACTION_SNOOZE_RAPID), MANAGE_NETWORK_POLICY, mHandler);
 
             // listen for configured wifi networks to be loaded
             final IntentFilter wifiFilter =
@@ -960,14 +957,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
      * Receiver that watches for {@link Notification} control of
      * {@link NetworkPolicy#lastWarningSnooze}.
      */
-    final private BroadcastReceiver mSnoozeWarningReceiver = new BroadcastReceiver() {
+    final private BroadcastReceiver mSnoozeReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             // on background handler thread, and verified MANAGE_NETWORK_POLICY
             // permission above.
 
             final NetworkTemplate template = intent.getParcelableExtra(EXTRA_NETWORK_TEMPLATE);
-            performSnooze(template, TYPE_WARNING);
+            if (ACTION_SNOOZE_WARNING.equals(intent.getAction())) {
+                performSnooze(template, TYPE_WARNING);
+            } else if (ACTION_SNOOZE_RAPID.equals(intent.getAction())) {
+                performSnooze(template, TYPE_RAPID);
+            }
         }
     };
 
@@ -1025,13 +1026,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
         }
     };
 
-    @VisibleForTesting
-    public void updateNotifications() {
-        synchronized (mNetworkPoliciesSecondLock) {
-            updateNotificationsNL();
-        }
-    }
-
     /**
      * Check {@link NetworkPolicy} against current {@link INetworkStatsService}
      * to show visible notifications as needed.
@@ -1047,6 +1041,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
         // cycle boundary to recompute notifications.
 
         // examine stats for each active policy
+        final long now = currentTimeMillis();
         for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
             final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
             // ignore policies that aren't relevant to user
@@ -1055,12 +1050,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
 
             final Pair<ZonedDateTime, ZonedDateTime> cycle = NetworkPolicyManager
                     .cycleIterator(policy).next();
-            final long start = cycle.first.toInstant().toEpochMilli();
-            final long end = cycle.second.toInstant().toEpochMilli();
-            final long totalBytes = getTotalBytes(policy.template, start, end);
+            final long cycleStart = cycle.first.toInstant().toEpochMilli();
+            final long cycleEnd = cycle.second.toInstant().toEpochMilli();
+            final long totalBytes = getTotalBytes(policy.template, cycleStart, cycleEnd);
 
+            // Notify when data usage is over warning/limit
             if (policy.isOverLimit(totalBytes)) {
-                if (policy.lastLimitSnooze >= start) {
+                final boolean snoozedThisCycle = policy.lastLimitSnooze >= cycleStart;
+                if (snoozedThisCycle) {
                     enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes);
                 } else {
                     enqueueNotification(policy, TYPE_LIMIT, totalBytes);
@@ -1070,45 +1067,30 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
             } else {
                 notifyUnderLimitNL(policy.template);
 
-                if (policy.isOverWarning(totalBytes) && policy.lastWarningSnooze < start) {
+                final boolean snoozedThisCycle = policy.lastWarningSnooze >= cycleStart;
+                if (policy.isOverWarning(totalBytes) && !snoozedThisCycle) {
                     enqueueNotification(policy, TYPE_WARNING, totalBytes);
                 }
             }
-        }
 
-        // Alert the user about heavy recent data usage that might result in
-        // going over their carrier limit.
-        for (int i = 0; i < mNetIdToSubId.size(); i++) {
-            final int subId = mNetIdToSubId.valueAt(i);
-            final SubscriptionPlan plan = getPrimarySubscriptionPlanLocked(subId);
-            if (plan == null) continue;
-
-            final long limitBytes = plan.getDataLimitBytes();
-            if (limitBytes == SubscriptionPlan.BYTES_UNKNOWN) {
-                // Ignore missing limits
-            } else if (limitBytes == SubscriptionPlan.BYTES_UNLIMITED) {
-                // Unlimited data; no rapid usage alerting
-            } else {
-                // Warn if average usage over last 4 days is on track to blow
-                // pretty far past the plan limits.
+            // Warn if average usage over last 4 days is on track to blow pretty
+            // far past the plan limits.
+            if (policy.limitBytes != LIMIT_DISABLED) {
                 final long recentDuration = TimeUnit.DAYS.toMillis(4);
-                final long end = RecurrenceRule.sClock.millis();
-                final long start = end - recentDuration;
+                final long recentBytes = getTotalBytes(policy.template, now - recentDuration, now);
 
-                final NetworkTemplate template = NetworkTemplate.buildTemplateMobileAll(
-                        mContext.getSystemService(TelephonyManager.class).getSubscriberId(subId));
-                final long recentBytes = getTotalBytes(template, start, end);
+                final long cycleDuration = cycleEnd - cycleStart;
+                final long projectedBytes = (recentBytes * cycleDuration) / recentDuration;
+                final long alertBytes = (policy.limitBytes * 3) / 2;
 
-                final Pair<ZonedDateTime, ZonedDateTime> cycle = plan.cycleIterator().next();
-                final long cycleDuration = cycle.second.toInstant().toEpochMilli()
-                        - cycle.first.toInstant().toEpochMilli();
+                if (LOGD) {
+                    Slog.d(TAG, "Rapid usage considering recent " + recentBytes + " projected "
+                            + projectedBytes + " alert " + alertBytes);
+                }
 
-                final long projectedBytes = (recentBytes * cycleDuration) / recentDuration;
-                final long alertBytes = (limitBytes * 3) / 2;
-                if (projectedBytes > alertBytes) {
-                    final NetworkPolicy policy = new NetworkPolicy(template, plan.getCycleRule(),
-                            NetworkPolicy.WARNING_DISABLED, NetworkPolicy.LIMIT_DISABLED,
-                            NetworkPolicy.SNOOZE_NEVER, NetworkPolicy.SNOOZE_NEVER, true, true);
+                final boolean snoozedRecently = policy.lastRapidSnooze >= now
+                        - DateUtils.DAY_IN_MILLIS;
+                if (projectedBytes > alertBytes && !snoozedRecently) {
                     enqueueNotification(policy, TYPE_RAPID, 0);
                 }
             }
@@ -1131,8 +1113,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
      */
     private boolean isTemplateRelevant(NetworkTemplate template) {
         if (template.isMatchRuleMobile()) {
-            final TelephonyManager tele = TelephonyManager.from(mContext);
-            final SubscriptionManager sub = SubscriptionManager.from(mContext);
+            final TelephonyManager tele = mContext.getSystemService(TelephonyManager.class);
+            final SubscriptionManager sub = mContext.getSystemService(SubscriptionManager.class);
 
             // Mobile template is relevant when any active subscriber matches
             final int[] subIds = ArrayUtils.defeatNullable(sub.getActiveSubscriptionIdList());
@@ -1173,7 +1155,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
     private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) {
         final NotificationId notificationId = new NotificationId(policy, type);
         final Notification.Builder builder =
-                new Notification.Builder(mContext, SystemNotificationChannels.NETWORK_STATUS);
+                new Notification.Builder(mContext, SystemNotificationChannels.NETWORK_ALERTS);
         builder.setOnlyAlertOnce(true);
         builder.setWhen(0L);
         builder.setColor(mContext.getColor(
@@ -1190,8 +1172,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                 builder.setTicker(title);
                 builder.setContentTitle(title);
                 builder.setContentText(body);
-                builder.setDefaults(Notification.DEFAULT_ALL);
-                builder.setChannelId(SystemNotificationChannels.NETWORK_ALERTS);
 
                 final Intent snoozeIntent = buildSnoozeWarningIntent(policy.template);
                 builder.setDeleteIntent(PendingIntent.getBroadcast(
@@ -1267,6 +1247,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                 builder.setTicker(title);
                 builder.setContentTitle(title);
                 builder.setContentText(body);
+                builder.setChannelId(SystemNotificationChannels.NETWORK_STATUS);
 
                 final Intent intent = buildViewDataUsageIntent(res, policy.template);
                 builder.setContentIntent(PendingIntent.getActivity(
@@ -1277,45 +1258,34 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                 final CharSequence title = res.getText(R.string.data_usage_rapid_title);
                 body = res.getText(R.string.data_usage_rapid_body);
 
-                builder.setOngoing(true);
                 builder.setSmallIcon(R.drawable.stat_notify_error);
                 builder.setTicker(title);
                 builder.setContentTitle(title);
                 builder.setContentText(body);
 
-                final Intent intent = buildViewDataUsageIntent(res, policy.template);
+                final Intent snoozeIntent = buildSnoozeRapidIntent(policy.template);
+                builder.setDeleteIntent(PendingIntent.getBroadcast(
+                        mContext, 0, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT));
+
+                final Intent viewIntent = buildViewDataUsageIntent(res, policy.template);
                 builder.setContentIntent(PendingIntent.getActivity(
-                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
+                        mContext, 0, viewIntent, PendingIntent.FLAG_UPDATE_CURRENT));
                 break;
             }
         }
 
-        // TODO: move to NotificationManager once we can mock it
-        try {
-            final String packageName = mContext.getPackageName();
-            if (!TextUtils.isEmpty(body)) {
-                builder.setStyle(new Notification.BigTextStyle()
-                        .bigText(body));
-            }
-            mNotifManager.enqueueNotificationWithTag(
-                    packageName, packageName, notificationId.getTag(), notificationId.getId(),
-                    builder.build(), UserHandle.USER_ALL);
-            mActiveNotifs.add(notificationId);
-        } catch (RemoteException e) {
-            // ignored; service lives in system_server
+        if (!TextUtils.isEmpty(body)) {
+            builder.setStyle(new Notification.BigTextStyle().bigText(body));
         }
+
+        mContext.getSystemService(NotificationManager.class).notifyAsUser(notificationId.getTag(),
+                notificationId.getId(), builder.build(), UserHandle.ALL);
+        mActiveNotifs.add(notificationId);
     }
 
     private void cancelNotification(NotificationId notificationId) {
-        // TODO: move to NotificationManager once we can mock it
-        try {
-            final String packageName = mContext.getPackageName();
-            mNotifManager.cancelNotificationWithTag(
-                    packageName, notificationId.getTag(), notificationId.getId(),
-                    UserHandle.USER_ALL);
-        } catch (RemoteException e) {
-            // ignored; service lives in system_server
-        }
+        mContext.getSystemService(NotificationManager.class).cancel(notificationId.getTag(),
+                notificationId.getId());
     }
 
     /**
@@ -1342,8 +1312,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
     };
 
     @VisibleForTesting
-    public void updateNetworks() {
+    public void updateNetworks() throws InterruptedException {
         mConnReceiver.onReceive(null, null);
+        final CountDownLatch latch = new CountDownLatch(1);
+        mHandler.post(() -> {
+            latch.countDown();
+        });
+        latch.await(5, TimeUnit.SECONDS);
     }
 
     /**
@@ -1357,7 +1332,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
         if (LOGV) Slog.v(TAG, "maybeUpdateMobilePolicyCycleAL()");
 
         boolean policyUpdated = false;
-        final String subscriberId = TelephonyManager.from(mContext).getSubscriberId(subId);
+        final String subscriberId = mContext.getSystemService(TelephonyManager.class)
+                .getSubscriberId(subId);
 
         // find and update the mobile NetworkPolicy for this subscriber id
         final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
@@ -1482,7 +1458,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                 return;
             }
             final int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, -1);
-            final TelephonyManager tele = TelephonyManager.from(mContext);
+            final TelephonyManager tele = mContext.getSystemService(TelephonyManager.class);
             final String subscriberId = tele.getSubscriberId(subId);
 
             maybeRefreshTrustedTime();
@@ -1561,8 +1537,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
         if (template.getMatchRule() == MATCH_MOBILE_ALL) {
             // If mobile data usage hits the limit or if the user resumes the data, we need to
             // notify telephony.
-            final SubscriptionManager sm = SubscriptionManager.from(mContext);
-            final TelephonyManager tm = TelephonyManager.from(mContext);
+            final SubscriptionManager sm = mContext.getSystemService(SubscriptionManager.class);
+            final TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
 
             final int[] subIds = ArrayUtils.defeatNullable(sm.getActiveSubscriptionIdList());
             for (int subId : subIds) {
@@ -1746,7 +1722,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                 final long totalBytes = getTotalBytes(
                         NetworkTemplate.buildTemplateMobileAll(state.subscriberId), start, end);
                 final long remainingBytes = limitBytes - totalBytes;
-                final long remainingDays = Math.min(1, (end - RecurrenceRule.sClock.millis())
+                final long remainingDays = Math.min(1, (end - currentTimeMillis())
                         / TimeUnit.DAYS.toMillis(1));
                 if (remainingBytes > 0) {
                     quotaBytes = (remainingBytes / remainingDays) / 10;
@@ -1770,8 +1746,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
         if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyAL()");
         if (mSuppressDefaultPolicy) return;
 
-        final TelephonyManager tele = TelephonyManager.from(mContext);
-        final SubscriptionManager sub = SubscriptionManager.from(mContext);
+        final TelephonyManager tele = mContext.getSystemService(TelephonyManager.class);
+        final SubscriptionManager sub = mContext.getSystemService(SubscriptionManager.class);
 
         final int[] subIds = ArrayUtils.defeatNullable(sub.getActiveSubscriptionIdList());
         for (int subId : subIds) {
@@ -2516,7 +2492,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
     }
 
     private void normalizePoliciesNL(NetworkPolicy[] policies) {
-        final TelephonyManager tele = TelephonyManager.from(mContext);
+        final TelephonyManager tele = mContext.getSystemService(TelephonyManager.class);
         final String[] merged = tele.getMergedSubscriberIds();
 
         mNetworkPolicy.clear();
@@ -2564,6 +2540,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                     case TYPE_LIMIT:
                         policy.lastLimitSnooze = currentTime;
                         break;
+                    case TYPE_RAPID:
+                        policy.lastRapidSnooze = currentTime;
+                        break;
                     default:
                         throw new IllegalArgumentException("unexpected type");
                 }
@@ -4425,6 +4404,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
 
     private static Intent buildSnoozeWarningIntent(NetworkTemplate template) {
         final Intent intent = new Intent(ACTION_SNOOZE_WARNING);
+        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
+        return intent;
+    }
+
+    private static Intent buildSnoozeRapidIntent(NetworkTemplate template) {
+        final Intent intent = new Intent(ACTION_SNOOZE_RAPID);
+        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
         intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
         return intent;
     }
index d5ed98e..3210f1a 100644 (file)
@@ -1193,7 +1193,6 @@ public final class SystemServer {
             SystemNotificationChannels.createAll(context);
             notification = INotificationManager.Stub.asInterface(
                     ServiceManager.getService(Context.NOTIFICATION_SERVICE));
-            networkPolicy.bindNotificationManager(notification);
             traceEnd();
 
             traceBeginAndSlog("StartDeviceMonitor");
index 045b73c..184e8de 100644 (file)
@@ -27,7 +27,6 @@ import static android.net.NetworkPolicyManager.POLICY_NONE;
 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
 import static android.net.NetworkPolicyManager.uidPoliciesToString;
 import static android.net.NetworkTemplate.buildTemplateMobileAll;
-import static android.net.TrafficStats.KB_IN_BYTES;
 import static android.net.TrafficStats.MB_IN_BYTES;
 import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
 import static android.telephony.CarrierConfigManager.DATA_CYCLE_THRESHOLD_DISABLED;
@@ -35,12 +34,12 @@ import static android.telephony.CarrierConfigManager.DATA_CYCLE_USE_PLATFORM_DEF
 import static android.telephony.CarrierConfigManager.KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG;
 import static android.telephony.CarrierConfigManager.KEY_DATA_WARNING_THRESHOLD_BYTES_LONG;
 import static android.telephony.CarrierConfigManager.KEY_MONTHLY_DATA_CYCLE_DAY_INT;
-import static android.telephony.SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED;
-import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import static android.telephony.SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED;
 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_RAPID;
 import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -72,9 +71,9 @@ import android.Manifest;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.IActivityManager;
-import android.app.INotificationManager;
 import android.app.IUidObserver;
 import android.app.Notification;
+import android.app.NotificationManager;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.Context;
 import android.content.Intent;
@@ -107,12 +106,12 @@ import android.os.PowerSaveState;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionPlan;
 import android.telephony.TelephonyManager;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.text.TextUtils;
 import android.text.format.Time;
 import android.util.DataUnit;
@@ -193,6 +192,8 @@ public class NetworkPolicyManagerServiceTest {
     private static final String TEST_IFACE = "test0";
     private static final String TEST_SSID = "AndroidAP";
     private static final String TEST_IMSI = "310210";
+    private static final int TEST_SUB_ID = 42;
+    private static final int TEST_NET_ID = 24;
 
     private static NetworkTemplate sTemplateWifi = NetworkTemplate.buildTemplateWifi(TEST_SSID);
 
@@ -216,7 +217,7 @@ public class NetworkPolicyManagerServiceTest {
     private @Mock INetworkManagementService mNetworkManager;
     private @Mock TrustedTime mTime;
     private @Mock IConnectivityManager mConnManager;
-    private @Mock INotificationManager mNotifManager;
+    private @Mock NotificationManager mNotifManager;
     private @Mock PackageManager mPackageManager;
     private @Mock IPackageManager mIpm;
     private @Mock SubscriptionManager mSubscriptionManager;
@@ -312,6 +313,8 @@ public class NetworkPolicyManagerServiceTest {
                         return mCarrierConfigManager;
                     case Context.TELEPHONY_SERVICE:
                         return mTelephonyManager;
+                    case Context.NOTIFICATION_SERVICE:
+                        return mNotifManager;
                     default:
                         return super.getSystemService(name);
                 }
@@ -340,7 +343,6 @@ public class NetworkPolicyManagerServiceTest {
         mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mStatsService,
                 mNetworkManager, mIpm, mTime, mPolicyDir, true);
         mService.bindConnectivityManager(mConnManager);
-        mService.bindNotificationManager(mNotifManager);
         mPolicyListener = new NetworkPolicyListenerAnswer(mService);
 
         // Sets some common expectations.
@@ -960,124 +962,112 @@ public class NetworkPolicyManagerServiceTest {
                 sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
         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);
+        verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(TEST_IFACE,
+                (2 * MB_IN_BYTES) - 512);
     }
 
     @Test
-    public void testOverWarningLimitNotification() throws Exception {
-        NetworkState[] state = null;
-        NetworkStats stats = null;
-        Future<String> tagFuture = null;
+    public void testNotificationWarningLimitSnooze() throws Exception {
+        // Create a place to store fake usage
+        final NetworkStatsHistory history = new NetworkStatsHistory(TimeUnit.HOURS.toMillis(1));
+        when(mStatsService.getNetworkTotalBytes(any(), anyLong(), anyLong()))
+                .thenAnswer(new Answer<Long>() {
+                    @Override
+                    public Long answer(InvocationOnMock invocation) throws Throwable {
+                        final NetworkStatsHistory.Entry entry = history.getValues(
+                                invocation.getArgument(1), invocation.getArgument(2), null);
+                        return entry.rxBytes + entry.txBytes;
+                    }
+                });
 
-        final int CYCLE_DAY = 15;
-        final long NOW = parseTime("2007-03-10T00:00Z");
-        final long CYCLE_START = parseTime("2007-02-15T00:00Z");
-        final long CYCLE_END = parseTime("2007-03-15T00:00Z");
+        // Get active mobile network in place
+        expectMobileDefaults();
+        mService.updateNetworks();
 
-        setCurrentTimeMillis(NOW);
+        // Define simple data plan
+        final SubscriptionPlan plan = SubscriptionPlan.Builder
+                .createRecurringMonthly(ZonedDateTime.parse("2015-11-01T00:00:00.00Z"))
+                .setDataLimit(DataUnit.MEGABYTES.toBytes(1800), LIMIT_BEHAVIOR_DISABLED)
+                .build();
+        mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[] { plan },
+                mServiceContext.getOpPackageName());
 
-        // assign wifi policy
-        state = new NetworkState[] {};
-        stats = new NetworkStats(getElapsedRealtime(), 1)
-                .addIfaceValues(TEST_IFACE, 0L, 0L, 0L, 0L);
+        // We're 20% through the month (6 days)
+        final long start = parseTime("2015-11-01T00:00Z");
+        final long end = parseTime("2015-11-07T00:00Z");
+        setCurrentTimeMillis(end);
+        expectCurrentTime();
 
+        // Normal usage means no notification
         {
-            expectCurrentTime();
-            when(mConnManager.getAllNetworkState()).thenReturn(state);
-            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, CYCLE_START,
-                    CYCLE_END)).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(any());
-            verifyPolicyDataEnable(TYPE_WIFI, true);
-        }
-
-        // bring up wifi network
-        incrementCurrentTime(MINUTE_IN_MILLIS);
-        state = new NetworkState[] { buildWifi() };
-        stats = new NetworkStats(getElapsedRealtime(), 1)
-                .addIfaceValues(TEST_IFACE, 0L, 0L, 0L, 0L);
+            history.removeBucketsBefore(Long.MAX_VALUE);
+            history.recordData(start, end,
+                    new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(360), 0L, 0L, 0L, 0));
 
-        {
-            expectCurrentTime();
-            when(mConnManager.getAllNetworkState()).thenReturn(state);
-            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, CYCLE_START,
-                    CYCLE_END)).thenReturn(stats.getTotalBytes());
+            reset(mTelephonyManager, mNetworkManager, mNotifManager);
+            expectMobileDefaults();
 
-            mPolicyListener.expect().onMeteredIfacesChanged(any());
-            mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
-            mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+            mService.updateNetworks();
 
-            verifyPolicyDataEnable(TYPE_WIFI, true);
-            verifyRemoveInterfaceQuota(TEST_IFACE);
-            verifySetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
+            verify(mTelephonyManager, atLeastOnce()).setPolicyDataEnabled(true, TEST_SUB_ID);
+            verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(TEST_IFACE,
+                    DataUnit.MEGABYTES.toBytes(1800 - 360));
+            verify(mNotifManager, never()).notifyAsUser(any(), anyInt(), any(), any());
         }
 
-        // go over warning, which should kick notification
-        incrementCurrentTime(MINUTE_IN_MILLIS);
-        stats = new NetworkStats(getElapsedRealtime(), 1)
-                .addIfaceValues(TEST_IFACE, 1536 * KB_IN_BYTES, 15L, 0L, 0L);
-
+        // Push over warning
         {
-            expectCurrentTime();
-            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, CYCLE_START,
-                    CYCLE_END)).thenReturn(stats.getTotalBytes());
-            tagFuture = expectEnqueueNotification();
+            history.removeBucketsBefore(Long.MAX_VALUE);
+            history.recordData(start, end,
+                    new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(1799), 0L, 0L, 0L, 0));
 
-            mNetworkObserver.limitReached(null, TEST_IFACE);
+            reset(mTelephonyManager, mNetworkManager, mNotifManager);
+            expectMobileDefaults();
 
-            assertNotificationType(TYPE_WARNING, tagFuture.get());
-            verifyPolicyDataEnable(TYPE_WIFI, true);
+            mService.updateNetworks();
 
+            verify(mTelephonyManager, atLeastOnce()).setPolicyDataEnabled(true, TEST_SUB_ID);
+            verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(TEST_IFACE,
+                    DataUnit.MEGABYTES.toBytes(1800 - 1799));
+            verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_WARNING),
+                    isA(Notification.class), eq(UserHandle.ALL));
         }
 
-        // go over limit, which should kick notification and dialog
-        incrementCurrentTime(MINUTE_IN_MILLIS);
-        stats = new NetworkStats(getElapsedRealtime(), 1)
-                .addIfaceValues(TEST_IFACE, 5 * MB_IN_BYTES, 512L, 0L, 0L);
-
+        // Push over limit
         {
-            expectCurrentTime();
-            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, CYCLE_START,
-                    CYCLE_END)).thenReturn(stats.getTotalBytes());
-            tagFuture = expectEnqueueNotification();
+            history.removeBucketsBefore(Long.MAX_VALUE);
+            history.recordData(start, end,
+                    new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(1810), 0L, 0L, 0L, 0));
 
-            mNetworkObserver.limitReached(null, TEST_IFACE);
+            reset(mTelephonyManager, mNetworkManager, mNotifManager);
+            expectMobileDefaults();
 
-            assertNotificationType(TYPE_LIMIT, tagFuture.get());
-            verifyPolicyDataEnable(TYPE_WIFI, false);
-        }
+            mService.updateNetworks();
 
-        // now snooze policy, which should remove quota
-        incrementCurrentTime(MINUTE_IN_MILLIS);
+            verify(mTelephonyManager, atLeastOnce()).setPolicyDataEnabled(false, TEST_SUB_ID);
+            verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(TEST_IFACE, 1);
+            verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT),
+                    isA(Notification.class), eq(UserHandle.ALL));
+        }
 
+        // Snooze limit
         {
-            expectCurrentTime();
-            when(mConnManager.getAllNetworkState()).thenReturn(state);
-            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, CYCLE_START,
-                    CYCLE_END)).thenReturn(stats.getTotalBytes());
-            tagFuture = expectEnqueueNotification();
+            reset(mTelephonyManager, mNetworkManager, mNotifManager);
+            expectMobileDefaults();
 
-            mPolicyListener.expect().onMeteredIfacesChanged(any());
-            mService.snoozeLimit(sTemplateWifi);
-            mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+            mService.snoozeLimit(NetworkTemplate.buildTemplateMobileAll(TEST_IMSI));
+            mService.updateNetworks();
 
-            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);
+            verify(mTelephonyManager, atLeastOnce()).setPolicyDataEnabled(true, TEST_SUB_ID);
+            verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(TEST_IFACE,
+                    Long.MAX_VALUE);
+            verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED),
+                    isA(Notification.class), eq(UserHandle.ALL));
         }
     }
 
     @Test
-    public void testRapidNotification() throws Exception {
+    public void testNotificationRapid() throws Exception {
         // Create a place to store fake usage
         final NetworkStatsHistory history = new NetworkStatsHistory(TimeUnit.HOURS.toMillis(1));
         when(mStatsService.getNetworkTotalBytes(any(), anyLong(), anyLong()))
@@ -1090,38 +1080,33 @@ public class NetworkPolicyManagerServiceTest {
                     }
                 });
 
+        // Get active mobile network in place
+        expectMobileDefaults();
+        mService.updateNetworks();
+
         // Define simple data plan which gives us effectively 60MB/day
         final SubscriptionPlan plan = SubscriptionPlan.Builder
                 .createRecurringMonthly(ZonedDateTime.parse("2015-11-01T00:00:00.00Z"))
-                .setDataLimit(DataUnit.MEGABYTES.toBytes(1800), LIMIT_BEHAVIOR_THROTTLED)
+                .setDataLimit(DataUnit.MEGABYTES.toBytes(1800), LIMIT_BEHAVIOR_DISABLED)
                 .build();
-        mService.setSubscriptionPlans(42, new SubscriptionPlan[] { plan },
+        mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[] { plan },
                 mServiceContext.getOpPackageName());
 
-        // And get that active network in place
-        when(mConnManager.getAllNetworkState()).thenReturn(new NetworkState[] {
-                new NetworkState(null, new LinkProperties(),
-                        new NetworkCapabilities().addTransportType(TRANSPORT_CELLULAR)
-                                .setNetworkSpecifier(new StringNetworkSpecifier("42")),
-                        new Network(42), TEST_IMSI, null)
-        });
-        mService.updateNetworks();
-
         // We're 20% through the month (6 days)
         final long start = parseTime("2015-11-01T00:00Z");
         final long end = parseTime("2015-11-07T00:00Z");
         setCurrentTimeMillis(end);
+        expectCurrentTime();
 
-        // Using 20% of data in 20% is normal
+        // Using 20% data in 20% time is normal
         {
             history.removeBucketsBefore(Long.MAX_VALUE);
             history.recordData(start, end,
                     new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(360), 0L, 0L, 0L, 0));
 
             reset(mNotifManager);
-            mService.updateNotifications();
-            verify(mNotifManager, never()).enqueueNotificationWithTag(any(), any(), any(),
-                    anyInt(), any(), anyInt());
+            mService.updateNetworks();
+            verify(mNotifManager, never()).notifyAsUser(any(), anyInt(), any(), any());
         }
 
         // Using 80% data in 20% time is alarming
@@ -1131,9 +1116,9 @@ public class NetworkPolicyManagerServiceTest {
                     new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(1440), 0L, 0L, 0L, 0));
 
             reset(mNotifManager);
-            mService.updateNotifications();
-            verify(mNotifManager, atLeastOnce()).enqueueNotificationWithTag(any(), any(), any(),
-                    anyInt(), any(), anyInt());
+            mService.updateNetworks();
+            verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_RAPID),
+                    isA(Notification.class), eq(UserHandle.ALL));
         }
     }
 
@@ -1165,9 +1150,8 @@ public class NetworkPolicyManagerServiceTest {
                     true));
             mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
 
-            verifyPolicyDataEnable(TYPE_WIFI, true);
-            verifyRemoveInterfaceQuota(TEST_IFACE);
-            verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
+            verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(TEST_IFACE,
+                    Long.MAX_VALUE);
         }
     }
 
@@ -1426,6 +1410,26 @@ public class NetworkPolicyManagerServiceTest {
                 true);
     }
 
+    private NetworkInfo buildNetworkInfo() {
+        final NetworkInfo ni = new NetworkInfo(ConnectivityManager.TYPE_MOBILE,
+                TelephonyManager.NETWORK_TYPE_LTE, null, null);
+        ni.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
+        return ni;
+    }
+
+    private LinkProperties buildLinkProperties(String iface) {
+        final LinkProperties lp = new LinkProperties();
+        lp.setInterfaceName(iface);
+        return lp;
+    }
+
+    private NetworkCapabilities buildNetworkCapabilities(int subId) {
+        final NetworkCapabilities nc = new NetworkCapabilities();
+        nc.addTransportType(TRANSPORT_CELLULAR);
+        nc.setNetworkSpecifier(new StringNetworkSpecifier(String.valueOf(subId)));
+        return nc;
+    }
+
     private NetworkPolicy buildDefaultFakeMobilePolicy() {
         NetworkPolicy p = mService.buildDefaultMobilePolicy(FAKE_SUB_ID, FAKE_SUBSCRIBER_ID);
         // set a deterministic cycle date
@@ -1478,30 +1482,21 @@ public class NetworkPolicyManagerServiceTest {
         when(mTime.getCacheCertainty()).thenReturn(0L);
     }
 
-    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), anyInt());
-        return futureAnswer;
-    }
-
     private void expectHasInternetPermission(int uid, boolean hasIt) throws Exception {
         when(mIpm.checkUidPermission(Manifest.permission.INTERNET, uid)).thenReturn(
                 hasIt ? PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED);
     }
 
-    private void verifySetInterfaceQuota(String iface, long quotaBytes) throws Exception {
-        verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(iface, quotaBytes);
-    }
-
-    private void verifyRemoveInterfaceQuota(String iface) throws Exception {
-        verify(mNetworkManager, atLeastOnce()).removeInterfaceQuota(iface);
-    }
-
-    private Future<Void> verifyPolicyDataEnable(int type, boolean enabled) throws Exception {
-        // TODO: bring back this test
-        return null;
+    private void expectMobileDefaults() throws Exception {
+        when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(
+                new int[] { TEST_SUB_ID });
+        when(mTelephonyManager.getSubscriberId(TEST_SUB_ID)).thenReturn(TEST_IMSI);
+        when(mConnManager.getAllNetworkState()).thenReturn(new NetworkState[] {
+                new NetworkState(buildNetworkInfo(),
+                        buildLinkProperties(TEST_IFACE),
+                        buildNetworkCapabilities(TEST_SUB_ID),
+                        new Network(TEST_NET_ID), TEST_IMSI, null)
+        });
     }
 
     private void verifyAdvisePersistThreshold() throws Exception {
@@ -1519,21 +1514,6 @@ public class NetworkPolicyManagerServiceTest {
         }
     }
 
-    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(InvocationOnMock invocation) throws Throwable {
-            @SuppressWarnings("unchecked")
-            T captured = (T) invocation.getArguments()[index];
-            set(captured);
-            return null;
-        }
-    }
-
     private static void assertTimeEquals(long expected, long actual) {
         if (expected != actual) {
             fail("expected " + formatTime(expected) + " but was actually " + formatTime(actual));