aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Ebinger <breadley@google.com>2018-01-17 23:01:09 +0000
committerandroid-build-merger <android-build-merger@google.com>2018-01-17 23:01:09 +0000
commit79e74c78aed874589af8cb82ac4b8eb153248ba1 (patch)
tree641f21d864b6657a2c8b313cf9a5c36d96f8d186
parente0e696b0c10c3e361c776cab45a80c18a740cb68 (diff)
parent0e170c7f6ca88c32d45ad5b4a932b6808956d472 (diff)
downloadims-79e74c78aed874589af8cb82ac4b8eb153248ba1.tar.gz
Integrate Registration APIs
am: 0e170c7f6c Change-Id: If262feac39f40a3c59a4b0ad1e810c72568df231
-rw-r--r--src/java/com/android/ims/ImsConnectionStateListener.java35
-rw-r--r--src/java/com/android/ims/ImsManager.java147
-rw-r--r--src/java/com/android/ims/ImsServiceProxy.java76
-rw-r--r--src/java/com/android/ims/ImsServiceProxyCompat.java27
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);
}