Add a way to use libraries from the Android tree

This patch adds a gn variable build_with_android which makes it possible
to use Android internal (i.e., non-NDK) libraries when Perfetto is being
built as a part of the Android tree.

Change-Id: I935582fa969ab230b9ab0ac7d392dfeace802b0e
diff --git a/Android.bp b/Android.bp
index 4b8b1b8..4e32744 100644
--- a/Android.bp
+++ b/Android.bp
@@ -64,6 +64,7 @@
     "libandroid",
     "liblog",
     "libprotobuf-cpp-lite",
+    "libutils",
   ],
   static_libs: [
     "libgtest_prod",
@@ -81,6 +82,9 @@
   defaults: [
     "perfetto_defaults",
   ],
+  cflags: [
+    "-DPERFETTO_BUILD_WITH_ANDROID",
+  ],
 }
 
 // GN target: //:perfetto
@@ -93,6 +97,7 @@
     "libandroid",
     "liblog",
     "libtraced_shared",
+    "libutils",
   ],
   defaults: [
     "perfetto_defaults",
@@ -893,6 +898,7 @@
     "libandroid",
     "liblog",
     "libtraced_shared",
+    "libutils",
   ],
   defaults: [
     "perfetto_defaults",
@@ -909,6 +915,7 @@
     "libandroid",
     "liblog",
     "libtraced_shared",
+    "libutils",
   ],
   defaults: [
     "perfetto_defaults",
diff --git a/BUILD.gn b/BUILD.gn
index 512934e..1996c66 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -66,6 +66,10 @@
       "src/traced/probes",
       "src/traced/service",
     ]
+    if (build_with_android) {
+      cflags = [ "-DPERFETTO_BUILD_WITH_ANDROID" ]
+      libs = [ "utils" ]
+    }
   }
 
   # The unprivileged trace daemon that listens for Producer and Consumer
diff --git a/build_overrides/build.gni b/build_overrides/build.gni
index b7a2bab..a89a764 100644
--- a/build_overrides/build.gni
+++ b/build_overrides/build.gni
@@ -12,8 +12,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# When building perfetto in the android tree this variable becomes magically
+# When building perfetto in the Chromium tree this variable becomes magically
 # true by virtue of including //build_overrides by absolute path.
 # When false, instead, the build files can assume this is a Perfetto standalone
 # build.
 build_with_chromium = false
+
+declare_args() {
+  # The Android blueprint file generator overrides this to true.
+  build_with_android = false
+}
diff --git a/src/traced/perfetto_cmd/perfetto_cmd.cc b/src/traced/perfetto_cmd/perfetto_cmd.cc
index 32d5b87..66ce34b 100644
--- a/src/traced/perfetto_cmd/perfetto_cmd.cc
+++ b/src/traced/perfetto_cmd/perfetto_cmd.cc
@@ -35,16 +35,27 @@
 
 #include "protos/tracing_service/trace_config.pb.h"
 
+#if defined(PERFETTO_BUILD_WITH_ANDROID)
+#include "perfetto/base/android_task_runner.h"
+
+#include <utils/Looper.h>
+#include <utils/StrongPointer.h>
+#endif  // defined(PERFETTO_BUILD_WITH_ANDROID)
+
 // TODO(primiano): add the ability to pass the file descriptor directly to the
 // traced service instead of receiving a copy of the chunks and writing them
 // from this process.
-
 namespace perfetto {
 
+#if defined(PERFETTO_BUILD_WITH_ANDROID)
+using PlatformTaskRunner = base::AndroidTaskRunner;
+#else
+using PlatformTaskRunner = base::UnixTaskRunner;
+#endif
+
 class PerfettoCmd : public Consumer {
  public:
   int Main(int argc, char** argv);
-
   int PrintUsage(const char* argv0);
   void OnStopTraceTimer();
 
@@ -54,7 +65,7 @@
   void OnTraceData(std::vector<TracePacket>, bool has_more) override;
 
  private:
-  perfetto::base::UnixTaskRunner task_runner_;
+  PlatformTaskRunner task_runner_;
   std::unique_ptr<perfetto::Service::ConsumerEndpoint> consumer_endpoint_;
   std::unique_ptr<TraceConfig> trace_config_;
   std::ofstream trace_out_stream_;
@@ -144,7 +155,14 @@
   consumer_endpoint_ = ConsumerIPCClient::Connect(PERFETTO_CONSUMER_SOCK_NAME,
                                                   this, &task_runner_);
 
+#if defined(PERFETTO_BUILD_WITH_ANDROID)
+  android::sp<android::Looper> looper(android::Looper::prepare(0 /* opts */));
+  while (true) {
+    looper->pollAll(-1 /* timeoutMillis */);
+  }
+#else  // defined(PERFETTO_BUILD_WITH_ANDROID)
   task_runner_.Run();
+#endif // defined(PERFETTO_BUILD_WITH_ANDROID)
   return did_receive_full_trace_ ? 0 : 1;
 }  // namespace perfetto
 
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index 48f69ca..79416d4 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -26,6 +26,7 @@
 # libraries are also mapped to their Android equivalents -- see |builtin_deps|.
 
 import argparse
+import errno
 import json
 import os
 import re
@@ -35,11 +36,12 @@
 
 # Default targets to translate to the blueprint file.
 default_targets = [
+    '//:libtraced_shared',
+    '//:perfetto',
     '//:perfetto_tests',
     '//:perfetto',
     '//:traced',
     '//:traced_probes',
-    '//:libtraced_shared',
     '//src/tracing:consumer_cmd',
 ]
 
@@ -48,7 +50,7 @@
 target_initrc = {}  # TODO(primiano): populate in upcoming CLs.
 
 # Arguments for the GN output directory.
-gn_args = 'target_os="android" target_cpu="arm" is_debug=false'
+gn_args = 'target_os="android" target_cpu="arm" is_debug=false build_with_android=true'
 
 # All module names are prefixed with this string to avoid collisions.
 module_prefix = 'perfetto_'
@@ -57,6 +59,7 @@
 library_whitelist = [
     'android',
     'log',
+    'utils',
 ]
 
 # Name of the module which settings such as compiler flags for all other
@@ -66,6 +69,9 @@
 # Location of the project in the Android source tree.
 tree_path = 'external/perfetto'
 
+# Compiler flags which are passed through to the blueprint.
+cflag_whitelist = r'^-DPERFETTO.*$'
+
 
 def enable_gmock(module):
     module.static_libs.append('libgmock')
@@ -437,6 +443,9 @@
         # Don't try to inject library/source dependencies into genrules because
         # they are not compiled in the traditional sense.
         if module.type != 'genrule':
+            for flag in target.get('cflags', []):
+                if re.match(cflag_whitelist, flag):
+                  module.cflags.append(flag)
             module.defaults = [defaults_module]
             apply_module_dependency(blueprint, desc, module, target_name)
             for dep in resolve_dependencies(desc, target_name):