Client API: use only system backend in the android tree

This change makes the client library backends selectable with GN.
This is achieved by splitting out the client_api_base target and
pairing it with either the real backends or with fallback versions
that return nullptr nad print an error.
This is to avoid linking the in-process backend (which in turn pulls
all the consumer and service code) on Android.
Saves 214KB of binary size in Android.

Bug: 148198993
Change-Id: I6b6f5ad0095e9e4ba2e1dd6c3fe5330a2568b0ad
diff --git a/Android.bp b/Android.bp
index d29f875..c1ca304 100644
--- a/Android.bp
+++ b/Android.bp
@@ -478,15 +478,18 @@
     ":perfetto_src_ipc_common",
     ":perfetto_src_ipc_host",
     ":perfetto_src_protozero_protozero",
-    ":perfetto_src_tracing_client_api",
+    ":perfetto_src_tracing_client_api_base",
+    ":perfetto_src_tracing_client_api_system_backend_only",
     ":perfetto_src_tracing_common",
     ":perfetto_src_tracing_core_core",
     ":perfetto_src_tracing_core_service",
+    ":perfetto_src_tracing_in_process_backend_fake",
     ":perfetto_src_tracing_ipc_common",
     ":perfetto_src_tracing_ipc_consumer_consumer",
     ":perfetto_src_tracing_ipc_producer_producer",
     ":perfetto_src_tracing_ipc_service_service",
     ":perfetto_src_tracing_platform_posix",
+    ":perfetto_src_tracing_system_process_backend",
   ],
   export_include_dirs: [
     "include",
@@ -1360,15 +1363,17 @@
     ":perfetto_src_traced_probes_probes_src",
     ":perfetto_src_traced_probes_ps_ps",
     ":perfetto_src_traced_probes_sys_stats_sys_stats",
-    ":perfetto_src_tracing_client_api",
+    ":perfetto_src_tracing_client_api_base",
     ":perfetto_src_tracing_common",
     ":perfetto_src_tracing_core_core",
     ":perfetto_src_tracing_core_service",
+    ":perfetto_src_tracing_in_process_backend",
     ":perfetto_src_tracing_ipc_common",
     ":perfetto_src_tracing_ipc_consumer_consumer",
     ":perfetto_src_tracing_ipc_producer_producer",
     ":perfetto_src_tracing_ipc_service_service",
     ":perfetto_src_tracing_platform_posix",
+    ":perfetto_src_tracing_system_process_backend",
     ":perfetto_src_tracing_test_api_test_support",
     ":perfetto_src_tracing_test_client_api_integrationtests",
     ":perfetto_test_end_to_end_integrationtests",
@@ -6500,15 +6505,13 @@
   ],
 }
 
-// GN: //src/tracing:client_api
+// GN: //src/tracing:client_api_base
 filegroup {
-  name: "perfetto_src_tracing_client_api",
+  name: "perfetto_src_tracing_client_api_base",
   srcs: [
     "src/tracing/data_source.cc",
     "src/tracing/debug_annotation.cc",
     "src/tracing/event_context.cc",
-    "src/tracing/internal/in_process_tracing_backend.cc",
-    "src/tracing/internal/system_tracing_backend.cc",
     "src/tracing/internal/tracing_muxer_impl.cc",
     "src/tracing/internal/track_event_internal.cc",
     "src/tracing/platform.cc",
@@ -6519,6 +6522,11 @@
   ],
 }
 
+// GN: //src/tracing:client_api_system_backend_only
+filegroup {
+  name: "perfetto_src_tracing_client_api_system_backend_only",
+}
+
 // GN: //src/tracing:common
 filegroup {
   name: "perfetto_src_tracing_common",
@@ -6588,6 +6596,22 @@
   ],
 }
 
+// GN: //src/tracing:in_process_backend
+filegroup {
+  name: "perfetto_src_tracing_in_process_backend",
+  srcs: [
+    "src/tracing/internal/in_process_tracing_backend.cc",
+  ],
+}
+
+// GN: //src/tracing:in_process_backend_fake
+filegroup {
+  name: "perfetto_src_tracing_in_process_backend_fake",
+  srcs: [
+    "src/tracing/internal/in_process_tracing_backend_fake.cc",
+  ],
+}
+
 // GN: //src/tracing/ipc:common
 filegroup {
   name: "perfetto_src_tracing_ipc_common",
@@ -6639,6 +6663,14 @@
   ],
 }
 
