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

Commit 532601e8 authored by Brad Ebinger's avatar Brad Ebinger
Browse files

Callbacks into phone for IMS feature state should be on main thread

When IMS feature state callbacks update the IMS feature state,
they should be on the main thread to ensure that new callback
executors that are registered are not on the binder thread.

Bug: 123305476
Test: manual - crash phone process, atest FrameworksTelephonyTests
Change-Id: I26292022e9274676d751ebe3e0ec63f50e5a200a
parent 6dec24eb
Loading
Loading
Loading
Loading
+36 −28
Original line number Diff line number Diff line
@@ -228,6 +228,7 @@ public class ImsManager {
                new MmTelFeatureConnection.IFeatureUpdate() {
                    @Override
                    public void notifyStateChanged() {
                        mExecutor.execute(() -> {
                            try {
                                int status = ImsFeature.STATE_UNAVAILABLE;
                                synchronized (mLock) {
@@ -255,18 +256,22 @@ public class ImsManager {
                                notifyNotReady();
                                retryGetImsService();
                            }
                        });
                    }

                    @Override
                    public void notifyUnavailable() {
                        mExecutor.execute(() -> {
                            notifyNotReady();
                            retryGetImsService();
                        });
                    }
                };

        private final Context mContext;
        private final int mPhoneId;
        private final Listener mListener;
        private final Executor mExecutor;
        private final Object mLock = new Object();

        private int mRetryCount = 0;
@@ -287,15 +292,18 @@ public class ImsManager {
            mContext = context;
            mPhoneId = phoneId;
            mListener = listener;
            mExecutor = new HandlerExecutor(this);
        }

        public Connector(Context context, int phoneId, Listener listener, Looper looper) {
            super(looper);
        @VisibleForTesting
        public Connector(Context context, int phoneId, Listener listener, Executor executor) {
            mContext = context;
            mPhoneId = phoneId;
            mListener= listener;
            mExecutor = executor;
        }


        /**
         * Start the creation of a connection to the underlying ImsService implementation. When the
         * service is connected, {@link Listener#connectionReady(ImsManager)} will be called with
+63 −44
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.ims;

import android.annotation.Nullable;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Looper;
@@ -56,6 +58,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

/**
@@ -417,6 +420,7 @@ public class MmTelFeatureConnection {
    protected final int mSlotId;
    protected IBinder mBinder;
    private Context mContext;
    private Executor mExecutor;

    private volatile boolean mIsAvailable = false;
    // ImsFeature Status from the ImsService. Cached.
@@ -492,9 +496,10 @@ public class MmTelFeatureConnection {
            new IImsServiceFeatureCallback.Stub() {

        @Override
        public void imsFeatureCreated(int slotId, int feature) throws RemoteException {
            // The feature has been enabled. This happens when the feature is first created and may
            // happen when the feature is re-enabled.
        public void imsFeatureCreated(int slotId, int feature) {
                mExecutor.execute(() -> {
                // The feature has been enabled. This happens when the feature is first created and
                // may happen when the feature is re-enabled.
                synchronized (mLock) {
                    if(mSlotId != slotId) {
                        return;
@@ -513,12 +518,13 @@ public class MmTelFeatureConnection {
                            break;
                        }
                    }

                }
            });
        }

        @Override
        public void imsFeatureRemoved(int slotId, int feature) throws RemoteException {
        public void imsFeatureRemoved(int slotId, int feature) {
            mExecutor.execute(() -> {
                synchronized (mLock) {
                    if (mSlotId != slotId) {
                        return;
@@ -536,10 +542,12 @@ public class MmTelFeatureConnection {
                        }
                    }
                }
            });
        }

        @Override
        public void imsStatusChanged(int slotId, int feature, int status) throws RemoteException {
        public void imsStatusChanged(int slotId, int feature, int status) {
            mExecutor.execute(() -> {
                synchronized (mLock) {
                    Log.i(TAG, "imsStatusChanged: slot: " + slotId + " feature: " + feature +
                            " status: " + status);
@@ -550,12 +558,23 @@ public class MmTelFeatureConnection {
                        }
                    }
                }
            });
        }
    };

    public MmTelFeatureConnection(Context context, int slotId) {
        mSlotId = slotId;
        mContext = context;
        // Callbacks should be scheduled on the main thread.
        if (context.getMainLooper() != null) {
            mExecutor = context.getMainExecutor();
        } else {
            // Fallback to the current thread.
            if (Looper.myLooper() == null) {
                Looper.prepare();
            }
            mExecutor = new HandlerExecutor(new Handler(Looper.myLooper()));
        }
        mRegistrationCallbackManager = new ImsRegistrationCallbackAdapter(context, mLock);
        mCapabilityCallbackManager = new CapabilityCallbackManager(context, mLock);
        mProvisioningCallbackManager = new ProvisioningCallbackManager(context, mLock);