Add AIDL connections for SipDelegateManager am: bf9c710733

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1462844

Change-Id: I78ba0369a730f52fa796398b08f9701c6e23e88c
This commit is contained in:
Brad Ebinger
2020-11-12 23:30:37 +00:00
committed by Automerger Merge Worker
14 changed files with 559 additions and 29 deletions

View File

@@ -22,7 +22,12 @@ import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.telephony.BinderCacheManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyFrameworkInitializer;
import android.telephony.ims.aidl.IImsRcsController;
import com.android.internal.telephony.ITelephony;
/**
* Provides access to information about Telephony IMS services on the device.
@@ -30,8 +35,6 @@ import android.telephony.SubscriptionManager;
@SystemService(Context.TELEPHONY_IMS_SERVICE)
public class ImsManager {
private Context mContext;
/**
* <p>Broadcast Action: Indicates that a previously allowed IMS operation was rejected by the
* network due to the network returning a "forbidden" response. This may be due to a
@@ -87,6 +90,14 @@ public class ImsManager {
public static final String EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE =
"android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_MESSAGE";
// Cache Telephony Binder interfaces, one cache per process.
private static final BinderCacheManager<ITelephony> sTelephonyCache =
new BinderCacheManager<>(ImsManager::getITelephonyInterface);
private static final BinderCacheManager<IImsRcsController> sRcsCache =
new BinderCacheManager<>(ImsManager::getIImsRcsControllerInterface);
private final Context mContext;
/**
* Use {@link Context#getSystemService(String)} to get an instance of this class.
* @hide
@@ -108,7 +119,7 @@ public class ImsManager {
throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId);
}
return new ImsRcsManager(mContext, subscriptionId);
return new ImsRcsManager(mContext, subscriptionId, sRcsCache);
}
/**
@@ -124,7 +135,7 @@ public class ImsManager {
throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId);
}
return new ImsMmTelManager(subscriptionId);
return new ImsMmTelManager(subscriptionId, sTelephonyCache);
}
/**
@@ -146,6 +157,22 @@ public class ImsManager {
throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId);
}
return new SipDelegateManager(mContext, subscriptionId);
return new SipDelegateManager(mContext, subscriptionId, sRcsCache);
}
private static IImsRcsController getIImsRcsControllerInterface() {
return IImsRcsController.Stub.asInterface(
TelephonyFrameworkInitializer
.getTelephonyServiceManager()
.getTelephonyImsServiceRegisterer()
.get());
}
private static ITelephony getITelephonyInterface() {
return ITelephony.Stub.asInterface(
TelephonyFrameworkInitializer
.getTelephonyServiceManager()
.getTelephonyServiceRegisterer()
.get());
}
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.ims;
parcelable DelegateRegistrationState;

View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.ims;
parcelable DelegateRequest;

View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.ims;
parcelable FeatureTagState;

View File

@@ -29,6 +29,7 @@ import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.telephony.AccessNetworkConstants;
import android.telephony.BinderCacheManager;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyFrameworkInitializer;
@@ -213,6 +214,7 @@ public class ImsMmTelManager implements RegistrationManager {
}
private final int mSubId;
private final BinderCacheManager<ITelephony> mBinderCache;
/**
* Create an instance of {@link ImsMmTelManager} for the subscription id specified.
@@ -242,7 +244,8 @@ public class ImsMmTelManager implements RegistrationManager {
throw new IllegalArgumentException("Invalid subscription ID");
}
return new ImsMmTelManager(subId);
return new ImsMmTelManager(subId, new BinderCacheManager<>(
ImsMmTelManager::getITelephonyInterface));
}
/**
@@ -250,8 +253,9 @@ public class ImsMmTelManager implements RegistrationManager {
* @hide
*/
@VisibleForTesting
public ImsMmTelManager(int subId) {
public ImsMmTelManager(int subId, BinderCacheManager<ITelephony> binderCache) {
mSubId = subId;
mBinderCache = binderCache;
}
/**
@@ -1367,7 +1371,11 @@ public class ImsMmTelManager implements RegistrationManager {
}
}
private static ITelephony getITelephony() {
private ITelephony getITelephony() {
return mBinderCache.getBinder();
}
private static ITelephony getITelephonyInterface() {
ITelephony binder = ITelephony.Stub.asInterface(
TelephonyFrameworkInitializer
.getTelephonyServiceManager()

View File

@@ -28,6 +28,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.provider.Settings;
import android.telephony.AccessNetworkConstants;
import android.telephony.BinderCacheManager;
import android.telephony.CarrierConfigManager;
import android.telephony.TelephonyFrameworkInitializer;
import android.telephony.ims.aidl.IImsCapabilityCallback;
@@ -149,14 +150,17 @@ public class ImsRcsManager {
private final int mSubId;
private final Context mContext;
private final BinderCacheManager<IImsRcsController> mBinderCache;
/**
* Use {@link ImsManager#getImsRcsManager(int)} to create an instance of this class.
* @hide
*/
public ImsRcsManager(Context context, int subId) {
public ImsRcsManager(Context context, int subId,
BinderCacheManager<IImsRcsController> binderCache) {
mSubId = subId;
mContext = context;
mBinderCache = binderCache;
}
/**

View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.ims;
parcelable SipDelegateImsConfiguration;

View File

@@ -22,12 +22,12 @@ import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.Context;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.telephony.BinderCacheManager;
import android.telephony.CarrierConfigManager;
import android.telephony.TelephonyFrameworkInitializer;
import android.telephony.ims.aidl.IImsRcsController;
import android.telephony.ims.aidl.SipDelegateConnectionAidlWrapper;
import android.telephony.ims.stub.DelegateConnectionMessageCallback;
import android.telephony.ims.stub.DelegateConnectionStateCallback;
import android.telephony.ims.stub.SipDelegate;
@@ -261,6 +261,7 @@ public class SipDelegateManager {
private final Context mContext;
private final int mSubId;
private final BinderCacheManager<IImsRcsController> mBinderCache;
/**
* Only visible for testing. To instantiate an instance of this class, please use
@@ -268,9 +269,11 @@ public class SipDelegateManager {
* @hide
*/
@VisibleForTesting
public SipDelegateManager(Context context, int subId) {
public SipDelegateManager(Context context, int subId,
BinderCacheManager<IImsRcsController> binderCache) {
mContext = context;
mSubId = subId;
mBinderCache = binderCache;
}
/**
@@ -290,7 +293,7 @@ public class SipDelegateManager {
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean isSupported() throws ImsException {
try {
IImsRcsController controller = getIImsRcsController();
IImsRcsController controller = mBinderCache.getBinder();
if (controller == null) {
throw new ImsException("Telephony server is down",
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
@@ -315,7 +318,7 @@ public class SipDelegateManager {
* a persistent binding to when the app is the default SMS application.
* @param request The parameters that are associated with the SipDelegate creation request that
* will be used to create the SipDelegate connection.
* @param e The executor that will be used to call the callbacks associated with this
* @param executor The executor that will be used to call the callbacks associated with this
* SipDelegate.
* @param dc The callback that will be used to notify the listener of the creation/destruction
* of the remote SipDelegate as well as changes to the state of the remote SipDelegate
@@ -327,18 +330,34 @@ public class SipDelegateManager {
* associated with this SipDelegateManager. See {@link ImsException#getCode()}.
* @hide
*/
public void createSipDelegate(@NonNull DelegateRequest request, @NonNull Executor e,
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void createSipDelegate(@NonNull DelegateRequest request, @NonNull Executor executor,
@NonNull DelegateConnectionStateCallback dc,
@NonNull DelegateConnectionMessageCallback mc) throws ImsException {
if (request == null || e == null || dc == null || mc == null) {
if (request == null || executor == null || dc == null || mc == null) {
throw new IllegalArgumentException("Invalid arguments passed into createSipDelegate");
}
throw new ImsException("creating a SipDelegate is not supported" ,
ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
try {
SipDelegateConnectionAidlWrapper wrapper =
new SipDelegateConnectionAidlWrapper(executor, dc, mc);
IImsRcsController controller = mBinderCache.listenOnBinder(wrapper,
wrapper::binderDied);
if (controller == null) {
throw new ImsException("Telephony server is down",
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
controller.createSipDelegate(mSubId, request, wrapper.getStateCallbackBinder(),
wrapper.getMessageCallbackBinder());
} catch (ServiceSpecificException e) {
throw new ImsException(e.getMessage(), e.errorCode);
} catch (RemoteException e) {
throw new ImsException(e.getMessage(),
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
/**
* Destroy a previously created SipDelegateConnection that was created using
* Destroy a previously created {@link SipDelegateConnection} that was created using
* {@link #createSipDelegate}.
* <p>
* This will also clean up all related callbacks in the associated ImsService.
@@ -346,20 +365,32 @@ public class SipDelegateManager {
* @param reason The reason for why this SipDelegateConnection was destroyed.
* @hide
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void destroySipDelegate(@NonNull SipDelegateConnection delegateConnection,
@SipDelegateDestroyReason int reason) {
if (delegateConnection == null) {
throw new IllegalArgumentException("invalid argument passed into destroySipDelegate");
}
// not supported yet.
}
private IImsRcsController getIImsRcsController() {
IBinder binder = TelephonyFrameworkInitializer
.getTelephonyServiceManager()
.getTelephonyImsServiceRegisterer()
.get();
return IImsRcsController.Stub.asInterface(binder);
if (delegateConnection instanceof SipDelegateConnectionAidlWrapper) {
SipDelegateConnectionAidlWrapper w =
(SipDelegateConnectionAidlWrapper) delegateConnection;
try {
IImsRcsController c = mBinderCache.removeRunnable(w);
c.destroySipDelegate(mSubId, w.getSipDelegateBinder(), reason);
} catch (RemoteException e) {
// Connection to telephony died, but this will signal destruction of SipDelegate
// eventually anyway, so return normally.
try {
w.getStateCallbackBinder().onDestroyed(
SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
} catch (RemoteException ignore) {
// Local to process.
}
}
} else {
throw new IllegalArgumentException("Unknown SipDelegateConnection implementation passed"
+ " into this method");
}
}
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.ims;
parcelable SipMessage;

View File

@@ -17,10 +17,15 @@
package android.telephony.ims.aidl;
import android.net.Uri;
import android.telephony.ims.DelegateRequest;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.telephony.ims.aidl.IRcsUceControllerCallback;
import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
import android.telephony.ims.aidl.ISipDelegate;
import android.telephony.ims.aidl.ISipDelegateMessageCallback;
import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
import com.android.ims.ImsFeatureContainer;
import com.android.ims.internal.IImsServiceFeatureCallback;
@@ -58,6 +63,10 @@ interface IImsRcsController {
// SipDelegateManager
boolean isSipDelegateSupported(int subId);
void createSipDelegate(int subId, in DelegateRequest request,
ISipDelegateConnectionStateCallback delegateState,
ISipDelegateMessageCallback delegateMessage);
void destroySipDelegate(int subId, ISipDelegate connection, int reason);
// Internal commands that should not be made public
void registerRcsFeatureCallback(int slotId, in IImsServiceFeatureCallback callback);

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.ims.aidl;
import android.telephony.ims.SipMessage;
/**
* See {@link SipDelegate} and {@link SipDelegateConnection} for docs regarding this callback.
* {@hide}
*/
oneway interface ISipDelegate {
void sendMessage(in SipMessage sipMessage, int configVersion);
void notifyMessageReceived(in String viaTransactionId);
void notifyMessageReceiveError(in String viaTransactionId, int reason);
// only used by SipDelegate.
void closeDialog(in String callId);
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.ims.aidl;
import android.telephony.ims.DelegateRegistrationState;
import android.telephony.ims.FeatureTagState;
import android.telephony.ims.SipDelegateImsConfiguration;
import android.telephony.ims.aidl.ISipDelegate;
/**
* See {@link SipDelegateConnectionStateCallback} for docs regarding this callback.
* {@hide}
*/
oneway interface ISipDelegateConnectionStateCallback {
void onCreated(ISipDelegate c);
void onFeatureTagStatusChanged(in DelegateRegistrationState registrationState,
in List<FeatureTagState> deniedFeatureTags);
void onImsConfigurationChanged(in SipDelegateImsConfiguration registeredSipConfig);
void onDestroyed(int reason);
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.ims.aidl;
import android.telephony.ims.SipMessage;
/**
* See {@link DelegateMessageCallback} and {@link DelegateConnectionMessageCallback} for docs
* regarding this callback.
* {@hide}
*/
oneway interface ISipDelegateMessageCallback {
void onMessageReceived(in SipMessage message);
void onMessageSent(in String viaTransactionId);
void onMessageSendFailure(in String viaTransactionId, int reason);
}

View File

@@ -0,0 +1,260 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.ims.aidl;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.telephony.ims.DelegateRegistrationState;
import android.telephony.ims.FeatureTagState;
import android.telephony.ims.SipDelegateConnection;
import android.telephony.ims.SipDelegateImsConfiguration;
import android.telephony.ims.SipDelegateManager;
import android.telephony.ims.SipMessage;
import android.telephony.ims.stub.DelegateConnectionMessageCallback;
import android.telephony.ims.stub.DelegateConnectionStateCallback;
import android.telephony.ims.stub.SipDelegate;
import android.util.ArraySet;
import android.util.Log;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicReference;
/**
* Wrapper class implementing {@link SipDelegateConnection} using AIDL, which is returned to the
* local process. Also holds a reference to incoming connection message and state AIDL impl to
* trampoline events to callbacks as well as notify the local process in the event that the remote
* process becomes unavailable.
* <p>
* When the remote {@link SipDelegate} is created, this instance tracks the
* {@link ISipDelegate} associated with it and implements the
* {@link SipDelegateConnection} sent back to the local callback.
* @hide
*/
public class SipDelegateConnectionAidlWrapper implements SipDelegateConnection,
IBinder.DeathRecipient {
private static final String LOG_TAG = "SipDelegateCAW";
private final ISipDelegateConnectionStateCallback.Stub mStateBinder =
new ISipDelegateConnectionStateCallback.Stub() {
@Override
public void onCreated(ISipDelegate c) {
associateSipDelegate(c);
final long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(() ->
mStateCallback.onCreated(SipDelegateConnectionAidlWrapper.this));
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override
public void onFeatureTagStatusChanged(DelegateRegistrationState registrationState,
List<FeatureTagState> deniedFeatureTags) {
final long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(() ->
mStateCallback.onFeatureTagStatusChanged(registrationState,
new ArraySet<>(deniedFeatureTags)));
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override
public void onImsConfigurationChanged(SipDelegateImsConfiguration registeredSipConfig) {
final long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(() ->
mStateCallback.onImsConfigurationChanged(registeredSipConfig));
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override
public void onDestroyed(int reason) {
invalidateSipDelegateBinder();
final long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(() ->
mStateCallback.onDestroyed(reason));
} finally {
Binder.restoreCallingIdentity(token);
}
}
};
private final ISipDelegateMessageCallback.Stub mMessageBinder =
new ISipDelegateMessageCallback.Stub() {
@Override
public void onMessageReceived(SipMessage message) {
final long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(() ->
mMessageCallback.onMessageReceived(message));
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override
public void onMessageSent(String viaTransactionId) {
final long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(() ->
mMessageCallback.onMessageSent(viaTransactionId));
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override
public void onMessageSendFailure(String viaTransactionId, int reason) {
final long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(() ->
mMessageCallback.onMessageSendFailure(viaTransactionId, reason));
} finally {
Binder.restoreCallingIdentity(token);
}
}
};
private final Executor mExecutor;
private final DelegateConnectionStateCallback mStateCallback;
private final DelegateConnectionMessageCallback mMessageCallback;
private final AtomicReference<ISipDelegate> mDelegateBinder =
new AtomicReference<>();
/**
* Wrap the local state and message callbacks, calling the implementation of these interfaces
* when the remote process calls these methods.
*/
public SipDelegateConnectionAidlWrapper(Executor executor,
DelegateConnectionStateCallback stateCallback,
DelegateConnectionMessageCallback messageCallback) {
mExecutor = executor;
mStateCallback = stateCallback;
mMessageCallback = messageCallback;
}
@Override
public void sendMessage(SipMessage sipMessage, int configVersion) {
try {
ISipDelegate conn = getSipDelegateBinder();
if (conn == null) {
notifyLocalMessageFailedToSend(sipMessage,
SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED);
return;
}
conn.sendMessage(sipMessage, configVersion);
} catch (RemoteException e) {
notifyLocalMessageFailedToSend(sipMessage,
SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_DEAD);
}
}
@Override
public void notifyMessageReceived(String viaTransactionId) {
try {
ISipDelegate conn = getSipDelegateBinder();
if (conn == null) {
return;
}
conn.notifyMessageReceived(viaTransactionId);
} catch (RemoteException e) {
// Nothing to do here, app will eventually get remote death callback.
}
}
@Override
public void notifyMessageReceiveError(String viaTransactionId, int reason) {
try {
ISipDelegate conn = getSipDelegateBinder();
if (conn == null) {
return;
}
conn.notifyMessageReceiveError(viaTransactionId, reason);
} catch (RemoteException e) {
// Nothing to do here, app will eventually get remote death callback.
}
}
// Also called upon IImsRcsController death (telephony process dies).
@Override
public void binderDied() {
invalidateSipDelegateBinder();
mExecutor.execute(() -> mStateCallback.onDestroyed(
SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD));
}
/**
* @return Implementation of state binder.
*/
public ISipDelegateConnectionStateCallback getStateCallbackBinder() {
return mStateBinder;
}
/**
* @return Implementation of message binder.
*/
public ISipDelegateMessageCallback getMessageCallbackBinder() {
return mMessageBinder;
}
/**
* @return The ISipDelegateConnection associated with this wrapper.
*/
public ISipDelegate getSipDelegateBinder() {
return mDelegateBinder.get();
}
private void associateSipDelegate(ISipDelegate c) {
if (c != null) {
try {
c.asBinder().linkToDeath(this, 0 /*flags*/);
} catch (RemoteException e) {
// already dead.
c = null;
}
}
mDelegateBinder.set(c);
}
private void invalidateSipDelegateBinder() {
ISipDelegate oldVal = mDelegateBinder.getAndUpdate((unused) -> null);
if (oldVal != null) {
try {
oldVal.asBinder().unlinkToDeath(this, 0 /*flags*/);
} catch (NoSuchElementException e) {
Log.i(LOG_TAG, "invalidateSipDelegateBinder: " + e);
}
}
}
private void notifyLocalMessageFailedToSend(SipMessage m, int reason) {
//TODO: parse transaction ID or throw IllegalArgumentException if the SipMessage
// transaction ID can not be parsed.
mExecutor.execute(() ->
mMessageCallback.onMessageSendFailure(null, reason));
}
}