summaryrefslogtreecommitdiffstats
path: root/tools/dexpreopt/dexopt-wrapper/DexOptWrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/dexpreopt/dexopt-wrapper/DexOptWrapper.cpp')
-rw-r--r--tools/dexpreopt/dexopt-wrapper/DexOptWrapper.cpp173
1 files changed, 173 insertions, 0 deletions
diff --git a/tools/dexpreopt/dexopt-wrapper/DexOptWrapper.cpp b/tools/dexpreopt/dexopt-wrapper/DexOptWrapper.cpp
new file mode 100644
index 0000000..fde2d08
--- /dev/null
+++ b/tools/dexpreopt/dexopt-wrapper/DexOptWrapper.cpp
@@ -0,0 +1,173 @@
+/*
+ * 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);
+}