1cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le/*
2cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * Copyright (C) 2013 DroidDriver committers
3cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le *
4cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * Licensed under the Apache License, Version 2.0 (the "License");
5cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * you may not use this file except in compliance with the License.
6cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * You may obtain a copy of the License at
7cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le *
8cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le *      http://www.apache.org/licenses/LICENSE-2.0
9cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le *
10cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * Unless required by applicable law or agreed to in writing, software
11cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * distributed under the License is distributed on an "AS IS" BASIS,
12cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * See the License for the specific language governing permissions and
14cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le * limitations under the License.
15cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le */
16cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le
174b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinpackage io.appium.droiddriver.actions;
18cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le
19082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jinimport android.annotation.SuppressLint;
20082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jinimport android.annotation.TargetApi;
218d19bb634c670a49f7a58636a2a535c86b57d538Kevin Jinimport android.os.Build;
22cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Leimport android.view.KeyEvent;
23cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le
244b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.UiElement;
254b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.util.Events;
264b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.util.Strings;
274b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.util.Strings.ToStringHelper;
28cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le
29cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le/**
30082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin * An action to press a single key. While it is convenient for navigating the UI, do not overuse it
31082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin * - the application may interpret key codes in a custom way and, more importantly, application
32082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin * users may not have access to it because the device (physical or virtual keyboard) may not support
33082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin * all key codes.
34cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le */
3529d66eeee5d30f7db747cceeb84defec961b4125Kevin Jinpublic class SingleKeyAction extends KeyAction {
36082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin  // Common instances for convenience and memory preservation.
3729d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin  public static final SingleKeyAction MENU = new SingleKeyAction(KeyEvent.KEYCODE_MENU);
3829d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin  public static final SingleKeyAction SEARCH = new SingleKeyAction(KeyEvent.KEYCODE_SEARCH);
3929d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin  public static final SingleKeyAction BACK = new SingleKeyAction(KeyEvent.KEYCODE_BACK);
4029d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin  public static final SingleKeyAction DELETE = new SingleKeyAction(KeyEvent.KEYCODE_DEL);
41082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin  /** Requires SDK API 11 or higher */
42082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin  @SuppressLint("InlinedApi")
43337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett  public static final SingleKeyAction CTRL_MOVE_HOME = new SingleKeyAction(
44337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett      KeyEvent.KEYCODE_MOVE_HOME, KeyEvent.META_CTRL_LEFT_ON);
45082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin  /** Requires SDK API 11 or higher */
46082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin  @SuppressLint("InlinedApi")
47337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett  public static final SingleKeyAction CTRL_MOVE_END = new SingleKeyAction(
48337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett      KeyEvent.KEYCODE_MOVE_END, KeyEvent.META_CTRL_LEFT_ON);
4970e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin
50cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le  private final int keyCode;
51337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett  private final int metaState;
52cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le
53082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin  /** Defaults metaState to 0 */
5429d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin  public SingleKeyAction(int keyCode) {
55337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett    this(keyCode, 0);
5621a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin  }
5721a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin
58082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin  /** Defaults timeoutMillis to 100 and checkFocused to false */
59337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett  public SingleKeyAction(int keyCode, int metaState) {
60337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett    this(keyCode, metaState, 100L, false);
61337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett  }
62337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett
63337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett  public SingleKeyAction(int keyCode, int metaState, long timeoutMillis, boolean checkFocused) {
6470e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin    super(timeoutMillis, checkFocused);
65cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le    this.keyCode = keyCode;
66337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett    this.metaState = metaState;
67cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le  }
68cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le
69cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le  @Override
70cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le  public boolean perform(InputInjector injector, UiElement element) {
7170e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin    maybeCheckFocused(element);
7270e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin
73337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett    final long downTime = Events.keyDown(injector, keyCode, metaState);
74337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett    Events.keyUp(injector, downTime, keyCode, metaState);
75cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le
76337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett    return true;
77cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le  }
7852b875da168081ca17d5532cebfbe78974ecce55Kevin Jin
79082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin  @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
8052b875da168081ca17d5532cebfbe78974ecce55Kevin Jin  @Override
8152b875da168081ca17d5532cebfbe78974ecce55Kevin Jin  public String toString() {
828d19bb634c670a49f7a58636a2a535c86b57d538Kevin Jin    String keyCodeString =
838d19bb634c670a49f7a58636a2a535c86b57d538Kevin Jin        Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1 ? String.valueOf(keyCode)
848d19bb634c670a49f7a58636a2a535c86b57d538Kevin Jin            : KeyEvent.keyCodeToString(keyCode);
85337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett    ToStringHelper toStringHelper = Strings.toStringHelper(this);
86337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett    if (metaState != 0) {
87337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett      toStringHelper.add("metaState", metaState);
88337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett    }
89337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett    return toStringHelper.addValue(keyCodeString).toString();
9052b875da168081ca17d5532cebfbe78974ecce55Kevin Jin  }
91cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le}
92