diff options
author | Brad Ebinger <breadley@google.com> | 2018-01-17 23:01:09 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2018-01-17 23:01:09 +0000 |
commit | 79e74c78aed874589af8cb82ac4b8eb153248ba1 (patch) | |
tree | 641f21d864b6657a2c8b313cf9a5c36d96f8d186 | |
parent | e0e696b0c10c3e361c776cab45a80c18a740cb68 (diff) | |
parent | 0e170c7f6ca88c32d45ad5b4a932b6808956d472 (diff) | |
download | ims-79e74c78aed874589af8cb82ac4b8eb153248ba1.tar.gz |
Integrate Registration APIs
am: 0e170c7f6c
Change-Id: If262feac39f40a3c59a4b0ad1e810c72568df231
-rw-r--r-- | src/java/com/android/ims/ImsConnectionStateListener.java | 35 | ||||
-rw-r--r-- | src/java/com/android/ims/ImsManager.java | 147 | ||||
-rw-r--r-- | src/java/com/android/ims/ImsServiceProxy.java | 76 | ||||
-rw-r--r-- | src/java/com/android/ims/ImsServiceProxyCompat.java | 27 |
4 files changed, 215 insertions, 70 deletions
diff --git a/src/java/com/android/ims/ImsConnectionStateListener.java b/src/java/com/android/ims/ImsConnectionStateListener.java index 4425854b..216bc410 100644 --- a/src/java/com/android/ims/ImsConnectionStateListener.java +++ b/src/java/com/android/ims/ImsConnectionStateListener.java @@ -17,15 +17,42 @@ package com.android.ims; import android.net.Uri; +import android.telephony.ims.stub.ImsRegistrationImplBase; /** * Listener for receiving notifications about changes to the IMS connection. * It provides a state of IMS registration between UE and IMS network, the service * availability of the local device during IMS registered. - * + * @Deprecated Use {@link ImsRegistrationImplBase.Callback} instead. * @hide */ -public class ImsConnectionStateListener { +public class ImsConnectionStateListener extends ImsRegistrationImplBase.Callback { + + @Override + public final void onRegistered(@ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech) { + onImsConnected(imsRadioTech); + } + + @Override + public final void onRegistering(@ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech) { + onImsProgressing(imsRadioTech); + } + + @Override + public final void onDeregistered(ImsReasonInfo info) { + onImsDisconnected(info); + } + + @Override + public final void onTechnologyChangeFailed( + @ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech, ImsReasonInfo info) { + onRegistrationChangeFailed(imsRadioTech, info); + } + + @Override + public void onSubscriberAssociatedUriChanged(Uri[] uris) { + registrationAssociatedUriChanged(uris); + } /** * Called when the device is connected to the IMS network with {@param imsRadioTech}. */ @@ -50,6 +77,7 @@ public class ImsConnectionStateListener { /** * Called when its suspended IMS connection is resumed, meaning the connection * now allows throughput. + * @deprecated not used in newer IMS provider implementations. */ public void onImsResumed() { // no-op @@ -57,6 +85,7 @@ public class ImsConnectionStateListener { /** * Called when its current IMS connection is suspended, meaning there is no data throughput. + * @deprecated not used in newer IMS provider implementations. */ public void onImsSuspended() { // no-op @@ -64,6 +93,7 @@ public class ImsConnectionStateListener { /** * Called when its current IMS connection feature capability changes. + * @deprecated Not used in newer IMS provider implementations. */ public void onFeatureCapabilityChanged(int serviceClass, int[] enabledFeatures, int[] disabledFeatures) { @@ -72,6 +102,7 @@ public class ImsConnectionStateListener { /** * Called when waiting voice message count changes. + * @deprecated not used in newer IMS provider implementations. */ public void onVoiceMessageCountChanged(int count) { // no-op diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index 56dd0400..8f2e7633 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -28,7 +28,6 @@ import android.os.Message; import android.os.Parcel; import android.os.PersistableBundle; import android.os.RemoteException; -import android.os.ServiceManager; import android.os.SystemProperties; import android.provider.Settings; import android.telecom.TelecomManager; @@ -37,16 +36,14 @@ import android.telephony.Rlog; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; -import android.telephony.ims.feature.ImsFeature; import android.util.Log; import com.android.ims.internal.IImsCallSession; import com.android.ims.internal.IImsConfig; import com.android.ims.internal.IImsEcbm; -import com.android.ims.internal.IImsMMTelFeature; import com.android.ims.internal.IImsMultiEndpoint; +import com.android.ims.internal.IImsRegistrationCallback; import com.android.ims.internal.IImsRegistrationListener; -import com.android.ims.internal.IImsServiceController; import com.android.ims.internal.IImsUt; import com.android.ims.internal.ImsCallSession; import com.android.internal.annotations.VisibleForTesting; @@ -59,6 +56,7 @@ import java.util.HashMap; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; /** * Provides APIs for IMS services, such as initiating IMS calls, and provides access to @@ -83,13 +81,6 @@ public class ImsManager { public static final int PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT = 0; /** - * For accessing the IMS related service. - * Internal use only. - * @hide - */ - private static final String IMS_SERVICE = "ims"; - - /** * The result code to be sent back with the incoming call {@link PendingIntent}. * @see #open(PendingIntent, ImsConnectionStateListener) */ @@ -197,14 +188,20 @@ public class ImsManager { private ImsMultiEndpoint mMultiEndpoint = null; - private Set<ImsServiceProxy.INotifyStatusChanged> mStatusCallbacks = new HashSet<>(); + private Set<ImsServiceProxy.IFeatureUpdate> mStatusCallbacks = new CopyOnWriteArraySet<>(); // Keep track of the ImsRegistrationListenerProxys that have been created so that we can // remove them from the ImsService. private final Set<ImsConnectionStateListener> mRegistrationListeners = new HashSet<>(); - private final ImsRegistrationListenerProxy mRegistrationListenerProxy = + + // Used for compatibility with the old Registration method + // TODO: Remove once the compat layer is in place + private final ImsRegistrationListenerProxy mImsRegistrationListenerProxy = new ImsRegistrationListenerProxy(); + // New API for registration to the ImsService. + private final ImsRegistrationCallback mRegistrationCallback = new ImsRegistrationCallback(); + // When true, we have registered the mRegistrationListenerProxy with the ImsService. Don't do // it again. @@ -1409,7 +1406,7 @@ public class ImsManager { * Adds a callback for status changed events if the binder is already available. If it is not, * this method will throw an ImsException. */ - public void addNotifyStatusChangedCallbackIfAvailable(ImsServiceProxy.INotifyStatusChanged c) + public void addNotifyStatusChangedCallbackIfAvailable(ImsServiceProxy.IFeatureUpdate c) throws ImsException { if (!mImsServiceProxy.isBinderAlive()) { throw new ImsException("Binder is not active!", @@ -1420,6 +1417,14 @@ public class ImsManager { } } + public void removeNotifyStatusChangedCallback(ImsServiceProxy.IFeatureUpdate c) { + if (c != null) { + mStatusCallbacks.remove(c); + } else { + Log.w(TAG, "removeNotifyStatusChangedCallback: callback is null!"); + } + } + /** * Opens the IMS service for making calls and/or receiving generic IMS calls. * The caller may make subsquent calls through {@link #makeCall}. @@ -1504,9 +1509,7 @@ public class ImsManager { * @throws NullPointerException if {@code listener} is null * @throws ImsException if calling the IMS service results in an error */ - public void addRegistrationListener(ImsConnectionStateListener listener) - throws ImsException { - + public void addRegistrationListener(ImsConnectionStateListener listener) throws ImsException { if (listener == null) { throw new NullPointerException("listener can't be null"); } @@ -1515,8 +1518,11 @@ public class ImsManager { if (!mHasRegisteredForProxy) { try { checkAndThrowExceptionIfServiceUnavailable(); - mImsServiceProxy.addRegistrationListener(mRegistrationListenerProxy); - log("RegistrationListenerProxy registered."); + // TODO: Remove once new MmTelFeature is merged in + mImsServiceProxy.addRegistrationListener(mImsRegistrationListenerProxy); + mImsServiceProxy.getRegistration().addRegistrationCallback( + mRegistrationCallback); + log("Registration Callback/Listener registered."); // Only record if there isn't a RemoteException. mHasRegisteredForProxy = true; } catch (RemoteException e) { @@ -1956,53 +1962,31 @@ public class ImsManager { */ private void createImsService() { if (!mConfigDynamicBind) { - // Old method of binding + // Deprecated method of binding Rlog.i(TAG, "Creating ImsService using ServiceManager"); - mImsServiceProxy = getServiceProxyCompat(); + mImsServiceProxy = ImsServiceProxyCompat.create(mPhoneId, mDeathRecipient); } else { Rlog.i(TAG, "Creating ImsService using ImsResolver"); - mImsServiceProxy = getServiceProxy(); + mImsServiceProxy = ImsServiceProxy.create(mContext, mPhoneId); } + // Forwarding interface to tell mStatusCallbacks that the Proxy is unavailable. + mImsServiceProxy.setStatusCallback(new ImsServiceProxy.IFeatureUpdate() { + @Override + public void notifyStateChanged() { + mStatusCallbacks.forEach(ImsServiceProxy.IFeatureUpdate::notifyStateChanged); + } + + @Override + public void notifyUnavailable() { + mStatusCallbacks.forEach(ImsServiceProxy.IFeatureUpdate::notifyUnavailable); + } + }); // We have created a new ImsService connection, signal for re-registration synchronized (mHasRegisteredLock) { mHasRegisteredForProxy = false; } } - // Deprecated method of binding with the ImsService defined in the ServiceManager. - private ImsServiceProxyCompat getServiceProxyCompat() { - IBinder binder = ServiceManager.checkService(IMS_SERVICE); - - if (binder != null) { - try { - binder.linkToDeath(mDeathRecipient, 0); - } catch (RemoteException e) { - } - } - - return new ImsServiceProxyCompat(mPhoneId, binder); - } - - // New method of binding with the ImsResolver - private ImsServiceProxy getServiceProxy() { - TelephonyManager tm = (TelephonyManager) - mContext.getSystemService(Context.TELEPHONY_SERVICE); - ImsServiceProxy serviceProxy = new ImsServiceProxy(mPhoneId, ImsFeature.MMTEL); - serviceProxy.setStatusCallback(() -> mStatusCallbacks.forEach( - ImsServiceProxy.INotifyStatusChanged::notifyStatusChanged)); - // Returns null if the service is not available. - IImsMMTelFeature b = tm.getImsMMTelFeatureAndListen(mPhoneId, - serviceProxy.getListener()); - if (b != null) { - serviceProxy.setBinder(b.asBinder()); - // Trigger the cache to be updated for feature status. - serviceProxy.getFeatureStatus(); - } else { - Rlog.w(TAG, "getServiceProxy: b is null! Phone Id: " + mPhoneId); - } - return serviceProxy; - } - /** * Creates a {@link ImsCallSession} with the specified call profile. * Use other methods, if applicable, instead of interacting with @@ -2333,6 +2317,57 @@ public class ImsManager { } } + // New API for Registration, uses ImsConnectionStateListener for backwards compatibility with + // deprecated APIs. + private class ImsRegistrationCallback extends IImsRegistrationCallback.Stub { + + @Override + public void onRegistered(int imsRadioTech) { + if (DBG) log("onRegistered ::"); + + synchronized (mRegistrationListeners) { + mRegistrationListeners.forEach(l -> l.onRegistered(imsRadioTech)); + } + } + + @Override + public void onRegistering(int imsRadioTech) { + if (DBG) log("onRegistering ::"); + + synchronized (mRegistrationListeners) { + mRegistrationListeners.forEach(l -> l.onRegistering(imsRadioTech)); + } + } + + @Override + public void onDeregistered(ImsReasonInfo imsReasonInfo) { + if (DBG) log("onDeregistered ::"); + + synchronized (mRegistrationListeners) { + mRegistrationListeners.forEach(l -> l.onDeregistered(imsReasonInfo)); + } + } + + @Override + public void onTechnologyChangeFailed(int targetRadioTech, ImsReasonInfo imsReasonInfo) { + if (DBG) log("onTechnologyChangeFailed :: targetAccessTech=" + targetRadioTech + + ", imsReasonInfo=" + imsReasonInfo); + + synchronized (mRegistrationListeners) { + mRegistrationListeners.forEach(l -> l.onTechnologyChangeFailed(targetRadioTech, + imsReasonInfo)); + } + } + + @Override + public void onSubscriberAssociatedUriChanged(Uri[] uris) { + if (DBG) log("onSubscriberAssociatedUriChanged"); + synchronized (mRegistrationListeners) { + mRegistrationListeners.forEach(l -> l.onSubscriberAssociatedUriChanged(uris)); + } + } + } + /** * Gets the ECBM interface to request ECBM exit. * diff --git a/src/java/com/android/ims/ImsServiceProxy.java b/src/java/com/android/ims/ImsServiceProxy.java index f3489194..543e31ef 100644 --- a/src/java/com/android/ims/ImsServiceProxy.java +++ b/src/java/com/android/ims/ImsServiceProxy.java @@ -16,10 +16,14 @@ package com.android.ims; +import android.annotation.Nullable; import android.app.PendingIntent; +import android.content.Context; import android.os.IBinder; import android.os.Message; import android.os.RemoteException; +import android.telephony.Rlog; +import android.telephony.TelephonyManager; import android.telephony.ims.feature.ImsFeature; import android.util.Log; @@ -29,6 +33,7 @@ import com.android.ims.internal.IImsConfig; import com.android.ims.internal.IImsEcbm; import com.android.ims.internal.IImsMMTelFeature; import com.android.ims.internal.IImsMultiEndpoint; +import com.android.ims.internal.IImsRegistration; import com.android.ims.internal.IImsRegistrationListener; import com.android.ims.internal.IImsServiceFeatureCallback; import com.android.ims.internal.IImsUt; @@ -41,20 +46,58 @@ import com.android.ims.internal.IImsUt; public class ImsServiceProxy { - protected String LOG_TAG = "ImsServiceProxy"; + protected static final String TAG = "ImsServiceProxy"; protected final int mSlotId; protected IBinder mBinder; private final int mSupportedFeature; + private Context mContext; // Start by assuming the proxy is available for usage. private boolean mIsAvailable = true; // ImsFeature Status from the ImsService. Cached. private Integer mFeatureStatusCached = null; - private ImsServiceProxy.INotifyStatusChanged mStatusCallback; + private IFeatureUpdate mStatusCallback; private final Object mLock = new Object(); - public interface INotifyStatusChanged { - void notifyStatusChanged(); + public static ImsServiceProxy create(Context context , int slotId) { + ImsServiceProxy serviceProxy = new ImsServiceProxy(context, slotId, ImsFeature.MMTEL); + + TelephonyManager tm = getTelephonyManager(context); + if (tm == null) { + Rlog.w(TAG, "getServiceProxy: TelephonyManager is null!"); + // Binder can be unset in this case because it will be torn down/recreated as part of + // a retry mechanism until the serviceProxy binder is set successfully. + return serviceProxy; + } + + IImsMMTelFeature binder = tm.getImsMMTelFeatureAndListen(slotId, + serviceProxy.getListener()); + if (binder != null) { + serviceProxy.setBinder(binder.asBinder()); + // Trigger the cache to be updated for feature status. + serviceProxy.getFeatureStatus(); + } else { + Rlog.w(TAG, "getServiceProxy: binder is null! Phone Id: " + slotId); + } + return serviceProxy; + } + + public static TelephonyManager getTelephonyManager(Context context) { + return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + } + + public interface IFeatureUpdate { + /** + * Called when the ImsFeature has changed its state. Use + * {@link ImsFeature#getFeatureState()} to get the new state. + */ + void notifyStateChanged(); + + /** + * Called when the ImsFeature has become unavailable due to the binder switching or app + * crashing. A new ImsServiceProxy should be requested for that feature. + */ + void notifyUnavailable(); } private final IImsServiceFeatureCallback mListenerBinder = @@ -65,7 +108,7 @@ public class ImsServiceProxy { // The feature has been re-enabled. This may happen when the service crashes. synchronized (mLock) { if (!mIsAvailable && mSlotId == slotId && feature == mSupportedFeature) { - Log.i(LOG_TAG, "Feature enabled on slotId: " + slotId + " for feature: " + + Log.i(TAG, "Feature enabled on slotId: " + slotId + " for feature: " + feature); mIsAvailable = true; } @@ -76,9 +119,12 @@ public class ImsServiceProxy { public void imsFeatureRemoved(int slotId, int feature) throws RemoteException { synchronized (mLock) { if (mIsAvailable && mSlotId == slotId && feature == mSupportedFeature) { - Log.i(LOG_TAG, "Feature disabled on slotId: " + slotId + " for feature: " + + Log.i(TAG, "Feature disabled on slotId: " + slotId + " for feature: " + feature); mIsAvailable = false; + if (mStatusCallback != null) { + mStatusCallback.notifyUnavailable(); + } } } } @@ -86,12 +132,12 @@ public class ImsServiceProxy { @Override public void imsStatusChanged(int slotId, int feature, int status) throws RemoteException { synchronized (mLock) { - Log.i(LOG_TAG, "imsStatusChanged: slot: " + slotId + " feature: " + feature + + Log.i(TAG, "imsStatusChanged: slot: " + slotId + " feature: " + feature + " status: " + status); if (mSlotId == slotId && feature == mSupportedFeature) { mFeatureStatusCached = status; if (mStatusCallback != null) { - mStatusCallback.notifyStatusChanged(); + mStatusCallback.notifyStateChanged(); } } } @@ -104,8 +150,14 @@ public class ImsServiceProxy { mSupportedFeature = featureType; } - public ImsServiceProxy(int slotId, int featureType) { + public ImsServiceProxy(Context context, int slotId, int featureType) { this(slotId, null, featureType); + mContext = context; + } + + public @Nullable IImsRegistration getRegistration() { + TelephonyManager tm = getTelephonyManager(mContext); + return tm != null ? tm.getImsRegistration(mSlotId, ImsFeature.MMTEL) : null; } public IImsServiceFeatureCallback getListener() { @@ -246,7 +298,7 @@ public class ImsServiceProxy { public int getFeatureStatus() { synchronized (mLock) { if (isBinderAlive() && mFeatureStatusCached != null) { - Log.i(LOG_TAG, "getFeatureStatus - returning cached: " + mFeatureStatusCached); + Log.i(TAG, "getFeatureStatus - returning cached: " + mFeatureStatusCached); return mFeatureStatusCached; } } @@ -259,7 +311,7 @@ public class ImsServiceProxy { // Cache only non-null value for feature status. mFeatureStatusCached = status; } - Log.i(LOG_TAG, "getFeatureStatus - returning " + status); + Log.i(TAG, "getFeatureStatus - returning " + status); return status; } @@ -280,7 +332,7 @@ public class ImsServiceProxy { /** * @param c Callback that will fire when the feature status has changed. */ - public void setStatusCallback(INotifyStatusChanged c) { + public void setStatusCallback(IFeatureUpdate c) { mStatusCallback = c; } diff --git a/src/java/com/android/ims/ImsServiceProxyCompat.java b/src/java/com/android/ims/ImsServiceProxyCompat.java index 5ba1f351..44f72e6a 100644 --- a/src/java/com/android/ims/ImsServiceProxyCompat.java +++ b/src/java/com/android/ims/ImsServiceProxyCompat.java @@ -17,15 +17,20 @@ package com.android.ims; import android.app.PendingIntent; +import android.content.Context; import android.os.IBinder; import android.os.Message; import android.os.RemoteException; +import android.os.ServiceManager; +import android.telephony.Rlog; +import android.telephony.TelephonyManager; import android.telephony.ims.feature.ImsFeature; import com.android.ims.internal.IImsCallSession; import com.android.ims.internal.IImsCallSessionListener; import com.android.ims.internal.IImsConfig; import com.android.ims.internal.IImsEcbm; +import com.android.ims.internal.IImsMMTelFeature; import com.android.ims.internal.IImsMultiEndpoint; import com.android.ims.internal.IImsRegistrationListener; import com.android.ims.internal.IImsService; @@ -42,6 +47,28 @@ public class ImsServiceProxyCompat extends ImsServiceProxy { private static final int SERVICE_ID = ImsFeature.MMTEL; + /** + * For accessing the IMS related service. + * Internal use only. + * @hide + */ + private static final String IMS_SERVICE = "ims"; + + public static ImsServiceProxyCompat create(int slotId, IBinder.DeathRecipient recipient) { + IBinder binder = ServiceManager.checkService(IMS_SERVICE); + + if (binder != null) { + try { + binder.linkToDeath(recipient, 0); + } catch (RemoteException e) { + } + } + + // If the proxy is created with a null binder, subsequent calls that depend on a live + // binder will fail, causing this structure to be torn down and created again. + return new ImsServiceProxyCompat(slotId, binder); + } + public ImsServiceProxyCompat(int slotId, IBinder binder) { super(slotId, binder, SERVICE_ID); } |