/*
 * Copyright (C) 2022 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 com.android.server.am;

import android.annotation.NonNull;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
import android.os.SystemClock;
import android.util.ArraySet;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;

import java.io.PrintWriter;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.function.BiConsumer;

/**
 * Collection of {@link Looper} that are known to be used for broadcast dispatch
 * within the system. This collection can be useful for callers interested in
 * confirming that all pending broadcasts have been successfully enqueued.
 */
public class BroadcastLoopers {
    private static final String TAG = "BroadcastLoopers";

    @GuardedBy("sLoopers")
    private static final ArraySet<Looper> sLoopers = new ArraySet<>();

    /**
     * Register the given {@link Looper} as possibly having messages that will
     * dispatch broadcasts.
     */
    public static void addLooper(@NonNull Looper looper) {
        synchronized (sLoopers) {
            sLoopers.add(Objects.requireNonNull(looper));
        }
    }

    /**
     * If the current thread is hosting a {@link Looper}, then register it as
     * possibly having messages that will dispatch broadcasts.
     */
    public static void addMyLooper() {
        final Looper looper = Looper.myLooper();
        if (looper != null) {
            synchronized (sLoopers) {
                if (sLoopers.add(looper)) {
                    Slog.w(TAG, "Found previously unknown looper " + looper.getThread());
                }
            }
        }
    }

    /**
     * Wait for all registered {@link Looper} instances to become idle, as
     * defined by {@link MessageQueue#isIdle()}. Note that {@link Message#when}
     * still in the future are ignored for the purposes of the idle test.
     */
    public static void waitForIdle(@NonNull PrintWriter pw) {
        waitForCondition(pw, (looper, latch) -> {
            final MessageQueue queue = looper.getQueue();
            queue.addIdleHandler(() -> {
                latch.countDown();
                return false;
            });
        });
    }

    /**
     * Wait for all registered {@link Looper} instances to handle currently waiting messages.
     * Note that {@link Message#when} still in the future are ignored for the purposes
     * of the idle test.
     */
    public static void waitForBarrier(@NonNull PrintWriter pw) {
        waitForCondition(pw, (looper, latch) -> {
            (new Handler(looper)).post(() -> {
                latch.countDown();
            });
        });
    }

    /**
     * Wait for all registered {@link Looper} instances to meet a certain condition.
     */
    private static void waitForCondition(@NonNull PrintWriter pw,
            @NonNull BiConsumer<Looper, CountDownLatch> condition) {
        final CountDownLatch latch;
        synchronized (sLoopers) {
            final int N = sLoopers.size();
            latch = new CountDownLatch(N);
            for (int i = 0; i < N; i++) {
                final Looper looper = sLoopers.valueAt(i);
                final MessageQueue queue = looper.getQueue();
                if (queue.isIdle()) {
                    latch.countDown();
                } else {
                    condition.accept(looper, latch);
                }
            }
        }

        long lastPrint = 0;
        while (latch.getCount() > 0) {
            final long now = SystemClock.uptimeMillis();
            if (now >= lastPrint + 1000) {
                lastPrint = now;
                pw.println("Waiting for " + latch.getCount() + " loopers to drain...");
                pw.flush();
            }
            SystemClock.sleep(100);
        }
        pw.println("Loopers drained!");
        pw.flush();
    }
}
