summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Brad Ebinger <breadley@google.com> 2020-11-12 23:58:25 +0000
committer Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> 2020-11-12 23:58:25 +0000
commit449e45b1168c533dbe3ed74670ed390494efd21c (patch)
treec0024847f99fb94ddca441374d43626ec3f12f5f
parentf9bd6dc7343698f133aeb2ba60a6d9f81b52df19 (diff)
parent20734105de9b050d8037e62be3f1bf66cedbaeda (diff)
Add AIDL connections for SipDelegateManager am: bf9c710733 am: 20734105de
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1462844 Change-Id: Ib01d1b59e6b73ae3c93e0c7dbe6c8cab421f2957
-rw-r--r--telephony/java/android/telephony/ImsManager.java37
-rw-r--r--telephony/java/android/telephony/ims/DelegateRegistrationState.aidl19
-rw-r--r--telephony/java/android/telephony/ims/DelegateRequest.aidl19
-rw-r--r--telephony/java/android/telephony/ims/FeatureTagState.aidl19
-rw-r--r--telephony/java/android/telephony/ims/ImsMmTelManager.java14
-rw-r--r--telephony/java/android/telephony/ims/ImsRcsManager.java6
-rw-r--r--telephony/java/android/telephony/ims/SipDelegateImsConfiguration.aidl19
-rw-r--r--telephony/java/android/telephony/ims/SipDelegateManager.java69
-rw-r--r--telephony/java/android/telephony/ims/SipMessage.aidl19
-rw-r--r--telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl11
-rw-r--r--telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl32
-rw-r--r--telephony/java/android/telephony/ims/aidl/ISipDelegateConnectionStateCallback.aidl34
-rw-r--r--telephony/java/android/telephony/ims/aidl/ISipDelegateMessageCallback.aidl30
-rw-r--r--telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java260
14 files changed, 559 insertions, 29 deletions
diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java
index 13f407b14f01..42d7707c97d9 100644
--- a/telephony/java/android/telephony/ImsManager.java
+++ b/telephony/java/android/telephony/ImsManager.java
@@ -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());
}
}
diff --git a/telephony/java/android/telephony/ims/DelegateRegistrationState.aidl b/telephony/java/android/telephony/ims/DelegateRegistrationState.aidl
new file mode 100644
index 000000000000..756ea920d06a
--- /dev/null
+++ b/telephony/java/android/telephony/ims/DelegateRegistrationState.aidl
@@ -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;
diff --git a/telephony/java/android/telephony/ims/DelegateRequest.aidl b/telephony/java/android/telephony/ims/DelegateRequest.aidl
new file mode 100644
index 000000000000..60c990f8258f
--- /dev/null
+++ b/telephony/java/android/telephony/ims/DelegateRequest.aidl
@@ -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;
diff --git a/telephony/java/android/telephony/ims/FeatureTagState.aidl b/telephony/java/android/telephony/ims/FeatureTagState.aidl
new file mode 100644
index 000000000000..bce55742461c
--- /dev/null
+++ b/telephony/java/android/telephony/ims/FeatureTagState.aidl
@@ -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;
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index a4f2a316c99d..d1a893f61e00 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -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()
diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java
index 8b6dac82b0eb..4292aae59515 100644
--- a/telephony/java/android/telephony/ims/ImsRcsManager.java
+++ b/telephony/java/android/telephony/ims/ImsRcsManager.java
@@ -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;
}
/**
diff --git a/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.aidl b/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.aidl
new file mode 100644
index 000000000000..44ae1b130046
--- /dev/null
+++ b/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.aidl
@@ -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;
diff --git a/telephony/java/android/telephony/ims/SipDelegateManager.java b/telephony/java/android/telephony/ims/SipDelegateManager.java
index 3c59d4f6209c..337b7d49323d 100644
--- a/telephony/java/android/telephony/ims/SipDelegateManager.java
+++ b/telephony/java/android/telephony/ims/SipDelegateManager.java
@@ -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");
+ }
}
}
diff --git a/telephony/java/android/telephony/ims/SipMessage.aidl b/telephony/java/android/telephony/ims/SipMessage.aidl
new file mode 100644
index 000000000000..5140f8ac357f
--- /dev/null
+++ b/telephony/java/android/telephony/ims/SipMessage.aidl
@@ -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;
diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
index 8e84e9373f65..f218e35a5a9b 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
@@ -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);
diff --git a/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl b/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl
new file mode 100644
index 000000000000..477ee958e1e8
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl
@@ -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);
+}
diff --git a/telephony/java/android/telephony/ims/aidl/ISipDelegateConnectionStateCallback.aidl b/telephony/java/android/telephony/ims/aidl/ISipDelegateConnectionStateCallback.aidl
new file mode 100644
index 000000000000..ddfcb9994cb8
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/ISipDelegateConnectionStateCallback.aidl
@@ -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);
+}
diff --git a/telephony/java/android/telephony/ims/aidl/ISipDelegateMessageCallback.aidl b/telephony/java/android/telephony/ims/aidl/ISipDelegateMessageCallback.aidl
new file mode 100644
index 000000000000..30b7d6c70647
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/ISipDelegateMessageCallback.aidl
@@ -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);
+}
diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
new file mode 100644
index 000000000000..3bd1a462b31a
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
@@ -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));
+ }
+}