Merge "APIs to disable data usage notifications." into pi-dev
am: f0b9fbebc0
Change-Id: I7b5bd380f00b6e94da79f43b354ecfc52df3f8e4
This commit is contained in:
@@ -27213,6 +27213,7 @@ package android.net {
|
||||
field public static final int NET_CAPABILITY_IMS = 4; // 0x4
|
||||
field public static final int NET_CAPABILITY_INTERNET = 12; // 0xc
|
||||
field public static final int NET_CAPABILITY_MMS = 0; // 0x0
|
||||
field public static final int NET_CAPABILITY_NOT_CONGESTED = 20; // 0x14
|
||||
field public static final int NET_CAPABILITY_NOT_METERED = 11; // 0xb
|
||||
field public static final int NET_CAPABILITY_NOT_RESTRICTED = 13; // 0xd
|
||||
field public static final int NET_CAPABILITY_NOT_ROAMING = 18; // 0x12
|
||||
@@ -41693,7 +41694,10 @@ package android.telephony {
|
||||
field public static final java.lang.String KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING = "config_plans_package_override_string";
|
||||
field public static final java.lang.String KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL = "config_telephony_use_own_number_for_voicemail_bool";
|
||||
field public static final java.lang.String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
|
||||
field public static final java.lang.String KEY_DATA_LIMIT_NOTIFICATION_BOOL = "data_limit_notification_bool";
|
||||
field public static final java.lang.String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG = "data_limit_threshold_bytes_long";
|
||||
field public static final java.lang.String KEY_DATA_RAPID_NOTIFICATION_BOOL = "data_rapid_notification_bool";
|
||||
field public static final java.lang.String KEY_DATA_WARNING_NOTIFICATION_BOOL = "data_warning_notification_bool";
|
||||
field public static final java.lang.String KEY_DATA_WARNING_THRESHOLD_BYTES_LONG = "data_warning_threshold_bytes_long";
|
||||
field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
|
||||
field public static final java.lang.String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
|
||||
|
||||
@@ -254,9 +254,8 @@ public final class NetworkCapabilities implements Parcelable {
|
||||
/**
|
||||
* Indicates that this network is not congested.
|
||||
* <p>
|
||||
* When a network is congested, the device should defer network traffic that
|
||||
* can be done at a later time without breaking developer contracts.
|
||||
* @hide
|
||||
* When a network is congested, applications should defer network traffic
|
||||
* that can be done at a later time, such as uploading analytics.
|
||||
*/
|
||||
public static final int NET_CAPABILITY_NOT_CONGESTED = 20;
|
||||
|
||||
|
||||
@@ -149,6 +149,10 @@ public class RecurrenceRule implements Parcelable {
|
||||
}
|
||||
};
|
||||
|
||||
public boolean isRecurring() {
|
||||
return period != null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean isMonthly() {
|
||||
return start != null
|
||||
|
||||
@@ -80,6 +80,9 @@ import static android.provider.Settings.Global.NETPOLICY_QUOTA_UNLIMITED;
|
||||
import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
|
||||
import static android.telephony.CarrierConfigManager.DATA_CYCLE_THRESHOLD_DISABLED;
|
||||
import static android.telephony.CarrierConfigManager.DATA_CYCLE_USE_PLATFORM_DEFAULT;
|
||||
import static android.telephony.CarrierConfigManager.KEY_DATA_LIMIT_NOTIFICATION_BOOL;
|
||||
import static android.telephony.CarrierConfigManager.KEY_DATA_RAPID_NOTIFICATION_BOOL;
|
||||
import static android.telephony.CarrierConfigManager.KEY_DATA_WARNING_NOTIFICATION_BOOL;
|
||||
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||
|
||||
import static com.android.internal.util.ArrayUtils.appendInt;
|
||||
@@ -1093,8 +1096,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
final long now = mClock.millis();
|
||||
for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
|
||||
final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
|
||||
final int subId = findRelevantSubId(policy.template);
|
||||
|
||||
// ignore policies that aren't relevant to user
|
||||
if (!isTemplateRelevant(policy.template)) continue;
|
||||
if (subId == INVALID_SUBSCRIPTION_ID) continue;
|
||||
if (!policy.hasCycle()) continue;
|
||||
|
||||
final Pair<ZonedDateTime, ZonedDateTime> cycle = NetworkPolicyManager
|
||||
@@ -1103,28 +1108,43 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
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)) {
|
||||
final boolean snoozedThisCycle = policy.lastLimitSnooze >= cycleStart;
|
||||
if (snoozedThisCycle) {
|
||||
enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes, null);
|
||||
} else {
|
||||
enqueueNotification(policy, TYPE_LIMIT, totalBytes, null);
|
||||
notifyOverLimitNL(policy.template);
|
||||
// Carrier might want to manage notifications themselves
|
||||
final PersistableBundle config = mCarrierConfigManager.getConfigForSubId(subId);
|
||||
final boolean notifyWarning = getBooleanDefeatingNullable(config,
|
||||
KEY_DATA_WARNING_NOTIFICATION_BOOL, true);
|
||||
final boolean notifyLimit = getBooleanDefeatingNullable(config,
|
||||
KEY_DATA_LIMIT_NOTIFICATION_BOOL, true);
|
||||
final boolean notifyRapid = getBooleanDefeatingNullable(config,
|
||||
KEY_DATA_RAPID_NOTIFICATION_BOOL, true);
|
||||
|
||||
// Notify when data usage is over warning
|
||||
if (notifyWarning) {
|
||||
if (policy.isOverWarning(totalBytes) && !policy.isOverLimit(totalBytes)) {
|
||||
final boolean snoozedThisCycle = policy.lastWarningSnooze >= cycleStart;
|
||||
if (!snoozedThisCycle) {
|
||||
enqueueNotification(policy, TYPE_WARNING, totalBytes, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
notifyUnderLimitNL(policy.template);
|
||||
|
||||
final boolean snoozedThisCycle = policy.lastWarningSnooze >= cycleStart;
|
||||
if (policy.isOverWarning(totalBytes) && !snoozedThisCycle) {
|
||||
enqueueNotification(policy, TYPE_WARNING, totalBytes, null);
|
||||
// Notify when data usage is over limit
|
||||
if (notifyLimit) {
|
||||
if (policy.isOverLimit(totalBytes)) {
|
||||
final boolean snoozedThisCycle = policy.lastLimitSnooze >= cycleStart;
|
||||
if (snoozedThisCycle) {
|
||||
enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes, null);
|
||||
} else {
|
||||
enqueueNotification(policy, TYPE_LIMIT, totalBytes, null);
|
||||
notifyOverLimitNL(policy.template);
|
||||
}
|
||||
} else {
|
||||
notifyUnderLimitNL(policy.template);
|
||||
}
|
||||
}
|
||||
|
||||
// Warn if average usage over last 4 days is on track to blow pretty
|
||||
// far past the plan limits.
|
||||
if (policy.limitBytes != LIMIT_DISABLED) {
|
||||
if (notifyRapid && policy.limitBytes != LIMIT_DISABLED) {
|
||||
final long recentDuration = TimeUnit.DAYS.toMillis(4);
|
||||
final long recentStart = now - recentDuration;
|
||||
final long recentEnd = now;
|
||||
@@ -1201,27 +1221,26 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
* current device state, such as when
|
||||
* {@link TelephonyManager#getSubscriberId()} matches. This is regardless of
|
||||
* data connection status.
|
||||
*
|
||||
* @return relevant subId, or {@link #INVALID_SUBSCRIPTION_ID} when no
|
||||
* matching subId found.
|
||||
*/
|
||||
private boolean isTemplateRelevant(NetworkTemplate template) {
|
||||
if (template.isMatchRuleMobile()) {
|
||||
final TelephonyManager tele = mContext.getSystemService(TelephonyManager.class);
|
||||
final SubscriptionManager sub = mContext.getSystemService(SubscriptionManager.class);
|
||||
private int findRelevantSubId(NetworkTemplate template) {
|
||||
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());
|
||||
for (int subId : subIds) {
|
||||
final String subscriberId = tele.getSubscriberId(subId);
|
||||
final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
|
||||
TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true,
|
||||
true);
|
||||
if (template.matches(probeIdent)) {
|
||||
return true;
|
||||
}
|
||||
// Mobile template is relevant when any active subscriber matches
|
||||
final int[] subIds = ArrayUtils.defeatNullable(sub.getActiveSubscriptionIdList());
|
||||
for (int subId : subIds) {
|
||||
final String subscriberId = tele.getSubscriberId(subId);
|
||||
final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
|
||||
TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true,
|
||||
true);
|
||||
if (template.matches(probeIdent)) {
|
||||
return subId;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return INVALID_SUBSCRIPTION_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3086,9 +3105,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
|
||||
// We can only override when carrier told us about plans
|
||||
synchronized (mNetworkPoliciesSecondLock) {
|
||||
if (ArrayUtils.isEmpty(mSubscriptionPlans.get(subId))) {
|
||||
final SubscriptionPlan plan = getPrimarySubscriptionPlanLocked(subId);
|
||||
if (plan == null
|
||||
|| plan.getDataLimitBehavior() == SubscriptionPlan.LIMIT_BEHAVIOR_UNKNOWN) {
|
||||
throw new IllegalStateException(
|
||||
"Must provide SubscriptionPlan information before overriding");
|
||||
"Must provide valid SubscriptionPlan to enable overriding");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4831,7 +4852,21 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
@GuardedBy("mNetworkPoliciesSecondLock")
|
||||
private SubscriptionPlan getPrimarySubscriptionPlanLocked(int subId) {
|
||||
final SubscriptionPlan[] plans = mSubscriptionPlans.get(subId);
|
||||
return ArrayUtils.isEmpty(plans) ? null : plans[0];
|
||||
if (!ArrayUtils.isEmpty(plans)) {
|
||||
for (SubscriptionPlan plan : plans) {
|
||||
if (plan.getCycleRule().isRecurring()) {
|
||||
// Recurring plans will always have an active cycle
|
||||
return plan;
|
||||
} else {
|
||||
// Non-recurring plans need manual test for active cycle
|
||||
final Range<ZonedDateTime> cycle = plan.cycleIterator().next();
|
||||
if (cycle.contains(ZonedDateTime.now(mClock))) {
|
||||
return plan;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4878,6 +4913,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
return (val != null) ? val : new NetworkState[0];
|
||||
}
|
||||
|
||||
private static boolean getBooleanDefeatingNullable(@Nullable PersistableBundle bundle,
|
||||
String key, boolean defaultValue) {
|
||||
return (bundle != null) ? bundle.getBoolean(key, defaultValue) : defaultValue;
|
||||
}
|
||||
|
||||
private class NotificationId {
|
||||
private final String mTag;
|
||||
private final int mId;
|
||||
|
||||
@@ -1714,6 +1714,8 @@ public class NetworkPolicyManagerServiceTest {
|
||||
}
|
||||
|
||||
private void expectNetworkState(boolean roaming) throws Exception {
|
||||
when(mCarrierConfigManager.getConfigForSubId(eq(TEST_SUB_ID)))
|
||||
.thenReturn(CarrierConfigManager.getDefaultConfig());
|
||||
when(mConnManager.getAllNetworkState()).thenReturn(new NetworkState[] {
|
||||
new NetworkState(buildNetworkInfo(),
|
||||
buildLinkProperties(TEST_IFACE),
|
||||
|
||||
@@ -1683,6 +1683,14 @@ public class CarrierConfigManager {
|
||||
public static final String KEY_DATA_WARNING_THRESHOLD_BYTES_LONG =
|
||||
"data_warning_threshold_bytes_long";
|
||||
|
||||
/**
|
||||
* Controls if the device should automatically notify the user as they reach
|
||||
* their cellular data warning. When set to {@code false} the carrier is
|
||||
* expected to have implemented their own notification mechanism.
|
||||
*/
|
||||
public static final String KEY_DATA_WARNING_NOTIFICATION_BOOL =
|
||||
"data_warning_notification_bool";
|
||||
|
||||
/**
|
||||
* Controls the cellular data limit.
|
||||
* <p>
|
||||
@@ -1697,6 +1705,22 @@ public class CarrierConfigManager {
|
||||
public static final String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG =
|
||||
"data_limit_threshold_bytes_long";
|
||||
|
||||
/**
|
||||
* Controls if the device should automatically notify the user as they reach
|
||||
* their cellular data limit. When set to {@code false} the carrier is
|
||||
* expected to have implemented their own notification mechanism.
|
||||
*/
|
||||
public static final String KEY_DATA_LIMIT_NOTIFICATION_BOOL =
|
||||
"data_limit_notification_bool";
|
||||
|
||||
/**
|
||||
* Controls if the device should automatically notify the user when rapid
|
||||
* cellular data usage is observed. When set to {@code false} the carrier is
|
||||
* expected to have implemented their own notification mechanism.
|
||||
*/
|
||||
public static final String KEY_DATA_RAPID_NOTIFICATION_BOOL =
|
||||
"data_rapid_notification_bool";
|
||||
|
||||
/**
|
||||
* Offset to be reduced from rsrp threshold while calculating signal strength level.
|
||||
* @hide
|
||||
@@ -2165,7 +2189,10 @@ public class CarrierConfigManager {
|
||||
|
||||
sDefaults.putInt(KEY_MONTHLY_DATA_CYCLE_DAY_INT, DATA_CYCLE_USE_PLATFORM_DEFAULT);
|
||||
sDefaults.putLong(KEY_DATA_WARNING_THRESHOLD_BYTES_LONG, DATA_CYCLE_USE_PLATFORM_DEFAULT);
|
||||
sDefaults.putBoolean(KEY_DATA_WARNING_NOTIFICATION_BOOL, true);
|
||||
sDefaults.putLong(KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG, DATA_CYCLE_USE_PLATFORM_DEFAULT);
|
||||
sDefaults.putBoolean(KEY_DATA_LIMIT_NOTIFICATION_BOOL, true);
|
||||
sDefaults.putBoolean(KEY_DATA_RAPID_NOTIFICATION_BOOL, true);
|
||||
|
||||
// Rat families: {GPRS, EDGE}, {EVDO, EVDO_A, EVDO_B}, {UMTS, HSPA, HSDPA, HSUPA, HSPAP},
|
||||
// {LTE, LTE_CA}
|
||||
|
||||
@@ -254,6 +254,9 @@ public final class SubscriptionPlan implements Parcelable {
|
||||
* @param period The period after which the plan automatically recurs.
|
||||
*/
|
||||
public static Builder createRecurring(ZonedDateTime start, Period period) {
|
||||
if (period.isZero() || period.isNegative()) {
|
||||
throw new IllegalArgumentException("Period " + period + " must be positive");
|
||||
}
|
||||
return new Builder(start, null, period);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user