diff options
author | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-02-07 17:54:26 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-02-07 17:54:26 +0000 |
commit | d193fbd550015d567e68090ddc114bb9fb03ea6d (patch) | |
tree | c4bb9bf3a5c7c488fb0e2a2aa51f99c5a73df74b | |
parent | 4cc06444e27b9a6e775799e11873f3fc75ba70e5 (diff) | |
parent | 6e27787a8e84d20c8589dd654d001e4a24318ad4 (diff) | |
download | ims-d193fbd550015d567e68090ddc114bb9fb03ea6d.tar.gz |
Merge "Refactor RcsFEatureManager to be created from TelephonyRcsService" am: 6e27787a8e
Change-Id: I68e0e13482ce0012757d0a9693bef416b7d4f2bf
-rw-r--r-- | src/java/com/android/ims/FeatureConnector.java | 23 | ||||
-rw-r--r-- | src/java/com/android/ims/IFeatureConnector.java | 4 | ||||
-rw-r--r-- | src/java/com/android/ims/ImsCallbackAdapterManager.java | 12 | ||||
-rw-r--r-- | src/java/com/android/ims/ImsManager.java | 11 | ||||
-rw-r--r-- | src/java/com/android/ims/MmTelFeatureConnection.java | 14 | ||||
-rw-r--r-- | src/java/com/android/ims/RcsFeatureConnection.java | 195 | ||||
-rw-r--r-- | src/java/com/android/ims/RcsFeatureManager.java | 420 |
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 39d9e503..2e696ba7 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. */ |