Cleanup perfetto_cmd.cc

- Move android-specific stuff to perfetto_cmd_android.cc
- Move dropbox code into android_internal
- Get rid of AndroidTaskRunner. Looks like it's not necessary
  anymore.
- Get rid of libandroid.so dependency (previously required for
  AndroidTaskRunner). This is a huge improvement because
  libandroid.so was used to pull transitively hundreds of .so(s)

Test: manual
Change-Id: I2d9a78a6a9cd146c3693fbccd88467acfbb2eac5
diff --git a/Android.bp b/Android.bp
index da5a262..550e67c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -393,6 +393,7 @@
   name: "libperfetto_android_internal",
   srcs: [
     "src/android_internal/atrace_hal.cc",
+    "src/android_internal/dropbox_service.cc",
     "src/android_internal/health_hal.cc",
     "src/android_internal/incident_service.cc",
     "src/android_internal/power_stats_hal.cc",
@@ -406,6 +407,7 @@
     "libhidlbase",
     "libincident",
     "liblog",
+    "libservices",
     "libutils",
   ],
   static_libs: [
@@ -417,6 +419,11 @@
   cflags: [
     "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
+  product_variables: {
+    pdk: {
+      enabled: false,
+    },
+  },
 }
 
 // GN target: //:libperfetto_client_experimental
@@ -598,7 +605,6 @@
     ":perfetto_src_ipc_wire_protocol_gen",
     ":perfetto_src_perfetto_cmd_protos_gen",
     "src/android_internal/lazy_library_loader.cc",
-    "src/base/android_task_runner.cc",
     "src/base/event_fd.cc",
     "src/base/file_utils.cc",
     "src/base/metatrace.cc",
@@ -627,6 +633,7 @@
     "src/perfetto_cmd/packet_writer.cc",
     "src/perfetto_cmd/pbtxt_to_pb.cc",
     "src/perfetto_cmd/perfetto_cmd.cc",
+    "src/perfetto_cmd/perfetto_cmd_android.cc",
     "src/perfetto_cmd/rate_limiter.cc",
     "src/perfetto_cmd/trigger_producer.cc",
     "src/protozero/message.cc",
@@ -661,12 +668,8 @@
     "src/tracing/trace_writer_base.cc",
   ],
   shared_libs: [
-    "libandroid",
-    "libbinder",
     "liblog",
     "libprotobuf-cpp-lite",
-    "libservices",
-    "libutils",
     "libz",
   ],
   static_libs: [
@@ -705,11 +708,6 @@
     "-DHAVE_HIDDEN",
     "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
-  product_variables: {
-    pdk: {
-      enabled: false,
-    },
-  },
 }
 
 cc_defaults {
@@ -778,7 +776,6 @@
     ":perfetto_protos_perfetto_trace_zero_gen",
     ":perfetto_src_ipc_wire_protocol_gen",
     "src/android_internal/lazy_library_loader.cc",
-    "src/base/android_task_runner.cc",
     "src/base/event_fd.cc",
     "src/base/file_utils.cc",
     "src/base/metatrace.cc",
@@ -897,7 +894,6 @@
     "test/test_helper.cc",
   ],
   shared_libs: [
-    "libandroid",
     "libbase",
     "liblog",
     "libprocinfo",
@@ -953,11 +949,6 @@
     "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
     "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
-  product_variables: {
-    pdk: {
-      enabled: false,
-    },
-  },
 }
 
 // GN target: //protos/perfetto/common:lite_gen
@@ -3402,7 +3393,6 @@
     ":perfetto_src_traced_probes_ftrace_test_messages_lite_gen",
     ":perfetto_src_traced_probes_ftrace_test_messages_zero_gen",
     "src/android_internal/lazy_library_loader.cc",
-    "src/base/android_task_runner.cc",
     "src/base/circular_queue_unittest.cc",
     "src/base/copyable_ptr_unittest.cc",
     "src/base/event_fd.cc",
@@ -3461,6 +3451,7 @@
     "src/perfetto_cmd/pbtxt_to_pb.cc",
     "src/perfetto_cmd/pbtxt_to_pb_unittest.cc",
     "src/perfetto_cmd/perfetto_cmd.cc",
+    "src/perfetto_cmd/perfetto_cmd_android.cc",
     "src/perfetto_cmd/rate_limiter.cc",
     "src/perfetto_cmd/rate_limiter_unittest.cc",
     "src/perfetto_cmd/trigger_producer.cc",
@@ -3605,16 +3596,12 @@
     "tools/sanitizers_unittests/sanitizers_unittest.cc",
   ],
   shared_libs: [
-    "libandroid",
     "libbase",
-    "libbinder",
     "liblog",
     "libprocinfo",
     "libprotobuf-cpp-full",
     "libprotobuf-cpp-lite",
-    "libservices",
     "libunwindstack",
-    "libutils",
     "libz",
   ],
   static_libs: [
@@ -3672,11 +3659,6 @@
     "-DHAVE_HIDDEN",
     "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
-  product_variables: {
-    pdk: {
-      enabled: false,
-    },
-  },
 }
 
 // GN target: //:trace_processor_shell
