OSDN Git Service

358f0ca15a0bb43fbce521836b4a9fe0058632bf
[android-x86/build.git] / tools / dexpreopt / dexopt-wrapper / DexOptWrapper.cpp
1 /*
2  * dexopt invocation test.
3  *
4  * You must have BOOTCLASSPATH defined.  On the simulator, you will also
5  * need ANDROID_ROOT.
6  */
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <unistd.h>
10 #include <string.h>
11 #include <sys/types.h>
12 #include <sys/wait.h>
13 #include <sys/file.h>
14 #include <fcntl.h>
15 #include <errno.h>
16
17 //using namespace android;
18
19 /*
20  * Privilege reduction function.
21  *
22  * Returns 0 on success, nonzero on failure.
23  */
24 static int privFunc(void)
25 {
26     printf("--- would reduce privs here\n");
27     return 0;
28 }
29
30 /*
31  * We're in the child process.  exec dexopt.
32  */
33 static void runDexopt(int zipFd, int odexFd, const char* inputFileName)
34 {
35     static const char* kDexOptBin = "/bin/dexopt";
36     static const int kMaxIntLen = 12;   // '-'+10dig+'\0' -OR- 0x+8dig
37     char zipNum[kMaxIntLen];
38     char odexNum[kMaxIntLen];
39     const char* androidRoot;
40     char* execFile;
41
42     /* find dexopt executable; this exists for simulator compatibility */
43     androidRoot = getenv("ANDROID_ROOT");
44     if (androidRoot == NULL)
45         androidRoot = "/system";
46     execFile = (char*) malloc(strlen(androidRoot) + strlen(kDexOptBin) +1);
47     sprintf(execFile, "%s%s", androidRoot, kDexOptBin);
48
49     sprintf(zipNum, "%d", zipFd);
50     sprintf(odexNum, "%d", odexFd);
51
52     execl(execFile, execFile, "--zip", zipNum, odexNum, inputFileName,
53         (char*) NULL);
54     fprintf(stderr, "execl(%s) failed: %s\n", kDexOptBin, strerror(errno));
55 }
56
57 /*
58  * Run dexopt on the specified Jar/APK.
59  *
60  * This uses fork() and exec() to mimic the way this would work in an
61  * installer; in practice for something this simple you could just exec()
62  * unless you really wanted the status messages.
63  *
64  * Returns 0 on success.
65  */
66 int doStuff(const char* zipName, const char* odexName)
67 {
68     int zipFd, odexFd;
69
70     /*
71      * Open the zip archive and the odex file, creating the latter (and
72      * failing if it already exists).  This must be done while we still
73      * have sufficient privileges to read the source file and create a file
74      * in the target directory.  The "classes.dex" file will be extracted.
75      */
76     zipFd = open(zipName, O_RDONLY, 0);
77     if (zipFd < 0) {
78         fprintf(stderr, "Unable to open '%s': %s\n", zipName, strerror(errno));
79         return 1;
80     }
81
82     odexFd = open(odexName, O_RDWR | O_CREAT | O_EXCL, 0644);
83     if (odexFd < 0) {
84         fprintf(stderr, "Unable to create '%s': %s\n",
85             odexName, strerror(errno));
86         close(zipFd);
87         return 1;
88     }
89
90     printf("--- BEGIN '%s' (bootstrap=%d) ---\n", zipName, 0);
91
92     /*
93      * Fork a child process.
94      */
95     pid_t pid = fork();
96     if (pid == 0) {
97         /* child -- drop privs */
98         if (privFunc() != 0)
99             exit(66);
100
101         /* lock the input file */
102         if (flock(odexFd, LOCK_EX | LOCK_NB) != 0) {
103             fprintf(stderr, "Unable to lock '%s': %s\n",
104                 odexName, strerror(errno));
105             exit(65);
106         }
107
108         runDexopt(zipFd, odexFd, zipName);  /* does not return */
109         exit(67);                           /* usually */
110     } else {
111         /* parent -- wait for child to finish */
112         printf("waiting for verify+opt, pid=%d\n", (int) pid);
113         int status, oldStatus;
114         pid_t gotPid;
115
116         close(zipFd);
117         close(odexFd);
118
119         /*
120          * Wait for the optimization process to finish.
121          */
122         while (true) {
123             gotPid = waitpid(pid, &status, 0);
124             if (gotPid == -1 && errno == EINTR) {
125                 printf("waitpid interrupted, retrying\n");
126             } else {
127                 break;
128             }
129         }
130         if (gotPid != pid) {
131             fprintf(stderr, "waitpid failed: wanted %d, got %d: %s\n",
132                 (int) pid, (int) gotPid, strerror(errno));
133             return 1;
134         }
135
136         if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
137             printf("--- END '%s' (success) ---\n", zipName);
138             return 0;
139         } else {
140             printf("--- END '%s' --- status=0x%04x, process failed\n",
141                 zipName, status);
142             return 1;
143         }
144     }
145
146     /* notreached */
147 }
148
149 /*
150  * Parse args, do stuff.
151  */
152 int main(int argc, char** argv)
153 {
154     if (argc < 3 || argc > 4) {
155         fprintf(stderr, "Usage: %s <input jar/apk> <output odex> "
156             "[<bootclasspath>]\n\n", argv[0]);
157         fprintf(stderr, "Example: dexopttest "
158             "/system/app/NotePad.apk /system/app/NotePad.odex\n");
159         return 2;
160     }
161
162     if (argc > 3) {
163         setenv("BOOTCLASSPATH", argv[3], 1);
164     }
165
166     return (doStuff(argv[1], argv[2]) != 0);
167 }