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