Tests for SubscriptionManager APIs.
Ensure that new SubscriptionManager APIs behave as documented. Test
based on device claiming FEATURE_TELEPHONY, and require that we have
a valid getDefaultDataSubscriptionId() to run our tests against.
Test: atest android.telephony.cts.SubscriptionManagerTest
Bug: 77327990, 71816837
Change-Id: Ib90ceeacf546c9b36ecf69694442cb661a62d353
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index ddb2a85..946d22e6 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -149,7 +149,6 @@
import android.net.wifi.WifiManager;
import android.os.BestClock;
import android.os.Binder;
-import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
@@ -360,6 +359,8 @@
private static final int UID_MSG_STATE_CHANGED = 100;
private static final int UID_MSG_GONE = 101;
+ private static final String PROP_SUB_PLAN_OWNER = "persist.sys.sub_plan_owner";
+
private final Context mContext;
private final IActivityManager mActivityManager;
private NetworkStatsManagerInternal mNetworkStats;
@@ -2786,10 +2787,17 @@
return;
}
- // Fourth check: is caller a testing app on a debug build?
- final boolean enableDebug = Build.IS_USERDEBUG || Build.IS_ENG;
- if (enableDebug && callingPackage
- .equals(SystemProperties.get("fw.sub_plan_owner." + subId, null))) {
+ // Fourth check: is caller a testing app?
+ final String testPackage = SystemProperties.get(PROP_SUB_PLAN_OWNER + "." + subId, null);
+ if (!TextUtils.isEmpty(testPackage)
+ && Objects.equals(testPackage, callingPackage)) {
+ return;
+ }
+
+ // Fifth check: is caller a legacy testing app?
+ final String legacyTestPackage = SystemProperties.get("fw.sub_plan_owner." + subId, null);
+ if (!TextUtils.isEmpty(legacyTestPackage)
+ && Objects.equals(legacyTestPackage, callingPackage)) {
return;
}
@@ -2990,6 +2998,14 @@
}
}
+ /**
+ * Only visible for testing purposes. This doesn't give any access to
+ * existing plans; it simply lets the debug package define new plans.
+ */
+ void setSubscriptionPlansOwner(int subId, String packageName) {
+ SystemProperties.set(PROP_SUB_PLAN_OWNER + "." + subId, packageName);
+ }
+
@Override
public String getSubscriptionPlansOwner(int subId) {
if (UserHandle.getCallingAppId() != android.os.Process.SYSTEM_UID) {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
index b65b9d7..56d41c5 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
@@ -21,7 +21,6 @@
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import android.content.Context;
-import android.net.INetworkPolicyManager;
import android.net.NetworkPolicyManager;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
@@ -33,10 +32,10 @@
class NetworkPolicyManagerShellCommand extends ShellCommand {
- private final INetworkPolicyManager mInterface;
+ private final NetworkPolicyManagerService mInterface;
private final WifiManager mWifiManager;
- NetworkPolicyManagerShellCommand(Context context, INetworkPolicyManager service) {
+ NetworkPolicyManagerShellCommand(Context context, NetworkPolicyManagerService service) {
mInterface = service;
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
}
@@ -97,6 +96,8 @@
pw.println(" Toggles whether the given wi-fi network is metered.");
pw.println(" set restrict-background BOOLEAN");
pw.println(" Sets the global restrict background usage status.");
+ pw.println(" set sub-plan-owner subId [packageName]");
+ pw.println(" Sets the data plan owner package for subId.");
}
private int runGet() throws RemoteException {
@@ -126,6 +127,8 @@
return setMeteredWifiNetwork();
case "restrict-background":
return setRestrictBackground();
+ case "sub-plan-owner":
+ return setSubPlanOwner();
}
pw.println("Error: unknown set type '" + type + "'");
return -1;
@@ -227,6 +230,13 @@
return 0;
}
+ private int setSubPlanOwner() throws RemoteException {
+ final int subId = Integer.parseInt(getNextArgRequired());
+ final String packageName = getNextArg();
+ mInterface.setSubscriptionPlansOwner(subId, packageName);
+ return 0;
+ }
+
private int setUidPolicy(int policy) throws RemoteException {
final int uid = getUidFromNextArg();
if (uid < 0) {
diff --git a/telephony/java/android/telephony/SubscriptionPlan.java b/telephony/java/android/telephony/SubscriptionPlan.java
index 9411652..4ffb70b 100644
--- a/telephony/java/android/telephony/SubscriptionPlan.java
+++ b/telephony/java/android/telephony/SubscriptionPlan.java
@@ -34,6 +34,7 @@
import java.time.Period;
import java.time.ZonedDateTime;
import java.util.Iterator;
+import java.util.Objects;
/**
* Description of a billing relationship plan between a carrier and a specific
@@ -124,6 +125,27 @@
.append("}").toString();
}
+ @Override
+ public int hashCode() {
+ return Objects.hash(cycleRule, title, summary, dataLimitBytes, dataLimitBehavior,
+ dataUsageBytes, dataUsageTime);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof SubscriptionPlan) {
+ final SubscriptionPlan other = (SubscriptionPlan) obj;
+ return Objects.equals(cycleRule, other.cycleRule)
+ && Objects.equals(title, other.title)
+ && Objects.equals(summary, other.summary)
+ && dataLimitBytes == other.dataLimitBytes
+ && dataLimitBehavior == other.dataLimitBehavior
+ && dataUsageBytes == other.dataUsageBytes
+ && dataUsageTime == other.dataUsageTime;
+ }
+ return false;
+ }
+
public static final Parcelable.Creator<SubscriptionPlan> CREATOR = new Parcelable.Creator<SubscriptionPlan>() {
@Override
public SubscriptionPlan createFromParcel(Parcel source) {