OSDN Git Service

Add "type" command to allow strings to be more easily typed.
[android-x86/development.git] / cmds / monkey / src / com / android / commands / monkey / MonkeySourceNetwork.java
index b444dd3..5937f09 100644 (file)
@@ -21,6 +21,7 @@ import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.util.Log;
+import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 
@@ -36,7 +37,9 @@ import java.net.Socket;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Queue;
 import java.util.StringTokenizer;
 
 /**
@@ -47,7 +50,7 @@ public class MonkeySourceNetwork implements MonkeyEventSource {
     private static final String TAG = "MonkeyStub";
 
     private interface MonkeyCommand {
-        MonkeyEvent translateCommand(List<String> command);
+        MonkeyEvent translateCommand(List<String> command, CommandQueue queue);
     }
 
     /**
@@ -56,7 +59,8 @@ public class MonkeySourceNetwork implements MonkeyEventSource {
     private static class FlipCommand implements MonkeyCommand {
         // flip open
         // flip closed
-        public MonkeyEvent translateCommand(List<String> command) {
+        public MonkeyEvent translateCommand(List<String> command,
+                                            CommandQueue queue) {
             if (command.size() > 1) {
                 String direction = command.get(1);
                 if ("open".equals(direction)) {
@@ -77,7 +81,8 @@ public class MonkeySourceNetwork implements MonkeyEventSource {
         // touch down 120 120
         // touch move 140 140
         // touch up 140 140
-        public MonkeyEvent translateCommand(List<String> command) {
+        public MonkeyEvent translateCommand(List<String> command,
+                                            CommandQueue queue) {
             if (command.size() == 4) {
                 String actionName = command.get(1);
                 int x = 0;
@@ -120,7 +125,8 @@ public class MonkeySourceNetwork implements MonkeyEventSource {
         // trackball [dx] [dy]
         // trackball 1 0 -- move right
         // trackball -1 0 -- move left
-        public MonkeyEvent translateCommand(List<String> command) {
+        public MonkeyEvent translateCommand(List<String> command,
+                                            CommandQueue queue) {
             if (command.size() == 3) {
                 int dx = 0;
                 int dy = 0;
@@ -147,29 +153,14 @@ public class MonkeySourceNetwork implements MonkeyEventSource {
         // key [down|up] [keycode]
         // key down 82
         // key up 82
-        public MonkeyEvent translateCommand(List<String> command) {
+        public MonkeyEvent translateCommand(List<String> command,
+                                            CommandQueue queue) {
             if (command.size() == 3) {
-                int keyCode = -1;
-                String keyName = command.get(2);
-                try {
-                    keyCode = Integer.parseInt(keyName);
-                } catch (NumberFormatException e) {
-                    // Ok, it wasn't a number, see if we have a
-                    // keycode name for it
-                    keyCode = MonkeySourceRandom.getKeyCode(keyName);
-                    if (keyCode == -1) {
-                        // OK, one last ditch effort to find a match.
-                        // Build the KEYCODE_STRING from the string
-                        // we've been given and see if that key
-                        // exists.  This would allow you to do "key
-                        // down menu", for example.
-                        keyCode = MonkeySourceRandom.getKeyCode("KEYCODE_" + keyName.toUpperCase());
-                        if (keyCode == -1) {
-                            // Ok, you gave us something bad.
-                            Log.e(TAG, "Can't find keyname: " + keyName);
-                            return null;
-                        }
-                    }
+                int keyCode = getKeyCode(command.get(2));
+                if (keyCode < 0) {
+                    // Ok, you gave us something bad.
+                    Log.e(TAG, "Can't find keyname: " + command.get(2));
+                    return null;
                 }
                 Log.d(TAG, "keycode: " + keyCode);
                 int action = -1;
@@ -189,18 +180,45 @@ public class MonkeySourceNetwork implements MonkeyEventSource {
     }
 
     /**
+     * Get an integer keycode value from a given keyname.
+     *
+     * @param keyName the key name to get the code for
+     * @returns the integer keycode value, or -1 on error.
+     */
+    private static int getKeyCode(String keyName) {
+        int keyCode = -1;
+        try {
+            keyCode = Integer.parseInt(keyName);
+        } catch (NumberFormatException e) {
+            // Ok, it wasn't a number, see if we have a
+            // keycode name for it
+            keyCode = MonkeySourceRandom.getKeyCode(keyName);
+            if (keyCode == -1) {
+                // OK, one last ditch effort to find a match.
+                // Build the KEYCODE_STRING from the string
+                // we've been given and see if that key
+                // exists.  This would allow you to do "key
+                // down menu", for example.
+                keyCode = MonkeySourceRandom.getKeyCode("KEYCODE_" + keyName.toUpperCase());
+            }
+        }
+        return keyCode;
+    }
+
+    /**
      * Command to put the Monkey to sleep.
      */
     private static class SleepCommand implements MonkeyCommand {
         // sleep 2000
-        public MonkeyEvent translateCommand(List<String> command) {
+        public MonkeyEvent translateCommand(List<String> command,
+                                            CommandQueue queue) {
             if (command.size() == 2) {
                 int sleep = -1;
                 String sleepStr = command.get(1);
                 try {
                     sleep = Integer.parseInt(sleepStr);
                 } catch (NumberFormatException e) {
-                    Log.e(TAG, "Not a number: " + sleepStr, e);
+                  Log.e(TAG, "Not a number: " + sleepStr, e);
                 }
                 return new MonkeyThrottleEvent(sleep);
             }
@@ -209,12 +227,41 @@ public class MonkeySourceNetwork implements MonkeyEventSource {
     }
 
     /**
+     * Command to type a string
+     */
+    private static class TypeCommand implements MonkeyCommand {
+        // wake
+        public MonkeyEvent translateCommand(List<String> command,
+                                            CommandQueue queue) {
+            if (command.size() == 2) {
+                String str = command.get(1);
+
+                char[] chars = str.toString().toCharArray();
+
+                // Convert the string to an array of KeyEvent's for
+                // the built in keymap.
+                KeyCharacterMap keyCharacterMap = KeyCharacterMap.
+                        load(KeyCharacterMap.BUILT_IN_KEYBOARD);
+                KeyEvent[] events = keyCharacterMap.getEvents(chars);
+
+                // enqueue all the events we just got.
+                for (KeyEvent event : events) {
+                    queue.enqueueEvent(new MonkeyKeyEvent(event));
+                }
+                return new MonkeyNoopEvent();
+            }
+            return null;
+        }
+    }
+
+    /**
      * Command to wake the device up
      */
     private static class WakeCommand implements MonkeyCommand {
         // wake
-        public MonkeyEvent translateCommand(List<String> command) {
-            if (wake()) {
+        public MonkeyEvent translateCommand(List<String> command,
+                                            CommandQueue queue) {
+            if (!wake()) {
                 return null;
             }
             return new MonkeyNoopEvent();
@@ -222,6 +269,62 @@ public class MonkeySourceNetwork implements MonkeyEventSource {
     }
 
     /**
+     * Command to "tap" at a location (Sends a down and up touch
+     * event).
+     */
+    private static class TapCommand implements MonkeyCommand {
+        // tap x y
+        public MonkeyEvent translateCommand(List<String> command,
+                                            CommandQueue queue) {
+            if (command.size() == 3) {
+                int x = 0;
+                int y = 0;
+                try {
+                    x = Integer.parseInt(command.get(1));
+                    y = Integer.parseInt(command.get(2));
+                } catch (NumberFormatException e) {
+                    // Ok, it wasn't a number
+                    Log.e(TAG, "Got something that wasn't a number", e);
+                    return null;
+                }
+
+                queue.enqueueEvent(new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER,
+                                                         -1, MotionEvent.ACTION_DOWN,
+                                                         x, y, 0));
+                queue.enqueueEvent(new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER,
+                                                         -1, MotionEvent.ACTION_UP,
+                                                         x, y, 0));
+                return new MonkeyNoopEvent();
+            }
+            return null;
+        }
+    }
+
+    /**
+     * Command to "press" a buttons (Sends an up and down key event.)
+     */
+    private static class PressCommand implements MonkeyCommand {
+        // press keycode
+        public MonkeyEvent translateCommand(List<String> command,
+                                            CommandQueue queue) {
+            if (command.size() == 2) {
+                int keyCode = getKeyCode(command.get(1));
+                if (keyCode < 0) {
+                    // Ok, you gave us something bad.
+                    Log.e(TAG, "Can't find keyname: " + command.get(1));
+                    return null;
+                }
+
+                queue.enqueueEvent(new MonkeyKeyEvent(KeyEvent.ACTION_DOWN, keyCode));
+                queue.enqueueEvent(new MonkeyKeyEvent(KeyEvent.ACTION_UP, keyCode));
+                return new MonkeyNoopEvent();
+
+            }
+            return null;
+        }
+    }
+
+    /**
      * Force the device to wake up.
      *
      * @return true if woken up OK.
@@ -249,6 +352,9 @@ public class MonkeySourceNetwork implements MonkeyEventSource {
         COMMAND_MAP.put("key", new KeyCommand());
         COMMAND_MAP.put("sleep", new SleepCommand());
         COMMAND_MAP.put("wake", new WakeCommand());
+        COMMAND_MAP.put("tap", new TapCommand());
+        COMMAND_MAP.put("press", new PressCommand());
+        COMMAND_MAP.put("type", new TypeCommand());
     }
 
     // QUIT command
@@ -258,6 +364,39 @@ public class MonkeySourceNetwork implements MonkeyEventSource {
     private static final String OK = "OK";
     private static final String ERROR = "ERROR";
 
+    private static interface CommandQueue {
+        /**
+         * Enqueue an event to be returned later.  This allows a
+         * command to return multiple events.  Commands using the
+         * command queue still have to return a valid event from their
+         * translateCommand method.  The returned command will be
+         * executed before anything put into the queue.
+         *
+         * @param e the event to be enqueued.
+         */
+        public void enqueueEvent(MonkeyEvent e);
+    };
+
+    // Queue of Events to be processed.  This allows commands to push
+    // multiple events into the queue to be processed.
+    private static class CommandQueueImpl implements CommandQueue{
+        private final Queue<MonkeyEvent> queuedEvents = new LinkedList<MonkeyEvent>();
+
+        public void enqueueEvent(MonkeyEvent e) {
+            queuedEvents.offer(e);
+        }
+
+        /**
+         * Get the next queued event to excecute.
+         *
+         * @returns the next event, or null if there aren't any more.
+         */
+        public MonkeyEvent getNextQueuedEvent() {
+            return queuedEvents.poll();
+        }
+    };
+
+    private final CommandQueueImpl commandQueue = new CommandQueueImpl();
 
     private final int port;
     private BufferedReader input;
@@ -292,6 +431,17 @@ public class MonkeySourceNetwork implements MonkeyEventSource {
     }
 
     /**
+     * Helper function for commandLineSplit that replaces quoted
+     * charaters with their real values.
+     *
+     * @param input the string to do replacement on.
+     * @returns the results with the characters replaced.
+     */
+    private static String replaceQuotedChars(String input) {
+        return input.replace("\\\"", "\"");
+    }
+
+    /**
      * This function splits the given line into String parts.  It obey's quoted
      * strings and returns them as a single part.
      *
@@ -311,22 +461,22 @@ public class MonkeySourceNetwork implements MonkeyEventSource {
             String cur = tok.nextToken();
             if (!insideQuote && cur.startsWith("\"")) {
                 // begin quote
-                quotedWord.append(cur);
+                quotedWord.append(replaceQuotedChars(cur));
                 insideQuote = true;
             } else if (insideQuote) {
                 // end quote
                 if (cur.endsWith("\"")) {
                     insideQuote = false;
-                    quotedWord.append(cur);
+                    quotedWord.append(" ").append(replaceQuotedChars(cur));
                     String word = quotedWord.toString();
 
                     // trim off the quotes
                     result.add(word.substring(1, word.length() - 1));
                 } else {
-                    quotedWord.append(cur);
+                    quotedWord.append(" ").append(replaceQuotedChars(cur));
                 }
             } else {
-                result.add(cur);
+                result.add(replaceQuotedChars(cur));
             }
         }
         return result;
@@ -345,7 +495,8 @@ public class MonkeySourceNetwork implements MonkeyEventSource {
         if (parts.size() > 0) {
             MonkeyCommand command = COMMAND_MAP.get(parts.get(0));
             if (command != null) {
-                return command.translateCommand(parts);
+                return command.translateCommand(parts,
+                                                commandQueue);
             }
             return null;
         }
@@ -366,6 +517,15 @@ public class MonkeySourceNetwork implements MonkeyEventSource {
         // Now, get the next command.  This call may block, but that's OK
         try {
             while (true) {
+                // Check to see if we have any events queued up.  If
+                // we do, use those until we have no more.  Then get
+                // more input from the user.
+                MonkeyEvent queuedEvent = commandQueue.getNextQueuedEvent();
+                if (queuedEvent != null) {
+                    // dispatch the event
+                    return queuedEvent;
+                }
+
                 String command = input.readLine();
                 if (command == null) {
                     Log.d(TAG, "Connection dropped.");