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

Commit e88480f6 authored by Youming Ye's avatar Youming Ye Committed by Gerrit Code Review
Browse files

Merge "Fix ImsManager callback called once registered"

parents d3ada02c 22fd3ca7
Loading
Loading
Loading
Loading
+32 −100
Original line number Diff line number Diff line
@@ -18,18 +18,17 @@ package com.android.ims;

import android.annotation.Nullable;
import android.content.Context;
import android.net.Uri;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.telephony.Rlog;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsCallProfile;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsMmTelFeature;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.telephony.ims.aidl.IImsSmsListener;
import android.telephony.ims.feature.CapabilityChangeRequest;
import android.telephony.ims.feature.ImsFeature;
@@ -44,11 +43,6 @@ import com.android.ims.internal.IImsMultiEndpoint;
import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.ims.internal.IImsUt;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * A container of the IImsServiceController binder, which implements all of the ImsFeatures that
 * the platform currently supports: MMTel and RCS.
@@ -80,113 +74,58 @@ public class MmTelFeatureConnection {
            onRemovedOrDied();
    };

    private abstract class CallbackAdapterManager<T> {
    private abstract class CallbackAdapterManager<T extends IInterface> {
        private static final String TAG = "CallbackAdapterManager";

        protected final Set<T> mLocalCallbacks =
                Collections.newSetFromMap(new ConcurrentHashMap<>());
        private boolean mHasConnected = false;
        protected final RemoteCallbackList<T> mRemoteCallbacks =
                new RemoteCallbackList<>();

        public void addCallback(T localCallback) throws RemoteException {
            // We only one one binding to the ImsService per process.
            // Store any more locally.
            synchronized (mLock) {
                if (!mHasConnected) {
                // throws a RemoteException if a connection can not be established.
                    if (createConnection()) {
                        mHasConnected = true;
                    } else {
                if (!createConnection(localCallback)) {
                    throw new RemoteException("Can not create connection!");
                }
                }
            }
                Log.i(TAG, "Local callback added: " + localCallback);
            mLocalCallbacks.add(localCallback);
                mRemoteCallbacks.register(localCallback);
            }
        }

        public void removeCallback(T localCallback) {
            // We only maintain one binding to the ImsService per process.
            Log.i(TAG, "Local callback removed: " + localCallback);
            mLocalCallbacks.remove(localCallback);
            synchronized (mLock) {
                // If we have removed all local callbacks, remove callback to ImsService.
                if(mHasConnected) {
                    if (mLocalCallbacks.isEmpty()) {
                        removeConnection();
                        mHasConnected = false;
                    }
                }
                removeConnection(localCallback);
                mRemoteCallbacks.unregister(localCallback);
            }
        }

        public void close() {
            synchronized (mLock) {
                if (mHasConnected) {
                    removeConnection();
                    // Still mark the connection as disconnected, even if this fails.
                    mHasConnected = false;
                }
                final int lastCallbackIndex = mRemoteCallbacks.getRegisteredCallbackCount() - 1;
                for(int ii = lastCallbackIndex; ii >= 0; ii --) {
                    T callbackItem = mRemoteCallbacks.getRegisteredCallbackItem(ii);
                    removeConnection(callbackItem);
                    mRemoteCallbacks.unregister(callbackItem);
                }
                Log.i(TAG, "Closing connection and clearing callbacks");
            mLocalCallbacks.clear();
            }
        }

        abstract boolean createConnection() throws RemoteException;
        abstract boolean createConnection(T localCallback) throws RemoteException;

        abstract void removeConnection();
        abstract void removeConnection(T localCallback);
    }
    private ImsRegistrationCallbackAdapter mRegistrationCallbackManager
            = new ImsRegistrationCallbackAdapter();
    private class ImsRegistrationCallbackAdapter
            extends CallbackAdapterManager<ImsRegistrationImplBase.Callback> {
        private final RegistrationCallbackAdapter mRegistrationCallbackAdapter
                = new RegistrationCallbackAdapter();

        private class RegistrationCallbackAdapter extends IImsRegistrationCallback.Stub {

            @Override
            public void onRegistered(int imsRadioTech) {
                Log.i(TAG, "onRegistered ::");

                mLocalCallbacks.forEach(l -> l.onRegistered(imsRadioTech));
            }

            @Override
            public void onRegistering(int imsRadioTech) {
                Log.i(TAG, "onRegistering ::");

                mLocalCallbacks.forEach(l -> l.onRegistering(imsRadioTech));
            }

            @Override
            public void onDeregistered(ImsReasonInfo imsReasonInfo) {
                Log.i(TAG, "onDeregistered ::");

                mLocalCallbacks.forEach(l -> l.onDeregistered(imsReasonInfo));
            }

            @Override
            public void onTechnologyChangeFailed(int targetRadioTech, ImsReasonInfo imsReasonInfo) {
                Log.i(TAG, "onTechnologyChangeFailed :: targetAccessTech=" + targetRadioTech +
                        ", imsReasonInfo=" + imsReasonInfo);

                    mLocalCallbacks.forEach(l -> l.onTechnologyChangeFailed(targetRadioTech,
                            imsReasonInfo));
            }

        @Override
            public void onSubscriberAssociatedUriChanged(Uri[] uris) {
                Log.i(TAG, "onSubscriberAssociatedUriChanged");

                mLocalCallbacks.forEach(l -> l.onSubscriberAssociatedUriChanged(uris));
            }
        }

        @Override
        boolean createConnection() throws RemoteException {
        boolean createConnection(ImsRegistrationImplBase.Callback localCallback)
                throws RemoteException {
            IImsRegistration imsRegistration = getRegistration();
            if (imsRegistration != null) {
                getRegistration().addRegistrationCallback(mRegistrationCallbackAdapter);
                getRegistration().addRegistrationCallback(localCallback);
                return true;
            } else {
                Log.e(TAG, "ImsRegistration is null");
@@ -195,11 +134,11 @@ public class MmTelFeatureConnection {
        }

        @Override
        void removeConnection() {
        void removeConnection(ImsRegistrationImplBase.Callback localCallback) {
            IImsRegistration imsRegistration = getRegistration();
            if (imsRegistration != null) {
                try {
                    getRegistration().removeRegistrationCallback(mRegistrationCallbackAdapter);
                    getRegistration().removeRegistrationCallback(localCallback);
                } catch (RemoteException e) {
                    Log.w(TAG, "removeConnection: couldn't remove registration callback");
                }
@@ -213,26 +152,16 @@ public class MmTelFeatureConnection {
            = new CapabilityCallbackManager();
    private class CapabilityCallbackManager
            extends CallbackAdapterManager<ImsFeature.CapabilityCallback> {
        private final CapabilityCallbackAdapter mCallbackAdapter = new CapabilityCallbackAdapter();

        private class CapabilityCallbackAdapter extends ImsFeature.CapabilityCallback {
            // Called when the Capabilities Status on this connection have changed.
        @Override
            public void onCapabilitiesStatusChanged(ImsFeature.Capabilities config) {
                mLocalCallbacks.forEach(
                        callback -> callback.onCapabilitiesStatusChanged(config));
            }
        }

        @Override
        boolean createConnection() throws RemoteException {
        boolean createConnection(ImsFeature.CapabilityCallback localCallback) throws RemoteException {
            IImsMmTelFeature binder;
            synchronized (mLock) {
                checkServiceIsReady();
                binder = getServiceInterface(mBinder);
            }
            if (binder != null) {
                binder.addCapabilityCallback(mCallbackAdapter);
                binder.addCapabilityCallback(localCallback);
                return true;
            } else {
                Log.w(TAG, "create: Couldn't get IImsMmTelFeature binder");
@@ -241,7 +170,7 @@ public class MmTelFeatureConnection {
        }

        @Override
        void removeConnection() {
        void removeConnection(ImsFeature.CapabilityCallback localCallback) {
            IImsMmTelFeature binder = null;
            synchronized (mLock) {
                try {
@@ -249,11 +178,12 @@ public class MmTelFeatureConnection {
                    binder = getServiceInterface(mBinder);
                } catch (RemoteException e) {
                    // binder is null
                    Log.w(TAG, "remove: Binder is null");
                }
            }
            if (binder != null) {
                try {
                    binder.removeCapabilityCallback(mCallbackAdapter);
                    binder.removeCapabilityCallback(localCallback);
                } catch (RemoteException e) {
                    Log.w(TAG, "remove: IImsMmTelFeature binder is dead");
                }
@@ -380,6 +310,8 @@ public class MmTelFeatureConnection {
     */
    private void onRemovedOrDied() {
        synchronized (mLock) {
            mRegistrationCallbackManager.close();
            mCapabilityCallbackManager.close();
            if (mIsAvailable) {
                mIsAvailable = false;
                // invalidate caches.