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

package org.chromium.content.browser.test.util;

import android.app.Instrumentation;
import android.os.SystemClock;
import android.view.KeyEvent;
import android.view.View;

import org.chromium.base.ThreadUtils;

/**
 * Collection of keyboard utilities.
 */
public class KeyUtils {
    /**
     * Sends (synchronously) a single key down/up pair of events to the specified view.
     * <p>
     * Does not use the event injecting framework, but instead relies on
     * {@link View#dispatchKeyEventPreIme(KeyEvent)} and {@link View#dispatchKeyEvent(KeyEvent)} of
     * the view itself
     * <p>
     * The event injecting framework requires INJECT_EVENTS permission and that has been flaky on
     * our perf bots.  So until a root cause of the issue can be found, we should use this instead
     * of the functionality provided by {@link #sendKeys(int...)}.
     *
     * @param i The application being instrumented.
     * @param v The view to receive the key event.
     * @param keyCode The keycode for the event to be issued.
     */
    public static void singleKeyEventView(Instrumentation i, final View v, int keyCode) {
        long downTime = SystemClock.uptimeMillis();
        long eventTime = SystemClock.uptimeMillis();

        final KeyEvent downEvent =
                new KeyEvent(downTime, eventTime, KeyEvent.ACTION_DOWN, keyCode, 0);
        dispatchKeyEvent(i, v, downEvent);

        downTime = SystemClock.uptimeMillis();
        eventTime = SystemClock.uptimeMillis();
        final KeyEvent upEvent =
                new KeyEvent(downTime, eventTime, KeyEvent.ACTION_UP, keyCode, 0);
        dispatchKeyEvent(i, v, upEvent);
    }

    private static void dispatchKeyEvent(final Instrumentation i, final View v,
            final KeyEvent event) {
        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                if (!v.dispatchKeyEventPreIme(event)) {
                    v.dispatchKeyEvent(event);
                }
            }
        });
        i.waitForIdleSync();
    }
}
@@ -275,16 +275,53 @@
 mClock;%0A
+import android.view.KeyCharacterMap;%0A
 import a
@@ -1854,16 +1854,605 @@
 %0A    %7D%0A%0A
+    /**%0A     * Types the given text (on character at a time) into the specified view.%0A     *%0A     * @param i The application being instrumented.%0A     * @param v The view to receive the text.%0A     * @param text The text to be input.%0A     */%0A    public static void typeTextIntoView(Instrumentation i, View v, String text) %7B%0A        KeyCharacterMap characterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);%0A        KeyEvent%5B%5D events = characterMap.getEvents(text.toCharArray());%0A        for (KeyEvent event : events) %7B%0A            dispatchKeyEvent(i, v, event);%0A        %7D%0A    %7D%0A%0A
     priv

Add a test utility to type a string into a view.