Merge "5G meteredness for telephony framework"
diff --git a/api/current.txt b/api/current.txt
index f759d94..12e139a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -45422,6 +45422,7 @@
method public long getDataLimitBytes();
method public long getDataUsageBytes();
method public long getDataUsageTime();
+ method @Nullable public int[] getNetworkTypes();
method @Nullable public CharSequence getSummary();
method @Nullable public CharSequence getTitle();
method public void writeToParcel(android.os.Parcel, int);
@@ -45441,6 +45442,7 @@
method public static android.telephony.SubscriptionPlan.Builder createRecurring(java.time.ZonedDateTime, java.time.Period);
method public android.telephony.SubscriptionPlan.Builder setDataLimit(long, int);
method public android.telephony.SubscriptionPlan.Builder setDataUsage(long, long);
+ method @NonNull public android.telephony.SubscriptionPlan.Builder setNetworkTypes(@Nullable int[]);
method public android.telephony.SubscriptionPlan.Builder setSummary(@Nullable CharSequence);
method public android.telephony.SubscriptionPlan.Builder setTitle(@Nullable CharSequence);
}
diff --git a/core/java/android/net/INetworkPolicyListener.aidl b/core/java/android/net/INetworkPolicyListener.aidl
index 106b7be..fe9141c 100644
--- a/core/java/android/net/INetworkPolicyListener.aidl
+++ b/core/java/android/net/INetworkPolicyListener.aidl
@@ -15,6 +15,7 @@
*/
package android.net;
+import android.telephony.SubscriptionPlan;
/** {@hide} */
oneway interface INetworkPolicyListener {
@@ -22,5 +23,6 @@
void onMeteredIfacesChanged(in String[] meteredIfaces);
void onRestrictBackgroundChanged(boolean restrictBackground);
void onUidPoliciesChanged(int uid, int uidPolicies);
- void onSubscriptionOverride(int subId, int overrideMask, int overrideValue, long networkTypeMask);
+ void onSubscriptionOverride(int subId, int overrideMask, int overrideValue);
+ void onSubscriptionPlansChanged(int subId, in SubscriptionPlan[] plans);
}
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 90327663..385cb1d 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -76,7 +76,7 @@
SubscriptionPlan[] getSubscriptionPlans(int subId, String callingPackage);
void setSubscriptionPlans(int subId, in SubscriptionPlan[] plans, String callingPackage);
String getSubscriptionPlansOwner(int subId);
- void setSubscriptionOverride(int subId, int overrideMask, int overrideValue, long networkTypeMask, long timeoutMillis, String callingPackage);
+ void setSubscriptionOverride(int subId, int overrideMask, int overrideValue, long timeoutMillis, String callingPackage);
void factoryReset(String subscriber);
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 53854c2..de962f8 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -31,6 +31,7 @@
import android.os.Build;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.telephony.SubscriptionPlan;
import android.util.DebugUtils;
import android.util.Pair;
import android.util.Range;
@@ -380,7 +381,8 @@
@Override public void onMeteredIfacesChanged(String[] meteredIfaces) { }
@Override public void onRestrictBackgroundChanged(boolean restrictBackground) { }
@Override public void onUidPoliciesChanged(int uid, int uidPolicies) { }
- @Override public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue,
- long networkTypeMask) { }
+ @Override public void onSubscriptionOverride(int subId, int overrideMask,
+ int overrideValue) { }
+ @Override public void onSubscriptionPlansChanged(int subId, SubscriptionPlan[] plans) { }
}
}
diff --git a/core/java/android/telephony/SubscriptionPlan.java b/core/java/android/telephony/SubscriptionPlan.java
index ec2050f..e24eb26 100644
--- a/core/java/android/telephony/SubscriptionPlan.java
+++ b/core/java/android/telephony/SubscriptionPlan.java
@@ -24,6 +24,7 @@
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.Annotation.NetworkType;
import android.util.Range;
import android.util.RecurrenceRule;
@@ -33,6 +34,7 @@
import java.lang.annotation.RetentionPolicy;
import java.time.Period;
import java.time.ZonedDateTime;
+import java.util.Arrays;
import java.util.Iterator;
import java.util.Objects;
@@ -80,6 +82,8 @@
private int dataLimitBehavior = LIMIT_BEHAVIOR_UNKNOWN;
private long dataUsageBytes = BYTES_UNKNOWN;
private long dataUsageTime = TIME_UNKNOWN;
+ private @NetworkType int[] networkTypes;
+ private long networkTypesBitMask;
private SubscriptionPlan(RecurrenceRule cycleRule) {
this.cycleRule = Preconditions.checkNotNull(cycleRule);
@@ -93,6 +97,7 @@
dataLimitBehavior = source.readInt();
dataUsageBytes = source.readLong();
dataUsageTime = source.readLong();
+ networkTypes = source.createIntArray();
}
@Override
@@ -109,6 +114,7 @@
dest.writeInt(dataLimitBehavior);
dest.writeLong(dataUsageBytes);
dest.writeLong(dataUsageTime);
+ dest.writeIntArray(networkTypes);
}
@Override
@@ -121,13 +127,14 @@
.append(" dataLimitBehavior=").append(dataLimitBehavior)
.append(" dataUsageBytes=").append(dataUsageBytes)
.append(" dataUsageTime=").append(dataUsageTime)
+ .append(" networkTypes=").append(Arrays.toString(networkTypes))
.append("}").toString();
}
@Override
public int hashCode() {
return Objects.hash(cycleRule, title, summary, dataLimitBytes, dataLimitBehavior,
- dataUsageBytes, dataUsageTime);
+ dataUsageBytes, dataUsageTime, Arrays.hashCode(networkTypes));
}
@Override
@@ -140,7 +147,8 @@
&& dataLimitBytes == other.dataLimitBytes
&& dataLimitBehavior == other.dataLimitBehavior
&& dataUsageBytes == other.dataUsageBytes
- && dataUsageTime == other.dataUsageTime;
+ && dataUsageTime == other.dataUsageTime
+ && Arrays.equals(networkTypes, other.networkTypes);
}
return false;
}
@@ -204,6 +212,32 @@
}
/**
+ * Return an array containing all {@link NetworkType}s this SubscriptionPlan applies to.
+ * A null array means this SubscriptionPlan applies to all network types.
+ */
+ public @Nullable @NetworkType int[] getNetworkTypes() {
+ return networkTypes;
+ }
+
+ /**
+ * Return the networkTypes array converted to a {@link TelephonyManager.NetworkTypeBitMask}
+ * @hide
+ */
+ public long getNetworkTypesBitMask() {
+ // calculate bitmask the first time and save for future calls
+ if (networkTypesBitMask == 0) {
+ if (networkTypes == null) {
+ networkTypesBitMask = ~0;
+ } else {
+ for (int networkType : networkTypes) {
+ networkTypesBitMask |= TelephonyManager.getBitMaskForNetworkType(networkType);
+ }
+ }
+ }
+ return networkTypesBitMask;
+ }
+
+ /**
* Return an iterator that will return all valid data usage cycles based on
* any recurrence rules. The iterator starts from the currently active cycle
* and walks backwards through time.
@@ -335,5 +369,24 @@
plan.dataUsageTime = dataUsageTime;
return this;
}
+
+ /**
+ * Set the network types this SubscriptionPlan applies to.
+ * The developer must supply at least one plan that applies to all network types (default),
+ * and all additional plans may not include a particular network type more than once.
+ * Plan selection will prefer plans that have specific network types defined
+ * over plans that apply to all network types.
+ *
+ * @param networkTypes a set of all {@link NetworkType}s that apply to this plan.
+ * A null value or empty array means the plan applies to all network types.
+ */
+ public @NonNull Builder setNetworkTypes(@Nullable @NetworkType int[] networkTypes) {
+ if (networkTypes == null || networkTypes.length == 0) {
+ plan.networkTypes = null;
+ } else {
+ plan.networkTypes = networkTypes;
+ }
+ return this;
+ }
}
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 877c40f..795ed55 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -222,13 +222,11 @@
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.RoSystemProperties;
-import com.android.internal.os.SomeArgs;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.Preconditions;
import com.android.internal.util.StatLogger;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
@@ -389,6 +387,7 @@
private static final int MSG_SUBSCRIPTION_OVERRIDE = 16;
private static final int MSG_METERED_RESTRICTED_PACKAGES_CHANGED = 17;
private static final int MSG_SET_NETWORK_TEMPLATE_ENABLED = 18;
+ private static final int MSG_SUBSCRIPTION_PLANS_CHANGED = 19;
private static final int UID_MSG_STATE_CHANGED = 100;
private static final int UID_MSG_GONE = 101;
@@ -3092,6 +3091,34 @@
mContext.enforceCallingOrSelfPermission(MANAGE_SUBSCRIPTION_PLANS, TAG);
}
+ private void enforceSubscriptionPlanValidity(SubscriptionPlan[] plans) {
+ // nothing to check if no plans
+ if (plans.length == 0) {
+ return;
+ }
+
+ long applicableNetworkTypes = 0;
+ boolean allNetworks = false;
+ for (SubscriptionPlan plan : plans) {
+ if (plan.getNetworkTypes() == null) {
+ allNetworks = true;
+ } else {
+ if ((applicableNetworkTypes & plan.getNetworkTypesBitMask()) != 0) {
+ throw new IllegalArgumentException(
+ "Multiple subscription plans defined for a single network type.");
+ } else {
+ applicableNetworkTypes |= plan.getNetworkTypesBitMask();
+ }
+ }
+ }
+
+ // ensure at least one plan applies for every network type
+ if (!allNetworks) {
+ throw new IllegalArgumentException(
+ "No generic subscription plan that applies to all network types.");
+ }
+ }
+
@Override
public SubscriptionPlan[] getSubscriptionPlans(int subId, String callingPackage) {
enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
@@ -3256,6 +3283,7 @@
@Override
public void setSubscriptionPlans(int subId, SubscriptionPlan[] plans, String callingPackage) {
enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
+ enforceSubscriptionPlanValidity(plans);
for (SubscriptionPlan plan : plans) {
Objects.requireNonNull(plan);
@@ -3284,6 +3312,8 @@
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
mContext.sendBroadcast(intent, android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS);
+ mHandler.sendMessage(
+ mHandler.obtainMessage(MSG_SUBSCRIPTION_PLANS_CHANGED, subId, 0, plans));
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -3310,7 +3340,7 @@
@Override
public void setSubscriptionOverride(int subId, int overrideMask, int overrideValue,
- long networkTypeMask, long timeoutMillis, String callingPackage) {
+ long timeoutMillis, String callingPackage) {
enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
// We can only override when carrier told us about plans
@@ -3328,16 +3358,11 @@
final boolean overrideEnabled = Settings.Global.getInt(mContext.getContentResolver(),
NETPOLICY_OVERRIDE_ENABLED, 1) != 0;
if (overrideEnabled || overrideValue == 0) {
- SomeArgs args = SomeArgs.obtain();
- args.arg1 = subId;
- args.arg2 = overrideMask;
- args.arg3 = overrideValue;
- args.arg4 = networkTypeMask;
- mHandler.sendMessage(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE, args));
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE,
+ overrideMask, overrideValue, subId));
if (timeoutMillis > 0) {
- args.arg3 = 0;
- mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE, args),
- timeoutMillis);
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE,
+ overrideMask, 0, subId), timeoutMillis);
}
}
}
@@ -4473,11 +4498,20 @@
}
private void dispatchSubscriptionOverride(INetworkPolicyListener listener, int subId,
- int overrideMask, int overrideValue, long networkTypeMask) {
+ int overrideMask, int overrideValue) {
if (listener != null) {
try {
- listener.onSubscriptionOverride(subId, overrideMask, overrideValue,
- networkTypeMask);
+ listener.onSubscriptionOverride(subId, overrideMask, overrideValue);
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
+
+ private void dispatchSubscriptionPlansChanged(INetworkPolicyListener listener, int subId,
+ SubscriptionPlan[] plans) {
+ if (listener != null) {
+ try {
+ listener.onSubscriptionPlansChanged(subId, plans);
} catch (RemoteException ignored) {
}
}
@@ -4578,16 +4612,13 @@
return true;
}
case MSG_SUBSCRIPTION_OVERRIDE: {
- final SomeArgs args = (SomeArgs) msg.obj;
- final int subId = (int) args.arg1;
- final int overrideMask = (int) args.arg2;
- final int overrideValue = (int) args.arg3;
- final long networkTypeMask = (long) args.arg4;
+ final int overrideMask = msg.arg1;
+ final int overrideValue = msg.arg2;
+ final int subId = (int) msg.obj;
final int length = mListeners.beginBroadcast();
for (int i = 0; i < length; i++) {
final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
- dispatchSubscriptionOverride(listener, subId, overrideMask, overrideValue,
- networkTypeMask);
+ dispatchSubscriptionOverride(listener, subId, overrideMask, overrideValue);
}
mListeners.finishBroadcast();
return true;
@@ -4604,6 +4635,17 @@
setNetworkTemplateEnabledInner(template, enabled);
return true;
}
+ case MSG_SUBSCRIPTION_PLANS_CHANGED: {
+ final SubscriptionPlan[] plans = (SubscriptionPlan[]) msg.obj;
+ final int subId = msg.arg1;
+ final int length = mListeners.beginBroadcast();
+ for (int i = 0; i < length; i++) {
+ final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
+ dispatchSubscriptionPlansChanged(listener, subId, plans);
+ }
+ mListeners.finishBroadcast();
+ return true;
+ }
default: {
return false;
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 2f37c2a..de99b0d 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -3018,7 +3018,7 @@
"ping_test_before_data_switch_bool";
/**
- * Controls time in milli seconds until DcTracker reevaluates 5G connection state.
+ * Controls time in milliseconds until DcTracker reevaluates 5G connection state.
* @hide
*/
public static final String KEY_5G_WATCHDOG_TIME_MS_LONG =
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 71ea3a3..9d744a6 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -54,7 +54,6 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Telephony.SimInfo;
-import android.telephony.Annotation.NetworkType;
import android.telephony.euicc.EuiccManager;
import android.telephony.ims.ImsMmTelManager;
import android.util.DisplayMetrics;
@@ -2501,8 +2500,12 @@
* @param plans the list of plans. The first plan is always the primary and
* most important plan. Any additional plans are secondary and
* may not be displayed or used by decision making logic.
+ * The list of all plans must meet the requirements defined in
+ * {@link SubscriptionPlan.Builder#setNetworkTypes(int[])}.
* @throws SecurityException if the caller doesn't meet the requirements
* outlined above.
+ * @throws IllegalArgumentException if plans don't meet the requirements
+ * mentioned above.
*/
public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) {
try {
@@ -2547,51 +2550,10 @@
*/
public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered,
@DurationMillisLong long timeoutMillis) {
- setSubscriptionOverrideUnmetered(subId, null, overrideUnmetered, timeoutMillis);
- }
-
- /**
- * Temporarily override the billing relationship between a carrier and
- * a specific subscriber to be considered unmetered for the given network
- * types. This will be reflected to apps via
- * {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED}.
- * This method is only accessible to the following narrow set of apps:
- * <ul>
- * <li>The carrier app for this subscriberId, as determined by
- * {@link TelephonyManager#hasCarrierPrivileges()}.
- * <li>The carrier app explicitly delegated access through
- * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
- * </ul>
- *
- * @param subId the subscriber this override applies to.
- * @param networkTypes all network types to set an override for. A null
- * network type means to apply the override to all network types.
- * Any unspecified network types will default to metered.
- * @param overrideUnmetered set if the billing relationship should be
- * considered unmetered.
- * @param timeoutMillis the timeout after which the requested override will
- * be automatically cleared, or {@code 0} to leave in the
- * requested state until explicitly cleared, or the next reboot,
- * whichever happens first.
- * @throws SecurityException if the caller doesn't meet the requirements
- * outlined above.
- * {@hide}
- */
- public void setSubscriptionOverrideUnmetered(int subId,
- @Nullable @NetworkType int[] networkTypes, boolean overrideUnmetered,
- @DurationMillisLong long timeoutMillis) {
try {
- long networkTypeMask = 0;
- if (networkTypes != null) {
- for (int networkType : networkTypes) {
- networkTypeMask |= TelephonyManager.getBitMaskForNetworkType(networkType);
- }
- } else {
- networkTypeMask = ~0;
- }
final int overrideValue = overrideUnmetered ? OVERRIDE_UNMETERED : 0;
getNetworkPolicy().setSubscriptionOverride(subId, OVERRIDE_UNMETERED, overrideValue,
- networkTypeMask, timeoutMillis, mContext.getOpPackageName());
+ timeoutMillis, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2623,52 +2585,10 @@
*/
public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested,
@DurationMillisLong long timeoutMillis) {
- setSubscriptionOverrideCongested(subId, null, overrideCongested, timeoutMillis);
- }
-
- /**
- * Temporarily override the billing relationship plan between a carrier and
- * a specific subscriber to be considered congested. This will cause the
- * device to delay certain network requests when possible, such as developer
- * jobs that are willing to run in a flexible time window.
- * <p>
- * This method is only accessible to the following narrow set of apps:
- * <ul>
- * <li>The carrier app for this subscriberId, as determined by
- * {@link TelephonyManager#hasCarrierPrivileges()}.
- * <li>The carrier app explicitly delegated access through
- * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
- * </ul>
- *
- * @param subId the subscriber this override applies to.
- * @param networkTypes all network types to set an override for. A null
- * network type means to apply the override to all network types.
- * Any unspecified network types will default to not congested.
- * @param overrideCongested set if the subscription should be considered
- * congested.
- * @param timeoutMillis the timeout after which the requested override will
- * be automatically cleared, or {@code 0} to leave in the
- * requested state until explicitly cleared, or the next reboot,
- * whichever happens first.
- * @throws SecurityException if the caller doesn't meet the requirements
- * outlined above.
- * @hide
- */
- public void setSubscriptionOverrideCongested(int subId,
- @Nullable @NetworkType int[] networkTypes, boolean overrideCongested,
- @DurationMillisLong long timeoutMillis) {
try {
- long networkTypeMask = 0;
- if (networkTypes != null) {
- for (int networkType : networkTypes) {
- networkTypeMask |= TelephonyManager.getBitMaskForNetworkType(networkType);
- }
- } else {
- networkTypeMask = ~0;
- }
final int overrideValue = overrideCongested ? OVERRIDE_CONGESTED : 0;
getNetworkPolicy().setSubscriptionOverride(subId, OVERRIDE_CONGESTED, overrideValue,
- networkTypeMask, timeoutMillis, mContext.getOpPackageName());
+ timeoutMillis, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 668a6af..9e786ce 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -111,7 +111,7 @@
public static final int EVENT_DATA_SERVICE_BINDING_CHANGED = BASE + 49;
public static final int EVENT_DEVICE_PROVISIONED_CHANGE = BASE + 50;
public static final int EVENT_DATA_ENABLED_OVERRIDE_RULES_CHANGED = BASE + 51;
- public static final int EVENT_5G_NETWORK_CHANGED = BASE + 52;
+ public static final int EVENT_SERVICE_STATE_CHANGED = BASE + 52;
public static final int EVENT_5G_TIMER_HYSTERESIS = BASE + 53;
public static final int EVENT_5G_TIMER_WATCHDOG = BASE + 54;