Merge "Trigger boot animation on userspace reboot"
diff --git a/adb/Android.bp b/adb/Android.bp
index b39defe..7c5e3ea 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -114,6 +114,61 @@
},
}
+// libadbconnection
+// =========================================================
+// libadbconnection_client/server implement the socket handling for jdwp
+// forwarding and the track-jdwp service.
+cc_library {
+ name: "libadbconnection_server",
+ srcs: ["adbconnection/adbconnection_server.cpp"],
+
+ export_include_dirs: ["adbconnection/include"],
+
+ stl: "libc++_static",
+ shared_libs: ["liblog"],
+ static_libs: ["libbase"],
+
+ defaults: ["adbd_defaults", "host_adbd_supported"],
+
+ // Avoid getting duplicate symbol of android::build::getbuildnumber().
+ use_version_lib: false,
+
+ recovery_available: true,
+ compile_multilib: "both",
+}
+
+cc_library {
+ name: "libadbconnection_client",
+ srcs: ["adbconnection/adbconnection_client.cpp"],
+
+ export_include_dirs: ["adbconnection/include"],
+
+ stl: "libc++_static",
+ shared_libs: ["liblog"],
+ static_libs: ["libbase"],
+
+ defaults: ["adbd_defaults"],
+ visibility: [
+ "//art:__subpackages__",
+ "//system/core/adb/apex:__subpackages__",
+ ],
+ apex_available: [
+ "com.android.adbd",
+ "test_com.android.adbd",
+ ],
+
+ // libadbconnection_client doesn't need an embedded build number.
+ use_version_lib: false,
+
+ stubs: {
+ symbol_file: "adbconnection/libadbconnection_client.map.txt",
+ versions: ["1"],
+ },
+
+ host_supported: true,
+ compile_multilib: "both",
+}
+
// libadb
// =========================================================
// These files are compiled for both the host and the device.
@@ -358,11 +413,11 @@
generated_headers: ["platform_tools_version"],
static_libs: [
+ "libadbconnection_server",
"libdiagnose_usb",
],
shared_libs: [
- "libadbconnection_server",
"libadbd_auth",
"libasyncio",
"libbase",
@@ -411,12 +466,12 @@
],
static_libs: [
+ "libadbconnection_server",
"libadbd_core",
"libdiagnose_usb",
],
shared_libs: [
- "libadbconnection_server",
"libadbd_auth",
"libasyncio",
"libbase",
@@ -452,7 +507,7 @@
defaults: ["adbd_defaults", "host_adbd_supported"],
recovery_available: true,
- // Avoid getting duplicate symbol of android::build::GetBuildNumber().
+ // avoid getting duplicate symbol of android::build::getbuildnumber().
use_version_lib: false,
// libminadbd wants both, as it's used to build native tests.
@@ -460,11 +515,11 @@
// libadbd doesn't build any additional source, but to expose libadbd_core as a shared library.
whole_static_libs: [
+ "libadbconnection_server",
"libadbd_core",
],
shared_libs: [
- "libadbconnection_server",
"libadbd_auth",
"libadbd_services",
"libasyncio",
@@ -500,6 +555,7 @@
stl: "libc++_static",
static_libs: [
+ "libadbconnection_server",
"libadbd",
"libadbd_auth",
"libadbd_services",
@@ -516,7 +572,6 @@
],
shared_libs: [
- "libadbconnection_server",
"libcrypto",
],
}
diff --git a/adb/adbconnection/.clang-format b/adb/adbconnection/.clang-format
new file mode 120000
index 0000000..e545823
--- /dev/null
+++ b/adb/adbconnection/.clang-format
@@ -0,0 +1 @@
+../../.clang-format-2
\ No newline at end of file
diff --git a/adb/adbconnection/adbconnection_client.cpp b/adb/adbconnection/adbconnection_client.cpp
new file mode 100644
index 0000000..ee48abb
--- /dev/null
+++ b/adb/adbconnection/adbconnection_client.cpp
@@ -0,0 +1,148 @@
+/*
+ * 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 "adbconnection/client.h"
+
+#include <pwd.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <memory>
+#include <optional>
+
+#include <android-base/cmsg.h>
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+
+using android::base::unique_fd;
+
+static constexpr char kJdwpControlName[] = "\0jdwp-control";
+
+struct AdbConnectionClientContext {
+ unique_fd control_socket_;
+};
+
+bool SocketPeerIsTrusted(int fd) {
+ ucred cr;
+ socklen_t cr_length = sizeof(cr);
+ if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_length) != 0) {
+ PLOG(ERROR) << "couldn't get socket credentials";
+ return false;
+ }
+
+ passwd* shell = getpwnam("shell");
+ if (cr.uid != 0 && cr.uid != shell->pw_uid) {
+ LOG(ERROR) << "untrusted uid " << cr.uid << " on other end of socket";
+ return false;
+ }
+
+ return true;
+}
+
+AdbConnectionClientContext* adbconnection_client_new(
+ const AdbConnectionClientInfo* const* info_elems, size_t info_count) {
+ auto ctx = std::make_unique<AdbConnectionClientContext>();
+
+ std::optional<uint64_t> pid;
+ std::optional<bool> debuggable;
+
+ for (size_t i = 0; i < info_count; ++i) {
+ auto info = info_elems[i];
+ switch (info->type) {
+ case AdbConnectionClientInfoType::pid:
+ if (pid) {
+ LOG(ERROR) << "multiple pid entries in AdbConnectionClientInfo, ignoring";
+ continue;
+ }
+ pid = info->data.pid;
+ break;
+
+ case AdbConnectionClientInfoType::debuggable:
+ if (debuggable) {
+ LOG(ERROR) << "multiple debuggable entries in AdbConnectionClientInfo, ignoring";
+ continue;
+ }
+ debuggable = info->data.pid;
+ break;
+ }
+ }
+
+ if (!pid) {
+ LOG(ERROR) << "AdbConnectionClientInfo missing required field pid";
+ return nullptr;
+ }
+
+ if (!debuggable) {
+ LOG(ERROR) << "AdbConnectionClientInfo missing required field debuggable";
+ return nullptr;
+ }
+
+ ctx->control_socket_.reset(socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0));
+ if (ctx->control_socket_ < 0) {
+ PLOG(ERROR) << "failed to create Unix domain socket";
+ return nullptr;
+ }
+
+ struct timeval timeout;
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+ setsockopt(ctx->control_socket_.get(), SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
+
+ sockaddr_un addr = {};
+ addr.sun_family = AF_UNIX;
+ memcpy(addr.sun_path, kJdwpControlName, sizeof(kJdwpControlName));
+ size_t addr_len = offsetof(sockaddr_un, sun_path) + sizeof(kJdwpControlName) - 1;
+
+ int rc = connect(ctx->control_socket_.get(), reinterpret_cast<sockaddr*>(&addr), addr_len);
+ if (rc != 0) {
+ PLOG(ERROR) << "failed to connect to jdwp control socket";
+ return nullptr;
+ }
+
+ bool trusted = SocketPeerIsTrusted(ctx->control_socket_.get());
+ if (!trusted) {
+ LOG(ERROR) << "adb socket is not trusted, aborting connection";
+ return nullptr;
+ }
+
+ uint32_t pid_u32 = static_cast<uint32_t>(*pid);
+ rc = TEMP_FAILURE_RETRY(write(ctx->control_socket_.get(), &pid_u32, sizeof(pid_u32)));
+ if (rc != sizeof(pid_u32)) {
+ PLOG(ERROR) << "failed to send JDWP process pid to adbd";
+ }
+
+ return ctx.release();
+}
+
+void adbconnection_client_destroy(AdbConnectionClientContext* ctx) {
+ delete ctx;
+}
+
+int adbconnection_client_pollfd(AdbConnectionClientContext* ctx) {
+ return ctx->control_socket_.get();
+}
+
+int adbconnection_client_receive_jdwp_fd(AdbConnectionClientContext* ctx) {
+ char dummy;
+ unique_fd jdwp_fd;
+ ssize_t rc = android::base::ReceiveFileDescriptors(ctx->control_socket_, &dummy, 1, &jdwp_fd);
+ if (rc != 1) {
+ return rc;
+ }
+ return jdwp_fd.release();
+}
diff --git a/adb/adbconnection/adbconnection_server.cpp b/adb/adbconnection/adbconnection_server.cpp
new file mode 100644
index 0000000..939da2f
--- /dev/null
+++ b/adb/adbconnection/adbconnection_server.cpp
@@ -0,0 +1,129 @@
+/*
+ * 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 "adbconnection/server.h"
+
+#include <sys/epoll.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <array>
+#include <vector>
+
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+
+using android::base::unique_fd;
+
+#define JDWP_CONTROL_NAME "\0jdwp-control"
+#define JDWP_CONTROL_NAME_LEN (sizeof(JDWP_CONTROL_NAME) - 1)
+
+static_assert(JDWP_CONTROL_NAME_LEN <= sizeof(reinterpret_cast<sockaddr_un*>(0)->sun_path));
+
+// Listen for incoming jdwp clients forever.
+void adbconnection_listen(void (*callback)(int fd, pid_t pid)) {
+ sockaddr_un addr = {};
+ socklen_t addrlen = JDWP_CONTROL_NAME_LEN + sizeof(addr.sun_family);
+
+ addr.sun_family = AF_UNIX;
+ memcpy(addr.sun_path, JDWP_CONTROL_NAME, JDWP_CONTROL_NAME_LEN);
+
+ unique_fd s(socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0));
+ if (s < 0) {
+ PLOG(ERROR) << "failed to create JDWP control socket";
+ return;
+ }
+
+ if (bind(s.get(), reinterpret_cast<sockaddr*>(&addr), addrlen) < 0) {
+ PLOG(ERROR) << "failed to bind JDWP control socket";
+ return;
+ }
+
+ if (listen(s.get(), 4) < 0) {
+ PLOG(ERROR) << "failed to listen on JDWP control socket";
+ return;
+ }
+
+ std::vector<unique_fd> pending_connections;
+
+ unique_fd epfd(epoll_create1(EPOLL_CLOEXEC));
+ std::array<epoll_event, 16> events;
+
+ events[0].events = EPOLLIN;
+ events[0].data.fd = -1;
+ if (epoll_ctl(epfd.get(), EPOLL_CTL_ADD, s.get(), &events[0]) != 0) {
+ LOG(FATAL) << "failed to register event with epoll fd";
+ }
+
+ while (true) {
+ int epoll_rc = TEMP_FAILURE_RETRY(epoll_wait(epfd.get(), events.data(), events.size(), -1));
+ if (epoll_rc == -1) {
+ PLOG(FATAL) << "epoll_wait failed";
+ }
+
+ for (int i = 0; i < epoll_rc; ++i) {
+ const epoll_event& event = events[i];
+ if (event.data.fd == -1) {
+ unique_fd client(
+ TEMP_FAILURE_RETRY(accept4(s.get(), nullptr, nullptr, SOCK_NONBLOCK | SOCK_CLOEXEC)));
+
+ if (client == -1) {
+ PLOG(WARNING) << "failed to accept client on JDWP control socket";
+ continue;
+ }
+
+ epoll_event register_event;
+ register_event.events = EPOLLIN;
+ register_event.data.fd = client.get();
+
+ if (epoll_ctl(epfd.get(), EPOLL_CTL_ADD, client.get(), ®ister_event) != 0) {
+ PLOG(FATAL) << "failed to register JDWP client with epoll";
+ }
+
+ pending_connections.emplace_back(std::move(client));
+ } else {
+ // n^2, but the backlog should be short.
+ auto it = std::find_if(pending_connections.begin(), pending_connections.end(),
+ [&](const unique_fd& fd) { return fd.get() == event.data.fd; });
+
+ if (it == pending_connections.end()) {
+ LOG(FATAL) << "failed to find JDWP client (" << event.data.fd
+ << ") in pending connections";
+ }
+
+ // Massively oversized buffer: we're expecting an int32_t from the other end.
+ char buf[32];
+ int rc = TEMP_FAILURE_RETRY(recv(it->get(), buf, sizeof(buf), MSG_DONTWAIT));
+ if (rc != 4) {
+ LOG(ERROR) << "received data of incorrect size from JDWP client: read " << rc
+ << ", expected 4";
+ } else {
+ int32_t pid;
+ memcpy(&pid, buf, sizeof(pid));
+ callback(it->release(), static_cast<pid_t>(pid));
+ }
+
+ if (epoll_ctl(epfd.get(), EPOLL_CTL_DEL, event.data.fd, nullptr) != 0) {
+ LOG(FATAL) << "failed to delete fd from JDWP epoll fd";
+ }
+
+ pending_connections.erase(it);
+ }
+ }
+ }
+}
diff --git a/adb/adbconnection/include/adbconnection/client.h b/adb/adbconnection/include/adbconnection/client.h
new file mode 100644
index 0000000..692fea0
--- /dev/null
+++ b/adb/adbconnection/include/adbconnection/client.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <android-base/unique_fd.h>
+
+extern "C" {
+
+struct AdbConnectionClientContext;
+
+enum AdbConnectionClientInfoType {
+ pid,
+ debuggable,
+};
+
+struct AdbConnectionClientInfo {
+ AdbConnectionClientInfoType type;
+ union {
+ uint64_t pid;
+ bool debuggable;
+ } data;
+};
+
+// Construct a context and connect to adbd.
+// Returns null if we fail to connect to adbd.
+AdbConnectionClientContext* adbconnection_client_new(
+ const AdbConnectionClientInfo* const* info_elems, size_t info_count);
+
+void adbconnection_client_destroy(AdbConnectionClientContext* ctx);
+
+// Get an fd which can be polled upon to detect when a jdwp socket is available.
+// You do not own this fd. Do not close it.
+int adbconnection_client_pollfd(AdbConnectionClientContext* ctx);
+
+// Receive a jdwp client fd.
+// Ownership is transferred to the caller of this function.
+int adbconnection_client_receive_jdwp_fd(AdbConnectionClientContext* ctx);
+}
diff --git a/adb/adbconnection/include/adbconnection/server.h b/adb/adbconnection/include/adbconnection/server.h
new file mode 100644
index 0000000..57ca6cd
--- /dev/null
+++ b/adb/adbconnection/include/adbconnection/server.h
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <sys/types.h>
+
+#include <android-base/unique_fd.h>
+
+extern "C" {
+
+void adbconnection_listen(void (*callback)(int fd, pid_t pid));
+}
diff --git a/adb/adbconnection/libadbconnection_client.map.txt b/adb/adbconnection/libadbconnection_client.map.txt
new file mode 100644
index 0000000..153a0e4
--- /dev/null
+++ b/adb/adbconnection/libadbconnection_client.map.txt
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LIBADBCONNECTION_CLIENT_1 {
+ global:
+ adbconnection_client_new;
+ adbconnection_client_destroy;
+ adbconnection_client_pollfd;
+ adbconnection_client_receive_jdwp_fd;
+ local:
+ *;
+};
diff --git a/adb/apex/Android.bp b/adb/apex/Android.bp
index 40ea448..75c4ed9 100644
--- a/adb/apex/Android.bp
+++ b/adb/apex/Android.bp
@@ -2,6 +2,12 @@
name: "com.android.adbd-defaults",
binaries: ["adbd"],
+ compile_multilib: "both",
+ multilib: {
+ both: {
+ native_shared_libs: ["libadbconnection_client"],
+ },
+ },
prebuilts: ["com.android.adbd.init.rc", "com.android.adbd.ld.config.txt"],
key: "com.android.adbd.key",
diff --git a/base/include/android-base/errno_restorer.h b/base/include/android-base/errno_restorer.h
new file mode 100644
index 0000000..1c8597c
--- /dev/null
+++ b/base/include/android-base/errno_restorer.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "errno.h"
+
+#include "android-base/macros.h"
+
+namespace android {
+namespace base {
+
+class ErrnoRestorer {
+ public:
+ ErrnoRestorer() : saved_errno_(errno) {}
+
+ ~ErrnoRestorer() { errno = saved_errno_; }
+
+ // Allow this object to be used as part of && operation.
+ operator bool() const { return true; }
+
+ private:
+ const int saved_errno_;
+
+ DISALLOW_COPY_AND_ASSIGN(ErrnoRestorer);
+};
+
+} // namespace base
+} // namespace android
diff --git a/base/include/android-base/expected.h b/base/include/android-base/expected.h
index 030ef35e..b3f5adb 100644
--- a/base/include/android-base/expected.h
+++ b/base/include/android-base/expected.h
@@ -111,6 +111,7 @@
!(!std::is_convertible_v<const U&, T> ||
!std::is_convertible_v<const G&, E>) /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr expected(const expected<U, G>& rhs) {
if (rhs.has_value()) var_ = rhs.value();
else var_ = unexpected(rhs.error());
@@ -149,6 +150,7 @@
!(!std::is_convertible_v<const U&, T> ||
!std::is_convertible_v<const G&, E>) /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr expected(expected<U, G>&& rhs) {
if (rhs.has_value()) var_ = std::move(rhs.value());
else var_ = unexpected(std::move(rhs.error()));
@@ -180,6 +182,7 @@
!std::is_same_v<unexpected<E>, std::remove_cv_t<std::remove_reference_t<U>>> &&
std::is_convertible_v<U&&, T> /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr expected(U&& v) : var_(std::in_place_index<0>, std::forward<U>(v)) {}
template <class U = T _ENABLE_IF(
@@ -195,6 +198,7 @@
std::is_constructible_v<E, const G&> &&
std::is_convertible_v<const G&, E> /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr expected(const unexpected<G>& e)
: var_(std::in_place_index<1>, e.value()) {}
@@ -209,6 +213,7 @@
std::is_constructible_v<E, G&&> &&
std::is_convertible_v<G&&, E> /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr expected(unexpected<G>&& e)
: var_(std::in_place_index<1>, std::move(e.value())) {}
@@ -457,6 +462,7 @@
std::is_void_v<U> &&
std::is_convertible_v<const G&, E> /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr expected(const expected<U, G>& rhs) {
if (!rhs.has_value()) var_ = unexpected(rhs.error());
}
@@ -473,6 +479,7 @@
std::is_void_v<U> &&
std::is_convertible_v<const G&&, E> /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr expected(expected<U, G>&& rhs) {
if (!rhs.has_value()) var_ = unexpected(std::move(rhs.error()));
}
@@ -489,6 +496,7 @@
std::is_constructible_v<E, const G&> &&
std::is_convertible_v<const G&, E> /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr expected(const unexpected<G>& e)
: var_(std::in_place_index<1>, e.value()) {}
@@ -503,6 +511,7 @@
std::is_constructible_v<E, G&&> &&
std::is_convertible_v<G&&, E> /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr expected(unexpected<G>&& e)
: var_(std::in_place_index<1>, std::move(e.value())) {}
@@ -640,6 +649,7 @@
std::is_constructible_v<E, Err> &&
!std::is_same_v<std::remove_cv_t<std::remove_reference_t<E>>, std::in_place_t> &&
!std::is_same_v<std::remove_cv_t<std::remove_reference_t<E>>, unexpected>)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr unexpected(Err&& e) : val_(std::forward<Err>(e)) {}
template<class U, class... Args _ENABLE_IF(
@@ -660,6 +670,7 @@
!std::is_convertible_v<const unexpected<Err>, E> &&
std::is_convertible_v<Err, E> /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr unexpected(const unexpected<Err>& rhs)
: val_(rhs.value()) {}
@@ -690,6 +701,7 @@
!std::is_convertible_v<const unexpected<Err>, E> &&
std::is_convertible_v<Err, E> /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr unexpected(unexpected<Err>&& rhs)
: val_(std::move(rhs.value())) {}
diff --git a/base/include/android-base/logging.h b/base/include/android-base/logging.h
index cc162cd..accc225 100644
--- a/base/include/android-base/logging.h
+++ b/base/include/android-base/logging.h
@@ -64,6 +64,7 @@
#include <memory>
#include <ostream>
+#include "android-base/errno_restorer.h"
#include "android-base/macros.h"
// Note: DO NOT USE DIRECTLY. Use LOG_TAG instead.
@@ -154,27 +155,6 @@
// Replace the current aborter.
void SetAborter(AbortFunction&& aborter);
-class ErrnoRestorer {
- public:
- ErrnoRestorer()
- : saved_errno_(errno) {
- }
-
- ~ErrnoRestorer() {
- errno = saved_errno_;
- }
-
- // Allow this object to be used as part of && operation.
- operator bool() const {
- return true;
- }
-
- private:
- const int saved_errno_;
-
- DISALLOW_COPY_AND_ASSIGN(ErrnoRestorer);
-};
-
// A helper macro that produces an expression that accepts both a qualified name and an
// unqualified name for a LogSeverity, and returns a LogSeverity value.
// Note: DO NOT USE DIRECTLY. This is an implementation detail.
diff --git a/base/include/android-base/result.h b/base/include/android-base/result.h
index 1b763af..b6d26e7 100644
--- a/base/include/android-base/result.h
+++ b/base/include/android-base/result.h
@@ -90,6 +90,7 @@
ResultError(T&& message, int code) : message_(std::forward<T>(message)), code_(code) {}
template <typename T>
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator android::base::expected<T, ResultError>() {
return android::base::unexpected(ResultError(message_, code_));
}
@@ -118,9 +119,11 @@
class Error {
public:
Error() : errno_(0), append_errno_(false) {}
+ // NOLINTNEXTLINE(google-explicit-constructor)
Error(int errno_to_append) : errno_(errno_to_append), append_errno_(true) {}
template <typename T>
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator android::base::expected<T, ResultError>() {
return android::base::unexpected(ResultError(str(), errno_));
}
diff --git a/base/logging.cpp b/base/logging.cpp
index 1d8ef57..a868706 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -608,7 +608,6 @@
// we need to fall back to using gMinimumLogSeverity, since __android_log_is_loggable() will not
// take into consideration the value from SetMinimumLogSeverity().
if (liblog_functions) {
- // TODO: It is safe to pass nullptr for tag, but it will be better to use the default log tag.
int priority = LogSeverityToPriority(severity);
return __android_log_is_loggable(priority, tag, ANDROID_LOG_INFO);
} else {
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 3463a68..9180a06 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -101,6 +101,7 @@
using android::base::unique_fd;
using android::dm::DeviceMapper;
using android::dm::DmDeviceState;
+using android::dm::DmTargetLinear;
// Realistically, this file should be part of the android::fs_mgr namespace;
using namespace android::fs_mgr;
@@ -1114,6 +1115,83 @@
}
}
+static constexpr const char* kUserdataWrapperName = "userdata-wrapper";
+
+static void WrapUserdata(FstabEntry* entry, dev_t dev, const std::string& block_device) {
+ DeviceMapper& dm = DeviceMapper::Instance();
+ if (dm.GetState(kUserdataWrapperName) != DmDeviceState::INVALID) {
+ // This will report failure for us. If we do fail to get the path,
+ // we leave the device unwrapped.
+ dm.GetDmDevicePathByName(kUserdataWrapperName, &entry->blk_device);
+ return;
+ }
+
+ unique_fd fd(open(block_device.c_str(), O_RDONLY | O_CLOEXEC));
+ if (fd < 0) {
+ PLOG(ERROR) << "open failed: " << entry->blk_device;
+ return;
+ }
+
+ auto dev_str = android::base::StringPrintf("%u:%u", major(dev), minor(dev));
+ uint64_t sectors = get_block_device_size(fd) / 512;
+
+ android::dm::DmTable table;
+ table.Emplace<DmTargetLinear>(0, sectors, dev_str, 0);
+
+ std::string dm_path;
+ if (!dm.CreateDevice(kUserdataWrapperName, table, &dm_path, 20s)) {
+ LOG(ERROR) << "Failed to create userdata wrapper device";
+ return;
+ }
+ entry->blk_device = dm_path;
+}
+
+// When using Virtual A/B, partitions can be backed by /data and mapped with
+// device-mapper in first-stage init. This can happen when merging an OTA or
+// when using adb remount to house "scratch". In this case, /data cannot be
+// mounted directly off the userdata block device, and e2fsck will refuse to
+// scan it, because the kernel reports the block device as in-use.
+//
+// As a workaround, when mounting /data, we create a trivial dm-linear wrapper
+// if the underlying block device already has dependencies. Note that we make
+// an exception for metadata-encrypted devices, since dm-default-key is already
+// a wrapper.
+static void WrapUserdataIfNeeded(FstabEntry* entry, const std::string& actual_block_device = {}) {
+ const auto& block_device =
+ actual_block_device.empty() ? entry->blk_device : actual_block_device;
+ if (entry->mount_point != "/data" || !entry->key_dir.empty() ||
+ android::base::StartsWith(block_device, "/dev/block/dm-")) {
+ return;
+ }
+
+ struct stat st;
+ if (stat(block_device.c_str(), &st) < 0) {
+ PLOG(ERROR) << "stat failed: " << block_device;
+ return;
+ }
+
+ std::string path = android::base::StringPrintf("/sys/dev/block/%u:%u/holders",
+ major(st.st_rdev), minor(st.st_rdev));
+ std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
+ if (!dir) {
+ PLOG(ERROR) << "opendir failed: " << path;
+ return;
+ }
+
+ struct dirent* d;
+ bool has_holders = false;
+ while ((d = readdir(dir.get())) != nullptr) {
+ if (strcmp(d->d_name, ".") != 0 && strcmp(d->d_name, "..") != 0) {
+ has_holders = true;
+ break;
+ }
+ }
+
+ if (has_holders) {
+ WrapUserdata(entry, st.st_rdev, block_device);
+ }
+}
+
static bool IsMountPointMounted(const std::string& mount_point) {
// Check if this is already mounted.
Fstab fstab;
@@ -1193,6 +1271,8 @@
}
}
+ WrapUserdataIfNeeded(¤t_entry);
+
if (!checkpoint_manager.Update(¤t_entry)) {
continue;
}
@@ -1463,6 +1543,9 @@
}
std::string block_device;
if (auto entry = GetEntryForMountPoint(&proc_mounts, "/data"); entry != nullptr) {
+ // Note: we don't care about a userdata wrapper here, since it's safe
+ // to remount on top of the bow device instead, there will be no
+ // conflicts.
block_device = entry->blk_device;
} else {
LERROR << "/data is not mounted";
@@ -1581,6 +1664,8 @@
}
}
+ WrapUserdataIfNeeded(&fstab_entry, n_blk_device);
+
if (!checkpoint_manager.Update(&fstab_entry, n_blk_device)) {
LERROR << "Could not set up checkpoint partition, skipping!";
continue;
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index f9a3df9..ff6b036 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -130,6 +130,7 @@
#define AID_GSID 1074 /* GSI service daemon */
#define AID_FSVERITY_CERT 1075 /* fs-verity key ownership in keystore */
#define AID_CREDSTORE 1076 /* identity credential manager service */
+#define AID_EXTERNAL_STORAGE 1077 /* Full external storage access including USB OTG volumes */
/* Changes to this file must be made in AOSP, *not* in internal branches. */
#define AID_SHELL 2000 /* adb and debug shell user */
diff --git a/liblog/logger_write.cpp b/liblog/logger_write.cpp
index e86d9ec..ca68296 100644
--- a/liblog/logger_write.cpp
+++ b/liblog/logger_write.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "logger_write.h"
+
#include <errno.h>
#include <inttypes.h>
#include <libgen.h>
@@ -27,6 +29,7 @@
#include <shared_mutex>
+#include <android-base/errno_restorer.h>
#include <android-base/macros.h>
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
@@ -52,6 +55,8 @@
#include <windows.h>
#endif
+using android::base::ErrnoRestorer;
+
#define LOG_BUF_SIZE 1024
#if defined(__ANDROID__)
@@ -136,11 +141,11 @@
// It's possible for logging to happen during static initialization before our globals are
// initialized, so we place this std::string in a function such that it is initialized on the first
// call.
-static std::string& GetDefaultTag() {
+std::string& GetDefaultTag() {
static std::string default_tag = getprogname();
return default_tag;
}
-static RwLock default_tag_lock;
+RwLock default_tag_lock;
void __android_log_set_default_tag(const char* tag) {
auto lock = std::unique_lock{default_tag_lock};
@@ -194,11 +199,9 @@
#ifdef __ANDROID__
static int write_to_log(log_id_t log_id, struct iovec* vec, size_t nr) {
- int ret, save_errno;
+ int ret;
struct timespec ts;
- save_errno = errno;
-
if (log_id == LOG_ID_KERNEL) {
return -EINVAL;
}
@@ -207,23 +210,19 @@
if (log_id == LOG_ID_SECURITY) {
if (vec[0].iov_len < 4) {
- errno = save_errno;
return -EINVAL;
}
ret = check_log_uid_permissions();
if (ret < 0) {
- errno = save_errno;
return ret;
}
if (!__android_log_security()) {
/* If only we could reset downstream logd counter */
- errno = save_errno;
return -EPERM;
}
} else if (log_id == LOG_ID_EVENTS || log_id == LOG_ID_STATS) {
if (vec[0].iov_len < 4) {
- errno = save_errno;
return -EINVAL;
}
}
@@ -231,7 +230,6 @@
ret = LogdWrite(log_id, &ts, vec, nr);
PmsgWrite(log_id, &ts, vec, nr);
- errno = save_errno;
return ret;
}
#else
@@ -311,6 +309,8 @@
}
void __android_log_write_logger_data(__android_logger_data* logger_data, const char* msg) {
+ ErrnoRestorer errno_restorer;
+
auto tag_lock = std::shared_lock{default_tag_lock, std::defer_lock};
if (logger_data->tag == nullptr) {
tag_lock.lock();
@@ -328,6 +328,8 @@
}
int __android_log_buf_write(int bufID, int prio, const char* tag, const char* msg) {
+ ErrnoRestorer errno_restorer;
+
if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
return 0;
}
@@ -338,6 +340,8 @@
}
int __android_log_vprint(int prio, const char* tag, const char* fmt, va_list ap) {
+ ErrnoRestorer errno_restorer;
+
if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
return 0;
}
@@ -353,6 +357,8 @@
}
int __android_log_print(int prio, const char* tag, const char* fmt, ...) {
+ ErrnoRestorer errno_restorer;
+
if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
return 0;
}
@@ -371,6 +377,8 @@
}
int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt, ...) {
+ ErrnoRestorer errno_restorer;
+
if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
return 0;
}
@@ -417,6 +425,8 @@
}
int __android_log_bwrite(int32_t tag, const void* payload, size_t len) {
+ ErrnoRestorer errno_restorer;
+
struct iovec vec[2];
vec[0].iov_base = &tag;
@@ -428,6 +438,8 @@
}
int __android_log_stats_bwrite(int32_t tag, const void* payload, size_t len) {
+ ErrnoRestorer errno_restorer;
+
struct iovec vec[2];
vec[0].iov_base = &tag;
@@ -439,6 +451,8 @@
}
int __android_log_security_bwrite(int32_t tag, const void* payload, size_t len) {
+ ErrnoRestorer errno_restorer;
+
struct iovec vec[2];
vec[0].iov_base = &tag;
@@ -455,6 +469,8 @@
* handy if we just want to dump an integer into the log.
*/
int __android_log_btwrite(int32_t tag, char type, const void* payload, size_t len) {
+ ErrnoRestorer errno_restorer;
+
struct iovec vec[3];
vec[0].iov_base = &tag;
@@ -472,6 +488,8 @@
* event log.
*/
int __android_log_bswrite(int32_t tag, const char* payload) {
+ ErrnoRestorer errno_restorer;
+
struct iovec vec[4];
char type = EVENT_TYPE_STRING;
uint32_t len = strlen(payload);
@@ -493,6 +511,8 @@
* security log.
*/
int __android_log_security_bswrite(int32_t tag, const char* payload) {
+ ErrnoRestorer errno_restorer;
+
struct iovec vec[4];
char type = EVENT_TYPE_STRING;
uint32_t len = strlen(payload);
diff --git a/liblog/logger_write.h b/liblog/logger_write.h
new file mode 100644
index 0000000..065fd55
--- /dev/null
+++ b/liblog/logger_write.h
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <string>
+
+#include "rwlock.h"
+
+std::string& GetDefaultTag(); // Must read lock default_tag_lock
+extern RwLock default_tag_lock;
\ No newline at end of file
diff --git a/liblog/properties.cpp b/liblog/properties.cpp
index a53c92b..b13662f 100644
--- a/liblog/properties.cpp
+++ b/liblog/properties.cpp
@@ -25,9 +25,12 @@
#include <unistd.h>
#include <algorithm>
+#include <shared_mutex>
#include <private/android_logger.h>
+#include "logger_write.h"
+
static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
static int lock() {
@@ -93,10 +96,17 @@
/* sizeof() is used on this array below */
static const char log_namespace[] = "persist.log.tag.";
static const size_t base_offset = 8; /* skip "persist." */
- /* calculate the size of our key temporary buffer */
- const size_t taglen = tag ? len : 0;
+
+ auto tag_lock = std::shared_lock{default_tag_lock, std::defer_lock};
+ if (tag == nullptr || len == 0) {
+ tag_lock.lock();
+ auto& tag_string = GetDefaultTag();
+ tag = tag_string.c_str();
+ len = tag_string.size();
+ }
+
/* sizeof(log_namespace) = strlen(log_namespace) + 1 */
- char key[sizeof(log_namespace) + taglen];
+ char key[sizeof(log_namespace) + len];
char* kp;
size_t i;
char c = 0;
@@ -146,7 +156,7 @@
}
}
- if (taglen) {
+ if (len) {
int local_change_detected = change_detected;
if (!not_locked) {
if (!last_tag || !last_tag[0] || (last_tag[0] != tag[0]) ||
diff --git a/liblog/tests/liblog_default_tag.cpp b/liblog/tests/liblog_default_tag.cpp
index a5baa9f..5643f63 100644
--- a/liblog/tests/liblog_default_tag.cpp
+++ b/liblog/tests/liblog_default_tag.cpp
@@ -96,4 +96,48 @@
LOG(WARNING) << "message";
EXPECT_TRUE(message_seen);
+}
+
+TEST(liblog_default_tag, default_tag_plus_log_severity) {
+ using namespace android::base;
+ bool message_seen = false;
+ std::string expected_tag = "liblog_test_tag";
+ SetLogger([&](LogId, LogSeverity, const char* tag, const char*, unsigned int, const char*) {
+ message_seen = true;
+ EXPECT_EQ(expected_tag, tag);
+ });
+ __android_log_set_default_tag(expected_tag.c_str());
+
+ auto log_tag_property = "log.tag." + expected_tag;
+ SetProperty(log_tag_property, "V");
+
+ __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_VERBOSE, nullptr, "message");
+ EXPECT_TRUE(message_seen);
+ message_seen = false;
+
+ LOG(VERBOSE) << "message";
+ EXPECT_TRUE(message_seen);
+}
+
+TEST(liblog_default_tag, generated_default_tag_plus_log_severity) {
+ using namespace android::base;
+ bool message_seen = false;
+ std::string expected_tag = getprogname();
+ SetLogger([&](LogId, LogSeverity, const char* tag, const char*, unsigned int, const char*) {
+ message_seen = true;
+ EXPECT_EQ(expected_tag, tag);
+ });
+
+ // Even without any calls to SetDefaultTag(), the first message that attempts to log, will
+ // generate a default tag from getprogname() and check log.tag.<default tag> for loggability. This
+ // case checks that we can log a Verbose message when log.tag.<getprogname()> is set to 'V'.
+ auto log_tag_property = "log.tag." + expected_tag;
+ SetProperty(log_tag_property, "V");
+
+ __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_VERBOSE, nullptr, "message");
+ EXPECT_TRUE(message_seen);
+ message_seen = false;
+
+ LOG(VERBOSE) << "message";
+ EXPECT_TRUE(message_seen);
}
\ No newline at end of file
diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c
index 8212eba..5999e39 100644
--- a/libnetutils/ifc_utils.c
+++ b/libnetutils/ifc_utils.c
@@ -257,8 +257,8 @@
*
* Returns zero on success and negative errno on failure.
*/
-int ifc_act_on_address(int action, const char *name, const char *address,
- int prefixlen) {
+int ifc_act_on_address(int action, const char* name, const char* address, int prefixlen,
+ bool nodad) {
int ifindex, s, len, ret;
struct sockaddr_storage ss;
int saved_errno;
@@ -311,6 +311,7 @@
// Interface address message header.
req.r.ifa_family = ss.ss_family;
+ req.r.ifa_flags = nodad ? IFA_F_NODAD : 0;
req.r.ifa_prefixlen = prefixlen;
req.r.ifa_index = ifindex;
@@ -363,12 +364,12 @@
// Returns zero on success and negative errno on failure.
int ifc_add_address(const char *name, const char *address, int prefixlen) {
- return ifc_act_on_address(RTM_NEWADDR, name, address, prefixlen);
+ return ifc_act_on_address(RTM_NEWADDR, name, address, prefixlen, /*nodad*/ false);
}
// Returns zero on success and negative errno on failure.
int ifc_del_address(const char *name, const char * address, int prefixlen) {
- return ifc_act_on_address(RTM_DELADDR, name, address, prefixlen);
+ return ifc_act_on_address(RTM_DELADDR, name, address, prefixlen, /*nodad*/ false);
}
/*
diff --git a/libnetutils/include/netutils/ifc.h b/libnetutils/include/netutils/ifc.h
index 3b27234..ee896ac 100644
--- a/libnetutils/include/netutils/ifc.h
+++ b/libnetutils/include/netutils/ifc.h
@@ -17,8 +17,9 @@
#ifndef _NETUTILS_IFC_H_
#define _NETUTILS_IFC_H_
-#include <sys/cdefs.h>
#include <arpa/inet.h>
+#include <stdbool.h>
+#include <sys/cdefs.h>
__BEGIN_DECLS
@@ -42,6 +43,8 @@
extern int ifc_get_addr(const char *name, in_addr_t *addr);
extern int ifc_set_addr(const char *name, in_addr_t addr);
+extern int ifc_act_on_address(int action, const char* name, const char* address, int prefixlen,
+ bool nodad);
extern int ifc_add_address(const char *name, const char *address,
int prefixlen);
extern int ifc_del_address(const char *name, const char *address,
diff --git a/libprocessgroup/sched_policy.cpp b/libprocessgroup/sched_policy.cpp
index 16339d3..698e74d 100644
--- a/libprocessgroup/sched_policy.cpp
+++ b/libprocessgroup/sched_policy.cpp
@@ -138,8 +138,17 @@
return enabled;
}
+static bool schedtune_enabled() {
+ return (CgroupMap::GetInstance().FindController("schedtune").IsUsable());
+}
+
+static bool cpuctl_enabled() {
+ return (CgroupMap::GetInstance().FindController("cpu").IsUsable());
+}
+
bool schedboost_enabled() {
- static bool enabled = (CgroupMap::GetInstance().FindController("schedtune").IsUsable());
+ static bool enabled = schedtune_enabled() || cpuctl_enabled();
+
return enabled;
}
@@ -162,7 +171,9 @@
std::string group;
if (schedboost_enabled()) {
- if (getCGroupSubsys(tid, "schedtune", group) < 0) return -1;
+ if ((getCGroupSubsys(tid, "schedtune", group) < 0) &&
+ (getCGroupSubsys(tid, "cpu", group) < 0))
+ return -1;
}
if (group.empty() && cpusets_enabled()) {
if (getCGroupSubsys(tid, "cpuset", group) < 0) return -1;
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index 9447f86..72f01af 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -288,6 +288,11 @@
return true;
}
+void TaskProfile::MoveTo(TaskProfile* profile) {
+ profile->elements_ = std::move(elements_);
+ profile->res_cached_ = res_cached_;
+}
+
bool TaskProfile::ExecuteForProcess(uid_t uid, pid_t pid) const {
for (const auto& element : elements_) {
if (!element->ExecuteForProcess(uid, pid)) {
@@ -458,7 +463,15 @@
LOG(WARNING) << "Unknown profile action: " << action_name;
}
}
- profiles_[profile_name] = profile;
+ auto iter = profiles_.find(profile_name);
+ if (iter == profiles_.end()) {
+ profiles_[profile_name] = profile;
+ } else {
+ // Move the content rather that replace the profile because old profile might be
+ // referenced from an aggregate profile if vendor overrides task profiles
+ profile->MoveTo(iter->second.get());
+ profile.reset();
+ }
}
const Json::Value& aggregateprofiles_val = root["AggregateProfiles"];
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index 9f2308c..a64ca50 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -143,6 +143,7 @@
TaskProfile() : res_cached_(false) {}
void Add(std::unique_ptr<ProfileAction> e) { elements_.push_back(std::move(e)); }
+ void MoveTo(TaskProfile* profile);
bool ExecuteForProcess(uid_t uid, pid_t pid) const;
bool ExecuteForTask(int tid) const;
diff --git a/libunwindstack/RegsArm64.cpp b/libunwindstack/RegsArm64.cpp
index 1df1dff..00b3367 100644
--- a/libunwindstack/RegsArm64.cpp
+++ b/libunwindstack/RegsArm64.cpp
@@ -100,8 +100,8 @@
fn("x27", regs_[ARM64_REG_R27]);
fn("x28", regs_[ARM64_REG_R28]);
fn("x29", regs_[ARM64_REG_R29]);
- fn("sp", regs_[ARM64_REG_SP]);
fn("lr", regs_[ARM64_REG_LR]);
+ fn("sp", regs_[ARM64_REG_SP]);
fn("pc", regs_[ARM64_REG_PC]);
fn("pst", regs_[ARM64_REG_PSTATE]);
}
@@ -110,10 +110,10 @@
arm64_user_regs* user = reinterpret_cast<arm64_user_regs*>(remote_data);
RegsArm64* regs = new RegsArm64();
- memcpy(regs->RawData(), &user->regs[0], (ARM64_REG_R31 + 1) * sizeof(uint64_t));
+ memcpy(regs->RawData(), &user->regs[0], (ARM64_REG_R30 + 1) * sizeof(uint64_t));
uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData());
- reg_data[ARM64_REG_PC] = user->pc;
reg_data[ARM64_REG_SP] = user->sp;
+ reg_data[ARM64_REG_PC] = user->pc;
reg_data[ARM64_REG_PSTATE] = user->pstate;
return regs;
}
diff --git a/libunwindstack/TEST_MAPPING b/libunwindstack/TEST_MAPPING
index 55771c0..909f897 100644
--- a/libunwindstack/TEST_MAPPING
+++ b/libunwindstack/TEST_MAPPING
@@ -2,6 +2,9 @@
"presubmit": [
{
"name": "libunwindstack_unit_test"
+ },
+ {
+ "name": "CtsSimpleperfTestCases"
}
]
}
diff --git a/libunwindstack/tests/RegsIterateTest.cpp b/libunwindstack/tests/RegsIterateTest.cpp
index bc95851..47e605a 100644
--- a/libunwindstack/tests/RegsIterateTest.cpp
+++ b/libunwindstack/tests/RegsIterateTest.cpp
@@ -111,8 +111,8 @@
result.push_back({"x27", ARM64_REG_R27});
result.push_back({"x28", ARM64_REG_R28});
result.push_back({"x29", ARM64_REG_R29});
- result.push_back({"sp", ARM64_REG_SP});
result.push_back({"lr", ARM64_REG_LR});
+ result.push_back({"sp", ARM64_REG_SP});
result.push_back({"pc", ARM64_REG_PC});
result.push_back({"pst", ARM64_REG_PSTATE});
return result;
diff --git a/rootdir/init.rc b/rootdir/init.rc
index c4f3e15..7f4f025 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -165,7 +165,7 @@
mkdir /mnt/secure/asec 0700 root root
mkdir /mnt/asec 0755 root system
mkdir /mnt/obb 0755 root system
- mkdir /mnt/media_rw 0750 root media_rw
+ mkdir /mnt/media_rw 0750 root external_storage
mkdir /mnt/user 0755 root root
mkdir /mnt/user/0 0755 root root
mkdir /mnt/user/0/self 0755 root root