chromium/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/NestedSystemMessageHandler.java

// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.content_public.browser.test;

import android.os.Handler;

import org.jni_zero.CalledByNative;
import org.jni_zero.JNINamespace;

import org.chromium.base.test.util.LooperUtils;

import java.lang.reflect.InvocationTargetException;

/**
 * Handles processing messages in nested run loops.
 *
 * Android does not support nested run loops by default. While running
 * in nested mode, we use reflection to retreive messages from the MessageQueue
 * and dispatch them.
 */
@JNINamespace("content")
public class NestedSystemMessageHandler {
    private static final int QUIT_MESSAGE = 10;
    private static final Handler sHandler = new Handler();

    private NestedSystemMessageHandler() {}

    /**
     * Dispatches the first message from the current MessageQueue, blocking
     * until a task becomes available if the queue is empty. Callbacks for
     * other event handlers registered to the thread's looper (e.g.,
     * MessagePumpAndroid) may also be processed as a side-effect.
     *
     * Returns true if task dispatching succeeded, or false if an exception was
     * thrown.
     */
    @SuppressWarnings("unused")
    @CalledByNative
    private static boolean dispatchOneMessage() {
        try {
            LooperUtils.runSingleNestedLooperTask();
        } catch (IllegalArgumentException
                | IllegalAccessException
                | SecurityException
                | InvocationTargetException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /*
     * Causes a previous call to dispatchOneMessage() to stop blocking and
     * return.
     */
    @SuppressWarnings("unused")
    @CalledByNative
    private static void postQuitMessage() {
        // Causes MessageQueue.next() to return in case it was blocking waiting
        // for more messages.
        sHandler.sendMessage(sHandler.obtainMessage(QUIT_MESSAGE));
    }
}