merge from donut

This commit is contained in:
Jean-Baptiste Queru
2009-09-03 14:12:47 -07:00
396 changed files with 11025 additions and 2267 deletions

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"Záloha"</string>
<string name="title">"Akce není podporována"</string>
<string name="error">"Tato akce není momentálně podporována."</string>
<string name="appTitle" msgid="161410001913116606">"Záloha"</string>
<string name="title" msgid="8156274565006125136">"Akce není podporována"</string>
<string name="error" msgid="6539615832923362301">"Tato akce není momentálně podporována."</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"Reserve"</string>
<string name="title">"Ikke understøttet handling"</string>
<string name="error">"Handlingen er ikke understøttet i øjeblikket."</string>
<string name="appTitle" msgid="161410001913116606">"Reserve"</string>
<string name="title" msgid="8156274565006125136">"Ikke understøttet handling"</string>
<string name="error" msgid="6539615832923362301">"Handlingen er ikke understøttet i øjeblikket."</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"Fallback"</string>
<string name="title">"Nicht unterstützte Aktion"</string>
<string name="error">"Diese Aktion wird zurzeit nicht unterstützt."</string>
<string name="appTitle" msgid="161410001913116606">"Fallback"</string>
<string name="title" msgid="8156274565006125136">"Nicht unterstützte Aktion"</string>
<string name="error" msgid="6539615832923362301">"Diese Aktion wird zurzeit nicht unterstützt."</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"Εναλλακτική"</string>
<string name="title">"Ενέργεια που δεν υποστηρίζεται"</string>
<string name="error">"Αυτή η ενέργεια δεν υποστηρίζεται αυτήν τη στιγμή."</string>
<string name="appTitle" msgid="161410001913116606">"Εναλλακτική"</string>
<string name="title" msgid="8156274565006125136">"Ενέργεια που δεν υποστηρίζεται"</string>
<string name="error" msgid="6539615832923362301">"Αυτή η ενέργεια δεν υποστηρίζεται αυτήν τη στιγμή."</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"Fallback"</string>
<string name="title">"Acción no admitida"</string>
<string name="error">"Esa acción no se admite actualmente."</string>
<string name="appTitle" msgid="161410001913116606">"Fallback"</string>
<string name="title" msgid="8156274565006125136">"Acción no admitida"</string>
<string name="error" msgid="6539615832923362301">"Esa acción no se admite actualmente."</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"Fallback"</string>
<string name="title">"Acción no admitida"</string>
<string name="error">"Esa acción no se admite actualmente."</string>
<string name="appTitle" msgid="161410001913116606">"Fallback"</string>
<string name="title" msgid="8156274565006125136">"Acción no admitida"</string>
<string name="error" msgid="6539615832923362301">"Esa acción no se admite actualmente."</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"Application de secours"</string>
<string name="title">"Action non prise en charge"</string>
<string name="error">"Cette action n\'est actuellement pas prise en charge."</string>
<string name="appTitle" msgid="161410001913116606">"Application de secours"</string>
<string name="title" msgid="8156274565006125136">"Action non prise en charge"</string>
<string name="error" msgid="6539615832923362301">"Cette action n\'est actuellement pas prise en charge."</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"Fallback"</string>
<string name="title">"Azione non supportata"</string>
<string name="error">"L\'azione non è al momento supportata."</string>
<string name="appTitle" msgid="161410001913116606">"Fallback"</string>
<string name="title" msgid="8156274565006125136">"Azione non supportata"</string>
<string name="error" msgid="6539615832923362301">"L\'azione non è al momento supportata."</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"Fallback"</string>
<string name="title">"サポートされていない操作"</string>
<string name="error">"現在サポートされていない操作です。"</string>
<string name="appTitle" msgid="161410001913116606">"Fallback"</string>
<string name="title" msgid="8156274565006125136">"サポートされていない操作"</string>
<string name="error" msgid="6539615832923362301">"現在サポートされていない操作です。"</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"폴백"</string>
<string name="title">"지원되지 않는 작업"</string>
<string name="error">"이 작업은 현재 지원되지 않습니다."</string>
<string name="appTitle" msgid="161410001913116606">"폴백"</string>
<string name="title" msgid="8156274565006125136">"지원되지 않는 작업"</string>
<string name="error" msgid="6539615832923362301">"이 작업은 현재 지원되지 않습니다."</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"Fallback"</string>
<string name="title">"Ustøttet handling"</string>
<string name="error">"Denne handlingen er ikke støttet nå."</string>
<string name="appTitle" msgid="161410001913116606">"Fallback"</string>
<string name="title" msgid="8156274565006125136">"Ustøttet handling"</string>
<string name="error" msgid="6539615832923362301">"Denne handlingen er ikke støttet nå."</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"Reserve"</string>
<string name="title">"Niet-ondersteunde actie"</string>
<string name="error">"Die actie wordt momenteel niet ondersteund."</string>
<string name="appTitle" msgid="161410001913116606">"Reserve"</string>
<string name="title" msgid="8156274565006125136">"Niet-ondersteunde actie"</string>
<string name="error" msgid="6539615832923362301">"Die actie wordt momenteel niet ondersteund."</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"Wycofanie"</string>
<string name="title">"Nieobsługiwana czynność"</string>
<string name="error">"Ta czynność nie jest aktualnie obsługiwana."</string>
<string name="appTitle" msgid="161410001913116606">"Wycofanie"</string>
<string name="title" msgid="8156274565006125136">"Nieobsługiwana czynność"</string>
<string name="error" msgid="6539615832923362301">"Ta czynność nie jest aktualnie obsługiwana."</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"Fallback"</string>
<string name="title">"Acção não suportada"</string>
<string name="error">"Esta·acção·ainda·não·é·suportada."</string>
<string name="appTitle" msgid="161410001913116606">"Fallback"</string>
<string name="title" msgid="8156274565006125136">"Acção não suportada"</string>
<string name="error" msgid="6539615832923362301">"Esta acção ainda não é suportada."</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"Fallback"</string>
<string name="title">"Ação não suportada"</string>
<string name="error">"Essa ação não é suportada no momento."</string>
<string name="appTitle" msgid="161410001913116606">"Fallback"</string>
<string name="title" msgid="8156274565006125136">"Ação não suportada"</string>
<string name="error" msgid="6539615832923362301">"Essa ação não é suportada no momento."</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"Переход в обходной режим"</string>
<string name="title">"Неподдерживаемое действие"</string>
<string name="error">"В настоящее время это действие не поддерживается."</string>
<string name="appTitle" msgid="161410001913116606">"Переход в обходной режим"</string>
<string name="title" msgid="8156274565006125136">"Неподдерживаемое действие"</string>
<string name="error" msgid="6539615832923362301">"В настоящее время это действие не поддерживается."</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"Reserv"</string>
<string name="title">"Åtgärden stöds inte"</string>
<string name="error">"Den här åtgärden stöds inte för närvarande."</string>
<string name="appTitle" msgid="161410001913116606">"Reserv"</string>
<string name="title" msgid="8156274565006125136">"Åtgärden stöds inte"</string>
<string name="error" msgid="6539615832923362301">"Den här åtgärden stöds inte för närvarande."</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"Fallback"</string>
<string name="title">"Desteklenmeyen işlem"</string>
<string name="error">"Bu işlem şu an desteklenmiyor."</string>
<string name="appTitle" msgid="161410001913116606">"Fallback"</string>
<string name="title" msgid="8156274565006125136">"Desteklenmeyen işlem"</string>
<string name="error" msgid="6539615832923362301">"Bu işlem şu an desteklenmiyor."</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"后备"</string>
<string name="title">"不支持此操作"</string>
<string name="error">"目前不支持该操作。"</string>
<string name="appTitle" msgid="161410001913116606">"后备"</string>
<string name="title" msgid="8156274565006125136">"不支持此操作"</string>
<string name="error" msgid="6539615832923362301">"目前不支持该操作。"</string>
</resources>

View File

@@ -15,7 +15,7 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="appTitle">"備用"</string>
<string name="title">"不支援的操作"</string>
<string name="error">"目前不支援此操作。"</string>
<string name="appTitle" msgid="161410001913116606">"備用"</string>
<string name="title" msgid="8156274565006125136">"不支援的操作"</string>
<string name="error" msgid="6539615832923362301">"目前不支援此操作。"</string>
</resources>

View File

@@ -31,6 +31,7 @@ bin/sqlite3 tools/sqlite3
bin/dmtracedump tools/dmtracedump
bin/hprof-conv tools/hprof-conv
bin/mksdcard tools/mksdcard
bin/zipalign tools/zipalign
# the uper-jar file that apps link against
out/target/common/obj/PACKAGING/android_jar_intermediates/android.jar platforms/${PLATFORM_NAME}/android.jar
@@ -39,7 +40,7 @@ out/target/common/obj/PACKAGING/android_jar_intermediates/android.jar platforms/
framework/org.eclipse.core.commands_3.4.0.I20080509-2000.jar tools/lib/org.eclipse.core.commands_3.4.0.I20080509-2000.jar
framework/org.eclipse.equinox.common_3.4.0.v20080421-2006.jar tools/lib/org.eclipse.equinox.common_3.4.0.v20080421-2006.jar
framework/org.eclipse.jface_3.4.2.M20090107-0800.jar tools/lib/org.eclipse.jface_3.4.2.M20090107-0800.jar
framework/osgi.jar tools/lib/osgi.jar
sdk/sdk-build.prop platforms/${PLATFORM_NAME}/build.prop
development/tools/scripts/plugin.prop tools/lib/plugin.prop
@@ -49,7 +50,6 @@ obj/framework.aidl platforms/${PLATFORM_NAME}/framework.aidl
# sdk scripts
development/tools/scripts/AndroidManifest.template platforms/${PLATFORM_NAME}/templates/AndroidManifest.template
development/tools/scripts/AndroidManifest.alias.template platforms/${PLATFORM_NAME}/templates/AndroidManifest.alias.template
development/tools/scripts/AndroidManifest.tests.template platforms/${PLATFORM_NAME}/templates/AndroidManifest.tests.template
development/tools/scripts/iml.template platforms/${PLATFORM_NAME}/templates/iml.template
development/tools/scripts/ipr.template platforms/${PLATFORM_NAME}/templates/ipr.template
@@ -58,11 +58,8 @@ development/tools/scripts/java_file.template platforms/${PLATFORM_NAME}/template
development/tools/scripts/java_tests_file.template platforms/${PLATFORM_NAME}/templates/java_tests_file.template
development/tools/scripts/layout.template platforms/${PLATFORM_NAME}/templates/layout.template
development/tools/scripts/strings.template platforms/${PLATFORM_NAME}/templates/strings.template
development/tools/scripts/alias.template platforms/${PLATFORM_NAME}/templates/alias.template
development/tools/scripts/android_rules.xml platforms/${PLATFORM_NAME}/templates/android_rules.xml
development/tools/scripts/alias_rules.xml platforms/${PLATFORM_NAME}/templates/alias_rules.xml
development/tools/scripts/build.template tools/lib/build.template
development/tools/scripts/build.alias.template tools/lib/build.alias.template
# emacs support
development/tools/scripts/android.el tools/lib/android.el
@@ -78,6 +75,7 @@ development/samples/SkeletonApp platforms/${PLATFORM_NAME}/samples/SkeletonApp
development/samples/Snake platforms/${PLATFORM_NAME}/samples/Snake
development/samples/SoftKeyboard platforms/${PLATFORM_NAME}/samples/SoftKeyboard
development/samples/JetBoy platforms/${PLATFORM_NAME}/samples/JetBoy
development/samples/SearchableDictionary platforms/${PLATFORM_NAME}/samples/SearchableDictionary
# dx
bin/dx platforms/${PLATFORM_NAME}/tools/dx
@@ -146,9 +144,10 @@ prebuilt/android-arm/kernel/kernel-qemu platforms/${PLATFORM_NAME}/images/kernel
external/qemu/android/avd/hardware-properties.ini tools/lib/hardware-properties.ini
# emulator skins
development/emulator/skins/HVGA platforms/${PLATFORM_NAME}/skins/HVGA
development/emulator/skins/QVGA platforms/${PLATFORM_NAME}/skins/QVGA
development/emulator/skins/WVGA platforms/${PLATFORM_NAME}/skins/WVGA
development/emulator/skins/HVGA platforms/${PLATFORM_NAME}/skins/HVGA
development/emulator/skins/QVGA platforms/${PLATFORM_NAME}/skins/QVGA
development/emulator/skins/WVGA800 platforms/${PLATFORM_NAME}/skins/WVGA800
development/emulator/skins/WVGA854 platforms/${PLATFORM_NAME}/skins/WVGA854
# NOTICE files are copied by build/core/Makefile
development/tools/scripts/sdk_files_NOTICE.txt platforms/${PLATFORM_NAME}/templates/NOTICE.txt

