xref: /aosp_15_r20/frameworks/base/tools/bit/adb.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker  *
4*d57664e9SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker  *
8*d57664e9SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker  *
10*d57664e9SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker  * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker  */
16*d57664e9SAndroid Build Coastguard Worker 
17*d57664e9SAndroid Build Coastguard Worker #include "adb.h"
18*d57664e9SAndroid Build Coastguard Worker 
19*d57664e9SAndroid Build Coastguard Worker #include "command.h"
20*d57664e9SAndroid Build Coastguard Worker #include "print.h"
21*d57664e9SAndroid Build Coastguard Worker #include "util.h"
22*d57664e9SAndroid Build Coastguard Worker 
23*d57664e9SAndroid Build Coastguard Worker #include <errno.h>
24*d57664e9SAndroid Build Coastguard Worker #include <string.h>
25*d57664e9SAndroid Build Coastguard Worker #include <stdlib.h>
26*d57664e9SAndroid Build Coastguard Worker #include <unistd.h>
27*d57664e9SAndroid Build Coastguard Worker #include <sys/types.h>
28*d57664e9SAndroid Build Coastguard Worker #include <sys/wait.h>
29*d57664e9SAndroid Build Coastguard Worker #include <limits.h>
30*d57664e9SAndroid Build Coastguard Worker 
31*d57664e9SAndroid Build Coastguard Worker #include <iostream>
32*d57664e9SAndroid Build Coastguard Worker #include <istream>
33*d57664e9SAndroid Build Coastguard Worker #include <streambuf>
34*d57664e9SAndroid Build Coastguard Worker 
35*d57664e9SAndroid Build Coastguard Worker using namespace std;
36*d57664e9SAndroid Build Coastguard Worker 
37*d57664e9SAndroid Build Coastguard Worker struct Buffer: public streambuf
38*d57664e9SAndroid Build Coastguard Worker {
39*d57664e9SAndroid Build Coastguard Worker     Buffer(char* begin, size_t size);
40*d57664e9SAndroid Build Coastguard Worker };
41*d57664e9SAndroid Build Coastguard Worker 
Buffer(char * begin,size_t size)42*d57664e9SAndroid Build Coastguard Worker Buffer::Buffer(char* begin, size_t size)
43*d57664e9SAndroid Build Coastguard Worker {
44*d57664e9SAndroid Build Coastguard Worker     this->setg(begin, begin, begin + size);
45*d57664e9SAndroid Build Coastguard Worker }
46*d57664e9SAndroid Build Coastguard Worker 
47*d57664e9SAndroid Build Coastguard Worker int
run_adb(const char * first,...)48*d57664e9SAndroid Build Coastguard Worker run_adb(const char* first, ...)
49*d57664e9SAndroid Build Coastguard Worker {
50*d57664e9SAndroid Build Coastguard Worker     Command cmd("adb");
51*d57664e9SAndroid Build Coastguard Worker 
52*d57664e9SAndroid Build Coastguard Worker     if (first == NULL) {
53*d57664e9SAndroid Build Coastguard Worker         return 0;
54*d57664e9SAndroid Build Coastguard Worker     }
55*d57664e9SAndroid Build Coastguard Worker 
56*d57664e9SAndroid Build Coastguard Worker     cmd.AddArg(first);
57*d57664e9SAndroid Build Coastguard Worker 
58*d57664e9SAndroid Build Coastguard Worker     va_list args;
59*d57664e9SAndroid Build Coastguard Worker     va_start(args, first);
60*d57664e9SAndroid Build Coastguard Worker     while (true) {
61*d57664e9SAndroid Build Coastguard Worker         const char* arg = va_arg(args, char*);
62*d57664e9SAndroid Build Coastguard Worker         if (arg == NULL) {
63*d57664e9SAndroid Build Coastguard Worker             break;
64*d57664e9SAndroid Build Coastguard Worker         }
65*d57664e9SAndroid Build Coastguard Worker         cmd.AddArg(arg);
66*d57664e9SAndroid Build Coastguard Worker     }
67*d57664e9SAndroid Build Coastguard Worker     va_end(args);
68*d57664e9SAndroid Build Coastguard Worker 
69*d57664e9SAndroid Build Coastguard Worker     return run_command(cmd);
70*d57664e9SAndroid Build Coastguard Worker }
71*d57664e9SAndroid Build Coastguard Worker 
72*d57664e9SAndroid Build Coastguard Worker string
get_system_property(const string & name,int * err)73*d57664e9SAndroid Build Coastguard Worker get_system_property(const string& name, int* err)
74*d57664e9SAndroid Build Coastguard Worker {
75*d57664e9SAndroid Build Coastguard Worker     Command cmd("adb");
76*d57664e9SAndroid Build Coastguard Worker     cmd.AddArg("exec-out");
77*d57664e9SAndroid Build Coastguard Worker     cmd.AddArg("getprop");
78*d57664e9SAndroid Build Coastguard Worker     cmd.AddArg(name);
79*d57664e9SAndroid Build Coastguard Worker 
80*d57664e9SAndroid Build Coastguard Worker     return trim(get_command_output(cmd, err, false));
81*d57664e9SAndroid Build Coastguard Worker }
82*d57664e9SAndroid Build Coastguard Worker 
83*d57664e9SAndroid Build Coastguard Worker 
84*d57664e9SAndroid Build Coastguard Worker static uint64_t
read_varint(int fd,int * err,bool * done)85*d57664e9SAndroid Build Coastguard Worker read_varint(int fd, int* err, bool* done)
86*d57664e9SAndroid Build Coastguard Worker {
87*d57664e9SAndroid Build Coastguard Worker     uint32_t bits = 0;
88*d57664e9SAndroid Build Coastguard Worker     uint64_t result = 0;
89*d57664e9SAndroid Build Coastguard Worker     while (true) {
90*d57664e9SAndroid Build Coastguard Worker         uint8_t byte;
91*d57664e9SAndroid Build Coastguard Worker         ssize_t amt = read(fd, &byte, 1);
92*d57664e9SAndroid Build Coastguard Worker         if (amt == 0) {
93*d57664e9SAndroid Build Coastguard Worker             *done = true;
94*d57664e9SAndroid Build Coastguard Worker             return result;
95*d57664e9SAndroid Build Coastguard Worker         } else if (amt < 0) {
96*d57664e9SAndroid Build Coastguard Worker             return *err = errno;
97*d57664e9SAndroid Build Coastguard Worker         }
98*d57664e9SAndroid Build Coastguard Worker         result |= uint64_t(byte & 0x7F) << bits;
99*d57664e9SAndroid Build Coastguard Worker         if ((byte & 0x80) == 0) {
100*d57664e9SAndroid Build Coastguard Worker             return result;
101*d57664e9SAndroid Build Coastguard Worker         }
102*d57664e9SAndroid Build Coastguard Worker         bits += 7;
103*d57664e9SAndroid Build Coastguard Worker         if (bits > 64) {
104*d57664e9SAndroid Build Coastguard Worker             *err = -1;
105*d57664e9SAndroid Build Coastguard Worker             return 0;
106*d57664e9SAndroid Build Coastguard Worker         }
107*d57664e9SAndroid Build Coastguard Worker     }
108*d57664e9SAndroid Build Coastguard Worker }
109*d57664e9SAndroid Build Coastguard Worker 
110*d57664e9SAndroid Build Coastguard Worker static char*
read_sized_buffer(int fd,int * err,size_t * resultSize)111*d57664e9SAndroid Build Coastguard Worker read_sized_buffer(int fd, int* err, size_t* resultSize)
112*d57664e9SAndroid Build Coastguard Worker {
113*d57664e9SAndroid Build Coastguard Worker     bool done = false;
114*d57664e9SAndroid Build Coastguard Worker     uint64_t size = read_varint(fd, err, &done);
115*d57664e9SAndroid Build Coastguard Worker     if (*err != 0 || done) {
116*d57664e9SAndroid Build Coastguard Worker         return NULL;
117*d57664e9SAndroid Build Coastguard Worker     }
118*d57664e9SAndroid Build Coastguard Worker     if (size == 0) {
119*d57664e9SAndroid Build Coastguard Worker         *resultSize = 0;
120*d57664e9SAndroid Build Coastguard Worker         return NULL;
121*d57664e9SAndroid Build Coastguard Worker     }
122*d57664e9SAndroid Build Coastguard Worker     // 10 MB seems like a reasonable limit.
123*d57664e9SAndroid Build Coastguard Worker     if (size > 10*1024*1024) {
124*d57664e9SAndroid Build Coastguard Worker         print_error("result buffer too large: %llu", size);
125*d57664e9SAndroid Build Coastguard Worker         return NULL;
126*d57664e9SAndroid Build Coastguard Worker     }
127*d57664e9SAndroid Build Coastguard Worker     char* buf = (char*)malloc(size);
128*d57664e9SAndroid Build Coastguard Worker     if (buf == NULL) {
129*d57664e9SAndroid Build Coastguard Worker         print_error("Can't allocate a buffer of size for test results: %llu", size);
130*d57664e9SAndroid Build Coastguard Worker         return NULL;
131*d57664e9SAndroid Build Coastguard Worker     }
132*d57664e9SAndroid Build Coastguard Worker     int pos = 0;
133*d57664e9SAndroid Build Coastguard Worker     while (size - pos > 0) {
134*d57664e9SAndroid Build Coastguard Worker         ssize_t amt = read(fd, buf+pos, size-pos);
135*d57664e9SAndroid Build Coastguard Worker         if (amt == 0) {
136*d57664e9SAndroid Build Coastguard Worker             // early end of pipe
137*d57664e9SAndroid Build Coastguard Worker             print_error("Early end of pipe.");
138*d57664e9SAndroid Build Coastguard Worker             *err = -1;
139*d57664e9SAndroid Build Coastguard Worker             free(buf);
140*d57664e9SAndroid Build Coastguard Worker             return NULL;
141*d57664e9SAndroid Build Coastguard Worker         } else if (amt < 0) {
142*d57664e9SAndroid Build Coastguard Worker             // error
143*d57664e9SAndroid Build Coastguard Worker             *err = errno;
144*d57664e9SAndroid Build Coastguard Worker             free(buf);
145*d57664e9SAndroid Build Coastguard Worker             return NULL;
146*d57664e9SAndroid Build Coastguard Worker         }
147*d57664e9SAndroid Build Coastguard Worker         pos += amt;
148*d57664e9SAndroid Build Coastguard Worker     }
149*d57664e9SAndroid Build Coastguard Worker     *resultSize = (size_t)size;
150*d57664e9SAndroid Build Coastguard Worker     return buf;
151*d57664e9SAndroid Build Coastguard Worker }
152*d57664e9SAndroid Build Coastguard Worker 
153*d57664e9SAndroid Build Coastguard Worker static int
read_sized_proto(int fd,Message * message)154*d57664e9SAndroid Build Coastguard Worker read_sized_proto(int fd, Message* message)
155*d57664e9SAndroid Build Coastguard Worker {
156*d57664e9SAndroid Build Coastguard Worker     int err = 0;
157*d57664e9SAndroid Build Coastguard Worker     size_t size;
158*d57664e9SAndroid Build Coastguard Worker     char* buf = read_sized_buffer(fd, &err, &size);
159*d57664e9SAndroid Build Coastguard Worker     if (err != 0) {
160*d57664e9SAndroid Build Coastguard Worker         if (buf != NULL) {
161*d57664e9SAndroid Build Coastguard Worker             free(buf);
162*d57664e9SAndroid Build Coastguard Worker         }
163*d57664e9SAndroid Build Coastguard Worker         return err;
164*d57664e9SAndroid Build Coastguard Worker     } else if (size == 0) {
165*d57664e9SAndroid Build Coastguard Worker         if (buf != NULL) {
166*d57664e9SAndroid Build Coastguard Worker             free(buf);
167*d57664e9SAndroid Build Coastguard Worker         }
168*d57664e9SAndroid Build Coastguard Worker         return 0;
169*d57664e9SAndroid Build Coastguard Worker     } else if (buf == NULL) {
170*d57664e9SAndroid Build Coastguard Worker         return -1;
171*d57664e9SAndroid Build Coastguard Worker     }
172*d57664e9SAndroid Build Coastguard Worker     Buffer buffer(buf, size);
173*d57664e9SAndroid Build Coastguard Worker     istream in(&buffer);
174*d57664e9SAndroid Build Coastguard Worker 
175*d57664e9SAndroid Build Coastguard Worker     err = message->ParseFromIstream(&in) ? 0 : -1;
176*d57664e9SAndroid Build Coastguard Worker 
177*d57664e9SAndroid Build Coastguard Worker     free(buf);
178*d57664e9SAndroid Build Coastguard Worker     return err;
179*d57664e9SAndroid Build Coastguard Worker }
180*d57664e9SAndroid Build Coastguard Worker 
181*d57664e9SAndroid Build Coastguard Worker static int
skip_bytes(int fd,ssize_t size,char * scratch,int scratchSize)182*d57664e9SAndroid Build Coastguard Worker skip_bytes(int fd, ssize_t size, char* scratch, int scratchSize)
183*d57664e9SAndroid Build Coastguard Worker {
184*d57664e9SAndroid Build Coastguard Worker     while (size > 0) {
185*d57664e9SAndroid Build Coastguard Worker         ssize_t amt = size < scratchSize ? size : scratchSize;
186*d57664e9SAndroid Build Coastguard Worker         fprintf(stderr, "skipping %lu/%ld bytes\n", size, amt);
187*d57664e9SAndroid Build Coastguard Worker         amt = read(fd, scratch, amt);
188*d57664e9SAndroid Build Coastguard Worker         if (amt == 0) {
189*d57664e9SAndroid Build Coastguard Worker             // early end of pipe
190*d57664e9SAndroid Build Coastguard Worker             print_error("Early end of pipe.");
191*d57664e9SAndroid Build Coastguard Worker             return -1;
192*d57664e9SAndroid Build Coastguard Worker         } else if (amt < 0) {
193*d57664e9SAndroid Build Coastguard Worker             // error
194*d57664e9SAndroid Build Coastguard Worker             return errno;
195*d57664e9SAndroid Build Coastguard Worker         }
196*d57664e9SAndroid Build Coastguard Worker         size -= amt;
197*d57664e9SAndroid Build Coastguard Worker     }
198*d57664e9SAndroid Build Coastguard Worker     return 0;
199*d57664e9SAndroid Build Coastguard Worker }
200*d57664e9SAndroid Build Coastguard Worker 
201*d57664e9SAndroid Build Coastguard Worker static int
skip_unknown_field(int fd,uint64_t tag,char * scratch,int scratchSize)202*d57664e9SAndroid Build Coastguard Worker skip_unknown_field(int fd, uint64_t tag, char* scratch, int scratchSize) {
203*d57664e9SAndroid Build Coastguard Worker     bool done = false;
204*d57664e9SAndroid Build Coastguard Worker     int err;
205*d57664e9SAndroid Build Coastguard Worker     uint64_t size;
206*d57664e9SAndroid Build Coastguard Worker     switch (tag & 0x7) {
207*d57664e9SAndroid Build Coastguard Worker         case 0: // varint
208*d57664e9SAndroid Build Coastguard Worker             read_varint(fd, &err, &done);
209*d57664e9SAndroid Build Coastguard Worker             if (err != 0) {
210*d57664e9SAndroid Build Coastguard Worker                 return err;
211*d57664e9SAndroid Build Coastguard Worker             } else if (done) {
212*d57664e9SAndroid Build Coastguard Worker                 return -1;
213*d57664e9SAndroid Build Coastguard Worker             } else {
214*d57664e9SAndroid Build Coastguard Worker                 return 0;
215*d57664e9SAndroid Build Coastguard Worker             }
216*d57664e9SAndroid Build Coastguard Worker         case 1:
217*d57664e9SAndroid Build Coastguard Worker             return skip_bytes(fd, 8, scratch, scratchSize);
218*d57664e9SAndroid Build Coastguard Worker         case 2:
219*d57664e9SAndroid Build Coastguard Worker             size = read_varint(fd, &err, &done);
220*d57664e9SAndroid Build Coastguard Worker             if (err != 0) {
221*d57664e9SAndroid Build Coastguard Worker                 return err;
222*d57664e9SAndroid Build Coastguard Worker             } else if (done) {
223*d57664e9SAndroid Build Coastguard Worker                 return -1;
224*d57664e9SAndroid Build Coastguard Worker             }
225*d57664e9SAndroid Build Coastguard Worker             if (size > INT_MAX) {
226*d57664e9SAndroid Build Coastguard Worker                 // we'll be here a long time but this keeps it from overflowing
227*d57664e9SAndroid Build Coastguard Worker                 return -1;
228*d57664e9SAndroid Build Coastguard Worker             }
229*d57664e9SAndroid Build Coastguard Worker             return skip_bytes(fd, (ssize_t)size, scratch, scratchSize);
230*d57664e9SAndroid Build Coastguard Worker         case 5:
231*d57664e9SAndroid Build Coastguard Worker             return skip_bytes(fd, 4, scratch, scratchSize);
232*d57664e9SAndroid Build Coastguard Worker         default:
233*d57664e9SAndroid Build Coastguard Worker             print_error("bad wire type for tag 0x%lx\n", tag);
234*d57664e9SAndroid Build Coastguard Worker             return -1;
235*d57664e9SAndroid Build Coastguard Worker     }
236*d57664e9SAndroid Build Coastguard Worker }
237*d57664e9SAndroid Build Coastguard Worker 
238*d57664e9SAndroid Build Coastguard Worker static int
read_instrumentation_results(int fd,char * scratch,int scratchSize,InstrumentationCallbacks * callbacks)239*d57664e9SAndroid Build Coastguard Worker read_instrumentation_results(int fd, char* scratch, int scratchSize,
240*d57664e9SAndroid Build Coastguard Worker         InstrumentationCallbacks* callbacks)
241*d57664e9SAndroid Build Coastguard Worker {
242*d57664e9SAndroid Build Coastguard Worker     bool done = false;
243*d57664e9SAndroid Build Coastguard Worker     int err = 0;
244*d57664e9SAndroid Build Coastguard Worker     string result;
245*d57664e9SAndroid Build Coastguard Worker     while (true) {
246*d57664e9SAndroid Build Coastguard Worker         uint64_t tag = read_varint(fd, &err, &done);
247*d57664e9SAndroid Build Coastguard Worker         if (done) {
248*d57664e9SAndroid Build Coastguard Worker             // Done reading input (this is the only place that a stream end isn't an error).
249*d57664e9SAndroid Build Coastguard Worker             return 0;
250*d57664e9SAndroid Build Coastguard Worker         } else if (err != 0) {
251*d57664e9SAndroid Build Coastguard Worker             return err;
252*d57664e9SAndroid Build Coastguard Worker         } else if (tag == 0xa) { // test_status
253*d57664e9SAndroid Build Coastguard Worker             TestStatus status;
254*d57664e9SAndroid Build Coastguard Worker             err = read_sized_proto(fd, &status);
255*d57664e9SAndroid Build Coastguard Worker             if (err != 0) {
256*d57664e9SAndroid Build Coastguard Worker                 return err;
257*d57664e9SAndroid Build Coastguard Worker             }
258*d57664e9SAndroid Build Coastguard Worker             callbacks->OnTestStatus(status);
259*d57664e9SAndroid Build Coastguard Worker         } else if (tag == 0x12) { // session_status
260*d57664e9SAndroid Build Coastguard Worker             SessionStatus status;
261*d57664e9SAndroid Build Coastguard Worker             err = read_sized_proto(fd, &status);
262*d57664e9SAndroid Build Coastguard Worker             if (err != 0) {
263*d57664e9SAndroid Build Coastguard Worker                 return err;
264*d57664e9SAndroid Build Coastguard Worker             }
265*d57664e9SAndroid Build Coastguard Worker             callbacks->OnSessionStatus(status);
266*d57664e9SAndroid Build Coastguard Worker         } else {
267*d57664e9SAndroid Build Coastguard Worker             err = skip_unknown_field(fd, tag, scratch, scratchSize);
268*d57664e9SAndroid Build Coastguard Worker             if (err != 0) {
269*d57664e9SAndroid Build Coastguard Worker                 return err;
270*d57664e9SAndroid Build Coastguard Worker             }
271*d57664e9SAndroid Build Coastguard Worker         }
272*d57664e9SAndroid Build Coastguard Worker     }
273*d57664e9SAndroid Build Coastguard Worker     return 0;
274*d57664e9SAndroid Build Coastguard Worker }
275*d57664e9SAndroid Build Coastguard Worker 
276*d57664e9SAndroid Build Coastguard Worker int
run_instrumentation_test(const string & packageName,const string & runner,const string & className,InstrumentationCallbacks * callbacks)277*d57664e9SAndroid Build Coastguard Worker run_instrumentation_test(const string& packageName, const string& runner, const string& className,
278*d57664e9SAndroid Build Coastguard Worker         InstrumentationCallbacks* callbacks)
279*d57664e9SAndroid Build Coastguard Worker {
280*d57664e9SAndroid Build Coastguard Worker     Command cmd("adb");
281*d57664e9SAndroid Build Coastguard Worker     cmd.AddArg("exec-out");
282*d57664e9SAndroid Build Coastguard Worker     cmd.AddArg("am");
283*d57664e9SAndroid Build Coastguard Worker     cmd.AddArg("instrument");
284*d57664e9SAndroid Build Coastguard Worker     cmd.AddArg("-w");
285*d57664e9SAndroid Build Coastguard Worker     cmd.AddArg("-m");
286*d57664e9SAndroid Build Coastguard Worker     const int classLen = className.length();
287*d57664e9SAndroid Build Coastguard Worker     if (classLen > 0) {
288*d57664e9SAndroid Build Coastguard Worker         if (classLen > 1 && className[classLen - 1] == '.') {
289*d57664e9SAndroid Build Coastguard Worker             cmd.AddArg("-e");
290*d57664e9SAndroid Build Coastguard Worker             cmd.AddArg("package");
291*d57664e9SAndroid Build Coastguard Worker 
292*d57664e9SAndroid Build Coastguard Worker             // "am" actually accepts without removing the last ".", but for cleanlines...
293*d57664e9SAndroid Build Coastguard Worker             cmd.AddArg(className.substr(0, classLen - 1));
294*d57664e9SAndroid Build Coastguard Worker         } else {
295*d57664e9SAndroid Build Coastguard Worker             cmd.AddArg("-e");
296*d57664e9SAndroid Build Coastguard Worker             cmd.AddArg("class");
297*d57664e9SAndroid Build Coastguard Worker             cmd.AddArg(className);
298*d57664e9SAndroid Build Coastguard Worker         }
299*d57664e9SAndroid Build Coastguard Worker     }
300*d57664e9SAndroid Build Coastguard Worker     cmd.AddArg(packageName + "/" + runner);
301*d57664e9SAndroid Build Coastguard Worker 
302*d57664e9SAndroid Build Coastguard Worker     print_command(cmd);
303*d57664e9SAndroid Build Coastguard Worker 
304*d57664e9SAndroid Build Coastguard Worker     int fds[2];
305*d57664e9SAndroid Build Coastguard Worker     if (0 != pipe(fds)) {
306*d57664e9SAndroid Build Coastguard Worker         return errno;
307*d57664e9SAndroid Build Coastguard Worker     }
308*d57664e9SAndroid Build Coastguard Worker 
309*d57664e9SAndroid Build Coastguard Worker     pid_t pid = fork();
310*d57664e9SAndroid Build Coastguard Worker 
311*d57664e9SAndroid Build Coastguard Worker     if (pid == -1) {
312*d57664e9SAndroid Build Coastguard Worker         // fork error
313*d57664e9SAndroid Build Coastguard Worker         return errno;
314*d57664e9SAndroid Build Coastguard Worker     } else if (pid == 0) {
315*d57664e9SAndroid Build Coastguard Worker         // child
316*d57664e9SAndroid Build Coastguard Worker         while ((dup2(fds[1], STDOUT_FILENO) == -1) && (errno == EINTR)) {}
317*d57664e9SAndroid Build Coastguard Worker         close(fds[1]);
318*d57664e9SAndroid Build Coastguard Worker         close(fds[0]);
319*d57664e9SAndroid Build Coastguard Worker         const char* prog = cmd.GetProg();
320*d57664e9SAndroid Build Coastguard Worker         char* const* argv = cmd.GetArgv();
321*d57664e9SAndroid Build Coastguard Worker         char* const* env = cmd.GetEnv();
322*d57664e9SAndroid Build Coastguard Worker         exec_with_path_search(prog, argv, env);
323*d57664e9SAndroid Build Coastguard Worker         print_error("Unable to run command: %s", prog);
324*d57664e9SAndroid Build Coastguard Worker         exit(1);
325*d57664e9SAndroid Build Coastguard Worker     } else {
326*d57664e9SAndroid Build Coastguard Worker         // parent
327*d57664e9SAndroid Build Coastguard Worker         close(fds[1]);
328*d57664e9SAndroid Build Coastguard Worker         string result;
329*d57664e9SAndroid Build Coastguard Worker         const int size = 16*1024;
330*d57664e9SAndroid Build Coastguard Worker         char* buf = (char*)malloc(size);
331*d57664e9SAndroid Build Coastguard Worker         int err = read_instrumentation_results(fds[0], buf, size, callbacks);
332*d57664e9SAndroid Build Coastguard Worker         free(buf);
333*d57664e9SAndroid Build Coastguard Worker         int status;
334*d57664e9SAndroid Build Coastguard Worker         waitpid(pid, &status, 0);
335*d57664e9SAndroid Build Coastguard Worker         if (err != 0) {
336*d57664e9SAndroid Build Coastguard Worker             return err;
337*d57664e9SAndroid Build Coastguard Worker         }
338*d57664e9SAndroid Build Coastguard Worker         if (WIFEXITED(status)) {
339*d57664e9SAndroid Build Coastguard Worker             return WEXITSTATUS(status);
340*d57664e9SAndroid Build Coastguard Worker         } else {
341*d57664e9SAndroid Build Coastguard Worker             return -1;
342*d57664e9SAndroid Build Coastguard Worker         }
343*d57664e9SAndroid Build Coastguard Worker     }
344*d57664e9SAndroid Build Coastguard Worker }
345*d57664e9SAndroid Build Coastguard Worker 
346*d57664e9SAndroid Build Coastguard Worker /**
347*d57664e9SAndroid Build Coastguard Worker  * Get the second to last bundle in the args list. Stores the last name found
348*d57664e9SAndroid Build Coastguard Worker  * in last. If the path is not found or if the args list is empty, returns NULL.
349*d57664e9SAndroid Build Coastguard Worker  */
350*d57664e9SAndroid Build Coastguard Worker static const ResultsBundleEntry *
find_penultimate_entry(const ResultsBundle & bundle,va_list args)351*d57664e9SAndroid Build Coastguard Worker find_penultimate_entry(const ResultsBundle& bundle, va_list args)
352*d57664e9SAndroid Build Coastguard Worker {
353*d57664e9SAndroid Build Coastguard Worker     const ResultsBundle* b = &bundle;
354*d57664e9SAndroid Build Coastguard Worker     const char* arg = va_arg(args, char*);
355*d57664e9SAndroid Build Coastguard Worker     while (arg) {
356*d57664e9SAndroid Build Coastguard Worker         string last = arg;
357*d57664e9SAndroid Build Coastguard Worker         arg = va_arg(args, char*);
358*d57664e9SAndroid Build Coastguard Worker         bool found = false;
359*d57664e9SAndroid Build Coastguard Worker         for (int i=0; i<b->entries_size(); i++) {
360*d57664e9SAndroid Build Coastguard Worker             const ResultsBundleEntry& e = b->entries(i);
361*d57664e9SAndroid Build Coastguard Worker             if (e.key() == last) {
362*d57664e9SAndroid Build Coastguard Worker                 if (arg == NULL) {
363*d57664e9SAndroid Build Coastguard Worker                     return &e;
364*d57664e9SAndroid Build Coastguard Worker                 } else if (e.has_value_bundle()) {
365*d57664e9SAndroid Build Coastguard Worker                     b = &e.value_bundle();
366*d57664e9SAndroid Build Coastguard Worker                     found = true;
367*d57664e9SAndroid Build Coastguard Worker                 }
368*d57664e9SAndroid Build Coastguard Worker             }
369*d57664e9SAndroid Build Coastguard Worker         }
370*d57664e9SAndroid Build Coastguard Worker         if (!found) {
371*d57664e9SAndroid Build Coastguard Worker             return NULL;
372*d57664e9SAndroid Build Coastguard Worker         }
373*d57664e9SAndroid Build Coastguard Worker         if (arg == NULL) {
374*d57664e9SAndroid Build Coastguard Worker             return NULL;
375*d57664e9SAndroid Build Coastguard Worker         }
376*d57664e9SAndroid Build Coastguard Worker     }
377*d57664e9SAndroid Build Coastguard Worker     return NULL;
378*d57664e9SAndroid Build Coastguard Worker }
379*d57664e9SAndroid Build Coastguard Worker 
380*d57664e9SAndroid Build Coastguard Worker string
get_bundle_string(const ResultsBundle & bundle,bool * found,...)381*d57664e9SAndroid Build Coastguard Worker get_bundle_string(const ResultsBundle& bundle, bool* found, ...)
382*d57664e9SAndroid Build Coastguard Worker {
383*d57664e9SAndroid Build Coastguard Worker     va_list args;
384*d57664e9SAndroid Build Coastguard Worker     va_start(args, found);
385*d57664e9SAndroid Build Coastguard Worker     const ResultsBundleEntry* entry = find_penultimate_entry(bundle, args);
386*d57664e9SAndroid Build Coastguard Worker     va_end(args);
387*d57664e9SAndroid Build Coastguard Worker     if (entry == NULL) {
388*d57664e9SAndroid Build Coastguard Worker         *found = false;
389*d57664e9SAndroid Build Coastguard Worker         return string();
390*d57664e9SAndroid Build Coastguard Worker     }
391*d57664e9SAndroid Build Coastguard Worker     if (entry->has_value_string()) {
392*d57664e9SAndroid Build Coastguard Worker         *found = true;
393*d57664e9SAndroid Build Coastguard Worker         return entry->value_string();
394*d57664e9SAndroid Build Coastguard Worker     }
395*d57664e9SAndroid Build Coastguard Worker     *found = false;
396*d57664e9SAndroid Build Coastguard Worker     return string();
397*d57664e9SAndroid Build Coastguard Worker }
398*d57664e9SAndroid Build Coastguard Worker 
399*d57664e9SAndroid Build Coastguard Worker int32_t
get_bundle_int(const ResultsBundle & bundle,bool * found,...)400*d57664e9SAndroid Build Coastguard Worker get_bundle_int(const ResultsBundle& bundle, bool* found, ...)
401*d57664e9SAndroid Build Coastguard Worker {
402*d57664e9SAndroid Build Coastguard Worker     va_list args;
403*d57664e9SAndroid Build Coastguard Worker     va_start(args, found);
404*d57664e9SAndroid Build Coastguard Worker     const ResultsBundleEntry* entry = find_penultimate_entry(bundle, args);
405*d57664e9SAndroid Build Coastguard Worker     va_end(args);
406*d57664e9SAndroid Build Coastguard Worker     if (entry == NULL) {
407*d57664e9SAndroid Build Coastguard Worker         *found = false;
408*d57664e9SAndroid Build Coastguard Worker         return 0;
409*d57664e9SAndroid Build Coastguard Worker     }
410*d57664e9SAndroid Build Coastguard Worker     if (entry->has_value_int()) {
411*d57664e9SAndroid Build Coastguard Worker         *found = true;
412*d57664e9SAndroid Build Coastguard Worker         return entry->value_int();
413*d57664e9SAndroid Build Coastguard Worker     }
414*d57664e9SAndroid Build Coastguard Worker     *found = false;
415*d57664e9SAndroid Build Coastguard Worker     return 0;
416*d57664e9SAndroid Build Coastguard Worker }
417*d57664e9SAndroid Build Coastguard Worker 
418*d57664e9SAndroid Build Coastguard Worker float
get_bundle_float(const ResultsBundle & bundle,bool * found,...)419*d57664e9SAndroid Build Coastguard Worker get_bundle_float(const ResultsBundle& bundle, bool* found, ...)
420*d57664e9SAndroid Build Coastguard Worker {
421*d57664e9SAndroid Build Coastguard Worker     va_list args;
422*d57664e9SAndroid Build Coastguard Worker     va_start(args, found);
423*d57664e9SAndroid Build Coastguard Worker     const ResultsBundleEntry* entry = find_penultimate_entry(bundle, args);
424*d57664e9SAndroid Build Coastguard Worker     va_end(args);
425*d57664e9SAndroid Build Coastguard Worker     if (entry == NULL) {
426*d57664e9SAndroid Build Coastguard Worker         *found = false;
427*d57664e9SAndroid Build Coastguard Worker         return 0;
428*d57664e9SAndroid Build Coastguard Worker     }
429*d57664e9SAndroid Build Coastguard Worker     if (entry->has_value_float()) {
430*d57664e9SAndroid Build Coastguard Worker         *found = true;
431*d57664e9SAndroid Build Coastguard Worker         return entry->value_float();
432*d57664e9SAndroid Build Coastguard Worker     }
433*d57664e9SAndroid Build Coastguard Worker     *found = false;
434*d57664e9SAndroid Build Coastguard Worker     return 0;
435*d57664e9SAndroid Build Coastguard Worker }
436*d57664e9SAndroid Build Coastguard Worker 
437*d57664e9SAndroid Build Coastguard Worker double
get_bundle_double(const ResultsBundle & bundle,bool * found,...)438*d57664e9SAndroid Build Coastguard Worker get_bundle_double(const ResultsBundle& bundle, bool* found, ...)
439*d57664e9SAndroid Build Coastguard Worker {
440*d57664e9SAndroid Build Coastguard Worker     va_list args;
441*d57664e9SAndroid Build Coastguard Worker     va_start(args, found);
442*d57664e9SAndroid Build Coastguard Worker     const ResultsBundleEntry* entry = find_penultimate_entry(bundle, args);
443*d57664e9SAndroid Build Coastguard Worker     va_end(args);
444*d57664e9SAndroid Build Coastguard Worker     if (entry == NULL) {
445*d57664e9SAndroid Build Coastguard Worker         *found = false;
446*d57664e9SAndroid Build Coastguard Worker         return 0;
447*d57664e9SAndroid Build Coastguard Worker     }
448*d57664e9SAndroid Build Coastguard Worker     if (entry->has_value_double()) {
449*d57664e9SAndroid Build Coastguard Worker         *found = true;
450*d57664e9SAndroid Build Coastguard Worker         return entry->value_double();
451*d57664e9SAndroid Build Coastguard Worker     }
452*d57664e9SAndroid Build Coastguard Worker     *found = false;
453*d57664e9SAndroid Build Coastguard Worker     return 0;
454*d57664e9SAndroid Build Coastguard Worker }
455*d57664e9SAndroid Build Coastguard Worker 
456*d57664e9SAndroid Build Coastguard Worker int64_t
get_bundle_long(const ResultsBundle & bundle,bool * found,...)457*d57664e9SAndroid Build Coastguard Worker get_bundle_long(const ResultsBundle& bundle, bool* found, ...)
458*d57664e9SAndroid Build Coastguard Worker {
459*d57664e9SAndroid Build Coastguard Worker     va_list args;
460*d57664e9SAndroid Build Coastguard Worker     va_start(args, found);
461*d57664e9SAndroid Build Coastguard Worker     const ResultsBundleEntry* entry = find_penultimate_entry(bundle, args);
462*d57664e9SAndroid Build Coastguard Worker     va_end(args);
463*d57664e9SAndroid Build Coastguard Worker     if (entry == NULL) {
464*d57664e9SAndroid Build Coastguard Worker         *found = false;
465*d57664e9SAndroid Build Coastguard Worker         return 0;
466*d57664e9SAndroid Build Coastguard Worker     }
467*d57664e9SAndroid Build Coastguard Worker     if (entry->has_value_long()) {
468*d57664e9SAndroid Build Coastguard Worker         *found = true;
469*d57664e9SAndroid Build Coastguard Worker         return entry->value_long();
470*d57664e9SAndroid Build Coastguard Worker     }
471*d57664e9SAndroid Build Coastguard Worker     *found = false;
472*d57664e9SAndroid Build Coastguard Worker     return 0;
473*d57664e9SAndroid Build Coastguard Worker }
474*d57664e9SAndroid Build Coastguard Worker 
475