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