From 1448b0b7023a43ff4461cc66d25230c9b6502724 Mon Sep 17 00:00:00 2001 From: Ying Wang Date: Sun, 26 Sep 2010 13:11:16 -0700 Subject: [PATCH] Remove emulator-based dexpreopt code Now dexpreopt is done on the host side. Change-Id: I1ea1a5d1fac2531028e017364ef870abb7420be7 --- tools/dexpreopt/Android.mk | 38 - tools/dexpreopt/Config.mk | 153 --- tools/dexpreopt/afar/Android.mk | 29 - tools/dexpreopt/afar/main.c | 247 ----- tools/dexpreopt/dexopt-wrapper/Android.mk | 36 - .../dexopt-wrapper/DexOptWrapper.cpp | 173 --- tools/dexpreopt/dexpreopt.py | 986 ------------------ tools/dexpreopt/geninitrc.awk | 62 -- 8 files changed, 1724 deletions(-) delete mode 100644 tools/dexpreopt/Android.mk delete mode 100644 tools/dexpreopt/Config.mk delete mode 100644 tools/dexpreopt/afar/Android.mk delete mode 100644 tools/dexpreopt/afar/main.c delete mode 100644 tools/dexpreopt/dexopt-wrapper/Android.mk delete mode 100644 tools/dexpreopt/dexopt-wrapper/DexOptWrapper.cpp delete mode 100755 tools/dexpreopt/dexpreopt.py delete mode 100644 tools/dexpreopt/geninitrc.awk diff --git a/tools/dexpreopt/Android.mk b/tools/dexpreopt/Android.mk deleted file mode 100644 index 40aeee2e3..000000000 --- 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 b2b32c6a4..000000000 --- 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 9f1b987ac..000000000 --- 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 d66d59c8c..000000000 --- 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 -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include // 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 ", 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 ae2b6a3e7..000000000 --- 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 102cf0e7c..000000000 --- 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#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 " - "[]\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 376f1359d..000000000 --- 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 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., /app/NotePad.odex would be copied to - /app/NotePad.odex, and /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 -Required options: - -kernel Kernel to use when running the emulator - -ramdisk Ramdisk to use when running the emulator - -image 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 The product directory, which usually contains - files like 'system.img' (files other than - the kernel in that directory won't - be used) - -outsystemdir 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 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 4b67e78e0..000000000 --- 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; - } -}