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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -31,6 +31,7 @@ bin/sqlite3 tools/sqlite3
bin/dmtracedump tools/dmtracedump bin/dmtracedump tools/dmtracedump
bin/hprof-conv tools/hprof-conv bin/hprof-conv tools/hprof-conv
bin/mksdcard tools/mksdcard bin/mksdcard tools/mksdcard
bin/zipalign tools/zipalign
# the uper-jar file that apps link against # the uper-jar file that apps link against
out/target/common/obj/PACKAGING/android_jar_intermediates/android.jar platforms/${PLATFORM_NAME}/android.jar 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.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.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/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 sdk/sdk-build.prop platforms/${PLATFORM_NAME}/build.prop
development/tools/scripts/plugin.prop tools/lib/plugin.prop development/tools/scripts/plugin.prop tools/lib/plugin.prop
@@ -49,7 +50,6 @@ obj/framework.aidl platforms/${PLATFORM_NAME}/framework.aidl
# sdk scripts # sdk scripts
development/tools/scripts/AndroidManifest.template platforms/${PLATFORM_NAME}/templates/AndroidManifest.template 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/AndroidManifest.tests.template platforms/${PLATFORM_NAME}/templates/AndroidManifest.tests.template
development/tools/scripts/iml.template platforms/${PLATFORM_NAME}/templates/iml.template development/tools/scripts/iml.template platforms/${PLATFORM_NAME}/templates/iml.template
development/tools/scripts/ipr.template platforms/${PLATFORM_NAME}/templates/ipr.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/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/layout.template platforms/${PLATFORM_NAME}/templates/layout.template
development/tools/scripts/strings.template platforms/${PLATFORM_NAME}/templates/strings.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/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.template tools/lib/build.template
development/tools/scripts/build.alias.template tools/lib/build.alias.template
# emacs support # emacs support
development/tools/scripts/android.el tools/lib/android.el 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/Snake platforms/${PLATFORM_NAME}/samples/Snake
development/samples/SoftKeyboard platforms/${PLATFORM_NAME}/samples/SoftKeyboard development/samples/SoftKeyboard platforms/${PLATFORM_NAME}/samples/SoftKeyboard
development/samples/JetBoy platforms/${PLATFORM_NAME}/samples/JetBoy development/samples/JetBoy platforms/${PLATFORM_NAME}/samples/JetBoy
development/samples/SearchableDictionary platforms/${PLATFORM_NAME}/samples/SearchableDictionary
# dx # dx
bin/dx platforms/${PLATFORM_NAME}/tools/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 external/qemu/android/avd/hardware-properties.ini tools/lib/hardware-properties.ini
# emulator skins # emulator skins
development/emulator/skins/HVGA platforms/${PLATFORM_NAME}/skins/HVGA development/emulator/skins/HVGA platforms/${PLATFORM_NAME}/skins/HVGA
development/emulator/skins/QVGA platforms/${PLATFORM_NAME}/skins/QVGA development/emulator/skins/QVGA platforms/${PLATFORM_NAME}/skins/QVGA
development/emulator/skins/WVGA platforms/${PLATFORM_NAME}/skins/WVGA 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 # NOTICE files are copied by build/core/Makefile
development/tools/scripts/sdk_files_NOTICE.txt platforms/${PLATFORM_NAME}/templates/NOTICE.txt 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" TEMP_DIR="$3"
[ -z "$TEMP_DIR" ] && TEMP_DIR=${TMP:-/tmp} [ -z "$TEMP_DIR" ] && TEMP_DIR=${TMP:-/tmp}
function die() { function die() {
echo "Error:" $* echo "Error:" $*
echo "Aborting" echo "Aborting"
exit 1 exit 1
} }
function usage() { function usage() {
echo "Usage: ${PROG_NAME} linux_or_mac_sdk.zip output_dir [temp_dir]" local NAME
echo "If temp_dir is not given, \$TMP is used. If that's missing, /tmp is used." NAME=`basename ${PROG_NAME}`
status echo "Usage: ${NAME} linux_or_mac_sdk.zip output_dir [temp_dir]"
exit 2 echo "If temp_dir is not given, \$TMP is used. If that's missing, /tmp is used."
status
exit 2
} }
function status() { function status() {
echo "Current values:" echo "Current values:"
echo "- Input SDK: ${SDK_ZIP:-missing}" echo "- Input SDK: ${SDK_ZIP:-missing}"
echo "- Output dir: ${DIST_DIR:-missing}" echo "- Output dir: ${DIST_DIR:-missing}"
echo "- Temp dir: ${TEMP_DIR:-missing}" echo "- Temp dir: ${TEMP_DIR:-missing}"
} }
function check() { function check() {
@@ -92,7 +93,14 @@ function build() {
make -j 4 emulator || die "Build failed" make -j 4 emulator || die "Build failed"
# Disable parallel build: it generates "permission denied" issues when # Disable parallel build: it generates "permission denied" issues when
# multiple "ar.exe" are running in parallel. # 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" || die "Build failed"
} }
@@ -124,12 +132,16 @@ function package() {
"Instead found " $THE_PLATFORM "Instead found " $THE_PLATFORM
[[ -d "$PLATFORM_TOOLS" ]] || die "Missing folder $PLATFORM_TOOLS." [[ -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 # Remove obsolete stuff from tools & platform
TOOLS="$TEMP_SDK_DIR/tools" TOOLS="$TEMP_SDK_DIR/tools"
LIB="$TEMP_SDK_DIR/tools/lib" LIB="$TEMP_SDK_DIR/tools/lib"
rm -v "$TOOLS"/{adb,android,apkbuilder,ddms,dmtracedump,draw9patch,emulator} 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 "$LIB"/*/swt.jar
rm -v "$PLATFORM_TOOLS"/{aapt,aidl,dx,dexdump} rm -v "$PLATFORM_TOOLS"/{aapt,aidl,dx,dexdump}
@@ -183,8 +195,9 @@ function package() {
# Copy or move platform specific tools to the default platform. # Copy or move platform specific tools to the default platform.
cp -v dalvik/dx/etc/dx.bat "$PLATFORM_TOOLS"/ 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} "$PLATFORM_TOOLS"/
mv -v "$TOOLS"/{aapt.exe,aidl.exe,dexdump.exe,mgwz.dll} "$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 # 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/ # 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 # 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" 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 "Done"
echo echo
echo "Resulting SDK is in $DIST_DIR/$DEST_NAME_ZIP" 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 check

View File

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

View File

@@ -22,7 +22,7 @@ import android.view.IWindowManager;
/** /**
* abstract class for monkey event * abstract class for monkey event
*/ */
public abstract class MonkeyEvent { public abstract class MonkeyEvent {
protected int eventType; protected int eventType;
public static final int EVENT_TYPE_KEY = 0; public static final int EVENT_TYPE_KEY = 0;
public static final int EVENT_TYPE_POINTER = 1; 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_ACTIVITY = 3;
public static final int EVENT_TYPE_FLIP = 4; // Keyboard flip public static final int EVENT_TYPE_FLIP = 4; // Keyboard flip
public static final int EVENT_TYPE_THROTTLE = 5; 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_SUCCESS = 1;
public static final int INJECT_FAIL = 0; public static final int INJECT_FAIL = 0;
// error code for remote exception during injection // 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 // error code for security exception during injection
public static final int INJECT_ERROR_SECURITY_EXCEPTION = -2; public static final int INJECT_ERROR_SECURITY_EXCEPTION = -2;
public MonkeyEvent(int type) { public MonkeyEvent(int type) {
eventType = type; eventType = type;
} }
/** /**
* @return event type * @return event type
*/ */
public int getEventType() { public int getEventType() {
return eventType; return eventType;
} }
/** /**
* @return true if it is safe to throttle after this event, and false otherwise. * @return true if it is safe to throttle after this event, and false otherwise.
*/ */
public boolean isThrottlable() { public boolean isThrottlable() {
return true; return true;
} }
/** /**
* a method for injecting event * a method for injecting event
* @param iwm wires to current window manager * @param iwm wires to current window manager
* @param iam wires to current activity 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 * @return INJECT_SUCCESS if it goes through, and INJECT_FAIL if it fails
* in the case of exceptions, return its corresponding error code * 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 * monkey key event
*/ */
public class MonkeyKeyEvent extends MonkeyEvent { public class MonkeyKeyEvent extends MonkeyEvent {
private long mDownTime = -1; private long mDownTime = -1;
private int mMetaState = -1; private int mMetaState = -1;
private int mAction = -1; private int mAction = -1;
@@ -32,18 +32,25 @@ public class MonkeyKeyEvent extends MonkeyEvent {
private int mRepeatCount = -1; private int mRepeatCount = -1;
private int mDeviceId = -1; private int mDeviceId = -1;
private long mEventTime = -1; private long mEventTime = -1;
private KeyEvent keyEvent = null;
public MonkeyKeyEvent(int action, int keycode) { public MonkeyKeyEvent(int action, int keycode) {
super(EVENT_TYPE_KEY); super(EVENT_TYPE_KEY);
mAction = action; mAction = action;
mKeyCode = keycode; mKeyCode = keycode;
} }
public MonkeyKeyEvent(KeyEvent e) {
super(EVENT_TYPE_KEY);
keyEvent = e;
}
public MonkeyKeyEvent(long downTime, long eventTime, int action, public MonkeyKeyEvent(long downTime, long eventTime, int action,
int code, int repeat, int metaState, int code, int repeat, int metaState,
int device, int scancode) { int device, int scancode) {
super(EVENT_TYPE_KEY); super(EVENT_TYPE_KEY);
mAction = action; mAction = action;
mKeyCode = code; mKeyCode = code;
mMetaState = metaState; mMetaState = metaState;
@@ -53,49 +60,52 @@ public class MonkeyKeyEvent extends MonkeyEvent {
mDownTime = downTime; mDownTime = downTime;
mEventTime = eventTime; mEventTime = eventTime;
} }
public int getKeyCode() { public int getKeyCode() {
return mKeyCode; return mKeyCode;
} }
public int getAction() { public int getAction() {
return mAction; return mAction;
} }
public long getDownTime() { public long getDownTime() {
return mDownTime; return mDownTime;
} }
public long getEventTime() { public long getEventTime() {
return mEventTime; return mEventTime;
} }
public void setDownTime(long downTime) { public void setDownTime(long downTime) {
mDownTime = downTime; mDownTime = downTime;
} }
public void setEventTime(long eventTime) { public void setEventTime(long eventTime) {
mEventTime = eventTime; mEventTime = eventTime;
} }
/** /**
* @return the key event * @return the key event
*/ */
private KeyEvent getEvent() { private KeyEvent getEvent() {
if (mDeviceId < 0) { if (keyEvent == null) {
return new KeyEvent(mAction, mKeyCode); if (mDeviceId < 0) {
} keyEvent = new KeyEvent(mAction, mKeyCode);
} else {
// for scripts // for scripts
return new KeyEvent(mDownTime, mEventTime, mAction, keyEvent = new KeyEvent(mDownTime, mEventTime, mAction,
mKeyCode, mRepeatCount, mMetaState, mDeviceId, mScancode); mKeyCode, mRepeatCount, mMetaState, mDeviceId, mScancode);
}
}
return keyEvent;
} }
@Override @Override
public boolean isThrottlable() { public boolean isThrottlable() {
return (getAction() == KeyEvent.ACTION_UP); return (getAction() == KeyEvent.ACTION_UP);
} }
@Override @Override
public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) { public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
if (verbose > 1) { if (verbose > 1) {
@@ -124,7 +134,7 @@ public class MonkeyKeyEvent extends MonkeyEvent {
} catch (RemoteException ex) { } catch (RemoteException ex) {
return MonkeyEvent.INJECT_ERROR_REMOTE_EXCEPTION; return MonkeyEvent.INJECT_ERROR_REMOTE_EXCEPTION;
} }
return MonkeyEvent.INJECT_SUCCESS; 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 * monkey event queue
*/ */
public class MonkeySourceRandom implements MonkeyEventSource { public class MonkeySourceRandom implements MonkeyEventSource {
/** Key events that move around the UI. */ /** Key events that move around the UI. */
private static final int[] NAV_KEYS = { private static final int[] NAV_KEYS = {
KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN,
@@ -55,7 +55,7 @@ public class MonkeySourceRandom implements MonkeyEventSource {
/** Nice names for all key events. */ /** Nice names for all key events. */
private static final String[] KEY_NAMES = { private static final String[] KEY_NAMES = {
"KEYCODE_UNKNOWN", "KEYCODE_UNKNOWN",
"KEYCODE_MENU", "KEYCODE_SOFT_LEFT",
"KEYCODE_SOFT_RIGHT", "KEYCODE_SOFT_RIGHT",
"KEYCODE_HOME", "KEYCODE_HOME",
"KEYCODE_BACK", "KEYCODE_BACK",
@@ -146,7 +146,7 @@ public class MonkeySourceRandom implements MonkeyEventSource {
"KEYCODE_REWIND", "KEYCODE_REWIND",
"KEYCODE_FORWARD", "KEYCODE_FORWARD",
"KEYCODE_MUTE", "KEYCODE_MUTE",
"TAG_LAST_KEYCODE" // EOL. used to keep the lists in sync "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_SYSOPS = 5;
public static final int FACTOR_APPSWITCH = 6; public static final int FACTOR_APPSWITCH = 6;
public static final int FACTOR_FLIP = 7; 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 public static final int FACTORZ_COUNT = 9; // should be last+1
/** percentages for each type of event. These will be remapped to working /** percentages for each type of event. These will be remapped to working
* values after we read any optional values. * values after we read any optional values.
**/ **/
private float[] mFactors = new float[FACTORZ_COUNT]; private float[] mFactors = new float[FACTORZ_COUNT];
private ArrayList<ComponentName> mMainApps; private ArrayList<ComponentName> mMainApps;
private int mEventCount = 0; //total number of events generated so far private int mEventCount = 0; //total number of events generated so far
private MonkeyEventQueue mQ; private MonkeyEventQueue mQ;
private Random mRandom; private Random mRandom;
private int mVerbose = 0; private int mVerbose = 0;
private long mThrottle = 0; private long mThrottle = 0;
private boolean mKeyboardOpen = false; private boolean mKeyboardOpen = false;
/** /**
* @return the last name in the key list * @return the last name in the key list
*/ */
public static String getLastKeyName() { public static String getLastKeyName() {
return KEY_NAMES[KeyEvent.getMaxKeyCode() + 1]; return KEY_NAMES[KeyEvent.getMaxKeyCode() + 1];
} }
public static String getKeyName(int keycode) { public static String getKeyName(int keycode) {
return KEY_NAMES[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) { public MonkeySourceRandom(long seed, ArrayList<ComponentName> MainApps, long throttle) {
// default values for random distributions // default values for random distributions
// note, these are straight percentages, to match user input (cmd line args) // 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_APPSWITCH] = 2.0f;
mFactors[FACTOR_FLIP] = 1.0f; mFactors[FACTOR_FLIP] = 1.0f;
mFactors[FACTOR_ANYTHING] = 15.0f; mFactors[FACTOR_ANYTHING] = 15.0f;
mRandom = new SecureRandom(); mRandom = new SecureRandom();
mRandom.setSeed((seed == 0) ? -1 : seed); mRandom.setSeed((seed == 0) ? -1 : seed);
mMainApps = MainApps; mMainApps = MainApps;
@@ -220,25 +236,25 @@ public class MonkeySourceRandom implements MonkeyEventSource {
} else { } else {
defaultSum += mFactors[i]; defaultSum += mFactors[i];
++defaultCount; ++defaultCount;
} }
} }
// if the user request was > 100%, reject it // if the user request was > 100%, reject it
if (userSum > 100.0f) { if (userSum > 100.0f) {
System.err.println("** Event weights > 100%"); System.err.println("** Event weights > 100%");
return false; return false;
} }
// if the user specified all of the weights, then they need to be 100% // if the user specified all of the weights, then they need to be 100%
if (defaultCount == 0 && (userSum < 99.9f || userSum > 100.1f)) { if (defaultCount == 0 && (userSum < 99.9f || userSum > 100.1f)) {
System.err.println("** Event weights != 100%"); System.err.println("** Event weights != 100%");
return false; return false;
} }
// compute the adjustment necessary // compute the adjustment necessary
float defaultsTarget = (100.0f - userSum); float defaultsTarget = (100.0f - userSum);
float defaultsAdjustment = defaultsTarget / defaultSum; float defaultsAdjustment = defaultsTarget / defaultSum;
// fix all values, by adjusting defaults, or flipping user values back to >0 // fix all values, by adjusting defaults, or flipping user values back to >0
for (int i = 0; i < FACTORZ_COUNT; ++i) { for (int i = 0; i < FACTORZ_COUNT; ++i) {
if (mFactors[i] <= 0.0f) { // user values are zero or negative if (mFactors[i] <= 0.0f) { // user values are zero or negative
@@ -247,46 +263,46 @@ public class MonkeySourceRandom implements MonkeyEventSource {
mFactors[i] *= defaultsAdjustment; mFactors[i] *= defaultsAdjustment;
} }
} }
// if verbose, show factors // if verbose, show factors
if (mVerbose > 0) { if (mVerbose > 0) {
System.out.println("// Event percentages:"); System.out.println("// Event percentages:");
for (int i = 0; i < FACTORZ_COUNT; ++i) { for (int i = 0; i < FACTORZ_COUNT; ++i) {
System.out.println("// " + i + ": " + mFactors[i] + "%"); System.out.println("// " + i + ": " + mFactors[i] + "%");
} }
} }
// finally, normalize and convert to running sum // finally, normalize and convert to running sum
float sum = 0.0f; float sum = 0.0f;
for (int i = 0; i < FACTORZ_COUNT; ++i) { for (int i = 0; i < FACTORZ_COUNT; ++i) {
sum += mFactors[i] / 100.0f; sum += mFactors[i] / 100.0f;
mFactors[i] = sum; mFactors[i] = sum;
} }
return true; return true;
} }
/** /**
* set the factors * set the factors
* *
* @param factors: percentages for each type of event * @param factors: percentages for each type of event
*/ */
public void setFactors(float factors[]) { public void setFactors(float factors[]) {
int c = FACTORZ_COUNT; int c = FACTORZ_COUNT;
if (factors.length < c) { if (factors.length < c) {
c = factors.length; c = factors.length;
} }
for (int i = 0; i < c; i++) for (int i = 0; i < c; i++)
mFactors[i] = factors[i]; mFactors[i] = factors[i];
} }
public void setFactors(int index, float v) { public void setFactors(int index, float v) {
mFactors[index] = v; mFactors[index] = v;
} }
/** /**
* Generates a random motion event. This method counts a down, move, and up as multiple events. * 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: Test & fix the selectors when non-zero percentages
* TODO: Longpress. * TODO: Longpress.
* TODO: Fling. * 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 * 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 * and distance, and divvy it up into a random number of segments. (This would serve to
* generate fling gestures, which are important). * generate fling gestures, which are important).
* *
* @param random Random number source for positioning * @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){ private void generateMotionEvent(Random random, boolean motionEvent){
Display display = WindowManagerImpl.getDefault().getDefaultDisplay(); Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
float x = Math.abs(random.nextInt() % display.getWidth()); float x = Math.abs(random.nextInt() % display.getWidth());
@@ -310,12 +326,12 @@ public class MonkeySourceRandom implements MonkeyEventSource {
if (downAt == -1) { if (downAt == -1) {
downAt = eventTime; downAt = eventTime;
} }
MonkeyMotionEvent e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER, MonkeyMotionEvent e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER,
downAt, MotionEvent.ACTION_DOWN, x, y, 0); downAt, MotionEvent.ACTION_DOWN, x, y, 0);
e.setIntermediateNote(false); e.setIntermediateNote(false);
mQ.addLast(e); mQ.addLast(e);
// sometimes we'll move during the touch // sometimes we'll move during the touch
if (motionEvent) { if (motionEvent) {
int count = random.nextInt(10); int count = random.nextInt(10);
@@ -323,34 +339,34 @@ public class MonkeySourceRandom implements MonkeyEventSource {
// generate some slop in the up event // generate some slop in the up event
x = (x + (random.nextInt() % 10)) % display.getWidth(); x = (x + (random.nextInt() % 10)) % display.getWidth();
y = (y + (random.nextInt() % 10)) % display.getHeight(); y = (y + (random.nextInt() % 10)) % display.getHeight();
e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER, e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER,
downAt, MotionEvent.ACTION_MOVE, x, y, 0); downAt, MotionEvent.ACTION_MOVE, x, y, 0);
e.setIntermediateNote(true); e.setIntermediateNote(true);
mQ.addLast(e); mQ.addLast(e);
} }
} }
// TODO generate some slop in the up event // TODO generate some slop in the up event
e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER, e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER,
downAt, MotionEvent.ACTION_UP, x, y, 0); downAt, MotionEvent.ACTION_UP, x, y, 0);
e.setIntermediateNote(false); e.setIntermediateNote(false);
mQ.addLast(e); mQ.addLast(e);
} }
/** /**
* Generates a random trackball event. This consists of a sequence of small moves, followed by * Generates a random trackball event. This consists of a sequence of small moves, followed by
* an optional single click. * an optional single click.
* *
* TODO: Longpress. * TODO: Longpress.
* TODO: Meta state * TODO: Meta state
* TODO: Parameterize the % clicked * TODO: Parameterize the % clicked
* TODO: More useful than the random walk here would be to pick a single random direction * 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 * and distance, and divvy it up into a random number of segments. (This would serve to
* generate fling gestures, which are important). * generate fling gestures, which are important).
* *
* @param random Random number source for positioning * @param random Random number source for positioning
* *
*/ */
private void generateTrackballEvent(Random random) { private void generateTrackballEvent(Random random) {
Display display = WindowManagerImpl.getDefault().getDefaultDisplay(); Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
@@ -362,47 +378,47 @@ public class MonkeySourceRandom implements MonkeyEventSource {
// generate a small random step // generate a small random step
int dX = random.nextInt(10) - 5; int dX = random.nextInt(10) - 5;
int dY = random.nextInt(10) - 5; int dY = random.nextInt(10) - 5;
e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, -1, e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, -1,
MotionEvent.ACTION_MOVE, dX, dY, 0); MotionEvent.ACTION_MOVE, dX, dY, 0);
e.setIntermediateNote(i > 0); e.setIntermediateNote(i > 0);
mQ.addLast(e); mQ.addLast(e);
} }
// 10% of trackball moves end with a click // 10% of trackball moves end with a click
if (0 == random.nextInt(10)) { if (0 == random.nextInt(10)) {
long downAt = SystemClock.uptimeMillis(); long downAt = SystemClock.uptimeMillis();
e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, downAt, e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, downAt,
MotionEvent.ACTION_DOWN, 0, 0, 0); MotionEvent.ACTION_DOWN, 0, 0, 0);
e.setIntermediateNote(true); e.setIntermediateNote(true);
mQ.addLast(e); mQ.addLast(e);
e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, downAt, e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, downAt,
MotionEvent.ACTION_UP, 0, 0, 0); MotionEvent.ACTION_UP, 0, 0, 0);
e.setIntermediateNote(false); e.setIntermediateNote(false);
mQ.addLast(e); mQ.addLast(e);
} }
} }
/** /**
* generate a random event based on mFactor * generate a random event based on mFactor
*/ */
private void generateEvents() { private void generateEvents() {
float cls = mRandom.nextFloat(); float cls = mRandom.nextFloat();
int lastKey = 0; int lastKey = 0;
boolean touchEvent = cls < mFactors[FACTOR_TOUCH]; boolean touchEvent = cls < mFactors[FACTOR_TOUCH];
boolean motionEvent = !touchEvent && (cls < mFactors[FACTOR_MOTION]); boolean motionEvent = !touchEvent && (cls < mFactors[FACTOR_MOTION]);
if (touchEvent || motionEvent) { if (touchEvent || motionEvent) {
generateMotionEvent(mRandom, motionEvent); generateMotionEvent(mRandom, motionEvent);
return; return;
} }
if (cls < mFactors[FACTOR_TRACKBALL]) { if (cls < mFactors[FACTOR_TRACKBALL]) {
generateTrackballEvent(mRandom); generateTrackballEvent(mRandom);
return; return;
} }
@@ -427,23 +443,23 @@ public class MonkeySourceRandom implements MonkeyEventSource {
} else { } else {
lastKey = 1 + mRandom.nextInt(KeyEvent.getMaxKeyCode() - 1); lastKey = 1 + mRandom.nextInt(KeyEvent.getMaxKeyCode() - 1);
} }
MonkeyKeyEvent e = new MonkeyKeyEvent(KeyEvent.ACTION_DOWN, lastKey); MonkeyKeyEvent e = new MonkeyKeyEvent(KeyEvent.ACTION_DOWN, lastKey);
mQ.addLast(e); mQ.addLast(e);
e = new MonkeyKeyEvent(KeyEvent.ACTION_UP, lastKey); e = new MonkeyKeyEvent(KeyEvent.ACTION_UP, lastKey);
mQ.addLast(e); mQ.addLast(e);
} }
public boolean validate() { public boolean validate() {
//check factors //check factors
return adjustEventFactors(); return adjustEventFactors();
} }
public void setVerbose(int verbose) { public void setVerbose(int verbose) {
mVerbose = verbose; mVerbose = verbose;
} }
/** /**
* generate an activity event * generate an activity event
*/ */
@@ -452,18 +468,18 @@ public class MonkeySourceRandom implements MonkeyEventSource {
mRandom.nextInt(mMainApps.size()))); mRandom.nextInt(mMainApps.size())));
mQ.addLast(e); mQ.addLast(e);
} }
/** /**
* if the queue is empty, we generate events first * 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() { public MonkeyEvent getNextEvent() {
if (mQ.isEmpty()) { if (mQ.isEmpty()) {
generateEvents(); generateEvents();
} }
mEventCount++; mEventCount++;
MonkeyEvent e = mQ.getFirst(); MonkeyEvent e = mQ.getFirst();
mQ.removeFirst(); mQ.removeFirst();
return e; return e;
} }
} }

View File

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