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

Commit 7f1951c0 authored by Nathan Harold's avatar Nathan Harold Committed by Android (Google) Code Review
Browse files

Merge "Lazily init Handler in SubscriptionManager" into main

parents 8f278f98 958f2008
Loading
Loading
Loading
Loading
+45 −19
Original line number Diff line number Diff line
@@ -35,6 +35,9 @@ import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.app.PendingIntent;
import android.app.PropertyInvalidatedCache;
import android.compat.Compatibility;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
@@ -85,6 +88,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -1322,41 +1326,61 @@ public class SubscriptionManager {
     * for #onSubscriptionsChanged to be invoked.
     */
    public static class OnSubscriptionsChangedListener {
        private class OnSubscriptionsChangedListenerHandler extends Handler {
            OnSubscriptionsChangedListenerHandler() {
                super();
            }

            OnSubscriptionsChangedListenerHandler(Looper looper) {
                super(looper);
            }
        }
        /**
         * After {@link Build.VERSION_CODES.Q}, it is no longer necessary to instantiate a
         * Handler inside of the OnSubscriptionsChangedListener in all cases, so it will only
         * be done for callers that do not supply an Executor.
         */
        @ChangeId
        @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
        private static final long LAZY_INITIALIZE_SUBSCRIPTIONS_CHANGED_HANDLER = 278814050L;

        /**
         * Posted executor callback on the handler associated with a given looper.
         * The looper can be the calling thread's looper or the looper passed from the
         * constructor {@link #OnSubscriptionsChangedListener(Looper)}.
         * For backwards compatibility reasons, stashes the Looper associated with the thread
         * context in which this listener was created.
         */
        private final HandlerExecutor mExecutor;
        private final Looper mCreatorLooper;

        /**
         * @hide
         */
        public HandlerExecutor getHandlerExecutor() {
            return mExecutor;
        public Looper getCreatorLooper() {
            return mCreatorLooper;
        }

        /**
         * Create an OnSubscriptionsChangedListener.
         *
         * For callers targeting {@link Build.VERSION_CODES.P} or earlier, this can only be called
         * on a thread that already has a prepared Looper. Callers targeting Q or later should
         * subsequently use {@link SubscriptionManager#addOnSubscriptionsChangedListener(
         * Executor, OnSubscriptionsChangedListener)}.
         *
         * On OS versions prior to {@link Build.VERSION_CODES.V} callers should assume that this
         * call will fail if invoked on a thread that does not already have a prepared looper.
         */
        public OnSubscriptionsChangedListener() {
            mExecutor = new HandlerExecutor(new OnSubscriptionsChangedListenerHandler());
            mCreatorLooper = Looper.myLooper();
            if (mCreatorLooper == null
                    && !Compatibility.isChangeEnabled(
                            LAZY_INITIALIZE_SUBSCRIPTIONS_CHANGED_HANDLER)) {
                // matches the implementation of Handler
                throw new RuntimeException(
                        "Can't create handler inside thread "
                        + Thread.currentThread()
                        + " that has not called Looper.prepare()");
            }
        }

        /**
         * Allow a listener to be created with a custom looper
         * @param looper the looper that the underlining handler should run on
         * @param looper the non-null Looper that the underlining handler should run on
         * @hide
         */
        public OnSubscriptionsChangedListener(Looper looper) {
            mExecutor = new HandlerExecutor(new OnSubscriptionsChangedListenerHandler(looper));
        public OnSubscriptionsChangedListener(@NonNull Looper looper) {
            Objects.requireNonNull(looper);
            mCreatorLooper = looper;
        }

        /**
@@ -1423,7 +1447,9 @@ public class SubscriptionManager {
    @Deprecated
    public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
        if (listener == null) return;
        addOnSubscriptionsChangedListener(listener.mExecutor, listener);

        addOnSubscriptionsChangedListener(
                new HandlerExecutor(new Handler(listener.getCreatorLooper())), listener);
    }

    /**