Merge "Notify ImsService Status Correctly"
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index f1f683c..511ac38 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -105,10 +105,11 @@
}
@Override
- public void removeImsFeature(int slotId, int feature) throws RemoteException {
+ public void removeImsFeature(int slotId, int feature, IImsFeatureStatusCallback c)
+ throws RemoteException {
synchronized (mFeatures) {
enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "removeImsFeature");
- onRemoveImsFeatureInternal(slotId, feature);
+ onRemoveImsFeatureInternal(slotId, feature, c);
}
}
@@ -355,7 +356,7 @@
if (f != null) {
f.setContext(this);
f.setSlotId(slotId);
- f.setImsFeatureStatusCallback(c);
+ f.addImsFeatureStatusCallback(c);
featureMap.put(featureType, f);
}
@@ -368,7 +369,8 @@
* defined in {@link ImsFeature}.
*/
// Be sure to lock on mFeatures before accessing this method
- private void onRemoveImsFeatureInternal(int slotId, int featureType) {
+ private void onRemoveImsFeatureInternal(int slotId, int featureType,
+ IImsFeatureStatusCallback c) {
SparseArray<ImsFeature> featureMap = mFeatures.get(slotId);
if (featureMap == null) {
return;
@@ -379,7 +381,7 @@
featureMap.remove(featureType);
featureToRemove.notifyFeatureRemoved(slotId);
// Remove reference to Binder
- featureToRemove.setImsFeatureStatusCallback(null);
+ featureToRemove.removeImsFeatureStatusCallback(c);
}
}
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index 395f1cc..9d880b7 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -28,7 +28,11 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
+import java.util.Set;
+import java.util.WeakHashMap;
/**
* Base class for all IMS features that are supported by the framework.
@@ -88,7 +92,8 @@
public static final int STATE_READY = 2;
private List<INotifyFeatureRemoved> mRemovedListeners = new ArrayList<>();
- private IImsFeatureStatusCallback mStatusCallback;
+ private final Set<IImsFeatureStatusCallback> mStatusCallbacks = Collections.newSetFromMap(
+ new WeakHashMap<IImsFeatureStatusCallback, Boolean>());
private @ImsState int mState = STATE_NOT_AVAILABLE;
private int mSlotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
private Context mContext;
@@ -136,11 +141,29 @@
}
}
- // Not final for testing.
- public void setImsFeatureStatusCallback(IImsFeatureStatusCallback c) {
- mStatusCallback = c;
- // If we have just connected, send queued status.
- notifyFeatureState(mState);
+ public void addImsFeatureStatusCallback(IImsFeatureStatusCallback c) {
+ if (c == null) {
+ return;
+ }
+ try {
+ // If we have just connected, send queued status.
+ c.notifyImsFeatureStatus(mState);
+ // Add the callback if the callback completes successfully without a RemoteException.
+ synchronized (mStatusCallbacks) {
+ mStatusCallbacks.add(c);
+ }
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage());
+ }
+ }
+
+ public void removeImsFeatureStatusCallback(IImsFeatureStatusCallback c) {
+ if (c == null) {
+ return;
+ }
+ synchronized (mStatusCallbacks) {
+ mStatusCallbacks.remove(c);
+ }
}
/**
@@ -148,13 +171,18 @@
* @param state
*/
private void notifyFeatureState(@ImsState int state) {
- if (mStatusCallback != null) {
- try {
- Log.i(LOG_TAG, "notifying ImsFeatureState=" + state);
- mStatusCallback.notifyImsFeatureStatus(state);
- } catch (RemoteException e) {
- mStatusCallback = null;
- Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage());
+ synchronized (mStatusCallbacks) {
+ for (Iterator<IImsFeatureStatusCallback> iter = mStatusCallbacks.iterator();
+ iter.hasNext(); ) {
+ IImsFeatureStatusCallback callback = iter.next();
+ try {
+ Log.i(LOG_TAG, "notifying ImsFeatureState=" + state);
+ callback.notifyImsFeatureStatus(state);
+ } catch (RemoteException e) {
+ // remove if the callback is no longer alive.
+ iter.remove();
+ Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage());
+ }
}
}
sendImsServiceIntent(state);
diff --git a/telephony/java/com/android/ims/internal/IImsServiceController.aidl b/telephony/java/com/android/ims/internal/IImsServiceController.aidl
index 712816f..bb06d7e 100644
--- a/telephony/java/com/android/ims/internal/IImsServiceController.aidl
+++ b/telephony/java/com/android/ims/internal/IImsServiceController.aidl
@@ -37,7 +37,7 @@
interface IImsServiceController {
// ImsService Control
void createImsFeature(int slotId, int feature, IImsFeatureStatusCallback c);
- void removeImsFeature(int slotId, int feature);
+ void removeImsFeature(int slotId, int feature, IImsFeatureStatusCallback c);
// MMTel Feature
int startSession(int slotId, int featureType, in PendingIntent incomingCallIntent,
in IImsRegistrationListener listener);