Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 18238546 authored by Brad Ebinger's avatar Brad Ebinger Committed by Automerger Merge Worker
Browse files

Merge changes from topics "sip_transport_api_conn", "sip_transport_api_def"...

Merge changes from topics "sip_transport_api_conn", "sip_transport_api_def" am: c87a4311 am: ccc28352 am: 8ffeb462 am: 7860541d

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

Change-Id: I21093871affa12c76c5091e7263cafb56fe1c682
parents 8b3df455 7860541d
Loading
Loading
Loading
Loading
+33 −0
Original line number Original line Diff line number Diff line
/*
 * 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);
}
+9 −1
Original line number Original line Diff line number Diff line
@@ -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);
}
}
+192 −0
Original line number Original line Diff line number Diff line
/*
 * 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));
        }
    }
}
+94 −11
Original line number Original line Diff line number Diff line
@@ -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 final Executor mBinderExecutor;
    private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
    private final ISipTransport mSipTransportImpl = new ISipTransport.Stub() {
        @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 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();
    }
    }


    /**
    /**