Move IMS to a listener type model instead of a poll model
Pipe through new listen commands for components requiring
access to ImsFeature binders and refactor the RCS
controllers to use the new model.
Test: atest TeleServiceTests
Change-Id: Ie3982c24525e5ac03d7166126694c41c37bc1ef6
diff --git a/src/com/android/phone/ImsRcsController.java b/src/com/android/phone/ImsRcsController.java
index f5f24d3..1d33514 100644
--- a/src/com/android/phone/ImsRcsController.java
+++ b/src/com/android/phone/ImsRcsController.java
@@ -29,14 +29,17 @@
import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.telephony.ims.aidl.IRcsUceControllerCallback;
import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
+import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.RcsFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.Log;
import com.android.ims.ImsManager;
+import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TelephonyPermissions;
+import com.android.internal.telephony.ims.ImsResolver;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.services.telephony.rcs.RcsFeatureController;
import com.android.services.telephony.rcs.TelephonyRcsService;
@@ -55,6 +58,7 @@
private PhoneGlobals mApp;
private TelephonyRcsService mRcsService;
+ private ImsResolver mImsResolver;
/**
* Initialize the singleton ImsRcsController instance.
@@ -77,6 +81,7 @@
mApp = app;
TelephonyFrameworkInitializer
.getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
+ mImsResolver = mApp.getImsResolver();
}
/**
@@ -349,6 +354,46 @@
}
/**
+ * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
+ * callback.
+ */
+ @Override
+ public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback,
+ boolean oneShot) {
+ enforceModifyPermission();
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ if (mImsResolver == null) {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+ "Device does not support IMS");
+ }
+ if (oneShot) {
+ mImsResolver.callBackIfExists(slotId, ImsFeature.FEATURE_RCS, callback);
+ } else {
+ mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ /**
+ * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
+ */
+ @Override
+ public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
+ enforceModifyPermission();
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ if (mImsResolver == null) return;
+ mImsResolver.unregisterImsFeatureCallback(callback);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
* Make sure either called from same process as self (phone) or IPC caller has read privilege.
*
* @throws SecurityException if the caller does not have the required permission
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index bd2b2ed..509aa57 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -55,6 +55,7 @@
import android.util.Log;
import android.widget.Toast;
+import com.android.ims.ImsFeatureBinderRepository;
import com.android.internal.telephony.CallManager;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.MmiCode;
@@ -356,7 +357,8 @@
String defaultImsRcsPackage = getResources().getString(
R.string.config_ims_rcs_package);
mImsResolver = new ImsResolver(this, defaultImsMmtelPackage,
- defaultImsRcsPackage, PhoneFactory.getPhones().length);
+ defaultImsRcsPackage, PhoneFactory.getPhones().length,
+ new ImsFeatureBinderRepository());
mImsResolver.initialize();
}
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index c22a8a4..9ddbe47 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -104,8 +104,6 @@
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsConfigCallback;
-import android.telephony.ims.aidl.IImsMmTelFeature;
-import android.telephony.ims.aidl.IImsRcsFeature;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.telephony.ims.feature.ImsFeature;
@@ -5007,58 +5005,40 @@
}
/**
- * Returns the {@link IImsMmTelFeature} that corresponds to the given slot Id for the MMTel
- * feature or {@link null} if the service is not available. If the feature is available, the
- * {@link IImsServiceFeatureCallback} callback is registered as a listener for feature updates.
+ * Registers for updates to the MmTelFeature connection through the IImsServiceFeatureCallback
+ * callback.
*/
- public IImsMmTelFeature getMmTelFeatureAndListen(int slotId,
- IImsServiceFeatureCallback callback) {
+ @Override
+ public void registerMmTelFeatureCallback(int slotId, IImsServiceFeatureCallback callback,
+ boolean oneShot) {
enforceModifyPermission();
final long identity = Binder.clearCallingIdentity();
try {
if (mImsResolver == null) {
- // may happen if the device does not support IMS.
- return null;
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+ "Device does not support IMS");
}
- return mImsResolver.getMmTelFeatureAndListen(slotId, callback);
+ if (oneShot) {
+ mImsResolver.callBackIfExists(slotId, ImsFeature.FEATURE_MMTEL, callback);
+ } else {
+ mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_MMTEL, callback);
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
}
-
- /**
- * Returns the {@link IImsRcsFeature} that corresponds to the given slot Id for the RCS
- * feature during emergency calling or {@link null} if the service is not available. If the
- * feature is available, the {@link IImsServiceFeatureCallback} callback is registered as a
- * listener for feature updates.
- */
- public IImsRcsFeature getRcsFeatureAndListen(int slotId, IImsServiceFeatureCallback callback) {
- enforceModifyPermission();
-
- final long identity = Binder.clearCallingIdentity();
- try {
- if (mImsResolver == null) {
- // may happen if the device does not support IMS.
- return null;
- }
- return mImsResolver.getRcsFeatureAndListen(slotId, callback);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
/**
* Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
*/
- public void unregisterImsFeatureCallback(int slotId, int featureType,
- IImsServiceFeatureCallback callback) {
+ @Override
+ public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
enforceModifyPermission();
final long identity = Binder.clearCallingIdentity();
try {
if (mImsResolver == null) return;
- mImsResolver.unregisterImsFeatureCallback(slotId, featureType, callback);
+ mImsResolver.unregisterImsFeatureCallback(callback);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 5a2b384..916b4ce 100755
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -1586,7 +1586,7 @@
}
}
- isVowifiEnabled = ImsUtil.isWfcEnabled(phone.getContext(), phone.getPhoneId());
+ isVowifiEnabled = isWfcEnabled(phone);
}
if (isCurrentVideoCall) {
@@ -2722,7 +2722,7 @@
boolean isIms = phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS;
boolean isVoWifiEnabled = false;
if (isIms) {
- isVoWifiEnabled = ImsUtil.isWfcEnabled(phone.getContext(), phone.getPhoneId());
+ isVoWifiEnabled = isWfcEnabled(phone);
}
boolean isRttMergeSupported = getCarrierConfig()
.getBoolean(CarrierConfigManager.KEY_ALLOW_MERGING_RTT_CALLS_BOOL);
@@ -2772,6 +2772,12 @@
notifyConferenceSupportedChanged(isConferenceSupported);
}
}
+
+ @VisibleForTesting
+ boolean isWfcEnabled(Phone phone) {
+ return ImsUtil.isWfcEnabled(phone.getContext(), phone.getPhoneId());
+ }
+
/**
* Provides a mapping from extras keys which may be found in the
* {@link com.android.internal.telephony.Connection} to their equivalents defined in
diff --git a/src/com/android/services/telephony/rcs/RcsFeatureController.java b/src/com/android/services/telephony/rcs/RcsFeatureController.java
index fcfe312..8c6fce0 100644
--- a/src/com/android/services/telephony/rcs/RcsFeatureController.java
+++ b/src/com/android/services/telephony/rcs/RcsFeatureController.java
@@ -20,7 +20,9 @@
import android.content.Context;
import android.net.Uri;
import android.telephony.ims.ImsException;
+import android.telephony.ims.ImsRcsManager;
import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.RegistrationManager;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.telephony.ims.stub.ImsRegistrationImplBase;
@@ -28,7 +30,7 @@
import android.util.Log;
import com.android.ims.FeatureConnector;
-import com.android.ims.IFeatureConnector;
+import com.android.ims.FeatureUpdates;
import com.android.ims.RcsFeatureManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.imsphone.ImsRegistrationCallbackHelper;
@@ -78,13 +80,13 @@
* Used to inject FeatureConnector instances for testing.
*/
@VisibleForTesting
- public interface FeatureConnectorFactory<T extends IFeatureConnector> {
+ public interface FeatureConnectorFactory<U extends FeatureUpdates> {
/**
- * @return a {@link FeatureConnector} associated for the given {@link IFeatureConnector}
- * and slot id.
+ * @return a {@link FeatureConnector} associated for the given {@link FeatureUpdates}
+ * and slot index.
*/
- FeatureConnector<T> create(Context context, int slotId,
- FeatureConnector.Listener<T> listener, Executor executor, String tag);
+ FeatureConnector<U> create(Context context, int slotIndex,
+ FeatureConnector.Listener<U> listener, Executor executor, String logPrefix);
}
/**
@@ -100,7 +102,8 @@
ImsRegistrationCallbackHelper.ImsRegistrationUpdate cb, Executor executor);
}
- private FeatureConnectorFactory<RcsFeatureManager> mFeatureFactory = FeatureConnector::new;
+ private FeatureConnectorFactory<RcsFeatureManager> mFeatureFactory =
+ RcsFeatureManager::getConnector;
private RegistrationHelperFactory mRegistrationHelperFactory =
ImsRegistrationCallbackHelper::new;
@@ -115,11 +118,6 @@
private FeatureConnector.Listener<RcsFeatureManager> mFeatureConnectorListener =
new FeatureConnector.Listener<RcsFeatureManager>() {
@Override
- public RcsFeatureManager getFeatureManager() {
- return new RcsFeatureManager(mContext, mSlotId);
- }
-
- @Override
public void connectionReady(RcsFeatureManager manager)
throws com.android.ims.ImsException {
if (manager == null) {
@@ -140,7 +138,10 @@
}
@Override
- public void connectionUnavailable() {
+ public void connectionUnavailable(int reason) {
+ if (reason == FeatureConnector.UNAVAILABLE_REASON_SERVER_UNAVAILABLE) {
+ loge("unexpected - connectionUnavailable due to server unavailable");
+ }
// Call before disabling connection to manager.
removeConnectionToService();
updateConnectionStatus(null /*manager*/);
@@ -279,7 +280,7 @@
}
@VisibleForTesting
- public void setFeatureConnectorFactory(FeatureConnectorFactory factory) {
+ public void setFeatureConnectorFactory(FeatureConnectorFactory<RcsFeatureManager> factory) {
mFeatureFactory = factory;
}
@@ -433,6 +434,10 @@
Log.w(LOG_TAG, getLogPrefix().append(log).toString());
}
+ private void loge(String log) {
+ Log.e(LOG_TAG, getLogPrefix().append(log).toString());
+ }
+
private StringBuilder getLogPrefix() {
StringBuilder sb = new StringBuilder("[");
sb.append(mSlotId);
diff --git a/tests/src/com/android/services/telephony/TestTelephonyConnection.java b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
index 09cec17..2635e60 100644
--- a/tests/src/com/android/services/telephony/TestTelephonyConnection.java
+++ b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
@@ -169,6 +169,12 @@
// Requires ImsManager dependencies, do not implement during testing.
}
+ @Override
+ boolean isWfcEnabled(Phone phone) {
+ // Requires ImsManager dependencies, mock for test.
+ return true;
+ }
+
public int getNotifyPhoneAccountChangedCount() {
return mNotifyPhoneAccountChangedCount;
}
diff --git a/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java b/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
index fbb270d..7e87dc7 100644
--- a/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
@@ -100,7 +100,8 @@
verify(mMockFeature).onRcsConnected(mFeatureManager);
// Disconnect
- mConnectorListener.getValue().connectionUnavailable();
+ mConnectorListener.getValue().connectionUnavailable(
+ FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED);
verify(mFeatureManager).unregisterImsRegistrationCallback(any());
verify(mMockFeature, times(2)).onRcsDisconnected();
@@ -193,7 +194,8 @@
public void testFeatureManagerDisconnectedAddFeature() {
RcsFeatureController controller = createFeatureController();
// Disconnect the RcsFeatureManager
- mConnectorListener.getValue().connectionUnavailable();
+ mConnectorListener.getValue().connectionUnavailable(
+ FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED);
controller.addFeature(mMockFeature, RcsFeatureController.Feature.class);
verify(mMockFeature).onRcsDisconnected();
@@ -205,7 +207,8 @@
IImsRegistrationCallback regCb = mock(IImsRegistrationCallback.class);
IImsCapabilityCallback capCb = mock(IImsCapabilityCallback.class);
// Disconnect the RcsFeatureManager
- mConnectorListener.getValue().connectionUnavailable();
+ mConnectorListener.getValue().connectionUnavailable(
+ FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED);
try {
controller.registerImsRegistrationCallback(0 /*subId*/, null /*callback*/);