View File

@@ -25,25 +25,26 @@ DIST_DIR="$2"
TEMP_DIR="$3"
[ -z "$TEMP_DIR" ] && TEMP_DIR=${TMP:-/tmp}
function die() {
echo "Error:" $*
echo "Aborting"
exit 1
echo "Error:" $*
echo "Aborting"
exit 1
}
function usage() {
echo "Usage: ${PROG_NAME} linux_or_mac_sdk.zip output_dir [temp_dir]"
echo "If temp_dir is not given, \$TMP is used. If that's missing, /tmp is used."
status
exit 2
local NAME
NAME=`basename ${PROG_NAME}`
echo "Usage: ${NAME} linux_or_mac_sdk.zip output_dir [temp_dir]"
echo "If temp_dir is not given, \$TMP is used. If that's missing, /tmp is used."
status
exit 2
}
function status() {
echo "Current values:"
echo "- Input SDK: ${SDK_ZIP:-missing}"
echo "- Output dir: ${DIST_DIR:-missing}"
echo "- Temp dir: ${TEMP_DIR:-missing}"
echo "Current values:"
echo "- Input SDK: ${SDK_ZIP:-missing}"
echo "- Output dir: ${DIST_DIR:-missing}"
echo "- Temp dir: ${TEMP_DIR:-missing}"
}
function check() {
@@ -92,7 +93,14 @@ function build() {
make -j 4 emulator || die "Build failed"
# Disable parallel build: it generates "permission denied" issues when
# multiple "ar.exe" are running in parallel.
make prebuilt adb fastboot aidl aapt dexdump dmtracedump hprof-conv mksdcard sqlite3 \
make aapt adb aidl \
prebuilt \
dexdump dmtracedump \
fastboot \
hprof-conv \
mksdcard \
sqlite3 \
zipalign \
|| die "Build failed"
}
@@ -124,12 +132,16 @@ function package() {
"Instead found " $THE_PLATFORM
[[ -d "$PLATFORM_TOOLS" ]] || die "Missing folder $PLATFORM_TOOLS."
# Package USB Driver
if type package_usb_driver 2>&1 | grep -q function ; then
package_usb_driver $TEMP_SDK_DIR
fi
# Remove obsolete stuff from tools & platform
TOOLS="$TEMP_SDK_DIR/tools"
LIB="$TEMP_SDK_DIR/tools/lib"
rm -v "$TOOLS"/{adb,android,apkbuilder,ddms,dmtracedump,draw9patch,emulator}
rm -v "$TOOLS"/{hierarchyviewer,hprof-conv,mksdcard,sqlite3,traceview}
rm -v "$TOOLS"/{hierarchyviewer,hprof-conv,mksdcard,sqlite3,traceview,zipalign}
rm -v "$LIB"/*/swt.jar
rm -v "$PLATFORM_TOOLS"/{aapt,aidl,dx,dexdump}
@@ -183,8 +195,9 @@ function package() {
# Copy or move platform specific tools to the default platform.
cp -v dalvik/dx/etc/dx.bat "$PLATFORM_TOOLS"/
# Note: mgwz.dll must be in same folder than aapt.exe
mv -v "$TOOLS"/{aapt.exe,aidl.exe,dexdump.exe,mgwz.dll} "$PLATFORM_TOOLS"/
mv -v "$TOOLS"/{aapt.exe,aidl.exe,dexdump.exe} "$PLATFORM_TOOLS"/
# Note: mgwz.dll must be both in SDK/tools for zipalign and in SDK/platform/XYZ/tools/ for aapt
cp -v "$TOOLS"/mgwz.dll "$PLATFORM_TOOLS"/
# Fix EOL chars to make window users happy - fix all files at the top level only
# as well as all batch files including those in platforms/<name>/tools/
@@ -200,14 +213,14 @@ function package() {
# Now move the final zip from the temp dest to the final dist dir
mv -v "$TEMP_DIR/$DEST_NAME_ZIP" "$DIST_DIR/$DEST_NAME_ZIP"
# We want fastboot and adb (and its DLLs) next to the new SDK
for i in fastboot.exe adb.exe AdbWinApi.dll AdbWinUsbApi.dll; do
cp -vf out/host/windows-x86/bin/$i "$DIST_DIR"/$i
done
echo "Done"
echo
echo "Resulting SDK is in $DIST_DIR/$DEST_NAME_ZIP"
# We want fastboot and adb next to the new SDK
for i in fastboot.exe adb.exe AdbWinApi.dll; do
mv -vf out/host/windows-x86/bin/$i "$DIST_DIR"/$i
done
}
check

View File

@@ -7,6 +7,7 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_MODULE := monkey
include $(BUILD_JAVA_LIBRARY)
################################################################
include $(CLEAR_VARS)
ALL_PREBUILT += $(TARGET_OUT)/bin/monkey
$(TARGET_OUT)/bin/monkey : $(LOCAL_PATH)/monkey | $(ACP)

View File

@@ -0,0 +1,129 @@
SIMPLE PROTOCOL FOR AUTOMATED NETWORK CONTROL
The Simple Protocol for Automated Network Control was designed to be a
low-level way to programmability inject KeyEvents and MotionEvents
into the input system. The idea is that a process will run on a host
computer that will support higher-level operations (like conditionals,
etc.) and will talk (via TCP over ADB) to the device in Simple
Protocol for Automated Network Control. For security reasons, the
Monkey only binds to localhost, so you will need to use adb to setup
port forwarding to actually talk to the device.
INITIAL SETUP
Setup port forwarding from a local port on your machine to a port on
the device:
$ adb forward tcp:1080 tcp:1080
Start the monkey server
$ adb shell monkey --port 1080
Now you're ready to run commands
COMMAND LIST
Individual commands are separated by newlines. The Monkey will
respond to every command with a line starting with OK for commands
that executed without a problem, or a line starting with ERROR for
commands that had problems being run. For commands that return a
value, that value is returned on the same line as the OK or ERROR
response. The value is everything after (but not include) the colon
on that line. For ERROR values, this could be a message indicating
what happened. A possible example:
key down menu
OK
touch monkey
ERROR: monkey not a number
getvar sdk
OK: donut
getvar foo
ERROR: no such var
The complete list of commands follows:
key [down|up] keycode
This command injects KeyEvent's into the input system. The keycode
parameter refers to the KEYCODE list in the KeyEvent class
(http://developer.android.com/reference/android/view/KeyEvent.html).
The format of that parameter is quite flexible. Using the menu key as
an example, it can be 82 (the integer value of the keycode),
KEYCODE_MENU (the name of the keycode), or just menu (and the Monkey
will add the KEYCODE part). Do note that this last part doesn't work
for things like KEYCODE_1 for obvious reasons.
Note that sending a full button press requires sending both the down
and the up event for that key
touch [down|up|move] x y
This command injects a MotionEvent into the input system that
simulates a user touching the touchscreen (or a pointer event). x and
y specify coordinates on the display (0 0 being the upper left) for
the touch event to happen. Just like key events, touch events at a
single location require both a down and an up. To simulate dragging,
send a "touch down", then a series of "touch move" events (to simulate
the drag), followed by a "touch up" at the final location.
trackball dx dy
This command injects a MotionEvent into the input system that
simulates a user using the trackball. dx and dy indicates the amount
of change in the trackball location (as opposed to exact coordinates
that the touch events use)
flip [open|close]
This simulates the opening or closing the keyboard (like on dream).
wake
This command will wake the device up from sleep and allow user input.
tap x y
The tap command is a shortcut for the touch command. It will
automatically send both the up and the down event.
press keycode
The press command is a shortcut for the key command. The keycode
paramter works just like the key command and will automatically send
both the up and the down event.
type string
This command will simulate a user typing the given string on the
keyboard by generating the proper KeyEvents.
listvar
This command lists all the vars that the monkey knows about. They are
returned as a whitespace separated list.
getvar varname
This command returns the value of the given var. listvar can be used
to find out what vars are supported.
quit
Fully quit the monkey and accept no new sessions.
done
Close the current session and allow a new session to connect
OTHER NOTES
There are some convenience features added to allow running without
needing a host process.
Lines starting with a # character are considered comments. The Monkey
eats them and returns no indication that it did anything (no ERROR and
no OK).
You can put the Monkey to sleep by using the "sleep" command with a
single argument, how many ms to sleep.

View File

@@ -0,0 +1,57 @@
# Touch the android
touch down 160 200
touch up 160 200
sleep 1000
# Hit Next
touch down 300 450
touch up 300 450
sleep 1000
# Hit Next
touch down 300 450
touch up 300 450
sleep 1000
# Hit Next
touch down 300 450
touch up 300 450
sleep 1000
# Go down and select the account username
key down dpad_down
key up dpad_down
key down dpad_down
key up dpad_down
key down dpad_center
key up dpad_center
# account name: bill
key down b
key up b
key down i
key up i
key down l
key up l
key down l
key up l
# Go down to the password field
key down dpad_down
key up dpad_down
# password: bill
key down b
key up b
key down i
key up i
key down l
key up l
key down l
key up l
# Select next
touch down 300 450
touch up 300 450
# quit
quit

View File

@@ -47,10 +47,10 @@ import java.util.List;
* Application that injects random key events and other actions into the system.
*/
public class Monkey {
/**
* Monkey Debugging/Dev Support
*
*
* All values should be zero when checking in.
*/
private final static int DEBUG_ALLOW_ANY_STARTS = 0;
@@ -74,20 +74,20 @@ public class Monkey {
/** Ignore any not responding timeouts while running? */
private boolean mIgnoreTimeouts;
/** Ignore security exceptions when launching activities */
/** (The activity launch still fails, but we keep pluggin' away) */
private boolean mIgnoreSecurityExceptions;
/** Monitor /data/tombstones and stop the monkey if new files appear. */
private boolean mMonitorNativeCrashes;
/** Send no events. Use with long throttle-time to watch user operations */
private boolean mSendNoEvents;
/** This is set when we would like to abort the running of the monkey. */
private boolean mAbort;
/** This is set by the ActivityController thread to request collection of ANR trace files */
private boolean mRequestAnrTraces = false;
@@ -96,7 +96,7 @@ public class Monkey {
/** Kill the process after a timeout or crash. */
private boolean mKillProcessAfterError;
/** Generate hprof reports before/after monkey runs */
private boolean mGenerateHprof;
@@ -106,16 +106,16 @@ public class Monkey {
ArrayList<String> mMainCategories = new ArrayList<String>();
/** Applications we can switch to. */
private ArrayList<ComponentName> mMainApps = new ArrayList<ComponentName>();
/** The delay between event inputs **/
long mThrottle = 0;
/** The number of iterations **/
int mCount = 1000;
/** The random number seed **/
long mSeed = 0;
/** Dropped-event statistics **/
long mDroppedKeyEvents = 0;
long mDroppedPointerEvents = 0;
@@ -124,14 +124,21 @@ public class Monkey {
/** a filename to the script (if any) **/
private String mScriptFileName = null;
/** a TCP port to listen on for remote commands. */
private int mServerPort = -1;
private static final File TOMBSTONES_PATH = new File("/data/tombstones");
private HashSet<String> mTombstones = null;
float[] mFactors = new float[MonkeySourceRandom.FACTORZ_COUNT];
float[] mFactors = new float[MonkeySourceRandom.FACTORZ_COUNT];
MonkeyEventSource mEventSource;
private MonkeyNetworkMonitor mNetworkMonitor = new MonkeyNetworkMonitor();
// information on the current activity.
public static Intent currentIntent;
public static String currentPackage;
/**
* Monitor operations happening in the system.
*/
@@ -142,21 +149,24 @@ public class Monkey {
System.out.println(" // " + (allow ? "Allowing" : "Rejecting")
+ " start of " + intent + " in package " + pkg);
}
currentPackage = pkg;
currentIntent = intent;
return allow;
}
public boolean activityResuming(String pkg) {
System.out.println(" // activityResuming(" + pkg + ")");
boolean allow = checkEnteringPackage(pkg) || (DEBUG_ALLOW_ANY_RESTARTS != 0);
if (!allow) {
if (mVerbose > 0) {
System.out.println(" // " + (allow ? "Allowing" : "Rejecting")
+ " resume of package " + pkg);
+ " resume of package " + pkg);
}
}
currentPackage = pkg;
return allow;
}
private boolean checkEnteringPackage(String pkg) {
if (pkg == null) {
return true;
@@ -168,7 +178,7 @@ public class Monkey {
return mValidPackages.contains(pkg);
}
}
public boolean appCrashed(String processName, int pid, String shortMsg,
String longMsg, byte[] crashData) {
System.err.println("// CRASH: " + processName + " (pid " + pid
@@ -223,14 +233,14 @@ public class Monkey {
return 1;
}
}
/**
* Run the procrank tool to insert system status information into the debug report.
*/
private void reportProcRank() {
commandLineReport("procrank", "procrank");
}
/**
* Run "cat /data/anr/traces.txt". Wait about 5 seconds first, to let the asynchronous
* report writing complete.
@@ -238,21 +248,21 @@ public class Monkey {
private void reportAnrTraces() {
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
} catch (InterruptedException e) {
}
commandLineReport("anr traces", "cat /data/anr/traces.txt");
}
/**
* Run "dumpsys meminfo"
*
*
* NOTE: You cannot perform a dumpsys call from the ActivityController callback, as it will
* deadlock. This should only be called from the main loop of the monkey.
*/
private void reportDumpsysMemInfo() {
commandLineReport("meminfo", "dumpsys meminfo");
}
/**
* Print report from a single command line.
* @param reportName Simple tag that will print before the report and in various annotations.
@@ -266,7 +276,7 @@ public class Monkey {
try {
// Process must be fully qualified here because android.os.Process is used elsewhere
java.lang.Process p = Runtime.getRuntime().exec(command);
// pipe everything from process stdout -> System.err
InputStream inStream = p.getInputStream();
InputStreamReader inReader = new InputStreamReader(inStream);
@@ -275,7 +285,7 @@ public class Monkey {
while ((s = inBuffer.readLine()) != null) {
System.err.println(s);
}
int status = p.waitFor();
System.err.println("// " + reportName + " status was " + status);
} catch (Exception e) {
@@ -307,26 +317,26 @@ public class Monkey {
Debug.waitForDebugger();
}
}
// Default values for some command-line options
mVerbose = 0;
mCount = 1000;
mSeed = 0;
mThrottle = 0;
// prepare for command-line processing
mArgs = args;
mNextArg = 0;
//set a positive value, indicating none of the factors is provided yet
for (int i = 0; i < MonkeySourceRandom.FACTORZ_COUNT; i++) {
mFactors[i] = 1.0f;
}
if (!processOptions()) {
return -1;
}
// now set up additional data in preparation for launch
if (mMainCategories.size() == 0) {
mMainCategories.add(Intent.CATEGORY_LAUNCHER);
@@ -348,11 +358,11 @@ public class Monkey {
}
}
}
if (!checkInternalConfiguration()) {
return -2;
}
if (!getSystemInterfaces()) {
return -3;
}
@@ -360,11 +370,19 @@ public class Monkey {
if (!getMainApps()) {
return -4;
}
if (mScriptFileName != null) {
// script mode, ignore other options
mEventSource = new MonkeySourceScript(mScriptFileName, mThrottle);
mEventSource.setVerbose(mVerbose);
} else if (mServerPort != -1) {
try {
mEventSource = new MonkeySourceNetwork(mServerPort);
} catch (IOException e) {
System.out.println("Error binding to network socket.");
return -5;
}
mCount = Integer.MAX_VALUE;
} else {
// random source by default
if (mVerbose >= 2) { // check seeding performance
@@ -378,7 +396,7 @@ public class Monkey {
((MonkeySourceRandom) mEventSource).setFactors(i, mFactors[i]);
}
}
//in random mode, we start with a random activity
((MonkeySourceRandom) mEventSource).generateActivity();
}
@@ -387,7 +405,7 @@ public class Monkey {
if (!mEventSource.validate()) {
return -5;
}
if (mScriptFileName != null) {
// in random mode, count is the number of single events
// while in script mode, count is the number of repetition
@@ -396,12 +414,12 @@ public class Monkey {
mCount = mCount * ((MonkeySourceScript) mEventSource)
.getOneRoundEventCount();
}
// If we're profiling, do it immediately before/after the main monkey loop
if (mGenerateHprof) {
signalPersistentProcesses();
}
mNetworkMonitor.start();
int crashedAtCycle = runMonkeyCycles();
mNetworkMonitor.stop();
@@ -423,7 +441,7 @@ public class Monkey {
System.out.println("// Generated profiling reports in /data/misc");
}
}
try {
mAm.setActivityController(null);
mNetworkMonitor.unregister(mAm);
@@ -434,7 +452,7 @@ public class Monkey {
crashedAtCycle = mCount - 1;
}
}
// report dropped event stats
if (mVerbose > 0) {
System.out.print(":Dropped: keys=");
@@ -446,7 +464,7 @@ public class Monkey {
System.out.print(" flips=");
System.out.println(mDroppedFlipEvents);
}
// report network stats
mNetworkMonitor.dump();
@@ -461,10 +479,10 @@ public class Monkey {
return 0;
}
}
/**
* Process the command-line options
*
*
* @return Returns true if options were parsed with no apparent errors.
*/
private boolean processOptions() {
@@ -498,28 +516,28 @@ public class Monkey {
} else if (opt.equals("--hprof")) {
mGenerateHprof = true;
} else if (opt.equals("--pct-touch")) {
mFactors[MonkeySourceRandom.FACTOR_TOUCH] =
mFactors[MonkeySourceRandom.FACTOR_TOUCH] =
-nextOptionLong("touch events percentage");
} else if (opt.equals("--pct-motion")) {
mFactors[MonkeySourceRandom.FACTOR_MOTION] =
mFactors[MonkeySourceRandom.FACTOR_MOTION] =
-nextOptionLong("motion events percentage");
} else if (opt.equals("--pct-trackball")) {
mFactors[MonkeySourceRandom.FACTOR_TRACKBALL] =
mFactors[MonkeySourceRandom.FACTOR_TRACKBALL] =
-nextOptionLong("trackball events percentage");
} else if (opt.equals("--pct-nav")) {
mFactors[MonkeySourceRandom.FACTOR_NAV] =
mFactors[MonkeySourceRandom.FACTOR_NAV] =
-nextOptionLong("nav events percentage");
} else if (opt.equals("--pct-majornav")) {
mFactors[MonkeySourceRandom.FACTOR_MAJORNAV] =
mFactors[MonkeySourceRandom.FACTOR_MAJORNAV] =
-nextOptionLong("major nav events percentage");
} else if (opt.equals("--pct-appswitch")) {
mFactors[MonkeySourceRandom.FACTOR_APPSWITCH] =
mFactors[MonkeySourceRandom.FACTOR_APPSWITCH] =
-nextOptionLong("app switch events percentage");
} else if (opt.equals("--pct-flip")) {
mFactors[MonkeySourceRandom.FACTOR_FLIP] =
-nextOptionLong("keyboard flip percentage");
} else if (opt.equals("--pct-anyevent")) {
mFactors[MonkeySourceRandom.FACTOR_ANYTHING] =
mFactors[MonkeySourceRandom.FACTOR_ANYTHING] =
-nextOptionLong("any events percentage");
} else if (opt.equals("--throttle")) {
mThrottle = nextOptionLong("delay (in milliseconds) to wait between events");
@@ -527,7 +545,9 @@ public class Monkey {
// do nothing - it's caught at the very start of run()
} else if (opt.equals("--dbg-no-events")) {
mSendNoEvents = true;
} else if (opt.equals("-f")) {
} else if (opt.equals("--port")) {
mServerPort = (int) nextOptionLong("Server port to listen on for commands");
} else if (opt.equals("-f")) {
mScriptFileName = nextOptionData();
} else if (opt.equals("-h")) {
showUsage();
@@ -544,19 +564,23 @@ public class Monkey {
return false;
}
String countStr = nextArg();
if (countStr == null) {
System.err.println("** Error: Count not specified");
showUsage();
return false;
}
// If a server port hasn't been specified, we need to specify
// a count
if (mServerPort == -1) {
String countStr = nextArg();
if (countStr == null) {
System.err.println("** Error: Count not specified");
showUsage();
return false;
}
try {
mCount = Integer.parseInt(countStr);
} catch (NumberFormatException e) {
System.err.println("** Error: Count is not a number");
showUsage();
return false;
try {
mCount = Integer.parseInt(countStr);
} catch (NumberFormatException e) {
System.err.println("** Error: Count is not a number");
showUsage();
return false;
}
}
return true;
@@ -564,7 +588,7 @@ public class Monkey {
/**
* Check for any internal configuration (primarily build-time) errors.
*
*
* @return Returns true if ready to rock.
*/
private boolean checkInternalConfiguration() {
@@ -585,7 +609,7 @@ public class Monkey {
/**
* Attach to the required system interfaces.
*
*
* @return Returns true if all system interfaces were available.
*/
private boolean getSystemInterfaces() {
@@ -621,7 +645,7 @@ public class Monkey {
/**
* Using the restrictions provided (categories & packages), generate a list of activities
* that we can actually switch to.
*
*
* @return Returns true if it could successfully build a list of target activities
*/
private boolean getMainApps() {
@@ -644,7 +668,7 @@ public class Monkey {
final int NA = mainApps.size();
for (int a = 0; a < NA; a++) {
ResolveInfo r = mainApps.get(a);
if (mValidPackages.size() == 0 ||
if (mValidPackages.size() == 0 ||
mValidPackages.contains(r.activityInfo.applicationInfo.packageName)) {
if (mVerbose >= 2) { // very verbose
System.out.println("// + Using main activity "
@@ -676,15 +700,15 @@ public class Monkey {
System.out.println("** No activities found to run, monkey aborted.");
return false;
}
return true;
}
/**
* Run mCount cycles and see if we hit any crashers.
*
*
* TODO: Meta state on keys
*
*
* @return Returns the last cycle which executed. If the value == mCount, no errors detected.
*/
private int runMonkeyCycles() {
@@ -749,9 +773,11 @@ public class Monkey {
} else if (injectCode == MonkeyEvent.INJECT_ERROR_SECURITY_EXCEPTION) {
systemCrashed = !mIgnoreSecurityExceptions;
}
} else {
// Event Source has signaled that we have no more events to process
break;
}
}
// If we got this far, we succeeded!
return mCount;
}
@@ -775,18 +801,18 @@ public class Monkey {
/**
* Watch for appearance of new tombstone files, which indicate native crashes.
*
*
* @return Returns true if new files have appeared in the list
*/
private boolean checkNativeCrashes() {
String[] tombstones = TOMBSTONES_PATH.list();
// shortcut path for usually empty directory, so we don't waste even more objects
if ((tombstones == null) || (tombstones.length == 0)) {
mTombstones = null;
return false;
}
// use set logic to look for new files
HashSet<String> newStones = new HashSet<String>();
for (String x : tombstones) {
@@ -804,14 +830,14 @@ public class Monkey {
/**
* Return the next command line option. This has a number of special cases which
* closely, but not exactly, follow the POSIX command line options patterns:
*
*
* -- means to stop processing additional options
* -z means option z
* -z ARGS means option z with (non-optional) arguments ARGS
* -zARGS means option z with (optional) arguments ARGS
* --zz means option zz
* --zz ARGS means option zz with (non-optional) arguments ARGS
*
*
* Note that you cannot combine single letter options; -abc != -a -b -c
*
* @return Returns the option string, or null if there are no more options.
@@ -857,10 +883,10 @@ public class Monkey {
mNextArg++;
return data;
}
/**
* Returns a long converted from the next data argument, with error handling if not available.
*
*
* @param opt The name of the option.
* @return Returns a long converted from the argument.
*/
@@ -904,6 +930,7 @@ public class Monkey {
System.err.println(" [--pct-appswitch PERCENT] [--pct-flip PERCENT]");
System.err.println(" [--pct-anyevent PERCENT]");
System.err.println(" [--wait-dbg] [--dbg-no-events] [-f scriptfile]");
System.err.println(" [--port port]");
System.err.println(" [-s SEED] [-v [-v] ...] [--throttle MILLISEC]");
System.err.println(" COUNT");
}

View File

@@ -22,7 +22,7 @@ import android.view.IWindowManager;
/**
* abstract class for monkey event
*/
public abstract class MonkeyEvent {
public abstract class MonkeyEvent {
protected int eventType;
public static final int EVENT_TYPE_KEY = 0;
public static final int EVENT_TYPE_POINTER = 1;
@@ -30,41 +30,42 @@ public abstract class MonkeyEvent {
public static final int EVENT_TYPE_ACTIVITY = 3;
public static final int EVENT_TYPE_FLIP = 4; // Keyboard flip
public static final int EVENT_TYPE_THROTTLE = 5;
public static final int EVENT_TYPE_NOOP = 6;
public static final int INJECT_SUCCESS = 1;
public static final int INJECT_FAIL = 0;
// error code for remote exception during injection
public static final int INJECT_ERROR_REMOTE_EXCEPTION = -1;
public static final int INJECT_ERROR_REMOTE_EXCEPTION = -1;
// error code for security exception during injection
public static final int INJECT_ERROR_SECURITY_EXCEPTION = -2;
public MonkeyEvent(int type) {
eventType = type;
}
/**
/**
* @return event type
*/
*/
public int getEventType() {
return eventType;
}
/**
* @return true if it is safe to throttle after this event, and false otherwise.
*/
public boolean isThrottlable() {
return true;
}
/**
* a method for injecting event
* @param iwm wires to current window manager
* @param iam wires to current activity manager
* @param verbose a log switch
* @param verbose a log switch
* @return INJECT_SUCCESS if it goes through, and INJECT_FAIL if it fails
* in the case of exceptions, return its corresponding error code
*/
public abstract int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose);
public abstract int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose);
}

View File

@@ -23,7 +23,7 @@ import android.view.KeyEvent;
/**
* monkey key event
*/
public class MonkeyKeyEvent extends MonkeyEvent {
public class MonkeyKeyEvent extends MonkeyEvent {
private long mDownTime = -1;
private int mMetaState = -1;
private int mAction = -1;
@@ -32,18 +32,25 @@ public class MonkeyKeyEvent extends MonkeyEvent {
private int mRepeatCount = -1;
private int mDeviceId = -1;
private long mEventTime = -1;
private KeyEvent keyEvent = null;
public MonkeyKeyEvent(int action, int keycode) {
super(EVENT_TYPE_KEY);
mAction = action;
mKeyCode = keycode;
}
public MonkeyKeyEvent(KeyEvent e) {
super(EVENT_TYPE_KEY);
keyEvent = e;
}
public MonkeyKeyEvent(long downTime, long eventTime, int action,
int code, int repeat, int metaState,
int device, int scancode) {
super(EVENT_TYPE_KEY);
mAction = action;
mKeyCode = code;
mMetaState = metaState;
@@ -53,49 +60,52 @@ public class MonkeyKeyEvent extends MonkeyEvent {
mDownTime = downTime;
mEventTime = eventTime;
}
public int getKeyCode() {
return mKeyCode;
}
public int getAction() {
return mAction;
}
public long getDownTime() {
return mDownTime;
}
public long getEventTime() {
return mEventTime;
}
public void setDownTime(long downTime) {
mDownTime = downTime;
}
public void setEventTime(long eventTime) {
mEventTime = eventTime;
}
/**
/**
* @return the key event
*/
*/
private KeyEvent getEvent() {
if (mDeviceId < 0) {
return new KeyEvent(mAction, mKeyCode);
}
// for scripts
return new KeyEvent(mDownTime, mEventTime, mAction,
mKeyCode, mRepeatCount, mMetaState, mDeviceId, mScancode);
if (keyEvent == null) {
if (mDeviceId < 0) {
keyEvent = new KeyEvent(mAction, mKeyCode);
} else {
// for scripts
keyEvent = new KeyEvent(mDownTime, mEventTime, mAction,
mKeyCode, mRepeatCount, mMetaState, mDeviceId, mScancode);
}
}
return keyEvent;
}
@Override
public boolean isThrottlable() {
return (getAction() == KeyEvent.ACTION_UP);
}
@Override
public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
if (verbose > 1) {
@@ -124,7 +134,7 @@ public class MonkeyKeyEvent extends MonkeyEvent {
} catch (RemoteException ex) {
return MonkeyEvent.INJECT_ERROR_REMOTE_EXCEPTION;
}
return MonkeyEvent.INJECT_SUCCESS;
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.commands.monkey;
import java.util.List;
import android.app.IActivityManager;
import android.view.IWindowManager;
/**
* monkey noop event (don't do anything).
*/
public class MonkeyNoopEvent extends MonkeyEvent {
public MonkeyNoopEvent() {
super(MonkeyEvent.EVENT_TYPE_NOOP);
}
@Override
public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
// No real work to do
if (verbose > 1) {
System.out.println("NOOP");
}
return MonkeyEvent.INJECT_SUCCESS;
}
}

View File

@@ -0,0 +1,697 @@
/*
* Copyright 2009, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.commands.monkey;
import android.content.Context;
import android.os.IPowerManager;
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;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.Integer;
import java.lang.NumberFormatException;
import java.net.InetAddress;
import java.net.ServerSocket;
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;
/**
* An Event source for getting Monkey Network Script commands from
* over the network.
*/
public class MonkeySourceNetwork implements MonkeyEventSource {
private static final String TAG = "MonkeyStub";
/**
* ReturnValue from the MonkeyCommand that indicates whether the
* command was sucessful or not.
*/
public static class MonkeyCommandReturn {
private final boolean success;
private final String message;
public MonkeyCommandReturn(boolean success) {
this.success = success;
this.message = null;
}
public MonkeyCommandReturn(boolean success,
String message) {
this.success = success;
this.message = message;
}
boolean hasMessage() {
return message != null;
}
String getMessage() {
return message;
}
boolean wasSuccessful() {
return success;
}
}
public final static MonkeyCommandReturn OK = new MonkeyCommandReturn(true);
public final static MonkeyCommandReturn ERROR = new MonkeyCommandReturn(false);
public final static MonkeyCommandReturn EARG = new MonkeyCommandReturn(false,
"Invalid Argument");
/**
* Interface that MonkeyCommands must implement.
*/
public interface MonkeyCommand {
/**
* Translate the command line into a sequence of MonkeyEvents.
*
* @param command the command line.
* @param queue the command queue.
* @returs MonkeyCommandReturn indicating what happened.
*/
MonkeyCommandReturn translateCommand(List<String> command, CommandQueue queue);
}
/**
* Command to simulate closing and opening the keyboard.
*/
private static class FlipCommand implements MonkeyCommand {
// flip open
// flip closed
public MonkeyCommandReturn translateCommand(List<String> command,
CommandQueue queue) {
if (command.size() > 1) {
String direction = command.get(1);
if ("open".equals(direction)) {
queue.enqueueEvent(new MonkeyFlipEvent(true));
return OK;
} else if ("close".equals(direction)) {
queue.enqueueEvent(new MonkeyFlipEvent(false));
return OK;
}
}
return EARG;
}
}
/**
* Command to send touch events to the input system.
*/
private static class TouchCommand implements MonkeyCommand {
// touch [down|up|move] [x] [y]
// touch down 120 120
// touch move 140 140
// touch up 140 140
public MonkeyCommandReturn translateCommand(List<String> command,
CommandQueue queue) {
if (command.size() == 4) {
String actionName = command.get(1);
int x = 0;
int y = 0;
try {
x = Integer.parseInt(command.get(2));
y = Integer.parseInt(command.get(3));
} catch (NumberFormatException e) {
// Ok, it wasn't a number
Log.e(TAG, "Got something that wasn't a number", e);
return EARG;
}
// figure out the action
int action = -1;
if ("down".equals(actionName)) {
action = MotionEvent.ACTION_DOWN;
} else if ("up".equals(actionName)) {
action = MotionEvent.ACTION_UP;
} else if ("move".equals(actionName)) {
action = MotionEvent.ACTION_MOVE;
}
if (action == -1) {
Log.e(TAG, "Got a bad action: " + actionName);
return EARG;
}
queue.enqueueEvent(new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER,
-1, action, x, y, 0));
return OK;
}
return EARG;
}
}
/**
* Command to send Trackball events to the input system.
*/
private static class TrackballCommand implements MonkeyCommand {
// trackball [dx] [dy]
// trackball 1 0 -- move right
// trackball -1 0 -- move left
public MonkeyCommandReturn translateCommand(List<String> command,
CommandQueue queue) {
if (command.size() == 3) {
int dx = 0;
int dy = 0;
try {
dx = Integer.parseInt(command.get(1));
dy = 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 EARG;
}
queue.enqueueEvent(new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, -1,
MotionEvent.ACTION_MOVE, dx, dy, 0));
return OK;
}
return EARG;
}
}
/**
* Command to send Key events to the input system.
*/
private static class KeyCommand implements MonkeyCommand {
// key [down|up] [keycode]
// key down 82
// key up 82
public MonkeyCommandReturn translateCommand(List<String> command,
CommandQueue queue) {
if (command.size() == 3) {
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 EARG;
}
Log.d(TAG, "keycode: " + keyCode);
int action = -1;
if ("down".equals(command.get(1))) {
action = KeyEvent.ACTION_DOWN;
} else if ("up".equals(command.get(1))) {
action = KeyEvent.ACTION_UP;
}
if (action == -1) {
Log.e(TAG, "got unknown action.");
return EARG;
}
queue.enqueueEvent(new MonkeyKeyEvent(action, keyCode));
return OK;
}
return EARG;
}
}
/**
* 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 MonkeyCommandReturn 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);
return EARG;
}
queue.enqueueEvent(new MonkeyThrottleEvent(sleep));
return OK;
}
return EARG;
}
}
/**
* Command to type a string
*/
private static class TypeCommand implements MonkeyCommand {
// wake
public MonkeyCommandReturn 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 OK;
}
return EARG;
}
}
/**
* Command to wake the device up
*/
private static class WakeCommand implements MonkeyCommand {
// wake
public MonkeyCommandReturn translateCommand(List<String> command,
CommandQueue queue) {
if (!wake()) {
return ERROR;
}
return OK;
}
}
/**
* Command to "tap" at a location (Sends a down and up touch
* event).
*/
private static class TapCommand implements MonkeyCommand {
// tap x y
public MonkeyCommandReturn 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 EARG;
}
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 OK;
}
return EARG;
}
}
/**
* Command to "press" a buttons (Sends an up and down key event.)
*/
private static class PressCommand implements MonkeyCommand {
// press keycode
public MonkeyCommandReturn 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 EARG;
}
queue.enqueueEvent(new MonkeyKeyEvent(KeyEvent.ACTION_DOWN, keyCode));
queue.enqueueEvent(new MonkeyKeyEvent(KeyEvent.ACTION_UP, keyCode));
return OK;
}
return EARG;
}
}
/**
* Force the device to wake up.
*
* @return true if woken up OK.
*/
private static final boolean wake() {
IPowerManager pm =
IPowerManager.Stub.asInterface(ServiceManager.getService(Context.POWER_SERVICE));
try {
pm.userActivityWithForce(SystemClock.uptimeMillis(), true, true);
} catch (RemoteException e) {
Log.e(TAG, "Got remote exception", e);
return false;
}
return true;
}
// This maps from command names to command implementations.
private static final Map<String, MonkeyCommand> COMMAND_MAP = new HashMap<String, MonkeyCommand>();
static {
// Add in all the commands we support
COMMAND_MAP.put("flip", new FlipCommand());
COMMAND_MAP.put("touch", new TouchCommand());
COMMAND_MAP.put("trackball", new TrackballCommand());
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());
COMMAND_MAP.put("listvar", new MonkeySourceNetworkVars.ListVarCommand());
COMMAND_MAP.put("getvar", new MonkeySourceNetworkVars.GetVarCommand());
}
// QUIT command
private static final String QUIT = "quit";
// DONE command
private static final String DONE = "done";
// command response strings
private static final String OK_STR = "OK";
private static final String ERROR_STR = "ERROR";
public 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 BufferedReader input;
private PrintWriter output;
private boolean started = false;
private ServerSocket serverSocket;
private Socket clientSocket;
public MonkeySourceNetwork(int port) throws IOException {
// Only bind this to local host. This means that you can only
// talk to the monkey locally, or though adb port forwarding.
serverSocket = new ServerSocket(port,
0, // default backlog
InetAddress.getLocalHost());
}
/**
* Start a network server listening on the specified port. The
* network protocol is a line oriented protocol, where each line
* is a different command that can be run.
*
* @param port the port to listen on
*/
private void startServer() throws IOException {
clientSocket = serverSocket.accept();
// At this point, we have a client connected. Wake the device
// up in preparation for doing some commands.
wake();
input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// auto-flush
output = new PrintWriter(clientSocket.getOutputStream(), true);
}
/**
* Stop the server from running so it can reconnect a new client.
*/
private void stopServer() throws IOException {
clientSocket.close();
input.close();
output.close();
started = false;
}
/**
* 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.
*
* "This is a test" -> returns only one element
* This is a test -> returns four elements
*
* @param line the line to parse
* @return the List of elements
*/
private static List<String> commandLineSplit(String line) {
ArrayList<String> result = new ArrayList<String>();
StringTokenizer tok = new StringTokenizer(line);
boolean insideQuote = false;
StringBuffer quotedWord = new StringBuffer();
while (tok.hasMoreTokens()) {
String cur = tok.nextToken();
if (!insideQuote && cur.startsWith("\"")) {
// begin quote
quotedWord.append(replaceQuotedChars(cur));
insideQuote = true;
} else if (insideQuote) {
// end quote
if (cur.endsWith("\"")) {
insideQuote = false;
quotedWord.append(" ").append(replaceQuotedChars(cur));
String word = quotedWord.toString();
// trim off the quotes
result.add(word.substring(1, word.length() - 1));
} else {
quotedWord.append(" ").append(replaceQuotedChars(cur));
}
} else {
result.add(replaceQuotedChars(cur));
}
}
return result;
}
/**
* Translate the given command line into a MonkeyEvent.
*
* @param commandLine the full command line given.
*/
private void translateCommand(String commandLine) {
Log.d(TAG, "translateCommand: " + commandLine);
List<String> parts = commandLineSplit(commandLine);
if (parts.size() > 0) {
MonkeyCommand command = COMMAND_MAP.get(parts.get(0));
if (command != null) {
MonkeyCommandReturn ret = command.translateCommand(parts,
commandQueue);
if (ret.wasSuccessful()) {
if (ret.hasMessage()) {
returnOk(ret.getMessage());
} else {
returnOk();
}
} else {
if (ret.hasMessage()) {
returnError(ret.getMessage());
} else {
returnError();
}
}
}
}
}
public MonkeyEvent getNextEvent() {
if (!started) {
try {
startServer();
} catch (IOException e) {
Log.e(TAG, "Got IOException from server", e);
return null;
}
started = true;
}
// 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.");
// Treat this exactly the same as if the user had
// ended the session cleanly with a done commant.
command = DONE;
}
if (DONE.equals(command)) {
// stop the server so it can accept new connections
try {
stopServer();
} catch (IOException e) {
Log.e(TAG, "Got IOException shutting down!", e);
return null;
}
// return a noop event so we keep executing the main
// loop
return new MonkeyNoopEvent();
}
// Do quit checking here
if (QUIT.equals(command)) {
// then we're done
Log.d(TAG, "Quit requested");
// let the host know the command ran OK
returnOk();
return null;
}
// Do comment checking here. Comments aren't a
// command, so we don't echo anything back to the
// user.
if (command.startsWith("#")) {
// keep going
continue;
}
// Translate the command line. This will handle returning error/ok to the user
translateCommand(command);
}
} catch (IOException e) {
Log.e(TAG, "Exception: ", e);
return null;
}
}
/**
* Returns ERROR to the user.
*/
private void returnError() {
output.println(ERROR_STR);
}
/**
* Returns ERROR to the user.
*
* @param msg the error message to include
*/
private void returnError(String msg) {
output.print(ERROR_STR);
output.print(":");
output.println(msg);
}
/**
* Returns OK to the user.
*/
private void returnOk() {
output.println(OK_STR);
}
/**
* Returns OK to the user.
*
* @param returnValue the value to return from this command.
*/
private void returnOk(String returnValue) {
output.print(OK_STR);
output.print(":");
output.println(returnValue);
}
public void setVerbose(int verbose) {
// We're not particualy verbose
}
public boolean validate() {
// we have no pre-conditions to validate
return true;
}
}

View File

@@ -0,0 +1,197 @@
/*
* Copyright 2009, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.commands.monkey;
import android.os.Build;
import android.os.SystemClock;
import android.view.Display;
import android.view.WindowManagerImpl;
import android.util.DisplayMetrics;
import com.android.commands.monkey.MonkeySourceNetwork.CommandQueue;
import com.android.commands.monkey.MonkeySourceNetwork.MonkeyCommand;
import com.android.commands.monkey.MonkeySourceNetwork.MonkeyCommandReturn;
import java.lang.Integer;
import java.lang.Float;
import java.lang.Long;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class MonkeySourceNetworkVars {
/**
* Interface to get the value of a var.
*/
private static interface VarGetter {
/**
* Get the value of the var.
* @returns the value of the var.
*/
public String get();
}
private static class StaticVarGetter implements VarGetter {
private final String value;
public StaticVarGetter(String value) {
this.value = value;
}
public String get() {
return value;
}
}
// Use a TreeMap to keep the keys sorted so they get displayed nicely in listvar
private static final Map<String, VarGetter> VAR_MAP = new TreeMap<String, VarGetter>();
static {
VAR_MAP.put("build.board", new StaticVarGetter(Build.BOARD));
VAR_MAP.put("build.brand", new StaticVarGetter(Build.BRAND));
VAR_MAP.put("build.device", new StaticVarGetter(Build.DEVICE));
VAR_MAP.put("build.display", new StaticVarGetter(Build.DISPLAY));
VAR_MAP.put("build.fingerprint", new StaticVarGetter(Build.FINGERPRINT));
VAR_MAP.put("build.host", new StaticVarGetter(Build.HOST));
VAR_MAP.put("build.id", new StaticVarGetter(Build.ID));
VAR_MAP.put("build.model", new StaticVarGetter(Build.MODEL));
VAR_MAP.put("build.product", new StaticVarGetter(Build.PRODUCT));
VAR_MAP.put("build.tags", new StaticVarGetter(Build.TAGS));
VAR_MAP.put("build.brand", new StaticVarGetter(Long.toString(Build.TIME)));
VAR_MAP.put("build.type", new StaticVarGetter(Build.TYPE));
VAR_MAP.put("build.user", new StaticVarGetter(Build.USER));
VAR_MAP.put("build.cpu_abi", new StaticVarGetter(Build.CPU_ABI));
VAR_MAP.put("build.manufacturer", new StaticVarGetter(Build.MANUFACTURER));
VAR_MAP.put("build.version.incremental", new StaticVarGetter(Build.VERSION.INCREMENTAL));
VAR_MAP.put("build.version.release", new StaticVarGetter(Build.VERSION.RELEASE));
VAR_MAP.put("build.version.sdk", new StaticVarGetter(Integer.toString(Build.VERSION.SDK_INT)));
VAR_MAP.put("build.version.codename", new StaticVarGetter(Build.VERSION.CODENAME));
// Display
Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
VAR_MAP.put("display.width", new StaticVarGetter(Integer.toString(display.getWidth())));
VAR_MAP.put("display.height", new StaticVarGetter(Integer.toString(display.getHeight())));
DisplayMetrics dm = new DisplayMetrics();
display.getMetrics(dm);
VAR_MAP.put("display.density", new StaticVarGetter(Float.toString(dm.density)));
// am. note that the current activity information isn't valid
// until the first activity gets launched after the monkey has
// been started.
VAR_MAP.put("am.current.package", new VarGetter() {
public String get() {
return Monkey.currentPackage;
}
});
VAR_MAP.put("am.current.action", new VarGetter() {
public String get() {
if (Monkey.currentIntent == null) {
return null;
}
return Monkey.currentIntent.getAction();
}
});
VAR_MAP.put("am.current.comp.class", new VarGetter() {
public String get() {
if (Monkey.currentIntent == null) {
return null;
}
return Monkey.currentIntent.getComponent().getClassName();
}
});
VAR_MAP.put("am.current.comp.package", new VarGetter() {
public String get() {
if (Monkey.currentIntent == null) {
return null;
}
return Monkey.currentIntent.getComponent().getPackageName();
}
});
VAR_MAP.put("am.current.data", new VarGetter() {
public String get() {
if (Monkey.currentIntent == null) {
return null;
}
return Monkey.currentIntent.getDataString();
}
});
VAR_MAP.put("am.current.categories", new VarGetter() {
public String get() {
if (Monkey.currentIntent == null) {
return null;
}
StringBuffer sb = new StringBuffer();
for (String cat : Monkey.currentIntent.getCategories()) {
sb.append(cat).append(" ");
}
return sb.toString();
}
});
// clock
VAR_MAP.put("clock.realtime", new VarGetter() {
public String get() {
return Long.toString(SystemClock.elapsedRealtime());
}
});
VAR_MAP.put("clock.uptime", new VarGetter() {
public String get() {
return Long.toString(SystemClock.uptimeMillis());
}
});
VAR_MAP.put("clock.millis", new VarGetter() {
public String get() {
return Long.toString(System.currentTimeMillis());
}
});
}
/**
* Command to list the "vars" that the monkey knows about.
*/
public static class ListVarCommand implements MonkeySourceNetwork.MonkeyCommand {
// listvar
public MonkeyCommandReturn translateCommand(List<String> command,
CommandQueue queue) {
Set<String> keys = VAR_MAP.keySet();
StringBuffer sb = new StringBuffer();
for (String key : keys) {
sb.append(key).append(" ");
}
return new MonkeyCommandReturn(true, sb.toString());
}
}
/**
* Command to get the value of a var.
*/
public static class GetVarCommand implements MonkeyCommand {
// getvar varname
public MonkeyCommandReturn translateCommand(List<String> command,
CommandQueue queue) {
if (command.size() == 2) {
VarGetter getter = VAR_MAP.get(command.get(1));
if (getter == null) {
return new MonkeyCommandReturn(false, "unknown var");
}
return new MonkeyCommandReturn(true, getter.get());
}
return MonkeySourceNetwork.EARG;
}
}
}

View File

@@ -31,7 +31,7 @@ import java.util.Random;
/**
* monkey event queue
*/
public class MonkeySourceRandom implements MonkeyEventSource {
public class MonkeySourceRandom implements MonkeyEventSource {
/** Key events that move around the UI. */
private static final int[] NAV_KEYS = {
KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN,
@@ -55,7 +55,7 @@ public class MonkeySourceRandom implements MonkeyEventSource {
/** Nice names for all key events. */
private static final String[] KEY_NAMES = {
"KEYCODE_UNKNOWN",
"KEYCODE_MENU",
"KEYCODE_SOFT_LEFT",
"KEYCODE_SOFT_RIGHT",
"KEYCODE_HOME",
"KEYCODE_BACK",
@@ -146,7 +146,7 @@ public class MonkeySourceRandom implements MonkeyEventSource {
"KEYCODE_REWIND",
"KEYCODE_FORWARD",
"KEYCODE_MUTE",
"TAG_LAST_KEYCODE" // EOL. used to keep the lists in sync
};
@@ -158,34 +158,50 @@ public class MonkeySourceRandom implements MonkeyEventSource {
public static final int FACTOR_SYSOPS = 5;
public static final int FACTOR_APPSWITCH = 6;
public static final int FACTOR_FLIP = 7;
public static final int FACTOR_ANYTHING = 8;
public static final int FACTOR_ANYTHING = 8;
public static final int FACTORZ_COUNT = 9; // should be last+1
/** percentages for each type of event. These will be remapped to working
* values after we read any optional values.
**/
**/
private float[] mFactors = new float[FACTORZ_COUNT];
private ArrayList<ComponentName> mMainApps;
private int mEventCount = 0; //total number of events generated so far
private MonkeyEventQueue mQ;
private Random mRandom;
private Random mRandom;
private int mVerbose = 0;
private long mThrottle = 0;
private boolean mKeyboardOpen = false;
/**
/**
* @return the last name in the key list
*/
public static String getLastKeyName() {
return KEY_NAMES[KeyEvent.getMaxKeyCode() + 1];
}
public static String getKeyName(int keycode) {
return KEY_NAMES[keycode];
}
/**
* Looks up the keyCode from a given KEYCODE_NAME. NOTE: This may
* be an expensive operation.
*
* @param keyName the name of the KEYCODE_VALUE to lookup.
* @returns the intenger keyCode value, or -1 if not found
*/
public static int getKeyCode(String keyName) {
for (int x = 0; x < KEY_NAMES.length; x++) {
if (KEY_NAMES[x].equals(keyName)) {
return x;
}
}
return -1;
}
public MonkeySourceRandom(long seed, ArrayList<ComponentName> MainApps, long throttle) {
// default values for random distributions
// note, these are straight percentages, to match user input (cmd line args)
@@ -199,7 +215,7 @@ public class MonkeySourceRandom implements MonkeyEventSource {
mFactors[FACTOR_APPSWITCH] = 2.0f;
mFactors[FACTOR_FLIP] = 1.0f;
mFactors[FACTOR_ANYTHING] = 15.0f;
mRandom = new SecureRandom();
mRandom.setSeed((seed == 0) ? -1 : seed);
mMainApps = MainApps;
@@ -220,25 +236,25 @@ public class MonkeySourceRandom implements MonkeyEventSource {
} else {
defaultSum += mFactors[i];
++defaultCount;
}
}
}
// if the user request was > 100%, reject it
if (userSum > 100.0f) {
System.err.println("** Event weights > 100%");
return false;
}
// if the user specified all of the weights, then they need to be 100%
if (defaultCount == 0 && (userSum < 99.9f || userSum > 100.1f)) {
System.err.println("** Event weights != 100%");
return false;
}
// compute the adjustment necessary
float defaultsTarget = (100.0f - userSum);
float defaultsAdjustment = defaultsTarget / defaultSum;
// fix all values, by adjusting defaults, or flipping user values back to >0
for (int i = 0; i < FACTORZ_COUNT; ++i) {
if (mFactors[i] <= 0.0f) { // user values are zero or negative
@@ -247,46 +263,46 @@ public class MonkeySourceRandom implements MonkeyEventSource {
mFactors[i] *= defaultsAdjustment;
}
}
// if verbose, show factors
if (mVerbose > 0) {
System.out.println("// Event percentages:");
for (int i = 0; i < FACTORZ_COUNT; ++i) {
System.out.println("// " + i + ": " + mFactors[i] + "%");
}
}
}
// finally, normalize and convert to running sum
float sum = 0.0f;
for (int i = 0; i < FACTORZ_COUNT; ++i) {
sum += mFactors[i] / 100.0f;
mFactors[i] = sum;
}
}
return true;
}
/**
* set the factors
*
*
* @param factors: percentages for each type of event
*/
public void setFactors(float factors[]) {
int c = FACTORZ_COUNT;
if (factors.length < c) {
c = factors.length;
}
}
for (int i = 0; i < c; i++)
mFactors[i] = factors[i];
}
public void setFactors(int index, float v) {
mFactors[index] = v;
}
/**
* Generates a random motion event. This method counts a down, move, and up as multiple events.
*
*
* TODO: Test & fix the selectors when non-zero percentages
* TODO: Longpress.
* TODO: Fling.
@@ -294,13 +310,13 @@ public class MonkeySourceRandom implements MonkeyEventSource {
* TODO: More useful than the random walk here would be to pick a single random direction
* and distance, and divvy it up into a random number of segments. (This would serve to
* generate fling gestures, which are important).
*
*
* @param random Random number source for positioning
* @param motionEvent If false, touch/release. If true, touch/move/release.
*
* @param motionEvent If false, touch/release. If true, touch/move/release.
*
*/
private void generateMotionEvent(Random random, boolean motionEvent){
Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
float x = Math.abs(random.nextInt() % display.getWidth());
@@ -310,12 +326,12 @@ public class MonkeySourceRandom implements MonkeyEventSource {
if (downAt == -1) {
downAt = eventTime;
}
MonkeyMotionEvent e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER,
downAt, MotionEvent.ACTION_DOWN, x, y, 0);
e.setIntermediateNote(false);
MonkeyMotionEvent e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER,
downAt, MotionEvent.ACTION_DOWN, x, y, 0);
e.setIntermediateNote(false);
mQ.addLast(e);
// sometimes we'll move during the touch
if (motionEvent) {
int count = random.nextInt(10);
@@ -323,34 +339,34 @@ public class MonkeySourceRandom implements MonkeyEventSource {
// generate some slop in the up event
x = (x + (random.nextInt() % 10)) % display.getWidth();
y = (y + (random.nextInt() % 10)) % display.getHeight();
e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER,
downAt, MotionEvent.ACTION_MOVE, x, y, 0);
e.setIntermediateNote(true);
e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER,
downAt, MotionEvent.ACTION_MOVE, x, y, 0);
e.setIntermediateNote(true);
mQ.addLast(e);
}
}
// TODO generate some slop in the up event
e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER,
downAt, MotionEvent.ACTION_UP, x, y, 0);
e.setIntermediateNote(false);
e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER,
downAt, MotionEvent.ACTION_UP, x, y, 0);
e.setIntermediateNote(false);
mQ.addLast(e);
}
/**
* Generates a random trackball event. This consists of a sequence of small moves, followed by
* an optional single click.
*
*
* TODO: Longpress.
* TODO: Meta state
* TODO: Parameterize the % clicked
* TODO: More useful than the random walk here would be to pick a single random direction
* and distance, and divvy it up into a random number of segments. (This would serve to
* generate fling gestures, which are important).
*
*
* @param random Random number source for positioning
*
*
*/
private void generateTrackballEvent(Random random) {
Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
@@ -362,47 +378,47 @@ public class MonkeySourceRandom implements MonkeyEventSource {
// generate a small random step
int dX = random.nextInt(10) - 5;
int dY = random.nextInt(10) - 5;
e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, -1,
MotionEvent.ACTION_MOVE, dX, dY, 0);
e.setIntermediateNote(i > 0);
e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, -1,
MotionEvent.ACTION_MOVE, dX, dY, 0);
e.setIntermediateNote(i > 0);
mQ.addLast(e);
}
// 10% of trackball moves end with a click
if (0 == random.nextInt(10)) {
long downAt = SystemClock.uptimeMillis();
e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, downAt,
MotionEvent.ACTION_DOWN, 0, 0, 0);
e.setIntermediateNote(true);
e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, downAt,
MotionEvent.ACTION_DOWN, 0, 0, 0);
e.setIntermediateNote(true);
mQ.addLast(e);
e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, downAt,
MotionEvent.ACTION_UP, 0, 0, 0);
e.setIntermediateNote(false);
e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, downAt,
MotionEvent.ACTION_UP, 0, 0, 0);
e.setIntermediateNote(false);
mQ.addLast(e);
}
}
}
/**
/**
* generate a random event based on mFactor
*/
private void generateEvents() {
private void generateEvents() {
float cls = mRandom.nextFloat();
int lastKey = 0;
boolean touchEvent = cls < mFactors[FACTOR_TOUCH];
boolean motionEvent = !touchEvent && (cls < mFactors[FACTOR_MOTION]);
if (touchEvent || motionEvent) {
if (touchEvent || motionEvent) {
generateMotionEvent(mRandom, motionEvent);
return;
}
if (cls < mFactors[FACTOR_TRACKBALL]) {
if (cls < mFactors[FACTOR_TRACKBALL]) {
generateTrackballEvent(mRandom);
return;
}
@@ -427,23 +443,23 @@ public class MonkeySourceRandom implements MonkeyEventSource {
} else {
lastKey = 1 + mRandom.nextInt(KeyEvent.getMaxKeyCode() - 1);
}
MonkeyKeyEvent e = new MonkeyKeyEvent(KeyEvent.ACTION_DOWN, lastKey);
mQ.addLast(e);
e = new MonkeyKeyEvent(KeyEvent.ACTION_UP, lastKey);
mQ.addLast(e);
}
public boolean validate() {
//check factors
return adjustEventFactors();
}
public void setVerbose(int verbose) {
mVerbose = verbose;
}
/**
* generate an activity event
*/
@@ -452,18 +468,18 @@ public class MonkeySourceRandom implements MonkeyEventSource {
mRandom.nextInt(mMainApps.size())));
mQ.addLast(e);
}
/**
* if the queue is empty, we generate events first
* @return the first event in the queue
* @return the first event in the queue
*/
public MonkeyEvent getNextEvent() {
if (mQ.isEmpty()) {
generateEvents();
}
mEventCount++;
MonkeyEvent e = mQ.getFirst();
mQ.removeFirst();
}
mEventCount++;
MonkeyEvent e = mQ.getFirst();
mQ.removeFirst();
return e;
}
}

View File

@@ -1,8 +1,8 @@
<html>
<head>
<meta http-equiv="refresh" content="0;url=docs/sdk/1.1_r1/index.html">
<meta http-equiv="refresh" content="0;url=docs/sdk/RELEASENOTES.html">
</head>
<body>
<a href="docs/sdk/1.1_r1/index.html">click here if you are not redirected</a>
<a href="docs/sdk/RELEASENOTES.html">click here if you are not redirected</a>
</body>
</html>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 449 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 825 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 795 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -1,84 +1,104 @@
parts {
device {
portrait {
background {
image device.png
image background_port.png
}
}
landscape {
background {
image background_land.png
}
}
device {
display {
width 320
height 480
x 31
y 72
x 0
y 0
}
}
controls {
background {
image controls.png
}
buttons {
soft-left {
image menu.png
x 147
y 555
image button.png
x 56
y 142
}
home {
image home.png
x 48
y 590
image button.png
x 0
y 142
}
back {
image back.png
x 286
y 590
image button.png
x 112
y 142
}
dpad-up {
image arrow_up.png
x 140
y 595
x 77
y 53
}
dpad-down {
image arrow_down.png
x 140
y 656
x 77
y 106
}
dpad-left {
image arrow_left.png
x 111
y 598
x 53
y 53
}
dpad-right {
image arrow_right.png
x 222
y 598
x 123
y 53
}
dpad-center {
image select.png
x 142
y 626
x 77
y 81
}
phone-dial {
image send.png
x 48
y 646
image button.png
x 0
y 71
}
phone-hangup {
image end.png
x 286
y 646
image button.png
x 168
y 71
}
power {
image power.png
x -38
y 52
image button.png
x 168
y 0
}
volume-up {
image volume_up.png
x 362
y 260
image button.png
x 112
y 0
}
volume-down {
image volume_down.png
x 362
y 310
image button.png
x 56
y 0
}
search {
image button.png
x 168
y 142
}
}
}
@@ -89,242 +109,242 @@ parts {
buttons {
1 {
image key.png
x 0
y 0
x 5
y 5
}
2 {
image key.png
x 37
y 0
x 42
y 5
}
3 {
image key.png
x 74
y 0
x 79
y 5
}
4 {
image key.png
x 111
y 0
x 116
y 5
}
5 {
image key.png
x 148
y 0
x 153
y 5
}
6 {
image key.png
x 185
y 0
x 190
y 5
}
7 {
image key.png
x 222
y 0
x 227
y 5
}
8 {
image key.png
x 259
y 0
x 264
y 5
}
9 {
image key.png
x 296
y 0
x 301
y 5
}
0 {
image key.png
x 333
y 0
x 338
y 5
}
q {
image key.png
x 0
y 36
x 5
y 41
}
w {
image key.png
x 37
y 36
x 42
y 41
}
e {
image key.png
x 74
y 36
x 79
y 41
}
r {
image key.png
x 111
y 36
x 116
y 41
}
t {
image key.png
x 148
y 36
x 153
y 41
}
y {
image key.png
x 185
y 36
x 190
y 41
}
u {
image key.png
x 222
y 36
x 227
y 41
}
i {
image key.png
x 259
y 36
x 264
y 41
}
o {
image key.png
x 296
y 36
x 301
y 41
}
p {
image key.png
x 333
y 36
x 338
y 41
}
a {
image key.png
x 0
y 72
x 5
y 77
}
s {
image key.png
x 37
y 72
x 42
y 77
}
d {
image key.png
x 74
y 72
x 79
y 77
}
f {
image key.png
x 111
y 72
x 116
y 77
}
g {
image key.png
x 148
y 72
x 153
y 77
}
h {
image key.png
x 185
y 72
x 190
y 77
}
j {
image key.png
x 222
y 72
x 227
y 77
}
k {
image key.png
x 259
y 72
x 264
y 77
}
l {
image key.png
x 296
y 72
x 301
y 77
}
DEL {
image key.png
x 333
y 72
x 338
y 77
}
CAP {
image key.png
x 0
y 108
x 5
y 113
}
z {
image key.png
x 37
y 108
x 42
y 113
}
x {
image key.png
x 74
y 108
x 79
y 113
}
c {
image key.png
x 111
y 108
x 116
y 113
}
v {
image key.png
x 148
y 108
x 153
y 113
}
b {
image key.png
x 185
y 108
x 190
y 113
}
n {
image key.png
x 222
y 108
x 227
y 113
}
m {
image key.png
x 259
y 108
x 264
y 113
}
PERIOD {
image key.png
x 296
y 108
x 301
y 113
}
ENTER {
image key.png
x 333
y 108
x 338
y 113
}
ALT {
image key.png
x 0
y 144
x 5
y 149
}
SYM {
image key.png
x 37
y 144
x 42
y 149
}
AT {
image key.png
x 74
y 144
x 79
y 149
}
SPACE {
image spacebar.png
x 111
y 144
x 116
y 149
}
SLASH {
image key.png
x 259
y 144
x 264
y 149
}
COMMA {
image key.png
x 296
y 144
x 301
y 149
}
ALT2 {
image key.png
x 333
y 144
x 338
y 149
}
}
@@ -333,39 +353,76 @@ parts {
layouts {
portrait {
width 900
height 730
width 791
height 534
color 0xe0e0e0
event EV_SW:0:1
part1 {
name device
x 40
y -18
name portrait
x 0
y 0
}
part2 {
name keyboard
x 480
y 200
name landscape
x 800
y 0
}
part3 {
name device
x 28
y 27
}
part4 {
name controls
x 476
y 77
}
part5 {
name keyboard
x 395
y 328
}
}
landscape {
width 900
height 670
width 640
height 601
color 0xe0e0e0
event EV_SW:0:0
part1 {
name portrait
x 800
y 0
}
part2 {
name landscape
x 0
y 0
}
part3 {
name device
x 50
y 440
x 80
y 349
rotation 3
}
part2 {
part4 {
name controls
x 410
y 396
}
part5 {
name keyboard
x 250
y 470
x 18
y 396
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 449 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 825 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 795 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -1,84 +1,104 @@
parts {
device {
portrait {
background {
image device.png
image background_port.png
}
}
landscape {
background {
image background_land.png
}
}
device {
display {
width 240
height 320
x 33
y 69
x 0
y 0
}
}
controls {
background {
image controls.png
}
buttons {
soft-left {
image menu.png
x 131
y 404
image button.png
x 56
y 142
}
home {
image home.png
x 77
y 404
image button.png
x 0
y 142
}
back {
image back.png
x 185
y 404
image button.png
x 112
y 142
}
dpad-up {
image arrow_up.png
x 105
y 463
x 77
y 53
}
dpad-down {
image arrow_down.png
x 104
y 519
x 77
y 106
}
dpad-left {
image arrow_left.png
x 96
y 470
x 53
y 53
}
dpad-right {
image arrow_right.png
x 172
y 470
x 123
y 53
}
dpad-center {
image select.png
x 131
y 492
x 77
y 81
}
phone-dial {
image send.png
x 23
y 404
image button.png
x 0
y 71
}
phone-hangup {
image end.png
x 238
y 404
image button.png
x 168
y 71
}
power {
image power.png
x -16
image button.png
x 168
y 0
}
volume-up {
image volume_up.png
x 289
y 177
image button.png
x 112
y 0
}
volume-down {
image volume_down.png
x 289
y 233
image button.png
x 56
y 0
}
search {
image button.png
x 168
y 142
}
}
}
@@ -89,242 +109,242 @@ parts {
buttons {
1 {
image key.png
x 0
y 0
x 5
y 5
}
2 {
image key.png
x 37
y 0
x 42
y 5
}
3 {
image key.png
x 74
y 0
x 79
y 5
}
4 {
image key.png
x 111
y 0
x 116
y 5
}
5 {
image key.png
x 148
y 0
x 153
y 5
}
6 {
image key.png
x 185
y 0
x 190
y 5
}
7 {
image key.png
x 222
y 0
x 227
y 5
}
8 {
image key.png
x 259
y 0
x 264
y 5
}
9 {
image key.png
x 296
y 0
x 301
y 5
}
0 {
image key.png
x 333
y 0
x 338
y 5
}
q {
image key.png
x 0
y 36
x 5
y 41
}
w {
image key.png
x 37
y 36
x 42
y 41
}
e {
image key.png
x 74
y 36
x 79
y 41
}
r {
image key.png
x 111
y 36
x 116
y 41
}
t {
image key.png
x 148
y 36
x 153
y 41
}
y {
image key.png
x 185
y 36
x 190
y 41
}
u {
image key.png
x 222
y 36
x 227
y 41
}
i {
image key.png
x 259
y 36
x 264
y 41
}
o {
image key.png
x 296
y 36
x 301
y 41
}
p {
image key.png
x 333
y 36
x 338
y 41
}
a {
image key.png
x 0
y 72
x 5
y 77
}
s {
image key.png
x 37
y 72
x 42
y 77
}
d {
image key.png
x 74
y 72
x 79
y 77
}
f {
image key.png
x 111
y 72
x 116
y 77
}
g {
image key.png
x 148
y 72
x 153
y 77
}
h {
image key.png
x 185
y 72
x 190
y 77
}
j {
image key.png
x 222
y 72
x 227
y 77
}
k {
image key.png
x 259
y 72
x 264
y 77
}
l {
image key.png
x 296
y 72
x 301
y 77
}
DEL {
image key.png
x 333
y 72
x 338
y 77
}
CAP {
image key.png
x 0
y 108
x 5
y 113
}
z {
image key.png
x 37
y 108
x 42
y 113
}
x {
image key.png
x 74
y 108
x 79
y 113
}
c {
image key.png
x 111
y 108
x 116
y 113
}
v {
image key.png
x 148
y 108
x 153
y 113
}
b {
image key.png
x 185
y 108
x 190
y 113
}
n {
image key.png
x 222
y 108
x 227
y 113
}
m {
image key.png
x 259
y 108
x 264
y 113
}
PERIOD {
image key.png
x 296
y 108
x 301
y 113
}
ENTER {
image key.png
x 333
y 108
x 338
y 113
}
ALT {
image key.png
x 0
y 144
x 5
y 149
}
SYM {
image key.png
x 37
y 144
x 42
y 149
}
AT {
image key.png
x 74
y 144
x 79
y 149
}
SPACE {
image spacebar.png
x 111
y 144
x 116
y 149
}
SLASH {
image key.png
x 259
y 144
x 264
y 149
}
COMMA {
image key.png
x 296
y 144
x 301
y 149
}
ALT2 {
image key.png
x 333
y 144
x 338
y 149
}
}
@@ -333,39 +353,75 @@ parts {
layouts {
portrait {
width 750
height 610
width 711
height 435
color 0xe0e0e0
event EV_SW:0:1
part1 {
name device
x 30
y 097
name portrait
x 0
y 0
}
part2 {
name keyboard
x 360
y 300
name landscape
x 800
y 0
}
part3 {
name device
x 28
y 58
}
part4 {
name controls
x 396
y 27
}
part5 {
name keyboard
x 315
y 229
}
}
landscape {
width 645
height 575
width 640
height 522
color 0xe0e0e0
event EV_SW:0:0
part1 {
name portrait
x 800
y 0
}
part2 {
name landscape
x 0
y 0
}
part3 {
name device
x 10
y 360
x 160
y 270
rotation 3
}
part2 {
part4 {
name controls
x 410
y 317
}
part5 {
name keyboard
x 135
y 380
x 18
y 317
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 835 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 449 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 825 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 795 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -0,0 +1,2 @@
# skin-specific hardware values
hw.lcd.density=120

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -0,0 +1,436 @@
parts {
portrait {
background {
image background_port.png
}
}
landscape {
background {
image background_land.png
}
}
device {
display {
width 240
height 432
x 0
y 0
}
}
controls {
background {
image controls.png
}
buttons {
soft-left {
image button.png
x 56
y 142
}
home {
image button.png
x 0
y 142
}
back {
image button.png
x 112
y 142
}
dpad-up {
image arrow_up.png
x 77
y 53
}
dpad-down {
image arrow_down.png
x 77
y 106
}
dpad-left {
image arrow_left.png
x 53
y 53
}
dpad-right {
image arrow_right.png
x 123
y 53
}
dpad-center {
image select.png
x 77
y 81
}
phone-dial {
image button.png
x 0
y 71
}
phone-hangup {
image button.png
x 168
y 71
}
power {
image button.png
x 168
y 0
}
volume-up {
image button.png
x 112
y 0
}
volume-down {
image button.png
x 56
y 0
}
search {
image button.png
x 168
y 142
}
}
}
keyboard {
background {
image keyboard.png
}
buttons {
1 {
image key.png
x 5
y 5
}
2 {
image key.png
x 42
y 5
}
3 {
image key.png
x 79
y 5
}
4 {
image key.png
x 116
y 5
}
5 {
image key.png
x 153
y 5
}
6 {
image key.png
x 190
y 5
}
7 {
image key.png
x 227
y 5
}
8 {
image key.png
x 264
y 5
}
9 {
image key.png
x 301
y 5
}
0 {
image key.png
x 338
y 5
}
q {
image key.png
x 5
y 41
}
w {
image key.png
x 42
y 41
}
e {
image key.png
x 79
y 41
}
r {
image key.png
x 116
y 41
}
t {
image key.png
x 153
y 41
}
y {
image key.png
x 190
y 41
}
u {
image key.png
x 227
y 41
}
i {
image key.png
x 264
y 41
}
o {
image key.png
x 301
y 41
}
p {
image key.png
x 338
y 41
}
a {
image key.png
x 5
y 77
}
s {
image key.png
x 42
y 77
}
d {
image key.png
x 79
y 77
}
f {
image key.png
x 116
y 77
}
g {
image key.png
x 153
y 77
}
h {
image key.png
x 190
y 77
}
j {
image key.png
x 227
y 77
}
k {
image key.png
x 264
y 77
}
l {
image key.png
x 301
y 77
}
DEL {
image key.png
x 338
y 77
}
CAP {
image key.png
x 5
y 113
}
z {
image key.png
x 42
y 113
}
x {
image key.png
x 79
y 113
}
c {
image key.png
x 116
y 113
}
v {
image key.png
x 153
y 113
}
b {
image key.png
x 190
y 113
}
n {
image key.png
x 227
y 113
}
m {
image key.png
x 264
y 113
}
PERIOD {
image key.png
x 301
y 113
}
ENTER {
image key.png
x 338
y 113
}
ALT {
image key.png
x 5
y 149
}
SYM {
image key.png
x 42
y 149
}
AT {
image key.png
x 79
y 149
}
SPACE {
image spacebar.png
x 116
y 149
}
SLASH {
image key.png
x 264
y 149
}
COMMA {
image key.png
x 301
y 149
}
ALT2 {
image key.png
x 338
y 149
}
}
}
}
layouts {
portrait {
width 711
height 486
color 0xe0e0e0
event EV_SW:0:1
part1 {
name portrait
x 0
y 0
}
part2 {
name landscape
x 800
y 0
}
part3 {
name device
x 28
y 27
}
part4 {
name controls
x 396
y 53
}
part5 {
name keyboard
x 315
y 280
}
}
landscape {
width 640
height 522
color 0xe0e0e0
event EV_SW:0:0
part1 {
name portrait
x 800
y 0
}
part2 {
name landscape
x 0
y 0
}
part3 {
name device
x 104
y 270
rotation 3
}
part4 {
name controls
x 410
y 317
}
part5 {
name keyboard
x 18
y 317
}
}
}
keyboard {
charmap qwerty2
}
network {
speed full
delay none
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Some files were not shown because too many files have changed in this diff Show More