Input.java revision 797e4465fbc1f6a818e2905d17719e5df8c2a705
1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.commands.input; 18 19import android.os.RemoteException; 20import android.os.ServiceManager; 21import android.os.SystemClock; 22import android.util.Log; 23import android.view.IWindowManager; 24import android.view.KeyCharacterMap; 25import android.view.KeyEvent; 26import android.view.MotionEvent; 27 28/** 29 * Command that sends key events to the device, either by their keycode, or by 30 * desired character output. 31 */ 32 33public class Input { 34 private static final String TAG = "Input"; 35 36 private IWindowManager mWindowManager; 37 38 /** 39 * Command-line entry point. 40 * 41 * @param args The command-line arguments 42 */ 43 public static void main(String[] args) { 44 (new Input()).run(args); 45 } 46 47 private IWindowManager getWindowManager() { 48 if (mWindowManager == null) { 49 mWindowManager = (IWindowManager.Stub.asInterface(ServiceManager.getService("window"))); 50 } 51 return mWindowManager; 52 } 53 54 private void run(String[] args) { 55 if (args.length < 1) { 56 showUsage(); 57 return; 58 } 59 60 String command = args[0]; 61 62 try { 63 if (command.equals("text")) { 64 if (args.length == 2) { 65 sendText(args[1]); 66 return; 67 } 68 } else if (command.equals("keyevent")) { 69 if (args.length == 2) { 70 sendKeyEvent(Integer.parseInt(args[1])); 71 return; 72 } 73 } else if (command.equals("tap")) { 74 if (args.length == 3) { 75 sendTap(Float.parseFloat(args[1]), Float.parseFloat(args[2])); 76 return; 77 } 78 } else if (command.equals("swipe")) { 79 if (args.length == 5) { 80 sendSwipe(Float.parseFloat(args[1]), Float.parseFloat(args[2]), 81 Float.parseFloat(args[3]), Float.parseFloat(args[4])); 82 return; 83 } 84 } else { 85 System.err.println("Error: Unknown command: " + command); 86 showUsage(); 87 return; 88 } 89 } catch (NumberFormatException ex) { 90 } 91 System.err.println("Error: Invalid arguments for command: " + command); 92 showUsage(); 93 } 94 95 /** 96 * Convert the characters of string text into key event's and send to 97 * device. 98 * 99 * @param text is a string of characters you want to input to the device. 100 */ 101 private void sendText(String text) { 102 103 StringBuffer buff = new StringBuffer(text); 104 105 boolean escapeFlag = false; 106 for (int i=0; i<buff.length(); i++) { 107 if (escapeFlag) { 108 escapeFlag = false; 109 if (buff.charAt(i) == 's') { 110 buff.setCharAt(i, ' '); 111 buff.deleteCharAt(--i); 112 } 113 } 114 if (buff.charAt(i) == '%') { 115 escapeFlag = true; 116 } 117 } 118 119 char[] chars = buff.toString().toCharArray(); 120 121 KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); 122 KeyEvent[] events = kcm.getEvents(chars); 123 for(int i = 0; i < events.length; i++) { 124 injectKeyEvent(events[i]); 125 } 126 } 127 128 private void sendKeyEvent(int keyCode) { 129 long now = SystemClock.uptimeMillis(); 130 injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0)); 131 injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0)); 132 } 133 134 private void sendTap(float x, float y) { 135 long now = SystemClock.uptimeMillis(); 136 injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, x, y, 0)); 137 injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, x, y, 0)); 138 } 139 140 private void sendSwipe(float x1, float y1, float x2, float y2) { 141 final int NUM_STEPS = 11; 142 long now = SystemClock.uptimeMillis(); 143 injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, x1, y1, 0)); 144 for (int i = 1; i < NUM_STEPS; i++) { 145 float alpha = (float)i / NUM_STEPS; 146 injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_MOVE, 147 lerp(x1, x2, alpha), lerp(y1, y2, alpha), 0)); 148 } 149 injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, x2, y2, 0)); 150 } 151 152 private void injectKeyEvent(KeyEvent event) { 153 try { 154 Log.i(TAG, "InjectKeyEvent: " + event); 155 getWindowManager().injectKeyEvent(event, true); 156 } catch (RemoteException ex) { 157 Log.i(TAG, "RemoteException", ex); 158 } 159 } 160 161 private void injectPointerEvent(MotionEvent event) { 162 try { 163 Log.i("Input", "InjectPointerEvent: " + event); 164 getWindowManager().injectPointerEvent(event, true); 165 } catch (RemoteException ex) { 166 Log.i(TAG, "RemoteException", ex); 167 } finally { 168 event.recycle(); 169 } 170 } 171 172 private static final float lerp(float a, float b, float alpha) { 173 return (b - a) * alpha + a; 174 } 175 176 private void showUsage() { 177 System.err.println("usage: input [text|keyevent]"); 178 System.err.println(" input text <string>"); 179 System.err.println(" input keyevent <key code>"); 180 System.err.println(" input tap <x> <y>"); 181 System.err.println(" input swipe <x1> <y1> <x2> <y2>"); 182 } 183} 184