Notify rcs config as needed when RCS service ready, and support test mode
Bug: 180503768
Bug: 181054754
Test: atest TeleServiceTests:com.android.phone.RcsProvisioningMonitorTest
Merged-In: Icef61a850c679334a8279f0e28e5110f867b75c1
Change-Id: Icef61a850c679334a8279f0e28e5110f867b75c1
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 111a38c..eac13bb 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -9820,6 +9820,28 @@
}
/**
+ * Enables or disables the test mode for RCS VoLTE single registration.
+ */
+ @Override
+ public void setRcsSingleRegistrationTestModeEnabled(boolean enabled) {
+ TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
+ "setRcsSingleRegistrationTestModeEnabled");
+
+ RcsProvisioningMonitor.getInstance().setTestModeEnabled(enabled);
+ }
+
+ /**
+ * Gets the test mode for RCS VoLTE single registration.
+ */
+ @Override
+ public boolean getRcsSingleRegistrationTestModeEnabled() {
+ TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
+ "getRcsSingleRegistrationTestModeEnabled");
+
+ return RcsProvisioningMonitor.getInstance().getTestModeEnabled();
+ }
+
+ /**
* Overrides the config of RCS VoLTE single registration enabled for the device.
*/
@Override
diff --git a/src/com/android/phone/RcsProvisioningMonitor.java b/src/com/android/phone/RcsProvisioningMonitor.java
index 79310ef..13dddec 100644
--- a/src/com/android/phone/RcsProvisioningMonitor.java
+++ b/src/com/android/phone/RcsProvisioningMonitor.java
@@ -38,15 +38,20 @@
import android.telephony.ims.RcsConfig;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IRcsConfigCallback;
-import android.telephony.ims.feature.ImsFeature;
import android.text.TextUtils;
+import android.util.ArraySet;
+import android.util.SparseArray;
+import com.android.ims.FeatureConnector;
+import com.android.ims.FeatureUpdates;
+import com.android.ims.RcsFeatureManager;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.util.HandlerExecutor;
import com.android.internal.util.CollectionUtils;
import com.android.telephony.Rlog;
+import java.util.Arrays;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
@@ -66,6 +71,7 @@
private static final int EVENT_RECONFIG_REQUEST = 5;
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 final PhoneGlobals mPhone;
private final Handler mHandler;
@@ -76,12 +82,15 @@
private final HashMap<Integer, Boolean> mCarrierSingleRegistrationEnabledOverride =
new HashMap<>();
private String mDmaPackageName;
+ private final SparseArray<RcsFeatureListener> mRcsFeatureListeners = new SparseArray<>();
+ private volatile boolean mTestModeEnabled;
private final CarrierConfigManager mCarrierConfigManager;
private final DmaChangedListener mDmaChangedListener;
private final SubscriptionManager mSubscriptionManager;
private final TelephonyRegistryManager mTelephonyRegistryManager;
private final RoleManagerAdapter mRoleManager;
+ private FeatureConnectorFactory<RcsFeatureManager> mFeatureFactory;
private static RcsProvisioningMonitor sInstance;
@@ -146,6 +155,7 @@
@Override
public void handleMessage(Message msg) {
+ logv("handleMessage: " + msg);
switch (msg.what) {
case EVENT_SUB_CHANGED:
onSubChanged();
@@ -177,6 +187,9 @@
onCarrierConfigChange();
}
break;
+ case EVENT_RESET:
+ reset();
+ break;
default:
loge("Unhandled event " + msg.what);
}
@@ -187,13 +200,20 @@
private int mSubId;
private volatile int mSingleRegistrationCapability;
private volatile byte[] mConfig;
- private HashSet<IRcsConfigCallback> mRcsConfigCallbacks;
+ private ArraySet<IRcsConfigCallback> mRcsConfigCallbacks;
+ private IImsConfig mIImsConfig;
+ private boolean mHasReconfigRequest;
RcsProvisioningInfo(int subId, int singleRegistrationCapability, byte[] config) {
mSubId = subId;
mSingleRegistrationCapability = singleRegistrationCapability;
mConfig = config;
- mRcsConfigCallbacks = new HashSet<>();
+ mRcsConfigCallbacks = new ArraySet<>();
+ registerRcsFeatureListener(this);
+ }
+
+ int getSubId() {
+ return mSubId;
}
void setSingleRegistrationCapability(int singleRegistrationCapability) {
@@ -205,7 +225,14 @@
}
void setConfig(byte[] config) {
- mConfig = config;
+ if (!Arrays.equals(mConfig, config)) {
+ mConfig = config;
+ if (mConfig != null) {
+ notifyRcsAutoConfigurationReceived();
+ } else {
+ notifyRcsAutoConfigurationRemoved();
+ }
+ }
}
byte[] getConfig() {
@@ -213,15 +240,14 @@
}
boolean addRcsConfigCallback(IRcsConfigCallback cb) {
- IImsConfig imsConfig = getIImsConfig(mSubId, ImsFeature.FEATURE_RCS);
- if (imsConfig == null) {
+ if (mIImsConfig == null) {
logd("fail to addRcsConfigCallback as imsConfig is null");
return false;
}
synchronized (mRcsConfigCallbacks) {
try {
- imsConfig.addRcsConfigCallback(cb);
+ mIImsConfig.addRcsConfigCallback(cb);
} catch (RemoteException e) {
loge("fail to addRcsConfigCallback due to " + e);
return false;
@@ -233,12 +259,11 @@
boolean removeRcsConfigCallback(IRcsConfigCallback cb) {
boolean result = true;
- IImsConfig imsConfig = getIImsConfig(mSubId, ImsFeature.FEATURE_RCS);
synchronized (mRcsConfigCallbacks) {
- if (imsConfig != null) {
+ if (mIImsConfig != null) {
try {
- imsConfig.removeRcsConfigCallback(cb);
+ mIImsConfig.removeRcsConfigCallback(cb);
} catch (RemoteException e) {
loge("fail to removeRcsConfigCallback due to " + e);
}
@@ -257,16 +282,89 @@
return result;
}
+ void triggerRcsReconfiguration() {
+ if (mIImsConfig != null) {
+ try {
+ logv("triggerRcsReconfiguration for sub:" + mSubId);
+ mIImsConfig.triggerRcsReconfiguration();
+ mHasReconfigRequest = false;
+ } catch (RemoteException e) {
+ loge("triggerRcsReconfiguration failed due to " + e);
+ }
+ } else {
+ logd("triggerRcsReconfiguration failed due to IImsConfig null.");
+ mHasReconfigRequest = true;
+ }
+ }
+
+ void destroy() {
+ unregisterRcsFeatureListener(this);
+ clear();
+ mIImsConfig = null;
+ mRcsConfigCallbacks = null;
+ }
+
void clear() {
setConfig(null);
+ clearCallbacks();
+ }
+
+ void onRcsStatusChanged(IImsConfig binder) {
+ logv("onRcsStatusChanged for sub:" + mSubId + ", IImsConfig?" + binder);
+ if (mIImsConfig != binder) {
+ mIImsConfig = binder;
+ if (mIImsConfig != null) {
+ if (mHasReconfigRequest) {
+ triggerRcsReconfiguration();
+ } else {
+ notifyRcsAutoConfigurationReceived();
+ }
+ } else {
+ // clear callbacks if rcs disconnected
+ clearCallbacks();
+ }
+ }
+ }
+
+ private void notifyRcsAutoConfigurationReceived() {
+ if (mConfig == null) {
+ logd("Rcs config is null for sub : " + mSubId);
+ return;
+ }
+
+ if (mIImsConfig != null) {
+ try {
+ logv("notifyRcsAutoConfigurationReceived for sub:" + mSubId);
+ mIImsConfig.notifyRcsAutoConfigurationReceived(mConfig, false);
+ } catch (RemoteException e) {
+ loge("notifyRcsAutoConfigurationReceived failed due to " + e);
+ }
+ } else {
+ logd("notifyRcsAutoConfigurationReceived failed due to IImsConfig null.");
+ }
+ }
+
+ private void notifyRcsAutoConfigurationRemoved() {
+ if (mIImsConfig != null) {
+ try {
+ logv("notifyRcsAutoConfigurationRemoved for sub:" + mSubId);
+ mIImsConfig.notifyRcsAutoConfigurationRemoved();
+ } catch (RemoteException e) {
+ loge("notifyRcsAutoConfigurationRemoved failed due to " + e);
+ }
+ } else {
+ logd("notifyRcsAutoConfigurationRemoved failed due to IImsConfig null.");
+ }
+ }
+
+ private void clearCallbacks() {
synchronized (mRcsConfigCallbacks) {
- IImsConfig imsConfig = getIImsConfig(mSubId, ImsFeature.FEATURE_RCS);
Iterator<IRcsConfigCallback> it = mRcsConfigCallbacks.iterator();
while (it.hasNext()) {
IRcsConfigCallback cb = it.next();
- if (imsConfig != null) {
+ if (mIImsConfig != null) {
try {
- imsConfig.removeRcsConfigCallback(cb);
+ mIImsConfig.removeRcsConfigCallback(cb);
} catch (RemoteException e) {
loge("fail to removeRcsConfigCallback due to " + e);
}
@@ -283,7 +381,61 @@
}
@VisibleForTesting
- public RcsProvisioningMonitor(PhoneGlobals app, Looper looper, RoleManagerAdapter roleManager) {
+ public interface FeatureConnectorFactory<U extends FeatureUpdates> {
+ /**
+ * @return a {@link FeatureConnector} associated for the given {@link FeatureUpdates}
+ * and slot index.
+ */
+ FeatureConnector<U> create(Context context, int slotIndex,
+ FeatureConnector.Listener<U> listener, Executor executor, String logPrefix);
+ }
+
+ private final class RcsFeatureListener implements FeatureConnector.Listener<RcsFeatureManager> {
+ private final ArraySet<RcsProvisioningInfo> mRcsProvisioningInfos = new ArraySet<>();
+ private RcsFeatureManager mRcsFeatureManager;
+ private FeatureConnector<RcsFeatureManager> mConnector;
+
+ RcsFeatureListener(int slotId) {
+ mConnector = mFeatureFactory.create(
+ mPhone, slotId, this, new HandlerExecutor(mHandler), TAG);
+ mConnector.connect();
+ }
+
+ void destroy() {
+ mConnector.disconnect();
+ mConnector = null;
+ mRcsFeatureManager = null;
+ mRcsProvisioningInfos.clear();
+ }
+
+ void addRcsProvisioningInfo(RcsProvisioningInfo info) {
+ if (!mRcsProvisioningInfos.contains(info)) {
+ mRcsProvisioningInfos.add(info);
+ info.onRcsStatusChanged(mRcsFeatureManager == null ? null
+ : mRcsFeatureManager.getConfig());
+ }
+ }
+
+ void removeRcsProvisioningInfo(RcsProvisioningInfo info) {
+ mRcsProvisioningInfos.remove(info);
+ }
+
+ @Override
+ public void connectionReady(RcsFeatureManager manager) {
+ mRcsFeatureManager = manager;
+ mRcsProvisioningInfos.forEach(v -> v.onRcsStatusChanged(manager.getConfig()));
+ }
+
+ @Override
+ public void connectionUnavailable(int reason) {
+ mRcsFeatureManager = null;
+ mRcsProvisioningInfos.forEach(v -> v.onRcsStatusChanged(null));
+ }
+ }
+
+ @VisibleForTesting
+ public RcsProvisioningMonitor(PhoneGlobals app, Looper looper, RoleManagerAdapter roleManager,
+ FeatureConnectorFactory<RcsFeatureManager> factory) {
mPhone = app;
mHandler = new MyHandler(looper);
mCarrierConfigManager = mPhone.getSystemService(CarrierConfigManager.class);
@@ -292,15 +444,9 @@
mRoleManager = roleManager;
mDmaPackageName = getDmaPackageName();
logv("DMA is " + mDmaPackageName);
- IntentFilter filter = new IntentFilter();
- filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
- mPhone.registerReceiver(mReceiver, filter);
- mTelephonyRegistryManager.addOnSubscriptionsChangedListener(
- mSubChangedListener, mSubChangedListener.getHandlerExecutor());
mDmaChangedListener = new DmaChangedListener();
- mDmaChangedListener.register();
- //initialize configs for all active sub
- onSubChanged();
+ mFeatureFactory = factory;
+ init();
}
/**
@@ -312,7 +458,7 @@
HandlerThread handlerThread = new HandlerThread(TAG);
handlerThread.start();
sInstance = new RcsProvisioningMonitor(app, handlerThread.getLooper(),
- new RoleManagerAdapterImpl(app));
+ new RoleManagerAdapterImpl(app), RcsFeatureManager::getConnector);
}
return sInstance;
}
@@ -324,15 +470,44 @@
return sInstance;
}
+ private void init() {
+ logd("init.");
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+ mPhone.registerReceiver(mReceiver, filter);
+ mTelephonyRegistryManager.addOnSubscriptionsChangedListener(
+ mSubChangedListener, mSubChangedListener.getHandlerExecutor());
+ mDmaChangedListener.register();
+ //initialize configs for all active sub
+ onSubChanged();
+ }
+
+ private void release() {
+ logd("release.");
+ mDmaChangedListener.unregister();
+ mTelephonyRegistryManager.removeOnSubscriptionsChangedListener(mSubChangedListener);
+ mPhone.unregisterReceiver(mReceiver);
+ for (int i = 0; i < mRcsFeatureListeners.size(); i++) {
+ mRcsFeatureListeners.valueAt(i).destroy();
+ }
+ mRcsFeatureListeners.clear();
+ mRcsProvisioningInfos.forEach((k, v)->v.destroy());
+ mRcsProvisioningInfos.clear();
+ mCarrierSingleRegistrationEnabledOverride.clear();
+ }
+
+ private void reset() {
+ release();
+ init();
+ }
+
/**
* destroy the instance
*/
@VisibleForTesting
public void destroy() {
logd("destroy it.");
- mDmaChangedListener.unregister();
- mTelephonyRegistryManager.removeOnSubscriptionsChangedListener(mSubChangedListener);
- mPhone.unregisterReceiver(mReceiver);
+ release();
mHandler.getLooper().quit();
}
@@ -410,6 +585,27 @@
}
/**
+ * Enables or disables test mode.
+ *
+ * <p> If test mode is enabled, any rcs config change will not update the database.
+ */
+ public void setTestModeEnabled(boolean enabled) {
+ logv("setTestModeEnabled as " + enabled);
+ if (mTestModeEnabled != enabled) {
+ mTestModeEnabled = enabled;
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_RESET));
+ }
+ }
+
+
+ /**
+ * Returns whether the test mode is enabled.
+ */
+ public boolean getTestModeEnabled() {
+ return mTestModeEnabled;
+ }
+
+ /**
* override the device config whether single registration is enabled
*/
public void overrideDeviceSingleRegistrationEnabled(Boolean enabled) {
@@ -462,61 +658,29 @@
v.clear();
if (isAcsUsed(k)) {
logv("acs used, trigger to re-configure.");
- notifyRcsAutoConfigurationRemoved(k);
- triggerRcsReconfiguration(k);
+ updateConfigForSub(k, null, true);
+ v.triggerRcsReconfiguration();
} else {
+ logv("acs not used, set cached config and notify.");
v.setConfig(cachedConfig);
- logv("acs not used, notify.");
- notifyRcsAutoConfigurationReceived(k, v.getConfig(), false);
}
});
}
}
- private void notifyRcsAutoConfigurationReceived(int subId, byte[] config,
- boolean isCompressed) {
- if (config == null) {
- logd("Rcs config is null for sub : " + subId);
- return;
- }
-
- IImsConfig imsConfig = getIImsConfig(subId, ImsFeature.FEATURE_RCS);
- if (imsConfig != null) {
- try {
- imsConfig.notifyRcsAutoConfigurationReceived(config, isCompressed);
- } catch (RemoteException e) {
- loge("fail to notify rcs configuration received!");
- }
- } else {
- logd("getIImsConfig returns null.");
+ private void updateConfigForSub(int subId, byte[] config, boolean isCompressed) {
+ logv("updateConfigForSub, subId:" + subId + ", mTestModeEnabled:" + mTestModeEnabled);
+ if (!mTestModeEnabled) {
+ RcsConfig.updateConfigForSub(mPhone, subId, config, isCompressed);
}
}
- private void notifyRcsAutoConfigurationRemoved(int subId) {
- RcsConfig.updateConfigForSub(mPhone, subId, null, true);
- IImsConfig imsConfig = getIImsConfig(subId, ImsFeature.FEATURE_RCS);
- if (imsConfig != null) {
- try {
- imsConfig.notifyRcsAutoConfigurationRemoved();
- } catch (RemoteException e) {
- loge("fail to notify rcs configuration removed!");
- }
- } else {
- logd("getIImsConfig returns null.");
+ private byte[] loadConfigForSub(int subId) {
+ logv("loadConfigForSub, subId:" + subId + ", mTestModeEnabled:" + mTestModeEnabled);
+ if (!mTestModeEnabled) {
+ return RcsConfig.loadRcsConfigForSub(mPhone, subId, false);
}
- }
-
- private void triggerRcsReconfiguration(int subId) {
- IImsConfig imsConfig = getIImsConfig(subId, ImsFeature.FEATURE_RCS);
- if (imsConfig != null) {
- try {
- imsConfig.triggerRcsReconfiguration();
- } catch (RemoteException e) {
- loge("fail to trigger rcs reconfiguration!");
- }
- } else {
- logd("getIImsConfig returns null.");
- }
+ return null;
}
private boolean isAcsUsed(int subId) {
@@ -568,26 +732,25 @@
private void onSubChanged() {
final int[] activeSubs = mSubscriptionManager.getActiveSubscriptionIdList();
- final HashSet<Integer> subsToBeDeactivated = new HashSet<>(mRcsProvisioningInfos.keySet());
+ final ArraySet<Integer> subsToBeDeactivated =
+ new ArraySet<>(mRcsProvisioningInfos.keySet());
for (int i : activeSubs) {
subsToBeDeactivated.remove(i);
if (!mRcsProvisioningInfos.containsKey(i)) {
- byte[] data = RcsConfig.loadRcsConfigForSub(mPhone, i, false);
+ byte[] data = loadConfigForSub(i);
int capability = getSingleRegistrationCapableValue(i);
logv("new info is created for sub : " + i + ", single registration capability :"
+ capability + ", rcs config : " + data);
mRcsProvisioningInfos.put(i, new RcsProvisioningInfo(i, capability, data));
- notifyRcsAutoConfigurationReceived(i, data, false);
notifyDmaForSub(i, capability);
}
}
subsToBeDeactivated.forEach(i -> {
RcsProvisioningInfo info = mRcsProvisioningInfos.remove(i);
- notifyRcsAutoConfigurationRemoved(i);
if (info != null) {
- info.clear();
+ info.destroy();
}
});
}
@@ -596,11 +759,8 @@
logv("onConfigReceived, subId:" + subId + ", config:"
+ config + ", isCompressed:" + isCompressed);
RcsProvisioningInfo info = mRcsProvisioningInfos.get(subId);
- if (info != null) {
- info.setConfig(isCompressed ? RcsConfig.decompressGzip(config) : config);
- }
- RcsConfig.updateConfigForSub(mPhone, subId, config, isCompressed);
- notifyRcsAutoConfigurationReceived(subId, config, isCompressed);
+ info.setConfig(isCompressed ? RcsConfig.decompressGzip(config) : config);
+ updateConfigForSub(subId, config, isCompressed);
}
private void onReconfigRequest(int subId) {
@@ -608,9 +768,10 @@
RcsProvisioningInfo info = mRcsProvisioningInfos.get(subId);
if (info != null) {
info.setConfig(null);
+ // clear rcs config stored in db
+ updateConfigForSub(subId, null, true);
+ info.triggerRcsReconfiguration();
}
- notifyRcsAutoConfigurationRemoved(subId);
- triggerRcsReconfiguration(subId);
}
private void notifyDmaForSub(int subId, int capability) {
@@ -620,7 +781,14 @@
intent.putExtra(ProvisioningManager.EXTRA_SUBSCRIPTION_ID, subId);
intent.putExtra(ProvisioningManager.EXTRA_STATUS, capability);
logv("notify " + intent);
- mPhone.sendBroadcast(intent);
+ // Only send permission to the default sms app if it has the correct permissions
+ // except test mode enabled
+ if (!mTestModeEnabled) {
+ //mPhone.sendBroadcast(intent, Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION);
+ mPhone.sendBroadcast(intent);
+ } else {
+ mPhone.sendBroadcast(intent);
+ }
}
private IImsConfig getIImsConfig(int subId, int feature) {
@@ -637,6 +805,24 @@
}
}
+ void registerRcsFeatureListener(RcsProvisioningInfo info) {
+ int slotId = SubscriptionManager.getSlotIndex(info.getSubId());
+ RcsFeatureListener cb = mRcsFeatureListeners.get(slotId);
+ if (cb == null) {
+ cb = new RcsFeatureListener(slotId);
+ mRcsFeatureListeners.put(slotId, cb);
+ }
+ cb.addRcsProvisioningInfo(info);
+ }
+
+ void unregisterRcsFeatureListener(RcsProvisioningInfo info) {
+ int slotId = SubscriptionManager.getSlotIndex(info.getSubId());
+ RcsFeatureListener cb = mRcsFeatureListeners.get(slotId);
+ if (cb != null) {
+ cb.removeRcsProvisioningInfo(info);
+ }
+ }
+
private static boolean booleanEquals(Boolean val1, Boolean val2) {
return (val1 == null && val2 == null)
|| (Boolean.TRUE.equals(val1) && Boolean.TRUE.equals(val2))
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 8acfd1d..74d6b57 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -102,6 +102,8 @@
private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
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 D2D_SUBCOMMAND = "d2d";
private static final String D2D_SEND = "send";
@@ -417,6 +419,11 @@
private void onHelpSrc() {
PrintWriter pw = getOutPrintWriter();
pw.println("RCS VoLTE Single Registration Config Commands:");
+ pw.println(" src set-test-enabled true|false");
+ pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
+ pw.println(" The value could be true, false, or null(undefined).");
+ pw.println(" src get-test-enabled");
+ pw.println(" Gets the test mode for RCS VoLTE single registration.");
pw.println(" src set-device-enabled true|false|null");
pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
pw.println(" The value could be true, false, or null(undefined).");
@@ -1618,6 +1625,12 @@
}
switch (arg) {
+ case SRC_SET_TEST_ENABLED: {
+ return handleSrcSetTestEnabledCommand();
+ }
+ case SRC_GET_TEST_ENABLED: {
+ return handleSrcGetTestEnabledCommand();
+ }
case SRC_SET_DEVICE_ENABLED: {
return handleSrcSetDeviceEnabledCommand();
}
@@ -1737,6 +1750,40 @@
return 0;
}
+ private int handleSrcSetTestEnabledCommand() {
+ String enabledStr = getNextArg();
+ if (enabledStr == null) {
+ return -1;
+ }
+
+ try {
+ mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
+ if (VDBG) {
+ Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
+ }
+ getOutPrintWriter().println("Done");
+ } catch (NumberFormatException | RemoteException e) {
+ Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
+ getErrPrintWriter().println("Exception: " + e.getMessage());
+ return -1;
+ }
+ return 0;
+ }
+
+ private int handleSrcGetTestEnabledCommand() {
+ boolean result = false;
+ try {
+ result = mInterface.getRcsSingleRegistrationTestModeEnabled();
+ } catch (RemoteException e) {
+ return -1;
+ }
+ if (VDBG) {
+ Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
+ }
+ getOutPrintWriter().println(result);
+ return 0;
+ }
+
private int handleSrcSetDeviceEnabledCommand() {
String enabledStr = getNextArg();
if (enabledStr == null) {
diff --git a/tests/src/com/android/phone/RcsProvisioningMonitorTest.java b/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
index 6c36c2c..d72b348 100644
--- a/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
+++ b/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
@@ -55,20 +55,21 @@
import android.telephony.ims.RcsConfig;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IRcsConfigCallback;
-import android.telephony.ims.feature.ImsFeature;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.TestableLooper;
import android.util.Log;
+import com.android.ims.FeatureConnector;
+import com.android.ims.RcsFeatureManager;
import com.android.internal.telephony.ITelephony;
-import com.android.internal.telephony.ims.ImsResolver;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
@@ -130,7 +131,13 @@
@Mock
private ITelephony.Stub mITelephony;
@Mock
- private ImsResolver mImsResolver;
+ private RcsFeatureManager mFeatureManager;
+ @Mock
+ private RcsProvisioningMonitor.FeatureConnectorFactory<RcsFeatureManager> mFeatureFactory;
+ @Mock
+ private FeatureConnector<RcsFeatureManager> mFeatureConnector;
+ @Captor
+ ArgumentCaptor<FeatureConnector.Listener<RcsFeatureManager>> mConnectorListener;
@Mock
private IImsConfig.Stub mIImsConfig;
@Mock
@@ -246,8 +253,7 @@
when(mCursor.getColumnIndexOrThrow(any())).thenReturn(1);
when(mCursor.getBlob(anyInt())).thenReturn(
RcsConfig.compressGzip(SAMPLE_CONFIG.getBytes()));
- when(mPhone.getImsResolver()).thenReturn(mImsResolver);
- when(mImsResolver.getImsConfig(anyInt(), anyInt())).thenReturn(mIImsConfig);
+
mHandlerThread = new HandlerThread("RcsProvisioningMonitorTest");
mHandlerThread.start();
}
@@ -268,8 +274,9 @@
@Test
@SmallTest
public void testInitWithSavedConfig() throws Exception {
- createMonitor(3);
ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class);
+ createMonitor(3);
+
for (int i = 0; i < 3; i++) {
assertTrue(Arrays.equals(SAMPLE_CONFIG.getBytes(),
mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE + i)));
@@ -279,8 +286,6 @@
Intent capturedIntent = captorIntent.getAllValues().get(1);
assertEquals(ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE,
capturedIntent.getAction());
- PhoneGlobals.getInstance().getImsResolver();
- verify(mPhone, atLeastOnce()).getImsResolver();
verify(mIImsConfig, times(3)).notifyRcsAutoConfigurationReceived(any(), anyBoolean());
}
@@ -293,6 +298,7 @@
verify(mPhone, times(3)).sendBroadcast(captorIntent.capture());
Intent capturedIntent = captorIntent.getAllValues().get(1);
+
assertEquals(ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE,
capturedIntent.getAction());
//Should not notify null config
@@ -304,8 +310,7 @@
public void testSubInfoChanged() throws Exception {
createMonitor(3);
ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class);
- mExecutor.execute(() -> mSubChangedListener.onSubscriptionsChanged());
- processAllMessages();
+
for (int i = 0; i < 3; i++) {
assertTrue(Arrays.equals(SAMPLE_CONFIG.getBytes(),
mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE + i)));
@@ -354,7 +359,7 @@
byte[] configCached = mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE);
assertTrue(Arrays.equals(SAMPLE_CONFIG.getBytes(), configCached));
- verify(mIImsConfig, never()).notifyRcsAutoConfigurationRemoved();
+ verify(mIImsConfig, times(1)).notifyRcsAutoConfigurationRemoved();
// The api should be called 2 times, one happens when monitor is initilized,
// Another happens when DMS is changed.
verify(mIImsConfig, times(2))
@@ -419,8 +424,6 @@
mRcsProvisioningMonitor.updateConfig(FAKE_SUB_ID_BASE, SAMPLE_CONFIG.getBytes(), false);
processAllMessages();
- verify(mImsResolver, atLeastOnce()).getImsConfig(
- anyInt(), eq(ImsFeature.FEATURE_RCS));
verify(mIImsConfig, atLeastOnce()).notifyRcsAutoConfigurationReceived(
argumentBytes.capture(), eq(false));
assertTrue(Arrays.equals(SAMPLE_CONFIG.getBytes(), argumentBytes.getValue()));
@@ -434,8 +437,6 @@
mRcsProvisioningMonitor.requestReconfig(FAKE_SUB_ID_BASE);
processAllMessages();
- verify(mImsResolver, atLeastOnce()).getImsConfig(
- anyInt(), eq(ImsFeature.FEATURE_RCS));
verify(mIImsConfig, times(1)).notifyRcsAutoConfigurationRemoved();
verify(mIImsConfig, times(1)).triggerRcsReconfiguration();
}
@@ -519,19 +520,79 @@
verify(mCallback, times(1)).onRemoved();
}
- private void createMonitor(int subCount) {
+ @Test
+ @SmallTest
+ public void testRcsConnectedAndDisconnected() throws Exception {
+ createMonitor(1);
+ mRcsProvisioningMonitor.registerRcsProvisioningChangedCallback(
+ FAKE_SUB_ID_BASE, mCallback);
+
+ verify(mIImsConfig, times(1))
+ .notifyRcsAutoConfigurationReceived(any(), anyBoolean());
+
+ mConnectorListener.getValue().connectionUnavailable(0);
+
+ verify(mCallback, times(1)).onRemoved();
+ }
+
+ @Test
+ @SmallTest
+ public void testTestModeEnabledAndDisabled() throws Exception {
+ when(mCursor.getBlob(anyInt())).thenReturn(null);
+ createMonitor(1);
+
+ verify(mCursor, times(1)).getBlob(anyInt());
+
+ mRcsProvisioningMonitor.setTestModeEnabled(true);
+ processAllMessages();
+
+ //should not query db in test mode
+ verify(mCursor, times(1)).getBlob(anyInt());
+ assertNull(mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE));
+
+ mRcsProvisioningMonitor.updateConfig(FAKE_SUB_ID_BASE, SAMPLE_CONFIG.getBytes(), false);
+ processAllMessages();
+
+ //config cahced in monitor should be updated, but db should not
+ assertNull(mProvider.getContentValues());
+ assertTrue(Arrays.equals(SAMPLE_CONFIG.getBytes(),
+ mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE)));
+
+ //verify if monitor goes back to normal mode
+ mRcsProvisioningMonitor.setTestModeEnabled(false);
+ processAllMessages();
+
+ verify(mCursor, times(2)).getBlob(anyInt());
+ assertNull(mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE));
+
+ mRcsProvisioningMonitor.updateConfig(FAKE_SUB_ID_BASE, SAMPLE_CONFIG.getBytes(), false);
+ processAllMessages();
+
+ assertTrue(Arrays.equals(SAMPLE_CONFIG.getBytes(),
+ mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE)));
+ assertTrue(Arrays.equals(RcsConfig.compressGzip(SAMPLE_CONFIG.getBytes()),
+ (byte[]) mProvider.getContentValues().get(SimInfo.COLUMN_RCS_CONFIG)));
+ }
+
+ private void createMonitor(int subCount) throws Exception {
if (Looper.myLooper() == null) {
Looper.prepare();
}
makeFakeActiveSubIds(subCount);
+ when(mFeatureFactory.create(any(), anyInt(), mConnectorListener.capture(), any(), any()))
+ .thenReturn(mFeatureConnector);
+ when(mFeatureManager.getConfig()).thenReturn(mIImsConfig);
mRcsProvisioningMonitor = new RcsProvisioningMonitor(mPhone, mHandlerThread.getLooper(),
- mRoleManager);
+ mRoleManager, mFeatureFactory);
mHandler = mRcsProvisioningMonitor.getHandler();
try {
mLooper = new TestableLooper(mHandler.getLooper());
} catch (Exception e) {
logd("Unable to create looper from handler.");
}
+ mConnectorListener.getValue().connectionReady(mFeatureManager);
+
+ verify(mFeatureConnector, atLeastOnce()).connect();
}
private void broadcastCarrierConfigChange(int subId) {