am 1448b0b7: Remove emulator-based dexpreopt code
Merge commit '1448b0b7023a43ff4461cc66d25230c9b6502724' into gingerbread-plus-aosp
* commit '1448b0b7023a43ff4461cc66d25230c9b6502724':
Remove emulator-based dexpreopt code
diff --git a/tools/dexpreopt/Android.mk b/tools/dexpreopt/Android.mk
deleted file mode 100644
index 40aeee2..0000000
--- a/tools/dexpreopt/Android.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-#
-# Copyright (C) 2008 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.
-#
-ifneq ($(TARGET_SIMULATOR),true)
-ifneq ($(DISABLE_DEXPREOPT),true)
-
-LOCAL_PATH := $(my-dir)
-include $(CLEAR_VARS)
-LOCAL_PREBUILT_EXECUTABLES := dexpreopt.py
-include $(BUILD_SYSTEM)/host_prebuilt.mk
-DEXPREOPT := $(LOCAL_INSTALLED_MODULE)
-
-# The script uses some other tools; make sure that they're
-# installed along with it.
-tools := \
- emulator$(HOST_EXECUTABLE_SUFFIX)
-
-$(DEXPREOPT): | $(addprefix $(HOST_OUT_EXECUTABLES)/,$(tools))
-
-subdir_makefiles := \
- $(LOCAL_PATH)/dexopt-wrapper/Android.mk \
- $(LOCAL_PATH)/afar/Android.mk
-include $(subdir_makefiles)
-
-endif # !disable_dexpreopt
-endif # !sim
diff --git a/tools/dexpreopt/Config.mk b/tools/dexpreopt/Config.mk
deleted file mode 100644
index b2b32c6..0000000
--- a/tools/dexpreopt/Config.mk
+++ /dev/null
@@ -1,153 +0,0 @@
-#
-# Copyright (C) 2008 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.
-#
-
-#
-# Included by config/Makefile.
-# Defines the pieces necessary for the dexpreopt process.
-#
-# inputs: INSTALLED_RAMDISK_TARGET, BUILT_SYSTEMIMAGE_UNOPT
-# outputs: BUILT_SYSTEMIMAGE, SYSTEMIMAGE_SOURCE_DIR
-#
-LOCAL_PATH := $(my-dir)
-
-# TODO: see if we can make the .odex files not be product-specific.
-# They can't be completely common, though, because their format
-# depends on the architecture of the target system; ARM and x86
-# would have different versions.
-intermediates := \
- $(call intermediates-dir-for,PACKAGING,dexpreopt)
-dexpreopt_system_dir := $(intermediates)/system
-built_afar := $(call intermediates-dir-for,EXECUTABLES,afar)/afar
-built_dowrapper := \
- $(call intermediates-dir-for,EXECUTABLES,dexopt-wrapper)/dexopt-wrapper
-
-# Generate a stripped-down init.rc based on the real one.
-dexpreopt_initrc := $(intermediates)/etc/init.rc
-geninitrc_script := $(LOCAL_PATH)/geninitrc.awk
-$(dexpreopt_initrc): script := $(geninitrc_script)
-$(dexpreopt_initrc): system/core/rootdir/init.rc $(geninitrc_script)
- @echo "Dexpreopt init.rc: $@"
- @mkdir -p $(dir $@)
- $(hide) awk -f $(script) < $< > $@
-
-BUILT_DEXPREOPT_RAMDISK := $(intermediates)/ramdisk.img
-$(BUILT_DEXPREOPT_RAMDISK): intermediates := $(intermediates)
-$(BUILT_DEXPREOPT_RAMDISK): dexpreopt_root_out := $(intermediates)/root
-$(BUILT_DEXPREOPT_RAMDISK): dexpreopt_initrc := $(dexpreopt_initrc)
-$(BUILT_DEXPREOPT_RAMDISK): built_afar := $(built_afar)
-$(BUILT_DEXPREOPT_RAMDISK): built_dowrapper := $(built_dowrapper)
-$(BUILT_DEXPREOPT_RAMDISK): \
- $(INSTALLED_RAMDISK_TARGET) \
- $(dexpreopt_initrc) \
- $(built_afar) \
- $(built_dowrapper) \
- | $(MKBOOTFS) $(ACP)
-$(BUILT_DEXPREOPT_RAMDISK):
- @echo "Dexpreopt ramdisk: $@"
- $(hide) rm -f $@
- $(hide) rm -rf $(dexpreopt_root_out)
- $(hide) mkdir -p $(dexpreopt_root_out)
- $(hide) $(ACP) -rd $(TARGET_ROOT_OUT) $(intermediates)
- $(hide) $(ACP) -f $(dexpreopt_initrc) $(dexpreopt_root_out)/
- $(hide) $(ACP) $(built_afar) $(dexpreopt_root_out)/sbin/
- $(hide) $(ACP) $(built_dowrapper) $(dexpreopt_root_out)/sbin/
- $(MKBOOTFS) $(dexpreopt_root_out) | gzip > $@
-
-sign_dexpreopt := true
-ifdef sign_dexpreopt
- # Such a huge hack. We need to re-sign the .apks with the
- # same certs that they were originally signed with.
- dexpreopt_package_certs_file := $(intermediates)/package-certs
- $(shell mkdir -p $(intermediates))
- $(shell rm -f $(dexpreopt_package_certs_file))
- $(foreach p,$(PACKAGES),\
- $(shell echo "$(p) $(PACKAGES.$(p).CERTIFICATE) $(PACKAGES.$(p).PRIVATE_KEY)" >> $(dexpreopt_package_certs_file)))
-endif
-
-# The kernel used for ARMv7 system images is different
-ifeq ($(ARCH_ARM_HAVE_ARMV7A),true)
-BUILD_DEXPREOPT_KERNEL := prebuilt/android-arm/kernel/kernel-qemu-armv7
-else
-BUILD_DEXPREOPT_KERNEL := prebuilt/android-arm/kernel/kernel-qemu
-endif
-
-# Build an optimized image from the unoptimized image
-BUILT_DEXPREOPT_SYSTEMIMAGE := $(intermediates)/system.img
-$(BUILT_DEXPREOPT_SYSTEMIMAGE): $(BUILT_SYSTEMIMAGE_UNOPT)
-$(BUILT_DEXPREOPT_SYSTEMIMAGE): $(BUILT_DEXPREOPT_RAMDISK)
-$(BUILT_DEXPREOPT_SYSTEMIMAGE): | $(DEXPREOPT) $(ACP) $(ZIPALIGN)
-$(BUILT_DEXPREOPT_SYSTEMIMAGE): SYSTEM_DIR := $(dexpreopt_system_dir)
-$(BUILT_DEXPREOPT_SYSTEMIMAGE): DEXPREOPT_TMP := $(intermediates)/emutmp
-ifdef sign_dexpreopt
-$(BUILT_DEXPREOPT_SYSTEMIMAGE): | $(SIGNAPK_JAR)
-endif
-$(BUILT_DEXPREOPT_SYSTEMIMAGE):
- @rm -f $@
- @echo "dexpreopt: copy system to $(SYSTEM_DIR)"
- @rm -rf $(SYSTEM_DIR)
- @mkdir -p $(dir $(SYSTEM_DIR))
- $(hide) $(ACP) -rd $(TARGET_OUT) $(SYSTEM_DIR)
- @echo "dexpreopt: optimize dex files"
- @rm -rf $(DEXPREOPT_TMP)
- @mkdir -p $(DEXPREOPT_TMP)
- $(hide) \
- PATH=$(HOST_OUT_EXECUTABLES):$$PATH \
- $(DEXPREOPT) \
- --kernel $(BUILD_DEXPREOPT_KERNEL) \
- --ramdisk $(BUILT_DEXPREOPT_RAMDISK) \
- --image $(BUILT_SYSTEMIMAGE_UNOPT) \
- --system $(PRODUCT_OUT) \
- --tmpdir $(DEXPREOPT_TMP) \
- --outsystemdir $(SYSTEM_DIR)
-ifdef sign_dexpreopt
- @echo "dexpreopt: re-sign apk files"
- $(hide) \
- export PATH=$(HOST_OUT_EXECUTABLES):$$PATH; \
- for apk in $(SYSTEM_DIR)/app/*.apk; do \
- packageName=`basename $$apk`; \
- packageName=`echo $$packageName | sed -e 's/.apk$$//'`; \
- cert=`grep "^$$packageName " $(dexpreopt_package_certs_file) | \
- awk '{print $$2}'`; \
- pkey=`grep "^$$packageName " $(dexpreopt_package_certs_file) | \
- awk '{print $$3}'`; \
- if [ "$$cert" -a "$$pkey" ]; then \
- echo "dexpreopt: re-sign app/"$$packageName".apk"; \
- tmpApk=$$apk~; \
- rm -f $$tmpApk; \
- java -jar $(SIGNAPK_JAR) $$cert $$pkey $$apk $$tmpApk || \
- exit 11; \
- mv -f $$tmpApk $$apk; \
- else \
- echo "dexpreopt: no keys for app/"$$packageName".apk"; \
- rm $(SYSTEM_DIR)/app/$$packageName.* && \
- cp $(TARGET_OUT)/app/$$packageName.apk \
- $(SYSTEM_DIR)/app || exit 12; \
- fi; \
- tmpApk=$$apk~; \
- rm -f $$tmpApk; \
- $(ZIPALIGN) -f 4 $$apk $$tmpApk || exit 13; \
- mv -f $$tmpApk $$apk; \
- done
-endif
- @echo "Dexpreopt system image: $@"
- $(hide) $(MKYAFFS2) -f $(SYSTEM_DIR) $@
-
-.PHONY: dexpreoptimage
-dexpreoptimage: $(BUILT_DEXPREOPT_SYSTEMIMAGE)
-
-# Tell our caller to use the optimized systemimage
-BUILT_SYSTEMIMAGE := $(BUILT_DEXPREOPT_SYSTEMIMAGE)
-SYSTEMIMAGE_SOURCE_DIR := $(dexpreopt_system_dir)
diff --git a/tools/dexpreopt/afar/Android.mk b/tools/dexpreopt/afar/Android.mk
deleted file mode 100644
index 9f1b987..0000000
--- a/tools/dexpreopt/afar/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Copyright (C) 2008 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.
-#
-LOCAL_PATH := $(my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- main.c
-
-# Just for adler32()
-LOCAL_C_INCLUDES := external/zlib
-LOCAL_SHARED_LIBRARIES := libz
-
-LOCAL_MODULE := afar
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
diff --git a/tools/dexpreopt/afar/main.c b/tools/dexpreopt/afar/main.c
deleted file mode 100644
index d66d59c..0000000
--- a/tools/dexpreopt/afar/main.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
-
-#include <stdarg.h>
-#include <fcntl.h>
-#include <termios.h>
-
-#include <zlib.h> // for adler32()
-
-static int verbose = 0;
-
-/*
- * Android File Archive format:
- *
- * magic[5]: 'A' 'F' 'A' 'R' '\n'
- * version[4]: 0x00 0x00 0x00 0x01
- * for each file:
- * file magic[4]: 'F' 'I' 'L' 'E'
- * namelen[4]: Length of file name, including NUL byte (big-endian)
- * name[*]: NUL-terminated file name
- * datalen[4]: Length of file (big-endian)
- * data[*]: Unencoded file data
- * adler32[4]: adler32 of the unencoded file data (big-endian)
- * file end magic[4]: 'f' 'i' 'l' 'e'
- * end magic[4]: 'E' 'N' 'D' 0x00
- *
- * This format is about as simple as possible; it was designed to
- * make it easier to transfer multiple files over an stdin/stdout
- * pipe to another process, so word-alignment wasn't necessary.
- */
-
-static void
-die(const char *why, ...)
-{
- va_list ap;
-
- va_start(ap, why);
- fprintf(stderr, "error: ");
- vfprintf(stderr, why, ap);
- fprintf(stderr, "\n");
- va_end(ap);
- exit(1);
-}
-
-static void
-write_big_endian(size_t v)
-{
- putchar((v >> 24) & 0xff);
- putchar((v >> 16) & 0xff);
- putchar((v >> 8) & 0xff);
- putchar( v & 0xff);
-}
-
-static void
-_eject(struct stat *s, char *out, int olen, char *data, size_t datasize)
-{
- unsigned long adler;
-
- /* File magic.
- */
- printf("FILE");
-
- /* Name length includes the NUL byte.
- */
- write_big_endian(olen + 1);
-
- /* File name and terminating NUL.
- */
- printf("%s", out);
- putchar('\0');
-
- /* File length.
- */
- write_big_endian(datasize);
-
- /* File data.
- */
- if (fwrite(data, 1, datasize, stdout) != datasize) {
- die("Error writing file data");
- }
-
- /* Checksum.
- */
- adler = adler32(0, NULL, 0);
- adler = adler32(adler, (unsigned char *)data, datasize);
- write_big_endian(adler);
-
- /* File end magic.
- */
- printf("file");
-}
-
-static void _archive(char *in, int ilen);
-
-static void
-_archive_dir(char *in, int ilen)
-{
- int t;
- DIR *d;
- struct dirent *de;
-
- if (verbose) {
- fprintf(stderr, "_archive_dir('%s', %d)\n", in, ilen);
- }
-
- d = opendir(in);
- if (d == 0) {
- die("cannot open directory '%s'", in);
- }
-
- while ((de = readdir(d)) != 0) {
- /* xxx: feature? maybe some dotfiles are okay */
- if (strcmp(de->d_name, ".") == 0 ||
- strcmp(de->d_name, "..") == 0)
- {
- continue;
- }
-
- t = strlen(de->d_name);
- in[ilen] = '/';
- memcpy(in + ilen + 1, de->d_name, t + 1);
-
- _archive(in, ilen + t + 1);
-
- in[ilen] = '\0';
- }
-}
-
-static void
-_archive(char *in, int ilen)
-{
- struct stat s;
-
- if (verbose) {
- fprintf(stderr, "_archive('%s', %d)\n", in, ilen);
- }
-
- if (lstat(in, &s)) {
- die("could not stat '%s'\n", in);
- }
-
- if (S_ISREG(s.st_mode)) {
- char *tmp;
- int fd;
-
- fd = open(in, O_RDONLY);
- if (fd < 0) {
- die("cannot open '%s' for read", in);
- }
-
- tmp = (char*) malloc(s.st_size);
- if (tmp == 0) {
- die("cannot allocate %d bytes", s.st_size);
- }
-
- if (read(fd, tmp, s.st_size) != s.st_size) {
- die("cannot read %d bytes", s.st_size);
- }
-
- _eject(&s, in, ilen, tmp, s.st_size);
-
- free(tmp);
- close(fd);
- } else if (S_ISDIR(s.st_mode)) {
- _archive_dir(in, ilen);
- } else {
- /* We don't handle links, etc. */
- die("Unknown '%s' (mode %d)?\n", in, s.st_mode);
- }
-}
-
-void archive(const char *start)
-{
- char in[8192];
-
- strcpy(in, start);
-
- _archive_dir(in, strlen(in));
-}
-
-int
-main(int argc, char *argv[])
-{
- struct termios old_termios;
-
- if (argc == 1) {
- die("usage: %s <dir-list>", argv[0]);
- }
- argc--;
- argv++;
-
- /* Force stdout into raw mode.
- */
- struct termios s;
- if (tcgetattr(1, &s) < 0) {
- die("Could not get termios for stdout");
- }
- old_termios = s;
- cfmakeraw(&s);
- if (tcsetattr(1, TCSANOW, &s) < 0) {
- die("Could not set termios for stdout");
- }
-
- /* Print format magic and version.
- */
- printf("AFAR\n");
- write_big_endian(1);
-
- while (argc-- > 0) {
- archive(*argv++);
- }
-
- /* Print end magic.
- */
- printf("END");
- putchar('\0');
-
- /* Restore stdout.
- */
- if (tcsetattr(1, TCSANOW, &old_termios) < 0) {
- die("Could not restore termios for stdout");
- }
-
- return 0;
-}
diff --git a/tools/dexpreopt/dexopt-wrapper/Android.mk b/tools/dexpreopt/dexopt-wrapper/Android.mk
deleted file mode 100644
index ae2b6a3..0000000
--- a/tools/dexpreopt/dexopt-wrapper/Android.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Copyright (C) 2008 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- DexOptWrapper.cpp
-
-LOCAL_C_INCLUDES += \
- dalvik
-
-LOCAL_STATIC_LIBRARIES := \
- libdex
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils
-
-LOCAL_MODULE := dexopt-wrapper
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
diff --git a/tools/dexpreopt/dexopt-wrapper/DexOptWrapper.cpp b/tools/dexpreopt/dexopt-wrapper/DexOptWrapper.cpp
deleted file mode 100644
index 102cf0e..0000000
--- a/tools/dexpreopt/dexopt-wrapper/DexOptWrapper.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * dexopt invocation test.
- *
- * You must have BOOTCLASSPATH defined. On the simulator, you will also
- * need ANDROID_ROOT.
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/file.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include "cutils/properties.h"
-
-//using namespace android;
-
-/*
- * Privilege reduction function.
- *
- * Returns 0 on success, nonzero on failure.
- */
-static int privFunc(void)
-{
- printf("--- would reduce privs here\n");
- return 0;
-}
-
-/*
- * We're in the child process. exec dexopt.
- */
-static void runDexopt(int zipFd, int odexFd, const char* inputFileName)
-{
- static const char* kDexOptBin = "/bin/dexopt";
- static const int kMaxIntLen = 12; // '-'+10dig+'\0' -OR- 0x+8dig
- char zipNum[kMaxIntLen];
- char odexNum[kMaxIntLen];
- char dexoptFlags[PROPERTY_VALUE_MAX];
- const char* androidRoot;
- char* execFile;
-
- /* pull optional configuration tweaks out of properties */
- property_get("dalvik.vm.dexopt-flags", dexoptFlags, "");
-
- /* find dexopt executable; this exists for simulator compatibility */
- androidRoot = getenv("ANDROID_ROOT");
- if (androidRoot == NULL)
- androidRoot = "/system";
- execFile = (char*) malloc(strlen(androidRoot) + strlen(kDexOptBin) +1);
- sprintf(execFile, "%s%s", androidRoot, kDexOptBin);
-
- sprintf(zipNum, "%d", zipFd);
- sprintf(odexNum, "%d", odexFd);
-
- execl(execFile, execFile, "--zip", zipNum, odexNum, inputFileName,
- dexoptFlags, (char*) NULL);
- fprintf(stderr, "execl(%s) failed: %s\n", kDexOptBin, strerror(errno));
-}
-
-/*
- * Run dexopt on the specified Jar/APK.
- *
- * This uses fork() and exec() to mimic the way this would work in an
- * installer; in practice for something this simple you could just exec()
- * unless you really wanted the status messages.
- *
- * Returns 0 on success.
- */
-int doStuff(const char* zipName, const char* odexName)
-{
- int zipFd, odexFd;
-
- /*
- * Open the zip archive and the odex file, creating the latter (and
- * failing if it already exists). This must be done while we still
- * have sufficient privileges to read the source file and create a file
- * in the target directory. The "classes.dex" file will be extracted.
- */
- zipFd = open(zipName, O_RDONLY, 0);
- if (zipFd < 0) {
- fprintf(stderr, "Unable to open '%s': %s\n", zipName, strerror(errno));
- return 1;
- }
-
- odexFd = open(odexName, O_RDWR | O_CREAT | O_EXCL, 0644);
- if (odexFd < 0) {
- fprintf(stderr, "Unable to create '%s': %s\n",
- odexName, strerror(errno));
- close(zipFd);
- return 1;
- }
-
- printf("--- BEGIN '%s' (bootstrap=%d) ---\n", zipName, 0);
-
- /*
- * Fork a child process.
- */
- pid_t pid = fork();
- if (pid == 0) {
- /* child -- drop privs */
- if (privFunc() != 0)
- exit(66);
-
- /* lock the input file */
- if (flock(odexFd, LOCK_EX | LOCK_NB) != 0) {
- fprintf(stderr, "Unable to lock '%s': %s\n",
- odexName, strerror(errno));
- exit(65);
- }
-
- runDexopt(zipFd, odexFd, zipName); /* does not return */
- exit(67); /* usually */
- } else {
- /* parent -- wait for child to finish */
- printf("--- waiting for verify+opt, pid=%d\n", (int) pid);
- int status, oldStatus;
- pid_t gotPid;
-
- close(zipFd);
- close(odexFd);
-
- /*
- * Wait for the optimization process to finish.
- */
- while (true) {
- gotPid = waitpid(pid, &status, 0);
- if (gotPid == -1 && errno == EINTR) {
- printf("waitpid interrupted, retrying\n");
- } else {
- break;
- }
- }
- if (gotPid != pid) {
- fprintf(stderr, "waitpid failed: wanted %d, got %d: %s\n",
- (int) pid, (int) gotPid, strerror(errno));
- return 1;
- }
-
- if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
- printf("--- END '%s' (success) ---\n", zipName);
- return 0;
- } else {
- printf("--- END '%s' --- status=0x%04x, process failed\n",
- zipName, status);
- return 1;
- }
- }
-
- /* notreached */
-}
-
-/*
- * Parse args, do stuff.
- */
-int main(int argc, char** argv)
-{
- if (argc < 3 || argc > 4) {
- fprintf(stderr, "Usage: %s <input jar/apk> <output odex> "
- "[<bootclasspath>]\n\n", argv[0]);
- fprintf(stderr, "Example: dexopttest "
- "/system/app/NotePad.apk /system/app/NotePad.odex\n");
- return 2;
- }
-
- if (argc > 3) {
- setenv("BOOTCLASSPATH", argv[3], 1);
- }
-
- return (doStuff(argv[1], argv[2]) != 0);
-}
diff --git a/tools/dexpreopt/dexpreopt.py b/tools/dexpreopt/dexpreopt.py
deleted file mode 100755
index 376f135..0000000
--- a/tools/dexpreopt/dexpreopt.py
+++ /dev/null
@@ -1,986 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2008 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.
-#
-
-"""Creates optimized versions of APK files.
-
-A tool and associated functions to communicate with an Android
-emulator instance, run commands, and scrape out files.
-
-Requires at least python2.4.
-"""
-
-import array
-import datetime
-import optparse
-import os
-import posix
-import select
-import signal
-import struct
-import subprocess
-import sys
-import tempfile
-import time
-import zlib
-
-
-_emulator_popen = None
-_DEBUG_READ = 1
-
-
-def EnsureTempDir(path=None):
- """Creates a temporary directory and returns its path.
-
- Creates any necessary parent directories.
-
- Args:
- path: If specified, used as the temporary directory. If not specified,
- a safe temporary path is created. The caller is responsible for
- deleting the directory.
-
- Returns:
- The path to the new directory, or None if a problem occurred.
- """
- if path is None:
- path = tempfile.mkdtemp('', 'dexpreopt-')
- elif not os.path.exists(path):
- os.makedirs(path)
- elif not os.path.isdir(path):
- return None
- return path
-
-
-def CreateZeroedFile(path, length):
- """Creates the named file and writes <length> zero bytes to it.
-
- Unlinks the file first if it already exists.
- Creates its containing directory if necessary.
-
- Args:
- path: The path to the file to create.
- length: The number of zero bytes to write to the file.
-
- Returns:
- True on success.
- """
- subprocess.call(['rm', '-f', path])
- d = os.path.dirname(path)
- if d and not os.path.exists(d): os.makedirs(os.path.dirname(d))
- # TODO: redirect child's stdout to /dev/null
- ret = subprocess.call(['dd', 'if=/dev/zero', 'of=%s' % path,
- 'bs=%d' % length, 'count=1'])
- return not ret # i.e., ret == 0; i.e., the child exited successfully.
-
-
-def StartEmulator(exe_name='emulator', kernel=None,
- ramdisk=None, image=None, userdata=None, system=None):
- """Runs the emulator with the specified arguments.
-
- Args:
- exe_name: The name of the emulator to run. May be absolute, relative,
- or unqualified (and left to exec() to find).
- kernel: If set, passed to the emulator as "-kernel".
- ramdisk: If set, passed to the emulator as "-ramdisk".
- image: If set, passed to the emulator as "-system".
- userdata: If set, passed to the emulator as "-initdata" and "-data".
- system: If set, passed to the emulator as "-sysdir".
-
- Returns:
- A subprocess.Popen that refers to the emulator process, or None if
- a problem occurred.
- """
- #exe_name = './stuff'
- args = [exe_name]
- if kernel: args += ['-kernel', kernel]
- if ramdisk: args += ['-ramdisk', ramdisk]
- if image: args += ['-system', image]
- if userdata: args += ['-initdata', userdata, '-data', userdata]
- if system: args += ['-sysdir', system]
- args += ['-partition-size', '128']
- args += ['-no-window', '-netfast', '-noaudio']
-
- _USE_PIPE = True
-
- if _USE_PIPE:
- # Use dedicated fds instead of stdin/out to talk to the
- # emulator so that the emulator doesn't try to tty-cook
- # the data.
- em_stdin_r, em_stdin_w = posix.pipe()
- em_stdout_r, em_stdout_w = posix.pipe()
- args += ['-shell-serial', 'fdpair:%d:%d' % (em_stdin_r, em_stdout_w)]
- else:
- args += ['-shell']
-
- # This is a work-around for the ARMv7 emulation bug.
- # XXX: It only works by chance, if any ! A real emulation fix is on the way
- args += ['-qemu', '-singlestep']
-
- # Ensure that this environment variable isn't set;
- # if it is, the emulator will print the log to stdout.
- if os.environ.get('ANDROID_LOG_TAGS'):
- del os.environ['ANDROID_LOG_TAGS']
-
- try:
- # bufsize=1 line-buffered, =0 unbuffered,
- # <0 system default (fully buffered)
- Trace('Running emulator: %s' % ' '.join(args))
- if _USE_PIPE:
- ep = subprocess.Popen(args)
- else:
- ep = subprocess.Popen(args, close_fds=True,
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- if ep:
- if _USE_PIPE:
- # Hijack the Popen.stdin/.stdout fields to point to our
- # pipes. These are the same fields that would have been set
- # if we called Popen() with stdin=subprocess.PIPE, etc.
- # Note that these names are from the point of view of the
- # child process.
- #
- # Since we'll be using select.select() to read data a byte
- # at a time, it's important that these files are unbuffered
- # (bufsize=0). If Popen() took care of the pipes, they're
- # already unbuffered.
- ep.stdin = os.fdopen(em_stdin_w, 'w', 0)
- ep.stdout = os.fdopen(em_stdout_r, 'r', 0)
- return ep
- except OSError, e:
- print >>sys.stderr, 'Could not start emulator:', e
- return None
-
-
-def IsDataAvailable(fo, timeout=0):
- """Indicates whether or not data is available to be read from a file object.
-
- Args:
- fo: A file object to read from.
- timeout: The number of seconds to wait for data, or zero for no timeout.
-
- Returns:
- True iff data is available to be read.
- """
- return select.select([fo], [], [], timeout) == ([fo], [], [])
-
-
-def ConsumeAvailableData(fo):
- """Reads data from a file object while it's available.
-
- Stops when no more data is immediately available or upon reaching EOF.
-
- Args:
- fo: A file object to read from.
-
- Returns:
- An unsigned byte array.array of the data that was read.
- """
- buf = array.array('B')
- while IsDataAvailable(fo):
- try:
- buf.fromfile(fo, 1)
- except EOFError:
- break
- return buf
-
-
-def ShowTimeout(timeout, end_time):
- """For debugging, display the timeout info.
-
- Args:
- timeout: the timeout in seconds.
- end_time: a time.time()-based value indicating when the timeout should
- expire.
- """
- if _DEBUG_READ:
- if timeout:
- remaining = end_time - time.time()
- Trace('ok, time remaining %.1f of %.1f' % (remaining, timeout))
- else:
- Trace('ok (no timeout)')
-
-
-def WaitForString(inf, pattern, timeout=0, max_len=0, eat_to_eol=True,
- reset_on_activity=False):
- """Reads from a file object and returns when the pattern matches the data.
-
- Reads a byte at a time to avoid consuming extra data, so do not call
- this function when you expect the pattern to match a large amount of data.
-
- Args:
- inf: The file object to read from.
- pattern: The string to look for in the input data.
- May be a tuple of strings.
- timeout: How long to wait, in seconds. No timeout if it evaluates to False.
- max_len: Return None if this many bytes have been read without matching.
- No upper bound if it evaluates to False.
- eat_to_eol: If true, the input data will be consumed until a '\\n' or EOF
- is encountered.
- reset_on_activity: If True, reset the timeout whenever a character is
- read.
-
- Returns:
- The input data matching the expression as an unsigned char array,
- or None if the operation timed out or didn't match after max_len bytes.
-
- Raises:
- IOError: An error occurred reading from the input file.
- """
- if timeout:
- end_time = time.time() + timeout
- else:
- end_time = 0
-
- if _DEBUG_READ:
- Trace('WaitForString: "%s", %.1f' % (pattern, timeout))
-
- buf = array.array('B') # unsigned char array
- eating = False
- while True:
- if end_time:
- remaining = end_time - time.time()
- if remaining <= 0:
- Trace('Timeout expired after %.1f seconds' % timeout)
- return None
- else:
- remaining = None
-
- if IsDataAvailable(inf, remaining):
- if reset_on_activity and timeout:
- end_time = time.time() + timeout
-
- buf.fromfile(inf, 1)
- if _DEBUG_READ:
- c = buf.tostring()[-1:]
- ci = ord(c)
- if ci < 0x20: c = '.'
- if _DEBUG_READ > 1:
- print 'read [%c] 0x%02x' % (c, ci)
-
- if not eating:
- if buf.tostring().endswith(pattern):
- if eat_to_eol:
- if _DEBUG_READ > 1:
- Trace('Matched; eating to EOL')
- eating = True
- else:
- ShowTimeout(timeout, end_time)
- return buf
- if _DEBUG_READ > 2:
- print '/%s/ ? "%s"' % (pattern, buf.tostring())
- else:
- if buf.tostring()[-1:] == '\n':
- ShowTimeout(timeout, end_time)
- return buf
-
- if max_len and len(buf) >= max_len: return None
-
-
-def WaitForEmulator(ep, timeout=0):
- """Waits for the emulator to start up and print the first prompt.
-
- Args:
- ep: A subprocess.Popen object referring to the emulator process.
- timeout: How long to wait, in seconds. No timeout if it evaluates to False.
-
- Returns:
- True on success, False if the timeout occurred.
- """
- # Prime the pipe; the emulator doesn't start without this.
- print >>ep.stdin, ''
-
- # Wait until the console is ready and the first prompt appears.
- buf = WaitForString(ep.stdout, '#', timeout=timeout, eat_to_eol=False)
- if buf:
- Trace('Saw the prompt: "%s"' % buf.tostring())
- return True
- return False
-
-
-def WaitForPrompt(ep, prompt=None, timeout=0, reset_on_activity=False):
- """Blocks until the prompt appears on ep.stdout or the timeout elapses.
-
- Args:
- ep: A subprocess.Popen connection to the emulator process.
- prompt: The prompt to wait for. If None, uses ep.prompt.
- timeout: How many seconds to wait for the prompt. Waits forever
- if timeout is zero.
- reset_on_activity: If True, reset the timeout whenever a character is
- read.
-
- Returns:
- A string containing the data leading up to the prompt. The string
- will always end in '\\n'. Returns None if the prompt was not seen
- within the timeout, or if some other error occurred.
- """
- if not prompt: prompt = ep.prompt
- if prompt:
- #Trace('waiting for prompt "%s"' % prompt)
- data = WaitForString(ep.stdout, prompt,
- timeout=timeout, reset_on_activity=reset_on_activity)
- if data:
- # data contains everything on ep.stdout up to and including the prompt,
- # plus everything up 'til the newline. Scrape out the prompt
- # and everything that follows, and ensure that the result ends
- # in a newline (which is important if it would otherwise be empty).
- s = data.tostring()
- i = s.rfind(prompt)
- s = s[:i]
- if s[-1:] != '\n':
- s += '\n'
- if _DEBUG_READ:
- print 'WaitForPrompt saw """\n%s"""' % s
- return s
- return None
-
-
-def ReplaceEmulatorPrompt(ep, prompt=None):
- """Replaces PS1 in the emulator with a different value.
-
- This is useful for making the prompt unambiguous; i.e., something
- that probably won't appear in the output of another command.
-
- Assumes that the emulator is already sitting at a prompt,
- waiting for shell input.
-
- Puts the new prompt in ep.prompt.
-
- Args:
- ep: A subprocess.Popen object referring to the emulator process.
- prompt: The new prompt to use
-
- Returns:
- True on success, False if the timeout occurred.
- """
- if not prompt:
- prompt = '-----DEXPREOPT-PROMPT-----'
- print >>ep.stdin, 'PS1="%s\n"' % prompt
- ep.prompt = prompt
-
- # Eat the command echo.
- data = WaitForPrompt(ep, timeout=2)
- if not data:
- return False
-
- # Make sure it's actually there.
- return WaitForPrompt(ep, timeout=2)
-
-
-def RunEmulatorCommand(ep, cmd, timeout=0):
- """Sends the command to the emulator's shell and waits for the result.
-
- Assumes that the emulator is already sitting at a prompt,
- waiting for shell input.
-
- Args:
- ep: A subprocess.Popen object referring to the emulator process.
- cmd: The shell command to run in the emulator.
- timeout: The number of seconds to wait for the command to complete,
- or zero for no timeout.
-
- Returns:
- If the command ran and returned to the console prompt before the
- timeout, returns the output of the command as a string.
- Returns None otherwise.
- """
- ConsumeAvailableData(ep.stdout)
-
- Trace('Running "%s"' % cmd)
- print >>ep.stdin, '%s' % cmd
-
- # The console will echo the command.
- #Trace('Waiting for echo')
- if WaitForString(ep.stdout, cmd, timeout=timeout):
- #Trace('Waiting for completion')
- return WaitForPrompt(ep, timeout=timeout, reset_on_activity=True)
-
- return None
-
-
-def ReadFileList(ep, dir_list, timeout=0):
- """Returns a list of emulator files in each dir in dir_list.
-
- Args:
- ep: A subprocess.Popen object referring to the emulator process.
- dir_list: List absolute paths to directories to read.
- timeout: The number of seconds to wait for the command to complete,
- or zero for no timeout.
-
- Returns:
- A list of absolute paths to files in the named directories,
- in the context of the emulator's filesystem.
- None on failure.
- """
- ret = []
- for d in dir_list:
- output = RunEmulatorCommand(ep, 'ls ' + d, timeout=timeout)
- if not output:
- Trace('Could not ls ' + d)
- return None
- ret += ['%s/%s' % (d, f) for f in output.splitlines()]
- return ret
-
-
-def DownloadDirectoryHierarchy(ep, src, dest, timeout=0):
- """Recursively downloads an emulator directory to the local filesystem.
-
- Args:
- ep: A subprocess.Popen object referring to the emulator process.
- src: The path on the emulator's filesystem to download from.
- dest: The path on the local filesystem to download to.
- timeout: The number of seconds to wait for the command to complete,
- or zero for no timeout. (CURRENTLY IGNORED)
-
- Returns:
- True iff the files downloaded successfully, False otherwise.
- """
- ConsumeAvailableData(ep.stdout)
-
- if not os.path.exists(dest):
- os.makedirs(dest)
-
- cmd = 'afar %s' % src
- Trace('Running "%s"' % cmd)
- print >>ep.stdin, '%s' % cmd
-
- # The console will echo the command.
- #Trace('Waiting for echo')
- if not WaitForString(ep.stdout, cmd, timeout=timeout):
- return False
-
- #TODO: use a signal to support timing out?
-
- #
- # Android File Archive format:
- #
- # magic[5]: 'A' 'F' 'A' 'R' '\n'
- # version[4]: 0x00 0x00 0x00 0x01
- # for each file:
- # file magic[4]: 'F' 'I' 'L' 'E'
- # namelen[4]: Length of file name, including NUL byte (big-endian)
- # name[*]: NUL-terminated file name
- # datalen[4]: Length of file (big-endian)
- # data[*]: Unencoded file data
- # adler32[4]: adler32 of the unencoded file data (big-endian)
- # file end magic[4]: 'f' 'i' 'l' 'e'
- # end magic[4]: 'E' 'N' 'D' 0x00
- #
-
- # Read the header.
- HEADER = array.array('B', 'AFAR\n\000\000\000\001')
- buf = array.array('B')
- buf.fromfile(ep.stdout, len(HEADER))
- if buf != HEADER:
- Trace('Header does not match: "%s"' % buf)
- return False
-
- # Read the file entries.
- FILE_START = array.array('B', 'FILE')
- FILE_END = array.array('B', 'file')
- END = array.array('B', 'END\000')
- while True:
- # Entry magic.
- buf = array.array('B')
- buf.fromfile(ep.stdout, 4)
- if buf == FILE_START:
- # Name length (4 bytes, big endian)
- buf = array.array('B')
- buf.fromfile(ep.stdout, 4)
- (name_len,) = struct.unpack('>I', buf)
- #Trace('name len %d' % name_len)
-
- # Name, NUL-terminated.
- buf = array.array('B')
- buf.fromfile(ep.stdout, name_len)
- buf.pop() # Remove trailing NUL byte.
- file_name = buf.tostring()
- Trace('FILE: %s' % file_name)
-
- # File length (4 bytes, big endian)
- buf = array.array('B')
- buf.fromfile(ep.stdout, 4)
- (file_len,) = struct.unpack('>I', buf)
-
- # File data.
- data = array.array('B')
- data.fromfile(ep.stdout, file_len)
- #Trace('FILE: read %d bytes from %s' % (file_len, file_name))
-
- # adler32 (4 bytes, big endian)
- buf = array.array('B')
- buf.fromfile(ep.stdout, 4)
- (adler32,) = struct.unpack('>i', buf) # adler32 wants a signed int ('i')
- data_adler32 = zlib.adler32(data)
- # Because of a difference in behavior of zlib.adler32 on 32-bit and 64-bit
- # systems (one returns signed values, the other unsigned), we take the
- # modulo 2**32 of the checksums, and compare those.
- # See also http://bugs.python.org/issue1202
- if (adler32 % (2**32)) != (data_adler32 % (2**32)):
- Trace('adler32 does not match: calculated 0x%08x != expected 0x%08x' %
- (data_adler32, adler32))
- return False
-
- # File end magic.
- buf = array.array('B')
- buf.fromfile(ep.stdout, 4)
- if buf != FILE_END:
- Trace('Unexpected file end magic "%s"' % buf)
- return False
-
- # Write to the output file
- out_file_name = dest + '/' + file_name[len(src):]
- p = os.path.dirname(out_file_name)
- if not os.path.exists(p): os.makedirs(p)
- fo = file(out_file_name, 'w+b')
- fo.truncate(0)
- Trace('FILE: Writing %d bytes to %s' % (len(data), out_file_name))
- data.tofile(fo)
- fo.close()
-
- elif buf == END:
- break
- else:
- Trace('Unexpected magic "%s"' % buf)
- return False
-
- return WaitForPrompt(ep, timeout=timeout, reset_on_activity=True)
-
-
-def ReadBootClassPath(ep, timeout=0):
- """Reads and returns the default bootclasspath as a list of files.
-
- Args:
- ep: A subprocess.Popen object referring to the emulator process.
- timeout: The number of seconds to wait for the command to complete,
- or zero for no timeout.
-
- Returns:
- The bootclasspath as a list of strings.
- None on failure.
- """
- bcp = RunEmulatorCommand(ep, 'echo $BOOTCLASSPATH', timeout=timeout)
- if not bcp:
- Trace('Could not find bootclasspath')
- return None
- return bcp.strip().split(':') # strip trailing newline
-
-
-def RunDexoptOnFileList(ep, files, dest_root, move=False, timeout=0):
- """Creates the corresponding .odex file for all jar/apk files in 'files'.
- Copies the .odex file to a location under 'dest_root'. If 'move' is True,
- the file is moved instead of copied.
-
- Args:
- ep: A subprocess.Popen object referring to the emulator process.
- files: The list of files to optimize
- dest_root: directory to copy/move odex files to. Must already exist.
- move: if True, move rather than copy files
- timeout: The number of seconds to wait for the command to complete,
- or zero for no timeout.
-
- Returns:
- True on success, False on failure.
- """
- for jar_file in files:
- if jar_file.endswith('.apk') or jar_file.endswith('.jar'):
- odex_file = jar_file[:jar_file.rfind('.')] + '.odex'
- cmd = 'dexopt-wrapper %s %s' % (jar_file, odex_file)
- if not RunEmulatorCommand(ep, cmd, timeout=timeout):
- Trace('"%s" failed' % cmd)
- return False
-
- # Always copy the odex file. There's no cp(1), so we
- # cat out to the new file.
- dst_odex = dest_root + odex_file
- cmd = 'cat %s > %s' % (odex_file, dst_odex) # no cp(1)
- if not RunEmulatorCommand(ep, cmd, timeout=timeout):
- Trace('"%s" failed' % cmd)
- return False
-
- # Move it if we're asked to. We can't use mv(1) because
- # the files tend to move between filesystems.
- if move:
- cmd = 'rm %s' % odex_file
- if not RunEmulatorCommand(ep, cmd, timeout=timeout):
- Trace('"%s" failed' % cmd)
- return False
- return True
-
-
-def InstallCacheFiles(cache_system_dir, out_system_dir):
- """Install files in cache_system_dir to the proper places in out_system_dir.
-
- cache_system_dir contains various files from /system, plus .odex files
- for most of the .apk/.jar files that live there.
- This function copies each .odex file from the cache dir to the output dir
- and removes "classes.dex" from each appropriate .jar/.apk.
-
- E.g., <cache_system_dir>/app/NotePad.odex would be copied to
- <out_system_dir>/app/NotePad.odex, and <out_system_dir>/app/NotePad.apk
- would have its classes.dex file removed.
-
- Args:
- cache_system_dir: The directory containing the cache files scraped from
- the emulator.
- out_system_dir: The local directory that corresponds to "/system"
- on the device filesystem. (the root of system.img)
-
- Returns:
- True if everything succeeded, False if any problems occurred.
- """
- # First, walk through cache_system_dir and copy every .odex file
- # over to out_system_dir, ensuring that the destination directory
- # contains the corresponding source file.
- for root, dirs, files in os.walk(cache_system_dir):
- for name in files:
- if name.endswith('.odex'):
- odex_file = os.path.join(root, name)
-
- # Find the path to the .odex file's source apk/jar file.
- out_stem = odex_file[len(cache_system_dir):odex_file.rfind('.')]
- out_stem = out_system_dir + out_stem;
- jar_file = out_stem + '.jar'
- if not os.path.exists(jar_file):
- jar_file = out_stem + '.apk'
- if not os.path.exists(jar_file):
- Trace('Cannot find source .jar/.apk for %s: %s' %
- (odex_file, out_stem + '.{jar,apk}'))
- return False
-
- # Copy the cache file next to the source file.
- cmd = ['cp', odex_file, out_stem + '.odex']
- ret = subprocess.call(cmd)
- if ret: # non-zero exit status
- Trace('%s failed' % ' '.join(cmd))
- return False
-
- # Walk through the output /system directory, making sure
- # that every .jar/.apk has an odex file. While we do this,
- # remove the classes.dex entry from each source archive.
- for root, dirs, files in os.walk(out_system_dir):
- for name in files:
- if name.endswith('.apk') or name.endswith('.jar'):
- jar_file = os.path.join(root, name)
- odex_file = jar_file[:jar_file.rfind('.')] + '.odex'
- if not os.path.exists(odex_file):
- if root.endswith('/system/app') or root.endswith('/system/framework'):
- Trace('jar/apk %s has no .odex file %s' % (jar_file, odex_file))
- return False
- else:
- continue
-
- # Attempting to dexopt a jar with no classes.dex currently
- # creates a 40-byte odex file.
- # TODO: use a more reliable check
- if os.path.getsize(odex_file) > 100:
- # Remove classes.dex from the .jar file.
- cmd = ['zip', '-dq', jar_file, 'classes.dex']
- ret = subprocess.call(cmd)
- if ret: # non-zero exit status
- Trace('"%s" failed' % ' '.join(cmd))
- return False
- else:
- # Some of the apk files don't contain any code.
- if not name.endswith('.apk'):
- Trace('%s has a zero-length odex file' % jar_file)
- return False
- cmd = ['rm', odex_file]
- ret = subprocess.call(cmd)
- if ret: # non-zero exit status
- Trace('"%s" failed' % ' '.join(cmd))
- return False
-
- return True
-
-
-def KillChildProcess(p, sig=signal.SIGTERM, timeout=0):
- """Waits for a child process to die without getting stuck in wait().
-
- After Jean Brouwers's 2004 post to python-list.
-
- Args:
- p: A subprocess.Popen representing the child process to kill.
- sig: The signal to send to the child process.
- timeout: How many seconds to wait for the child process to die.
- If zero, do not time out.
-
- Returns:
- The exit status of the child process, if it was successfully killed.
- The final value of p.returncode if it wasn't.
- """
- os.kill(p.pid, sig)
- if timeout > 0:
- while p.poll() < 0:
- if timeout > 0.5:
- timeout -= 0.25
- time.sleep(0.25)
- else:
- os.kill(p.pid, signal.SIGKILL)
- time.sleep(0.5)
- p.poll()
- break
- else:
- p.wait()
- return p.returncode
-
-
-def Trace(msg):
- """Prints a message to stdout.
-
- Args:
- msg: The message to print.
- """
- #print 'dexpreopt: %s' % msg
- when = datetime.datetime.now()
- print '%02d:%02d.%d dexpreopt: %s' % (when.minute, when.second, when.microsecond, msg)
-
-
-def KillEmulator():
- """Attempts to kill the emulator process, if it is running.
-
- Returns:
- The exit status of the emulator process, or None if the emulator
- was not running or was unable to be killed.
- """
- global _emulator_popen
- if _emulator_popen:
- Trace('Killing emulator')
- try:
- ret = KillChildProcess(_emulator_popen, sig=signal.SIGINT, timeout=5)
- except OSError:
- Trace('Could not kill emulator')
- ret = None
- _emulator_popen = None
- return ret
- return None
-
-
-def Fail(msg=None):
- """Prints an error and causes the process to exit.
-
- Args:
- msg: Additional error string to print (optional).
-
- Returns:
- Does not return.
- """
- s = 'dexpreopt: ERROR'
- if msg: s += ': %s' % msg
- print >>sys.stderr, msg
- KillEmulator()
- sys.exit(1)
-
-
-def PrintUsage(msg=None):
- """Prints commandline usage information for the tool and exits with an error.
-
- Args:
- msg: Additional string to print (optional).
-
- Returns:
- Does not return.
- """
- if msg:
- print >>sys.stderr, 'dexpreopt: %s', msg
- print >>sys.stderr, """Usage: dexpreopt <options>
-Required options:
- -kernel <kernel file> Kernel to use when running the emulator
- -ramdisk <ramdisk.img file> Ramdisk to use when running the emulator
- -image <system.img file> System image to use when running the
- emulator. /system/app should contain the
- .apk files to optimize, and any required
- bootclasspath libraries must be present
- in the correct locations.
- -system <path> The product directory, which usually contains
- files like 'system.img' (files other than
- the kernel in that directory won't
- be used)
- -outsystemdir <path> A fully-populated /system directory, ready
- to be modified to contain the optimized
- files. The appropriate .jar/.apk files
- will be stripped of their classes.dex
- entries, and the optimized .dex files
- will be added alongside the packages
- that they came from.
-Optional:
- -tmpdir <path> If specified, use this directory for
- intermediate objects. If not specified,
- a unique directory under the system
- temp dir is used.
- """
- sys.exit(2)
-
-
-def ParseArgs(argv):
- """Parses commandline arguments.
-
- Args:
- argv: A list of arguments; typically sys.argv[1:]
-
- Returns:
- A tuple containing two dictionaries; the first contains arguments
- that will be passsed to the emulator, and the second contains other
- arguments.
- """
- parser = optparse.OptionParser()
-
- parser.add_option('--kernel', help='Passed to emulator')
- parser.add_option('--ramdisk', help='Passed to emulator')
- parser.add_option('--image', help='Passed to emulator')
- parser.add_option('--system', help='Passed to emulator')
- parser.add_option('--outsystemdir', help='Destination /system directory')
- parser.add_option('--tmpdir', help='Optional temp directory to use')
-
- options, args = parser.parse_args(args=argv)
- if args: PrintUsage()
-
- emulator_args = {}
- other_args = {}
- if options.kernel: emulator_args['kernel'] = options.kernel
- if options.ramdisk: emulator_args['ramdisk'] = options.ramdisk
- if options.image: emulator_args['image'] = options.image
- if options.system: emulator_args['system'] = options.system
- if options.outsystemdir: other_args['outsystemdir'] = options.outsystemdir
- if options.tmpdir: other_args['tmpdir'] = options.tmpdir
-
- return (emulator_args, other_args)
-
-
-def DexoptEverything(ep, dest_root):
- """Logic for finding and dexopting files in the necessary order.
-
- Args:
- ep: A subprocess.Popen object referring to the emulator process.
- dest_root: directory to copy/move odex files to
-
- Returns:
- True on success, False on failure.
- """
- _extra_tests = False
- if _extra_tests:
- if not RunEmulatorCommand(ep, 'ls /system/app', timeout=5):
- Fail('Could not ls')
-
- # We're very short on space, so remove a bunch of big stuff that we
- # don't need.
- cmd = 'rm -r /system/sounds /system/media /system/fonts /system/xbin'
- if not RunEmulatorCommand(ep, cmd, timeout=40):
- Trace('"%s" failed' % cmd)
- return False
-
- Trace('Read file list')
- jar_dirs = ['/system/framework', '/system/app']
- files = ReadFileList(ep, jar_dirs, timeout=5)
- if not files:
- Fail('Could not list files in %s' % ' '.join(jar_dirs))
- #Trace('File list:\n"""\n%s\n"""' % '\n'.join(files))
-
- bcp = ReadBootClassPath(ep, timeout=2)
- if not files:
- Fail('Could not sort by bootclasspath')
-
- # Remove bootclasspath entries from the main file list.
- for jar in bcp:
- try:
- files.remove(jar)
- except ValueError:
- Trace('File list does not contain bootclasspath entry "%s"' % jar)
- return False
-
- # Create the destination directories.
- for d in ['', '/system'] + jar_dirs:
- cmd = 'mkdir %s%s' % (dest_root, d)
- if not RunEmulatorCommand(ep, cmd, timeout=4):
- Trace('"%s" failed' % cmd)
- return False
-
- # First, dexopt the bootclasspath. Keep their cache files in place.
- Trace('Dexopt %d bootclasspath files' % len(bcp))
- if not RunDexoptOnFileList(ep, bcp, dest_root, timeout=120):
- Trace('Could not dexopt bootclasspath')
- return False
-
- # dexopt the rest. To avoid running out of space on the emulator
- # volume, move each cache file after it's been created.
- Trace('Dexopt %d files' % len(files))
- if not RunDexoptOnFileList(ep, files, dest_root, move=True, timeout=120):
- Trace('Could not dexopt files')
- return False
-
- if _extra_tests:
- if not RunEmulatorCommand(ep, 'ls /system/app', timeout=5):
- Fail('Could not ls')
-
- return True
-
-
-
-def MainInternal():
- """Main function that can be wrapped in a try block.
-
- Returns:
- Nothing.
- """
- emulator_args, other_args = ParseArgs(sys.argv[1:])
-
- tmp_dir = EnsureTempDir(other_args.get('tmpdir'))
- if not tmp_dir: Fail('Could not create temp dir')
-
- Trace('Creating data image')
- userdata = '%s/data.img' % tmp_dir
- if not CreateZeroedFile(userdata, 32 * 1024 * 1024):
- Fail('Could not create data image file')
- emulator_args['userdata'] = userdata
-
- ep = StartEmulator(**emulator_args)
- if not ep: Fail('Could not start emulator')
- global _emulator_popen
- _emulator_popen = ep
-
- # TODO: unlink the big userdata file now, since the emulator
- # has it open.
-
- if not WaitForEmulator(ep, timeout=20): Fail('Emulator did not respond')
- if not ReplaceEmulatorPrompt(ep): Fail('Could not replace prompt')
-
- dest_root = '/data/dexpreopt-root'
- if not DexoptEverything(ep, dest_root): Fail('Could not dexopt files')
-
- # Grab the odex files that were left in dest_root.
- cache_system_dir = tmp_dir + '/cache-system'
- if not DownloadDirectoryHierarchy(ep, dest_root + '/system',
- cache_system_dir,
- timeout=20):
- Fail('Could not download %s/system from emulator' % dest_root)
-
- if not InstallCacheFiles(cache_system_dir=cache_system_dir,
- out_system_dir=other_args['outsystemdir']):
- Fail('Could not install files')
-
- Trace('dexpreopt successful')
- # Success!
-
-
-def main():
- try:
- MainInternal()
- finally:
- KillEmulator()
-
-
-if __name__ == '__main__':
- main()
diff --git a/tools/dexpreopt/geninitrc.awk b/tools/dexpreopt/geninitrc.awk
deleted file mode 100644
index 4b67e78..0000000
--- a/tools/dexpreopt/geninitrc.awk
+++ /dev/null
@@ -1,62 +0,0 @@
-#
-# 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.
-#
-BEGIN {
- fixed_remount = 0;
- console_state = 0;
-}
-
-/^ mount yaffs2 mtd@system \/system ro remount$/ {
- fixed_remount = 1;
- print " # dexpreopt needs to write to /system";
- print " ### " $0;
- next;
-}
-
-console_state == 0 && /^service console \/system\/bin\/sh$/ {
- console_state = 1;
- print;
- next;
-}
-
-console_state == 1 && /^ console$/ {
- console_state = 2;
- print;
- exit;
-}
-
-console_state == 1 {
- # The second line of the console entry should always immediately
- # follow the first.
- exit;
-}
-
-{ print }
-
-END {
- failed = 0;
- if (fixed_remount != 1) {
- print "ERROR: no match for remount line" > "/dev/stderr";
- failed = 1;
- }
- if (console_state != 2) {
- print "ERROR: no match for console lines" > "/dev/stderr";
- failed = 1;
- }
- if (failed == 1) {
- print ">>>> FAILED <<<<"
- exit 1;
- }
-}