Loading src/java/com/android/ims/ImsEcbm.java +6 −12 Original line number Diff line number Diff line Loading @@ -39,9 +39,7 @@ import com.android.ims.internal.IImsEcbmListener; import com.android.telephony.Rlog; /** * Provides APIs for the supplementary service settings using IMS (Ut interface). * It is created from 3GPP TS 24.623 (XCAP(XML Configuration Access Protocol) * over the Ut interface for manipulating supplementary services). * Provides APIs for the modem to communicate the CDMA Emergency Callback Mode status for IMS. * * @hide */ Loading @@ -56,13 +54,9 @@ public class ImsEcbm { miEcbm = iEcbm; } public void setEcbmStateListener(ImsEcbmStateListener ecbmListener) throws ImsException { try { miEcbm.setListener(new ImsEcbmListenerProxy(ecbmListener)); } catch (RemoteException e) { throw new ImsException("setEcbmStateListener()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); } public void setEcbmStateListener(ImsEcbmStateListener ecbmListener) throws RemoteException { miEcbm.setListener(ecbmListener != null ? new ImsEcbmListenerProxy(ecbmListener) : null); } @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) Loading @@ -82,8 +76,8 @@ public class ImsEcbm { /** * Adapter class for {@link IImsEcbmListener}. */ private class ImsEcbmListenerProxy extends IImsEcbmListener.Stub { private ImsEcbmStateListener mListener; private static class ImsEcbmListenerProxy extends IImsEcbmListener.Stub { private final ImsEcbmStateListener mListener; public ImsEcbmListenerProxy(ImsEcbmStateListener listener) { mListener = listener; Loading src/java/com/android/ims/ImsManager.java +30 −47 Original line number Diff line number Diff line Loading @@ -1729,18 +1729,23 @@ public class ImsManager implements FeatureUpdates { } /** * Opens the IMS service for making calls and/or receiving generic IMS calls. * Opens the IMS service for making calls and/or receiving generic IMS calls as well as * register listeners for ECBM, Multiendpoint, and UT if the ImsService supports it. * <p> * The caller may make subsequent calls through {@link #makeCall}. * The IMS service will register the device to the operator's network with the credentials * (from ISIM) periodically in order to receive calls from the operator's network. * When the IMS service receives a new call, it will call * {@link MmTelFeature.Listener#onIncomingCall} * @param listener A {@link MmTelFeature.Listener}, which is the interface the * {@link MmTelFeature} uses to notify the framework of updates * {@link MmTelFeature} uses to notify the framework of updates. * @param ecbmListener Listener used for ECBM indications. * @param multiEndpointListener Listener used for multiEndpoint indications. * @throws NullPointerException if {@code listener} is null * @throws ImsException if calling the IMS service results in an error */ public void open(MmTelFeature.Listener listener) throws ImsException { public void open(MmTelFeature.Listener listener, ImsEcbmStateListener ecbmListener, ImsExternalCallStateListener multiEndpointListener) throws ImsException { MmTelFeatureConnection c = getOrThrowExceptionIfServiceUnavailable(); if (listener == null) { Loading @@ -1748,7 +1753,7 @@ public class ImsManager implements FeatureUpdates { } try { c.openConnection(listener); c.openConnection(listener, ecbmListener, multiEndpointListener); } catch (RemoteException e) { throw new ImsException("open()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); } Loading Loading @@ -1893,16 +1898,18 @@ public class ImsManager implements FeatureUpdates { /** * Removes a previously registered {@link ImsMmTelManager.CapabilityCallback} callback. * @throws ImsException when the ImsService connection is not available. */ public void removeCapabilitiesCallback(ImsMmTelManager.CapabilityCallback callback) throws ImsException { public void removeCapabilitiesCallback(ImsMmTelManager.CapabilityCallback callback) { if (callback == null) { throw new NullPointerException("capabilities callback can't be null"); } try { MmTelFeatureConnection c = getOrThrowExceptionIfServiceUnavailable(); c.removeCapabilityCallback(callback.getBinder()); } catch (ImsException e) { log("Exception removing Capability , exception=" + e); } } /** Loading Loading @@ -2007,24 +2014,27 @@ public class ImsManager implements FeatureUpdates { } /** * Closes the connection and removes all active callbacks. * All the resources that were allocated to the service are also released. * Closes the connection opened in {@link #open} and removes the associated listeners. */ public void close() { mMmTelConnectionRef.get().closeConnection(); } /** * Gets the configuration interface to provision / withdraw the supplementary service settings. * Create or get the existing configuration interface to provision / withdraw the supplementary * service settings. * <p> * There can only be one connection to the UT interface, so this may only be called by one * ImsManager instance. Otherwise, an IllegalStateException will be thrown. * * @return the Ut interface instance * @throws ImsException if getting the Ut interface results in an error */ public ImsUtInterface getSupplementaryServiceConfiguration() throws ImsException { public ImsUtInterface createOrGetSupplementaryServiceConfiguration() throws ImsException { ImsUt iUt; MmTelFeatureConnection c = getOrThrowExceptionIfServiceUnavailable(); try { iUt = c.getUtInterface(); iUt = c.createOrGetUtInterface(); if (iUt == null) { throw new ImsException("getSupplementaryServiceConfiguration()", ImsReasonInfo.CODE_UT_NOT_SUPPORTED); Loading Loading @@ -2657,24 +2667,20 @@ public class ImsManager implements FeatureUpdates { /** * Gets the ECBM interface to request ECBM exit. * <p> * This should only be called after {@link #open} has been called. * * @return the ECBM interface instance * @throws ImsException if getting the ECBM interface results in an error */ public ImsEcbm getEcbmInterface() throws ImsException { ImsEcbm iEcbm = null; MmTelFeatureConnection c = getOrThrowExceptionIfServiceUnavailable(); try { iEcbm = c.getEcbmInterface(); ImsEcbm iEcbm = c.getEcbmInterface(); if (iEcbm == null) { throw new ImsException("getEcbmInterface()", ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED); } } catch (RemoteException e) { throw new ImsException("getEcbmInterface()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); } return iEcbm; } Loading Loading @@ -2754,29 +2760,6 @@ public class ImsManager implements FeatureUpdates { } } /** * Gets the Multi-Endpoint interface to subscribe to multi-enpoint notifications.. * * @return the multi-endpoint interface instance * @throws ImsException if getting the multi-endpoint interface results in an error */ public ImsMultiEndpoint getMultiEndpointInterface() throws ImsException { ImsMultiEndpoint iImsMultiEndpoint; try { iImsMultiEndpoint = mMmTelConnectionRef.get().getMultiEndpointInterface(); if (iImsMultiEndpoint == null) { throw new ImsException("getMultiEndpointInterface()", ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED); } } catch (RemoteException e) { throw new ImsException("getMultiEndpointInterface()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); } return iImsMultiEndpoint; } /** * Resets ImsManager settings back to factory defaults. * Loading src/java/com/android/ims/ImsMultiEndpoint.java +4 −9 Original line number Diff line number Diff line Loading @@ -70,15 +70,10 @@ public class ImsMultiEndpoint { } public void setExternalCallStateListener(ImsExternalCallStateListener externalCallStateListener) throws ImsException { try { throws RemoteException { if (DBG) Rlog.d(TAG, "setExternalCallStateListener"); mImsMultiendpoint.setListener(new ImsExternalCallStateListenerProxy( externalCallStateListener)); } catch (RemoteException e) { throw new ImsException("setExternalCallStateListener could not be set.", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); } mImsMultiendpoint.setListener(externalCallStateListener != null ? new ImsExternalCallStateListenerProxy(externalCallStateListener) : null); } public boolean isBinderAlive() { Loading src/java/com/android/ims/MmTelFeatureConnection.java +127 −35 Original line number Diff line number Diff line Loading @@ -16,12 +16,12 @@ package com.android.ims; import android.annotation.NonNull; import android.content.Context; import android.os.Binder; import android.os.IBinder; import android.os.IInterface; import android.os.Message; import android.os.RemoteException; import android.telephony.TelephonyManager; import android.telephony.ims.ImsCallProfile; import android.telephony.ims.ImsService; import android.telephony.ims.RtpHeaderExtensionType; Loading @@ -34,8 +34,8 @@ import android.telephony.ims.aidl.IImsRegistrationCallback; import android.telephony.ims.aidl.IImsSmsListener; import android.telephony.ims.aidl.ISipTransport; import android.telephony.ims.feature.CapabilityChangeRequest; import android.telephony.ims.feature.ImsFeature; import android.telephony.ims.feature.MmTelFeature; import android.telephony.ims.stub.ImsEcbmImplBase; import android.telephony.ims.stub.ImsSmsImplBase; import android.util.Log; Loading @@ -43,9 +43,9 @@ import com.android.ims.internal.IImsCallSession; import com.android.ims.internal.IImsEcbm; import com.android.ims.internal.IImsMultiEndpoint; import com.android.ims.internal.IImsUt; import com.android.telephony.Rlog; import java.util.ArrayList; import java.util.Optional; import java.util.Set; /** Loading Loading @@ -197,12 +197,54 @@ public class MmTelFeatureConnection extends FeatureConnection { } } private static final class BinderAccessState<T> { /** * We have not tried to get the interface yet. */ static final int STATE_NOT_SET = 0; /** * We have tried to get the interface, but it is not supported. */ static final int STATE_NOT_SUPPORTED = 1; /** * The interface is available from the service. */ static final int STATE_AVAILABLE = 2; public static <T> BinderAccessState<T> of(T value) { return new BinderAccessState<>(value); } private final int mState; private final T mInterface; public BinderAccessState(int state) { mState = state; mInterface = null; } public BinderAccessState(T binderInterface) { mState = STATE_AVAILABLE; mInterface = binderInterface; } public int getState() { return mState; } public T getInterface() { return mInterface; } } // Updated by IImsServiceFeatureCallback when FEATURE_EMERGENCY_MMTEL is sent. private boolean mSupportsEmergencyCalling = false; // MMTEL specific binder Interfaces private BinderAccessState<ImsEcbm> mEcbm = new BinderAccessState<>(BinderAccessState.STATE_NOT_SET); private BinderAccessState<ImsMultiEndpoint> mMultiEndpoint = new BinderAccessState<>(BinderAccessState.STATE_NOT_SET); private MmTelFeature.Listener mMmTelFeatureListener; private ImsUt mUt; private ImsEcbm mEcbm; private ImsMultiEndpoint mMultiEndpoint; private final ImsRegistrationCallbackAdapter mRegistrationCallbackManager; private final CapabilityCallbackManager mCapabilityCallbackManager; Loading @@ -220,9 +262,23 @@ public class MmTelFeatureConnection extends FeatureConnection { @Override protected void onRemovedOrDied() { // Release all callbacks being tracked and unregister them from the connected MmTelFeature. mRegistrationCallbackManager.close(); mCapabilityCallbackManager.close(); mProvisioningCallbackManager.close(); // Close mUt interface separately from other listeners, as it is not tied directly to // calling. There is still a limitation currently that only one UT listener can be set // (through ImsPhoneCallTracker), but this could be relaxed in the future via the ability // to register multiple callbacks. synchronized (mLock) { if (mUt != null) { mUt.close(); mUt = null; } closeConnection(); super.onRemovedOrDied(); } } public boolean isEmergencyMmTelAvailable() { return mSupportsEmergencyCalling; Loading @@ -232,37 +288,45 @@ public class MmTelFeatureConnection extends FeatureConnection { * Opens the connection to the {@link MmTelFeature} and establishes a listener back to the * framework. Calling this method multiple times will reset the listener attached to the * {@link MmTelFeature}. * @param listener A {@link MmTelFeature.Listener} that will be used by the {@link MmTelFeature} * to notify the framework of updates. * @param mmTelListener A {@link MmTelFeature.Listener} that will be used by the * {@link MmTelFeature} to notify the framework of mmtel calling updates. * @param ecbmListener Listener used to listen for ECBM updates from {@link ImsEcbmImplBase} * implementation. */ public void openConnection(MmTelFeature.Listener listener) throws RemoteException { public void openConnection(MmTelFeature.Listener mmTelListener, ImsEcbmStateListener ecbmListener, ImsExternalCallStateListener multiEndpointListener) throws RemoteException { synchronized (mLock) { checkServiceIsReady(); getServiceInterface(mBinder).setListener(listener); mMmTelFeatureListener = mmTelListener; getServiceInterface(mBinder).setListener(mmTelListener); setEcbmInterface(ecbmListener); setMultiEndpointInterface(multiEndpointListener); } } /** * Clean up all caches as well as any callbacks that are currently associated with the * MmTelFeature. * Closes the connection to the {@link MmTelFeature} if it was previously opened via * {@link #openConnection} by removing all listeners. */ public void closeConnection() { mRegistrationCallbackManager.close(); mCapabilityCallbackManager.close(); mProvisioningCallbackManager.close(); synchronized (mLock) { if (mUt != null) { mUt.close(); mUt = null; } mEcbm = null; mMultiEndpoint = null; if (!isBinderAlive()) return; try { if (isBinderAlive()) { if (mMmTelFeatureListener != null) { mMmTelFeatureListener = null; getServiceInterface(mBinder).setListener(null); } if (mEcbm.getState() == BinderAccessState.STATE_AVAILABLE) { mEcbm.getInterface().setEcbmStateListener(null); mEcbm = new BinderAccessState<>(BinderAccessState.STATE_NOT_SET); } if (mMultiEndpoint.getState() == BinderAccessState.STATE_AVAILABLE) { mMultiEndpoint.getInterface().setExternalCallStateListener(null); mMultiEndpoint = new BinderAccessState<>(BinderAccessState.STATE_NOT_SET); } } catch (RemoteException e) { Log.w(TAG + " [" + mSlotId + "]", "closeConnection: couldn't remove listener!"); Log.w(TAG + " [" + mSlotId + "]", "closeConnection: couldn't remove listeners!"); } } } Loading Loading @@ -363,25 +427,45 @@ public class MmTelFeatureConnection extends FeatureConnection { } } public ImsUt getUtInterface() throws RemoteException { public ImsUt createOrGetUtInterface() throws RemoteException { synchronized (mLock) { if (mUt != null) return mUt; checkServiceIsReady(); IImsUt imsUt = getServiceInterface(mBinder).getUtInterface(); // This will internally set up a listener on the ImsUtImplBase interface, and there is // a limitation that there can only be one. If multiple connections try to create this // UT interface, it will throw an IllegalStateException. mUt = (imsUt != null) ? new ImsUt(imsUt) : null; return mUt; } } public ImsEcbm getEcbmInterface() throws RemoteException { private void setEcbmInterface(ImsEcbmStateListener ecbmListener) throws RemoteException { synchronized (mLock) { if (mEcbm != null) return mEcbm; if (mEcbm.getState() != BinderAccessState.STATE_NOT_SET) { throw new IllegalStateException("ECBM interface already open"); } checkServiceIsReady(); IImsEcbm imsEcbm = getServiceInterface(mBinder).getEcbmInterface(); mEcbm = (imsEcbm != null) ? new ImsEcbm(imsEcbm) : null; return mEcbm; mEcbm = (imsEcbm != null) ? BinderAccessState.of(new ImsEcbm(imsEcbm)) : new BinderAccessState<>(BinderAccessState.STATE_NOT_SUPPORTED); if (mEcbm.getState() == BinderAccessState.STATE_AVAILABLE) { // May throw an IllegalStateException if a listener already exists. mEcbm.getInterface().setEcbmStateListener(ecbmListener); } } } public ImsEcbm getEcbmInterface() { synchronized (mLock) { if (mEcbm.getState() == BinderAccessState.STATE_NOT_SET) { throw new IllegalStateException("ECBM interface has not been opened"); } return mEcbm.getState() == BinderAccessState.STATE_AVAILABLE ? mEcbm.getInterface() : null; } } Loading @@ -393,14 +477,22 @@ public class MmTelFeatureConnection extends FeatureConnection { } } public ImsMultiEndpoint getMultiEndpointInterface() throws RemoteException { private void setMultiEndpointInterface(ImsExternalCallStateListener listener) throws RemoteException { synchronized (mLock) { if(mMultiEndpoint != null) return mMultiEndpoint; if (mMultiEndpoint.getState() != BinderAccessState.STATE_NOT_SET) { throw new IllegalStateException("multiendpoint interface is already open"); } checkServiceIsReady(); IImsMultiEndpoint imEndpoint = getServiceInterface(mBinder).getMultiEndpointInterface(); mMultiEndpoint = (imEndpoint != null) ? new ImsMultiEndpoint(imEndpoint) : null; return mMultiEndpoint; mMultiEndpoint = (imEndpoint != null) ? BinderAccessState.of(new ImsMultiEndpoint(imEndpoint)) : new BinderAccessState<>(BinderAccessState.STATE_NOT_SUPPORTED); if (mMultiEndpoint.getState() == BinderAccessState.STATE_AVAILABLE) { // May throw an IllegalStateException if a listener already exists. mMultiEndpoint.getInterface().setExternalCallStateListener(listener); } } } Loading Loading
src/java/com/android/ims/ImsEcbm.java +6 −12 Original line number Diff line number Diff line Loading @@ -39,9 +39,7 @@ import com.android.ims.internal.IImsEcbmListener; import com.android.telephony.Rlog; /** * Provides APIs for the supplementary service settings using IMS (Ut interface). * It is created from 3GPP TS 24.623 (XCAP(XML Configuration Access Protocol) * over the Ut interface for manipulating supplementary services). * Provides APIs for the modem to communicate the CDMA Emergency Callback Mode status for IMS. * * @hide */ Loading @@ -56,13 +54,9 @@ public class ImsEcbm { miEcbm = iEcbm; } public void setEcbmStateListener(ImsEcbmStateListener ecbmListener) throws ImsException { try { miEcbm.setListener(new ImsEcbmListenerProxy(ecbmListener)); } catch (RemoteException e) { throw new ImsException("setEcbmStateListener()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); } public void setEcbmStateListener(ImsEcbmStateListener ecbmListener) throws RemoteException { miEcbm.setListener(ecbmListener != null ? new ImsEcbmListenerProxy(ecbmListener) : null); } @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) Loading @@ -82,8 +76,8 @@ public class ImsEcbm { /** * Adapter class for {@link IImsEcbmListener}. */ private class ImsEcbmListenerProxy extends IImsEcbmListener.Stub { private ImsEcbmStateListener mListener; private static class ImsEcbmListenerProxy extends IImsEcbmListener.Stub { private final ImsEcbmStateListener mListener; public ImsEcbmListenerProxy(ImsEcbmStateListener listener) { mListener = listener; Loading
src/java/com/android/ims/ImsManager.java +30 −47 Original line number Diff line number Diff line Loading @@ -1729,18 +1729,23 @@ public class ImsManager implements FeatureUpdates { } /** * Opens the IMS service for making calls and/or receiving generic IMS calls. * Opens the IMS service for making calls and/or receiving generic IMS calls as well as * register listeners for ECBM, Multiendpoint, and UT if the ImsService supports it. * <p> * The caller may make subsequent calls through {@link #makeCall}. * The IMS service will register the device to the operator's network with the credentials * (from ISIM) periodically in order to receive calls from the operator's network. * When the IMS service receives a new call, it will call * {@link MmTelFeature.Listener#onIncomingCall} * @param listener A {@link MmTelFeature.Listener}, which is the interface the * {@link MmTelFeature} uses to notify the framework of updates * {@link MmTelFeature} uses to notify the framework of updates. * @param ecbmListener Listener used for ECBM indications. * @param multiEndpointListener Listener used for multiEndpoint indications. * @throws NullPointerException if {@code listener} is null * @throws ImsException if calling the IMS service results in an error */ public void open(MmTelFeature.Listener listener) throws ImsException { public void open(MmTelFeature.Listener listener, ImsEcbmStateListener ecbmListener, ImsExternalCallStateListener multiEndpointListener) throws ImsException { MmTelFeatureConnection c = getOrThrowExceptionIfServiceUnavailable(); if (listener == null) { Loading @@ -1748,7 +1753,7 @@ public class ImsManager implements FeatureUpdates { } try { c.openConnection(listener); c.openConnection(listener, ecbmListener, multiEndpointListener); } catch (RemoteException e) { throw new ImsException("open()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); } Loading Loading @@ -1893,16 +1898,18 @@ public class ImsManager implements FeatureUpdates { /** * Removes a previously registered {@link ImsMmTelManager.CapabilityCallback} callback. * @throws ImsException when the ImsService connection is not available. */ public void removeCapabilitiesCallback(ImsMmTelManager.CapabilityCallback callback) throws ImsException { public void removeCapabilitiesCallback(ImsMmTelManager.CapabilityCallback callback) { if (callback == null) { throw new NullPointerException("capabilities callback can't be null"); } try { MmTelFeatureConnection c = getOrThrowExceptionIfServiceUnavailable(); c.removeCapabilityCallback(callback.getBinder()); } catch (ImsException e) { log("Exception removing Capability , exception=" + e); } } /** Loading Loading @@ -2007,24 +2014,27 @@ public class ImsManager implements FeatureUpdates { } /** * Closes the connection and removes all active callbacks. * All the resources that were allocated to the service are also released. * Closes the connection opened in {@link #open} and removes the associated listeners. */ public void close() { mMmTelConnectionRef.get().closeConnection(); } /** * Gets the configuration interface to provision / withdraw the supplementary service settings. * Create or get the existing configuration interface to provision / withdraw the supplementary * service settings. * <p> * There can only be one connection to the UT interface, so this may only be called by one * ImsManager instance. Otherwise, an IllegalStateException will be thrown. * * @return the Ut interface instance * @throws ImsException if getting the Ut interface results in an error */ public ImsUtInterface getSupplementaryServiceConfiguration() throws ImsException { public ImsUtInterface createOrGetSupplementaryServiceConfiguration() throws ImsException { ImsUt iUt; MmTelFeatureConnection c = getOrThrowExceptionIfServiceUnavailable(); try { iUt = c.getUtInterface(); iUt = c.createOrGetUtInterface(); if (iUt == null) { throw new ImsException("getSupplementaryServiceConfiguration()", ImsReasonInfo.CODE_UT_NOT_SUPPORTED); Loading Loading @@ -2657,24 +2667,20 @@ public class ImsManager implements FeatureUpdates { /** * Gets the ECBM interface to request ECBM exit. * <p> * This should only be called after {@link #open} has been called. * * @return the ECBM interface instance * @throws ImsException if getting the ECBM interface results in an error */ public ImsEcbm getEcbmInterface() throws ImsException { ImsEcbm iEcbm = null; MmTelFeatureConnection c = getOrThrowExceptionIfServiceUnavailable(); try { iEcbm = c.getEcbmInterface(); ImsEcbm iEcbm = c.getEcbmInterface(); if (iEcbm == null) { throw new ImsException("getEcbmInterface()", ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED); } } catch (RemoteException e) { throw new ImsException("getEcbmInterface()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); } return iEcbm; } Loading Loading @@ -2754,29 +2760,6 @@ public class ImsManager implements FeatureUpdates { } } /** * Gets the Multi-Endpoint interface to subscribe to multi-enpoint notifications.. * * @return the multi-endpoint interface instance * @throws ImsException if getting the multi-endpoint interface results in an error */ public ImsMultiEndpoint getMultiEndpointInterface() throws ImsException { ImsMultiEndpoint iImsMultiEndpoint; try { iImsMultiEndpoint = mMmTelConnectionRef.get().getMultiEndpointInterface(); if (iImsMultiEndpoint == null) { throw new ImsException("getMultiEndpointInterface()", ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED); } } catch (RemoteException e) { throw new ImsException("getMultiEndpointInterface()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); } return iImsMultiEndpoint; } /** * Resets ImsManager settings back to factory defaults. * Loading
src/java/com/android/ims/ImsMultiEndpoint.java +4 −9 Original line number Diff line number Diff line Loading @@ -70,15 +70,10 @@ public class ImsMultiEndpoint { } public void setExternalCallStateListener(ImsExternalCallStateListener externalCallStateListener) throws ImsException { try { throws RemoteException { if (DBG) Rlog.d(TAG, "setExternalCallStateListener"); mImsMultiendpoint.setListener(new ImsExternalCallStateListenerProxy( externalCallStateListener)); } catch (RemoteException e) { throw new ImsException("setExternalCallStateListener could not be set.", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); } mImsMultiendpoint.setListener(externalCallStateListener != null ? new ImsExternalCallStateListenerProxy(externalCallStateListener) : null); } public boolean isBinderAlive() { Loading
src/java/com/android/ims/MmTelFeatureConnection.java +127 −35 Original line number Diff line number Diff line Loading @@ -16,12 +16,12 @@ package com.android.ims; import android.annotation.NonNull; import android.content.Context; import android.os.Binder; import android.os.IBinder; import android.os.IInterface; import android.os.Message; import android.os.RemoteException; import android.telephony.TelephonyManager; import android.telephony.ims.ImsCallProfile; import android.telephony.ims.ImsService; import android.telephony.ims.RtpHeaderExtensionType; Loading @@ -34,8 +34,8 @@ import android.telephony.ims.aidl.IImsRegistrationCallback; import android.telephony.ims.aidl.IImsSmsListener; import android.telephony.ims.aidl.ISipTransport; import android.telephony.ims.feature.CapabilityChangeRequest; import android.telephony.ims.feature.ImsFeature; import android.telephony.ims.feature.MmTelFeature; import android.telephony.ims.stub.ImsEcbmImplBase; import android.telephony.ims.stub.ImsSmsImplBase; import android.util.Log; Loading @@ -43,9 +43,9 @@ import com.android.ims.internal.IImsCallSession; import com.android.ims.internal.IImsEcbm; import com.android.ims.internal.IImsMultiEndpoint; import com.android.ims.internal.IImsUt; import com.android.telephony.Rlog; import java.util.ArrayList; import java.util.Optional; import java.util.Set; /** Loading Loading @@ -197,12 +197,54 @@ public class MmTelFeatureConnection extends FeatureConnection { } } private static final class BinderAccessState<T> { /** * We have not tried to get the interface yet. */ static final int STATE_NOT_SET = 0; /** * We have tried to get the interface, but it is not supported. */ static final int STATE_NOT_SUPPORTED = 1; /** * The interface is available from the service. */ static final int STATE_AVAILABLE = 2; public static <T> BinderAccessState<T> of(T value) { return new BinderAccessState<>(value); } private final int mState; private final T mInterface; public BinderAccessState(int state) { mState = state; mInterface = null; } public BinderAccessState(T binderInterface) { mState = STATE_AVAILABLE; mInterface = binderInterface; } public int getState() { return mState; } public T getInterface() { return mInterface; } } // Updated by IImsServiceFeatureCallback when FEATURE_EMERGENCY_MMTEL is sent. private boolean mSupportsEmergencyCalling = false; // MMTEL specific binder Interfaces private BinderAccessState<ImsEcbm> mEcbm = new BinderAccessState<>(BinderAccessState.STATE_NOT_SET); private BinderAccessState<ImsMultiEndpoint> mMultiEndpoint = new BinderAccessState<>(BinderAccessState.STATE_NOT_SET); private MmTelFeature.Listener mMmTelFeatureListener; private ImsUt mUt; private ImsEcbm mEcbm; private ImsMultiEndpoint mMultiEndpoint; private final ImsRegistrationCallbackAdapter mRegistrationCallbackManager; private final CapabilityCallbackManager mCapabilityCallbackManager; Loading @@ -220,9 +262,23 @@ public class MmTelFeatureConnection extends FeatureConnection { @Override protected void onRemovedOrDied() { // Release all callbacks being tracked and unregister them from the connected MmTelFeature. mRegistrationCallbackManager.close(); mCapabilityCallbackManager.close(); mProvisioningCallbackManager.close(); // Close mUt interface separately from other listeners, as it is not tied directly to // calling. There is still a limitation currently that only one UT listener can be set // (through ImsPhoneCallTracker), but this could be relaxed in the future via the ability // to register multiple callbacks. synchronized (mLock) { if (mUt != null) { mUt.close(); mUt = null; } closeConnection(); super.onRemovedOrDied(); } } public boolean isEmergencyMmTelAvailable() { return mSupportsEmergencyCalling; Loading @@ -232,37 +288,45 @@ public class MmTelFeatureConnection extends FeatureConnection { * Opens the connection to the {@link MmTelFeature} and establishes a listener back to the * framework. Calling this method multiple times will reset the listener attached to the * {@link MmTelFeature}. * @param listener A {@link MmTelFeature.Listener} that will be used by the {@link MmTelFeature} * to notify the framework of updates. * @param mmTelListener A {@link MmTelFeature.Listener} that will be used by the * {@link MmTelFeature} to notify the framework of mmtel calling updates. * @param ecbmListener Listener used to listen for ECBM updates from {@link ImsEcbmImplBase} * implementation. */ public void openConnection(MmTelFeature.Listener listener) throws RemoteException { public void openConnection(MmTelFeature.Listener mmTelListener, ImsEcbmStateListener ecbmListener, ImsExternalCallStateListener multiEndpointListener) throws RemoteException { synchronized (mLock) { checkServiceIsReady(); getServiceInterface(mBinder).setListener(listener); mMmTelFeatureListener = mmTelListener; getServiceInterface(mBinder).setListener(mmTelListener); setEcbmInterface(ecbmListener); setMultiEndpointInterface(multiEndpointListener); } } /** * Clean up all caches as well as any callbacks that are currently associated with the * MmTelFeature. * Closes the connection to the {@link MmTelFeature} if it was previously opened via * {@link #openConnection} by removing all listeners. */ public void closeConnection() { mRegistrationCallbackManager.close(); mCapabilityCallbackManager.close(); mProvisioningCallbackManager.close(); synchronized (mLock) { if (mUt != null) { mUt.close(); mUt = null; } mEcbm = null; mMultiEndpoint = null; if (!isBinderAlive()) return; try { if (isBinderAlive()) { if (mMmTelFeatureListener != null) { mMmTelFeatureListener = null; getServiceInterface(mBinder).setListener(null); } if (mEcbm.getState() == BinderAccessState.STATE_AVAILABLE) { mEcbm.getInterface().setEcbmStateListener(null); mEcbm = new BinderAccessState<>(BinderAccessState.STATE_NOT_SET); } if (mMultiEndpoint.getState() == BinderAccessState.STATE_AVAILABLE) { mMultiEndpoint.getInterface().setExternalCallStateListener(null); mMultiEndpoint = new BinderAccessState<>(BinderAccessState.STATE_NOT_SET); } } catch (RemoteException e) { Log.w(TAG + " [" + mSlotId + "]", "closeConnection: couldn't remove listener!"); Log.w(TAG + " [" + mSlotId + "]", "closeConnection: couldn't remove listeners!"); } } } Loading Loading @@ -363,25 +427,45 @@ public class MmTelFeatureConnection extends FeatureConnection { } } public ImsUt getUtInterface() throws RemoteException { public ImsUt createOrGetUtInterface() throws RemoteException { synchronized (mLock) { if (mUt != null) return mUt; checkServiceIsReady(); IImsUt imsUt = getServiceInterface(mBinder).getUtInterface(); // This will internally set up a listener on the ImsUtImplBase interface, and there is // a limitation that there can only be one. If multiple connections try to create this // UT interface, it will throw an IllegalStateException. mUt = (imsUt != null) ? new ImsUt(imsUt) : null; return mUt; } } public ImsEcbm getEcbmInterface() throws RemoteException { private void setEcbmInterface(ImsEcbmStateListener ecbmListener) throws RemoteException { synchronized (mLock) { if (mEcbm != null) return mEcbm; if (mEcbm.getState() != BinderAccessState.STATE_NOT_SET) { throw new IllegalStateException("ECBM interface already open"); } checkServiceIsReady(); IImsEcbm imsEcbm = getServiceInterface(mBinder).getEcbmInterface(); mEcbm = (imsEcbm != null) ? new ImsEcbm(imsEcbm) : null; return mEcbm; mEcbm = (imsEcbm != null) ? BinderAccessState.of(new ImsEcbm(imsEcbm)) : new BinderAccessState<>(BinderAccessState.STATE_NOT_SUPPORTED); if (mEcbm.getState() == BinderAccessState.STATE_AVAILABLE) { // May throw an IllegalStateException if a listener already exists. mEcbm.getInterface().setEcbmStateListener(ecbmListener); } } } public ImsEcbm getEcbmInterface() { synchronized (mLock) { if (mEcbm.getState() == BinderAccessState.STATE_NOT_SET) { throw new IllegalStateException("ECBM interface has not been opened"); } return mEcbm.getState() == BinderAccessState.STATE_AVAILABLE ? mEcbm.getInterface() : null; } } Loading @@ -393,14 +477,22 @@ public class MmTelFeatureConnection extends FeatureConnection { } } public ImsMultiEndpoint getMultiEndpointInterface() throws RemoteException { private void setMultiEndpointInterface(ImsExternalCallStateListener listener) throws RemoteException { synchronized (mLock) { if(mMultiEndpoint != null) return mMultiEndpoint; if (mMultiEndpoint.getState() != BinderAccessState.STATE_NOT_SET) { throw new IllegalStateException("multiendpoint interface is already open"); } checkServiceIsReady(); IImsMultiEndpoint imEndpoint = getServiceInterface(mBinder).getMultiEndpointInterface(); mMultiEndpoint = (imEndpoint != null) ? new ImsMultiEndpoint(imEndpoint) : null; return mMultiEndpoint; mMultiEndpoint = (imEndpoint != null) ? BinderAccessState.of(new ImsMultiEndpoint(imEndpoint)) : new BinderAccessState<>(BinderAccessState.STATE_NOT_SUPPORTED); if (mMultiEndpoint.getState() == BinderAccessState.STATE_AVAILABLE) { // May throw an IllegalStateException if a listener already exists. mMultiEndpoint.getInterface().setExternalCallStateListener(listener); } } } Loading