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:
@@ -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);
|
||||||
|
}
|
||||||
@@ -16,9 +16,17 @@
|
|||||||
|
|
||||||
package android.telephony.ims.aidl;
|
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.
|
* Interface for commands to the SIP Transport implementation.
|
||||||
* {@hide}
|
* {@hide}
|
||||||
*/
|
*/
|
||||||
interface ISipTransport {
|
oneway interface ISipTransport {
|
||||||
|
void createSipDelegate(in DelegateRequest request, ISipDelegateStateCallback dc,
|
||||||
|
ISipDelegateMessageCallback mc);
|
||||||
|
void destroySipDelegate(ISipDelegate delegate, int reason);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,12 +18,22 @@ package android.telephony.ims.stub;
|
|||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.SystemApi;
|
import android.annotation.SystemApi;
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.IBinder;
|
||||||
import android.telephony.ims.DelegateMessageCallback;
|
import android.telephony.ims.DelegateMessageCallback;
|
||||||
import android.telephony.ims.DelegateRequest;
|
import android.telephony.ims.DelegateRequest;
|
||||||
import android.telephony.ims.DelegateStateCallback;
|
import android.telephony.ims.DelegateStateCallback;
|
||||||
import android.telephony.ims.SipDelegateManager;
|
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.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;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,16 +47,46 @@ import java.util.concurrent.Executor;
|
|||||||
*/
|
*/
|
||||||
@SystemApi
|
@SystemApi
|
||||||
public class SipTransportImplBase {
|
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 Executor mBinderExecutor;
|
||||||
private final ISipTransport mSipTransportImpl = new ISipTransport.Stub() {
|
private final ArrayList<SipDelegateAidlWrapper> mDelegates = new ArrayList<>();
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an implementation of SipTransportImplBase.
|
* 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) {
|
public SipTransportImplBase(@NonNull Executor executor) {
|
||||||
if (executor == null) {
|
if (executor == null) {
|
||||||
@@ -57,8 +97,13 @@ public class SipTransportImplBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ImsService implements this method to handle requests to create a new {@link SipDelegate}
|
* Called by the Telephony framework to request the creation of a new {@link SipDelegate}.
|
||||||
* for subscription associated with it.
|
* <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
|
* @param request A SIP delegate request containing the parameters that the remote RCS
|
||||||
* application wishes to use.
|
* application wishes to use.
|
||||||
@@ -70,20 +115,58 @@ public class SipTransportImplBase {
|
|||||||
*/
|
*/
|
||||||
public void createSipDelegate(@NonNull DelegateRequest request,
|
public void createSipDelegate(@NonNull DelegateRequest request,
|
||||||
@NonNull DelegateStateCallback dc, @NonNull DelegateMessageCallback mc) {
|
@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
|
* Destroys the SipDelegate associated with a remote IMS application.
|
||||||
* destroyed, SipDelegate#onDestroy should be called to notify listeners of its destruction to
|
* <p>
|
||||||
* release resources.
|
* After the delegate is destroyed, {@link DelegateStateCallback#onDestroyed(int)} must be
|
||||||
* @param delegate The delegate to be modified.
|
* called to notify listeners of its destruction to release associated resources.
|
||||||
* @param reason The reason the remote connection to this SipDelegate is being destroyed.
|
* <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
|
* @hide
|
||||||
*/
|
*/
|
||||||
public void destroySipDelegate(@NonNull SipDelegate delegate,
|
public void destroySipDelegate(@NonNull SipDelegate delegate,
|
||||||
@SipDelegateManager.SipDelegateDestroyReason int reason) {
|
@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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user