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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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.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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user