Add AIDL connections for SipDelegateManager
Implement AIDL backing for SipDelegateConnection, DelegateConnectionStateCallback, and DelegateConnectionMessageCallback as well as all Parcelables related to those callbacks. Implement SipDelegateConnection with an AIDL wrapper implementation, which trampolines callback events from the remote process to the local callback interface as well as wrap the SipDelegateConnection AIDL so the local process can send messages to the remote SipDelegate. The next CL will be the ImsService AIDL implementation for SipTransport/SipDelegate APIs. Test: atest FrameworksTelephonyTests Change-Id: Ic48cd0f80058d59362c63cf6381304437a81afe0
This commit is contained in:
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
19
telephony/java/android/telephony/ims/DelegateRequest.aidl
Normal file
19
telephony/java/android/telephony/ims/DelegateRequest.aidl
Normal 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;
|
||||
19
telephony/java/android/telephony/ims/FeatureTagState.aidl
Normal file
19
telephony/java/android/telephony/ims/FeatureTagState.aidl
Normal 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;
|
||||
@@ -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()
|
||||
|
||||
@@ -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.SubscriptionManager;
|
||||
import android.telephony.TelephonyFrameworkInitializer;
|
||||
@@ -152,14 +153,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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
19
telephony/java/android/telephony/ims/SipMessage.aidl
Normal file
19
telephony/java/android/telephony/ims/SipMessage.aidl
Normal 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;
|
||||
@@ -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;
|
||||
@@ -55,6 +60,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);
|
||||
|
||||
32
telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl
Normal file
32
telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl
Normal 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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user