Merge changes from topics "sip_transport_api_conn", "sip_transport_api_def" am: c87a43111a

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

Change-Id: Ib5c191e9e17ff8b82e266b9d3907bc96e0fde685
This commit is contained in:
Brad Ebinger
2020-11-12 23:39:04 +00:00
committed by Automerger Merge Worker
4 changed files with 329 additions and 13 deletions

View File

@@ -0,0 +1,33 @@
/*
* 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 SipDelegateStateCallback} for docs regarding this callback.
* {@hide}
*/
oneway interface ISipDelegateStateCallback {
void onCreated(ISipDelegate c, in List<FeatureTagState> deniedFeatureTags);
void onFeatureTagRegistrationChanged(in DelegateRegistrationState registrationState);
void onImsConfigurationChanged(in SipDelegateImsConfiguration registeredSipConfig);
void onDestroyed(int reason);
}

View File

@@ -16,9 +16,17 @@
package android.telephony.ims.aidl;
import android.telephony.ims.DelegateRequest;
import android.telephony.ims.aidl.ISipDelegate;
import android.telephony.ims.aidl.ISipDelegateMessageCallback;
import android.telephony.ims.aidl.ISipDelegateStateCallback;
/**
* Interface for commands to the SIP Transport implementation.
* {@hide}
*/
interface ISipTransport {
oneway interface ISipTransport {
void createSipDelegate(in DelegateRequest request, ISipDelegateStateCallback dc,
ISipDelegateMessageCallback mc);
void destroySipDelegate(ISipDelegate delegate, int reason);
}

View File

@@ -0,0 +1,192 @@
/*
* 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.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Binder;
import android.os.RemoteException;
import android.telephony.ims.DelegateMessageCallback;
import android.telephony.ims.DelegateRegistrationState;
import android.telephony.ims.DelegateStateCallback;
import android.telephony.ims.FeatureTagState;
import android.telephony.ims.SipDelegateImsConfiguration;
import android.telephony.ims.SipDelegateManager;
import android.telephony.ims.SipMessage;
import android.telephony.ims.stub.SipDelegate;
import java.util.List;
import java.util.concurrent.Executor;
/**
* Implementation of callbacks by wrapping the internal AIDL from telephony. Also implements
* ISipDelegate internally when {@link DelegateStateCallback#onCreated(SipDelegate, List)} is called
* in order to trampoline events back to telephony.
* @hide
*/
public class SipDelegateAidlWrapper implements DelegateStateCallback, DelegateMessageCallback {
private final ISipDelegate.Stub mDelegateBinder = new ISipDelegate.Stub() {
@Override
public void sendMessage(SipMessage sipMessage, int configVersion) {
SipDelegate d = mDelegate;
final long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(() -> d.sendMessage(sipMessage, configVersion));
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override
public void notifyMessageReceived(String viaTransactionId) {
SipDelegate d = mDelegate;
final long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(() -> d.notifyMessageReceived(viaTransactionId));
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override
public void notifyMessageReceiveError(String viaTransactionId, int reason) {
SipDelegate d = mDelegate;
final long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(() -> d.notifyMessageReceiveError(viaTransactionId, reason));
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override
public void closeDialog(String callId) {
SipDelegate d = mDelegate;
final long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(() -> d.closeDialog(callId));
} finally {
Binder.restoreCallingIdentity(token);
}
}
};
private final ISipDelegateMessageCallback mMessageBinder;
private final ISipDelegateStateCallback mStateBinder;
private final Executor mExecutor;
private volatile SipDelegate mDelegate;
public SipDelegateAidlWrapper(Executor executor, ISipDelegateStateCallback stateBinder,
ISipDelegateMessageCallback messageBinder) {
mExecutor = executor;
mStateBinder = stateBinder;
mMessageBinder = messageBinder;
}
@Override
public void onMessageReceived(SipMessage message) {
try {
mMessageBinder.onMessageReceived(message);
} catch (RemoteException e) {
// BinderDied will be called on SipTransport instance to trigger destruction. Notify
// failure message failure locally for now.
SipDelegate d = mDelegate;
if (d != null) {
notifyLocalMessageFailedToBeReceived(message,
SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_DEAD);
}
}
}
@Override
public void onMessageSent(String viaTransactionId) {
try {
mMessageBinder.onMessageSent(viaTransactionId);
} catch (RemoteException e) {
// BinderDied will trigger destroySipDelegate, so just ignore this locally.
}
}
@Override
public void onMessageSendFailure(String viaTransactionId, int reason) {
try {
mMessageBinder.onMessageSendFailure(viaTransactionId, reason);
} catch (RemoteException e) {
// BinderDied will trigger destroySipDelegate, so just ignore this locally.
}
}
@Override
public void onCreated(@NonNull SipDelegate delegate,
@Nullable List<FeatureTagState> deniedTags) {
mDelegate = delegate;
try {
mStateBinder.onCreated(mDelegateBinder, deniedTags);
} catch (RemoteException e) {
// BinderDied will trigger destroySipDelegate, so just ignore this locally.
}
}
@Override
public void onFeatureTagRegistrationChanged(DelegateRegistrationState registrationState) {
try {
mStateBinder.onFeatureTagRegistrationChanged(registrationState);
} catch (RemoteException e) {
// BinderDied will trigger destroySipDelegate, so just ignore this locally.
}
}
@Override
public void onImsConfigurationChanged(@NonNull SipDelegateImsConfiguration config) {
try {
mStateBinder.onImsConfigurationChanged(config);
} catch (RemoteException e) {
// BinderDied will trigger destroySipDelegate, so just ignore this locally.
}
}
@Override
public void onDestroyed(int reasonCode) {
mDelegate = null;
try {
mStateBinder.onDestroyed(reasonCode);
} catch (RemoteException e) {
// Do not worry about this if the remote side is already dead.
}
}
public SipDelegate getDelegate() {
return mDelegate;
}
public ISipDelegate getDelegateBinder() {
return mDelegateBinder;
}
private void notifyLocalMessageFailedToBeReceived(SipMessage m, int reason) {
//TODO: parse transaction ID or throw IllegalArgumentException if the SipMessage
// transaction ID can not be parsed.
SipDelegate d = mDelegate;
if (d != null) {
mExecutor.execute(() -> d.notifyMessageReceiveError(null, reason));
}
}
}

View File

@@ -18,12 +18,22 @@ package android.telephony.ims.stub;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Binder;
import android.os.IBinder;
import android.telephony.ims.DelegateMessageCallback;
import android.telephony.ims.DelegateRequest;
import android.telephony.ims.DelegateStateCallback;
import android.telephony.ims.SipDelegateManager;
import android.telephony.ims.aidl.ISipDelegate;
import android.telephony.ims.aidl.ISipDelegateMessageCallback;
import android.telephony.ims.aidl.ISipDelegateStateCallback;
import android.telephony.ims.aidl.ISipTransport;
import android.telephony.ims.aidl.SipDelegateAidlWrapper;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
/**
@@ -37,16 +47,46 @@ import java.util.concurrent.Executor;
*/
@SystemApi
public class SipTransportImplBase {
private static final String LOG_TAG = "SipTransportIB";
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
mBinderExecutor.execute(() -> binderDiedInternal());
}
};
private final ISipTransport.Stub mSipTransportImpl = new ISipTransport.Stub() {
@Override
public void createSipDelegate(DelegateRequest request, ISipDelegateStateCallback dc,
ISipDelegateMessageCallback mc) {
final long token = Binder.clearCallingIdentity();
try {
mBinderExecutor.execute(() -> createSipDelegateInternal(request, dc, mc));
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override
public void destroySipDelegate(ISipDelegate delegate, int reason) {
final long token = Binder.clearCallingIdentity();
try {
mBinderExecutor.execute(() -> destroySipDelegateInternal(delegate, reason));
} finally {
Binder.restoreCallingIdentity(token);
}
}
};
private final Executor mBinderExecutor;
private final ISipTransport mSipTransportImpl = new ISipTransport.Stub() {
};
private final ArrayList<SipDelegateAidlWrapper> mDelegates = new ArrayList<>();
/**
* Create an implementation of SipTransportImplBase.
*
* @param executor The executor that remote calls from the framework should be called on.
* @param executor The executor that remote calls from the framework will be called on. This
* includes the methods here as well as the methods in {@link SipDelegate}.
*/
public SipTransportImplBase(@NonNull Executor executor) {
if (executor == null) {
@@ -57,8 +97,13 @@ public class SipTransportImplBase {
}
/**
* The ImsService implements this method to handle requests to create a new {@link SipDelegate}
* for subscription associated with it.
* Called by the Telephony framework to request the creation of a new {@link SipDelegate}.
* <p>
* The implementation must call {@link DelegateStateCallback#onCreated(SipDelegate, List)} with
* the {@link SipDelegate} that is associated with the {@link DelegateRequest}.
* <p>
* This method will be called on the Executor specified in
* {@link SipTransportImplBase#SipTransportImplBase(Executor)}.
*
* @param request A SIP delegate request containing the parameters that the remote RCS
* application wishes to use.
@@ -70,20 +115,58 @@ public class SipTransportImplBase {
*/
public void createSipDelegate(@NonNull DelegateRequest request,
@NonNull DelegateStateCallback dc, @NonNull DelegateMessageCallback mc) {
throw new UnsupportedOperationException("destroySipDelegate not implemented!");
}
/**
* Destroys the SipDelegate associated with a remote IMS application. After the delegate is
* destroyed, SipDelegate#onDestroy should be called to notify listeners of its destruction to
* release resources.
* @param delegate The delegate to be modified.
* @param reason The reason the remote connection to this SipDelegate is being destroyed.
* Destroys the SipDelegate associated with a remote IMS application.
* <p>
* After the delegate is destroyed, {@link DelegateStateCallback#onDestroyed(int)} must be
* called to notify listeners of its destruction to release associated resources.
* <p>
* This method will be called on the Executor specified in
* {@link SipTransportImplBase#SipTransportImplBase(Executor)}.
* @param delegate The delegate to be destroyed.
* @param reason The reason the remote connection to this {@link SipDelegate} is being
* destroyed.
* @hide
*/
public void destroySipDelegate(@NonNull SipDelegate delegate,
@SipDelegateManager.SipDelegateDestroyReason int reason) {
throw new UnsupportedOperationException("destroySipDelegate not implemented!");
}
private void createSipDelegateInternal(DelegateRequest r, ISipDelegateStateCallback cb,
ISipDelegateMessageCallback mc) {
SipDelegateAidlWrapper wrapper = new SipDelegateAidlWrapper(mBinderExecutor, cb, mc);
mDelegates.add(wrapper);
createSipDelegate(r, wrapper, wrapper);
}
private void destroySipDelegateInternal(ISipDelegate d, int reason) {
SipDelegateAidlWrapper result = null;
for (SipDelegateAidlWrapper w : mDelegates) {
if (Objects.equals(d, w.getDelegateBinder())) {
result = w;
break;
}
}
if (result != null) {
mDelegates.remove(result);
destroySipDelegate(result.getDelegate(), reason);
} else {
Log.w(LOG_TAG, "destroySipDelegateInternal, could not findSipDelegate corresponding to "
+ d);
}
}
private void binderDiedInternal() {
for (SipDelegateAidlWrapper w : mDelegates) {
destroySipDelegate(w.getDelegate(),
SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD);
}
mDelegates.clear();
}
/**