1 /*
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 
34 using namespace std;
35 
36 #define NATIVE_TESTS "NATIVE_TESTS"
37 
38 /**
39  * An entry from the command line for something that will be built, installed,
40  * and/or tested.
41  */
42 struct 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;
55     int testIgnoreCount;
56     int unknownFailureCount; // unknown failure == "Process crashed", etc.
57 
58     Target(bool b, bool i, bool t, const string& p);
59 };
60 
Target(bool b,bool i,bool t,const string & p)61 Target::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),
69         testIgnoreCount(0),
70         unknownFailureCount(0) {}
71 
72 /**
73  * Command line options.
74  */
75 struct Options {
76     // For help
77     bool runHelp;
78 
79     // For refreshing module-info.json
80     bool runRefresh;
81 
82     // For tab completion
83     bool runTab;
84     string tabPattern;
85 
86     // For build/install/test
87     bool noRestart;
88     bool reboot;
89     vector<Target*> targets;
90 
91     Options();
92     ~Options();
93 };
94 
Options()95 Options::Options()
96     :runHelp(false),
97      runRefresh(false),
98      runTab(false),
99      noRestart(false),
100      reboot(false),
101      targets()
102 {
103 }
104 
~Options()105 Options::~Options()
106 {
107 }
108 
109 struct InstallApk
110 {
111     TrackedFile file;
112     bool alwaysInstall;
113     bool installed;
114 
115     InstallApk();
116     InstallApk(const InstallApk& that);
117     InstallApk(const string& filename, bool always);
~InstallApkInstallApk118     ~InstallApk() {};
119 };
120 
InstallApk()121 InstallApk::InstallApk()
122 {
123 }
124 
InstallApk(const InstallApk & that)125 InstallApk::InstallApk(const InstallApk& that)
126     :file(that.file),
127      alwaysInstall(that.alwaysInstall),
128      installed(that.installed)
129 {
130 }
131 
InstallApk(const string & filename,bool always)132 InstallApk::InstallApk(const string& filename, bool always)
133     :file(filename),
134      alwaysInstall(always),
135      installed(false)
136 {
137 }
138 
139 struct PushedFile
140 {
141     TrackedFile file;
142     string dest;
143 
144     PushedFile();
145     PushedFile(const PushedFile& that);
146     PushedFile(const string& filename, const string& dest);
~PushedFilePushedFile147     ~PushedFile() {};
148 };
149 
PushedFile()150 PushedFile::PushedFile()
151 {
152 }
153 
PushedFile(const PushedFile & that)154 PushedFile::PushedFile(const PushedFile& that)
155     :file(that.file),
156      dest(that.dest)
157 {
158 }
159 
PushedFile(const string & f,const string & d)160 PushedFile::PushedFile(const string& f, const string& d)
161     :file(f),
162      dest(d)
163 {
164 }
165 
166 /**
167  * Record for an test that is going to be launched.
168  */
169 struct TestAction {
170     TestAction();
171 
172     // The package name from the apk
173     string packageName;
174 
175     // The test runner class
176     string runner;
177 
178     // The test class, or none if all tests should be run
179     string className;
180 
181     // The original target that requested this action
182     Target* target;
183 
184     // The number of tests that passed
185     int passCount;
186 
187     // The number of tests that failed
188     int failCount;
189 
190     // The number of tests that were ignored (because of @Ignore)
191     int ignoreCount;
192 };
193 
TestAction()194 TestAction::TestAction() : passCount(0), failCount(0), ignoreCount(0) {}
195 
196 /**
197  * Record for an activity that is going to be launched.
198  */
199 struct ActivityAction {
200     // The package name from the apk
201     string packageName;
202 
203     // The test class, or none if all tests should be run
204     string className;
205 };
206 
207 /**
208  * Callback class for the am instrument command.
209  */
210 class TestResults: public InstrumentationCallbacks
211 {
212 public:
213     virtual void OnTestStatus(TestStatus& status);
214     virtual void OnSessionStatus(SessionStatus& status);
215 
216     /**
217      * Set the TestAction that the tests are for.
218      * It will be updated with statistics as the tests run.
219      */
220     void SetCurrentAction(TestAction* action);
221 
222     bool IsSuccess();
223 
224     string GetErrorMessage();
225 
226 private:
227     TestAction* m_currentAction;
228     SessionStatus m_sessionStatus;
229 };
230 
231 void
OnTestStatus(TestStatus & status)232 TestResults::OnTestStatus(TestStatus& status)
233 {
234     bool found;
235 //    printf("OnTestStatus\n");
236 //    status.PrintDebugString();
237     int32_t resultCode = status.has_results() ? status.result_code() : 0;
238 
239     if (!status.has_results()) {
240         return;
241     }
242     const ResultsBundle &results = status.results();
243 
244     int32_t currentTestNum = get_bundle_int(results, &found, "current", NULL);
245     if (!found) {
246         currentTestNum = -1;
247     }
248 
249     int32_t testCount = get_bundle_int(results, &found, "numtests", NULL);
250     if (!found) {
251         testCount = -1;
252     }
253 
254     string className = get_bundle_string(results, &found, "class", NULL);
255     if (!found) {
256         return;
257     }
258 
259     string testName = get_bundle_string(results, &found, "test", NULL);
260     if (!found) {
261         return;
262     }
263 
264     if (resultCode == 0) {
265         // test passed
266         m_currentAction->passCount++;
267         m_currentAction->target->testPassCount++;
268     } else if (resultCode == 1) {
269         // test starting
270         ostringstream line;
271         line << "Running";
272         if (currentTestNum > 0) {
273             line << ": " << currentTestNum;
274             if (testCount > 0) {
275                 line << " of " << testCount;
276             }
277         }
278         line << ": " << m_currentAction->target->name << ':' << className << "#" << testName;
279         print_one_line("%s", line.str().c_str());
280     } else if ((resultCode == -1) || (resultCode == -2)) {
281         // test failed
282         // Note -2 means an assertion failure, and -1 means other exceptions.  We just treat them
283         // all as "failures".
284         m_currentAction->failCount++;
285         m_currentAction->target->testFailCount++;
286         printf("%s\n%sFailed: %s:%s#%s%s\n", g_escapeClearLine, g_escapeRedBold,
287                m_currentAction->target->name.c_str(), className.c_str(), testName.c_str(),
288                g_escapeEndColor);
289 
290         bool stackFound;
291         string stack = get_bundle_string(results, &stackFound, "stack", NULL);
292         if (status.has_logcat()) {
293             const string logcat = status.logcat();
294             if (logcat.length() > 0) {
295                 printf("%s\n", logcat.c_str());
296             }
297         } else if (stackFound) {
298             printf("%s\n", stack.c_str());
299         }
300     } else if (resultCode == -3) {
301         // test ignored
302         m_currentAction->ignoreCount++;
303         m_currentAction->target->testIgnoreCount++;
304         printf("%s\n%sIgnored: %s:%s#%s%s\n", g_escapeClearLine, g_escapeYellowBold,
305                m_currentAction->target->name.c_str(), className.c_str(), testName.c_str(),
306                g_escapeEndColor);
307     }
308 }
309 
310 void
OnSessionStatus(SessionStatus & status)311 TestResults::OnSessionStatus(SessionStatus& status)
312 {
313     //status.PrintDebugString();
314     m_sessionStatus = status;
315     if (m_currentAction && !IsSuccess()) {
316         m_currentAction->target->unknownFailureCount++;
317     }
318 }
319 
320 void
SetCurrentAction(TestAction * action)321 TestResults::SetCurrentAction(TestAction* action)
322 {
323     m_currentAction = action;
324 }
325 
326 bool
IsSuccess()327 TestResults::IsSuccess()
328 {
329     return m_sessionStatus.result_code() == -1; // Activity.RESULT_OK.
330 }
331 
332 string
GetErrorMessage()333 TestResults::GetErrorMessage()
334 {
335     bool found;
336     string shortMsg = get_bundle_string(m_sessionStatus.results(), &found, "shortMsg", NULL);
337     if (!found) {
338         return IsSuccess() ? "" : "Unknown failure";
339     }
340     return shortMsg;
341 }
342 
343 
344 /**
345  * Prints the usage statement / help text.
346  */
347 static void
print_usage(FILE * out)348 print_usage(FILE* out) {
349     fprintf(out, "usage: bit OPTIONS PATTERN\n");
350     fprintf(out, "\n");
351     fprintf(out, "  Build, sync and test android code.\n");
352     fprintf(out, "\n");
353     fprintf(out, "  The -b -i and -t options allow you to specify which phases\n");
354     fprintf(out, "  you want to run. If none of those options are given, then\n");
355     fprintf(out, "  all phases are run. If any of these options are provided\n");
356     fprintf(out, "  then only the listed phases are run.\n");
357     fprintf(out, "\n");
358     fprintf(out, "  OPTIONS\n");
359     fprintf(out, "  -b     Run a build\n");
360     fprintf(out, "  -i     Install the targets\n");
361     fprintf(out, "  -t     Run the tests\n");
362     fprintf(out, "\n");
363     fprintf(out, "  -n     Don't reboot or restart\n");
364     fprintf(out, "  -r     If the runtime needs to be restarted, do a full reboot\n");
365     fprintf(out, "         instead\n");
366     fprintf(out, "\n");
367     fprintf(out, "  PATTERN\n");
368     fprintf(out, "  One or more targets to build, install and test. The target\n");
369     fprintf(out, "  names are the names that appear in the LOCAL_MODULE or\n");
370     fprintf(out, "  LOCAL_PACKAGE_NAME variables in Android.mk or Android.bp files.\n");
371     fprintf(out, "\n");
372     fprintf(out, "  Building and installing\n");
373     fprintf(out, "  -----------------------\n");
374     fprintf(out, "  The modules specified will be built and then installed. If the\n");
375     fprintf(out, "  files are on the system partition, they will be synced and the\n");
376     fprintf(out, "  attached device rebooted. If they are APKs that aren't on the\n");
377     fprintf(out, "  system partition they are installed with adb install.\n");
378     fprintf(out, "\n");
379     fprintf(out, "  For example:\n");
380     fprintf(out, "    bit framework\n");
381     fprintf(out, "      Builds framework.jar, syncs the system partition and reboots.\n");
382     fprintf(out, "\n");
383     fprintf(out, "    bit SystemUI\n");
384     fprintf(out, "      Builds SystemUI.apk, syncs the system partition and reboots.\n");
385     fprintf(out, "\n");
386     fprintf(out, "    bit CtsProtoTestCases\n");
387     fprintf(out, "      Builds this CTS apk, adb installs it, but does not run any\n");
388     fprintf(out, "      tests.\n");
389     fprintf(out, "\n");
390     fprintf(out, "  Running Unit Tests\n");
391     fprintf(out, "  ------------------\n");
392     fprintf(out, "  To run a unit test, list the test class names and optionally the\n");
393     fprintf(out, "  test method after the module.\n");
394     fprintf(out, "\n");
395     fprintf(out, "  For example:\n");
396     fprintf(out, "    bit CtsProtoTestCases:*\n");
397     fprintf(out, "      Builds this CTS apk, adb installs it, and runs all the tests\n");
398     fprintf(out, "      contained in that apk.\n");
399     fprintf(out, "\n");
400     fprintf(out, "    bit framework CtsProtoTestCases:*\n");
401     fprintf(out, "      Builds the framework and the apk, syncs and reboots, then\n");
402     fprintf(out, "      adb installs CtsProtoTestCases.apk, and runs all tests \n");
403     fprintf(out, "      contained in that apk.\n");
404     fprintf(out, "\n");
405     fprintf(out, "    bit CtsProtoTestCases:.ProtoOutputStreamBoolTest\n");
406     fprintf(out, "    bit CtsProtoTestCases:android.util.proto.cts.ProtoOutputStreamBoolTest\n");
407     fprintf(out, "      Builds and installs CtsProtoTestCases.apk, and runs all the\n");
408     fprintf(out, "      tests in the ProtoOutputStreamBoolTest class.\n");
409     fprintf(out, "\n");
410     fprintf(out, "    bit CtsProtoTestCases:.ProtoOutputStreamBoolTest#testWrite\n");
411     fprintf(out, "      Builds and installs CtsProtoTestCases.apk, and runs the testWrite\n");
412     fprintf(out, "      test method on that class.\n");
413     fprintf(out, "\n");
414     fprintf(out,
415             "    bit "
416             "CtsProtoTestCases:.ProtoOutputStreamBoolTest#testWrite,.ProtoOutputStreamBoolTest#"
417             "testRepeated\n");
418     fprintf(out, "      Builds and installs CtsProtoTestCases.apk, and runs the testWrite\n");
419     fprintf(out, "      and testRepeated test methods on that class.\n");
420     fprintf(out, "\n");
421     fprintf(out, "    bit CtsProtoTestCases:android.util.proto.cts.\n");
422     fprintf(out, "      Builds and installs CtsProtoTestCases.apk, and runs the tests in the java package\n");
423     fprintf(out, "      \"android.util.proto.cts\".\n");
424     fprintf(out, "\n");
425     fprintf(out, "  Launching an Activity\n");
426     fprintf(out, "  ---------------------\n");
427     fprintf(out, "  To launch an activity, specify the activity class name after\n");
428     fprintf(out, "  the module name.\n");
429     fprintf(out, "\n");
430     fprintf(out, "  For example:\n");
431     fprintf(out, "    bit StatusBarTest:NotificationBuilderTest\n");
432     fprintf(out, "    bit StatusBarTest:.NotificationBuilderTest\n");
433     fprintf(out, "    bit StatusBarTest:com.android.statusbartest.NotificationBuilderTest\n");
434     fprintf(out, "      Builds and installs StatusBarTest.apk, launches the\n");
435     fprintf(out, "      com.android.statusbartest/.NotificationBuilderTest activity.\n");
436     fprintf(out, "\n");
437     fprintf(out, "\n");
438     fprintf(out, "usage: bit --refresh\n");
439     fprintf(out, "\n");
440     fprintf(out, "  Update module-info.json, the cache of make goals that can be built.\n");
441     fprintf(out, "\n");
442     fprintf(out, "usage: bit --tab ...\n");
443     fprintf(out, "\n");
444     fprintf(out, "  Lists the targets in a format for tab completion. To get tab\n");
445     fprintf(out, "  completion, add this to your bash environment:\n");
446     fprintf(out, "\n");
447     fprintf(out, "     complete -C \"bit --tab\" bit\n");
448     fprintf(out, "\n");
449     fprintf(out, "  Sourcing android's build/envsetup.sh will do this for you\n");
450     fprintf(out, "  automatically.\n");
451     fprintf(out, "\n");
452     fprintf(out, "\n");
453     fprintf(out, "usage: bit --help\n");
454     fprintf(out, "usage: bit -h\n");
455     fprintf(out, "\n");
456     fprintf(out, "  Print this help message\n");
457     fprintf(out, "\n");
458 }
459 
460 /**
461  * Prints a possibly color-coded summary of test results. Example output:
462  *
463  *     "34 passed, 0 failed, 1 ignored\n"
464  */
print_results(int passed,int failed,int ignored)465 static void print_results(int passed, int failed, int ignored) {
466     char const* nothing = "";
467     char const* cp = nothing;
468     char const* cf = nothing;
469     char const* ci = nothing;
470 
471     if (failed > 0) {
472         cf = g_escapeRedBold;
473     } else if (passed > 0 || ignored > 0) {
474         cp = passed > 0 ? g_escapeGreenBold : nothing;
475         ci = ignored > 0 ? g_escapeYellowBold : nothing;
476     } else {
477         cp = g_escapeYellowBold;
478         cf = g_escapeYellowBold;
479     }
480 
481     if (ignored > 0) {
482         printf("%s%d passed%s, %s%d failed%s, %s%d ignored%s\n", cp, passed, g_escapeEndColor, cf,
483                failed, g_escapeEndColor, ci, ignored, g_escapeEndColor);
484     } else {
485         printf("%s%d passed%s, %s%d failed%s\n", cp, passed, g_escapeEndColor, cf, failed,
486                g_escapeEndColor);
487     }
488 }
489 
490 /**
491  * Sets the appropriate flag* variables. If there is a problem with the
492  * commandline arguments, prints the help message and exits with an error.
493  */
494 static void
parse_args(Options * options,int argc,const char ** argv)495 parse_args(Options* options, int argc, const char** argv)
496 {
497     // Help
498     if (argc == 2 && (strcmp(argv[1],  "-h") == 0 || strcmp(argv[1], "--help") == 0)) {
499         options->runHelp = true;
500         return;
501     }
502 
503     // Refresh
504     if (argc == 2 && strcmp(argv[1], "--refresh") == 0) {
505         options->runRefresh = true;
506         return;
507     }
508 
509     // Tab
510     if (argc >= 4 && strcmp(argv[1], "--tab") == 0) {
511         options->runTab = true;
512         options->tabPattern = argv[3];
513         return;
514     }
515 
516     // Normal usage
517     bool anyPhases = false;
518     bool gotPattern = false;
519     bool flagBuild = false;
520     bool flagInstall = false;
521     bool flagTest = false;
522     for (int i=1; i < argc; i++) {
523         string arg(argv[i]);
524         if (arg[0] == '-') {
525             for (size_t j=1; j<arg.size(); j++) {
526                 switch (arg[j]) {
527                     case '-':
528                         break;
529                     case 'b':
530                         if (gotPattern) {
531                             gotPattern = false;
532                             flagInstall = false;
533                             flagTest = false;
534                         }
535                         flagBuild = true;
536                         anyPhases = true;
537                         break;
538                     case 'i':
539                         if (gotPattern) {
540                             gotPattern = false;
541                             flagBuild = false;
542                             flagTest = false;
543                         }
544                         flagInstall = true;
545                         anyPhases = true;
546                         break;
547                     case 't':
548                         if (gotPattern) {
549                             gotPattern = false;
550                             flagBuild = false;
551                             flagInstall = false;
552                         }
553                         flagTest = true;
554                         anyPhases = true;
555                         break;
556                     case 'n':
557                         options->noRestart = true;
558                         break;
559                     case 'r':
560                         options->reboot = true;
561                         break;
562                     default:
563                         fprintf(stderr, "Unrecognized option '%c'\n", arg[j]);
564                         print_usage(stderr);
565                         exit(1);
566                         break;
567                 }
568             }
569         } else {
570             Target* target = new Target(flagBuild || !anyPhases, flagInstall || !anyPhases,
571                     flagTest || !anyPhases, arg);
572             size_t colonPos = arg.find(':');
573             if (colonPos == 0) {
574                 fprintf(stderr, "Test / activity supplied without a module to build: %s\n",
575                         arg.c_str());
576                 print_usage(stderr);
577                 delete target;
578                 exit(1);
579             } else if (colonPos == string::npos) {
580                 target->name = arg;
581             } else {
582                 target->name.assign(arg, 0, colonPos);
583                 size_t beginPos = colonPos+1;
584                 size_t commaPos;
585                 while (true) {
586                     commaPos = arg.find(',', beginPos);
587                     if (commaPos == string::npos) {
588                         if (beginPos != arg.size()) {
589                             target->actions.push_back(string(arg, beginPos, commaPos));
590                         }
591                         break;
592                     } else {
593                         if (commaPos != beginPos) {
594                             target->actions.push_back(string(arg, beginPos, commaPos-beginPos));
595                         }
596                         beginPos = commaPos+1;
597                     }
598                 }
599             }
600             options->targets.push_back(target);
601             gotPattern = true;
602         }
603     }
604     // If no pattern was supplied, give an error
605     if (options->targets.size() == 0) {
606         fprintf(stderr, "No PATTERN supplied.\n\n");
607         print_usage(stderr);
608         exit(1);
609     }
610 }
611 
612 /**
613  * Get an environment variable.
614  * Exits with an error if it is unset or the empty string.
615  */
616 static string
get_required_env(const char * name,bool quiet)617 get_required_env(const char* name, bool quiet)
618 {
619     const char* value = getenv(name);
620     if (value == NULL || value[0] == '\0') {
621         if (!quiet) {
622             fprintf(stderr, "%s not set. Did you source build/envsetup.sh,"
623                     " run lunch and do a build?\n", name);
624         }
625         exit(1);
626     }
627     return string(value);
628 }
629 
630 /**
631  * Get the out directory.
632  *
633  * This duplicates the logic in build/make/core/envsetup.mk (which hasn't changed since 2011)
634  * so that we don't have to wait for get_build_var make invocation.
635  */
636 string
get_out_dir()637 get_out_dir()
638 {
639     const char* out_dir = getenv("OUT_DIR");
640     if (out_dir == NULL || out_dir[0] == '\0') {
641         const char* common_base = getenv("OUT_DIR_COMMON_BASE");
642         if (common_base == NULL || common_base[0] == '\0') {
643             // We don't prefix with buildTop because we cd there and it
644             // makes all the filenames long when being pretty printed.
645             return "out";
646         } else {
647             char pwd[PATH_MAX];
648             if (getcwd(pwd, PATH_MAX) == NULL) {
649                 fprintf(stderr, "Your pwd is too long.\n");
650                 exit(1);
651             }
652             const char* slash = strrchr(pwd, '/');
653             if (slash == NULL) {
654                 slash = "";
655             }
656             string result(common_base);
657             result += slash;
658             return result;
659         }
660     }
661     return string(out_dir);
662 }
663 
664 /**
665  * Check that a system property on the device matches the expected value.
666  * Exits with an error if they don't.
667  */
668 static void
check_device_property(const string & property,const string & expected)669 check_device_property(const string& property, const string& expected)
670 {
671     int err;
672     string deviceValue = get_system_property(property, &err);
673     check_error(err);
674     if (deviceValue != expected) {
675         print_error("There is a mismatch between the build you just did and the device you");
676         print_error("are trying to sync it to in the %s system property", property.c_str());
677         print_error("   build:  %s", expected.c_str());
678         print_error("   device: %s", deviceValue.c_str());
679         exit(1);
680     }
681 }
682 
683 static void
chdir_or_exit(const char * path)684 chdir_or_exit(const char *path) {
685     // TODO: print_command("cd", path);
686     if (0 != chdir(path)) {
687         print_error("Error: Could not chdir: %s", path);
688         exit(1);
689     }
690 }
691 
692 /**
693  * Run the build, install, and test actions.
694  */
695 bool
run_phases(vector<Target * > targets,const Options & options)696 run_phases(vector<Target*> targets, const Options& options)
697 {
698     int err = 0;
699 
700     //
701     // Initialization
702     //
703 
704     print_status("Initializing");
705 
706     const string buildTop = get_required_env("ANDROID_BUILD_TOP", false);
707     const string buildProduct = get_required_env("TARGET_PRODUCT", false);
708     const string buildVariant = get_required_env("TARGET_BUILD_VARIANT", false);
709     const string buildType = get_required_env("TARGET_BUILD_TYPE", false);
710     const string buildOut = get_out_dir();
711     chdir_or_exit(buildTop.c_str());
712 
713     BuildVars buildVars(buildOut, buildProduct, buildVariant, buildType);
714 
715     const string buildDevice = buildVars.GetBuildVar("TARGET_DEVICE", false);
716     const string buildId = buildVars.GetBuildVar("BUILD_ID", false);
717 
718     // Get the modules for the targets
719     map<string,Module> modules;
720     read_modules(buildOut, buildDevice, &modules, false);
721     for (size_t i=0; i<targets.size(); i++) {
722         Target* target = targets[i];
723         map<string,Module>::iterator mod = modules.find(target->name);
724         if (mod != modules.end()) {
725             target->module = mod->second;
726         } else {
727             print_error("Error: Could not find module: %s", target->name.c_str());
728             fprintf(stderr, "Try running %sbit --refresh%s if you recently added %s%s%s.\n",
729                     g_escapeBold, g_escapeEndColor,
730                     g_escapeBold, target->name.c_str(), g_escapeEndColor);
731             err = 1;
732         }
733     }
734     if (err != 0) {
735         exit(1);
736     }
737 
738     // Choose the goals
739     vector<string> goals;
740     for (size_t i=0; i<targets.size(); i++) {
741         Target* target = targets[i];
742         if (target->build) {
743             goals.push_back(target->name);
744         }
745     }
746 
747 
748     // Figure out whether we need to sync the system and which apks to install
749     string deviceTargetPath = buildOut + "/target/product/" + buildDevice;
750     string systemPath = deviceTargetPath + "/system/";
751     string dataPath = deviceTargetPath + "/data/";
752     string testPath = deviceTargetPath + "/testcases/";
753     bool syncSystem = false;
754     bool alwaysSyncSystem = false;
755     vector<string> systemFiles;
756     vector<InstallApk> installApks;
757     vector<PushedFile> pushedFiles;
758     for (size_t i=0; i<targets.size(); i++) {
759         Target* target = targets[i];
760         if (target->install) {
761             for (size_t j=0; j<target->module.installed.size(); j++) {
762                 const string& file = target->module.installed[j];
763                 // System partition
764                 if (starts_with(file, systemPath)) {
765                     syncSystem = true;
766                     systemFiles.push_back(file);
767                     if (!target->build) {
768                         // If a system partition target didn't get built then
769                         // it won't change we will always need to do adb sync
770                         alwaysSyncSystem = true;
771                     }
772                     continue;
773                 }
774                 // Apk in the data partition
775                 if (ends_with(file, ".apk")
776                         && (starts_with(file, dataPath) || starts_with(file, testPath))) {
777                     // Always install it if we didn't build it because otherwise
778                     // it will never have changed.
779                     installApks.push_back(InstallApk(file, !target->build));
780                     continue;
781                 }
782                 // If it's a native test module, push it.
783                 if (target->module.HasClass(NATIVE_TESTS) && starts_with(file, dataPath)) {
784                     string installedPath(file.c_str() + deviceTargetPath.length());
785                     pushedFiles.push_back(PushedFile(file, installedPath));
786                 }
787             }
788         }
789     }
790     map<string,FileInfo> systemFilesBefore;
791     if (syncSystem && !alwaysSyncSystem) {
792         get_directory_contents(systemPath, &systemFilesBefore);
793     }
794 
795     if (systemFiles.size() > 0){
796         print_info("System files:");
797         for (size_t i=0; i<systemFiles.size(); i++) {
798             printf("  %s\n", systemFiles[i].c_str());
799         }
800     }
801     if (pushedFiles.size() > 0){
802         print_info("Files to push:");
803         for (size_t i=0; i<pushedFiles.size(); i++) {
804             printf("  %s\n", pushedFiles[i].file.filename.c_str());
805             printf("    --> %s\n", pushedFiles[i].dest.c_str());
806         }
807     }
808     if (installApks.size() > 0){
809         print_info("APKs to install:");
810         for (size_t i=0; i<installApks.size(); i++) {
811             printf("  %s\n", installApks[i].file.filename.c_str());
812         }
813     }
814 
815     //
816     // Build
817     //
818 
819     // Run the build
820     if (goals.size() > 0) {
821         print_status("Building");
822         err = build_goals(goals);
823         check_error(err);
824     }
825 
826     //
827     // Install
828     //
829 
830     // Sync the system partition and reboot
831     bool skipSync = false;
832     if (syncSystem) {
833         print_status("Syncing /system");
834 
835         if (!alwaysSyncSystem) {
836             // If nothing changed and we weren't forced to sync, skip the reboot for speed.
837             map<string,FileInfo> systemFilesAfter;
838             get_directory_contents(systemPath, &systemFilesAfter);
839             skipSync = !directory_contents_differ(systemFilesBefore, systemFilesAfter);
840         }
841         if (skipSync) {
842             printf("Skipping sync because no files changed.\n");
843         } else {
844             // Do some sanity checks
845             check_device_property("ro.build.product", buildProduct);
846             check_device_property("ro.build.type", buildVariant);
847             check_device_property("ro.build.id", buildId);
848 
849             // Stop & Sync
850             if (!options.noRestart) {
851                 err = run_adb("exec-out", "stop", NULL);
852                 check_error(err);
853             }
854             err = run_adb("remount", NULL);
855             check_error(err);
856             err = run_adb("sync", "system", NULL);
857             check_error(err);
858 
859             if (!options.noRestart) {
860                 if (options.reboot) {
861                     print_status("Rebooting");
862 
863                     err = run_adb("reboot", NULL);
864                     check_error(err);
865                     err = run_adb("wait-for-device", NULL);
866                     check_error(err);
867                 } else {
868                     print_status("Restarting the runtime");
869 
870                     err = run_adb("exec-out", "setprop", "sys.boot_completed", "0", NULL);
871                     check_error(err);
872                     err = run_adb("exec-out", "start", NULL);
873                     check_error(err);
874                 }
875 
876                 while (true) {
877                     string completed = get_system_property("sys.boot_completed", &err);
878                     check_error(err);
879                     if (completed == "1") {
880                         break;
881                     }
882                     sleep(2);
883                 }
884                 sleep(1);
885                 err = run_adb("exec-out", "wm", "dismiss-keyguard", NULL);
886                 check_error(err);
887             }
888         }
889     }
890 
891     // Push files
892     if (pushedFiles.size() > 0) {
893         print_status("Pushing files");
894         for (size_t i=0; i<pushedFiles.size(); i++) {
895             const PushedFile& pushed = pushedFiles[i];
896             string dir = dirname(pushed.dest);
897             if (dir.length() == 0 || dir == "/") {
898                 // This isn't really a file inside the data directory. Just skip it.
899                 continue;
900             }
901             // TODO: if (!apk.file.fileInfo.exists || apk.file.HasChanged())
902             err = run_adb("exec-out", "mkdir", "-p", dir.c_str(), NULL);
903             check_error(err);
904             err = run_adb("push", pushed.file.filename.c_str(), pushed.dest.c_str(), NULL);
905             check_error(err);
906             // pushed.installed = true;
907         }
908     }
909 
910     // Install APKs
911     if (installApks.size() > 0) {
912         print_status("Installing APKs");
913         for (size_t i=0; i<installApks.size(); i++) {
914             InstallApk& apk = installApks[i];
915             if (!apk.file.fileInfo.exists || apk.file.HasChanged()) {
916                 // It didn't exist before or it changed, so int needs install
917                 err = run_adb("install", "-r", "-g", apk.file.filename.c_str(), NULL);
918                 check_error(err);
919                 apk.installed = true;
920             } else {
921                 printf("APK didn't change. Skipping install of %s\n", apk.file.filename.c_str());
922             }
923         }
924     }
925 
926     //
927     // Actions
928     //
929 
930     // Whether there have been any tests run, so we can print a summary.
931     bool testsRun = false;
932 
933     // Run the native tests.
934     // TODO: We don't have a good way of running these and capturing the output of
935     // them live.  It'll take some work.  On the other hand, if they're gtest tests,
936     // the output of gtest is not completely insane like the text output of the
937     // instrumentation tests.  So for now, we'll just live with that.
938     for (size_t i=0; i<targets.size(); i++) {
939         Target* target = targets[i];
940         if (target->test && target->module.HasClass(NATIVE_TESTS)) {
941             // We don't have a clear signal from the build system which of the installed
942             // files is actually the test, so we guess by looking for one with the same
943             // leaf name as the module that is executable.
944             for (size_t j=0; j<target->module.installed.size(); j++) {
945                 string filename = target->module.installed[j];
946                 if (!starts_with(filename, dataPath)) {
947                     // Native tests go into the data directory.
948                     continue;
949                 }
950                 if (leafname(filename) != target->module.name) {
951                     // This isn't the test executable.
952                     continue;
953                 }
954                 if (!is_executable(filename)) {
955                     continue;
956                 }
957                 string installedPath(filename.c_str() + deviceTargetPath.length());
958                 printf("the magic one is: %s\n", filename.c_str());
959                 printf("  and it's installed at: %s\n", installedPath.c_str());
960 
961                 // Convert bit-style actions to gtest test filter arguments
962                 if (target->actions.size() > 0) {
963                     testsRun = true;
964                     target->testActionCount++;
965                     bool runAll = false;
966                     string filterArg("--gtest_filter=");
967                     for (size_t k=0; k<target->actions.size(); k++) {
968                         string actionString = target->actions[k];
969                         if (actionString == "*") {
970                             runAll = true;
971                         } else {
972                             filterArg += actionString;
973                             if (k != target->actions.size()-1) {
974                                 // We would otherwise have to worry about this condition
975                                 // being true, and appending an extra ':', but we know that
976                                 // if the extra action is "*", then we'll just run all and
977                                 // won't use filterArg anyway, so just keep this condition
978                                 // simple.
979                                 filterArg += ':';
980                             }
981                         }
982                     }
983                     if (runAll) {
984                         err = run_adb("exec-out", installedPath.c_str(), NULL);
985                     } else {
986                         err = run_adb("exec-out", installedPath.c_str(), filterArg.c_str(), NULL);
987                     }
988                     if (err == 0) {
989                         target->testPassCount++;
990                     } else {
991                         target->testFailCount++;
992                     }
993                 }
994             }
995         }
996     }
997 
998     // Inspect the apks, and figure out what is an activity and what needs a test runner
999     bool printedInspecting = false;
1000     vector<TestAction> testActions;
1001     vector<ActivityAction> activityActions;
1002     for (size_t i=0; i<targets.size(); i++) {
1003         Target* target = targets[i];
1004         if (target->test) {
1005             for (size_t j=0; j<target->module.installed.size(); j++) {
1006                 string filename = target->module.installed[j];
1007 
1008                 // Skip of not apk in the data partition or test
1009                 if (!(ends_with(filename, ".apk")
1010                         && (starts_with(filename, dataPath) || starts_with(filename, testPath)))) {
1011                     continue;
1012                 }
1013 
1014                 if (!printedInspecting) {
1015                     printedInspecting = true;
1016                     print_status("Inspecting APKs");
1017                 }
1018 
1019                 Apk apk;
1020                 err = inspect_apk(&apk, filename);
1021                 check_error(err);
1022 
1023                 for (size_t k=0; k<target->actions.size(); k++) {
1024                     string actionString = target->actions[k];
1025                     if (actionString == "*") {
1026                         if (apk.runner.length() == 0) {
1027                             print_error("Error: Test requested for apk that doesn't"
1028                                     " have an <instrumentation> tag: %s\n",
1029                                     target->module.name.c_str());
1030                             exit(1);
1031                         }
1032                         TestAction action;
1033                         action.packageName = apk.package;
1034                         action.runner = apk.runner;
1035                         action.target = target;
1036                         testActions.push_back(action);
1037                         target->testActionCount++;
1038                     } else if (apk.HasActivity(actionString)) {
1039                         ActivityAction action;
1040                         action.packageName = apk.package;
1041                         action.className = full_class_name(apk.package, actionString);
1042                         activityActions.push_back(action);
1043                     } else {
1044                         if (apk.runner.length() == 0) {
1045                             print_error("Error: Test requested for apk that doesn't"
1046                                     " have an <instrumentation> tag: %s\n",
1047                                     target->module.name.c_str());
1048                             exit(1);
1049                         }
1050                         TestAction action;
1051                         action.packageName = apk.package;
1052                         action.runner = apk.runner;
1053                         action.className = full_class_name(apk.package, actionString);
1054                         action.target = target;
1055                         testActions.push_back(action);
1056                         target->testActionCount++;
1057                     }
1058                 }
1059             }
1060         }
1061     }
1062 
1063     // Run the instrumentation tests
1064     TestResults testResults;
1065     if (testActions.size() > 0) {
1066         print_status("Running tests");
1067         testsRun = true;
1068         for (size_t i=0; i<testActions.size(); i++) {
1069             TestAction& action = testActions[i];
1070             testResults.SetCurrentAction(&action);
1071             err = run_instrumentation_test(action.packageName, action.runner, action.className,
1072                     &testResults);
1073             check_error(err);
1074             int total = action.passCount + action.failCount;
1075             printf("%sRan %d test%s for %s. ", g_escapeClearLine,
1076                     total, total > 1 ? "s" : "", action.target->name.c_str());
1077             print_results(action.passCount, action.failCount, action.ignoreCount);
1078             if (!testResults.IsSuccess()) {
1079                 printf("\n%sTest didn't finish successfully: %s%s\n", g_escapeRedBold,
1080                         testResults.GetErrorMessage().c_str(), g_escapeEndColor);
1081             }
1082         }
1083     }
1084 
1085     // Launch the activity
1086     if (activityActions.size() > 0) {
1087         print_status("Starting activity");
1088 
1089         if (activityActions.size() > 1) {
1090             print_warning("Multiple activities specified.  Will only start the first one:");
1091             for (size_t i=0; i<activityActions.size(); i++) {
1092                 ActivityAction& action = activityActions[i];
1093                 print_warning("   %s",
1094                         pretty_component_name(action.packageName, action.className).c_str());
1095             }
1096         }
1097 
1098         const ActivityAction& action = activityActions[0];
1099         string componentName = action.packageName + "/" + action.className;
1100         err = run_adb("exec-out", "am", "start", componentName.c_str(), NULL);
1101         check_error(err);
1102     }
1103 
1104     //
1105     // Print summary
1106     //
1107 
1108     printf("\n%s--------------------------------------------%s\n", g_escapeBold, g_escapeEndColor);
1109 
1110     // Build
1111     if (goals.size() > 0) {
1112         printf("%sBuilt:%s\n", g_escapeBold, g_escapeEndColor);
1113         for (size_t i=0; i<goals.size(); i++) {
1114             printf("   %s\n", goals[i].c_str());
1115         }
1116     }
1117 
1118     // Install
1119     if (syncSystem) {
1120         if (skipSync) {
1121             printf("%sSkipped syncing /system partition%s\n", g_escapeBold, g_escapeEndColor);
1122         } else {
1123             printf("%sSynced /system partition%s\n", g_escapeBold, g_escapeEndColor);
1124         }
1125     }
1126     if (installApks.size() > 0) {
1127         bool printedTitle = false;
1128         for (size_t i=0; i<installApks.size(); i++) {
1129             const InstallApk& apk = installApks[i];
1130             if (apk.installed) {
1131                 if (!printedTitle) {
1132                     printf("%sInstalled:%s\n", g_escapeBold, g_escapeEndColor);
1133                     printedTitle = true;
1134                 }
1135                 printf("   %s\n", apk.file.filename.c_str());
1136             }
1137         }
1138         printedTitle = false;
1139         for (size_t i=0; i<installApks.size(); i++) {
1140             const InstallApk& apk = installApks[i];
1141             if (!apk.installed) {
1142                 if (!printedTitle) {
1143                     printf("%sSkipped install:%s\n", g_escapeBold, g_escapeEndColor);
1144                     printedTitle = true;
1145                 }
1146                 printf("   %s\n", apk.file.filename.c_str());
1147             }
1148         }
1149     }
1150 
1151     // Tests
1152     bool hasErrors = false;
1153     if (testsRun) {
1154         printf("%sRan tests:%s\n", g_escapeBold, g_escapeEndColor);
1155         size_t maxNameLength = 0;
1156         for (size_t i=0; i<targets.size(); i++) {
1157             Target* target = targets[i];
1158             if (target->test) {
1159                 size_t len = target->name.length();
1160                 if (len > maxNameLength) {
1161                     maxNameLength = len;
1162                 }
1163             }
1164         }
1165         string padding(maxNameLength, ' ');
1166         for (size_t i=0; i<targets.size(); i++) {
1167             Target* target = targets[i];
1168             if (target->testActionCount > 0) {
1169                 printf("   %s%s", target->name.c_str(), padding.c_str() + target->name.length());
1170                 if (target->unknownFailureCount > 0) {
1171                     printf("     %sUnknown failure, see above message.%s\n",
1172                             g_escapeRedBold, g_escapeEndColor);
1173                     hasErrors = true;
1174                 } else {
1175                     printf("   %s%s     ", target->name.c_str(),
1176                            padding.c_str() + target->name.length());
1177                     print_results(target->testPassCount, target->testFailCount,
1178                                   target->testIgnoreCount);
1179                 }
1180             }
1181         }
1182     }
1183     if (activityActions.size() > 1) {
1184         printf("%sStarted Activity:%s\n", g_escapeBold, g_escapeEndColor);
1185         const ActivityAction& action = activityActions[0];
1186         printf("   %s\n", pretty_component_name(action.packageName, action.className).c_str());
1187     }
1188 
1189     printf("%s--------------------------------------------%s\n", g_escapeBold, g_escapeEndColor);
1190     return !hasErrors;
1191 }
1192 
1193 /**
1194  * Refresh module-info.
1195  */
1196 void
run_refresh()1197 run_refresh()
1198 {
1199     int err;
1200 
1201     print_status("Initializing");
1202     const string buildTop = get_required_env("ANDROID_BUILD_TOP", false);
1203     const string buildProduct = get_required_env("TARGET_PRODUCT", false);
1204     const string buildVariant = get_required_env("TARGET_BUILD_VARIANT", false);
1205     const string buildType = get_required_env("TARGET_BUILD_TYPE", false);
1206     const string buildOut = get_out_dir();
1207     chdir_or_exit(buildTop.c_str());
1208 
1209     BuildVars buildVars(buildOut, buildProduct, buildVariant, buildType);
1210 
1211     string buildDevice = buildVars.GetBuildVar("TARGET_DEVICE", false);
1212 
1213     vector<string> goals;
1214     goals.push_back(buildOut + "/target/product/" + buildDevice + "/module-info.json");
1215 
1216     print_status("Refreshing module-info.json");
1217     err = build_goals(goals);
1218     check_error(err);
1219 }
1220 
1221 /**
1222  * Implement tab completion of the target names from the all modules file.
1223  */
1224 void
run_tab_completion(const string & word)1225 run_tab_completion(const string& word)
1226 {
1227     const string buildTop = get_required_env("ANDROID_BUILD_TOP", false);
1228     const string buildProduct = get_required_env("TARGET_PRODUCT", false);
1229     const string buildVariant = get_required_env("TARGET_BUILD_VARIANT", false);
1230     const string buildType = get_required_env("TARGET_BUILD_TYPE", false);
1231     const string buildOut = get_out_dir();
1232     chdir_or_exit(buildTop.c_str());
1233 
1234     BuildVars buildVars(buildOut, buildProduct, buildVariant, buildType);
1235 
1236     string buildDevice = buildVars.GetBuildVar("TARGET_DEVICE", false);
1237 
1238     map<string,Module> modules;
1239     read_modules(buildOut, buildDevice, &modules, true);
1240 
1241     for (map<string,Module>::const_iterator it = modules.begin(); it != modules.end(); it++) {
1242         if (starts_with(it->first, word)) {
1243             printf("%s\n", it->first.c_str());
1244         }
1245     }
1246 }
1247 
1248 /**
1249  * Main entry point.
1250  */
1251 int
main(int argc,const char ** argv)1252 main(int argc, const char** argv)
1253 {
1254     GOOGLE_PROTOBUF_VERIFY_VERSION;
1255     init_print();
1256 
1257     Options options;
1258     parse_args(&options, argc, argv);
1259 
1260     if (options.runHelp) {
1261         // Help
1262         print_usage(stdout);
1263         exit(0);
1264     } else if (options.runRefresh) {
1265         run_refresh();
1266         exit(0);
1267     } else if (options.runTab) {
1268         run_tab_completion(options.tabPattern);
1269         exit(0);
1270     } else {
1271         // Normal run
1272         exit(run_phases(options.targets, options) ? 0 : 1);
1273     }
1274 
1275     return 0;
1276 }
1277 
1278