diff options
5 files changed, 259 insertions, 277 deletions
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java index 5df742c5a394..9f47f62775e1 100644 --- a/core/java/android/net/NetworkPolicy.java +++ b/core/java/android/net/NetworkPolicy.java @@ -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); } } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index d58b95a6697c..770385e04d2b 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -323,6 +323,7 @@ <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" /> diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index f09de5222715..a6f049e1d8d0 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -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; } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index d5ed98e373bc..3210f1a2e8b9 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -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"); diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java index 045b73c59345..184e8de15973 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java @@ -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)); |