Input.java revision 797e4465fbc1f6a818e2905d17719e5df8c2a705
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.commands.input; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IWindowManager; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyCharacterMap; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent; 26797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brownimport android.view.MotionEvent; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Command that sends key events to the device, either by their keycode, or by 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * desired character output. 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Input { 34797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown private static final String TAG = "Input"; 35797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown 36797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown private IWindowManager mWindowManager; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Command-line entry point. 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param args The command-line arguments 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void main(String[] args) { 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (new Input()).run(args); 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 47797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown private IWindowManager getWindowManager() { 48797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown if (mWindowManager == null) { 49797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown mWindowManager = (IWindowManager.Stub.asInterface(ServiceManager.getService("window"))); 50797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } 51797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown return mWindowManager; 52797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } 53797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void run(String[] args) { 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (args.length < 1) { 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project showUsage(); 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String command = args[0]; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 62797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown try { 63797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown if (command.equals("text")) { 64797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown if (args.length == 2) { 65797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown sendText(args[1]); 66797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown return; 67797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } 68797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } else if (command.equals("keyevent")) { 69797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown if (args.length == 2) { 70797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown sendKeyEvent(Integer.parseInt(args[1])); 71797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown return; 72797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } 73797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } else if (command.equals("tap")) { 74797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown if (args.length == 3) { 75797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown sendTap(Float.parseFloat(args[1]), Float.parseFloat(args[2])); 76797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown return; 77797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } 78797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } else if (command.equals("swipe")) { 79797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown if (args.length == 5) { 80797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown sendSwipe(Float.parseFloat(args[1]), Float.parseFloat(args[2]), 81797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown Float.parseFloat(args[3]), Float.parseFloat(args[4])); 82797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown return; 83797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } 84797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } else { 85797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown System.err.println("Error: Unknown command: " + command); 86797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown showUsage(); 87797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown return; 88797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } 89797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } catch (NumberFormatException ex) { 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 91797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown System.err.println("Error: Invalid arguments for command: " + command); 92797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown showUsage(); 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Convert the characters of string text into key event's and send to 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * device. 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param text is a string of characters you want to input to the device. 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void sendText(String text) { 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuffer buff = new StringBuffer(text); 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean escapeFlag = false; 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<buff.length(); i++) { 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (escapeFlag) { 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project escapeFlag = false; 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (buff.charAt(i) == 's') { 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buff.setCharAt(i, ' '); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buff.deleteCharAt(--i); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (buff.charAt(i) == '%') { 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project escapeFlag = true; 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] chars = buff.toString().toCharArray(); 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 121797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); 122797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown KeyEvent[] events = kcm.getEvents(chars); 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for(int i = 0; i < events.length; i++) { 124797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown injectKeyEvent(events[i]); 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 128797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown private void sendKeyEvent(int keyCode) { 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = SystemClock.uptimeMillis(); 130797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0)); 131797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0)); 132797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } 133797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown 134797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown private void sendTap(float x, float y) { 135797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown long now = SystemClock.uptimeMillis(); 136797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, x, y, 0)); 137797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, x, y, 0)); 138797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } 139797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown 140797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown private void sendSwipe(float x1, float y1, float x2, float y2) { 141797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown final int NUM_STEPS = 11; 142797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown long now = SystemClock.uptimeMillis(); 143797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, x1, y1, 0)); 144797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown for (int i = 1; i < NUM_STEPS; i++) { 145797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown float alpha = (float)i / NUM_STEPS; 146797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_MOVE, 147797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown lerp(x1, x2, alpha), lerp(y1, y2, alpha), 0)); 148797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } 149797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, x2, y2, 0)); 150797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } 151797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown 152797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown private void injectKeyEvent(KeyEvent event) { 153797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown try { 154797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown Log.i(TAG, "InjectKeyEvent: " + event); 155797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown getWindowManager().injectKeyEvent(event, true); 156797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } catch (RemoteException ex) { 157797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown Log.i(TAG, "RemoteException", ex); 158797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } 159797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } 160797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown 161797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown private void injectPointerEvent(MotionEvent event) { 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 163797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown Log.i("Input", "InjectPointerEvent: " + event); 164797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown getWindowManager().injectPointerEvent(event, true); 165797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } catch (RemoteException ex) { 166797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown Log.i(TAG, "RemoteException", ex); 167797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown } finally { 168797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown event.recycle(); 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 172797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown private static final float lerp(float a, float b, float alpha) { 173797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown return (b - a) * alpha + a; 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void showUsage() { 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.err.println("usage: input [text|keyevent]"); 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.err.println(" input text <string>"); 179797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown System.err.println(" input keyevent <key code>"); 180797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown System.err.println(" input tap <x> <y>"); 181797e4465fbc1f6a818e2905d17719e5df8c2a705Jeff Brown System.err.println(" input swipe <x1> <y1> <x2> <y2>"); 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 184