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