Integrate RCS provisioning updates into SipTransport
Bug: 173828167
Test: atest TeleServiceTests:com.android.phone.RcsProvisioningMonitorTest
Test: atest TeleServiceTests:com.android.services.telephony.rcs.SipTransportControllerTest
Merged-In: I4b7e9ee4017f78cb465723592d8dcfa618f69421
Change-Id: I4b7e9ee4017f78cb465723592d8dcfa618f69421
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index ebe6c4d..9a1e275 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -9884,6 +9884,30 @@
}
/**
+ * Overrides the ims feature validation result
+ */
+ @Override
+ public boolean setImsFeatureValidationOverride(int subId, String enabledStr) {
+ TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
+ "setImsFeatureValidationOverride");
+
+ Boolean enabled = "NULL".equalsIgnoreCase(enabledStr) ? null
+ : Boolean.parseBoolean(enabledStr);
+ return RcsProvisioningMonitor.getInstance().overrideImsFeatureValidation(
+ subId, enabled);
+ }
+
+ /**
+ * Gets the ims feature validation override value
+ */
+ @Override
+ public boolean getImsFeatureValidationOverride(int subId) {
+ TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
+ "getImsFeatureValidationOverride");
+ return RcsProvisioningMonitor.getInstance().getImsFeatureValidationOverride(subId);
+ }
+
+ /**
* Get the mobile provisioning url that is used to launch a browser to allow users to manage
* their mobile plan.
*/
diff --git a/src/com/android/phone/RcsProvisioningMonitor.java b/src/com/android/phone/RcsProvisioningMonitor.java
index bcf1491..6fdde78 100644
--- a/src/com/android/phone/RcsProvisioningMonitor.java
+++ b/src/com/android/phone/RcsProvisioningMonitor.java
@@ -73,6 +73,7 @@
private static final int EVENT_DEVICE_CONFIG_OVERRIDE = 6;
private static final int EVENT_CARRIER_CONFIG_OVERRIDE = 7;
private static final int EVENT_RESET = 8;
+ private static final int EVENT_FEATURE_ENABLED_OVERRIDE = 9;
private final PhoneGlobals mPhone;
private final Handler mHandler;
@@ -82,6 +83,8 @@
private Boolean mDeviceSingleRegistrationEnabledOverride;
private final HashMap<Integer, Boolean> mCarrierSingleRegistrationEnabledOverride =
new HashMap<>();
+ private final ConcurrentHashMap<Integer, Boolean> mImsFeatureValidationOverride =
+ new ConcurrentHashMap<>();
private String mDmaPackageName;
private final SparseArray<RcsFeatureListener> mRcsFeatureListeners = new SparseArray<>();
private volatile boolean mTestModeEnabled;
@@ -626,6 +629,18 @@
}
/**
+ * override the rcs feature validation result for a subscription
+ */
+ public boolean overrideImsFeatureValidation(int subId, Boolean enabled) {
+ if (enabled == null) {
+ mImsFeatureValidationOverride.remove(subId);
+ } else {
+ mImsFeatureValidationOverride.put(subId, enabled);
+ }
+ return true;
+ }
+
+ /**
* Returns the device config whether single registration is enabled
*/
public boolean getDeviceSingleRegistrationEnabled() {
@@ -647,6 +662,13 @@
return false;
}
+ /**
+ * Returns the rcs feature validation override value, null if it is not set.
+ */
+ public Boolean getImsFeatureValidationOverride(int subId) {
+ return mImsFeatureValidationOverride.get(subId);
+ }
+
private void onDefaultMessagingApplicationChanged() {
final String packageName = getDmaPackageName();
if (!TextUtils.equals(mDmaPackageName, packageName)) {
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index b2e1a99..36d539a 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -113,6 +113,8 @@
private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
+ private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
+ private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
private static final String D2D_SUBCOMMAND = "d2d";
private static final String D2D_SEND = "send";
@@ -532,6 +534,17 @@
pw.println(" Options are:");
pw.println(" -s: The SIM slot ID to read the config value for. If no option");
pw.println(" is specified, it will choose the default voice SIM slot.");
+ pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
+ pw.println(" Sets ims feature validation result.");
+ pw.println(" The value could be true, false, or null(undefined).");
+ pw.println(" Options are:");
+ pw.println(" -s: The SIM slot ID to set the config value for. If no option");
+ pw.println(" is specified, it will choose the default voice SIM slot.");
+ pw.println(" src get-feature-validation [-s SLOT_ID]");
+ pw.println(" Gets ims feature validation override value.");
+ pw.println(" Options are:");
+ pw.println(" -s: The SIM slot ID to read the config value for. If no option");
+ pw.println(" is specified, it will choose the default voice SIM slot.");
}
private int handleImsCommand() {
@@ -1765,6 +1778,12 @@
case SRC_GET_CARRIER_ENABLED: {
return handleSrcGetCarrierEnabledCommand();
}
+ case SRC_SET_FEATURE_ENABLED: {
+ return handleSrcSetFeatureValidationCommand();
+ }
+ case SRC_GET_FEATURE_ENABLED: {
+ return handleSrcGetFeatureValidationCommand();
+ }
}
return -1;
@@ -2088,6 +2107,55 @@
return 0;
}
+ private int handleSrcSetFeatureValidationCommand() {
+ //the release time value could be -1
+ int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
+ : SubscriptionManager.getDefaultSubscriptionId();
+ if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ return -1;
+ }
+
+ String enabledStr = getNextArg();
+ if (enabledStr == null) {
+ return -1;
+ }
+
+ try {
+ boolean result =
+ mInterface.setImsFeatureValidationOverride(subId, enabledStr);
+ if (VDBG) {
+ Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
+ + enabledStr + ", result=" + result);
+ }
+ getOutPrintWriter().println(result);
+ } catch (NumberFormatException | RemoteException e) {
+ Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
+ + enabledStr + ", error" + e.getMessage());
+ getErrPrintWriter().println("Exception: " + e.getMessage());
+ return -1;
+ }
+ return 0;
+ }
+
+ private int handleSrcGetFeatureValidationCommand() {
+ int subId = getSubId("src get-feature-validation");
+ if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ return -1;
+ }
+
+ Boolean result = false;
+ try {
+ result = mInterface.getImsFeatureValidationOverride(subId);
+ } catch (RemoteException e) {
+ return -1;
+ }
+ if (VDBG) {
+ Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
+ }
+ getOutPrintWriter().println(result);
+ return 0;
+ }
+
private int handleHasCarrierPrivilegesCommand() {
String packageName = getNextArgRequired();
diff --git a/src/com/android/services/telephony/rcs/SipTransportController.java b/src/com/android/services/telephony/rcs/SipTransportController.java
index a948cdb..cecc8a2 100644
--- a/src/com/android/services/telephony/rcs/SipTransportController.java
+++ b/src/com/android/services/telephony/rcs/SipTransportController.java
@@ -19,8 +19,10 @@
import android.app.role.OnRoleHoldersChangedListener;
import android.app.role.RoleManager;
import android.content.Context;
+import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.telephony.CarrierConfigManager;
import android.telephony.ims.DelegateRequest;
import android.telephony.ims.FeatureTagState;
import android.telephony.ims.ImsException;
@@ -44,12 +46,14 @@
import com.android.ims.RcsFeatureManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.phone.RcsProvisioningMonitor;
import com.google.common.base.Objects;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
@@ -247,6 +251,10 @@
private RcsFeatureManager mRcsManager;
// Cached package name of the app that is considered the default SMS app.
private String mCachedSmsRolePackageName = "";
+ // Callback to monitor rcs provisioning change
+ private CarrierConfigManager mCarrierConfigManager;
+ // Cached allowed feature tags from carrier config
+ ArraySet<String> mFeatureTagsAllowed = new ArraySet<>();
/**
* Create an instance of SipTransportController.
@@ -261,6 +269,7 @@
mRoleManagerAdapter = new RoleManagerAdapterImpl(context);
mTimerAdapter = new TimerAdapterImpl();
mExecutorService = Executors.newSingleThreadScheduledExecutor();
+ mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
}
/**
@@ -277,6 +286,7 @@
mTimerAdapter = timerAdapter;
mDelegateControllerFactory = delegateFactory;
mExecutorService = executor;
+ mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
logi("created");
}
@@ -813,21 +823,14 @@
}
ArraySet<String> previouslyGrantedTags = new ArraySet<>(alreadyRequestedTags);
- // deny tags already used by other delegates
- Set<FeatureTagState> deniedTags = new ArraySet<>();
- for (String s : requestedFeatureTags) {
- if (previouslyGrantedTags.contains(s)) {
- deniedTags.add(new FeatureTagState(s,
- SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE));
- }
- }
- Set<String> nonDeniedTags = requestedFeatureTags.stream()
- .filter(r -> !previouslyGrantedTags.contains(r))
- .collect(Collectors.toSet());
+ ArraySet<String> candidateFeatureTags = new ArraySet<>(requestedFeatureTags);
+ Set<FeatureTagState> deniedTags =
+ updateSupportedTags(candidateFeatureTags, previouslyGrantedTags);
+
// Add newly granted tags to the already requested tags list.
- previouslyGrantedTags.addAll(nonDeniedTags);
+ previouslyGrantedTags.addAll(candidateFeatureTags);
CompletableFuture<Boolean> pendingChange = controller.changeSupportedFeatureTags(
- nonDeniedTags, deniedTags);
+ candidateFeatureTags, deniedTags);
logi("changeSupportedFeatureTags pendingChange=" + pendingChange);
// do not worry about executor used here, this stage used to interpret result + add log.
return pendingChange.thenApply((completedSuccessfully) -> {
@@ -838,6 +841,51 @@
}
/**
+ * Update candidate feature tags according to feature tags allowed by carrier config,
+ * and previously granted by other SipDelegates.
+ *
+ * @param candidateFeatureTags The candidate feature tags to be updated. It will be
+ * updated as needed per the carrier config and previously granted feature tags.
+ * @param previouslyGrantedTags The feature tags already granted by other SipDelegates.
+ * @return The set of denied feature tags.
+ */
+ private Set<FeatureTagState> updateSupportedTags(Set<String> candidateFeatureTags,
+ Set<String> previouslyGrantedTags) {
+ Boolean overrideRes = RcsProvisioningMonitor.getInstance()
+ .getImsFeatureValidationOverride(mSubId);
+ // deny tags already used by other delegates
+ Set<FeatureTagState> deniedTags = new ArraySet<>();
+
+ // match config if feature validation is not overridden
+ if (overrideRes == null) {
+ Iterator<String> it = candidateFeatureTags.iterator();
+ while (it.hasNext()) {
+ String tag = it.next();
+ if (previouslyGrantedTags.contains(tag)) {
+ logi(tag + " has already been granted previously.");
+ it.remove();
+ deniedTags.add(new FeatureTagState(tag,
+ SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE));
+ } else if (!mFeatureTagsAllowed.contains(tag.trim().toLowerCase())) {
+ logi(tag + " is not allowed per config.");
+ it.remove();
+ deniedTags.add(new FeatureTagState(tag,
+ SipDelegateManager.DENIED_REASON_NOT_ALLOWED));
+ }
+ }
+ } else if (Boolean.FALSE.equals(overrideRes)) {
+ logi("all features are denied for test purpose.");
+ for (String s : candidateFeatureTags) {
+ deniedTags.add(new FeatureTagState(s,
+ SipDelegateManager.DENIED_REASON_NOT_ALLOWED));
+ }
+ candidateFeatureTags.clear();
+ }
+
+ return deniedTags;
+ }
+
+ /**
* Run a Callable on the ExecutorService Thread and wait for the result.
* If an ImsException is thrown, catch it and rethrow it to caller.
*/
@@ -918,6 +966,8 @@
scheduleDestroyDelegates(
SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN);
}
+
+ onCarrierConfigChangedInternal();
}
/**
@@ -925,6 +975,15 @@
*/
private void onCarrierConfigChangedInternal() {
logi("Carrier Config changed for subId: " + mSubId);
+ mFeatureTagsAllowed.clear();
+ PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
+ String[] tagConfigs = carrierConfig.getStringArray(
+ CarrierConfigManager.Ims.KEY_RCS_FEATURE_TAG_ALLOWED_STRING_ARRAY);
+ if (tagConfigs != null && tagConfigs.length > 0) {
+ for (String tag : tagConfigs) {
+ mFeatureTagsAllowed.add(tag.trim().toLowerCase());
+ }
+ }
}
/**