+// GN: //src/tracing:system_process_backend
+filegroup {
+  name: "perfetto_src_tracing_system_process_backend",
+  srcs: [
+    "src/tracing/internal/system_tracing_backend.cc",
+  ],
+}
+
 // GN: //src/tracing/test:api_test_support
 filegroup {
   name: "perfetto_src_tracing_test_api_test_support",
diff --git a/BUILD b/BUILD
index be3b241..bbad73c 100644
--- a/BUILD
+++ b/BUILD
@@ -1230,16 +1230,14 @@
     ],
 )
 
-# GN target: //src/tracing:client_api
+# GN target: //src/tracing:client_api_base
 filegroup(
-    name = "src_tracing_client_api",
+    name = "src_tracing_client_api_base",
     srcs = [
         "src/tracing/data_source.cc",
         "src/tracing/debug_annotation.cc",
         "src/tracing/event_context.cc",
-        "src/tracing/internal/in_process_tracing_backend.cc",
         "src/tracing/internal/in_process_tracing_backend.h",
-        "src/tracing/internal/system_tracing_backend.cc",
         "src/tracing/internal/system_tracing_backend.h",
         "src/tracing/internal/tracing_muxer_impl.cc",
         "src/tracing/internal/tracing_muxer_impl.h",
@@ -1260,6 +1258,14 @@
     ],
 )
 
+# GN target: //src/tracing:in_process_backend
+filegroup(
+    name = "src_tracing_in_process_backend",
+    srcs = [
+        "src/tracing/internal/in_process_tracing_backend.cc",
+    ],
+)
+
 # GN target: //src/tracing:platform_posix
 filegroup(
     name = "src_tracing_platform_posix",
@@ -1268,6 +1274,14 @@
     ],
 )
 
+# GN target: //src/tracing:system_process_backend
+filegroup(
+    name = "src_tracing_system_process_backend",
+    srcs = [
+        "src/tracing/internal/system_tracing_backend.cc",
+    ],
+)
+
 # GN target: //tools/trace_to_text:common
 filegroup(
     name = "tools_trace_to_text_common",
@@ -2474,15 +2488,17 @@
         ":src_ipc_common",
         ":src_ipc_host",
         ":src_protozero_protozero",
-        ":src_tracing_client_api",
+        ":src_tracing_client_api_base",
         ":src_tracing_common",
         ":src_tracing_core_core",
         ":src_tracing_core_service",
+        ":src_tracing_in_process_backend",
         ":src_tracing_ipc_common",
         ":src_tracing_ipc_consumer_consumer",
         ":src_tracing_ipc_producer_producer",
         ":src_tracing_ipc_service_service",
         ":src_tracing_platform_posix",
+        ":src_tracing_system_process_backend",
     ],
     hdrs = [
         ":include_perfetto_base_base",
diff --git a/BUILD.gn b/BUILD.gn
index 8bb0383..c57fd69 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -132,6 +132,9 @@
 
     # Used in the when updating the ftrace protos
     "protos/perfetto/trace/ftrace:descriptor",
+
+    # Checks that the "fake" backend implementations build.
+    "src/tracing:client_api_no_backends_compile_test",
   ]
 }
 
@@ -200,7 +203,7 @@
 }
 
 if (!build_with_chromium) {
-  # Client library target.
+  # Client library target exposed to the Android tree.
   # Still in experimental stage and not API stable yet.
   # See "libperfetto_client_example" (in Android.bp.extras) for an example
   # on how to use the Perfetto Client API from the android tree.
@@ -208,10 +211,18 @@
     complete_static_lib = true
     public_deps = [
       "gn:default_deps",
-      "src/tracing:client_api",
       "src/tracing:platform_posix",
       "src/tracing/core",
     ]
+
+    if (perfetto_build_with_android) {
+      # Android in-tree builds expose only the system backend and don't expose
+      # the in-process backend. This is to save binary size and memory (see
+      # b/148198993).
+      public_deps += [ "src/tracing:client_api_system_backend_only" ]
+    } else {
+      public_deps += [ "src/tracing:client_api" ]
+    }
     sources = [ "include/perfetto/tracing.h" ]
     assert_no_deps = [ "//gn:protobuf_lite" ]
   }
