aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Ebinger <breadley@google.com>2020-01-30 17:27:47 -0800
committerBrad Ebinger <breadley@google.com>2020-02-04 11:22:09 -0800
commitc514e52ea6b0c89ae8f5e2ab8666585ed815900a (patch)
tree9ffd7c6b592ac20672c1b29edb3f046c317e3465
parentdc42846038d3f92ad52102d0ee2537d3c2b9b778 (diff)
downloadims-c514e52ea6b0c89ae8f5e2ab8666585ed815900a.tar.gz
Refactor RcsFEatureManager to be created from TelephonyRcsService
The RcsFeatureManager and management code has been moved from ImsService to RcsFetureManager in order to remove some of the messy coupling that had to occur to get signalling between them. Test: atest FrameworksTelephonyTests Test: atest TeleServiceTests Test: atest CtsTelephonyTestCases Change-Id: I2cc8785f1f7feed78d82a136621abfc66391e008
-rw-r--r--src/java/com/android/ims/FeatureConnector.java23
-rw-r--r--src/java/com/android/ims/IFeatureConnector.java4
-rw-r--r--src/java/com/android/ims/ImsCallbackAdapterManager.java12
-rw-r--r--src/java/com/android/ims/ImsManager.java11
-rw-r--r--src/java/com/android/ims/MmTelFeatureConnection.java14
-rw-r--r--src/java/com/android/ims/RcsFeatureConnection.java195
-rw-r--r--src/java/com/android/ims/RcsFeatureManager.java420
7 files changed, 339 insertions, 340 deletions
diff --git a/src/java/com/android/ims/FeatureConnector.java b/src/java/com/android/ims/FeatureConnector.java
index 2f424842..273dd958 100644
--- a/src/java/com/android/ims/FeatureConnector.java
+++ b/src/java/com/android/ims/FeatureConnector.java
@@ -46,11 +46,6 @@ public class FeatureConnector<T extends IFeatureConnector> extends Handler {
public interface Listener<T> {
/**
- * Check if ImsFeature supported
- */
- boolean isSupported();
-
- /**
* Get ImsFeature manager instance
*/
T getFeatureManager();
@@ -96,14 +91,6 @@ public class FeatureConnector<T extends IFeatureConnector> extends Handler {
}
};
- public FeatureConnector(Context context, int phoneId, Listener<T> listener) {
- mContext = context;
- mPhoneId = phoneId;
- mListener = listener;
- mExecutor = new HandlerExecutor(this);
- mLogPrefix = "?";
- }
-
public FeatureConnector(Context context, int phoneId, Listener<T> listener,
String logPrefix) {
mContext = context;
@@ -157,7 +144,7 @@ public class FeatureConnector<T extends IFeatureConnector> extends Handler {
// Check if this ImsFeature is supported or not.
private boolean isSupported() {
- return mListener.isSupported();
+ return ImsManager.isImsSupportedOnDevice(mContext);
}
/**
@@ -178,18 +165,18 @@ public class FeatureConnector<T extends IFeatureConnector> extends Handler {
private final Runnable mGetServiceRunnable = () -> {
try {
createImsService();
- } catch (ImsException e) {
+ } catch (android.telephony.ims.ImsException e) {
int errorCode = e.getCode();
if (DBG) logw("Create IMS service error: " + errorCode);
- if (ImsReasonInfo.CODE_LOCAL_IMS_NOT_SUPPORTED_ON_DEVICE != errorCode) {
- // Retry when error is not IMS_NOT_SUPPORTED_ON_DEVICE
+ if (android.telephony.ims.ImsException.CODE_ERROR_UNSUPPORTED_OPERATION != errorCode) {
+ // Retry when error is not CODE_ERROR_UNSUPPORTED_OPERATION
retryGetImsService();
}
}
};
@VisibleForTesting
- public void createImsService() throws ImsException {
+ public void createImsService() throws android.telephony.ims.ImsException {
synchronized (mLock) {
if (DBG) log("createImsService");
mManager = mListener.getFeatureManager();
diff --git a/src/java/com/android/ims/IFeatureConnector.java b/src/java/com/android/ims/IFeatureConnector.java
index a169bb23..66428ce7 100644
--- a/src/java/com/android/ims/IFeatureConnector.java
+++ b/src/java/com/android/ims/IFeatureConnector.java
@@ -16,9 +16,9 @@
package com.android.ims;
-public interface IFeatureConnector {
+public interface IFeatureConnector<T> {
int getImsServiceState() throws ImsException;
void addNotifyStatusChangedCallbackIfAvailable(FeatureConnection.IFeatureUpdate callback)
- throws ImsException;
+ throws android.telephony.ims.ImsException;
void removeNotifyStatusChangedCallback(FeatureConnection.IFeatureUpdate callback);
} \ No newline at end of file
diff --git a/src/java/com/android/ims/ImsCallbackAdapterManager.java b/src/java/com/android/ims/ImsCallbackAdapterManager.java
index bf2bd39d..d4926b2f 100644
--- a/src/java/com/android/ims/ImsCallbackAdapterManager.java
+++ b/src/java/com/android/ims/ImsCallbackAdapterManager.java
@@ -35,7 +35,7 @@ import java.util.Set;
import java.util.stream.Collectors;
public abstract class ImsCallbackAdapterManager<T extends IInterface> {
- private static final String TAG = "ImsCallbackAdapterManager";
+ private static final String TAG = "ImsCallbackAM";
private final Context mContext;
private final Object mLock;
@@ -98,8 +98,8 @@ public abstract class ImsCallbackAdapterManager<T extends IInterface> {
};
}
- // Add a callback to the MmTelFeature associated with this manager (independent of the)
- // current subscription.
+ // Add a callback to the ImsFeature associated with this manager (independent of the
+ // current subscription).
public final void addCallback(T localCallback) {
synchronized (mLock) {
// Skip registering to callback subscription map here, because we are registering
@@ -124,7 +124,7 @@ public abstract class ImsCallbackAdapterManager<T extends IInterface> {
}
}
- // Removes a callback associated with the MmTelFeature.
+ // Removes a callback associated with the ImsFeature.
public final void removeCallback(T localCallback) {
Log.i(TAG + " [" + mSlotId + "]", "Local callback removed: " + localCallback);
synchronized (mLock) {
@@ -255,9 +255,9 @@ public abstract class ImsCallbackAdapterManager<T extends IInterface> {
}
}
- // A callback has been registered. Register that callback with the MmTelFeature.
+ // A callback has been registered. Register that callback with the ImsFeature.
public abstract void registerCallback(T localCallback);
- // A callback has been removed, unregister that callback with the MmTelFeature.
+ // A callback has been removed, unregister that callback with the RcsFeature.
public abstract void unregisterCallback(T localCallback);
}
diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java
index 0d75bd4d..8e1a1e1e 100644
--- a/src/java/com/android/ims/ImsManager.java
+++ b/src/java/com/android/ims/ImsManager.java
@@ -1557,10 +1557,10 @@ public class ImsManager implements IFeatureConnector {
@Override
@VisibleForTesting
public void addNotifyStatusChangedCallbackIfAvailable(FeatureConnection.IFeatureUpdate c)
- throws ImsException {
+ throws android.telephony.ims.ImsException {
if (!mMmTelFeatureConnection.isBinderAlive()) {
- throw new ImsException("Binder is not active!",
- ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
+ throw new android.telephony.ims.ImsException("Can not connect to ImsService",
+ android.telephony.ims.ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
if (c != null) {
mStatusCallbacks.add(c);
@@ -2277,10 +2277,7 @@ public class ImsManager implements IFeatureConnector {
}
/**
- * Binds the IMS service to make/receive the call. Supports two methods of exposing an
- * ImsService:
- * 1) com.android.ims.ImsService implementation in ServiceManager (deprecated).
- * 2) android.telephony.ims.ImsService implementation through ImsResolver.
+ * Creates a connection to the ImsService associated with this slot.
*/
private void createImsService() {
mMmTelFeatureConnection = MmTelFeatureConnection.create(mContext, mPhoneId);
diff --git a/src/java/com/android/ims/MmTelFeatureConnection.java b/src/java/com/android/ims/MmTelFeatureConnection.java
index 2c10a238..40075bcb 100644
--- a/src/java/com/android/ims/MmTelFeatureConnection.java
+++ b/src/java/com/android/ims/MmTelFeatureConnection.java
@@ -240,21 +240,11 @@ public class MmTelFeatureConnection extends FeatureConnection {
@Override
protected void onRemovedOrDied() {
synchronized (mLock) {
+ super.onRemovedOrDied();
mRegistrationCallbackManager.close();
mCapabilityCallbackManager.close();
mProvisioningCallbackManager.close();
- if (mIsAvailable) {
- mIsAvailable = false;
- // invalidate caches.
- mRegistrationBinder = null;
- mConfigBinder = null;
- if (mBinder != null) {
- mBinder.unlinkToDeath(mDeathRecipient, 0);
- }
- if (mStatusCallback != null) {
- mStatusCallback.notifyUnavailable();
- }
- }
+ mConfigBinder = null;
}
}
diff --git a/src/java/com/android/ims/RcsFeatureConnection.java b/src/java/com/android/ims/RcsFeatureConnection.java
index ea09e6fd..daee6dd6 100644
--- a/src/java/com/android/ims/RcsFeatureConnection.java
+++ b/src/java/com/android/ims/RcsFeatureConnection.java
@@ -21,32 +21,90 @@ import android.content.Context;
import android.os.IBinder;
import android.os.RemoteException;
import android.telephony.TelephonyManager;
-import android.telephony.ims.RcsContactUceCapability;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsRcsFeature;
+import android.telephony.ims.aidl.IImsRegistration;
+import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.telephony.ims.aidl.IRcsFeatureListener;
import android.telephony.ims.feature.CapabilityChangeRequest;
import android.telephony.ims.feature.ImsFeature;
-import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.service.ims.presence.PresencePublisher;
-import com.android.service.ims.presence.SubscribePublisher;
import com.android.telephony.Rlog;
/**
* A container of the IImsServiceController binder, which implements all of the RcsFeatures that
* the platform currently supports: RCS
*/
-public class RcsFeatureConnection extends FeatureConnection implements PresencePublisher,
- SubscribePublisher {
+public class RcsFeatureConnection extends FeatureConnection {
private static final String TAG = "RcsFeatureConnection";
- public interface IRcsFeatureUpdate extends IFeatureUpdate {
- /**
- * Called when the ImsFeature has been created.
- */
- void notifyFeatureCreated();
+ public class AvailabilityCallbackManager extends
+ ImsCallbackAdapterManager<IImsCapabilityCallback> {
+
+ AvailabilityCallbackManager(Context context) {
+ super(context, new Object() /* Lock object */, mSlotId);
+ }
+
+ @Override
+ public void registerCallback(IImsCapabilityCallback localCallback) {
+ try {
+ addCapabilityCallback(localCallback);
+ } catch (RemoteException e) {
+ loge("Register capability callback error: " + e);
+ throw new IllegalStateException(
+ " CapabilityCallbackManager: Register callback error");
+ }
+ }
+
+ @Override
+ public void unregisterCallback(IImsCapabilityCallback localCallback) {
+ try {
+ removeCapabilityCallback(localCallback);
+ } catch (RemoteException e) {
+ loge("Cannot remove capability callback: " + e);
+ }
+ }
+ }
+
+ private class RegistrationCallbackManager extends
+ ImsCallbackAdapterManager<IImsRegistrationCallback> {
+
+ public RegistrationCallbackManager(Context context) {
+ super(context, new Object() /* Lock object */, mSlotId);
+ }
+
+ @Override
+ public void registerCallback(IImsRegistrationCallback localCallback) {
+ IImsRegistration imsRegistration = getRegistration();
+ if (imsRegistration == null) {
+ loge("Register IMS registration callback: ImsRegistration is null");
+ throw new IllegalStateException("RegistrationCallbackAdapter: RcsFeature is"
+ + " not available!");
+ }
+
+ try {
+ imsRegistration.addRegistrationCallback(localCallback);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("RegistrationCallbackAdapter: RcsFeature"
+ + " binder is dead.");
+ }
+ }
+
+ @Override
+ public void unregisterCallback(IImsRegistrationCallback localCallback) {
+ IImsRegistration imsRegistration = getRegistration();
+ if (imsRegistration == null) {
+ logi("Unregister IMS registration callback: ImsRegistration is null");
+ return;
+ }
+
+ try {
+ imsRegistration.removeRegistrationCallback(localCallback);
+ } catch (RemoteException e) {
+ loge("Cannot remove registration callback: " + e);
+ }
+ }
}
public static @NonNull RcsFeatureConnection create(Context context , int slotId,
@@ -83,51 +141,55 @@ public class RcsFeatureConnection extends FeatureConnection implements PresenceP
}
@VisibleForTesting
- public IRcsFeatureUpdate mRcsFeatureStatusCallback;
+ public AvailabilityCallbackManager mAvailabilityCallbackManager;
+ @VisibleForTesting
+ public RegistrationCallbackManager mRegistrationCallbackManager;
private RcsFeatureConnection(Context context, int slotId, IFeatureUpdate callback) {
super(context, slotId, ImsFeature.FEATURE_RCS);
setStatusCallback(callback);
+ mAvailabilityCallbackManager = new AvailabilityCallbackManager(mContext);
+ mRegistrationCallbackManager = new RegistrationCallbackManager(mContext);
}
public void close() {
removeRcsFeatureListener();
+ mAvailabilityCallbackManager.close();
+ mRegistrationCallbackManager.close();
}
@Override
- public void setStatusCallback(IFeatureUpdate callback) {
- super.setStatusCallback(callback);
- mRcsFeatureStatusCallback = (IRcsFeatureUpdate) mStatusCallback;
+ protected void onRemovedOrDied() {
+ super.onRemovedOrDied();
+ synchronized (mLock) {
+ close();
+ }
}
@Override
@VisibleForTesting
public void handleImsFeatureCreatedCallback(int slotId, int feature) {
- Log.i(TAG, "IMS feature created: slotId= " + slotId + ", feature=" + feature);
+ logi("IMS feature created: slotId= " + slotId + ", feature=" + feature);
if (!isUpdateForThisFeatureAndSlot(slotId, feature)) {
return;
}
synchronized(mLock) {
if (!mIsAvailable) {
- Log.i(TAG, "RCS enabled on slotId: " + slotId);
+ logi("RCS enabled on slotId: " + slotId);
mIsAvailable = true;
}
- // Notify RcsFeatureManager that RCS feature has already been created
- if (mRcsFeatureStatusCallback != null) {
- mRcsFeatureStatusCallback.notifyFeatureCreated();
- }
}
}
@Override
@VisibleForTesting
public void handleImsFeatureRemovedCallback(int slotId, int feature) {
- Log.i(TAG, "IMS feature removed: slotId= " + slotId + ", feature=" + feature);
+ logi("IMS feature removed: slotId= " + slotId + ", feature=" + feature);
if (!isUpdateForThisFeatureAndSlot(slotId, feature)) {
return;
}
synchronized(mLock) {
- Log.i(TAG, "Rcs UCE removed on slotId: " + slotId);
+ logi("Rcs UCE removed on slotId: " + slotId);
onRemovedOrDied();
}
}
@@ -135,17 +197,13 @@ public class RcsFeatureConnection extends FeatureConnection implements PresenceP
@Override
@VisibleForTesting
public void handleImsStatusChangedCallback(int slotId, int feature, int status) {
- Log.i(TAG, "IMS status changed: slotId=" + slotId
- + ", feature=" + feature + ", status=" + status);
+ logi("IMS status changed: slotId=" + slotId + ", feature=" + feature + ", status="
+ + status);
if (!isUpdateForThisFeatureAndSlot(slotId, feature)) {
return;
}
synchronized(mLock) {
mFeatureStateCached = status;
- // notify RCS feature status changed
- if (mRcsFeatureStatusCallback != null) {
- mRcsFeatureStatusCallback.notifyStateChanged();
- }
}
}
@@ -167,6 +225,7 @@ public class RcsFeatureConnection extends FeatureConnection implements PresenceP
try {
setRcsFeatureListener(null);
} catch (RemoteException e) {
+ // If we are not still connected, there is no need to fail removing.
}
}
@@ -177,14 +236,40 @@ public class RcsFeatureConnection extends FeatureConnection implements PresenceP
}
}
- public void addCapabilityCallback(IImsCapabilityCallback callback) throws RemoteException {
+ public void addCallbackForSubscription(int subId, IImsCapabilityCallback cb) {
+ mAvailabilityCallbackManager.addCallbackForSubscription(cb, subId);
+ }
+
+ public void addCallbackForSubscription(int subId, IImsRegistrationCallback cb) {
+ mRegistrationCallbackManager.addCallbackForSubscription(cb, subId);
+ }
+
+ public void addCallback(IImsRegistrationCallback cb) {
+ mRegistrationCallbackManager.addCallback(cb);
+ }
+
+ public void removeCallbackForSubscription(int subId, IImsCapabilityCallback cb) {
+ mAvailabilityCallbackManager.removeCallbackForSubscription(cb, subId);
+ }
+
+ public void removeCallbackForSubscription(int subId, IImsRegistrationCallback cb) {
+ mRegistrationCallbackManager.removeCallbackForSubscription(cb, subId);
+ }
+
+ public void removeCallback(IImsRegistrationCallback cb) {
+ mRegistrationCallbackManager.removeCallback(cb);
+ }
+
+ // Add callback to remote service
+ private void addCapabilityCallback(IImsCapabilityCallback callback) throws RemoteException {
synchronized (mLock) {
checkServiceIsReady();
getServiceInterface(mBinder).addCapabilityCallback(callback);
}
}
- public void removeCapabilityCallback(IImsCapabilityCallback callback) throws RemoteException {
+ // Remove callback to remote service
+ private void removeCapabilityCallback(IImsCapabilityCallback callback) throws RemoteException {
synchronized (mLock) {
checkServiceIsReady();
getServiceInterface(mBinder).removeCapabilityCallback(callback);
@@ -208,43 +293,6 @@ public class RcsFeatureConnection extends FeatureConnection implements PresenceP
}
@Override
- public int getPublisherState() {
- // Need to implement this api
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int requestPublication(RcsContactUceCapability capabilities, String contactUri,
- int taskId) {
- // Need to implement this api
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void updatePublisherState(int publishState) {
- // Need to implement this api
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int requestCapability(String[] formattedContacts, int taskId) {
- // Need to implement this api
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int requestAvailability(String formattedContact, int taskId) {
- // Need to implement this api
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getStackStatusForCapabilityRequest() {
- // Need to implement this api
- throw new UnsupportedOperationException();
- }
-
- @Override
@VisibleForTesting
public Integer retrieveFeatureState() {
if (mBinder != null) {
@@ -261,4 +309,15 @@ public class RcsFeatureConnection extends FeatureConnection implements PresenceP
public IImsRcsFeature getServiceInterface(IBinder b) {
return IImsRcsFeature.Stub.asInterface(b);
}
+ private void log(String s) {
+ Rlog.d(TAG + " [" + mSlotId + "]", s);
+ }
+
+ private void logi(String s) {
+ Rlog.i(TAG + " [" + mSlotId + "]", s);
+ }
+
+ private void loge(String s) {
+ Rlog.e(TAG + " [" + mSlotId + "]", s);
+ }
}
diff --git a/src/java/com/android/ims/RcsFeatureManager.java b/src/java/com/android/ims/RcsFeatureManager.java
index 1d8e6f1c..3fe92129 100644
--- a/src/java/com/android/ims/RcsFeatureManager.java
+++ b/src/java/com/android/ims/RcsFeatureManager.java
@@ -16,27 +16,27 @@
package com.android.ims;
-import android.annotation.Nullable;
import android.content.Context;
import android.net.Uri;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
-import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.RcsContactUceCapability;
+import android.telephony.ims.RegistrationManager;
import android.telephony.ims.aidl.IImsCapabilityCallback;
-import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.telephony.ims.aidl.IRcsFeatureListener;
import android.telephony.ims.feature.CapabilityChangeRequest;
+import android.telephony.ims.feature.RcsFeature;
import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities;
import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.telephony.ims.stub.RcsCapabilityExchange;
import android.telephony.ims.stub.RcsPresenceExchangeImplBase;
+import android.telephony.ims.stub.RcsSipOptionsImplBase;
import android.util.Log;
import com.android.ims.FeatureConnection.IFeatureUpdate;
-import com.android.ims.RcsFeatureConnection.IRcsFeatureUpdate;
import com.android.internal.annotations.VisibleForTesting;
import com.android.telephony.Rlog;
@@ -47,6 +47,12 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
+/**
+ * Encapsulates all logic related to the RcsFeature:
+ * - Updating RcsFeature capabilities.
+ * - Registering/Unregistering availability/registration callbacks.
+ * - Querying Registration and Capability information.
+ */
public class RcsFeatureManager implements IFeatureConnector {
private static final String TAG = "RcsFeatureManager";
private static boolean DBG = true;
@@ -54,47 +60,109 @@ public class RcsFeatureManager implements IFeatureConnector {
private static final int CAPABILITY_OPTIONS = RcsImsCapabilities.CAPABILITY_TYPE_OPTIONS_UCE;
private static final int CAPABILITY_PRESENCE = RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE;
+ /**
+ * Callbacks from the RcsFeature, which have an empty default implementation and can be
+ * overridden for each Feature.
+ */
+ public static class RcsFeatureCallbacks {
+ /** See {@link RcsCapabilityExchange#onCommandUpdate(int, int)} */
+ void onCommandUpdate(int commandCode, int operationToken) {}
+
+ /** See {@link RcsPresenceExchangeImplBase#onNetworkResponse(int, String, int)} */
+ public void onNetworkResponse(int code, String reason, int operationToken) {}
+
+ /** See {@link RcsPresenceExchangeImplBase#onCapabilityRequestResponse(List, int)} */
+ public void onCapabilityRequestResponsePresence(List<RcsContactUceCapability> infos,
+ int operationToken) {}
+
+ /** See {@link RcsPresenceExchangeImplBase#onNotifyUpdateCapabilites(int)} */
+ public void onNotifyUpdateCapabilities(int publishTriggerType) {}
+
+ /** See {@link RcsPresenceExchangeImplBase#onUnpublish()} */
+ public void onUnpublish() {}
+
+ /**
+ * See {@link RcsSipOptionsImplBase#onCapabilityRequestResponse(int,String,
+ * RcsContactUceCapability, int)}
+ */
+ public void onCapabilityRequestResponseOptions(int code, String reason,
+ RcsContactUceCapability info, int operationToken) {}
+
+ /**
+ * See {@link RcsSipOptionsImplBase#onRemoteCapabilityRequest(Uri, RcsContactUceCapability,
+ * int)}
+ */
+ public void onRemoteCapabilityRequest(Uri contactUri, RcsContactUceCapability remoteInfo,
+ int operationToken) {}
+ }
+
+ private final IRcsFeatureListener mRcsFeatureCallbackAdapter = new IRcsFeatureListener.Stub() {
+ @Override
+ public void onCommandUpdate(int commandCode, int operationToken) {
+ mRcsFeatureCallbacks.forEach(listener-> listener.onCommandUpdate(commandCode,
+ operationToken));
+ }
+
+ @Override
+ public void onNetworkResponse(int code, String reason, int operationToken) {
+ mRcsFeatureCallbacks.forEach(listener-> listener.onNetworkResponse(code, reason,
+ operationToken));
+ }
+
+ @Override
+ public void onCapabilityRequestResponsePresence(List<RcsContactUceCapability> infos,
+ int operationToken) {
+ mRcsFeatureCallbacks.forEach(listener-> listener.onCapabilityRequestResponsePresence(
+ infos, operationToken));
+ }
+
+ @Override
+ public void onNotifyUpdateCapabilities(int publishTriggerType) {
+ mRcsFeatureCallbacks.forEach(listener-> listener.onNotifyUpdateCapabilities(
+ publishTriggerType));
+ }
+
+ @Override
+ public void onUnpublish() {
+ mRcsFeatureCallbacks.forEach(listener-> listener.onUnpublish());
+ }
+
+ @Override
+ public void onCapabilityRequestResponseOptions(int code, String reason,
+ RcsContactUceCapability info, int operationToken) {
+ mRcsFeatureCallbacks.forEach(listener -> listener.onCapabilityRequestResponseOptions(
+ code, reason, info, operationToken));
+ }
+
+ @Override
+ public void onRemoteCapabilityRequest(Uri contactUri, RcsContactUceCapability remoteInfo,
+ int operationToken) {
+ mRcsFeatureCallbacks.forEach(listener -> listener.onRemoteCapabilityRequest(
+ contactUri, remoteInfo, operationToken));
+ }
+ };
+
private final int mSlotId;
private final Context mContext;
+ @VisibleForTesting
+ public final Set<IFeatureUpdate> mStatusCallbacks = new CopyOnWriteArraySet<>();
+ private final Set<RcsFeatureCallbacks> mRcsFeatureCallbacks = new CopyOnWriteArraySet<>();
@VisibleForTesting
public RcsFeatureConnection mRcsFeatureConnection;
- @VisibleForTesting
- public RcsCapabilityCallbackManager mCapabilityCallbackManager;
- @VisibleForTesting
- public ImsRegistrationCallbackAdapter mRegistrationCallbackManager;
- @VisibleForTesting
- public Set<IFeatureUpdate> mStatusCallbacks = new CopyOnWriteArraySet<>();
public RcsFeatureManager(Context context, int slotId) {
mContext = context;
mSlotId = slotId;
logi("RcsFeatureManager");
- mCapabilityCallbackManager = new RcsCapabilityCallbackManager(context);
- mRegistrationCallbackManager = new ImsRegistrationCallbackAdapter(context);
-
createImsService();
}
- public void release() {
- logi("release");
- mStatusCallbacks.clear();
- mCapabilityCallbackManager.close();
- mRegistrationCallbackManager.close();
- mRcsFeatureConnection.close();
- }
-
// Binds the IMS service to the RcsFeature instance.
private void createImsService() {
mRcsFeatureConnection = RcsFeatureConnection.create(mContext, mSlotId,
- new IRcsFeatureUpdate() {
- @Override
- public void notifyFeatureCreated() {
- logi("RcsFeature is created");
- setRcsFeatureListener();
- updateCapabilities();
- }
+ new IFeatureUpdate() {
@Override
public void notifyStateChanged() {
mStatusCallbacks.forEach(
@@ -110,148 +178,100 @@ public class RcsFeatureManager implements IFeatureConnector {
}
/**
- * Set RcsFeature listener and it will also trigger onFeatureReady in RcsFeature.
+ * Opens a persistent connection to the RcsFeature. This must be called before the RcsFeature
+ * can be used to communicate. Triggers a {@link RcsFeature#onFeatureReady()} call on the
+ * service side.
*/
- private void setRcsFeatureListener() {
- if (DBG) log("Set RcsFeature listener");
+ public void openConnection() throws android.telephony.ims.ImsException {
try {
- mRcsFeatureConnection.setRcsFeatureListener(mRcsFeatureListener);
- } catch (RemoteException e) {
- loge("setRcsFeatureListener: ", e);
+ mRcsFeatureConnection.setRcsFeatureListener(mRcsFeatureCallbackAdapter);
+ } catch (RemoteException e){
+ throw new android.telephony.ims.ImsException("Service is not available.",
+ android.telephony.ims.ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
/**
- * Update current UCE capabilities.
+ * Closes the persistent connection to the RcsFeature. This must be called when this manager
+ * wishes to no longer be used to communicate with the RcsFeature.
*/
- @VisibleForTesting
- public void updateCapabilities() {
+ public void releaseConnection() {
+ try {
+ mRcsFeatureConnection.setRcsFeatureListener(null);
+ } catch (RemoteException e){
+ // Connection may not be available at this point.
+ }
+ mStatusCallbacks.clear();
+ mRcsFeatureConnection.close();
+ mRcsFeatureCallbacks.clear();
+ }
+
+ /**
+ * Adds a callback for {@link RcsFeatureCallbacks}.
+ * Note: These callbacks will be sent on the binder thread used to notify the callback.
+ */
+ public void addFeatureListenerCallback(RcsFeatureCallbacks listener) {
+ mRcsFeatureCallbacks.add(listener);
+ }
+
+ /**
+ * Removes an existing {@link RcsFeatureCallbacks}.
+ */
+ public void removeFeatureListenerCallback(RcsFeatureCallbacks listener) {
+ mRcsFeatureCallbacks.remove(listener);
+ }
+
+ /**
+ * Update the capabilities for this RcsFeature.
+ */
+ public void updateCapabilities() throws android.telephony.ims.ImsException {
boolean optionsSupport = isOptionsSupported();
boolean presenceSupported = isPresenceSupported();
- if (DBG) log("Update capabilities: options=" + optionsSupport
+ logi("Update capabilities for slot " + mSlotId + ": options=" + optionsSupport
+ ", presence=" + presenceSupported);
if (optionsSupport || presenceSupported) {
+ CapabilityChangeRequest request = new CapabilityChangeRequest();
if (optionsSupport) {
- enableRcsUceCapability(CAPABILITY_OPTIONS);
+ addRcsUceCapability(request, CAPABILITY_OPTIONS);
}
if (presenceSupported) {
- enableRcsUceCapability(CAPABILITY_PRESENCE);
+ addRcsUceCapability(request, CAPABILITY_PRESENCE);
}
+ sendCapabilityChangeRequest(request);
} else {
disableAllRcsUceCapabilities();
}
}
- public RcsFeatureConnection getRcsFeatureConnection() {
- return mRcsFeatureConnection;
- }
-
/**
- * The callback to receive updated from RcsFeature
- */
- protected IRcsFeatureListener mRcsFeatureListener = new IRcsFeatureListener.Stub() {
- @Override
- public void onCommandUpdate(int commandCode, int operationToken) {
- }
-
- @Override
- public void onNetworkResponse(int code, String reason, int operationToken) {
- }
-
- @Override
- public void onCapabilityRequestResponsePresence(
- List<RcsContactUceCapability> infos, int operationToken) {
- }
-
- @Override
- public void onNotifyUpdateCapabilities(
- @RcsPresenceExchangeImplBase.StackPublishTriggerType int triggerType) {
- }
-
- @Override
- public void onUnpublish() {
- }
-
- @Override
- public void onCapabilityRequestResponseOptions(
- int code, String reason, RcsContactUceCapability info, int operationToken) {
- }
-
- @Override
- public void onRemoteCapabilityRequest(
- Uri contactUri, RcsContactUceCapability remoteInfo, int operationToken) {
- }
- };
-
- /**
- * A inner class to manager all the ImsRegistrationCallback associated with RcsFeature.
+ * Add a {@link RegistrationManager.RegistrationCallback} callback that gets called when IMS
+ * registration has changed for a specific subscription.
*/
- private class ImsRegistrationCallbackAdapter extends
- ImsCallbackAdapterManager<IImsRegistrationCallback> {
-
- public ImsRegistrationCallbackAdapter(Context context) {
- super(context, new Object() /* Lock object */, mSlotId);
- }
-
- @Override
- public void registerCallback(IImsRegistrationCallback localCallback) {
- if (DBG) log("Register IMS registration callback");
-
- IImsRegistration imsRegistration = getRegistration();
- if (imsRegistration == null) {
- loge("Register IMS registration callback: ImsRegistration is null");
- throw new IllegalStateException("ImsRegistrationCallbackAdapter: RcsFeature is"
- + " not available!");
- }
-
- try {
- imsRegistration.addRegistrationCallback(localCallback);
- } catch (RemoteException e) {
- throw new IllegalStateException("ImsRegistrationCallbackAdapter: RcsFeature"
- + " binder is dead.");
- }
- }
-
- @Override
- public void unregisterCallback(IImsRegistrationCallback localCallback) {
- if (DBG) log("Unregister IMS registration callback");
-
- IImsRegistration imsRegistration = getRegistration();
- if (imsRegistration == null) {
- log("Unregister IMS registration callback: ImsRegistration is null");
- return;
- }
-
- try {
- imsRegistration.removeRegistrationCallback(localCallback);
- } catch (RemoteException e) {
- loge("Cannot remove registration callback: " + e);
- }
- }
-
- private @Nullable IImsRegistration getRegistration() {
- if (mRcsFeatureConnection == null) {
- return null;
- }
- return mRcsFeatureConnection.getRegistration();
+ public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback callback)
+ throws android.telephony.ims.ImsException {
+ try {
+ mRcsFeatureConnection.addCallbackForSubscription(subId, callback);
+ } catch (IllegalStateException e) {
+ loge("registerImsRegistrationCallback error: ", e);
+ throw new android.telephony.ims.ImsException("Can not register callback",
+ android.telephony.ims.ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
/**
* Add a {@link RegistrationManager.RegistrationCallback} callback that gets called when IMS
- * registration has changed for a specific subscription.
+ * registration has changed, independent of the subscription it is currently on.
*/
public void registerImsRegistrationCallback(IImsRegistrationCallback callback)
- throws ImsException {
+ throws android.telephony.ims.ImsException {
try {
- int subId = sSubscriptionManagerProxy.getSubId(mSlotId);
- mRegistrationCallbackManager.addCallbackForSubscription(callback, subId);
+ mRcsFeatureConnection.addCallback(callback);
} catch (IllegalStateException e) {
loge("registerImsRegistrationCallback error: ", e);
- throw new ImsException(
- "register registration callback", e, ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
+ throw new android.telephony.ims.ImsException("Can not register callback",
+ android.telephony.ims.ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
@@ -259,13 +279,16 @@ public class RcsFeatureManager implements IFeatureConnector {
* Removes a previously registered {@link RegistrationManager.RegistrationCallback} callback
* that is associated with a specific subscription.
*/
+ public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
+ mRcsFeatureConnection.removeCallbackForSubscription(subId, callback);
+ }
+
+ /**
+ * Removes a previously registered {@link RegistrationManager.RegistrationCallback} callback
+ * that was not associated with a subscription.
+ */
public void unregisterImsRegistrationCallback(IImsRegistrationCallback callback) {
- try {
- int subId = sSubscriptionManagerProxy.getSubId(mSlotId);
- mRegistrationCallbackManager.removeCallbackForSubscription(callback, subId);
- } catch (IllegalStateException e) {
- loge("unregisterImsRegistrationCallback error: ", e);
- }
+ mRcsFeatureConnection.removeCallback(callback);
}
/**
@@ -283,68 +306,25 @@ public class RcsFeatureManager implements IFeatureConnector {
}
/**
- * A inner class to manager all the ImsCapabilityCallbacks associated with RcsFeature.
- */
- @VisibleForTesting
- public class RcsCapabilityCallbackManager extends
- ImsCallbackAdapterManager<IImsCapabilityCallback> {
-
- RcsCapabilityCallbackManager(Context context) {
- super(context, new Object() /* Lock object */, mSlotId);
- }
-
- @Override
- public void registerCallback(IImsCapabilityCallback localCallback) {
- if (DBG) log("Register capability callback");
- try {
- mRcsFeatureConnection.addCapabilityCallback(localCallback);
- } catch (RemoteException e) {
- loge("Register capability callback error: " + e);
- throw new IllegalStateException(
- " CapabilityCallbackManager: Register callback error");
- }
- }
-
- @Override
- public void unregisterCallback(IImsCapabilityCallback localCallback) {
- if (DBG) log("Unregister capability callback");
- try {
- mRcsFeatureConnection.removeCapabilityCallback(localCallback);
- } catch (RemoteException e) {
- loge("Cannot remove capability callback: " + e);
- }
- }
- }
-
- /**
* Register an ImsCapabilityCallback with RCS service, which will provide RCS availability
* updates.
*/
- public void registerRcsAvailabilityCallback(IImsCapabilityCallback callback)
- throws ImsException {
+ public void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback)
+ throws android.telephony.ims.ImsException {
try {
- int subId = sSubscriptionManagerProxy.getSubId(mSlotId);
- mCapabilityCallbackManager.addCallbackForSubscription(callback, subId);
+ mRcsFeatureConnection.addCallbackForSubscription(subId, callback);
} catch (IllegalStateException e) {
loge("registerRcsAvailabilityCallback: ", e);
- throw new ImsException(
- "register capability callback", e, ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
+ throw new android.telephony.ims.ImsException("Can not register callback",
+ android.telephony.ims.ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
/**
* Remove an registered ImsCapabilityCallback from RCS service.
*/
- public void unregisterRcsAvailabilityCallback(IImsCapabilityCallback callback)
- throws ImsException {
- try {
- int subId = sSubscriptionManagerProxy.getSubId(mSlotId);
- mCapabilityCallbackManager.removeCallbackForSubscription(callback, subId);
- } catch (IllegalStateException e) {
- loge("unregisterRcsAvailabilityCallback: ", e);
- throw new ImsException(
- "unregister capability callback", e, ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
- }
+ public void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
+ mRcsFeatureConnection.removeCallbackForSubscription(subId, callback);
}
/**
@@ -352,7 +332,8 @@ public class RcsFeatureManager implements IFeatureConnector {
*/
public boolean isCapable(
@RcsImsCapabilities.RcsImsCapabilityFlag int capability,
- @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) throws ImsException {
+ @ImsRegistrationImplBase.ImsRegistrationTech int radioTech)
+ throws android.telephony.ims.ImsException {
CountDownLatch latch = new CountDownLatch(1);
AtomicReference<Boolean> capableRef = new AtomicReference<>();
@@ -386,7 +367,8 @@ public class RcsFeatureManager implements IFeatureConnector {
return awaitResult(latch, capableRef);
} catch (RemoteException e) {
loge("isCapable error: ", e);
- throw new ImsException("is capable", e, ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
+ throw new android.telephony.ims.ImsException("Can not determine capabilities",
+ android.telephony.ims.ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
@@ -403,13 +385,14 @@ public class RcsFeatureManager implements IFeatureConnector {
* Query the availability of an IMS RCS capability.
*/
public boolean isAvailable(@RcsImsCapabilities.RcsImsCapabilityFlag int capability)
- throws ImsException {
+ throws android.telephony.ims.ImsException {
try {
int currentStatus = mRcsFeatureConnection.queryCapabilityStatus();
return new RcsImsCapabilities(currentStatus).isCapable(capability);
} catch (RemoteException e) {
loge("isAvailable error: ", e);
- throw new ImsException("is RCS available", e, ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
+ throw new android.telephony.ims.ImsException("Can not determine availability",
+ android.telephony.ims.ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
@@ -419,10 +402,10 @@ public class RcsFeatureManager implements IFeatureConnector {
*/
@Override
public void addNotifyStatusChangedCallbackIfAvailable(FeatureConnection.IFeatureUpdate c)
- throws ImsException {
+ throws android.telephony.ims.ImsException {
if (!mRcsFeatureConnection.isBinderAlive()) {
- throw new ImsException("Binder is not active!",
- ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
+ throw new android.telephony.ims.ImsException("Can not connect to service.",
+ android.telephony.ims.ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
if (c != null) {
mStatusCallbacks.add(c);
@@ -437,29 +420,21 @@ public class RcsFeatureManager implements IFeatureConnector {
}
/**
- * Enable UCE capabilities with given type.
+ * Add UCE capabilities with given type.
* @param capability the specific RCS UCE capability wants to enable
*/
- public void enableRcsUceCapability(
+ public void addRcsUceCapability(CapabilityChangeRequest request,
@RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
-
- CapabilityChangeRequest request = new CapabilityChangeRequest();
request.addCapabilitiesToEnableForTech(capability,
ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
request.addCapabilitiesToEnableForTech(capability,
ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN);
- try {
- if (DBG) log("enableRcsUceCapability: " + capability);
- mRcsFeatureConnection.changeEnabledCapabilities(request, null);
- } catch (RemoteException e) {
- loge("enableRcsUceCapability: ", e);
- }
}
/**
* Disable all of the UCE capabilities.
*/
- private void disableAllRcsUceCapabilities() {
+ private void disableAllRcsUceCapabilities() throws android.telephony.ims.ImsException {
final int techLte = ImsRegistrationImplBase.REGISTRATION_TECH_LTE;
final int techIWlan = ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN;
CapabilityChangeRequest request = new CapabilityChangeRequest();
@@ -467,11 +442,17 @@ public class RcsFeatureManager implements IFeatureConnector {
request.addCapabilitiesToDisableForTech(CAPABILITY_OPTIONS, techIWlan);
request.addCapabilitiesToDisableForTech(CAPABILITY_PRESENCE, techLte);
request.addCapabilitiesToDisableForTech(CAPABILITY_PRESENCE, techIWlan);
+ sendCapabilityChangeRequest(request);
+ }
+
+ private void sendCapabilityChangeRequest(CapabilityChangeRequest request)
+ throws android.telephony.ims.ImsException {
try {
- if (DBG) log("disableAllRcsUceCapabilities");
+ if (DBG) log("sendCapabilityChangeRequest: " + request);
mRcsFeatureConnection.changeEnabledCapabilities(request, null);
} catch (RemoteException e) {
- Log.e(TAG, "disableAllRcsUceCapabilities " + e);
+ throw new android.telephony.ims.ImsException("Can not connect to service",
+ android.telephony.ims.ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
@@ -483,21 +464,6 @@ public class RcsFeatureManager implements IFeatureConnector {
return isCapabilityTypeSupported(mContext, mSlotId, CAPABILITY_PRESENCE);
}
- /**
- * Check if RCS UCE feature is supported by carrier.
- */
- public static boolean isRcsUceSupportedByCarrier(Context context, int slotId) {
- boolean isOptionsSupported = isCapabilityTypeSupported(
- context, slotId, CAPABILITY_OPTIONS);
- boolean isPresenceSupported = isCapabilityTypeSupported(
- context, slotId, CAPABILITY_PRESENCE);
-
- if (DBG) Log.d(TAG, "isRcsUceSupportedByCarrier: options=" + isOptionsSupported
- + ", presence=" + isPresenceSupported);
-
- return isOptionsSupported | isPresenceSupported;
- }
-
/*
* Check if the given type of capability is supported.
*/