@@ -4186,7 +4168,6 @@
 cc_library_static {
   name: "perfetto_cts_deps",
   srcs: [
-    "src/base/android_task_runner.cc",
     "src/base/test/test_task_runner.cc",
     "src/traced/probes/ftrace/cpu_reader.cc",
     "src/traced/probes/ftrace/event_info.cc",
@@ -4221,7 +4202,6 @@
 cc_library_static {
   name: "perfetto_cts_jni_deps",
   srcs: [
-    "src/base/android_task_runner.cc",
     "src/base/test/test_task_runner.cc",
     "test/fake_producer.cc",
     "test/task_runner_thread_delegates.cc",
diff --git a/Android.bp.extras b/Android.bp.extras
index 3d89bce..1defc2e 100644
--- a/Android.bp.extras
+++ b/Android.bp.extras
@@ -2,7 +2,6 @@
 cc_library_static {
   name: "perfetto_cts_deps",
   srcs: [
-    "src/base/android_task_runner.cc",
     "src/base/test/test_task_runner.cc",
     "src/traced/probes/ftrace/cpu_reader.cc",
     "src/traced/probes/ftrace/event_info.cc",
@@ -37,7 +36,6 @@
 cc_library_static {
   name: "perfetto_cts_jni_deps",
   srcs: [
-    "src/base/android_task_runner.cc",
     "src/base/test/test_task_runner.cc",
     "test/fake_producer.cc",
     "test/task_runner_thread_delegates.cc",
diff --git a/include/perfetto/ext/base/BUILD.gn b/include/perfetto/ext/base/BUILD.gn
index 112a927..753d9e2 100644
--- a/include/perfetto/ext/base/BUILD.gn
+++ b/include/perfetto/ext/base/BUILD.gn
@@ -47,9 +47,6 @@
     "watchdog_posix.h",
     "weak_ptr.h",
   ]
-  if (is_android) {
-    sources += [ "android_task_runner.h" ]
-  }
   if (perfetto_build_with_ipc_layer) {
     sources += [ "unix_socket.h" ]
   }
diff --git a/include/perfetto/ext/base/android_task_runner.h b/include/perfetto/ext/base/android_task_runner.h
deleted file mode 100644
index d73bea7..0000000
--- a/include/perfetto/ext/base/android_task_runner.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_BASE_ANDROID_TASK_RUNNER_H_
-#define INCLUDE_PERFETTO_EXT_BASE_ANDROID_TASK_RUNNER_H_
-
-#include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/event_fd.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/thread_checker.h"
-#include "perfetto/ext/base/time.h"
-
-#include <poll.h>
-#include <chrono>
-#include <map>
-#include <mutex>
-#include <queue>
-
-#include <android/looper.h>
-
-namespace perfetto {
-namespace base {
-
-// Runs a task runner on a thread owned by an Android Looper (ALooper).
-class AndroidTaskRunner : public TaskRunner {
- public:
-  AndroidTaskRunner();
-  ~AndroidTaskRunner() override;
-
-  // The following methods are only used in cases where the caller wants to take
-  // ownership of the current thread (e.g., tests and standalone tools).
-  // Normally the Android Framework runs the event loop on the thread. Run() can
-  // only be called from the main thread but Quit() can be called from any
-  // thread.
-  void Run();
-  void Quit();
-
-  // Checks whether there are any pending immediate tasks to run. Note that
-  // delayed tasks don't count even if they are due to run. Can only be called
-  // from the main thread.
-  bool IsIdleForTesting();
-
-  // TaskRunner implementation:
-  void PostTask(std::function<void()>) override;
-  void PostDelayedTask(std::function<void()>, uint32_t delay_ms) override;
-  void AddFileDescriptorWatch(int fd, std::function<void()>) override;
-  void RemoveFileDescriptorWatch(int fd) override;
-  bool RunsTasksOnCurrentThread() const override;
-
- private:
-  bool OnFileDescriptorEvent(int signalled_fd, int events);
-  void RunImmediateTask();
-  void RunDelayedTask();
-
-  void GetNextDelayedTaskRunTimeLocked(struct itimerspec* runtime);
-
-  void ScheduleImmediateWakeUp();
-  void ScheduleDelayedWakeUp(TimeMillis time);
-
-  ALooper* const looper_;
-  EventFd immediate_event_;
-  ScopedFile delayed_timer_;
-
-  ThreadChecker thread_checker_;
-
-  // --- Begin lock-protected members.
-  std::mutex lock_;
-  // Note: std::deque allocates blocks of 4k in some implementations. Consider
-  // another data structure if we end up having many task runner instances.
-  std::deque<std::function<void()>> immediate_tasks_;
-  std::multimap<TimeMillis, std::function<void()>> delayed_tasks_;
-  std::map<int, std::function<void()>> watch_tasks_;
-  bool quit_ = false;
-  // --- End lock-protected members.
-};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_ANDROID_TASK_RUNNER_H_
diff --git a/src/android_internal/BUILD.gn b/src/android_internal/BUILD.gn
index 52e86e1..d1bea0f 100644
--- a/src/android_internal/BUILD.gn
+++ b/src/android_internal/BUILD.gn
@@ -20,6 +20,7 @@
   ]
   sources = [
     "atrace_hal.h",
+    "dropbox_service.h",
     "health_hal.h",
     "incident_service.h",
     "power_stats_hal.h",
@@ -52,6 +53,7 @@
   if (perfetto_build_with_android) {
     sources = [
       "atrace_hal.cc",
+      "dropbox_service.cc",
       "health_hal.cc",
       "incident_service.cc",
       "power_stats_hal.cc",
@@ -65,6 +67,7 @@
       "log",
       "hidlbase",
       "incident",
+      "services",
       "utils",
     ]
   }
diff --git a/src/android_internal/dropbox_service.cc b/src/android_internal/dropbox_service.cc
new file mode 100644
index 0000000..8088028
--- /dev/null
+++ b/src/android_internal/dropbox_service.cc
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 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/android_internal/dropbox_service.h"
+
+#include <android/os/DropBoxManager.h>
+#include <utils/StrongPointer.h>
+
+namespace perfetto {
+namespace android_internal {
+
+bool SaveIntoDropbox(const char* tag, int fd) {
+  using android::os::DropBoxManager;
+  android::sp<DropBoxManager> dropbox(new DropBoxManager());
+  auto status = dropbox->addFile(android::String16(tag), fd, /*flags=*/0);
+  return status.isOk();
+}
+
+}  // namespace android_internal
+}  // namespace perfetto
diff --git a/src/android_internal/dropbox_service.h b/src/android_internal/dropbox_service.h
new file mode 100644
index 0000000..6365355
--- /dev/null
+++ b/src/android_internal/dropbox_service.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifndef SRC_ANDROID_INTERNAL_DROPBOX_SERVICE_H_
+#define SRC_ANDROID_INTERNAL_DROPBOX_SERVICE_H_
+
+namespace perfetto {
+namespace android_internal {
+
+extern "C" {
+
+// Saves the passed file into Dropbox with the given tag.
+// Takes ownership of the passed file descriptor.
+bool __attribute__((visibility("default")))
+SaveIntoDropbox(const char* tag, int fd);
+
+}  // extern "C"
+
+}  // namespace android_internal
+}  // namespace perfetto
+
+#endif  // SRC_ANDROID_INTERNAL_DROPBOX_SERVICE_H_
diff --git a/src/base/BUILD.gn b/src/base/BUILD.gn
index 043225b..eaced7d 100644
--- a/src/base/BUILD.gn
+++ b/src/base/BUILD.gn
@@ -57,26 +57,6 @@
   }
 }
 
-# The "android_task_runner" should be depended on only by targets that
-# explicitly need it, as it pulls in a dependency on libandroid.so that in turn
-# pulls dozen of other .so(s).
-if (is_android && (perfetto_build_standalone || perfetto_build_with_android)) {
-  source_set("android_task_runner") {
-    deps = [
-      ":base",
-      "../../gn:default_deps",
-    ]
-    sources = [
-      "android_task_runner.cc",
-    ]
-    all_dependent_configs = [ ":android_config" ]
-  }
-
-  config("android_config") {
-    libs = [ "android" ]
-  }
-}
-
 if (is_debug && perfetto_build_standalone && !is_wasm) {
   source_set("debug_crash_stack_trace") {
     sources = [
@@ -139,10 +119,6 @@
     "../../gn:gtest_and_gmock",
   ]
 
-  if (is_android &&
-      (perfetto_build_standalone || perfetto_build_with_android)) {
-    deps += [ ":android_task_runner" ]
-  }
   sources = [
     "circular_queue_unittest.cc",
     "copyable_ptr_unittest.cc",
diff --git a/src/base/android_task_runner.cc b/src/base/android_task_runner.cc
deleted file mode 100644
index e6979e4..0000000
--- a/src/base/android_task_runner.cc
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2017 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 "perfetto/ext/base/android_task_runner.h"
-
-#include <errno.h>
-#include <sys/timerfd.h>
-
-#include "perfetto/ext/base/watchdog.h"
-
-namespace perfetto {
-namespace base {
-
-AndroidTaskRunner::AndroidTaskRunner()
-    : looper_(ALooper_prepare(0 /* require callbacks */)),
-      delayed_timer_(
-          timerfd_create(kWallTimeClockSource, TFD_NONBLOCK | TFD_CLOEXEC)) {
-  ALooper_acquire(looper_);
-  PERFETTO_CHECK(delayed_timer_);
-  AddFileDescriptorWatch(immediate_event_.fd(),
-                         std::bind(&AndroidTaskRunner::RunImmediateTask, this));
-  AddFileDescriptorWatch(delayed_timer_.get(),
-                         std::bind(&AndroidTaskRunner::RunDelayedTask, this));
-}
-
-AndroidTaskRunner::~AndroidTaskRunner() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  std::lock_guard<std::mutex> lock(lock_);
-  for (const auto& watch : watch_tasks_) {
-    // ALooper doesn't guarantee that each watch doesn't run one last time if
-    // the file descriptor was already signalled. To guard against this point
-    // the watch to a no-op callback.
-    ALooper_addFd(
-        looper_, watch.first, ALOOPER_POLL_CALLBACK,
-        ALOOPER_EVENT_INPUT | ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP,
-        [](int, int, void*) -> int { return 0; }, nullptr);
-    ALooper_removeFd(looper_, watch.first);
-  }
-  ALooper_release(looper_);
-
-  struct itimerspec time = {};
-  timerfd_settime(delayed_timer_.get(), TFD_TIMER_ABSTIME, &time, nullptr);
-}
-
-void AndroidTaskRunner::Run() {
-  quit_ = false;
-  for (;;) {
-    {
-      std::lock_guard<std::mutex> lock(lock_);
-      if (quit_)
-        break;
-    }
-    ALooper_pollOnce(-1 /* timeout */, nullptr, nullptr, nullptr);
-  }
-}
-
-void AndroidTaskRunner::Quit() {
-  std::lock_guard<std::mutex> lock(lock_);
-  quit_ = true;
-  ALooper_wake(looper_);
-}
-
-bool AndroidTaskRunner::IsIdleForTesting() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  std::lock_guard<std::mutex> lock(lock_);
-  return immediate_tasks_.empty();
-}
-
-void AndroidTaskRunner::RunImmediateTask() {
-  immediate_event_.Clear();
-
-  // If locking overhead becomes an issue, add a separate work queue.
-  bool has_next;
-  std::function<void()> immediate_task;
-  {
-    std::lock_guard<std::mutex> lock(lock_);
-    if (immediate_tasks_.empty())
-      return;
-    immediate_task = std::move(immediate_tasks_.front());
-    immediate_tasks_.pop_front();
-    has_next = !immediate_tasks_.empty();
-  }
-  // Do another pass through the event loop even if we have immediate tasks to
-  // run for fairness.
-  if (has_next)
-    ScheduleImmediateWakeUp();
-  errno = 0;
-  RunTaskWithWatchdogGuard(immediate_task);
-}
-
-void AndroidTaskRunner::RunDelayedTask() {
-  uint64_t unused = 0;
-  if (read(delayed_timer_.get(), &unused, sizeof(unused)) != sizeof(unused) &&
-      errno != EAGAIN) {
-    PERFETTO_DPLOG("read");
-  }
-
-  std::function<void()> delayed_task;
-  TimeMillis next_wake_up{};
-  {
-    std::lock_guard<std::mutex> lock(lock_);
-    if (delayed_tasks_.empty())
-      return;
-    auto it = delayed_tasks_.begin();
-    PERFETTO_DCHECK(GetWallTimeMs() >= it->first);
-    delayed_task = std::move(it->second);
-    delayed_tasks_.erase(it);
-    if (!delayed_tasks_.empty())
-      next_wake_up = delayed_tasks_.begin()->first;
-  }
-  if (next_wake_up.count())
-    ScheduleDelayedWakeUp(next_wake_up);
-  errno = 0;
-  RunTaskWithWatchdogGuard(delayed_task);
-}
-
-void AndroidTaskRunner::ScheduleImmediateWakeUp() {
-  immediate_event_.Notify();
-}
-
-void AndroidTaskRunner::ScheduleDelayedWakeUp(TimeMillis time) {
-  PERFETTO_DCHECK(time.count());
-  struct itimerspec wake_up = {};
-  wake_up.it_value = ToPosixTimespec(time);
-  if (timerfd_settime(delayed_timer_.get(), TFD_TIMER_ABSTIME, &wake_up,
-                      nullptr) == -1) {
-    PERFETTO_DPLOG("timerfd_settime");
-  }
-}
-
-void AndroidTaskRunner::PostTask(std::function<void()> task) {
-  bool was_empty;
-  {
-    std::lock_guard<std::mutex> lock(lock_);
-    was_empty = immediate_tasks_.empty();
-    immediate_tasks_.push_back(std::move(task));
-  }
-  if (was_empty)
-    ScheduleImmediateWakeUp();
-}
-
-void AndroidTaskRunner::PostDelayedTask(std::function<void()> task,
-                                        uint32_t delay_ms) {
-  PERFETTO_DCHECK(delay_ms >= 0);
-  TimeMillis runtime = GetWallTimeMs() + TimeMillis(delay_ms);
-  bool is_next = false;
-  {
-    std::lock_guard<std::mutex> lock(lock_);
-    auto it = delayed_tasks_.insert(std::make_pair(runtime, std::move(task)));
-    if (it == delayed_tasks_.begin())
-      is_next = true;
-  }
-  if (is_next)
-    ScheduleDelayedWakeUp(runtime);
-}
-
-void AndroidTaskRunner::AddFileDescriptorWatch(int fd,
-                                               std::function<void()> task) {
-  PERFETTO_DCHECK(fd >= 0);
-  {
-    std::lock_guard<std::mutex> lock(lock_);
-    PERFETTO_DCHECK(!watch_tasks_.count(fd));
-    watch_tasks_[fd] = std::move(task);
-  }
-  // It's safe for the callback to hang on to |this| as everything is
-  // unregistered in the destructor.
-  auto callback = [](int signalled_fd, int events, void* data) -> int {
-    AndroidTaskRunner* task_runner = reinterpret_cast<AndroidTaskRunner*>(data);
-    return task_runner->OnFileDescriptorEvent(signalled_fd, events) ? 1 : 0;
-  };
-  PERFETTO_CHECK(ALooper_addFd(looper_, fd, ALOOPER_POLL_CALLBACK,
-                               ALOOPER_EVENT_INPUT | ALOOPER_EVENT_ERROR |
-                                   ALOOPER_EVENT_HANGUP,
-                               std::move(callback), this) != -1);
-}
-
-bool AndroidTaskRunner::OnFileDescriptorEvent(int signalled_fd, int events) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  if (!(events & (ALOOPER_EVENT_INPUT | ALOOPER_EVENT_ERROR |
-                  ALOOPER_EVENT_HANGUP | ALOOPER_EVENT_INVALID))) {
-    return true;
-  }
-  std::function<void()> task;
-  {
-    std::lock_guard<std::mutex> lock(lock_);
-    auto it = watch_tasks_.find(signalled_fd);
-    if (it == watch_tasks_.end())
-      return false;
-    task = it->second;
-  }
-  errno = 0;
-  RunTaskWithWatchdogGuard(task);
-  return true;
-}
-
-void AndroidTaskRunner::RemoveFileDescriptorWatch(int fd) {
-  PERFETTO_DCHECK(fd >= 0);
-  {
-    std::lock_guard<std::mutex> lock(lock_);
-    PERFETTO_DCHECK(watch_tasks_.count(fd));
-    watch_tasks_.erase(fd);
-  }
-  ALooper_removeFd(looper_, fd);
-}
-
-bool AndroidTaskRunner::RunsTasksOnCurrentThread() const {
-  return looper_ == ALooper_forThread();
-}
-
-}  // namespace base
-}  // namespace perfetto
diff --git a/src/base/task_runner_unittest.cc b/src/base/task_runner_unittest.cc
index 611cff3..6eb01f6 100644
--- a/src/base/task_runner_unittest.cc
+++ b/src/base/task_runner_unittest.cc
@@ -17,18 +17,12 @@
 #include "perfetto/ext/base/unix_task_runner.h"
 
 #include <gtest/gtest.h>
-#include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/scoped_file.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
-    !PERFETTO_BUILDFLAG(PERFETTO_EMBEDDER_BUILD)
-#include "perfetto/ext/base/android_task_runner.h"
-#endif
-
 #include <thread>
 
+#include "perfetto/base/build_config.h"
 #include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/pipe.h"
+#include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/ext/base/utils.h"
 #include "src/base/test/gtest_test_suite.h"
 
@@ -42,12 +36,7 @@
   T task_runner;
 };
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
-    !PERFETTO_BUILDFLAG(PERFETTO_EMBEDDER_BUILD)
-using TaskRunnerTypes = ::testing::Types<AndroidTaskRunner, UnixTaskRunner>;
-#else
 using TaskRunnerTypes = ::testing::Types<UnixTaskRunner>;
-#endif
 
 TYPED_TEST_SUITE(TaskRunnerTest, TaskRunnerTypes);
 
diff --git a/src/base/test/test_task_runner.h b/src/base/test/test_task_runner.h
index a1a9a35..2d970ec 100644
--- a/src/base/test/test_task_runner.h
+++ b/src/base/test/test_task_runner.h
@@ -28,21 +28,9 @@
 #include "perfetto/ext/base/thread_checker.h"
 #include "perfetto/ext/base/unix_task_runner.h"
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
-    !PERFETTO_BUILDFLAG(PERFETTO_EMBEDDER_BUILD)
-#include "perfetto/ext/base/android_task_runner.h"
-#endif
-
 namespace perfetto {
 namespace base {
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
-    !PERFETTO_BUILDFLAG(PERFETTO_EMBEDDER_BUILD)
-using PlatformTaskRunner = AndroidTaskRunner;
-#else
-using PlatformTaskRunner = UnixTaskRunner;
-#endif
-
 class TestTaskRunner : public TaskRunner {
  public:
   TestTaskRunner();
@@ -71,7 +59,7 @@
   std::string pending_checkpoint_;
   std::map<std::string, bool> checkpoints_;
 
-  PlatformTaskRunner task_runner_;
+  base::UnixTaskRunner task_runner_;
   ThreadChecker thread_checker_;
 };
 
diff --git a/src/perfetto_cmd/BUILD.gn b/src/perfetto_cmd/BUILD.gn
index 1ee4f01..84b9a1c 100644
--- a/src/perfetto_cmd/BUILD.gn
+++ b/src/perfetto_cmd/BUILD.gn
@@ -44,13 +44,8 @@
     "rate_limiter.cc",
     "rate_limiter.h",
   ]
-  if (perfetto_build_with_android) {
-    deps += [ "../base:android_task_runner" ]
-    libs = [
-      "binder",
-      "services",
-      "utils",
-    ]
+  if (is_android) {
+    sources += [ "perfetto_cmd_android.cc" ]
   }
 }
 
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index f54399d..4d97859 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -30,9 +30,9 @@
 #include <iterator>
 #include <sstream>
 
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+
 #include "perfetto/base/logging.h"
-#include "perfetto/common/tracing_service_state.pb.h"
-#include "perfetto/config/trace_config.pb.h"
 #include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/string_view.h"
 #include "perfetto/ext/base/time.h"
@@ -51,18 +51,8 @@
 #include "src/perfetto_cmd/pbtxt_to_pb.h"
 #include "src/perfetto_cmd/trigger_producer.h"
 
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-#include <sys/sendfile.h>
-
-#include <android/os/DropBoxManager.h>
-#include <utils/Looper.h>
-#include <utils/StrongPointer.h>
-
-#include "src/android_internal/incident_service.h"
-#include "src/android_internal/lazy_library_loader.h"
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+#include "perfetto/common/tracing_service_state.pb.h"
+#include "perfetto/config/trace_config.pb.h"
 
 namespace perfetto {
 namespace {
@@ -127,43 +117,9 @@
   return true;
 }
 
-void ClearUmask() {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
-  umask(0000);
-#endif
-}
-
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-static bool StartIncidentReport(const TraceConfig::IncidentReportConfig& cfg) {
-  PERFETTO_LAZY_LOAD(android_internal::StartIncidentReport, start_incident_fn);
-  if (!start_incident_fn)
-    return false;
-  return start_incident_fn(cfg.destination_package().c_str(),
-                           cfg.destination_class().c_str(),
-                           cfg.privacy_level());
-}
-#else
-static bool StartIncidentReport(const TraceConfig::IncidentReportConfig&) {
-  PERFETTO_FATAL("should not be called");
-}
-#endif
-
 }  // namespace
 
-// Directory for temporary trace files. Note that this is automatically created
-// by the system by setting setprop persist.traced.enable=1.
-const char* kTempDropBoxTraceDir = "/data/misc/perfetto-traces";
-
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-// If writing into an incident, the trace is written to a hardcoded location
-// that is known to incidentd.
-static const char kIncidentTraceLocation[] =
-    "/data/misc/perfetto-traces/incident-trace";
-static const char kTempIncidentTraceLocation[] =
-    "/data/misc/perfetto-traces/incident-trace.temp";
-#endif
+const char* kStateDir = "/data/misc/perfetto-traces";
 
 using protozero::proto_utils::MakeTagLengthDelimited;
 using protozero::proto_utils::WriteVarInt;
@@ -214,7 +170,7 @@
 }
 
 int PerfettoCmd::Main(int argc, char** argv) {
-  ClearUmask();  // make sure that file creation is not affected by umask
+  umask(0000);  // make sure that file creation is not affected by umask.
 
   enum LongOption {
     OPT_ALERT_ID = 1000,
@@ -332,13 +288,12 @@
     }
 
     if (option == OPT_DROPBOX) {
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-      if (!optarg)
-        PERFETTO_FATAL("optarg is null");
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+      PERFETTO_CHECK(optarg);
       dropbox_tag_ = optarg;
       continue;
 #else
-      PERFETTO_ELOG("DropBox is only supported with Android tree builds");
+      PERFETTO_ELOG("--dropbox is supported only on Android");
       return 1;
 #endif
     }
@@ -719,9 +674,12 @@
       bytes_written_ = static_cast<size_t>(sz);
   }
 
-  if (dropbox_tag_.empty()) {
+  if (!dropbox_tag_.empty()) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+    SaveTraceIntoDropboxAndIncidentOrCrash();
+#endif
+  } else {
     trace_out_stream_.reset();
-    did_process_full_trace_ = true;
     if (trace_config_->write_into_file()) {
       // trace_out_path_ might be empty in the case of --attach.
       PERFETTO_LOG("Trace written into the output file");
@@ -729,104 +687,17 @@
       PERFETTO_LOG("Wrote %" PRIu64 " bytes into %s", bytes_written_,
                    trace_out_path_ == "-" ? "stdout" : trace_out_path_.c_str());
     }
-    task_runner_.Quit();
-    return;
-  }
-
-  // Otherwise, write to Dropbox unless there's a special override in the
-  // incident report config.
-  if (!trace_config_->incident_report_config().skip_dropbox()) {
-    SaveOutputToDropboxOrCrash();
-  }
-
-  // Optionally save the trace as an incident. This is either in addition to, or
-  // instead of, the Dropbox write.
-  if (!trace_config_->incident_report_config().destination_package().empty()) {
-    SaveOutputToIncidentTraceOrCrash();
-
-    // Ask incidentd to create a report, which will read the file we just wrote.
-    PERFETTO_CHECK(
-        StartIncidentReport(trace_config_->incident_report_config()));
   }
 
   did_process_full_trace_ = true;
   task_runner_.Quit();
 }
 
-void PerfettoCmd::SaveOutputToDropboxOrCrash() {
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-  if (bytes_written_ == 0) {
-    PERFETTO_LOG("Skipping write to dropbox. Empty trace.");
-    return;
-  }
-  android::sp<android::os::DropBoxManager> dropbox =
-      new android::os::DropBoxManager();
-  PERFETTO_CHECK(fseek(*trace_out_stream_, 0, SEEK_SET) == 0);
-  // DropBox takes ownership of the file descriptor, so give it a duplicate.
-  // Also we need to give it a read-only copy of the fd or will hit a SELinux
-  // violation (about system_server ending up with a writable FD to our dir).
-  char fdpath[64];
-  sprintf(fdpath, "/proc/self/fd/%d", fileno(*trace_out_stream_));
-  base::ScopedFile read_only_fd(base::OpenFile(fdpath, O_RDONLY));
-  PERFETTO_CHECK(read_only_fd);
-  android::binder::Status status =
-      dropbox->addFile(android::String16(dropbox_tag_.c_str()),
-                       read_only_fd.release(), 0 /* flags */);
-  if (status.isOk()) {
-    PERFETTO_LOG("Wrote %" PRIu64
-                 " bytes (before compression) into DropBox with tag %s",
-                 bytes_written_, dropbox_tag_.c_str());
-  } else {
-    PERFETTO_FATAL("DropBox upload failed: %s", status.toString8().c_str());
-  }
-#endif
-}
-
-// Open a staging file (unlinking the previous instance), copy the trace
-// contents over, then rename to a final hardcoded path. Such tracing sessions
-// should not normally overlap. We do not use unique unique filenames to avoid
-// creating an unbounded amount of files in case of errors.
-void PerfettoCmd::SaveOutputToIncidentTraceOrCrash() {
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-  if (bytes_written_ == 0) {
-    PERFETTO_LOG("Skipping incident report. Empty trace.");
-    return;
-  }
-
-  PERFETTO_CHECK(unlink(kTempIncidentTraceLocation) == 0 || errno == ENOENT);
-
-  // SELinux constrains the set of readers.
-  base::ScopedFile staging_fd =
-      base::OpenFile(kTempIncidentTraceLocation, O_CREAT | O_RDWR, 0666);
-  PERFETTO_CHECK(staging_fd);
-
-  off_t offset = 0;
-  PERFETTO_CHECK(sendfile(*staging_fd, fileno(*trace_out_stream_), &offset,
-                          bytes_written_) == bytes_written_);
-
-  staging_fd.reset();
-  PERFETTO_CHECK(rename(kTempIncidentTraceLocation, kIncidentTraceLocation) ==
-                 0);
-// Note: not calling fsync(2), as we're not interested in the file being
-// consistent in case of a crash.
-#endif
-}
-
 bool PerfettoCmd::OpenOutputFile() {
   base::ScopedFile fd;
   if (!dropbox_tag_.empty()) {
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-    // If we are tracing to DropBox, there's no need to make a
-    // filesystem-visible temporary file.
-    // TODO(skyostil): Fall back to base::TempFile for older devices.
-    fd = base::OpenFile(kTempDropBoxTraceDir, O_TMPFILE | O_RDWR, 0600);
-    if (!fd) {
-      PERFETTO_PLOG("Could not create a temporary trace file in %s",
-                    kTempDropBoxTraceDir);
-      return false;
-    }
-#else
-    PERFETTO_FATAL("Tracing to Dropbox requires the Android build.");
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+    fd = OpenDropboxTmpFile();
 #endif
   } else if (trace_out_path_ == "-") {
     fd.reset(dup(STDOUT_FILENO));
diff --git a/src/perfetto_cmd/perfetto_cmd.h b/src/perfetto_cmd/perfetto_cmd.h
index f25e15e..404f8cc 100644
--- a/src/perfetto_cmd/perfetto_cmd.h
+++ b/src/perfetto_cmd/perfetto_cmd.h
@@ -34,23 +34,13 @@
 
 #include "src/perfetto_cmd/perfetto_cmd_state.pb.h"
 
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-#include "perfetto/ext/base/android_task_runner.h"
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-
 namespace perfetto {
 
 class PacketWriter;
 
-// Temporary directory for DropBox traces. Note that this is automatically
+// Directory for local state and temporary files. This is automatically
 // created by the system by setting setprop persist.traced.enable=1.
-extern const char* kTempDropBoxTraceDir;
-
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-using PlatformTaskRunner = base::AndroidTaskRunner;
-#else
-using PlatformTaskRunner = base::UnixTaskRunner;
-#endif
+extern const char* kStateDir;
 
 class PerfettoCmd : public Consumer {
  public:
@@ -77,10 +67,15 @@
   void OnTimeout();
   bool is_detach() const { return !detach_key_.empty(); }
   bool is_attach() const { return !attach_key_.empty(); }
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+  static base::ScopedFile OpenDropboxTmpFile();
+  void SaveTraceIntoDropboxAndIncidentOrCrash();
   void SaveOutputToDropboxOrCrash();
   void SaveOutputToIncidentTraceOrCrash();
+#endif
 
-  PlatformTaskRunner task_runner_;
+  base::UnixTaskRunner task_runner_;
   std::unique_ptr<perfetto::TracingService::ConsumerEndpoint>
       consumer_endpoint_;
   std::unique_ptr<TraceConfig> trace_config_;
diff --git a/src/perfetto_cmd/perfetto_cmd_android.cc b/src/perfetto_cmd/perfetto_cmd_android.cc
new file mode 100644
index 0000000..7ea8744
--- /dev/null
+++ b/src/perfetto_cmd/perfetto_cmd_android.cc
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2018 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/perfetto_cmd/perfetto_cmd.h"
+
+#include <inttypes.h>
+#include <sys/sendfile.h>
+
+#include "perfetto/base/build_config.h"
+#include "perfetto/base/logging.h"
+#include "perfetto/tracing/core/trace_config.h"
+#include "src/android_internal/dropbox_service.h"
+#include "src/android_internal/incident_service.h"
+#include "src/android_internal/lazy_library_loader.h"
+
+namespace perfetto {
+
+void PerfettoCmd::SaveTraceIntoDropboxAndIncidentOrCrash() {
+  PERFETTO_CHECK(!dropbox_tag_.empty());
+
+  // Otherwise, write to Dropbox unless there's a special override in the
+  // incident report config.
+  if (!trace_config_->incident_report_config().skip_dropbox())
+    SaveOutputToDropboxOrCrash();
+
+  // Optionally save the trace as an incident. This is either in addition to, or
+  // instead of, the Dropbox write.
+  if (!trace_config_->incident_report_config().destination_package().empty()) {
+    SaveOutputToIncidentTraceOrCrash();
+
+    // Ask incidentd to create a report, which will read the file we just wrote.
+    const auto& cfg = trace_config_->incident_report_config();
+    PERFETTO_LAZY_LOAD(android_internal::StartIncidentReport, incident_fn);
+    PERFETTO_CHECK(incident_fn(cfg.destination_package().c_str(),
+                               cfg.destination_class().c_str(),
+                               cfg.privacy_level()));
+  }
+}
+
+void PerfettoCmd::SaveOutputToDropboxOrCrash() {
+  if (bytes_written_ == 0) {
+    PERFETTO_LOG("Skipping write to dropbox. Empty trace.");
+    return;
+  }
+  PERFETTO_CHECK(fseek(*trace_out_stream_, 0, SEEK_SET) == 0);
+
+  // DropBox takes ownership of the file descriptor, so give it a duplicate.
+  // Also we need to give it a read-only copy of the fd or will hit a SELinux
+  // violation (about system_server ending up with a writable FD to our dir).
+  char fdpath[64];
+  sprintf(fdpath, "/proc/self/fd/%d", fileno(*trace_out_stream_));
+  base::ScopedFile read_only_fd(base::OpenFile(fdpath, O_RDONLY));
+  PERFETTO_CHECK(read_only_fd);
+
+  PERFETTO_LAZY_LOAD(android_internal::SaveIntoDropbox, dropbox_fn);
+  if (dropbox_fn(dropbox_tag_.c_str(), read_only_fd.release())) {
+    PERFETTO_LOG("Wrote %" PRIu64
+                 " bytes (before compression) into DropBox with tag %s",
+                 bytes_written_, dropbox_tag_.c_str());
+  } else {
+    PERFETTO_FATAL("DropBox upload failed");
+  }
+}
+
+// Open a staging file (unlinking the previous instance), copy the trace
+// contents over, then rename to a final hardcoded path. Such tracing sessions
+// should not normally overlap. We do not use unique unique filenames to avoid
+// creating an unbounded amount of files in case of errors.
+void PerfettoCmd::SaveOutputToIncidentTraceOrCrash() {
+  if (bytes_written_ == 0) {
+    PERFETTO_LOG("Skipping incident report. Empty trace.");
+    return;
+  }
+
+  // If writing into an incident, the trace is written to a hardcoded location
+  // that is known to incidentd.
+
+  char kIncidentTracePath[256];
+  sprintf(kIncidentTracePath, "%s/incident-trace", kStateDir);
+
+  char kTempIncidentTracePath[256];
+  sprintf(kTempIncidentTracePath, "%s.temp", kIncidentTracePath);
+
+  PERFETTO_CHECK(unlink(kTempIncidentTracePath) == 0 || errno == ENOENT);
+
+  // SELinux constrains the set of readers.
+  base::ScopedFile staging_fd =
+      base::OpenFile(kTempIncidentTracePath, O_CREAT | O_RDWR, 0666);
+  PERFETTO_CHECK(staging_fd);
+  off_t offset = 0;
+  auto wsize = sendfile(*staging_fd, fileno(*trace_out_stream_), &offset,
+                        static_cast<size_t>(bytes_written_));
+  PERFETTO_CHECK(wsize == static_cast<ssize_t>(bytes_written_));
+  staging_fd.reset();
+  PERFETTO_CHECK(rename(kTempIncidentTracePath, kIncidentTracePath) == 0);
+  // Note: not calling fsync(2), as we're not interested in the file being
+  // consistent in case of a crash.
+}
+
+// static
+base::ScopedFile PerfettoCmd::OpenDropboxTmpFile() {
+  // If we are tracing to DropBox, there's no need to make a
+  // filesystem-visible temporary file.
+  auto fd = base::OpenFile(kStateDir, O_TMPFILE | O_RDWR, 0600);
+  if (!fd)
+    PERFETTO_PLOG("Could not create a temporary trace file in %s", kStateDir);
+  return fd;
+}
+
+}  // namespace perfetto
diff --git a/src/perfetto_cmd/rate_limiter.cc b/src/perfetto_cmd/rate_limiter.cc
index 7b0cc77..1693d0e 100644
--- a/src/perfetto_cmd/rate_limiter.cc
+++ b/src/perfetto_cmd/rate_limiter.cc
@@ -164,7 +164,7 @@
 }
 
 std::string RateLimiter::GetStateFilePath() const {
-  return std::string(kTempDropBoxTraceDir) + "/.guardraildata";
+  return std::string(kStateDir) + "/.guardraildata";
 }
 
 bool RateLimiter::StateFileExists() {
diff --git a/test/BUILD.gn b/test/BUILD.gn
index 81d4e32..1f2afe1 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -36,10 +36,6 @@
   sources = [
     "end_to_end_integrationtest.cc",
   ]
-  if (is_android &&
-      (perfetto_build_standalone || perfetto_build_with_android)) {
-    deps += [ "../src/base:android_task_runner" ]
-  }
   if (start_daemons_for_testing) {
     cflags = [ "-DPERFETTO_START_DAEMONS_FOR_TESTING" ]
 
@@ -167,9 +163,6 @@
     sources = [
       "end_to_end_benchmark.cc",
     ]
-    if (is_android) {
-      deps += [ "../src/base:android_task_runner" ]
-    }
     if (start_daemons_for_testing) {
       cflags = [ "-DPERFETTO_START_DAEMONS_FOR_TESTING" ]
     }
diff --git a/test/task_runner_thread.cc b/test/task_runner_thread.cc
index 37e29c9..5a92ff5 100644
--- a/test/task_runner_thread.cc
+++ b/test/task_runner_thread.cc
@@ -85,7 +85,7 @@
 #endif
 
   // Create the task runner and execute the specicalised code.
-  base::PlatformTaskRunner task_runner;
+  base::UnixTaskRunner task_runner;
   delegate->Initialize(&task_runner);
 
   // Pass the runner back to the main thread.
diff --git a/test/task_runner_thread.h b/test/task_runner_thread.h
index 078d978..354c308 100644
--- a/test/task_runner_thread.h
+++ b/test/task_runner_thread.h
@@ -61,7 +61,7 @@
 
   // All variables below this point are protected by |mutex_|.
   std::mutex mutex_;
-  base::PlatformTaskRunner* runner_ = nullptr;
+  base::UnixTaskRunner* runner_ = nullptr;
 };
 
 }  // namespace perfetto