diff --git a/src/tracing/BUILD.gn b/src/tracing/BUILD.gn
index c93d5a5..936eb2d 100644
--- a/src/tracing/BUILD.gn
+++ b/src/tracing/BUILD.gn
@@ -17,6 +17,55 @@
 import("../../gn/perfetto.gni")
 import("../../gn/test.gni")
 
+# Full version of the client API. Supports both the in-process backend and the
+# system backend (on posix systems and if enabled by the enable_perfetto_ipc).
+# It has a larger binary footprint due to the service code for the in-proecss
+# backend.
+group("client_api") {
+  public_deps = [
+    ":client_api_base",
+    "../../gn:default_deps",
+  ]
+  deps = [ ":in_process_backend" ]
+  if (enable_perfetto_ipc) {
+    deps += [ ":system_process_backend" ]
+  } else {
+    deps += [ ":system_process_backend_fake" ]
+  }
+}
+
+# Slim version of the client API. Works only with the system backend (traced
+# connection over a UNIX socket). Has a lighter binary size impact.
+if (enable_perfetto_ipc) {
+  source_set("client_api_system_backend_only") {
+    public_deps = [
+      ":client_api_base",
+      "../../gn:default_deps",
+    ]
+    deps = [
+      ":in_process_backend_fake",
+      ":system_process_backend",
+    ]
+  }
+}
+
+# This target checks only that the "fake" backends compile. This is to detect
+# early if we break them with refactorings, without waiting for TreeHugger or
+# rolls into chromium.
+if (perfetto_build_standalone) {
+  shared_library("client_api_no_backends_compile_test") {
+    public_deps = [
+      ":client_api_base",
+      "../../gn:default_deps",
+    ]
+    deps = [
+      ":in_process_backend_fake",
+      ":platform_fake",
+      ":system_process_backend_fake",
+    ]
+  }
+}
+
 # Separate target because the embedder might not want this (e.g. on Windows).
 if (is_linux || is_mac || is_android) {
   source_set("platform_posix") {
@@ -51,13 +100,13 @@
   sources = [ "trace_writer_base.cc" ]
 }
 
-source_set("client_api") {
+# Base target for the client API. On its own doesn't provide any backend.
+source_set("client_api_base") {
   deps = [
     "../../include/perfetto/tracing/core",
     "../../protos/perfetto/config:cpp",
     "../base",
     "core",
-    "core:service",
   ]
   public_deps = [
     "../../gn:default_deps",
@@ -67,8 +116,8 @@
     "data_source.cc",
     "debug_annotation.cc",
     "event_context.cc",
-    "internal/in_process_tracing_backend.cc",
     "internal/in_process_tracing_backend.h",
+    "internal/system_tracing_backend.h",
     "internal/tracing_muxer_impl.cc",
     "internal/tracing_muxer_impl.h",
     "internal/track_event_internal.cc",
@@ -78,16 +127,59 @@
     "track_event_category_registry.cc",
     "virtual_destructors.cc",
   ]
+}
 
-  if (enable_perfetto_ipc) {
-    deps += [
+# System backend: connects to an external "traced" instance via a UNIX socket.
+# Requires the IPC layer and is supported only on posix systems.
+if (enable_perfetto_ipc) {
+  source_set("system_process_backend") {
+    public_deps = [ "../../include/perfetto/tracing" ]
+    deps = [
+      ":client_api_base",
+      "../../gn:default_deps",
+      "../../include/perfetto/tracing/core",
+      "../base",
       "ipc/consumer",
       "ipc/producer",
       "ipc/service",
     ]
-    sources += [
-      "internal/system_tracing_backend.cc",
-      "internal/system_tracing_backend.h",
-    ]
+    sources = [ "internal/system_tracing_backend.cc" ]
   }
 }
+
+# System backend fallback: it prints an error message and returns nullptr.
+source_set("system_process_backend_fake") {
+  public_deps = [ "../../include/perfetto/tracing" ]
+  deps = [
+    ":client_api_base",
+    "../../gn:default_deps",
+    "../base",
+  ]
+  sources = [ "internal/system_tracing_backend_fake.cc" ]
+}
+
+# In-process backend: starts the tracing service in-process on a dedicated
+# thread. It depends only on having a valid "platform" target. It has a larger
+# binary size cost because links in all the service code.
+source_set("in_process_backend") {
+  public_deps = [ "../../include/perfetto/tracing" ]
+  deps = [
+    ":client_api_base",
+    "../../gn:default_deps",
+    "../../include/perfetto/tracing/core",
+    "../base",
+    "core:service",
+  ]
+  sources = [ "internal/in_process_tracing_backend.cc" ]
+}
+
+# In-process backend fallback: it prints an error messaage and returns nullptr.
+source_set("in_process_backend_fake") {
+  public_deps = [ "../../include/perfetto/tracing" ]
+  deps = [
+    ":client_api_base",
+    "../../gn:default_deps",
+    "../base",
+  ]
+  sources = [ "internal/in_process_tracing_backend_fake.cc" ]
+}
diff --git a/src/tracing/internal/in_process_tracing_backend_fake.cc b/src/tracing/internal/in_process_tracing_backend_fake.cc
new file mode 100644
index 0000000..7ffafa8
--- /dev/null
+++ b/src/tracing/internal/in_process_tracing_backend_fake.cc
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/tracing/internal/in_process_tracing_backend.h"
+
+#include "perfetto/base/logging.h"
+
+namespace perfetto {
+namespace internal {
+
+// static
+InProcessTracingBackend* InProcessTracingBackend::GetInstance() {
+  PERFETTO_ELOG(
+      "In-process tracing backend not supported by the current build "
+      "configuration");
+  return nullptr;
+}
+
+}  // namespace internal
+}  // namespace perfetto
diff --git a/src/tracing/internal/system_tracing_backend_fake.cc b/src/tracing/internal/system_tracing_backend_fake.cc
new file mode 100644
index 0000000..6a940ae
--- /dev/null
+++ b/src/tracing/internal/system_tracing_backend_fake.cc
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/tracing/internal/system_tracing_backend.h"
+
+#include "perfetto/base/logging.h"
+
+namespace perfetto {
+namespace internal {
+
+// static
+SystemTracingBackend* SystemTracingBackend::GetInstance() {
+  PERFETTO_ELOG(
+      "System tracing backend not supported by the current build "
+      "configuration");
+  return nullptr;
+}
+
+}  // namespace internal
+}  // namespace perfetto
diff --git a/src/tracing/internal/tracing_muxer_impl.cc b/src/tracing/internal/tracing_muxer_impl.cc
index a185f25..e63bc11 100644
--- a/src/tracing/internal/tracing_muxer_impl.cc
+++ b/src/tracing/internal/tracing_muxer_impl.cc
@@ -421,6 +421,12 @@
   PERFETTO_DCHECK_THREAD(thread_checker_);  // Rebind the thread checker.
 
   auto add_backend = [this, &args](TracingBackend* backend, BackendType type) {
+    if (!backend) {
+      // We skip the log in release builds because the *_backend_fake.cc code
+      // has already an ELOG before returning a nullptr.
+      PERFETTO_DLOG("Backend creation failed, type %d", static_cast<int>(type));
+      return;
+    }
     TracingBackendId backend_id = backends_.size();
     backends_.emplace_back();
     RegisteredBackend& rb = backends_.back();
@@ -437,13 +443,12 @@
     rb.producer->Initialize(rb.backend->ConnectProducer(conn_args));
   };
 
-  if (args.backends & kSystemBackend) {
-#if (PERFETTO_BUILDFLAG(PERFETTO_IPC))
+  // Both the system and the in-process backends can be disabled at build-time
+  // and replaced with the _fake.cc versions. The "fake" versions will just
+  // ELOG() and return nullptr.
+
+  if (args.backends & kSystemBackend)
     add_backend(SystemTracingBackend::GetInstance(), kSystemBackend);
-#else
-    PERFETTO_ELOG("System backend not supporteed in the current configuration");
-#endif
-  }
 
   if (args.backends & kInProcessBackend)
     add_backend(InProcessTracingBackend::GetInstance(), kInProcessBackend);