Loading src/java/com/android/ims/FeatureConnection.java +8 −2 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ public abstract class FeatureConnection { protected static boolean sImsSupportedOnDevice = true; protected final int mSlotId; protected final int mSubId; protected Context mContext; protected IBinder mBinder; Loading @@ -56,9 +57,10 @@ public abstract class FeatureConnection { private final ISipTransport mSipTransportBinder; protected final Object mLock = new Object(); public FeatureConnection(Context context, int slotId, IImsConfig c, IImsRegistration r, ISipTransport s) { public FeatureConnection(Context context, int slotId, int subId, IImsConfig c, IImsRegistration r, ISipTransport s) { mSlotId = slotId; mSubId = subId; mContext = context; mRegistrationBinder = r; mConfigBinder = c; Loading Loading @@ -223,6 +225,10 @@ public abstract class FeatureConnection { return state; } public int getSubId() { return mSubId; } /** * Internal method used to retrieve the feature status from the corresponding ImsService. */ Loading src/java/com/android/ims/FeatureConnector.java +9 −9 Original line number Diff line number Diff line Loading @@ -104,7 +104,7 @@ public class FeatureConnector<U extends FeatureUpdates> { /** * ImsFeature manager is connected to the underlying IMS implementation. */ void connectionReady(U manager) throws ImsException; void connectionReady(U manager, int subId) throws ImsException; /** * The underlying IMS implementation is unavailable and can not be used to communicate. Loading @@ -115,15 +115,15 @@ public class FeatureConnector<U extends FeatureUpdates> { private final IImsServiceFeatureCallback mCallback = new IImsServiceFeatureCallback.Stub() { @Override public void imsFeatureCreated(ImsFeatureContainer c) { log("imsFeatureCreated: " + c); public void imsFeatureCreated(ImsFeatureContainer c, int subId) { log("imsFeatureCreated: " + c + ", subId: " + subId); synchronized (mLock) { mManager.associate(c); mManager.associate(c, subId); mManager.updateFeatureCapabilities(c.getCapabilities()); mDisconnectedReason = null; } // Notifies executor, so notify outside of lock imsStatusChanged(c.getState()); imsStatusChanged(c.getState(), subId); } @Override Loading Loading @@ -151,7 +151,7 @@ public class FeatureConnector<U extends FeatureUpdates> { } @Override public void imsStatusChanged(int status) { public void imsStatusChanged(int status, int subId) { log("imsStatusChanged: status=" + ImsFeature.STATE_LOG_MAP.get(status)); final U manager; final boolean isReady; Loading @@ -173,7 +173,7 @@ public class FeatureConnector<U extends FeatureUpdates> { mExecutor.execute(() -> { try { if (isReady) { notifyReady(manager); notifyReady(manager, subId); } else { notifyNotReady(); } Loading Loading @@ -282,10 +282,10 @@ public class FeatureConnector<U extends FeatureUpdates> { } // Should be called on executor private void notifyReady(U manager) throws ImsException { private void notifyReady(U manager, int subId) throws ImsException { try { if (DBG) log("notifyReady"); mListener.connectionReady(manager); mListener.connectionReady(manager, subId); } catch (ImsException e) { if(DBG) log("notifyReady exception: " + e.getMessage()); Loading src/java/com/android/ims/FeatureUpdates.java +2 −1 Original line number Diff line number Diff line Loading @@ -48,8 +48,9 @@ public interface FeatureUpdates { * Associate this Manager instance with the IMS Binder interfaces specified. This is usually * done by creating a FeatureConnection instance with these interfaces. * @param container Contains all of the related interfaces attached to a specific ImsFeature. * @param subId The subscription ID that the IMS Feature is being created for. */ void associate(ImsFeatureContainer container); void associate(ImsFeatureContainer container, int subId); /** * Invalidate the previously associated Binder interfaces set in {@link #associate}. Loading src/java/com/android/ims/ImsCallbackAdapterManager.java +8 −166 Original line number Diff line number Diff line Loading @@ -20,19 +20,12 @@ import android.content.Context; import android.os.IInterface; import android.os.Looper; import android.os.RemoteCallbackList; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.stream.Collectors; public abstract class ImsCallbackAdapterManager<T extends IInterface> { private static final String TAG = "ImsCallbackAM"; Loading @@ -40,62 +33,16 @@ public abstract class ImsCallbackAdapterManager<T extends IInterface> { private final Context mContext; private final Object mLock; private final int mSlotId; // Map of sub id -> List<callbacks> for sub id linked callbacks. private final SparseArray<Set<T>> mCallbackSubscriptionMap = new SparseArray<>(); private final int mSubId; // List of all active callbacks to ImsService private final RemoteCallbackList<T> mRemoteCallbacks = new RemoteCallbackList<>(); @VisibleForTesting public SubscriptionManager.OnSubscriptionsChangedListener mSubChangedListener; public ImsCallbackAdapterManager(Context context, Object lock, int slotId) { public ImsCallbackAdapterManager(Context context, Object lock, int slotId, int subId) { mContext = context; mLock = lock; mSlotId = slotId; if (Looper.myLooper() == null) { Looper.prepare(); } // Must be created after Looper.prepare() is called, or else we will get an exception. mSubChangedListener = new SubscriptionManager.OnSubscriptionsChangedListener() { @Override public void onSubscriptionsChanged() { SubscriptionManager manager = mContext.getSystemService(SubscriptionManager.class); if (manager == null) { Log.w(TAG + " [" + mSlotId + "]", "onSubscriptionsChanged: could not find " + "SubscriptionManager."); return; } List<SubscriptionInfo> subInfos = manager.getActiveSubscriptionInfoList(false); if (subInfos == null) { subInfos = Collections.emptyList(); } Set<Integer> newSubIds = subInfos.stream() .map(SubscriptionInfo::getSubscriptionId) .collect(Collectors.toSet()); synchronized (mLock) { Set<Integer> storedSubIds = new ArraySet<>(mCallbackSubscriptionMap.size()); for (int keyIndex = 0; keyIndex < mCallbackSubscriptionMap.size(); keyIndex++) { storedSubIds.add(mCallbackSubscriptionMap.keyAt(keyIndex)); } // Get the set of sub ids that are in storedSubIds that are not in newSubIds. // This is the set of sub ids that need to be removed. storedSubIds.removeAll(newSubIds); for (Integer subId : storedSubIds) { removeCallbacksForSubscription(subId); } } } }; mSubId = subId; } // Add a callback to the ImsFeature associated with this manager (independent of the Loading @@ -107,20 +54,20 @@ public abstract class ImsCallbackAdapterManager<T extends IInterface> { // Throws a IllegalStateException if this registration fails. registerCallback(localCallback); Log.i(TAG + " [" + mSlotId + "]", "Local callback added: " + localCallback); mRemoteCallbacks.register(localCallback); } } // Add a callback to be associated with a subscription. If that subscription is removed, // remove the callback and notify the callback that the subscription has been removed. // Add a callback to be associated with a subscription. public void addCallbackForSubscription(T localCallback, int subId) { if (!SubscriptionManager.isValidSubscriptionId(subId)) { Log.w(TAG + " [" + mSlotId + "]", "add callback: invalid subId " + subId); if (!SubscriptionManager.isValidSubscriptionId(subId) || mSubId != subId) { Log.w(TAG + " [" + mSlotId + ", " + mSubId + "]", "add callback: invalid subId or" + " inactive subID " + subId); return; } synchronized (mLock) { addCallback(localCallback); linkCallbackToSubscription(localCallback, subId); } } Loading @@ -135,110 +82,6 @@ public abstract class ImsCallbackAdapterManager<T extends IInterface> { } } // Remove an existing callback that has been linked to a subscription. public void removeCallbackForSubscription(T localCallback, int subId) { if (!SubscriptionManager.isValidSubscriptionId(subId)) { Log.w(TAG + " [" + mSlotId + "]", "remove callback: invalid subId " + subId); return; } synchronized (mLock) { removeCallback(localCallback); unlinkCallbackFromSubscription(localCallback, subId); } } // Links a callback to be tracked by a subscription. If it goes away, emove. private void linkCallbackToSubscription(T callback, int subId) { synchronized (mLock) { if (mCallbackSubscriptionMap.size() == 0) { // we are about to add the first entry to the map, register for subscriptions //changed listener. registerForSubscriptionsChanged(); } Set<T> callbacksPerSub = mCallbackSubscriptionMap.get(subId); if (callbacksPerSub == null) { // the callback list has not been created yet for this subscription. callbacksPerSub = new ArraySet<>(); mCallbackSubscriptionMap.put(subId, callbacksPerSub); } callbacksPerSub.add(callback); } } // Unlink the callback from the associated subscription. private void unlinkCallbackFromSubscription(T callback, int subId) { synchronized (mLock) { Set<T> callbacksPerSub = mCallbackSubscriptionMap.get(subId); if (callbacksPerSub != null) { callbacksPerSub.remove(callback); if (callbacksPerSub.isEmpty()) { mCallbackSubscriptionMap.remove(subId); } } if (mCallbackSubscriptionMap.size() == 0) { unregisterForSubscriptionsChanged(); } } } // Removes all of the callbacks that have been registered to the subscription specified. // This happens when Telephony sends an indication that the subscriptions have changed. private void removeCallbacksForSubscription(int subId) { if (!SubscriptionManager.isValidSubscriptionId(subId)) { Log.w(TAG + " [" + mSlotId + "]", "remove all callbacks: invalid subId " + subId); return; } synchronized (mLock) { Set<T> callbacksPerSub = mCallbackSubscriptionMap.get(subId); if (callbacksPerSub == null) { // no callbacks registered for this subscription. return; } // clear all registered callbacks in the subscription map for this subscription. mCallbackSubscriptionMap.remove(subId); for (T callback : callbacksPerSub) { removeCallback(callback); } // If there are no more callbacks being tracked, remove subscriptions changed // listener. if (mCallbackSubscriptionMap.size() == 0) { unregisterForSubscriptionsChanged(); } } } // Clear the Subscription -> Callback map because the ImsService connection is no longer // current. private void clearCallbacksForAllSubscriptions() { synchronized (mLock) { List<Integer> keys = new ArrayList<>(); for (int keyIndex = 0; keyIndex < mCallbackSubscriptionMap.size(); keyIndex++) { keys.add(mCallbackSubscriptionMap.keyAt(keyIndex)); } keys.forEach(this::removeCallbacksForSubscription); } } private void registerForSubscriptionsChanged() { SubscriptionManager manager = mContext.getSystemService(SubscriptionManager.class); if (manager != null) { manager.addOnSubscriptionsChangedListener(mSubChangedListener); } else { Log.w(TAG + " [" + mSlotId + "]", "registerForSubscriptionsChanged: could not find" + " SubscriptionManager."); } } private void unregisterForSubscriptionsChanged() { SubscriptionManager manager = mContext.getSystemService(SubscriptionManager.class); if (manager != null) { manager.removeOnSubscriptionsChangedListener(mSubChangedListener); } else { Log.w(TAG + " [" + mSlotId + "]", "unregisterForSubscriptionsChanged: could not" + " find SubscriptionManager."); } } // The ImsService these callbacks are registered to has become unavailable or crashed, or // the ImsResolver has switched to a new ImsService. In these cases, clean up all existing // callbacks. Loading @@ -250,7 +93,6 @@ public abstract class ImsCallbackAdapterManager<T extends IInterface> { unregisterCallback(callbackItem); mRemoteCallbacks.unregister(callbackItem); } clearCallbacksForAllSubscriptions(); Log.i(TAG + " [" + mSlotId + "]", "Closing connection and clearing callbacks"); } } Loading src/java/com/android/ims/ImsFeatureBinderRepository.java +17 −11 Original line number Diff line number Diff line Loading @@ -59,7 +59,7 @@ public class ImsFeatureBinderRepository { mExecutor = e; } public void notifyFeatureCreatedOrRemoved(ImsFeatureContainer connector) { public void notifyFeatureCreatedOrRemoved(ImsFeatureContainer connector, int subId) { if (connector == null) { mExecutor.execute(() -> { try { Loading @@ -73,7 +73,7 @@ public class ImsFeatureBinderRepository { else { mExecutor.execute(() -> { try { mCallback.imsFeatureCreated(connector); mCallback.imsFeatureCreated(connector, subId); } catch (RemoteException e) { // This listener will eventually be caught and removed during stale checks. } Loading @@ -81,10 +81,10 @@ public class ImsFeatureBinderRepository { } } public void notifyStateChanged(int state) { public void notifyStateChanged(int state, int subId) { mExecutor.execute(() -> { try { mCallback.imsStatusChanged(state); mCallback.imsStatusChanged(state, subId); } catch (RemoteException e) { // This listener will eventually be caught and removed during stale checks. } Loading Loading @@ -132,6 +132,7 @@ public class ImsFeatureBinderRepository { */ private static final class UpdateMapper { public final int phoneId; public int subId; public final @ImsFeature.FeatureType int imsFeatureType; private final List<ListenerContainer> mListeners = new ArrayList<>(); private ImsFeatureContainer mFeatureContainer; Loading @@ -150,7 +151,7 @@ public class ImsFeatureBinderRepository { mFeatureContainer = c; listeners = copyListenerList(mListeners); } listeners.forEach(l -> l.notifyFeatureCreatedOrRemoved(mFeatureContainer)); listeners.forEach(l -> l.notifyFeatureCreatedOrRemoved(mFeatureContainer, subId)); } public ImsFeatureContainer removeFeatureContainer() { Loading @@ -162,7 +163,7 @@ public class ImsFeatureBinderRepository { mFeatureContainer = null; listeners = copyListenerList(mListeners); } listeners.forEach(l -> l.notifyFeatureCreatedOrRemoved(mFeatureContainer)); listeners.forEach(l -> l.notifyFeatureCreatedOrRemoved(mFeatureContainer, subId)); return oldContainer; } Loading @@ -184,7 +185,7 @@ public class ImsFeatureBinderRepository { } // Do not call back until the feature container has been set. if (featureContainer != null) { c.notifyFeatureCreatedOrRemoved(featureContainer); c.notifyFeatureCreatedOrRemoved(featureContainer, subId); } } Loading Loading @@ -213,7 +214,7 @@ public class ImsFeatureBinderRepository { } // Only update if the feature container is set. if (featureContainer != null) { listeners.forEach(l -> l.notifyStateChanged(newState)); listeners.forEach(l -> l.notifyStateChanged(newState, subId)); } } Loading @@ -236,6 +237,10 @@ public class ImsFeatureBinderRepository { } } public void updateSubId(int newSubId) { subId = newSubId; } @GuardedBy("mLock") private void removeStaleListeners() { List<ListenerContainer> staleListeners = mListeners.stream().filter( Loading Loading @@ -337,14 +342,15 @@ public class ImsFeatureBinderRepository { * @param newConnection A Container containing the IBinder interface connections associated with * the ImsFeature type. */ public void addConnection(int phoneId, @ImsFeature.FeatureType int type, public void addConnection(int phoneId, int subId, @ImsFeature.FeatureType int type, @Nullable ImsFeatureContainer newConnection) { if (type < 0 || type >= ImsFeature.FEATURE_MAX) { throw new IllegalArgumentException("The type must valid"); } logInfoLineLocked(phoneId, "addConnection, type=" + ImsFeature.FEATURE_LOG_MAP.get(type) + ", conn=" + newConnection); logInfoLineLocked(phoneId, "addConnection, subId=" + subId + ", type=" + ImsFeature.FEATURE_LOG_MAP.get(type) + ", conn=" + newConnection); UpdateMapper m = getUpdateMapper(phoneId, type); m.updateSubId(subId); m.addFeatureContainer(newConnection); } Loading Loading
src/java/com/android/ims/FeatureConnection.java +8 −2 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ public abstract class FeatureConnection { protected static boolean sImsSupportedOnDevice = true; protected final int mSlotId; protected final int mSubId; protected Context mContext; protected IBinder mBinder; Loading @@ -56,9 +57,10 @@ public abstract class FeatureConnection { private final ISipTransport mSipTransportBinder; protected final Object mLock = new Object(); public FeatureConnection(Context context, int slotId, IImsConfig c, IImsRegistration r, ISipTransport s) { public FeatureConnection(Context context, int slotId, int subId, IImsConfig c, IImsRegistration r, ISipTransport s) { mSlotId = slotId; mSubId = subId; mContext = context; mRegistrationBinder = r; mConfigBinder = c; Loading Loading @@ -223,6 +225,10 @@ public abstract class FeatureConnection { return state; } public int getSubId() { return mSubId; } /** * Internal method used to retrieve the feature status from the corresponding ImsService. */ Loading
src/java/com/android/ims/FeatureConnector.java +9 −9 Original line number Diff line number Diff line Loading @@ -104,7 +104,7 @@ public class FeatureConnector<U extends FeatureUpdates> { /** * ImsFeature manager is connected to the underlying IMS implementation. */ void connectionReady(U manager) throws ImsException; void connectionReady(U manager, int subId) throws ImsException; /** * The underlying IMS implementation is unavailable and can not be used to communicate. Loading @@ -115,15 +115,15 @@ public class FeatureConnector<U extends FeatureUpdates> { private final IImsServiceFeatureCallback mCallback = new IImsServiceFeatureCallback.Stub() { @Override public void imsFeatureCreated(ImsFeatureContainer c) { log("imsFeatureCreated: " + c); public void imsFeatureCreated(ImsFeatureContainer c, int subId) { log("imsFeatureCreated: " + c + ", subId: " + subId); synchronized (mLock) { mManager.associate(c); mManager.associate(c, subId); mManager.updateFeatureCapabilities(c.getCapabilities()); mDisconnectedReason = null; } // Notifies executor, so notify outside of lock imsStatusChanged(c.getState()); imsStatusChanged(c.getState(), subId); } @Override Loading Loading @@ -151,7 +151,7 @@ public class FeatureConnector<U extends FeatureUpdates> { } @Override public void imsStatusChanged(int status) { public void imsStatusChanged(int status, int subId) { log("imsStatusChanged: status=" + ImsFeature.STATE_LOG_MAP.get(status)); final U manager; final boolean isReady; Loading @@ -173,7 +173,7 @@ public class FeatureConnector<U extends FeatureUpdates> { mExecutor.execute(() -> { try { if (isReady) { notifyReady(manager); notifyReady(manager, subId); } else { notifyNotReady(); } Loading Loading @@ -282,10 +282,10 @@ public class FeatureConnector<U extends FeatureUpdates> { } // Should be called on executor private void notifyReady(U manager) throws ImsException { private void notifyReady(U manager, int subId) throws ImsException { try { if (DBG) log("notifyReady"); mListener.connectionReady(manager); mListener.connectionReady(manager, subId); } catch (ImsException e) { if(DBG) log("notifyReady exception: " + e.getMessage()); Loading
src/java/com/android/ims/FeatureUpdates.java +2 −1 Original line number Diff line number Diff line Loading @@ -48,8 +48,9 @@ public interface FeatureUpdates { * Associate this Manager instance with the IMS Binder interfaces specified. This is usually * done by creating a FeatureConnection instance with these interfaces. * @param container Contains all of the related interfaces attached to a specific ImsFeature. * @param subId The subscription ID that the IMS Feature is being created for. */ void associate(ImsFeatureContainer container); void associate(ImsFeatureContainer container, int subId); /** * Invalidate the previously associated Binder interfaces set in {@link #associate}. Loading
src/java/com/android/ims/ImsCallbackAdapterManager.java +8 −166 Original line number Diff line number Diff line Loading @@ -20,19 +20,12 @@ import android.content.Context; import android.os.IInterface; import android.os.Looper; import android.os.RemoteCallbackList; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.stream.Collectors; public abstract class ImsCallbackAdapterManager<T extends IInterface> { private static final String TAG = "ImsCallbackAM"; Loading @@ -40,62 +33,16 @@ public abstract class ImsCallbackAdapterManager<T extends IInterface> { private final Context mContext; private final Object mLock; private final int mSlotId; // Map of sub id -> List<callbacks> for sub id linked callbacks. private final SparseArray<Set<T>> mCallbackSubscriptionMap = new SparseArray<>(); private final int mSubId; // List of all active callbacks to ImsService private final RemoteCallbackList<T> mRemoteCallbacks = new RemoteCallbackList<>(); @VisibleForTesting public SubscriptionManager.OnSubscriptionsChangedListener mSubChangedListener; public ImsCallbackAdapterManager(Context context, Object lock, int slotId) { public ImsCallbackAdapterManager(Context context, Object lock, int slotId, int subId) { mContext = context; mLock = lock; mSlotId = slotId; if (Looper.myLooper() == null) { Looper.prepare(); } // Must be created after Looper.prepare() is called, or else we will get an exception. mSubChangedListener = new SubscriptionManager.OnSubscriptionsChangedListener() { @Override public void onSubscriptionsChanged() { SubscriptionManager manager = mContext.getSystemService(SubscriptionManager.class); if (manager == null) { Log.w(TAG + " [" + mSlotId + "]", "onSubscriptionsChanged: could not find " + "SubscriptionManager."); return; } List<SubscriptionInfo> subInfos = manager.getActiveSubscriptionInfoList(false); if (subInfos == null) { subInfos = Collections.emptyList(); } Set<Integer> newSubIds = subInfos.stream() .map(SubscriptionInfo::getSubscriptionId) .collect(Collectors.toSet()); synchronized (mLock) { Set<Integer> storedSubIds = new ArraySet<>(mCallbackSubscriptionMap.size()); for (int keyIndex = 0; keyIndex < mCallbackSubscriptionMap.size(); keyIndex++) { storedSubIds.add(mCallbackSubscriptionMap.keyAt(keyIndex)); } // Get the set of sub ids that are in storedSubIds that are not in newSubIds. // This is the set of sub ids that need to be removed. storedSubIds.removeAll(newSubIds); for (Integer subId : storedSubIds) { removeCallbacksForSubscription(subId); } } } }; mSubId = subId; } // Add a callback to the ImsFeature associated with this manager (independent of the Loading @@ -107,20 +54,20 @@ public abstract class ImsCallbackAdapterManager<T extends IInterface> { // Throws a IllegalStateException if this registration fails. registerCallback(localCallback); Log.i(TAG + " [" + mSlotId + "]", "Local callback added: " + localCallback); mRemoteCallbacks.register(localCallback); } } // Add a callback to be associated with a subscription. If that subscription is removed, // remove the callback and notify the callback that the subscription has been removed. // Add a callback to be associated with a subscription. public void addCallbackForSubscription(T localCallback, int subId) { if (!SubscriptionManager.isValidSubscriptionId(subId)) { Log.w(TAG + " [" + mSlotId + "]", "add callback: invalid subId " + subId); if (!SubscriptionManager.isValidSubscriptionId(subId) || mSubId != subId) { Log.w(TAG + " [" + mSlotId + ", " + mSubId + "]", "add callback: invalid subId or" + " inactive subID " + subId); return; } synchronized (mLock) { addCallback(localCallback); linkCallbackToSubscription(localCallback, subId); } } Loading @@ -135,110 +82,6 @@ public abstract class ImsCallbackAdapterManager<T extends IInterface> { } } // Remove an existing callback that has been linked to a subscription. public void removeCallbackForSubscription(T localCallback, int subId) { if (!SubscriptionManager.isValidSubscriptionId(subId)) { Log.w(TAG + " [" + mSlotId + "]", "remove callback: invalid subId " + subId); return; } synchronized (mLock) { removeCallback(localCallback); unlinkCallbackFromSubscription(localCallback, subId); } } // Links a callback to be tracked by a subscription. If it goes away, emove. private void linkCallbackToSubscription(T callback, int subId) { synchronized (mLock) { if (mCallbackSubscriptionMap.size() == 0) { // we are about to add the first entry to the map, register for subscriptions //changed listener. registerForSubscriptionsChanged(); } Set<T> callbacksPerSub = mCallbackSubscriptionMap.get(subId); if (callbacksPerSub == null) { // the callback list has not been created yet for this subscription. callbacksPerSub = new ArraySet<>(); mCallbackSubscriptionMap.put(subId, callbacksPerSub); } callbacksPerSub.add(callback); } } // Unlink the callback from the associated subscription. private void unlinkCallbackFromSubscription(T callback, int subId) { synchronized (mLock) { Set<T> callbacksPerSub = mCallbackSubscriptionMap.get(subId); if (callbacksPerSub != null) { callbacksPerSub.remove(callback); if (callbacksPerSub.isEmpty()) { mCallbackSubscriptionMap.remove(subId); } } if (mCallbackSubscriptionMap.size() == 0) { unregisterForSubscriptionsChanged(); } } } // Removes all of the callbacks that have been registered to the subscription specified. // This happens when Telephony sends an indication that the subscriptions have changed. private void removeCallbacksForSubscription(int subId) { if (!SubscriptionManager.isValidSubscriptionId(subId)) { Log.w(TAG + " [" + mSlotId + "]", "remove all callbacks: invalid subId " + subId); return; } synchronized (mLock) { Set<T> callbacksPerSub = mCallbackSubscriptionMap.get(subId); if (callbacksPerSub == null) { // no callbacks registered for this subscription. return; } // clear all registered callbacks in the subscription map for this subscription. mCallbackSubscriptionMap.remove(subId); for (T callback : callbacksPerSub) { removeCallback(callback); } // If there are no more callbacks being tracked, remove subscriptions changed // listener. if (mCallbackSubscriptionMap.size() == 0) { unregisterForSubscriptionsChanged(); } } } // Clear the Subscription -> Callback map because the ImsService connection is no longer // current. private void clearCallbacksForAllSubscriptions() { synchronized (mLock) { List<Integer> keys = new ArrayList<>(); for (int keyIndex = 0; keyIndex < mCallbackSubscriptionMap.size(); keyIndex++) { keys.add(mCallbackSubscriptionMap.keyAt(keyIndex)); } keys.forEach(this::removeCallbacksForSubscription); } } private void registerForSubscriptionsChanged() { SubscriptionManager manager = mContext.getSystemService(SubscriptionManager.class); if (manager != null) { manager.addOnSubscriptionsChangedListener(mSubChangedListener); } else { Log.w(TAG + " [" + mSlotId + "]", "registerForSubscriptionsChanged: could not find" + " SubscriptionManager."); } } private void unregisterForSubscriptionsChanged() { SubscriptionManager manager = mContext.getSystemService(SubscriptionManager.class); if (manager != null) { manager.removeOnSubscriptionsChangedListener(mSubChangedListener); } else { Log.w(TAG + " [" + mSlotId + "]", "unregisterForSubscriptionsChanged: could not" + " find SubscriptionManager."); } } // The ImsService these callbacks are registered to has become unavailable or crashed, or // the ImsResolver has switched to a new ImsService. In these cases, clean up all existing // callbacks. Loading @@ -250,7 +93,6 @@ public abstract class ImsCallbackAdapterManager<T extends IInterface> { unregisterCallback(callbackItem); mRemoteCallbacks.unregister(callbackItem); } clearCallbacksForAllSubscriptions(); Log.i(TAG + " [" + mSlotId + "]", "Closing connection and clearing callbacks"); } } Loading
src/java/com/android/ims/ImsFeatureBinderRepository.java +17 −11 Original line number Diff line number Diff line Loading @@ -59,7 +59,7 @@ public class ImsFeatureBinderRepository { mExecutor = e; } public void notifyFeatureCreatedOrRemoved(ImsFeatureContainer connector) { public void notifyFeatureCreatedOrRemoved(ImsFeatureContainer connector, int subId) { if (connector == null) { mExecutor.execute(() -> { try { Loading @@ -73,7 +73,7 @@ public class ImsFeatureBinderRepository { else { mExecutor.execute(() -> { try { mCallback.imsFeatureCreated(connector); mCallback.imsFeatureCreated(connector, subId); } catch (RemoteException e) { // This listener will eventually be caught and removed during stale checks. } Loading @@ -81,10 +81,10 @@ public class ImsFeatureBinderRepository { } } public void notifyStateChanged(int state) { public void notifyStateChanged(int state, int subId) { mExecutor.execute(() -> { try { mCallback.imsStatusChanged(state); mCallback.imsStatusChanged(state, subId); } catch (RemoteException e) { // This listener will eventually be caught and removed during stale checks. } Loading Loading @@ -132,6 +132,7 @@ public class ImsFeatureBinderRepository { */ private static final class UpdateMapper { public final int phoneId; public int subId; public final @ImsFeature.FeatureType int imsFeatureType; private final List<ListenerContainer> mListeners = new ArrayList<>(); private ImsFeatureContainer mFeatureContainer; Loading @@ -150,7 +151,7 @@ public class ImsFeatureBinderRepository { mFeatureContainer = c; listeners = copyListenerList(mListeners); } listeners.forEach(l -> l.notifyFeatureCreatedOrRemoved(mFeatureContainer)); listeners.forEach(l -> l.notifyFeatureCreatedOrRemoved(mFeatureContainer, subId)); } public ImsFeatureContainer removeFeatureContainer() { Loading @@ -162,7 +163,7 @@ public class ImsFeatureBinderRepository { mFeatureContainer = null; listeners = copyListenerList(mListeners); } listeners.forEach(l -> l.notifyFeatureCreatedOrRemoved(mFeatureContainer)); listeners.forEach(l -> l.notifyFeatureCreatedOrRemoved(mFeatureContainer, subId)); return oldContainer; } Loading @@ -184,7 +185,7 @@ public class ImsFeatureBinderRepository { } // Do not call back until the feature container has been set. if (featureContainer != null) { c.notifyFeatureCreatedOrRemoved(featureContainer); c.notifyFeatureCreatedOrRemoved(featureContainer, subId); } } Loading Loading @@ -213,7 +214,7 @@ public class ImsFeatureBinderRepository { } // Only update if the feature container is set. if (featureContainer != null) { listeners.forEach(l -> l.notifyStateChanged(newState)); listeners.forEach(l -> l.notifyStateChanged(newState, subId)); } } Loading @@ -236,6 +237,10 @@ public class ImsFeatureBinderRepository { } } public void updateSubId(int newSubId) { subId = newSubId; } @GuardedBy("mLock") private void removeStaleListeners() { List<ListenerContainer> staleListeners = mListeners.stream().filter( Loading Loading @@ -337,14 +342,15 @@ public class ImsFeatureBinderRepository { * @param newConnection A Container containing the IBinder interface connections associated with * the ImsFeature type. */ public void addConnection(int phoneId, @ImsFeature.FeatureType int type, public void addConnection(int phoneId, int subId, @ImsFeature.FeatureType int type, @Nullable ImsFeatureContainer newConnection) { if (type < 0 || type >= ImsFeature.FEATURE_MAX) { throw new IllegalArgumentException("The type must valid"); } logInfoLineLocked(phoneId, "addConnection, type=" + ImsFeature.FEATURE_LOG_MAP.get(type) + ", conn=" + newConnection); logInfoLineLocked(phoneId, "addConnection, subId=" + subId + ", type=" + ImsFeature.FEATURE_LOG_MAP.get(type) + ", conn=" + newConnection); UpdateMapper m = getUpdateMapper(phoneId, type); m.updateSubId(subId); m.addFeatureContainer(newConnection); } Loading