Persistent storage in Carrier Config debug shell commands
Add support for Persistent storage in Carrier Config shell debug
commands. Adds an option "-p" in the command "cc set-config" to control
that the new value should be stored persistent.
The syntax for "cc set-value" then becomes:
cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]
Bug: 144544956
Test: atest TeleServiceTests
Change-Id: I775503c32974d658dace68ea88cdbeb564ca7c19
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 9841a82..13dcaa7 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -20,6 +20,7 @@
import static android.service.carrier.CarrierService.ICarrierServiceWrapper.RESULT_ERROR;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -94,6 +95,8 @@
private PersistableBundle[] mConfigFromDefaultApp;
// Carrier configs from privileged carrier config app, indexed by phoneID.
private PersistableBundle[] mConfigFromCarrierApp;
+ // Persistent Carrier configs that are provided via the override test API, indexed by phone ID.
+ private PersistableBundle[] mPersistentOverrideConfigs;
// Carrier configs that are provided via the override test API, indexed by phone ID.
private PersistableBundle[] mOverrideConfigs;
// Service connection for binding to config app.
@@ -151,6 +154,8 @@
private static final String TAG_VERSION = "package_version";
private static final String TAG_BUNDLE = "bundle_data";
+ private static final String OVERRIDE_PACKAGE_ADDITION = "-override";
+
// SharedPreferences key for last known build fingerprint.
private static final String KEY_FINGERPRINT = "build_fingerprint";
@@ -220,8 +225,17 @@
case EVENT_DO_FETCH_DEFAULT:
{
- final PersistableBundle config =
- restoreConfigFromXml(mPlatformCarrierConfigPackage, phoneId);
+ // Restore persistent override values.
+ PersistableBundle config = restoreConfigFromXml(
+ mPlatformCarrierConfigPackage, OVERRIDE_PACKAGE_ADDITION, phoneId);
+ if (config != null) {
+ log("Loaded persistent override config from XML. package="
+ + mPlatformCarrierConfigPackage
+ + " phoneId=" + phoneId);
+ mPersistentOverrideConfigs[phoneId] = config;
+ }
+
+ config = restoreConfigFromXml(mPlatformCarrierConfigPackage, "", phoneId);
if (config != null) {
log(
"Loaded config from XML. package="
@@ -283,7 +297,7 @@
}
PersistableBundle config =
resultData.getParcelable(KEY_CONFIG_BUNDLE);
- saveConfigToXml(mPlatformCarrierConfigPackage, phoneId,
+ saveConfigToXml(mPlatformCarrierConfigPackage, "", phoneId,
carrierId, config);
mConfigFromDefaultApp[phoneId] = config;
sendMessage(
@@ -351,7 +365,7 @@
{
final String carrierPackageName = getCarrierPackageForPhoneId(phoneId);
final PersistableBundle config =
- restoreConfigFromXml(carrierPackageName, phoneId);
+ restoreConfigFromXml(carrierPackageName, "", phoneId);
if (config != null) {
log(
"Loaded config from XML. package="
@@ -414,8 +428,8 @@
}
PersistableBundle config =
resultData.getParcelable(KEY_CONFIG_BUNDLE);
- saveConfigToXml(getCarrierPackageForPhoneId(phoneId), phoneId,
- carrierId, config);
+ saveConfigToXml(getCarrierPackageForPhoneId(phoneId), "",
+ phoneId, carrierId, config);
mConfigFromCarrierApp[phoneId] = config;
sendMessage(
obtainMessage(
@@ -528,6 +542,7 @@
int numPhones = TelephonyManager.from(context).getSupportedModemCount();
mConfigFromDefaultApp = new PersistableBundle[numPhones];
mConfigFromCarrierApp = new PersistableBundle[numPhones];
+ mPersistentOverrideConfigs = new PersistableBundle[numPhones];
mOverrideConfigs = new PersistableBundle[numPhones];
mServiceConnection = new CarrierServiceConnection[numPhones];
mHasSentConfigChange = new boolean[numPhones];
@@ -737,12 +752,13 @@
* In case of errors or invalid input, no file will be written.
*
* @param packageName the name of the package from which we fetched this bundle.
+ * @param extraString An extra string to be used in the XML file name.
* @param phoneId the phone ID.
* @param carrierId contains all carrier-identifying information.
* @param config the bundle to be written. Null will be treated as an empty bundle.
*/
- private void saveConfigToXml(String packageName, int phoneId, CarrierIdentifier carrierId,
- PersistableBundle config) {
+ private void saveConfigToXml(String packageName, @NonNull String extraString, int phoneId,
+ CarrierIdentifier carrierId, PersistableBundle config) {
if (SubscriptionManager.getSimStateForSlotIndex(phoneId)
!= TelephonyManager.SIM_STATE_LOADED) {
loge("Skip save config because SIM records are not loaded.");
@@ -776,7 +792,7 @@
try {
outFile = new FileOutputStream(
new File(mContext.getFilesDir(),
- getFilenameForConfig(packageName, iccid, cid)));
+ getFilenameForConfig(packageName, extraString, iccid, cid)));
FastXmlSerializer out = new FastXmlSerializer();
out.setOutput(outFile, "utf-8");
out.startDocument("utf-8", true);
@@ -810,11 +826,13 @@
* current version, then null will be returned.
*
* @param packageName the name of the package from which we fetched this bundle.
+ * @param extraString An extra string to be used in the XML file name.
* @param phoneId the phone ID.
* @return the bundle from the XML file. Returns null if there is no saved config, the saved
* version does not match, or reading config fails.
*/
- private PersistableBundle restoreConfigFromXml(String packageName, int phoneId) {
+ private PersistableBundle restoreConfigFromXml(String packageName, @NonNull String extraString,
+ int phoneId) {
final String version = getPackageVersion(packageName);
if (version == null) {
loge("Failed to get package version for: " + packageName);
@@ -834,11 +852,12 @@
}
PersistableBundle restoredBundle = null;
+ File file = null;
FileInputStream inFile = null;
try {
- inFile = new FileInputStream(
- new File(mContext.getFilesDir(),
- getFilenameForConfig(packageName, iccid, cid)));
+ file = new File(mContext.getFilesDir(),
+ getFilenameForConfig(packageName, extraString, iccid, cid));
+ inFile = new FileInputStream(file);
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
parser.setInput(inFile, "utf-8");
@@ -860,7 +879,9 @@
inFile.close();
}
catch (FileNotFoundException e) {
- loge(e.toString());
+ // Missing file is normal occurrence that might occur with a new sim or when restoring
+ // an override file during boot and should not be treated as an error.
+ if (file != null) log("File not found: " + file.getPath());
}
catch (XmlPullParserException e) {
loge(e.toString());
@@ -901,13 +922,13 @@
}
/** Builds a canonical file name for a config file. */
- private String getFilenameForConfig(@NonNull String packageName, @NonNull String iccid,
- int cid) {
+ private String getFilenameForConfig(@NonNull String packageName, @NonNull String extraString,
+ @NonNull String iccid, int cid) {
// the same carrier should have a single copy of XML file named after carrier id.
// However, it's still possible that platform doesn't recognize the current sim carrier,
// we will use iccid + carrierid as the canonical file name. carrierid can also handle the
// cases SIM OTA resolves to different carrier while iccid remains the same.
- return "carrierconfig-" + packageName + "-" + iccid + "-" + cid + ".xml";
+ return "carrierconfig-" + packageName + extraString + "-" + iccid + "-" + cid + ".xml";
}
/** Return the current version code of a package, or null if the name is not found. */
@@ -973,6 +994,11 @@
retConfig.putAll(config);
retConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
}
+ config = mPersistentOverrideConfigs[phoneId];
+ if (config != null) {
+ retConfig.putAll(config);
+ retConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
+ }
config = mOverrideConfigs[phoneId];
if (config != null) {
retConfig.putAll(config);
@@ -982,7 +1008,8 @@
}
@Override
- public void overrideConfig(int subscriptionId, PersistableBundle overrides) {
+ public void overrideConfig(int subscriptionId, @Nullable PersistableBundle overrides,
+ boolean persistent) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.MODIFY_PHONE_STATE, null);
//TODO: Also check for SHELL UID to restrict this method to testing only (b/131326259)
@@ -991,18 +1018,38 @@
log("Ignore invalid phoneId: " + phoneId + " for subId: " + subscriptionId);
return;
}
+ overrideConfig(mOverrideConfigs, phoneId, overrides);
- if (overrides == null) {
- mOverrideConfigs[phoneId] = new PersistableBundle();
- } else if (mOverrideConfigs[phoneId] == null) {
- mOverrideConfigs[phoneId] = overrides;
- } else {
- mOverrideConfigs[phoneId].putAll(overrides);
+ if (persistent) {
+ overrideConfig(mPersistentOverrideConfigs, phoneId, overrides);
+
+ if (overrides != null) {
+ final CarrierIdentifier carrierId = getCarrierIdentifierForPhoneId(phoneId);
+ saveConfigToXml(mPlatformCarrierConfigPackage, OVERRIDE_PACKAGE_ADDITION, phoneId,
+ carrierId, mPersistentOverrideConfigs[phoneId]);
+ } else {
+ final String iccid = getIccIdForPhoneId(phoneId);
+ final int cid = getSpecificCarrierIdForPhoneId(phoneId);
+ String fileName = getFilenameForConfig(mPlatformCarrierConfigPackage,
+ OVERRIDE_PACKAGE_ADDITION, iccid, cid);
+ File fileToDelete = new File(mContext.getFilesDir(), fileName);
+ fileToDelete.delete();
+ }
}
-
notifySubscriptionInfoUpdater(phoneId);
}
+ private void overrideConfig(@NonNull PersistableBundle[] currentOverrides, int phoneId,
+ @Nullable PersistableBundle overrides) {
+ if (overrides == null) {
+ currentOverrides[phoneId] = new PersistableBundle();
+ } else if (currentOverrides[phoneId] == null) {
+ currentOverrides[phoneId] = overrides;
+ } else {
+ currentOverrides[phoneId].putAll(overrides);
+ }
+ }
+
@Override
public void notifyConfigChangedForSubId(int subId) {
int phoneId = SubscriptionManager.getPhoneId(subId);
@@ -1074,6 +1121,8 @@
// display ConfigFromCarrierApp
printConfig(mConfigFromCarrierApp[i], pw, "mConfigFromCarrierApp");
pw.println("");
+ printConfig(mPersistentOverrideConfigs[i], pw, "mPersistentOverrideConfigs");
+ pw.println("");
printConfig(mOverrideConfigs[i], pw, "mOverrideConfigs");
}
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index ebadf88..672a27f 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -83,6 +83,11 @@
STRING_ARRAY, UNKNOWN
}
+ private class CcOptionParseResult {
+ public int mSubId;
+ public boolean mPersistent;
+ }
+
// Maps carrier config keys to type. It is possible to infer the type for most carrier config
// keys by looking at the end of the string which usually tells the type.
// For instance: "xxxx_string", "xxxx_string_array", etc.
@@ -226,11 +231,12 @@
pw.println(" is specified, it will choose the default voice SIM slot.");
pw.println(" KEY: The key to the carrier config value to print. All values are printed");
pw.println(" if KEY is not specified.");
- pw.println(" cc set-value [-s SLOT_ID] KEY [NEW_VALUE]");
+ pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
pw.println(" Set carrier config KEY to NEW_VALUE.");
pw.println(" Options are:");
pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
pw.println(" is specified, it will choose the default voice SIM slot.");
+ pw.println(" -p: Value will be stored persistent");
pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
@@ -568,32 +574,47 @@
return slotId;
}
- // Get the subId from argument SLOT_ID if it was provided. Otherwise use the default
- // subscription.
- private int getSubIdFromArgumentSlotId(String tag) {
+ // Parse options related to Carrier Config Commands.
+ private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
PrintWriter errPw = getErrPrintWriter();
- int subId = SubscriptionManager.getDefaultSubscriptionId();
- String opt;
+ CcOptionParseResult result = new CcOptionParseResult();
+ result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
+ result.mPersistent = false;
+ String opt;
while ((opt = getNextOption()) != null) {
switch (opt) {
case "-s": {
try {
- subId = slotStringToSubId(tag, getNextArgRequired());
+ result.mSubId = slotStringToSubId(tag, getNextArgRequired());
+ if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
+ errPw.println(tag + "No valid subscription found.");
+ return null;
+ }
+
} catch (IllegalArgumentException e) {
// Missing slot id
errPw.println(tag + "SLOT_ID expected after -s.");
- return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ return null;
+ }
+ break;
+ }
+ case "-p": {
+ if (allowOptionPersistent) {
+ result.mPersistent = true;
+ } else {
+ errPw.println(tag + "Unexpected option " + opt);
+ return null;
}
break;
}
default: {
errPw.println(tag + "Unknown option " + opt);
- return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ return null;
}
}
}
- return subId;
+ return result;
}
private int slotStringToSubId(String tag, String slotString) {
@@ -657,17 +678,16 @@
String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
String key = null;
- // Get the subId from the SLOT_ID-argument.
- int subId = getSubIdFromArgumentSlotId(tag);
- if (!SubscriptionManager.isValidSubscriptionId(subId)) {
- errPw.println(tag + "No valid subscription found.");
+ // Parse all options
+ CcOptionParseResult options = parseCcOptions(tag, false);
+ if (options == null) {
return -1;
}
// Get bundle containing all carrier configuration values.
- PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(subId);
+ PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
if (bundle == null) {
- errPw.println(tag + "No carrier config values found for subId " + subId + ".");
+ errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
return -1;
}
@@ -698,17 +718,16 @@
PrintWriter errPw = getErrPrintWriter();
String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
- // Get the subId from the SLOT_ID-argument.
- int subId = getSubIdFromArgumentSlotId(tag);
- if (!SubscriptionManager.isValidSubscriptionId(subId)) {
- errPw.println(tag + "No valid subscription found.");
+ // Parse all options
+ CcOptionParseResult options = parseCcOptions(tag, true);
+ if (options == null) {
return -1;
}
// Get bundle containing all current carrier configuration values.
- PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(subId);
+ PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
if (originalValues == null) {
- errPw.println(tag + "No carrier config values found for subId " + subId + ".");
+ errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
return -1;
}
@@ -745,12 +764,12 @@
}
// Override the value
- mCarrierConfigManager.overrideConfig(subId, overrideBundle);
+ mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
// Find bundle containing all new carrier configuration values after the override.
- PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(subId);
+ PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
if (newValues == null) {
- errPw.println(tag + "No carrier config values found for subId " + subId + ".");
+ errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
return -1;
}
@@ -768,15 +787,14 @@
PrintWriter errPw = getErrPrintWriter();
String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
- // Get the subId from the SLOT_ID-argument.
- int subId = getSubIdFromArgumentSlotId(tag);
- if (!SubscriptionManager.isValidSubscriptionId(subId)) {
- errPw.println(tag + "No valid subscription found.");
+ // Parse all options
+ CcOptionParseResult options = parseCcOptions(tag, false);
+ if (options == null) {
return -1;
}
// Clear all values that has previously been set.
- mCarrierConfigManager.overrideConfig(subId, null);
+ mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
getOutPrintWriter()
.println("All previously set carrier config override values has been cleared");
return 0;