chromium/chrome/android/javatests/src/org/chromium/chrome/browser/hardware_acceleration/Utils.java

// Copyright 2015 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.chrome.browser.hardware_acceleration;

import android.app.Dialog;
import android.view.View;
import android.view.ViewTreeObserver.OnPreDrawListener;

import org.junit.Assert;

import org.chromium.base.SysUtils;
import org.chromium.base.ThreadUtils;
import org.chromium.base.task.PostTask;
import org.chromium.base.task.TaskTraits;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.chrome.browser.app.ChromeActivity;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

/** Various utils for hardware acceleration tests. */
public class Utils {

    /**
     * Asserts that activity is hardware accelerated only on high-end devices. I.e. on low-end
     * devices hardware acceleration must be off.
     */
    public static void assertHardwareAcceleration(ChromeActivity activity) throws Exception {
        assertActivityAcceleration(activity);
        assertChildWindowAcceleration(activity);
    }

    /**
     * Asserts that there is no thread named 'RenderThread' (which is essential for hardware
     * acceleration).
     */
    public static void assertNoRenderThread() {
        Assert.assertFalse(collectThreadNames().contains("RenderThread"));
    }

    /** Asserts that the argument is true when HW acceleration is enabled and false otherwise. */
    public static void assertAcceleration(boolean accelerated) {
        if (SysUtils.isLowEndDevice()) {
            Assert.assertFalse(accelerated);
        } else {
            Assert.assertTrue(accelerated);
        }
    }

    private static void assertActivityAcceleration(final ChromeActivity activity) throws Exception {
        final AtomicBoolean accelerated = new AtomicBoolean();
        final CallbackHelper listenerCalled = new CallbackHelper();

        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    final View view = activity.getWindow().getDecorView();
                    view.getViewTreeObserver()
                            .addOnPreDrawListener(
                                    new OnPreDrawListener() {
                                        @Override
                                        public boolean onPreDraw() {
                                            view.getViewTreeObserver()
                                                    .removeOnPreDrawListener(this);
                                            accelerated.set(view.isHardwareAccelerated());
                                            listenerCalled.notifyCalled();
                                            return true;
                                        }
                                    });
                    view.invalidate();
                });

        listenerCalled.waitForCallback(0);
        assertAcceleration(accelerated.get());
    }

    private static void assertChildWindowAcceleration(final ChromeActivity activity)
            throws Exception {
        final AtomicBoolean accelerated = new AtomicBoolean();
        final CallbackHelper listenerCalled = new CallbackHelper();

        PostTask.postTask(
                TaskTraits.UI_DEFAULT,
                new Runnable() {
                    @Override
                    public void run() {
                        final Dialog dialog = new Dialog(activity);
                        dialog.setContentView(
                                new View(activity) {
                                    @Override
                                    public void onAttachedToWindow() {
                                        super.onAttachedToWindow();
                                        accelerated.set(isHardwareAccelerated());
                                        listenerCalled.notifyCalled();
                                        dialog.dismiss();
                                    }
                                });
                        dialog.show();
                    }
                });

        listenerCalled.waitForCallback(0);
        assertAcceleration(accelerated.get());
    }

    private static Set<String> collectThreadNames() {
        Set<String> names = new HashSet<String>();
        for (Thread thread : Thread.getAllStackTraces().keySet()) {
            names.add(thread.getName());
        }
        return names;
    }
}