aboutsummaryrefslogtreecommitdiff
path: root/src/java/com/android/ims/MmTelFeatureConnection.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/com/android/ims/MmTelFeatureConnection.java')
-rw-r--r--src/java/com/android/ims/MmTelFeatureConnection.java117
1 files changed, 72 insertions, 45 deletions
diff --git a/src/java/com/android/ims/MmTelFeatureConnection.java b/src/java/com/android/ims/MmTelFeatureConnection.java
index de8f9282..d6954f3f 100644
--- a/src/java/com/android/ims/MmTelFeatureConnection.java
+++ b/src/java/com/android/ims/MmTelFeatureConnection.java
@@ -44,8 +44,10 @@ import com.android.ims.internal.IImsMultiEndpoint;
import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.ims.internal.IImsUt;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
/**
* A container of the IImsServiceController binder, which implements all of the ImsFeatures that
@@ -73,35 +75,41 @@ public class MmTelFeatureConnection {
private IImsRegistration mRegistrationBinder;
private IImsConfig mConfigBinder;
+ private IBinder.DeathRecipient mDeathRecipient = () -> {
+ Log.w(TAG, "DeathRecipient triggered, binder died.");
+ onRemovedOrDied();
+ };
+
private abstract class CallbackAdapterManager<T> {
private static final String TAG = "CallbackAdapterManager";
- protected final Set<T> mLocalCallbacks = new HashSet<>();
+ protected final Set<T> mLocalCallbacks =
+ Collections.newSetFromMap(new ConcurrentHashMap<>());
private boolean mHasConnected = false;
public void addCallback(T localCallback) throws RemoteException {
// We only one one binding to the ImsService per process.
// Store any more locally.
synchronized (mLock) {
- if(!mHasConnected) {
+ if (!mHasConnected) {
// throws a RemoteException if a connection can not be established.
- if(createConnection()) {
+ if (createConnection()) {
mHasConnected = true;
} else {
throw new RemoteException("Can not create connection!");
}
}
- Log.i(TAG, "Local callback added: " + localCallback);
- mLocalCallbacks.add(localCallback);
}
+ Log.i(TAG, "Local callback added: " + localCallback);
+ mLocalCallbacks.add(localCallback);
}
public void removeCallback(T localCallback) {
// We only maintain one binding to the ImsService per process.
+ Log.i(TAG, "Local callback removed: " + localCallback);
+ mLocalCallbacks.remove(localCallback);
synchronized (mLock) {
- Log.i(TAG, "Local callback removed: " + localCallback);
- mLocalCallbacks.remove(localCallback);
- // If we have removed all local callbacks, remove callback to ImsService.
+ // If we have removed all local callbacks, remove callback to ImsService.
if(mHasConnected) {
if (mLocalCallbacks.isEmpty()) {
removeConnection();
@@ -118,9 +126,9 @@ public class MmTelFeatureConnection {
// Still mark the connection as disconnected, even if this fails.
mHasConnected = false;
}
- Log.i(TAG, "Closing connection and clearing callbacks");
- mLocalCallbacks.clear();
}
+ Log.i(TAG, "Closing connection and clearing callbacks");
+ mLocalCallbacks.clear();
}
abstract boolean createConnection() throws RemoteException;
@@ -140,27 +148,21 @@ public class MmTelFeatureConnection {
public void onRegistered(int imsRadioTech) {
Log.i(TAG, "onRegistered ::");
- synchronized (mLock) {
- mLocalCallbacks.forEach(l -> l.onRegistered(imsRadioTech));
- }
+ mLocalCallbacks.forEach(l -> l.onRegistered(imsRadioTech));
}
@Override
public void onRegistering(int imsRadioTech) {
Log.i(TAG, "onRegistering ::");
- synchronized (mLock) {
- mLocalCallbacks.forEach(l -> l.onRegistering(imsRadioTech));
- }
+ mLocalCallbacks.forEach(l -> l.onRegistering(imsRadioTech));
}
@Override
public void onDeregistered(ImsReasonInfo imsReasonInfo) {
Log.i(TAG, "onDeregistered ::");
- synchronized (mLock) {
- mLocalCallbacks.forEach(l -> l.onDeregistered(imsReasonInfo));
- }
+ mLocalCallbacks.forEach(l -> l.onDeregistered(imsReasonInfo));
}
@Override
@@ -168,18 +170,15 @@ public class MmTelFeatureConnection {
Log.i(TAG, "onTechnologyChangeFailed :: targetAccessTech=" + targetRadioTech +
", imsReasonInfo=" + imsReasonInfo);
- synchronized (mLock) {
mLocalCallbacks.forEach(l -> l.onTechnologyChangeFailed(targetRadioTech,
imsReasonInfo));
- }
}
@Override
public void onSubscriberAssociatedUriChanged(Uri[] uris) {
Log.i(TAG, "onSubscriberAssociatedUriChanged");
- synchronized (mLock) {
- mLocalCallbacks.forEach(l -> l.onSubscriberAssociatedUriChanged(uris));
- }
+
+ mLocalCallbacks.forEach(l -> l.onSubscriberAssociatedUriChanged(uris));
}
}
@@ -220,16 +219,18 @@ public class MmTelFeatureConnection {
// Called when the Capabilities Status on this connection have changed.
@Override
public void onCapabilitiesStatusChanged(ImsFeature.Capabilities config) {
- synchronized (mLock) {
- mLocalCallbacks.forEach(
- callback -> callback.onCapabilitiesStatusChanged(config));
- }
+ mLocalCallbacks.forEach(
+ callback -> callback.onCapabilitiesStatusChanged(config));
}
}
@Override
boolean createConnection() throws RemoteException {
- IImsMmTelFeature binder = getServiceInterface(mBinder);
+ IImsMmTelFeature binder;
+ synchronized (mLock) {
+ checkServiceIsReady();
+ binder = getServiceInterface(mBinder);
+ }
if (binder != null) {
binder.addCapabilityCallback(mCallbackAdapter);
return true;
@@ -241,7 +242,15 @@ public class MmTelFeatureConnection {
@Override
void removeConnection() {
- IImsMmTelFeature binder = getServiceInterface(mBinder);
+ IImsMmTelFeature binder = null;
+ synchronized (mLock) {
+ try {
+ checkServiceIsReady();
+ binder = getServiceInterface(mBinder);
+ } catch (RemoteException e) {
+ // binder is null
+ }
+ }
if (binder != null) {
try {
binder.removeCapabilityCallback(mCallbackAdapter);
@@ -333,14 +342,8 @@ public class MmTelFeatureConnection {
}
switch (feature) {
case ImsFeature.FEATURE_MMTEL: {
- if (mIsAvailable) {
- Log.i(TAG, "MmTel disabled on slotId: " + slotId);
- mIsAvailable = false;
- mmTelFeatureRemoved();
- if (mStatusCallback != null) {
- mStatusCallback.notifyUnavailable();
- }
- }
+ Log.i(TAG, "MmTel removed on slotId: " + slotId);
+ onRemovedOrDied();
break;
}
case ImsFeature.FEATURE_EMERGENCY_MMTEL : {
@@ -372,12 +375,23 @@ public class MmTelFeatureConnection {
mContext = context;
}
- // Called when the MmTelFeatureConnection has received an unavailable notification.
- private void mmTelFeatureRemoved() {
+ /**
+ * Called when the MmTelFeature has either been removed by Telephony or crashed.
+ */
+ private void onRemovedOrDied() {
synchronized (mLock) {
- // invalidate caches.
- mRegistrationBinder = null;
- mConfigBinder = null;
+ if (mIsAvailable) {
+ mIsAvailable = false;
+ // invalidate caches.
+ mRegistrationBinder = null;
+ mConfigBinder = null;
+ if (mBinder != null) {
+ mBinder.unlinkToDeath(mDeathRecipient, 0);
+ }
+ if (mStatusCallback != null) {
+ mStatusCallback.notifyUnavailable();
+ }
+ }
}
}
@@ -430,7 +444,16 @@ public class MmTelFeatureConnection {
}
public void setBinder(IBinder binder) {
- mBinder = binder;
+ synchronized (mLock) {
+ mBinder = binder;
+ try {
+ if (mBinder != null) {
+ mBinder.linkToDeath(mDeathRecipient, 0);
+ }
+ } catch (RemoteException e) {
+ // No need to do anything if the binder is already dead.
+ }
+ }
}
/**
@@ -451,7 +474,11 @@ public class MmTelFeatureConnection {
mRegistrationCallbackManager.close();
mCapabilityCallbackManager.close();
try {
- getServiceInterface(mBinder).setListener(null);
+ synchronized (mLock) {
+ if (isBinderAlive()) {
+ getServiceInterface(mBinder).setListener(null);
+ }
+ }
} catch (RemoteException e) {
Log.w(TAG, "closeConnection: couldn't remove listener!");
}