blob: b01737d8f6cd9afe3fe1b5dc511979d483134926 [file] [log] [blame]
Joe Onorato0578cbc2016-10-19 17:03:06 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "aapt.h"
18#include "adb.h"
19#include "make.h"
20#include "print.h"
21#include "util.h"
22
23#include <sstream>
24#include <string>
25#include <vector>
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <unistd.h>
31
32#include <google/protobuf/stubs/common.h>
33
34using namespace std;
35
Joe Onorato6c97f492019-02-27 20:42:37 -050036#define NATIVE_TESTS "NATIVE_TESTS"
37
Joe Onorato0578cbc2016-10-19 17:03:06 -070038/**
39 * An entry from the command line for something that will be built, installed,
40 * and/or tested.
41 */
42struct Target {
43 bool build;
44 bool install;
45 bool test;
46 string pattern;
47 string name;
48 vector<string> actions;
49 Module module;
50
51 int testActionCount;
52
53 int testPassCount;
54 int testFailCount;
Makoto Onuki6fb2c972017-08-02 14:40:12 -070055 int unknownFailureCount; // unknown failure == "Process crashed", etc.
Joe Onorato0578cbc2016-10-19 17:03:06 -070056 bool actionsWithNoTests;
57
58 Target(bool b, bool i, bool t, const string& p);
59};
60
61Target::Target(bool b, bool i, bool t, const string& p)
62 :build(b),
63 install(i),
64 test(t),
65 pattern(p),
66 testActionCount(0),
67 testPassCount(0),
68 testFailCount(0),
Makoto Onuki6fb2c972017-08-02 14:40:12 -070069 unknownFailureCount(0),
Joe Onorato0578cbc2016-10-19 17:03:06 -070070 actionsWithNoTests(false)
71{
72}
73
74/**
75 * Command line options.
76 */
77struct Options {
78 // For help
79 bool runHelp;
80
Joe Onorato7acae742019-03-23 16:12:32 -070081 // For refreshing module-info.json
82 bool runRefresh;
83
Joe Onorato0578cbc2016-10-19 17:03:06 -070084 // For tab completion
85 bool runTab;
86 string tabPattern;
87
88 // For build/install/test
Joe Onorato6592c3c2016-11-12 16:34:25 -080089 bool noRestart;
Joe Onorato0578cbc2016-10-19 17:03:06 -070090 bool reboot;
91 vector<Target*> targets;
92
93 Options();
94 ~Options();
95};
96
97Options::Options()
98 :runHelp(false),
Joe Onorato7acae742019-03-23 16:12:32 -070099 runRefresh(false),
Joe Onorato0578cbc2016-10-19 17:03:06 -0700100 runTab(false),
Joe Onorato6592c3c2016-11-12 16:34:25 -0800101 noRestart(false),
Joe Onorato0578cbc2016-10-19 17:03:06 -0700102 reboot(false),
103 targets()
104{
105}
106
107Options::~Options()
108{
109}
110
111struct InstallApk
112{
113 TrackedFile file;
114 bool alwaysInstall;
115 bool installed;
116
117 InstallApk();
118 InstallApk(const InstallApk& that);
119 InstallApk(const string& filename, bool always);
120 ~InstallApk() {};
121};
122
123InstallApk::InstallApk()
124{
125}
126
127InstallApk::InstallApk(const InstallApk& that)
128 :file(that.file),
129 alwaysInstall(that.alwaysInstall),
130 installed(that.installed)
131{
132}
133
134InstallApk::InstallApk(const string& filename, bool always)
135 :file(filename),
136 alwaysInstall(always),
137 installed(false)
138{
139}
140
Joe Onorato6c97f492019-02-27 20:42:37 -0500141struct PushedFile
142{
143 TrackedFile file;
144 string dest;
145
146 PushedFile();
147 PushedFile(const PushedFile& that);
148 PushedFile(const string& filename, const string& dest);
149 ~PushedFile() {};
150};
151
152PushedFile::PushedFile()
153{
154}
155
156PushedFile::PushedFile(const PushedFile& that)
157 :file(that.file),
158 dest(that.dest)
159{
160}
161
162PushedFile::PushedFile(const string& f, const string& d)
163 :file(f),
164 dest(d)
165{
166}
Joe Onorato0578cbc2016-10-19 17:03:06 -0700167
168/**
169 * Record for an test that is going to be launched.
170 */
171struct TestAction {
172 TestAction();
173
174 // The package name from the apk
175 string packageName;
176
177 // The test runner class
178 string runner;
179
180 // The test class, or none if all tests should be run
181 string className;
182
183 // The original target that requested this action
184 Target* target;
185
186 // The number of tests that passed
187 int passCount;
188
189 // The number of tests that failed
190 int failCount;
191};
192
193TestAction::TestAction()
194 :passCount(0),
195 failCount(0)
196{
197}
198
199/**
200 * Record for an activity that is going to be launched.
201 */
202struct ActivityAction {
203 // The package name from the apk
204 string packageName;
205
206 // The test class, or none if all tests should be run
207 string className;
208};
209
210/**
211 * Callback class for the am instrument command.
212 */
213class TestResults: public InstrumentationCallbacks
214{
215public:
216 virtual void OnTestStatus(TestStatus& status);
217 virtual void OnSessionStatus(SessionStatus& status);
218
219 /**
220 * Set the TestAction that the tests are for.
221 * It will be updated with statistics as the tests run.
222 */
223 void SetCurrentAction(TestAction* action);
224
Makoto Onuki6fb2c972017-08-02 14:40:12 -0700225 bool IsSuccess();
226
227 string GetErrorMessage();
228
Joe Onorato0578cbc2016-10-19 17:03:06 -0700229private:
230 TestAction* m_currentAction;
Makoto Onuki6fb2c972017-08-02 14:40:12 -0700231 SessionStatus m_sessionStatus;
Joe Onorato0578cbc2016-10-19 17:03:06 -0700232};
233
234void
235TestResults::OnTestStatus(TestStatus& status)
236{
237 bool found;
238// printf("OnTestStatus\n");
239// status.PrintDebugString();
240 int32_t resultCode = status.has_results() ? status.result_code() : 0;
241
242 if (!status.has_results()) {
243 return;
244 }
245 const ResultsBundle &results = status.results();
246
247 int32_t currentTestNum = get_bundle_int(results, &found, "current", NULL);
248 if (!found) {
249 currentTestNum = -1;
250 }
251
252 int32_t testCount = get_bundle_int(results, &found, "numtests", NULL);
253 if (!found) {
254 testCount = -1;
255 }
256
257 string className = get_bundle_string(results, &found, "class", NULL);
258 if (!found) {
259 return;
260 }
261
262 string testName = get_bundle_string(results, &found, "test", NULL);
263 if (!found) {
264 return;
265 }
266
267 if (resultCode == 0) {
268 // test passed
269 m_currentAction->passCount++;
270 m_currentAction->target->testPassCount++;
271 } else if (resultCode == 1) {
272 // test starting
273 ostringstream line;
274 line << "Running";
275 if (currentTestNum > 0) {
276 line << ": " << currentTestNum;
277 if (testCount > 0) {
278 line << " of " << testCount;
279 }
280 }
MÃ¥rten Kongstad4dcd3e02017-07-03 15:11:24 +0200281 line << ": " << m_currentAction->target->name << ':' << className << "#" << testName;
Joe Onorato0578cbc2016-10-19 17:03:06 -0700282 print_one_line("%s", line.str().c_str());
Makoto Onuki6fb2c972017-08-02 14:40:12 -0700283 } else if ((resultCode == -1) || (resultCode == -2)) {
Joe Onorato0578cbc2016-10-19 17:03:06 -0700284 // test failed
Makoto Onuki6fb2c972017-08-02 14:40:12 -0700285 // Note -2 means an assertion failure, and -1 means other exceptions. We just treat them
286 // all as "failures".
Joe Onorato0578cbc2016-10-19 17:03:06 -0700287 m_currentAction->failCount++;
288 m_currentAction->target->testFailCount++;
MÃ¥rten Kongstad4dcd3e02017-07-03 15:11:24 +0200289 printf("%s\n%sFailed: %s:%s#%s%s\n", g_escapeClearLine, g_escapeRedBold,
290 m_currentAction->target->name.c_str(), className.c_str(), testName.c_str(),
291 g_escapeEndColor);
Joe Onorato0578cbc2016-10-19 17:03:06 -0700292
Joe Onorato50307d92019-05-01 12:51:05 -0700293 bool stackFound;
294 string stack = get_bundle_string(results, &stackFound, "stack", NULL);
295 if (status.has_logcat()) {
296 const string logcat = status.logcat();
297 if (logcat.length() > 0) {
298 printf("%s\n", logcat.c_str());
299 }
300 } else if (stackFound) {
Joe Onorato0578cbc2016-10-19 17:03:06 -0700301 printf("%s\n", stack.c_str());
302 }
303 }
304}
305
306void
Makoto Onuki6fb2c972017-08-02 14:40:12 -0700307TestResults::OnSessionStatus(SessionStatus& status)
Joe Onorato0578cbc2016-10-19 17:03:06 -0700308{
309 //status.PrintDebugString();
Makoto Onuki6fb2c972017-08-02 14:40:12 -0700310 m_sessionStatus = status;
311 if (m_currentAction && !IsSuccess()) {
312 m_currentAction->target->unknownFailureCount++;
313 }
Joe Onorato0578cbc2016-10-19 17:03:06 -0700314}
315
316void
317TestResults::SetCurrentAction(TestAction* action)
318{
319 m_currentAction = action;
320}
321
Makoto Onuki6fb2c972017-08-02 14:40:12 -0700322bool
323TestResults::IsSuccess()
324{
325 return m_sessionStatus.result_code() == -1; // Activity.RESULT_OK.
326}
327
328string
329TestResults::GetErrorMessage()
330{
331 bool found;
332 string shortMsg = get_bundle_string(m_sessionStatus.results(), &found, "shortMsg", NULL);
333 if (!found) {
334 return IsSuccess() ? "" : "Unknown failure";
335 }
336 return shortMsg;
337}
338
339
Joe Onorato0578cbc2016-10-19 17:03:06 -0700340/**
341 * Prints the usage statement / help text.
342 */
343static void
344print_usage(FILE* out) {
345 fprintf(out, "usage: bit OPTIONS PATTERN\n");
346 fprintf(out, "\n");
347 fprintf(out, " Build, sync and test android code.\n");
348 fprintf(out, "\n");
349 fprintf(out, " The -b -i and -t options allow you to specify which phases\n");
350 fprintf(out, " you want to run. If none of those options are given, then\n");
351 fprintf(out, " all phases are run. If any of these options are provided\n");
352 fprintf(out, " then only the listed phases are run.\n");
353 fprintf(out, "\n");
354 fprintf(out, " OPTIONS\n");
355 fprintf(out, " -b Run a build\n");
356 fprintf(out, " -i Install the targets\n");
357 fprintf(out, " -t Run the tests\n");
358 fprintf(out, "\n");
Joe Onorato6592c3c2016-11-12 16:34:25 -0800359 fprintf(out, " -n Don't reboot or restart\n");
Joe Onorato0578cbc2016-10-19 17:03:06 -0700360 fprintf(out, " -r If the runtime needs to be restarted, do a full reboot\n");
361 fprintf(out, " instead\n");
362 fprintf(out, "\n");
363 fprintf(out, " PATTERN\n");
364 fprintf(out, " One or more targets to build, install and test. The target\n");
365 fprintf(out, " names are the names that appear in the LOCAL_MODULE or\n");
366 fprintf(out, " LOCAL_PACKAGE_NAME variables in Android.mk or Android.bp files.\n");
367 fprintf(out, "\n");
368 fprintf(out, " Building and installing\n");
369 fprintf(out, " -----------------------\n");
370 fprintf(out, " The modules specified will be built and then installed. If the\n");
371 fprintf(out, " files are on the system partition, they will be synced and the\n");
372 fprintf(out, " attached device rebooted. If they are APKs that aren't on the\n");
373 fprintf(out, " system partition they are installed with adb install.\n");
374 fprintf(out, "\n");
375 fprintf(out, " For example:\n");
376 fprintf(out, " bit framework\n");
377 fprintf(out, " Builds framework.jar, syncs the system partition and reboots.\n");
378 fprintf(out, "\n");
379 fprintf(out, " bit SystemUI\n");
380 fprintf(out, " Builds SystemUI.apk, syncs the system partition and reboots.\n");
381 fprintf(out, "\n");
382 fprintf(out, " bit CtsProtoTestCases\n");
383 fprintf(out, " Builds this CTS apk, adb installs it, but does not run any\n");
384 fprintf(out, " tests.\n");
385 fprintf(out, "\n");
386 fprintf(out, " Running Unit Tests\n");
387 fprintf(out, " ------------------\n");
388 fprintf(out, " To run a unit test, list the test class names and optionally the\n");
389 fprintf(out, " test method after the module.\n");
390 fprintf(out, "\n");
391 fprintf(out, " For example:\n");
392 fprintf(out, " bit CtsProtoTestCases:*\n");
393 fprintf(out, " Builds this CTS apk, adb installs it, and runs all the tests\n");
394 fprintf(out, " contained in that apk.\n");
395 fprintf(out, "\n");
396 fprintf(out, " bit framework CtsProtoTestCases:*\n");
397 fprintf(out, " Builds the framework and the apk, syncs and reboots, then\n");
398 fprintf(out, " adb installs CtsProtoTestCases.apk, and runs all tests \n");
399 fprintf(out, " contained in that apk.\n");
400 fprintf(out, "\n");
401 fprintf(out, " bit CtsProtoTestCases:.ProtoOutputStreamBoolTest\n");
402 fprintf(out, " bit CtsProtoTestCases:android.util.proto.cts.ProtoOutputStreamBoolTest\n");
403 fprintf(out, " Builds and installs CtsProtoTestCases.apk, and runs all the\n");
404 fprintf(out, " tests in the ProtoOutputStreamBoolTest class.\n");
405 fprintf(out, "\n");
MÃ¥rten Kongstad4dcd3e02017-07-03 15:11:24 +0200406 fprintf(out, " bit CtsProtoTestCases:.ProtoOutputStreamBoolTest#testWrite\n");
Joe Onorato0578cbc2016-10-19 17:03:06 -0700407 fprintf(out, " Builds and installs CtsProtoTestCases.apk, and runs the testWrite\n");
408 fprintf(out, " test method on that class.\n");
409 fprintf(out, "\n");
MÃ¥rten Kongstad4dcd3e02017-07-03 15:11:24 +0200410 fprintf(out,
411 " bit "
412 "CtsProtoTestCases:.ProtoOutputStreamBoolTest#testWrite,.ProtoOutputStreamBoolTest#"
413 "testRepeated\n");
Joe Onorato0578cbc2016-10-19 17:03:06 -0700414 fprintf(out, " Builds and installs CtsProtoTestCases.apk, and runs the testWrite\n");
415 fprintf(out, " and testRepeated test methods on that class.\n");
416 fprintf(out, "\n");
Makoto Onuki164e7962017-07-06 16:20:11 -0700417 fprintf(out, " bit CtsProtoTestCases:android.util.proto.cts.\n");
418 fprintf(out, " Builds and installs CtsProtoTestCases.apk, and runs the tests in the java package\n");
419 fprintf(out, " \"android.util.proto.cts\".\n");
420 fprintf(out, "\n");
Joe Onorato0578cbc2016-10-19 17:03:06 -0700421 fprintf(out, " Launching an Activity\n");
422 fprintf(out, " ---------------------\n");
423 fprintf(out, " To launch an activity, specify the activity class name after\n");
424 fprintf(out, " the module name.\n");
425 fprintf(out, "\n");
426 fprintf(out, " For example:\n");
427 fprintf(out, " bit StatusBarTest:NotificationBuilderTest\n");
428 fprintf(out, " bit StatusBarTest:.NotificationBuilderTest\n");
429 fprintf(out, " bit StatusBarTest:com.android.statusbartest.NotificationBuilderTest\n");
430 fprintf(out, " Builds and installs StatusBarTest.apk, launches the\n");
431 fprintf(out, " com.android.statusbartest/.NotificationBuilderTest activity.\n");
432 fprintf(out, "\n");
433 fprintf(out, "\n");
Joe Onorato7acae742019-03-23 16:12:32 -0700434 fprintf(out, "usage: bit --refresh\n");
435 fprintf(out, "\n");
436 fprintf(out, " Update module-info.json, the cache of make goals that can be built.\n");
437 fprintf(out, "\n");
Joe Onorato0578cbc2016-10-19 17:03:06 -0700438 fprintf(out, "usage: bit --tab ...\n");
439 fprintf(out, "\n");
440 fprintf(out, " Lists the targets in a format for tab completion. To get tab\n");
441 fprintf(out, " completion, add this to your bash environment:\n");
442 fprintf(out, "\n");
443 fprintf(out, " complete -C \"bit --tab\" bit\n");
444 fprintf(out, "\n");
445 fprintf(out, " Sourcing android's build/envsetup.sh will do this for you\n");
446 fprintf(out, " automatically.\n");
447 fprintf(out, "\n");
448 fprintf(out, "\n");
449 fprintf(out, "usage: bit --help\n");
450 fprintf(out, "usage: bit -h\n");
451 fprintf(out, "\n");
452 fprintf(out, " Print this help message\n");
453 fprintf(out, "\n");
454}
455
456
457/**
458 * Sets the appropriate flag* variables. If there is a problem with the
459 * commandline arguments, prints the help message and exits with an error.
460 */
461static void
462parse_args(Options* options, int argc, const char** argv)
463{
464 // Help
465 if (argc == 2 && (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)) {
466 options->runHelp = true;
467 return;
468 }
469
Joe Onorato7acae742019-03-23 16:12:32 -0700470 // Refresh
471 if (argc == 2 && strcmp(argv[1], "--refresh") == 0) {
472 options->runRefresh = true;
473 return;
474 }
475
Joe Onorato0578cbc2016-10-19 17:03:06 -0700476 // Tab
477 if (argc >= 4 && strcmp(argv[1], "--tab") == 0) {
478 options->runTab = true;
479 options->tabPattern = argv[3];
480 return;
481 }
482
483 // Normal usage
484 bool anyPhases = false;
485 bool gotPattern = false;
486 bool flagBuild = false;
487 bool flagInstall = false;
488 bool flagTest = false;
489 for (int i=1; i < argc; i++) {
490 string arg(argv[i]);
491 if (arg[0] == '-') {
492 for (size_t j=1; j<arg.size(); j++) {
493 switch (arg[j]) {
494 case '-':
495 break;
496 case 'b':
497 if (gotPattern) {
498 gotPattern = false;
499 flagInstall = false;
500 flagTest = false;
501 }
502 flagBuild = true;
503 anyPhases = true;
504 break;
505 case 'i':
506 if (gotPattern) {
507 gotPattern = false;
508 flagBuild = false;
509 flagTest = false;
510 }
511 flagInstall = true;
512 anyPhases = true;
513 break;
514 case 't':
515 if (gotPattern) {
516 gotPattern = false;
517 flagBuild = false;
518 flagInstall = false;
519 }
520 flagTest = true;
521 anyPhases = true;
522 break;
Joe Onorato6592c3c2016-11-12 16:34:25 -0800523 case 'n':
524 options->noRestart = true;
525 break;
Joe Onorato0578cbc2016-10-19 17:03:06 -0700526 case 'r':
527 options->reboot = true;
528 break;
529 default:
530 fprintf(stderr, "Unrecognized option '%c'\n", arg[j]);
531 print_usage(stderr);
532 exit(1);
533 break;
534 }
535 }
536 } else {
537 Target* target = new Target(flagBuild || !anyPhases, flagInstall || !anyPhases,
538 flagTest || !anyPhases, arg);
539 size_t colonPos = arg.find(':');
540 if (colonPos == 0) {
541 fprintf(stderr, "Test / activity supplied without a module to build: %s\n",
542 arg.c_str());
543 print_usage(stderr);
Yunlian Jiang2cfa8492016-12-06 16:08:39 -0800544 delete target;
Joe Onorato0578cbc2016-10-19 17:03:06 -0700545 exit(1);
546 } else if (colonPos == string::npos) {
547 target->name = arg;
548 } else {
549 target->name.assign(arg, 0, colonPos);
550 size_t beginPos = colonPos+1;
551 size_t commaPos;
552 while (true) {
553 commaPos = arg.find(',', beginPos);
554 if (commaPos == string::npos) {
555 if (beginPos != arg.size()) {
556 target->actions.push_back(string(arg, beginPos, commaPos));
557 }
558 break;
559 } else {
560 if (commaPos != beginPos) {
561 target->actions.push_back(string(arg, beginPos, commaPos-beginPos));
562 }
563 beginPos = commaPos+1;
564 }
565 }
566 }
567 options->targets.push_back(target);
568 gotPattern = true;
569 }
570 }
571 // If no pattern was supplied, give an error
572 if (options->targets.size() == 0) {
573 fprintf(stderr, "No PATTERN supplied.\n\n");
574 print_usage(stderr);
575 exit(1);
576 }
577}
578
579/**
580 * Get an environment variable.
581 * Exits with an error if it is unset or the empty string.
582 */
583static string
584get_required_env(const char* name, bool quiet)
585{
586 const char* value = getenv(name);
587 if (value == NULL || value[0] == '\0') {
588 if (!quiet) {
589 fprintf(stderr, "%s not set. Did you source build/envsetup.sh,"
590 " run lunch and do a build?\n", name);
591 }
592 exit(1);
593 }
594 return string(value);
595}
596
597/**
598 * Get the out directory.
599 *
600 * This duplicates the logic in build/make/core/envsetup.mk (which hasn't changed since 2011)
601 * so that we don't have to wait for get_build_var make invocation.
602 */
603string
604get_out_dir()
605{
606 const char* out_dir = getenv("OUT_DIR");
607 if (out_dir == NULL || out_dir[0] == '\0') {
608 const char* common_base = getenv("OUT_DIR_COMMON_BASE");
609 if (common_base == NULL || common_base[0] == '\0') {
610 // We don't prefix with buildTop because we cd there and it
611 // makes all the filenames long when being pretty printed.
612 return "out";
613 } else {
Joe Onorato8a5bb632016-10-21 14:31:42 -0700614 char pwd[PATH_MAX];
615 if (getcwd(pwd, PATH_MAX) == NULL) {
616 fprintf(stderr, "Your pwd is too long.\n");
617 exit(1);
618 }
Joe Onorato0578cbc2016-10-19 17:03:06 -0700619 const char* slash = strrchr(pwd, '/');
620 if (slash == NULL) {
621 slash = "";
622 }
623 string result(common_base);
624 result += slash;
Joe Onorato0578cbc2016-10-19 17:03:06 -0700625 return result;
626 }
627 }
628 return string(out_dir);
629}
630
631/**
632 * Check that a system property on the device matches the expected value.
633 * Exits with an error if they don't.
634 */
635static void
636check_device_property(const string& property, const string& expected)
637{
638 int err;
639 string deviceValue = get_system_property(property, &err);
640 check_error(err);
641 if (deviceValue != expected) {
642 print_error("There is a mismatch between the build you just did and the device you");
643 print_error("are trying to sync it to in the %s system property", property.c_str());
644 print_error(" build: %s", expected.c_str());
645 print_error(" device: %s", deviceValue.c_str());
646 exit(1);
647 }
648}
649
Chih-Hung Hsiehc7edf072017-10-03 09:57:55 -0700650static void
651chdir_or_exit(const char *path) {
652 // TODO: print_command("cd", path);
653 if (0 != chdir(path)) {
654 print_error("Error: Could not chdir: %s", path);
655 exit(1);
656 }
657}
658
Joe Onorato0578cbc2016-10-19 17:03:06 -0700659/**
660 * Run the build, install, and test actions.
661 */
Makoto Onuki6fb2c972017-08-02 14:40:12 -0700662bool
Joe Onorato6592c3c2016-11-12 16:34:25 -0800663run_phases(vector<Target*> targets, const Options& options)
Joe Onorato0578cbc2016-10-19 17:03:06 -0700664{
665 int err = 0;
666
667 //
668 // Initialization
669 //
670
671 print_status("Initializing");
672
673 const string buildTop = get_required_env("ANDROID_BUILD_TOP", false);
674 const string buildProduct = get_required_env("TARGET_PRODUCT", false);
675 const string buildVariant = get_required_env("TARGET_BUILD_VARIANT", false);
676 const string buildType = get_required_env("TARGET_BUILD_TYPE", false);
Joe Onoratoce0bd062019-01-14 15:30:05 -0800677 const string buildOut = get_out_dir();
Chih-Hung Hsiehc7edf072017-10-03 09:57:55 -0700678 chdir_or_exit(buildTop.c_str());
Joe Onorato0578cbc2016-10-19 17:03:06 -0700679
Joe Onoratoce0bd062019-01-14 15:30:05 -0800680 BuildVars buildVars(buildOut, buildProduct, buildVariant, buildType);
681
682 const string buildDevice = buildVars.GetBuildVar("TARGET_DEVICE", false);
683 const string buildId = buildVars.GetBuildVar("BUILD_ID", false);
Dan Willemsena40118d2017-10-17 17:46:41 -0700684
Joe Onorato0578cbc2016-10-19 17:03:06 -0700685 // Get the modules for the targets
686 map<string,Module> modules;
687 read_modules(buildOut, buildDevice, &modules, false);
688 for (size_t i=0; i<targets.size(); i++) {
689 Target* target = targets[i];
690 map<string,Module>::iterator mod = modules.find(target->name);
691 if (mod != modules.end()) {
692 target->module = mod->second;
693 } else {
694 print_error("Error: Could not find module: %s", target->name.c_str());
Joe Onorato7acae742019-03-23 16:12:32 -0700695 fprintf(stderr, "Try running %sbit --refresh%s if you recently added %s%s%s.\n",
696 g_escapeBold, g_escapeEndColor,
697 g_escapeBold, target->name.c_str(), g_escapeEndColor);
Joe Onorato0578cbc2016-10-19 17:03:06 -0700698 err = 1;
699 }
700 }
701 if (err != 0) {
702 exit(1);
703 }
704
705 // Choose the goals
706 vector<string> goals;
707 for (size_t i=0; i<targets.size(); i++) {
708 Target* target = targets[i];
709 if (target->build) {
710 goals.push_back(target->name);
711 }
712 }
713
Joe Onoratob42201b2019-10-23 12:52:41 -0700714
Joe Onorato0578cbc2016-10-19 17:03:06 -0700715 // Figure out whether we need to sync the system and which apks to install
Joe Onorato6c97f492019-02-27 20:42:37 -0500716 string deviceTargetPath = buildOut + "/target/product/" + buildDevice;
717 string systemPath = deviceTargetPath + "/system/";
718 string dataPath = deviceTargetPath + "/data/";
Joe Onoratob42201b2019-10-23 12:52:41 -0700719 string testPath = deviceTargetPath + "/testcases/";
Joe Onorato0578cbc2016-10-19 17:03:06 -0700720 bool syncSystem = false;
721 bool alwaysSyncSystem = false;
Joe Onorato70edfa82018-12-14 15:46:27 -0800722 vector<string> systemFiles;
Joe Onorato0578cbc2016-10-19 17:03:06 -0700723 vector<InstallApk> installApks;
Joe Onorato6c97f492019-02-27 20:42:37 -0500724 vector<PushedFile> pushedFiles;
Joe Onorato0578cbc2016-10-19 17:03:06 -0700725 for (size_t i=0; i<targets.size(); i++) {
726 Target* target = targets[i];
727 if (target->install) {
728 for (size_t j=0; j<target->module.installed.size(); j++) {
729 const string& file = target->module.installed[j];
730 // System partition
731 if (starts_with(file, systemPath)) {
732 syncSystem = true;
Joe Onorato70edfa82018-12-14 15:46:27 -0800733 systemFiles.push_back(file);
Joe Onorato0578cbc2016-10-19 17:03:06 -0700734 if (!target->build) {
735 // If a system partition target didn't get built then
736 // it won't change we will always need to do adb sync
737 alwaysSyncSystem = true;
738 }
739 continue;
740 }
741 // Apk in the data partition
Joe Onoratob42201b2019-10-23 12:52:41 -0700742 if (ends_with(file, ".apk")
743 && (starts_with(file, dataPath) || starts_with(file, testPath))) {
Joe Onorato0578cbc2016-10-19 17:03:06 -0700744 // Always install it if we didn't build it because otherwise
745 // it will never have changed.
746 installApks.push_back(InstallApk(file, !target->build));
747 continue;
748 }
Joe Onorato6c97f492019-02-27 20:42:37 -0500749 // If it's a native test module, push it.
750 if (target->module.HasClass(NATIVE_TESTS) && starts_with(file, dataPath)) {
751 string installedPath(file.c_str() + deviceTargetPath.length());
752 pushedFiles.push_back(PushedFile(file, installedPath));
753 }
Joe Onorato0578cbc2016-10-19 17:03:06 -0700754 }
755 }
756 }
757 map<string,FileInfo> systemFilesBefore;
758 if (syncSystem && !alwaysSyncSystem) {
759 get_directory_contents(systemPath, &systemFilesBefore);
760 }
761
Joe Onorato70edfa82018-12-14 15:46:27 -0800762 if (systemFiles.size() > 0){
763 print_info("System files:");
764 for (size_t i=0; i<systemFiles.size(); i++) {
765 printf(" %s\n", systemFiles[i].c_str());
766 }
767 }
Joe Onorato6c97f492019-02-27 20:42:37 -0500768 if (pushedFiles.size() > 0){
769 print_info("Files to push:");
770 for (size_t i=0; i<pushedFiles.size(); i++) {
771 printf(" %s\n", pushedFiles[i].file.filename.c_str());
772 printf(" --> %s\n", pushedFiles[i].dest.c_str());
773 }
774 }
Joe Onorato70edfa82018-12-14 15:46:27 -0800775 if (installApks.size() > 0){
776 print_info("APKs to install:");
777 for (size_t i=0; i<installApks.size(); i++) {
778 printf(" %s\n", installApks[i].file.filename.c_str());
779 }
780 }
781
Joe Onorato0578cbc2016-10-19 17:03:06 -0700782 //
783 // Build
784 //
785
786 // Run the build
787 if (goals.size() > 0) {
788 print_status("Building");
789 err = build_goals(goals);
790 check_error(err);
791 }
792
793 //
794 // Install
795 //
796
797 // Sync the system partition and reboot
798 bool skipSync = false;
799 if (syncSystem) {
800 print_status("Syncing /system");
801
802 if (!alwaysSyncSystem) {
803 // If nothing changed and we weren't forced to sync, skip the reboot for speed.
804 map<string,FileInfo> systemFilesAfter;
805 get_directory_contents(systemPath, &systemFilesAfter);
806 skipSync = !directory_contents_differ(systemFilesBefore, systemFilesAfter);
807 }
808 if (skipSync) {
809 printf("Skipping sync because no files changed.\n");
810 } else {
811 // Do some sanity checks
812 check_device_property("ro.build.product", buildProduct);
813 check_device_property("ro.build.type", buildVariant);
814 check_device_property("ro.build.id", buildId);
815
816 // Stop & Sync
Joe Onorato6592c3c2016-11-12 16:34:25 -0800817 if (!options.noRestart) {
MÃ¥rten Kongstad4dcd3e02017-07-03 15:11:24 +0200818 err = run_adb("exec-out", "stop", NULL);
Joe Onorato6592c3c2016-11-12 16:34:25 -0800819 check_error(err);
820 }
Joe Onorato0578cbc2016-10-19 17:03:06 -0700821 err = run_adb("remount", NULL);
822 check_error(err);
823 err = run_adb("sync", "system", NULL);
824 check_error(err);
825
Joe Onorato6592c3c2016-11-12 16:34:25 -0800826 if (!options.noRestart) {
827 if (options.reboot) {
828 print_status("Rebooting");
Joe Onorato0578cbc2016-10-19 17:03:06 -0700829
Joe Onorato6592c3c2016-11-12 16:34:25 -0800830 err = run_adb("reboot", NULL);
831 check_error(err);
832 err = run_adb("wait-for-device", NULL);
833 check_error(err);
834 } else {
835 print_status("Restarting the runtime");
Joe Onorato0578cbc2016-10-19 17:03:06 -0700836
MÃ¥rten Kongstad4dcd3e02017-07-03 15:11:24 +0200837 err = run_adb("exec-out", "setprop", "sys.boot_completed", "0", NULL);
Joe Onorato6592c3c2016-11-12 16:34:25 -0800838 check_error(err);
MÃ¥rten Kongstad4dcd3e02017-07-03 15:11:24 +0200839 err = run_adb("exec-out", "start", NULL);
Joe Onorato6592c3c2016-11-12 16:34:25 -0800840 check_error(err);
Joe Onorato0578cbc2016-10-19 17:03:06 -0700841 }
Joe Onorato6592c3c2016-11-12 16:34:25 -0800842
843 while (true) {
844 string completed = get_system_property("sys.boot_completed", &err);
845 check_error(err);
846 if (completed == "1") {
847 break;
848 }
849 sleep(2);
850 }
851 sleep(1);
MÃ¥rten Kongstad4dcd3e02017-07-03 15:11:24 +0200852 err = run_adb("exec-out", "wm", "dismiss-keyguard", NULL);
Joe Onorato6592c3c2016-11-12 16:34:25 -0800853 check_error(err);
Joe Onorato0578cbc2016-10-19 17:03:06 -0700854 }
Joe Onorato0578cbc2016-10-19 17:03:06 -0700855 }
856 }
857
Joe Onorato6c97f492019-02-27 20:42:37 -0500858 // Push files
859 if (pushedFiles.size() > 0) {
860 print_status("Pushing files");
861 for (size_t i=0; i<pushedFiles.size(); i++) {
862 const PushedFile& pushed = pushedFiles[i];
863 string dir = dirname(pushed.dest);
864 if (dir.length() == 0 || dir == "/") {
865 // This isn't really a file inside the data directory. Just skip it.
866 continue;
867 }
868 // TODO: if (!apk.file.fileInfo.exists || apk.file.HasChanged())
MÃ¥rten Kongstad4dcd3e02017-07-03 15:11:24 +0200869 err = run_adb("exec-out", "mkdir", "-p", dir.c_str(), NULL);
Joe Onorato6c97f492019-02-27 20:42:37 -0500870 check_error(err);
Joe Onorato871cf3e2019-03-25 14:30:34 -0700871 err = run_adb("push", pushed.file.filename.c_str(), pushed.dest.c_str(), NULL);
Joe Onorato6c97f492019-02-27 20:42:37 -0500872 check_error(err);
873 // pushed.installed = true;
874 }
875 }
876
Joe Onorato0578cbc2016-10-19 17:03:06 -0700877 // Install APKs
878 if (installApks.size() > 0) {
879 print_status("Installing APKs");
880 for (size_t i=0; i<installApks.size(); i++) {
881 InstallApk& apk = installApks[i];
882 if (!apk.file.fileInfo.exists || apk.file.HasChanged()) {
883 // It didn't exist before or it changed, so int needs install
Jeff Sharkey5f9dc422017-07-06 12:13:42 -0600884 err = run_adb("install", "-r", "-g", apk.file.filename.c_str(), NULL);
Joe Onorato0578cbc2016-10-19 17:03:06 -0700885 check_error(err);
886 apk.installed = true;
887 } else {
888 printf("APK didn't change. Skipping install of %s\n", apk.file.filename.c_str());
889 }
890 }
891 }
892
893 //
894 // Actions
895 //
896
Joe Onorato6c97f492019-02-27 20:42:37 -0500897 // Whether there have been any tests run, so we can print a summary.
898 bool testsRun = false;
899
900 // Run the native tests.
901 // TODO: We don't have a good way of running these and capturing the output of
902 // them live. It'll take some work. On the other hand, if they're gtest tests,
903 // the output of gtest is not completely insane like the text output of the
904 // instrumentation tests. So for now, we'll just live with that.
905 for (size_t i=0; i<targets.size(); i++) {
906 Target* target = targets[i];
907 if (target->test && target->module.HasClass(NATIVE_TESTS)) {
908 // We don't have a clear signal from the build system which of the installed
909 // files is actually the test, so we guess by looking for one with the same
910 // leaf name as the module that is executable.
911 for (size_t j=0; j<target->module.installed.size(); j++) {
912 string filename = target->module.installed[j];
913 if (!starts_with(filename, dataPath)) {
914 // Native tests go into the data directory.
915 continue;
916 }
917 if (leafname(filename) != target->module.name) {
918 // This isn't the test executable.
919 continue;
920 }
921 if (!is_executable(filename)) {
922 continue;
923 }
924 string installedPath(filename.c_str() + deviceTargetPath.length());
925 printf("the magic one is: %s\n", filename.c_str());
926 printf(" and it's installed at: %s\n", installedPath.c_str());
927
928 // Convert bit-style actions to gtest test filter arguments
929 if (target->actions.size() > 0) {
930 testsRun = true;
931 target->testActionCount++;
932 bool runAll = false;
933 string filterArg("--gtest_filter=");
934 for (size_t k=0; k<target->actions.size(); k++) {
935 string actionString = target->actions[k];
936 if (actionString == "*") {
937 runAll = true;
938 } else {
939 filterArg += actionString;
940 if (k != target->actions.size()-1) {
941 // We would otherwise have to worry about this condition
942 // being true, and appending an extra ':', but we know that
943 // if the extra action is "*", then we'll just run all and
944 // won't use filterArg anyway, so just keep this condition
945 // simple.
946 filterArg += ':';
947 }
948 }
949 }
950 if (runAll) {
MÃ¥rten Kongstad4dcd3e02017-07-03 15:11:24 +0200951 err = run_adb("exec-out", installedPath.c_str(), NULL);
Joe Onorato6c97f492019-02-27 20:42:37 -0500952 } else {
MÃ¥rten Kongstad4dcd3e02017-07-03 15:11:24 +0200953 err = run_adb("exec-out", installedPath.c_str(), filterArg.c_str(), NULL);
Joe Onorato6c97f492019-02-27 20:42:37 -0500954 }
955 if (err == 0) {
956 target->testPassCount++;
957 } else {
958 target->testFailCount++;
959 }
960 }
961 }
962 }
963 }
964
Joe Onorato0578cbc2016-10-19 17:03:06 -0700965 // Inspect the apks, and figure out what is an activity and what needs a test runner
966 bool printedInspecting = false;
967 vector<TestAction> testActions;
968 vector<ActivityAction> activityActions;
969 for (size_t i=0; i<targets.size(); i++) {
970 Target* target = targets[i];
971 if (target->test) {
972 for (size_t j=0; j<target->module.installed.size(); j++) {
973 string filename = target->module.installed[j];
974
Joe Onoratob42201b2019-10-23 12:52:41 -0700975 // Skip of not apk in the data partition or test
976 if (!(ends_with(filename, ".apk")
977 && (starts_with(filename, dataPath) || starts_with(filename, testPath)))) {
Joe Onorato0578cbc2016-10-19 17:03:06 -0700978 continue;
979 }
980
981 if (!printedInspecting) {
982 printedInspecting = true;
983 print_status("Inspecting APKs");
984 }
985
986 Apk apk;
987 err = inspect_apk(&apk, filename);
988 check_error(err);
989
990 for (size_t k=0; k<target->actions.size(); k++) {
991 string actionString = target->actions[k];
992 if (actionString == "*") {
993 if (apk.runner.length() == 0) {
994 print_error("Error: Test requested for apk that doesn't"
995 " have an <instrumentation> tag: %s\n",
996 target->module.name.c_str());
997 exit(1);
998 }
999 TestAction action;
1000 action.packageName = apk.package;
1001 action.runner = apk.runner;
1002 action.target = target;
1003 testActions.push_back(action);
1004 target->testActionCount++;
1005 } else if (apk.HasActivity(actionString)) {
1006 ActivityAction action;
1007 action.packageName = apk.package;
1008 action.className = full_class_name(apk.package, actionString);
1009 activityActions.push_back(action);
1010 } else {
1011 if (apk.runner.length() == 0) {
1012 print_error("Error: Test requested for apk that doesn't"
1013 " have an <instrumentation> tag: %s\n",
1014 target->module.name.c_str());
1015 exit(1);
1016 }
1017 TestAction action;
1018 action.packageName = apk.package;
1019 action.runner = apk.runner;
1020 action.className = full_class_name(apk.package, actionString);
1021 action.target = target;
1022 testActions.push_back(action);
1023 target->testActionCount++;
1024 }
1025 }
1026 }
1027 }
1028 }
1029
1030 // Run the instrumentation tests
1031 TestResults testResults;
1032 if (testActions.size() > 0) {
1033 print_status("Running tests");
Joe Onorato6c97f492019-02-27 20:42:37 -05001034 testsRun = true;
Joe Onorato0578cbc2016-10-19 17:03:06 -07001035 for (size_t i=0; i<testActions.size(); i++) {
1036 TestAction& action = testActions[i];
1037 testResults.SetCurrentAction(&action);
1038 err = run_instrumentation_test(action.packageName, action.runner, action.className,
1039 &testResults);
1040 check_error(err);
1041 if (action.passCount == 0 && action.failCount == 0) {
1042 action.target->actionsWithNoTests = true;
1043 }
1044 int total = action.passCount + action.failCount;
1045 printf("%sRan %d test%s for %s. ", g_escapeClearLine,
1046 total, total > 1 ? "s" : "", action.target->name.c_str());
1047 if (action.passCount == 0 && action.failCount == 0) {
1048 printf("%s%d passed, %d failed%s\n", g_escapeYellowBold, action.passCount,
1049 action.failCount, g_escapeEndColor);
1050 } else if (action.failCount > 0) {
1051 printf("%d passed, %s%d failed%s\n", action.passCount, g_escapeRedBold,
1052 action.failCount, g_escapeEndColor);
1053 } else {
1054 printf("%s%d passed%s, %d failed\n", g_escapeGreenBold, action.passCount,
1055 g_escapeEndColor, action.failCount);
1056 }
Makoto Onuki6fb2c972017-08-02 14:40:12 -07001057 if (!testResults.IsSuccess()) {
1058 printf("\n%sTest didn't finish successfully: %s%s\n", g_escapeRedBold,
1059 testResults.GetErrorMessage().c_str(), g_escapeEndColor);
1060 }
Joe Onorato0578cbc2016-10-19 17:03:06 -07001061 }
1062 }
1063
1064 // Launch the activity
1065 if (activityActions.size() > 0) {
1066 print_status("Starting activity");
1067
1068 if (activityActions.size() > 1) {
1069 print_warning("Multiple activities specified. Will only start the first one:");
1070 for (size_t i=0; i<activityActions.size(); i++) {
1071 ActivityAction& action = activityActions[i];
1072 print_warning(" %s",
1073 pretty_component_name(action.packageName, action.className).c_str());
1074 }
1075 }
1076
1077 const ActivityAction& action = activityActions[0];
1078 string componentName = action.packageName + "/" + action.className;
MÃ¥rten Kongstad4dcd3e02017-07-03 15:11:24 +02001079 err = run_adb("exec-out", "am", "start", componentName.c_str(), NULL);
Joe Onorato0578cbc2016-10-19 17:03:06 -07001080 check_error(err);
1081 }
1082
1083 //
1084 // Print summary
1085 //
1086
1087 printf("\n%s--------------------------------------------%s\n", g_escapeBold, g_escapeEndColor);
1088
1089 // Build
1090 if (goals.size() > 0) {
1091 printf("%sBuilt:%s\n", g_escapeBold, g_escapeEndColor);
1092 for (size_t i=0; i<goals.size(); i++) {
1093 printf(" %s\n", goals[i].c_str());
1094 }
1095 }
1096
1097 // Install
1098 if (syncSystem) {
1099 if (skipSync) {
1100 printf("%sSkipped syncing /system partition%s\n", g_escapeBold, g_escapeEndColor);
1101 } else {
1102 printf("%sSynced /system partition%s\n", g_escapeBold, g_escapeEndColor);
1103 }
1104 }
1105 if (installApks.size() > 0) {
1106 bool printedTitle = false;
1107 for (size_t i=0; i<installApks.size(); i++) {
1108 const InstallApk& apk = installApks[i];
1109 if (apk.installed) {
1110 if (!printedTitle) {
1111 printf("%sInstalled:%s\n", g_escapeBold, g_escapeEndColor);
1112 printedTitle = true;
1113 }
1114 printf(" %s\n", apk.file.filename.c_str());
1115 }
1116 }
1117 printedTitle = false;
1118 for (size_t i=0; i<installApks.size(); i++) {
1119 const InstallApk& apk = installApks[i];
1120 if (!apk.installed) {
1121 if (!printedTitle) {
1122 printf("%sSkipped install:%s\n", g_escapeBold, g_escapeEndColor);
1123 printedTitle = true;
1124 }
1125 printf(" %s\n", apk.file.filename.c_str());
1126 }
1127 }
1128 }
1129
1130 // Tests
Makoto Onuki6fb2c972017-08-02 14:40:12 -07001131 bool hasErrors = false;
Joe Onorato6c97f492019-02-27 20:42:37 -05001132 if (testsRun) {
Joe Onorato0578cbc2016-10-19 17:03:06 -07001133 printf("%sRan tests:%s\n", g_escapeBold, g_escapeEndColor);
1134 size_t maxNameLength = 0;
1135 for (size_t i=0; i<targets.size(); i++) {
1136 Target* target = targets[i];
1137 if (target->test) {
1138 size_t len = target->name.length();
1139 if (len > maxNameLength) {
1140 maxNameLength = len;
1141 }
1142 }
1143 }
1144 string padding(maxNameLength, ' ');
1145 for (size_t i=0; i<targets.size(); i++) {
1146 Target* target = targets[i];
1147 if (target->testActionCount > 0) {
1148 printf(" %s%s", target->name.c_str(), padding.c_str() + target->name.length());
Makoto Onuki6fb2c972017-08-02 14:40:12 -07001149 if (target->unknownFailureCount > 0) {
1150 printf(" %sUnknown failure, see above message.%s\n",
1151 g_escapeRedBold, g_escapeEndColor);
1152 hasErrors = true;
1153 } else if (target->actionsWithNoTests) {
Joe Onorato0578cbc2016-10-19 17:03:06 -07001154 printf(" %s%d passed, %d failed%s\n", g_escapeYellowBold,
1155 target->testPassCount, target->testFailCount, g_escapeEndColor);
Makoto Onuki6fb2c972017-08-02 14:40:12 -07001156 hasErrors = true;
Joe Onorato0578cbc2016-10-19 17:03:06 -07001157 } else if (target->testFailCount > 0) {
1158 printf(" %d passed, %s%d failed%s\n", target->testPassCount,
1159 g_escapeRedBold, target->testFailCount, g_escapeEndColor);
Makoto Onuki6fb2c972017-08-02 14:40:12 -07001160 hasErrors = true;
Joe Onorato0578cbc2016-10-19 17:03:06 -07001161 } else {
1162 printf(" %s%d passed%s, %d failed\n", g_escapeGreenBold,
1163 target->testPassCount, g_escapeEndColor, target->testFailCount);
1164 }
1165 }
1166 }
1167 }
1168 if (activityActions.size() > 1) {
1169 printf("%sStarted Activity:%s\n", g_escapeBold, g_escapeEndColor);
1170 const ActivityAction& action = activityActions[0];
1171 printf(" %s\n", pretty_component_name(action.packageName, action.className).c_str());
1172 }
1173
1174 printf("%s--------------------------------------------%s\n", g_escapeBold, g_escapeEndColor);
Makoto Onuki6fb2c972017-08-02 14:40:12 -07001175 return !hasErrors;
Joe Onorato0578cbc2016-10-19 17:03:06 -07001176}
1177
1178/**
Joe Onorato7acae742019-03-23 16:12:32 -07001179 * Refresh module-info.
1180 */
1181void
1182run_refresh()
1183{
1184 int err;
1185
1186 print_status("Initializing");
1187 const string buildTop = get_required_env("ANDROID_BUILD_TOP", false);
1188 const string buildProduct = get_required_env("TARGET_PRODUCT", false);
1189 const string buildVariant = get_required_env("TARGET_BUILD_VARIANT", false);
1190 const string buildType = get_required_env("TARGET_BUILD_TYPE", false);
1191 const string buildOut = get_out_dir();
1192 chdir_or_exit(buildTop.c_str());
1193
1194 BuildVars buildVars(buildOut, buildProduct, buildVariant, buildType);
1195
1196 string buildDevice = buildVars.GetBuildVar("TARGET_DEVICE", false);
1197
1198 vector<string> goals;
1199 goals.push_back(buildOut + "/target/product/" + buildDevice + "/module-info.json");
1200
1201 print_status("Refreshing module-info.json");
1202 err = build_goals(goals);
1203 check_error(err);
1204}
1205
1206/**
Joe Onorato0578cbc2016-10-19 17:03:06 -07001207 * Implement tab completion of the target names from the all modules file.
1208 */
1209void
1210run_tab_completion(const string& word)
1211{
Joe Onoratoce0bd062019-01-14 15:30:05 -08001212 const string buildTop = get_required_env("ANDROID_BUILD_TOP", false);
Joe Onorato0578cbc2016-10-19 17:03:06 -07001213 const string buildProduct = get_required_env("TARGET_PRODUCT", false);
Joe Onoratoce0bd062019-01-14 15:30:05 -08001214 const string buildVariant = get_required_env("TARGET_BUILD_VARIANT", false);
1215 const string buildType = get_required_env("TARGET_BUILD_TYPE", false);
Joe Onorato0578cbc2016-10-19 17:03:06 -07001216 const string buildOut = get_out_dir();
Chih-Hung Hsiehc7edf072017-10-03 09:57:55 -07001217 chdir_or_exit(buildTop.c_str());
Joe Onorato0578cbc2016-10-19 17:03:06 -07001218
Joe Onoratoce0bd062019-01-14 15:30:05 -08001219 BuildVars buildVars(buildOut, buildProduct, buildVariant, buildType);
1220
1221 string buildDevice = buildVars.GetBuildVar("TARGET_DEVICE", false);
Joe Onorato0578cbc2016-10-19 17:03:06 -07001222
1223 map<string,Module> modules;
1224 read_modules(buildOut, buildDevice, &modules, true);
1225
1226 for (map<string,Module>::const_iterator it = modules.begin(); it != modules.end(); it++) {
1227 if (starts_with(it->first, word)) {
1228 printf("%s\n", it->first.c_str());
1229 }
1230 }
1231}
1232
1233/**
1234 * Main entry point.
1235 */
1236int
1237main(int argc, const char** argv)
1238{
1239 GOOGLE_PROTOBUF_VERIFY_VERSION;
1240 init_print();
1241
1242 Options options;
1243 parse_args(&options, argc, argv);
1244
1245 if (options.runHelp) {
1246 // Help
1247 print_usage(stdout);
1248 exit(0);
Joe Onorato7acae742019-03-23 16:12:32 -07001249 } else if (options.runRefresh) {
1250 run_refresh();
1251 exit(0);
Joe Onorato0578cbc2016-10-19 17:03:06 -07001252 } else if (options.runTab) {
1253 run_tab_completion(options.tabPattern);
1254 exit(0);
1255 } else {
1256 // Normal run
Makoto Onuki6fb2c972017-08-02 14:40:12 -07001257 exit(run_phases(options.targets, options) ? 0 : 1);
Joe Onorato0578cbc2016-10-19 17:03:06 -07001258 }
1259
1260 return 0;
1261}
1262