Add ability for CTS to set itself as carrier service package
This change introduces a Carrier Service Package override, requiring
MODIFY_PHONE_STATE, ensuring that CTS can export a CarrierService, and
set itself as the carrier service.
The requirement for the application to also be carrier-privileged still
stands, but omits the SIM-certificate-match requirement, instead
allowing carrierConfig based certificates + carrier service package
override as a sufficient gate (which critically need to both be doable
with the CTS Shell permission identity)
Bug: 266904760
Test: Manually tested with a demo CTS build, will be used for Core
Networking CTS tests
Change-Id: I09f3107b860618d207a016964515eb1440e7beba
Merged-In: I09f3107b860618d207a016964515eb1440e7beba
(cherry picked from commit 810b869a628a290e6c4d794fb63daa5268ef0650)
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index efacda3..706373b 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -9183,6 +9183,34 @@
}
@Override
+ public void setCarrierServicePackageOverride(
+ int subId, String carrierServicePackage, String callingPackage) {
+ TelephonyPermissions.enforceShellOnly(
+ Binder.getCallingUid(), "setCarrierServicePackageOverride");
+
+ // Verify that the callingPackage belongs to the calling UID
+ mApp.getSystemService(AppOpsManager.class)
+ .checkPackage(Binder.getCallingUid(), callingPackage);
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ final Phone phone = getPhone(subId);
+ if (phone == null || phone.getSubId() != subId) {
+ loge("setCarrierServicePackageOverride fails with invalid subId: " + subId);
+ throw new IllegalArgumentException("No phone for subid");
+ }
+ CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
+ if (cpt == null) {
+ loge("setCarrierServicePackageOverride failed with no CPT for phone");
+ throw new IllegalStateException("No CPT for phone");
+ }
+ cpt.setTestOverrideCarrierServicePackage(carrierServicePackage);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public int getCarrierIdListVersion(int subId) {
enforceReadPrivilegedPermission("getCarrierIdListVersion");
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 9f86c24..70912c1 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -96,6 +96,10 @@
private static final String ENABLE = "enable";
private static final String DISABLE = "disable";
private static final String QUERY = "query";
+ private static final String SET_CARRIER_SERVICE_PACKAGE_OVERRIDE =
+ "set-carrier-service-package-override";
+ private static final String CLEAR_CARRIER_SERVICE_PACKAGE_OVERRIDE =
+ "clear-carrier-service-package-override";
private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
@@ -333,6 +337,10 @@
return handleGetSimSlotsMapping();
case RADIO_SUBCOMMAND:
return handleRadioCommand();
+ case SET_CARRIER_SERVICE_PACKAGE_OVERRIDE:
+ return setCarrierServicePackageOverride();
+ case CLEAR_CARRIER_SERVICE_PACKAGE_OVERRIDE:
+ return clearCarrierServicePackageOverride();
default: {
return handleDefaultCommands(cmd);
}
@@ -2972,4 +2980,95 @@
return -1;
}
+
+ // set-carrier-service-package-override
+ private int setCarrierServicePackageOverride() {
+ PrintWriter errPw = getErrPrintWriter();
+ int subId = SubscriptionManager.getDefaultSubscriptionId();
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "-s":
+ try {
+ subId = Integer.parseInt(getNextArgRequired());
+ } catch (NumberFormatException e) {
+ errPw.println(
+ "set-carrier-service-package-override requires an integer as a"
+ + " subscription ID.");
+ return -1;
+ }
+ break;
+ }
+ }
+
+ String packageName = getNextArg();
+ if (packageName == null) {
+ errPw.println("set-carrier-service-package-override requires a override package name.");
+ return -1;
+ }
+
+ try {
+ mInterface.setCarrierServicePackageOverride(
+ subId, packageName, mContext.getOpPackageName());
+
+ if (VDBG) {
+ Log.v(
+ LOG_TAG,
+ "set-carrier-service-package-override -s " + subId + " " + packageName);
+ }
+ } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
+ Log.w(
+ LOG_TAG,
+ "set-carrier-service-package-override -s "
+ + subId
+ + " "
+ + packageName
+ + ", error"
+ + e.getMessage());
+ errPw.println("Exception: " + e.getMessage());
+ return -1;
+ }
+ return 0;
+ }
+
+ // clear-carrier-service-package-override
+ private int clearCarrierServicePackageOverride() {
+ PrintWriter errPw = getErrPrintWriter();
+ int subId = getDefaultSlot();
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "-s":
+ try {
+ subId = Integer.parseInt(getNextArgRequired());
+ } catch (NumberFormatException e) {
+ errPw.println(
+ "clear-carrier-service-package-override requires an integer as a"
+ + " subscription ID.");
+ return -1;
+ }
+ break;
+ }
+ }
+
+ try {
+ mInterface.setCarrierServicePackageOverride(subId, null, mContext.getOpPackageName());
+
+ if (VDBG) {
+ Log.v(LOG_TAG, "clear-carrier-service-package-override -s " + subId);
+ }
+ } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
+ Log.w(
+ LOG_TAG,
+ "clear-carrier-service-package-override -s "
+ + subId
+ + ", error"
+ + e.getMessage());
+ errPw.println("Exception: " + e.getMessage());
+ return -1;
+ }
+ return 0;
+ }
}