Merge "init: add [[nodiscard]] to Result"
diff --git a/adb/Android.bp b/adb/Android.bp
index bccc71a..a9ccc84 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -24,6 +24,7 @@
"-Wno-missing-field-initializers",
"-Wvla",
],
+ cpp_std: "gnu++17",
rtti: true,
use_version_lib: true,
@@ -174,6 +175,12 @@
"libdiagnose_usb",
"libmdnssd",
"libusb",
+ "libandroidfw",
+ "libziparchive",
+ "libz",
+ "libutils",
+ "liblog",
+ "libcutils",
],
}
@@ -256,6 +263,12 @@
"liblog",
"libmdnssd",
"libusb",
+ "libandroidfw",
+ "libziparchive",
+ "libz",
+ "libutils",
+ "liblog",
+ "libcutils",
],
stl: "libc++_static",
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index f4a92e3..051ab73 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -21,6 +21,7 @@
#include <algorithm>
#include <list>
+#include <memory>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
@@ -29,7 +30,6 @@
#include "socket_spec.h"
#include "sysdeps.h"
-#include "sysdeps/memory.h"
#include "transport.h"
// A listener is an entity which binds to a local port and, upon receiving a connection on that
diff --git a/adb/client/adb_install.cpp b/adb/client/adb_install.cpp
index 4cbc45a..d69dbef 100644
--- a/adb/client/adb_install.cpp
+++ b/adb/client/adb_install.cpp
@@ -14,31 +14,27 @@
* limitations under the License.
*/
-#define TRACE_TAG ADB
+#include "adb_install.h"
#include <stdio.h>
#include <stdlib.h>
-
-#include "adb.h"
-#include "adb_client.h"
-#include "adb_install.h"
-#include "adb_utils.h"
-#include "client/file_sync_client.h"
-#include "commandline.h"
-#include "fastdeploy.h"
-#include "sysdeps.h"
-
+#include <unistd.h>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
-#include <unistd.h>
-
-#include <android-base/file.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <android-base/test_utils.h>
+#include "adb.h"
+#include "adb_client.h"
+#include "adb_utils.h"
+#include "android-base/file.h"
+#include "android-base/stringprintf.h"
+#include "android-base/strings.h"
+#include "android-base/test_utils.h"
+#include "client/file_sync_client.h"
+#include "commandline.h"
+#include "fastdeploy.h"
+#include "sysdeps.h"
static constexpr int kFastDeployMinApi = 24;
@@ -146,41 +142,16 @@
TemporaryFile patchTmpFile;
FILE* metadataFile = fopen(metadataTmpFile.path, "wb");
- int metadata_len = extract_metadata(file, metadataFile);
+ extract_metadata(file, metadataFile);
fclose(metadataFile);
- int result = -1;
- if (metadata_len <= 0) {
- printf("failed to extract metadata %d\n", metadata_len);
- return 1;
- } else {
- int create_patch_result = create_patch(file, metadataTmpFile.path, patchTmpFile.path);
- if (create_patch_result != 0) {
- printf("Patch creation failure, error code: %d\n", create_patch_result);
- result = create_patch_result;
- goto cleanup_streamed_apk;
- } else {
- std::vector<const char*> pm_args;
- // pass all but 1st (command) and last (apk path) parameters through to pm for
- // session creation
- for (int i = 1; i < argc - 1; i++) {
- pm_args.push_back(argv[i]);
- }
- int apply_patch_result =
- install_patch(file, patchTmpFile.path, pm_args.size(), pm_args.data());
- if (apply_patch_result != 0) {
- printf("Patch application failure, error code: %d\n", apply_patch_result);
- result = apply_patch_result;
- goto cleanup_streamed_apk;
- }
- }
- }
-
- cleanup_streamed_apk:
- if (use_fastdeploy == true) {
- delete_device_patch_file(file);
- }
- return result;
+ create_patch(file, metadataTmpFile.path, patchTmpFile.path);
+ // pass all but 1st (command) and last (apk path) parameters through to pm for
+ // session creation
+ std::vector<const char*> pm_args{argv + 1, argv + argc - 1};
+ install_patch(file, patchTmpFile.path, pm_args.size(), pm_args.data());
+ delete_device_patch_file(file);
+ return 0;
} else {
struct stat sb;
if (stat(file, &sb) == -1) {
@@ -265,29 +236,11 @@
TemporaryFile patchTmpFile;
FILE* metadataFile = fopen(metadataTmpFile.path, "wb");
- int metadata_len = extract_metadata(apk_file[0], metadataFile);
+ extract_metadata(apk_file[0], metadataFile);
fclose(metadataFile);
- if (metadata_len <= 0) {
- printf("failed to extract metadata %d\n", metadata_len);
- return 1;
- } else {
- int create_patch_result =
- create_patch(apk_file[0], metadataTmpFile.path, patchTmpFile.path);
- if (create_patch_result != 0) {
- printf("Patch creation failure, error code: %d\n", create_patch_result);
- result = create_patch_result;
- goto cleanup_apk;
- } else {
- int apply_patch_result =
- apply_patch_on_device(apk_file[0], patchTmpFile.path, apk_dest.c_str());
- if (apply_patch_result != 0) {
- printf("Patch application failure, error code: %d\n", apply_patch_result);
- result = apply_patch_result;
- goto cleanup_apk;
- }
- }
- }
+ create_patch(apk_file[0], metadataTmpFile.path, patchTmpFile.path);
+ apply_patch_on_device(apk_file[0], patchTmpFile.path, apk_dest.c_str());
} else {
if (!do_sync_push(apk_file, apk_dest.c_str(), false)) goto cleanup_apk;
}
@@ -347,7 +300,6 @@
use_localagent = true;
#endif
}
- // TODO: --installlog <filename>
}
if (installMode == INSTALL_DEFAULT) {
diff --git a/adb/client/adb_install.h b/adb/client/adb_install.h
index e9410a9..5b6c4cb 100644
--- a/adb/client/adb_install.h
+++ b/adb/client/adb_install.h
@@ -14,10 +14,9 @@
* limitations under the License.
*/
-#ifndef ADB_INSTALL_H
-#define ADB_INSTALL_H
+#pragma once
-#include "fastdeploy.h"
+#include <string>
int install_app(int argc, const char** argv);
int install_multiple_app(int argc, const char** argv);
@@ -26,4 +25,3 @@
int delete_device_file(const std::string& filename);
int delete_host_file(const std::string& filename);
-#endif
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index e38e305..22f8e8d 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -63,7 +63,6 @@
#include "services.h"
#include "shell_protocol.h"
#include "sysdeps/chrono.h"
-#include "sysdeps/memory.h"
extern int gListenAll;
diff --git a/adb/client/fastdeploy.cpp b/adb/client/fastdeploy.cpp
index d3f35c8..183a1fa 100644
--- a/adb/client/fastdeploy.cpp
+++ b/adb/client/fastdeploy.cpp
@@ -14,15 +14,18 @@
* limitations under the License.
*/
-#include <libgen.h>
+#include "fastdeploy.h"
+
#include <algorithm>
#include <array>
+#include <memory>
#include "android-base/file.h"
#include "android-base/strings.h"
+#include "androidfw/ResourceTypes.h"
+#include "androidfw/ZipFileRO.h"
#include "client/file_sync_client.h"
#include "commandline.h"
-#include "fastdeploy.h"
#include "fastdeploycallbacks.h"
#include "utils/String16.h"
@@ -138,60 +141,82 @@
}
}
-static std::string get_aapt2_path() {
- if (g_use_localagent) {
- // This should never happen on a Windows machine
- const char* host_out = getenv("ANDROID_HOST_OUT");
- if (host_out == nullptr) {
- fatal("Could not locate aapt2 because $ANDROID_HOST_OUT is not defined");
- }
- return android::base::StringPrintf("%s/bin/aapt2", host_out);
+static std::string get_string_from_utf16(const char16_t* input, int input_len) {
+ ssize_t utf8_length = utf16_to_utf8_length(input, input_len);
+ if (utf8_length <= 0) {
+ return {};
}
-
- std::string adb_dir = android::base::GetExecutableDirectory();
- if (adb_dir.empty()) {
- fatal("Could not locate aapt2");
- }
- return adb_dir + "/aapt2";
+ std::string utf8;
+ utf8.resize(utf8_length);
+ utf16_to_utf8(input, input_len, &*utf8.begin(), utf8_length + 1);
+ return utf8;
}
-static int system_capture(const char* cmd, std::string& output) {
- FILE* pipe = popen(cmd, "re");
- int fd = -1;
-
- if (pipe != nullptr) {
- fd = fileno(pipe);
- }
-
- if (fd == -1) {
- fatal_errno("Could not create pipe for process '%s'", cmd);
- }
-
- if (!android::base::ReadFdToString(fd, &output)) {
- fatal_errno("Error reading from process '%s'", cmd);
- }
-
- return pclose(pipe);
-}
-
-// output is required to point to a valid output string (non-null)
static std::string get_packagename_from_apk(const char* apkPath) {
- const char* kAapt2DumpNameCommandPattern = R"(%s dump packagename "%s")";
- std::string aapt2_path_string = get_aapt2_path();
- std::string getPackagenameCommand = android::base::StringPrintf(
- kAapt2DumpNameCommandPattern, aapt2_path_string.c_str(), apkPath);
-
- std::string package_name;
- int exit_code = system_capture(getPackagenameCommand.c_str(), package_name);
- if (exit_code != 0) {
- fatal("Error executing '%s' exitcode: %d", getPackagenameCommand.c_str(), exit_code);
+ std::unique_ptr<android::ZipFileRO> zipFile(android::ZipFileRO::open(apkPath));
+ if (zipFile == nullptr) {
+ fatal("Could not open %s", apkPath);
}
-
- // strip any line end characters from the output
- return android::base::Trim(package_name);
+ android::ZipEntryRO entry = zipFile->findEntryByName("AndroidManifest.xml");
+ if (entry == nullptr) {
+ fatal("Could not find AndroidManifest.xml inside %s", apkPath);
+ }
+ uint32_t manifest_len = 0;
+ if (!zipFile->getEntryInfo(entry, NULL, &manifest_len, NULL, NULL, NULL, NULL)) {
+ fatal("Could not read AndroidManifest.xml inside %s", apkPath);
+ }
+ std::vector<char> manifest_data(manifest_len);
+ if (!zipFile->uncompressEntry(entry, manifest_data.data(), manifest_len)) {
+ fatal("Could not uncompress AndroidManifest.xml inside %s", apkPath);
+ }
+ android::ResXMLTree tree;
+ android::status_t setto_status = tree.setTo(manifest_data.data(), manifest_len, true);
+ if (setto_status != android::OK) {
+ fatal("Could not parse AndroidManifest.xml inside %s", apkPath);
+ }
+ android::ResXMLParser::event_code_t code;
+ while ((code = tree.next()) != android::ResXMLParser::BAD_DOCUMENT &&
+ code != android::ResXMLParser::END_DOCUMENT) {
+ switch (code) {
+ case android::ResXMLParser::START_TAG: {
+ size_t element_name_length;
+ const char16_t* element_name = tree.getElementName(&element_name_length);
+ if (element_name == nullptr) {
+ continue;
+ }
+ std::u16string element_name_string(element_name, element_name_length);
+ if (element_name_string == u"manifest") {
+ for (size_t i = 0; i < tree.getAttributeCount(); i++) {
+ size_t attribute_name_length;
+ const char16_t* attribute_name_text =
+ tree.getAttributeName(i, &attribute_name_length);
+ if (attribute_name_text == nullptr) {
+ continue;
+ }
+ std::u16string attribute_name_string(attribute_name_text,
+ attribute_name_length);
+ if (attribute_name_string == u"package") {
+ size_t attribute_value_length;
+ const char16_t* attribute_value_text =
+ tree.getAttributeStringValue(i, &attribute_value_length);
+ if (attribute_value_text == nullptr) {
+ continue;
+ }
+ return get_string_from_utf16(attribute_value_text,
+ attribute_value_length);
+ }
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ fatal("Could not find package name tag in AndroidManifest.xml inside %s", apkPath);
}
-int extract_metadata(const char* apkPath, FILE* outputFp) {
+void extract_metadata(const char* apkPath, FILE* outputFp) {
std::string packageName = get_packagename_from_apk(apkPath);
const char* kAgentExtractCommandPattern = "/data/local/tmp/deployagent extract %s";
std::string extractCommand =
@@ -200,13 +225,10 @@
std::vector<char> extractErrorBuffer;
int statusCode;
DeployAgentFileCallback cb(outputFp, &extractErrorBuffer, &statusCode);
- int ret = send_shell_command(extractCommand, false, &cb);
-
- if (ret == 0) {
- return cb.getBytesWritten();
+ int returnCode = send_shell_command(extractCommand, false, &cb);
+ if (returnCode != 0) {
+ fatal("Executing %s returned %d\n", extractCommand.c_str(), returnCode);
}
-
- return ret;
}
static std::string get_patch_generator_command() {
@@ -229,11 +251,14 @@
adb_dir.c_str());
}
-int create_patch(const char* apkPath, const char* metadataPath, const char* patchPath) {
+void create_patch(const char* apkPath, const char* metadataPath, const char* patchPath) {
std::string generatePatchCommand = android::base::StringPrintf(
R"(%s "%s" "%s" > "%s")", get_patch_generator_command().c_str(), apkPath, metadataPath,
patchPath);
- return system(generatePatchCommand.c_str());
+ int returnCode = system(generatePatchCommand.c_str());
+ if (returnCode != 0) {
+ fatal("Executing %s returned %d\n", generatePatchCommand.c_str(), returnCode);
+ }
}
std::string get_patch_path(const char* apkPath) {
@@ -243,36 +268,38 @@
return patchDevicePath;
}
-int apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath) {
+void apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath) {
const std::string kAgentApplyCommandPattern = "/data/local/tmp/deployagent apply %s %s -o %s";
std::string packageName = get_packagename_from_apk(apkPath);
std::string patchDevicePath = get_patch_path(apkPath);
std::vector<const char*> srcs = {patchPath};
bool push_ok = do_sync_push(srcs, patchDevicePath.c_str(), false);
-
if (!push_ok) {
- return -1;
+ fatal("Error pushing %s to %s returned\n", patchPath, patchDevicePath.c_str());
}
std::string applyPatchCommand =
android::base::StringPrintf(kAgentApplyCommandPattern.c_str(), packageName.c_str(),
patchDevicePath.c_str(), outputPath);
- return send_shell_command(applyPatchCommand);
+ int returnCode = send_shell_command(applyPatchCommand);
+ if (returnCode != 0) {
+ fatal("Executing %s returned %d\n", applyPatchCommand.c_str(), returnCode);
+ }
}
-int install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv) {
+void install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv) {
const std::string kAgentApplyCommandPattern = "/data/local/tmp/deployagent apply %s %s -pm %s";
std::string packageName = get_packagename_from_apk(apkPath);
- std::vector<const char*> srcs;
+
std::string patchDevicePath =
android::base::StringPrintf("%s%s.patch", kDeviceAgentPath, packageName.c_str());
- srcs.push_back(patchPath);
- bool push_ok = do_sync_push(srcs, patchDevicePath.c_str(), false);
+ std::vector<const char*> srcs{patchPath};
+ bool push_ok = do_sync_push(srcs, patchDevicePath.c_str(), false);
if (!push_ok) {
- return -1;
+ fatal("Error pushing %s to %s returned\n", patchPath, patchDevicePath.c_str());
}
std::vector<unsigned char> applyOutputBuffer;
@@ -287,5 +314,8 @@
std::string applyPatchCommand =
android::base::StringPrintf(kAgentApplyCommandPattern.c_str(), packageName.c_str(),
patchDevicePath.c_str(), argsString.c_str());
- return send_shell_command(applyPatchCommand);
+ int returnCode = send_shell_command(applyPatchCommand);
+ if (returnCode != 0) {
+ fatal("Executing %s returned %d\n", applyPatchCommand.c_str(), returnCode);
+ }
}
diff --git a/adb/client/fastdeploy.h b/adb/client/fastdeploy.h
index e5e7663..a6b10d3 100644
--- a/adb/client/fastdeploy.h
+++ b/adb/client/fastdeploy.h
@@ -16,7 +16,7 @@
#pragma once
-#include "adb.h"
+#include <string>
enum FastDeploy_AgentUpdateStrategy {
FastDeploy_AgentUpdateAlways,
@@ -27,8 +27,8 @@
void fastdeploy_set_local_agent(bool use_localagent);
int get_device_api_level();
void update_agent(FastDeploy_AgentUpdateStrategy agentUpdateStrategy);
-int extract_metadata(const char* apkPath, FILE* outputFp);
-int create_patch(const char* apkPath, const char* metadataPath, const char* patchPath);
-int apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath);
-int install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv);
+void extract_metadata(const char* apkPath, FILE* outputFp);
+void create_patch(const char* apkPath, const char* metadataPath, const char* patchPath);
+void apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath);
+void install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv);
std::string get_patch_path(const char* apkPath);
diff --git a/adb/fdevent_test.cpp b/adb/fdevent_test.cpp
index 0cb2439..816134f 100644
--- a/adb/fdevent_test.cpp
+++ b/adb/fdevent_test.cpp
@@ -19,6 +19,7 @@
#include <gtest/gtest.h>
#include <limits>
+#include <memory>
#include <queue>
#include <string>
#include <thread>
@@ -26,7 +27,6 @@
#include "adb_io.h"
#include "fdevent_test.h"
-#include "sysdeps/memory.h"
class FdHandler {
public:
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index 1534792..dfd9a0a 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -26,10 +26,14 @@
#include <unistd.h>
#include <algorithm>
+#include <map>
#include <mutex>
#include <string>
+#include <thread>
#include <vector>
+#include <android-base/thread_annotations.h>
+
#if !ADB_HOST
#include <android-base/properties.h>
#include <log/log_properties.h>
@@ -37,9 +41,150 @@
#include "adb.h"
#include "adb_io.h"
+#include "adb_utils.h"
+#include "sysdeps/chrono.h"
#include "transport.h"
#include "types.h"
+// The standard (RFC 1122 - 4.2.2.13) says that if we call close on a
+// socket while we have pending data, a TCP RST should be sent to the
+// other end to notify it that we didn't read all of its data. However,
+// this can result in data that we've successfully written out to be dropped
+// on the other end. To avoid this, instead of immediately closing a
+// socket, call shutdown on it instead, and then read from the file
+// descriptor until we hit EOF or an error before closing.
+struct LingeringSocketCloser {
+ LingeringSocketCloser() = default;
+ ~LingeringSocketCloser() = delete;
+
+ // Defer thread creation until it's needed, because we need for there to
+ // only be one thread when dropping privileges in adbd.
+ void Start() {
+ CHECK(!thread_.joinable());
+
+ int fds[2];
+ if (adb_socketpair(fds) != 0) {
+ PLOG(FATAL) << "adb_socketpair failed";
+ }
+
+ set_file_block_mode(fds[0], false);
+ set_file_block_mode(fds[1], false);
+
+ notify_fd_read_.reset(fds[0]);
+ notify_fd_write_.reset(fds[1]);
+
+ thread_ = std::thread([this]() { Run(); });
+ }
+
+ void EnqueueSocket(unique_fd socket) {
+ // Shutdown the socket in the outgoing direction only, so that
+ // we don't have the same problem on the opposite end.
+ adb_shutdown(socket.get(), SHUT_WR);
+ set_file_block_mode(socket.get(), false);
+
+ std::lock_guard<std::mutex> lock(mutex_);
+ int fd = socket.get();
+ SocketInfo info = {
+ .fd = std::move(socket),
+ .deadline = std::chrono::steady_clock::now() + 1s,
+ };
+
+ D("LingeringSocketCloser received fd %d", fd);
+
+ fds_.emplace(fd, std::move(info));
+ if (adb_write(notify_fd_write_, "", 1) == -1 && errno != EAGAIN) {
+ PLOG(FATAL) << "failed to write to LingeringSocketCloser notify fd";
+ }
+ }
+
+ private:
+ std::vector<adb_pollfd> GeneratePollFds() {
+ std::lock_guard<std::mutex> lock(mutex_);
+ std::vector<adb_pollfd> result;
+ result.push_back(adb_pollfd{.fd = notify_fd_read_, .events = POLLIN});
+ for (auto& [fd, _] : fds_) {
+ result.push_back(adb_pollfd{.fd = fd, .events = POLLIN});
+ }
+ return result;
+ }
+
+ void Run() {
+ while (true) {
+ std::vector<adb_pollfd> pfds = GeneratePollFds();
+ int rc = adb_poll(pfds.data(), pfds.size(), 1000);
+ if (rc == -1) {
+ PLOG(FATAL) << "poll failed in LingeringSocketCloser";
+ }
+
+ std::lock_guard<std::mutex> lock(mutex_);
+ if (rc == 0) {
+ // Check deadlines.
+ auto now = std::chrono::steady_clock::now();
+ for (auto it = fds_.begin(); it != fds_.end();) {
+ if (now > it->second.deadline) {
+ D("LingeringSocketCloser closing fd %d due to deadline", it->first);
+ it = fds_.erase(it);
+ } else {
+ D("deadline still not expired for fd %d", it->first);
+ ++it;
+ }
+ }
+ continue;
+ }
+
+ for (auto& pfd : pfds) {
+ if ((pfd.revents & POLLIN) == 0) {
+ continue;
+ }
+
+ // Empty the fd.
+ ssize_t rc;
+ char buf[32768];
+ while ((rc = adb_read(pfd.fd, buf, sizeof(buf))) > 0) {
+ continue;
+ }
+
+ if (pfd.fd == notify_fd_read_) {
+ continue;
+ }
+
+ auto it = fds_.find(pfd.fd);
+ if (it == fds_.end()) {
+ LOG(FATAL) << "fd is missing";
+ }
+
+ if (rc == -1 && errno == EAGAIN) {
+ if (std::chrono::steady_clock::now() > it->second.deadline) {
+ D("LingeringSocketCloser closing fd %d due to deadline", pfd.fd);
+ } else {
+ continue;
+ }
+ } else if (rc == -1) {
+ D("LingeringSocketCloser closing fd %d due to error %d", pfd.fd, errno);
+ } else {
+ D("LingeringSocketCloser closing fd %d due to EOF", pfd.fd);
+ }
+
+ fds_.erase(it);
+ }
+ }
+ }
+
+ std::thread thread_;
+ unique_fd notify_fd_read_;
+ unique_fd notify_fd_write_;
+
+ struct SocketInfo {
+ unique_fd fd;
+ std::chrono::steady_clock::time_point deadline;
+ };
+
+ std::mutex mutex_;
+ std::map<int, SocketInfo> fds_ GUARDED_BY(mutex_);
+};
+
+static auto& socket_closer = *new LingeringSocketCloser();
+
static std::recursive_mutex& local_socket_list_lock = *new std::recursive_mutex();
static unsigned local_socket_next_id = 1;
@@ -243,10 +388,12 @@
D("LS(%d): destroying fde.fd=%d", s->id, s->fd);
- /* IMPORTANT: the remove closes the fd
- ** that belongs to this socket
- */
- fdevent_destroy(s->fde);
+ // Defer thread creation until it's needed, because we need for there to
+ // only be one thread when dropping privileges in adbd.
+ static std::once_flag once;
+ std::call_once(once, []() { socket_closer.Start(); });
+
+ socket_closer.EnqueueSocket(fdevent_release(s->fde));
remove_socket(s);
delete s;
diff --git a/adb/sysdeps/errno.cpp b/adb/sysdeps/errno.cpp
index 6869947..9a37ea2 100644
--- a/adb/sysdeps/errno.cpp
+++ b/adb/sysdeps/errno.cpp
@@ -24,10 +24,6 @@
#include "adb.h"
-#if defined(_WIN32)
-#define ETXTBSY EBUSY
-#endif
-
// Use the linux asm-generic values for errno (which are used on all android archs but mips).
#define ERRNO_VALUES() \
ERRNO_VALUE(EACCES, 13); \
diff --git a/adb/sysdeps/memory.h b/adb/sysdeps/memory.h
deleted file mode 100644
index 4108aff..0000000
--- a/adb/sysdeps/memory.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#pragma once
-
-/*
- * 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 <memory>
-#include <type_traits>
-
-#if defined(_WIN32)
-// We don't have C++14 on Windows yet.
-// Reimplement std::make_unique ourselves until we do.
-
-namespace internal {
-
-template <typename T>
-struct array_known_bounds;
-
-template <typename T>
-struct array_known_bounds<T[]> {
- constexpr static bool value = false;
-};
-
-template <typename T, size_t N>
-struct array_known_bounds<T[N]> {
- constexpr static bool value = true;
-};
-
-} // namespace internal
-
-namespace std {
-
-template <typename T, typename... Args>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type make_unique(
- Args&&... args) {
- return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
-}
-
-template <typename T>
-typename std::enable_if<std::is_array<T>::value && !internal::array_known_bounds<T>::value,
- std::unique_ptr<T>>::type
-make_unique(std::size_t size) {
- return std::unique_ptr<T>(new typename std::remove_extent<T>::type[size]());
-}
-
-template <typename T, typename... Args>
-typename std::enable_if<std::is_array<T>::value && internal::array_known_bounds<T>::value,
- std::unique_ptr<T>>::type
-make_unique(Args&&... args) = delete;
-
-} // namespace std
-
-#endif
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 8784757..0a08fbb 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -94,6 +94,10 @@
_fh_socket_writev,
};
+#if defined(assert)
+#undef assert
+#endif
+
#define assert(cond) \
do { \
if (!(cond)) fatal("assertion failed '%s' on %s:%d\n", #cond, __FILE__, __LINE__); \
diff --git a/adb/test_device.py b/adb/test_device.py
index c3166ff..4c45a73 100755
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -35,6 +35,8 @@
import time
import unittest
+from datetime import datetime
+
import adb
def requires_root(func):
@@ -1335,6 +1337,63 @@
self.device.forward_remove("tcp:{}".format(local_port))
+class SocketTest(DeviceTest):
+ def test_socket_flush(self):
+ """Test that we handle socket closure properly.
+
+ If we're done writing to a socket, closing before the other end has
+ closed will send a TCP_RST if we have incoming data queued up, which
+ may result in data that we've written being discarded.
+
+ Bug: http://b/74616284
+ """
+ s = socket.create_connection(("localhost", 5037))
+
+ def adb_length_prefixed(string):
+ encoded = string.encode("utf8")
+ result = b"%04x%s" % (len(encoded), encoded)
+ return result
+
+ if "ANDROID_SERIAL" in os.environ:
+ transport_string = "host:transport:" + os.environ["ANDROID_SERIAL"]
+ else:
+ transport_string = "host:transport-any"
+
+ s.sendall(adb_length_prefixed(transport_string))
+ response = s.recv(4)
+ self.assertEquals(b"OKAY", response)
+
+ shell_string = "shell:sleep 0.5; dd if=/dev/zero bs=1m count=1 status=none; echo foo"
+ s.sendall(adb_length_prefixed(shell_string))
+
+ response = s.recv(4)
+ self.assertEquals(b"OKAY", response)
+
+ # Spawn a thread that dumps garbage into the socket until failure.
+ def spam():
+ buf = b"\0" * 16384
+ try:
+ while True:
+ s.sendall(buf)
+ except Exception as ex:
+ print(ex)
+
+ thread = threading.Thread(target=spam)
+ thread.start()
+
+ time.sleep(1)
+
+ received = b""
+ while True:
+ read = s.recv(512)
+ if len(read) == 0:
+ break
+ received += read
+
+ self.assertEquals(1024 * 1024 + len("foo\n"), len(received))
+ thread.join()
+
+
if sys.platform == "win32":
# From https://stackoverflow.com/a/38749458
import os
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 95df490..cabd279 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -17,7 +17,6 @@
#define TRACE_TAG TRANSPORT
#include "sysdeps.h"
-#include "sysdeps/memory.h"
#include "transport.h"
@@ -32,6 +31,7 @@
#include <algorithm>
#include <deque>
#include <list>
+#include <memory>
#include <mutex>
#include <set>
#include <thread>
diff --git a/adb/transport_fd.cpp b/adb/transport_fd.cpp
index 85f3c52..ec61279 100644
--- a/adb/transport_fd.cpp
+++ b/adb/transport_fd.cpp
@@ -17,6 +17,7 @@
#include <stdint.h>
#include <deque>
+#include <memory>
#include <mutex>
#include <string>
#include <thread>
@@ -28,7 +29,6 @@
#include "adb_unique_fd.h"
#include "adb_utils.h"
#include "sysdeps.h"
-#include "sysdeps/memory.h"
#include "transport.h"
#include "types.h"
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 8353d89..dc87ac7 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -26,6 +26,7 @@
#include <sys/types.h>
#include <condition_variable>
+#include <memory>
#include <mutex>
#include <thread>
#include <unordered_map>
@@ -45,7 +46,6 @@
#include "adb_unique_fd.h"
#include "adb_utils.h"
#include "sysdeps/chrono.h"
-#include "sysdeps/memory.h"
#if ADB_HOST
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index 602970c..c471bf9 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -16,8 +16,9 @@
#define TRACE_TAG TRANSPORT
+#include <memory>
+
#include "sysdeps.h"
-#include "sysdeps/memory.h"
#include "transport.h"
#include <stdio.h>
diff --git a/adb/types.h b/adb/types.h
index 1f7008e..0c71c3a 100644
--- a/adb/types.h
+++ b/adb/types.h
@@ -25,7 +25,6 @@
#include <android-base/logging.h>
-#include "sysdeps/memory.h"
#include "sysdeps/uio.h"
// Essentially std::vector<char>, except without zero initialization or reallocation.
diff --git a/adb/types_test.cpp b/adb/types_test.cpp
index 31ab90a..1fbd2ca 100644
--- a/adb/types_test.cpp
+++ b/adb/types_test.cpp
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
-#include "sysdeps/memory.h"
+#include <memory>
#include "types.h"
static std::unique_ptr<IOVector::block_type> create_block(const std::string& string) {
diff --git a/base/include/android-base/utf8.h b/base/include/android-base/utf8.h
index 4b91623..1a414ec 100644
--- a/base/include/android-base/utf8.h
+++ b/base/include/android-base/utf8.h
@@ -17,6 +17,7 @@
#pragma once
#ifdef _WIN32
+#include <sys/types.h>
#include <string>
#else
// Bring in prototypes for standard APIs so that we can import them into the utf8 namespace.
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index d5ea6db..6e45133 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -237,7 +237,13 @@
CommandResult ret;
auto cb = [&ret](CommandResult result) { ret = result; };
auto result = boot_control_hal->setActiveBootSlot(slot, cb);
- if (result.isOk() && ret.success) return device->WriteStatus(FastbootResult::OKAY, "");
+ if (result.isOk() && ret.success) {
+ // Save as slot suffix to match the suffix format as returned from
+ // the boot control HAL.
+ auto current_slot = "_" + args[1];
+ device->set_active_slot(current_slot);
+ return device->WriteStatus(FastbootResult::OKAY, "");
+ }
return device->WriteStatus(FastbootResult::FAIL, "Unable to set slot");
}
diff --git a/fastboot/device/fastboot_device.cpp b/fastboot/device/fastboot_device.cpp
index b843c05..6cb4892 100644
--- a/fastboot/device/fastboot_device.cpp
+++ b/fastboot/device/fastboot_device.cpp
@@ -57,7 +57,8 @@
transport_(std::make_unique<ClientUsbTransport>()),
boot_control_hal_(IBootControl::getService()),
health_hal_(get_health_service()),
- fastboot_hal_(IFastboot::getService()) {}
+ fastboot_hal_(IFastboot::getService()),
+ active_slot_("") {}
FastbootDevice::~FastbootDevice() {
CloseDevice();
@@ -68,6 +69,11 @@
}
std::string FastbootDevice::GetCurrentSlot() {
+ // Check if a set_active ccommand was issued earlier since the boot control HAL
+ // returns the slot that is currently booted into.
+ if (!active_slot_.empty()) {
+ return active_slot_;
+ }
// Non-A/B devices must not have boot control HALs.
if (!boot_control_hal_) {
return "";
diff --git a/fastboot/device/fastboot_device.h b/fastboot/device/fastboot_device.h
index 2eb7177..091aadf 100644
--- a/fastboot/device/fastboot_device.h
+++ b/fastboot/device/fastboot_device.h
@@ -56,6 +56,8 @@
}
android::sp<android::hardware::health::V2_0::IHealth> health_hal() { return health_hal_; }
+ void set_active_slot(const std::string& active_slot) { active_slot_ = active_slot; }
+
private:
const std::unordered_map<std::string, CommandHandler> kCommandMap;
@@ -64,4 +66,5 @@
android::sp<android::hardware::health::V2_0::IHealth> health_hal_;
android::sp<android::hardware::fastboot::V1_0::IFastboot> fastboot_hal_;
std::vector<char> download_data_;
+ std::string active_slot_;
};
diff --git a/fastboot/device/flashing.cpp b/fastboot/device/flashing.cpp
index 4fc3d1d..2347496 100644
--- a/fastboot/device/flashing.cpp
+++ b/fastboot/device/flashing.cpp
@@ -72,7 +72,7 @@
}
int FlashSparseData(int fd, std::vector<char>& downloaded_data) {
- struct sparse_file* file = sparse_file_import_buf(downloaded_data.data(), true, true);
+ struct sparse_file* file = sparse_file_import_buf(downloaded_data.data(), true, false);
if (!file) {
return -ENOENT;
}
diff --git a/fastboot/device/variables.cpp b/fastboot/device/variables.cpp
index 630e22d..cbd2856 100644
--- a/fastboot/device/variables.cpp
+++ b/fastboot/device/variables.cpp
@@ -288,7 +288,7 @@
bool is_zero_length;
if (LogicalPartitionExists(args[0], device->GetCurrentSlot(), &is_zero_length) &&
is_zero_length) {
- *message = "0";
+ *message = "0x0";
return true;
}
// Otherwise, open the partition as normal.
@@ -308,7 +308,14 @@
*message = "Missing argument";
return false;
}
+
std::string partition_name = args[0];
+ if (!FindPhysicalPartition(partition_name) &&
+ !LogicalPartitionExists(partition_name, device->GetCurrentSlot())) {
+ *message = "Invalid partition";
+ return false;
+ }
+
auto fastboot_hal = device->fastboot_hal();
if (!fastboot_hal) {
*message = "Fastboot HAL not found";
diff --git a/fastboot/fuzzy_fastboot/main.cpp b/fastboot/fuzzy_fastboot/main.cpp
index e2076f5..c02ab1c 100644
--- a/fastboot/fuzzy_fastboot/main.cpp
+++ b/fastboot/fuzzy_fastboot/main.cpp
@@ -43,6 +43,7 @@
#include <thread>
#include <vector>
+#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <gtest/gtest.h>
#include <sparse/sparse.h>
@@ -331,8 +332,9 @@
<< cmd + " responded with a string with leading whitespace";
EXPECT_FALSE(resp.compare(0, 2, "0x"))
<< cmd + "responded with a string that does not start with 0x...";
- int64_t size = strtoll(resp.c_str(), nullptr, 16);
- EXPECT_GT(size, 0) << "'" + resp + "' is not a valid response from " + cmd;
+ uint64_t size;
+ ASSERT_TRUE(android::base::ParseUint(resp, &size))
+ << "'" + resp + "' is not a valid response from " + cmd;
}
}
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 7f9d9a4..a6ef35b 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -851,56 +851,115 @@
return true;
}
-bool fs_mgr_update_checkpoint_partition(struct fstab_rec* rec) {
- if (fs_mgr_is_checkpoint_fs(rec)) {
- if (!strcmp(rec->fs_type, "f2fs")) {
- std::string opts(rec->fs_options);
+class CheckpointManager {
+ public:
+ CheckpointManager(int needs_checkpoint = -1) : needs_checkpoint_(needs_checkpoint) {}
- opts += ",checkpoint=disable";
- free(rec->fs_options);
- rec->fs_options = strdup(opts.c_str());
- } else {
- LERROR << rec->fs_type << " does not implement checkpoints.";
+ bool Update(struct fstab_rec* rec) {
+ if (!fs_mgr_is_checkpoint(rec)) {
+ return true;
}
- } else if (fs_mgr_is_checkpoint_blk(rec)) {
- call_vdc({"checkpoint", "restoreCheckpoint", rec->blk_device});
- android::base::unique_fd fd(
- TEMP_FAILURE_RETRY(open(rec->blk_device, O_RDONLY | O_CLOEXEC)));
- if (!fd) {
- PERROR << "Cannot open device " << rec->blk_device;
+ if (fs_mgr_is_checkpoint_blk(rec)) {
+ call_vdc({"checkpoint", "restoreCheckpoint", rec->blk_device});
+ }
+
+ if (needs_checkpoint_ == UNKNOWN &&
+ !call_vdc_ret({"checkpoint", "needsCheckpoint"}, &needs_checkpoint_)) {
+ LERROR << "Failed to find if checkpointing is needed. Assuming no.";
+ needs_checkpoint_ = NO;
+ }
+
+ if (needs_checkpoint_ != YES) {
+ return true;
+ }
+
+ if (!UpdateCheckpointPartition(rec)) {
+ LERROR << "Could not set up checkpoint partition, skipping!";
return false;
}
- uint64_t size = get_block_device_size(fd) / 512;
- if (!size) {
- PERROR << "Cannot get device size";
- return false;
+ return true;
+ }
+
+ bool Revert(struct fstab_rec* rec) {
+ if (!fs_mgr_is_checkpoint(rec)) {
+ return true;
}
- android::dm::DmTable table;
- if (!table.AddTarget(
- std::make_unique<android::dm::DmTargetBow>(0, size, rec->blk_device))) {
- LERROR << "Failed to add Bow target";
- return false;
+ if (device_map_.find(rec->blk_device) == device_map_.end()) {
+ return true;
}
+ std::string bow_device = rec->blk_device;
+ free(rec->blk_device);
+ rec->blk_device = strdup(device_map_[bow_device].c_str());
+ device_map_.erase(bow_device);
+
DeviceMapper& dm = DeviceMapper::Instance();
- if (!dm.CreateDevice("bow", table)) {
- PERROR << "Failed to create bow device";
- return false;
+ if (!dm.DeleteDevice("bow")) {
+ PERROR << "Failed to remove bow device";
}
- std::string name;
- if (!dm.GetDmDevicePathByName("bow", &name)) {
- PERROR << "Failed to get bow device name";
- return false;
- }
-
- rec->blk_device = strdup(name.c_str());
+ return true;
}
- return true;
-}
+
+ private:
+ bool UpdateCheckpointPartition(struct fstab_rec* rec) {
+ if (fs_mgr_is_checkpoint_fs(rec)) {
+ if (!strcmp(rec->fs_type, "f2fs")) {
+ std::string opts(rec->fs_options);
+
+ opts += ",checkpoint=disable";
+ free(rec->fs_options);
+ rec->fs_options = strdup(opts.c_str());
+ } else {
+ LERROR << rec->fs_type << " does not implement checkpoints.";
+ }
+ } else if (fs_mgr_is_checkpoint_blk(rec)) {
+ android::base::unique_fd fd(
+ TEMP_FAILURE_RETRY(open(rec->blk_device, O_RDONLY | O_CLOEXEC)));
+ if (!fd) {
+ PERROR << "Cannot open device " << rec->blk_device;
+ return false;
+ }
+
+ uint64_t size = get_block_device_size(fd) / 512;
+ if (!size) {
+ PERROR << "Cannot get device size";
+ return false;
+ }
+
+ android::dm::DmTable table;
+ if (!table.AddTarget(
+ std::make_unique<android::dm::DmTargetBow>(0, size, rec->blk_device))) {
+ LERROR << "Failed to add bow target";
+ return false;
+ }
+
+ DeviceMapper& dm = DeviceMapper::Instance();
+ if (!dm.CreateDevice("bow", table)) {
+ PERROR << "Failed to create bow device";
+ return false;
+ }
+
+ std::string name;
+ if (!dm.GetDmDevicePathByName("bow", &name)) {
+ PERROR << "Failed to get bow device name";
+ return false;
+ }
+
+ device_map_[name] = rec->blk_device;
+ free(rec->blk_device);
+ rec->blk_device = strdup(name.c_str());
+ }
+ return true;
+ }
+
+ enum { UNKNOWN = -1, NO = 0, YES = 1 };
+ int needs_checkpoint_;
+ std::map<std::string, std::string> device_map_;
+};
/* When multiple fstab records share the same mount_point, it will
* try to mount each one in turn, and ignore any duplicates after a
@@ -914,7 +973,7 @@
int mret = -1;
int mount_errno = 0;
int attempted_idx = -1;
- int need_checkpoint = -1;
+ CheckpointManager checkpoint_manager;
FsManagerAvbUniquePtr avb_handle(nullptr);
if (!fstab) {
@@ -961,16 +1020,8 @@
}
}
- if (fs_mgr_is_checkpoint(&fstab->recs[i])) {
- if (need_checkpoint == -1 &&
- !call_vdc_ret({"checkpoint", "needsCheckpoint"}, &need_checkpoint)) {
- LERROR << "Failed to find if checkpointing is needed. Assuming no.";
- need_checkpoint = 0;
- }
- if (need_checkpoint == 1 && !fs_mgr_update_checkpoint_partition(&fstab->recs[i])) {
- LERROR << "Could not set up checkpoint partition, skipping!";
- continue;
- }
+ if (!checkpoint_manager.Update(&fstab->recs[i])) {
+ continue;
}
if (fstab->recs[i].fs_mgr_flags & MF_WAIT &&
@@ -1053,6 +1104,9 @@
<< " is wiped and " << fstab->recs[top_idx].mount_point
<< " " << fstab->recs[top_idx].fs_type
<< " is formattable. Format it.";
+
+ checkpoint_manager.Revert(&fstab->recs[top_idx]);
+
if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) &&
strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) {
int fd = open(fstab->recs[top_idx].key_loc, O_WRONLY);
@@ -1173,11 +1227,12 @@
* in turn, and stop on 1st success, or no more match.
*/
static int fs_mgr_do_mount_helper(fstab* fstab, const char* n_name, char* n_blk_device,
- char* tmp_mount_point, int need_checkpoint) {
+ char* tmp_mount_point, int needs_checkpoint) {
int i = 0;
int mount_errors = 0;
int first_mount_errno = 0;
char* mount_point;
+ CheckpointManager checkpoint_manager(needs_checkpoint);
FsManagerAvbUniquePtr avb_handle(nullptr);
if (!fstab) {
@@ -1206,16 +1261,9 @@
}
}
- if (fs_mgr_is_checkpoint(&fstab->recs[i])) {
- if (need_checkpoint == -1 &&
- !call_vdc_ret({"checkpoint", "needsCheckpoint"}, &need_checkpoint)) {
- LERROR << "Failed to find if checkpointing is needed. Assuming no.";
- need_checkpoint = 0;
- }
- if (need_checkpoint == 1 && !fs_mgr_update_checkpoint_partition(&fstab->recs[i])) {
- LERROR << "Could not set up checkpoint partition, skipping!";
- continue;
- }
+ if (!checkpoint_manager.Update(&fstab->recs[i])) {
+ LERROR << "Could not set up checkpoint partition, skipping!";
+ continue;
}
/* First check the filesystem if requested */
@@ -1292,8 +1340,8 @@
}
int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
- bool needs_cp) {
- return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, needs_cp);
+ bool needs_checkpoint) {
+ return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, needs_checkpoint);
}
/*
@@ -1498,8 +1546,6 @@
DeviceMapper& dm = DeviceMapper::Instance();
- bool system_root = android::base::GetProperty("ro.build.system_root_image", "") == "true";
-
for (int i = 0; i < fstab->num_entries; i++) {
auto fsrec = &fstab->recs[i];
if (!fs_mgr_is_verified(fsrec) && !fs_mgr_is_avb(fsrec)) {
@@ -1507,7 +1553,7 @@
}
std::string mount_point;
- if (system_root && !strcmp(fsrec->mount_point, "/")) {
+ if (!strcmp(fsrec->mount_point, "/")) {
// In AVB, the dm device name is vroot instead of system.
mount_point = fs_mgr_is_avb(fsrec) ? "vroot" : "system";
} else {
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 95326d1..ff7a75c 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -29,6 +29,7 @@
#include <sys/vfs.h>
#include <unistd.h>
+#include <algorithm>
#include <map>
#include <memory>
#include <string>
@@ -40,12 +41,18 @@
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <ext4_utils/ext4_utils.h>
+#include <fs_mgr_dm_linear.h>
#include <fs_mgr_overlayfs.h>
#include <fstab/fstab.h>
+#include <libdm/dm.h>
+#include <liblp/builder.h>
+#include <liblp/liblp.h>
#include "fs_mgr_priv.h"
using namespace std::literals;
+using namespace android::dm;
+using namespace android::fs_mgr;
#if ALLOW_ADBD_DISABLE_VERITY == 0 // If we are a user build, provide stubs
@@ -71,8 +78,10 @@
namespace {
-// acceptable overlayfs backing storage
-const auto kOverlayMountPoint = "/cache"s;
+// list of acceptable overlayfs backing storage
+const auto kScratchMountPoint = "/mnt/scratch"s;
+const auto kCacheMountPoint = "/cache"s;
+const std::vector<const std::string> kOverlayMountPoints = {kScratchMountPoint, kCacheMountPoint};
// Return true if everything is mounted, but before adb is started. Right
// after 'trigger load_persist_props_action' is done.
@@ -133,14 +142,17 @@
std::string fs_mgr_get_overlayfs_candidate(const std::string& mount_point) {
if (!fs_mgr_is_dir(mount_point)) return "";
- auto dir =
- kOverlayMountPoint + kOverlayTopDir + "/" + android::base::Basename(mount_point) + "/";
- auto upper = dir + kUpperName;
- if (!fs_mgr_is_dir(upper)) return "";
- auto work = dir + kWorkName;
- if (!fs_mgr_is_dir(work)) return "";
- if (!fs_mgr_dir_is_writable(work)) return "";
- return dir;
+ const auto base = android::base::Basename(mount_point) + "/";
+ for (const auto& overlay_mount_point : kOverlayMountPoints) {
+ auto dir = overlay_mount_point + kOverlayTopDir + "/" + base;
+ auto upper = dir + kUpperName;
+ if (!fs_mgr_is_dir(upper)) continue;
+ auto work = dir + kWorkName;
+ if (!fs_mgr_is_dir(work)) continue;
+ if (!fs_mgr_dir_is_writable(work)) continue;
+ return dir;
+ }
+ return "";
}
const auto kLowerdirOption = "lowerdir="s;
@@ -155,25 +167,9 @@
candidate + kUpperName + ",workdir=" + candidate + kWorkName;
}
-bool fs_mgr_system_root_image(const fstab* fstab) {
- if (!fstab) { // can not happen?
- // This will return empty on init first_stage_mount,
- // hence why we prefer checking the fstab instead.
- return android::base::GetBoolProperty("ro.build.system_root_image", false);
- }
- for (auto i = 0; i < fstab->num_entries; i++) {
- const auto fsrec = &fstab->recs[i];
- auto fsrec_mount_point = fsrec->mount_point;
- if (!fsrec_mount_point) continue;
- if ("/system"s == fsrec_mount_point) return false;
- }
- return true;
-}
-
-const char* fs_mgr_mount_point(const fstab* fstab, const char* mount_point) {
+const char* fs_mgr_mount_point(const char* mount_point) {
if (!mount_point) return mount_point;
if ("/"s != mount_point) return mount_point;
- if (!fs_mgr_system_root_image(fstab)) return mount_point;
return "/system";
}
@@ -184,6 +180,14 @@
return ret;
}
+bool fs_mgr_rw_access(const std::string& path) {
+ if (path.empty()) return false;
+ auto save_errno = errno;
+ auto ret = access(path.c_str(), R_OK | W_OK) == 0;
+ errno = save_errno;
+ return ret;
+}
+
// return true if system supports overlayfs
bool fs_mgr_wants_overlayfs() {
// Properties will return empty on init first_stage_mount, so speculative
@@ -197,7 +201,7 @@
return fs_mgr_access("/sys/module/overlay/parameters/override_creds");
}
-bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point) {
+bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only = true) {
std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab("/proc/mounts"),
fs_mgr_free_fstab);
if (!fstab) return false;
@@ -206,10 +210,11 @@
const auto fsrec = &fstab->recs[i];
const auto fs_type = fsrec->fs_type;
if (!fs_type) continue;
- if (("overlay"s != fs_type) && ("overlayfs"s != fs_type)) continue;
+ if (overlay_only && ("overlay"s != fs_type) && ("overlayfs"s != fs_type)) continue;
auto fsrec_mount_point = fsrec->mount_point;
if (!fsrec_mount_point) continue;
if (mount_point != fsrec_mount_point) continue;
+ if (!overlay_only) return true;
const auto fs_options = fsrec->fs_options;
if (!fs_options) continue;
const auto options = android::base::Split(fs_options, ",");
@@ -222,13 +227,12 @@
return false;
}
-bool fs_mgr_overlayfs_verity_enabled(const std::string& basename_mount_point) {
- auto found = false;
- fs_mgr_update_verity_state(
- [&basename_mount_point, &found](fstab_rec*, const char* mount_point, int, int) {
- if (mount_point && (basename_mount_point == mount_point)) found = true;
- });
- return found;
+std::vector<std::string> fs_mgr_overlayfs_verity_enabled_list() {
+ std::vector<std::string> ret;
+ fs_mgr_update_verity_state([&ret](fstab_rec*, const char* mount_point, int, int) {
+ ret.emplace_back(mount_point);
+ });
+ return ret;
}
bool fs_mgr_wants_overlayfs(const fstab_rec* fsrec) {
@@ -254,7 +258,7 @@
if (!fs_mgr_overlayfs_enabled(fsrec)) return false;
- return !fs_mgr_overlayfs_verity_enabled(android::base::Basename(fsrec_mount_point));
+ return true;
}
bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr) {
@@ -371,6 +375,67 @@
return ret;
}
+uint32_t fs_mgr_overlayfs_slot_number() {
+ return SlotNumberForSlotSuffix(fs_mgr_get_slot_suffix());
+}
+
+std::string fs_mgr_overlayfs_super_device(uint32_t slot_number) {
+ return "/dev/block/by-name/" + fs_mgr_get_super_partition_name(slot_number);
+}
+
+bool fs_mgr_overlayfs_has_logical(const fstab* fstab) {
+ if (!fstab) return false;
+ for (auto i = 0; i < fstab->num_entries; i++) {
+ const auto fsrec = &fstab->recs[i];
+ if (fs_mgr_is_logical(fsrec)) return true;
+ }
+ return false;
+}
+
+// reduce 'DM_DEV_STATUS failed for scratch: No such device or address' noise
+std::string scratch_device_cache;
+
+bool fs_mgr_overlayfs_teardown_scratch(const std::string& overlay, bool* change) {
+ // umount and delete kScratchMountPoint storage if we have logical partitions
+ if (overlay != kScratchMountPoint) return true;
+ scratch_device_cache.erase();
+ auto slot_number = fs_mgr_overlayfs_slot_number();
+ auto super_device = fs_mgr_overlayfs_super_device(slot_number);
+ if (!fs_mgr_rw_access(super_device)) return true;
+
+ auto save_errno = errno;
+ if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) {
+ // Lazy umount will allow us to move on and possibly later
+ // establish a new fresh mount without requiring a reboot should
+ // the developer wish to restart. Old references should melt
+ // away or have no data. Main goal is to shut the door on the
+ // current overrides with an expectation of a subsequent reboot,
+ // thus any errors here are ignored.
+ umount2(kScratchMountPoint.c_str(), MNT_DETACH);
+ }
+ auto builder = MetadataBuilder::New(super_device, slot_number);
+ if (!builder) {
+ errno = save_errno;
+ return true;
+ }
+ const auto partition_name = android::base::Basename(kScratchMountPoint);
+ if (builder->FindPartition(partition_name) == nullptr) {
+ errno = save_errno;
+ return true;
+ }
+ builder->RemovePartition(partition_name);
+ auto metadata = builder->Export();
+ if (metadata && UpdatePartitionTable(super_device, *metadata.get(), slot_number)) {
+ if (change) *change = true;
+ if (!DestroyLogicalPartition(partition_name, 0s)) return false;
+ } else {
+ PERROR << "delete partition " << overlay;
+ return false;
+ }
+ errno = save_errno;
+ return true;
+}
+
bool fs_mgr_overlayfs_teardown_one(const std::string& overlay, const std::string& mount_point,
bool* change) {
const auto top = overlay + kOverlayTopDir;
@@ -404,13 +469,16 @@
save_errno = errno;
if (!rmdir(top.c_str())) {
if (change) *change = true;
+ cleanup_all = true;
} else if ((errno != ENOENT) && (errno != ENOTEMPTY)) {
ret = false;
PERROR << "rmdir " << top;
} else {
errno = save_errno;
+ cleanup_all = true;
}
}
+ if (cleanup_all) ret &= fs_mgr_overlayfs_teardown_scratch(overlay, change);
return ret;
}
@@ -445,11 +513,16 @@
std::vector<std::string> mounts;
if (!fstab) return mounts;
+ auto verity = fs_mgr_overlayfs_verity_enabled_list();
for (auto i = 0; i < fstab->num_entries; i++) {
const auto fsrec = &fstab->recs[i];
if (!fs_mgr_wants_overlayfs(fsrec)) continue;
- std::string new_mount_point(fs_mgr_mount_point(fstab, fsrec->mount_point));
+ std::string new_mount_point(fs_mgr_mount_point(fsrec->mount_point));
if (mount_point && (new_mount_point != mount_point)) continue;
+ if (std::find(verity.begin(), verity.end(), android::base::Basename(new_mount_point)) !=
+ verity.end()) {
+ continue;
+ }
auto duplicate_or_more_specific = false;
for (auto it = mounts.begin(); it != mounts.end();) {
if ((*it == new_mount_point) ||
@@ -465,19 +538,170 @@
}
if (!duplicate_or_more_specific) mounts.emplace_back(new_mount_point);
}
- // if not itemized /system or /, system as root, fake up
- // fs_mgr_wants_overlayfs evaluation of /system as candidate.
- if ((std::find(mounts.begin(), mounts.end(), "/system") == mounts.end()) &&
- !fs_mgr_get_entry_for_mount_point(const_cast<struct fstab*>(fstab), "/") &&
- !fs_mgr_get_entry_for_mount_point(const_cast<struct fstab*>(fstab), "/system") &&
- (!mount_point || ("/system"s == mount_point)) &&
- !fs_mgr_overlayfs_verity_enabled("system")) {
- mounts.emplace_back("/system");
+ // if not itemized /system or /, system as root, fake one up?
+
+ // do we want or need to?
+ if (mount_point && ("/system"s != mount_point)) return mounts;
+ if (std::find(mounts.begin(), mounts.end(), "/system") != mounts.end()) return mounts;
+
+ // fs_mgr_overlayfs_verity_enabled_list says not to?
+ if (std::find(verity.begin(), verity.end(), "system") != verity.end()) return mounts;
+
+ // confirm that fstab is missing system
+ if (fs_mgr_get_entry_for_mount_point(const_cast<struct fstab*>(fstab), "/")) {
+ return mounts;
}
+ if (fs_mgr_get_entry_for_mount_point(const_cast<struct fstab*>(fstab), "/system")) {
+ return mounts;
+ }
+
+ // Manually check dm state because stunted fstab (w/o system as root) borken
+ auto& dm = DeviceMapper::Instance();
+ auto found = false;
+ for (auto& system : {"system", "vroot"}) {
+ if (dm.GetState(system) == DmDeviceState::INVALID) continue;
+ std::vector<DeviceMapper::TargetInfo> table;
+ found = !dm.GetTableStatus(system, &table) || table.empty() || table[0].data.empty() ||
+ (table[0].data[0] == 'C') || (table[0].data[0] == 'V');
+ if (found) break;
+ }
+ if (!found) mounts.emplace_back("/system");
return mounts;
}
+// Mount kScratchMountPoint
+bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::string mnt_type) {
+ if (setfscreatecon(kOverlayfsFileContext)) {
+ PERROR << "setfscreatecon " << kOverlayfsFileContext;
+ }
+ if (mkdir(kScratchMountPoint.c_str(), 0755) && (errno != EEXIST)) {
+ PERROR << "create " << kScratchMountPoint;
+ }
+
+ std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> local_fstab(
+ static_cast<fstab*>(calloc(1, sizeof(fstab))), fs_mgr_free_fstab);
+ auto fsrec = static_cast<fstab_rec*>(calloc(1, sizeof(fstab_rec)));
+ local_fstab->num_entries = 1;
+ local_fstab->recs = fsrec;
+ fsrec->blk_device = strdup(device_path.c_str());
+ fsrec->mount_point = strdup(kScratchMountPoint.c_str());
+ fsrec->fs_type = strdup(mnt_type.c_str());
+ fsrec->flags = MS_RELATIME;
+ fsrec->fs_options = strdup("");
+ auto mounted = fs_mgr_do_mount_one(fsrec) == 0;
+ auto save_errno = errno;
+ setfscreatecon(nullptr);
+ if (!mounted) rmdir(kScratchMountPoint.c_str());
+ errno = save_errno;
+ return mounted;
+}
+
+const std::string kMkF2fs("/system/bin/make_f2fs");
+const std::string kMkExt4("/system/bin/mke2fs");
+
+std::string fs_mgr_overlayfs_scratch_mount_type() {
+ if (!access(kMkF2fs.c_str(), X_OK)) return "f2fs";
+ if (!access(kMkExt4.c_str(), X_OK)) return "ext4";
+ return "auto";
+}
+
+std::string fs_mgr_overlayfs_scratch_device() {
+ if (!scratch_device_cache.empty()) return scratch_device_cache;
+
+ auto& dm = DeviceMapper::Instance();
+ const auto partition_name = android::base::Basename(kScratchMountPoint);
+ std::string path;
+ if (!dm.GetDmDevicePathByName(partition_name, &path)) return "";
+ return scratch_device_cache = path;
+}
+
+// Create and mount kScratchMountPoint storage if we have logical partitions
+bool fs_mgr_overlayfs_setup_scratch(const fstab* fstab, bool* change) {
+ if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true;
+ auto mnt_type = fs_mgr_overlayfs_scratch_mount_type();
+ auto scratch_device = fs_mgr_overlayfs_scratch_device();
+ auto partition_exists = fs_mgr_rw_access(scratch_device);
+ if (!partition_exists) {
+ auto slot_number = fs_mgr_overlayfs_slot_number();
+ auto super_device = fs_mgr_overlayfs_super_device(slot_number);
+ if (!fs_mgr_rw_access(super_device)) return false;
+ if (!fs_mgr_overlayfs_has_logical(fstab)) return false;
+ auto builder = MetadataBuilder::New(super_device, slot_number);
+ if (!builder) {
+ PERROR << "open " << super_device << " metadata";
+ return false;
+ }
+ const auto partition_name = android::base::Basename(kScratchMountPoint);
+ partition_exists = builder->FindPartition(partition_name) != nullptr;
+ if (!partition_exists) {
+ auto partition = builder->AddPartition(partition_name, LP_PARTITION_ATTR_NONE);
+ if (!partition) {
+ PERROR << "create " << partition_name;
+ return false;
+ }
+ auto partition_size = builder->AllocatableSpace() - builder->UsedSpace();
+ // 512MB or half the remaining available space, whichever is greater.
+ partition_size = std::max(uint64_t(512 * 1024 * 1024), partition_size / 2);
+ if (!builder->ResizePartition(partition, partition_size)) {
+ PERROR << "resize " << partition_name;
+ return false;
+ }
+
+ auto metadata = builder->Export();
+ if (!metadata) {
+ LERROR << "generate new metadata " << partition_name;
+ return false;
+ }
+ if (!UpdatePartitionTable(super_device, *metadata.get(), slot_number)) {
+ LERROR << "update " << partition_name;
+ return false;
+ }
+
+ if (change) *change = true;
+ }
+
+ if (!CreateLogicalPartition(super_device, slot_number, partition_name, true, 0s,
+ &scratch_device))
+ return false;
+ }
+
+ if (partition_exists) {
+ if (fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type)) {
+ if (change) *change = true;
+ return true;
+ }
+ // partition existed, but was not initialized;
+ errno = 0;
+ }
+
+ auto ret = system((mnt_type == "f2fs")
+ ? ((kMkF2fs + " -d1 " + scratch_device).c_str())
+ : ((kMkExt4 + " -b 4096 -t ext4 -m 0 -M "s + kScratchMountPoint +
+ " -O has_journal " + scratch_device)
+ .c_str()));
+ if (ret) {
+ LERROR << "make " << mnt_type << " filesystem on " << scratch_device << " error=" << ret;
+ return false;
+ }
+
+ if (change) *change = true;
+
+ return fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type);
+}
+
+bool fs_mgr_overlayfs_scratch_can_be_mounted(const std::string& scratch_device) {
+ if (scratch_device.empty()) return false;
+ if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return false;
+ if (fs_mgr_rw_access(scratch_device)) return true;
+ auto slot_number = fs_mgr_overlayfs_slot_number();
+ auto super_device = fs_mgr_overlayfs_super_device(slot_number);
+ if (!fs_mgr_rw_access(super_device)) return false;
+ auto builder = MetadataBuilder::New(super_device, slot_number);
+ if (!builder) return false;
+ return builder->FindPartition(android::base::Basename(kScratchMountPoint)) != nullptr;
+}
+
} // namespace
bool fs_mgr_overlayfs_mount_all(const fstab* fstab) {
@@ -487,14 +711,37 @@
if (!fstab) return ret;
+ auto scratch_can_be_mounted = true;
for (const auto& mount_point : fs_mgr_candidate_list(fstab)) {
if (fs_mgr_overlayfs_already_mounted(mount_point)) continue;
+ if (scratch_can_be_mounted) {
+ scratch_can_be_mounted = false;
+ auto scratch_device = fs_mgr_overlayfs_scratch_device();
+ if (fs_mgr_overlayfs_scratch_can_be_mounted(scratch_device) &&
+ fs_mgr_wait_for_file(scratch_device, 10s) &&
+ fs_mgr_overlayfs_mount_scratch(scratch_device,
+ fs_mgr_overlayfs_scratch_mount_type()) &&
+ !fs_mgr_access(kScratchMountPoint + kOverlayTopDir)) {
+ umount2(kScratchMountPoint.c_str(), MNT_DETACH);
+ rmdir(kScratchMountPoint.c_str());
+ }
+ }
if (fs_mgr_overlayfs_mount(mount_point)) ret = true;
}
return ret;
}
-std::vector<std::string> fs_mgr_overlayfs_required_devices(const fstab*) {
+std::vector<std::string> fs_mgr_overlayfs_required_devices(const fstab* fstab) {
+ if (fs_mgr_get_entry_for_mount_point(const_cast<struct fstab*>(fstab), kScratchMountPoint)) {
+ return {};
+ }
+
+ for (const auto& mount_point : fs_mgr_candidate_list(fstab)) {
+ if (fs_mgr_overlayfs_already_mounted(mount_point)) continue;
+ auto device = fs_mgr_overlayfs_scratch_device();
+ if (!fs_mgr_overlayfs_scratch_can_be_mounted(device)) break;
+ return {device};
+ }
return {};
}
@@ -503,10 +750,6 @@
bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* change) {
if (change) *change = false;
auto ret = false;
- if (backing && (kOverlayMountPoint != backing)) {
- errno = EINVAL;
- return ret;
- }
if (!fs_mgr_wants_overlayfs()) return ret;
if (!fs_mgr_boot_completed()) {
errno = EBUSY;
@@ -516,16 +759,32 @@
std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
fs_mgr_free_fstab);
- if (fstab && !fs_mgr_get_entry_for_mount_point(fstab.get(), kOverlayMountPoint)) return ret;
- auto mounts = fs_mgr_candidate_list(fstab.get(), fs_mgr_mount_point(fstab.get(), mount_point));
- if (fstab && mounts.empty()) return ret;
+ if (!fstab) return ret;
+ auto mounts = fs_mgr_candidate_list(fstab.get(), fs_mgr_mount_point(mount_point));
+ if (mounts.empty()) return ret;
+
+ std::string dir;
+ for (const auto& overlay_mount_point : kOverlayMountPoints) {
+ if (backing && backing[0] && (overlay_mount_point != backing)) continue;
+ if (overlay_mount_point == kScratchMountPoint) {
+ if (!fs_mgr_rw_access(fs_mgr_overlayfs_super_device(fs_mgr_overlayfs_slot_number())) ||
+ !fs_mgr_overlayfs_has_logical(fstab.get())) {
+ continue;
+ }
+ if (!fs_mgr_overlayfs_setup_scratch(fstab.get(), change)) continue;
+ } else {
+ if (!fs_mgr_get_entry_for_mount_point(fstab.get(), overlay_mount_point)) continue;
+ }
+ dir = overlay_mount_point;
+ break;
+ }
+ if (dir.empty()) {
+ errno = ESRCH;
+ return ret;
+ }
std::string overlay;
- ret |= fs_mgr_overlayfs_setup_dir(kOverlayMountPoint, &overlay, change);
-
- if (!fstab && mount_point && fs_mgr_overlayfs_setup_one(overlay, mount_point, change)) {
- ret = true;
- }
+ ret |= fs_mgr_overlayfs_setup_dir(dir, &overlay, change);
for (const auto& fsrec_mount_point : mounts) {
ret |= fs_mgr_overlayfs_setup_one(overlay, fsrec_mount_point, change);
}
@@ -536,11 +795,11 @@
// If something is altered, set *change.
bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) {
if (change) *change = false;
- mount_point = fs_mgr_mount_point(std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>(
- fs_mgr_read_fstab_default(), fs_mgr_free_fstab)
- .get(),
- mount_point);
- auto ret = fs_mgr_overlayfs_teardown_one(kOverlayMountPoint, mount_point ?: "", change);
+ mount_point = fs_mgr_mount_point(mount_point);
+ auto ret = true;
+ for (const auto& overlay_mount_point : kOverlayMountPoints) {
+ ret &= fs_mgr_overlayfs_teardown_one(overlay_mount_point, mount_point ?: "", change);
+ }
if (!fs_mgr_wants_overlayfs()) {
// After obligatory teardown to make sure everything is clean, but if
// we didn't want overlayfs in the the first place, we do not want to
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 506e81d..5e83cfb 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -128,10 +128,10 @@
FileWaitMode wait_mode = FileWaitMode::Exists);
int fs_mgr_set_blk_ro(const char* blockdev);
-bool fs_mgr_update_for_slotselect(struct fstab *fstab);
+bool fs_mgr_update_for_slotselect(fstab* fstab);
bool fs_mgr_is_device_unlocked();
const std::string& get_android_dt_dir();
bool is_dt_compatible();
-int load_verity_state(struct fstab_rec* fstab, int* mode);
+int load_verity_state(fstab_rec* fstab, int* mode);
#endif /* __CORE_FS_MGR_PRIV_H */
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index a4544b2..5dabe76 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -51,8 +51,8 @@
};
// Callback function for verity status
-typedef void fs_mgr_verity_state_callback(struct fstab_rec* fstab, const char* mount_point,
- int mode, int status);
+typedef void fs_mgr_verity_state_callback(fstab_rec* fstab, const char* mount_point, int mode,
+ int status);
#define FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED 7
#define FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION 6
@@ -63,32 +63,31 @@
#define FS_MGR_MNTALL_DEV_NOT_ENCRYPTED 1
#define FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE 0
#define FS_MGR_MNTALL_FAIL (-1)
-int fs_mgr_mount_all(struct fstab *fstab, int mount_mode);
+int fs_mgr_mount_all(fstab* fstab, int mount_mode);
#define FS_MGR_DOMNT_FAILED (-1)
#define FS_MGR_DOMNT_BUSY (-2)
#define FS_MGR_DOMNT_SUCCESS 0
-int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
- char *tmp_mount_point);
-int fs_mgr_do_mount(struct fstab* fstab, const char* n_name, char* n_blk_device,
- char* tmp_mount_point, bool need_cp);
-int fs_mgr_do_mount_one(struct fstab_rec *rec);
+int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point);
+int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
+ bool need_cp);
+int fs_mgr_do_mount_one(fstab_rec* rec);
int fs_mgr_do_tmpfs_mount(const char *n_name);
-struct fstab_rec const* fs_mgr_get_crypt_entry(struct fstab const* fstab);
-void fs_mgr_get_crypt_info(struct fstab* fstab, char* key_loc, char* real_blk_device, size_t size);
+fstab_rec const* fs_mgr_get_crypt_entry(fstab const* fstab);
+void fs_mgr_get_crypt_info(fstab* fstab, char* key_loc, char* real_blk_device, size_t size);
bool fs_mgr_load_verity_state(int* mode);
bool fs_mgr_update_verity_state(std::function<fs_mgr_verity_state_callback> callback);
int fs_mgr_swapon_all(struct fstab *fstab);
bool fs_mgr_update_logical_partition(struct fstab_rec* rec);
-int fs_mgr_do_format(struct fstab_rec *fstab, bool reserve_footer);
+int fs_mgr_do_format(fstab_rec* fstab, bool reserve_footer);
#define FS_MGR_SETUP_VERITY_SKIPPED (-3)
#define FS_MGR_SETUP_VERITY_DISABLED (-2)
#define FS_MGR_SETUP_VERITY_FAIL (-1)
#define FS_MGR_SETUP_VERITY_SUCCESS 0
-int fs_mgr_setup_verity(struct fstab_rec *fstab, bool wait_for_verity_dev);
+int fs_mgr_setup_verity(fstab_rec* fstab, bool wait_for_verity_dev);
// Return the name of the super partition if it exists. If a slot number is
// specified, the super partition for the corresponding metadata slot will be
diff --git a/gatekeeperd/IGateKeeperService.cpp b/gatekeeperd/IGateKeeperService.cpp
index 1c339f4..43d5708 100644
--- a/gatekeeperd/IGateKeeperService.cpp
+++ b/gatekeeperd/IGateKeeperService.cpp
@@ -70,7 +70,7 @@
} else {
reply->writeInt32(GATEKEEPER_RESPONSE_ERROR);
}
- return NO_ERROR;
+ return OK;
}
case VERIFY: {
CHECK_INTERFACE(IGateKeeperService, data, reply);
@@ -102,7 +102,7 @@
} else {
reply->writeInt32(GATEKEEPER_RESPONSE_ERROR);
}
- return NO_ERROR;
+ return OK;
}
case VERIFY_CHALLENGE: {
CHECK_INTERFACE(IGateKeeperService, data, reply);
@@ -141,7 +141,7 @@
} else {
reply->writeInt32(GATEKEEPER_RESPONSE_ERROR);
}
- return NO_ERROR;
+ return OK;
}
case GET_SECURE_USER_ID: {
CHECK_INTERFACE(IGateKeeperService, data, reply);
@@ -149,20 +149,20 @@
uint64_t sid = getSecureUserId(uid);
reply->writeNoException();
reply->writeInt64(sid);
- return NO_ERROR;
+ return OK;
}
case CLEAR_SECURE_USER_ID: {
CHECK_INTERFACE(IGateKeeperService, data, reply);
uint32_t uid = data.readInt32();
clearSecureUserId(uid);
reply->writeNoException();
- return NO_ERROR;
+ return OK;
}
case REPORT_DEVICE_SETUP_COMPLETE: {
CHECK_INTERFACE(IGateKeeperService, data, reply);
reportDeviceSetupComplete();
reply->writeNoException();
- return NO_ERROR;
+ return OK;
}
default:
return BBinder::onTransact(code, data, reply, flags);
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index 5f3ce36..f2818f3 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -386,7 +386,7 @@
write(fd, result, strlen(result) + 1);
}
- return NO_ERROR;
+ return OK;
}
private:
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 80c5afe..2a5667c 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -357,7 +357,7 @@
if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
val->valueInt64 =
getIntField(mHealthdConfig->batteryChargeCounterPath);
- ret = NO_ERROR;
+ ret = OK;
} else {
ret = NAME_NOT_FOUND;
}
@@ -367,7 +367,7 @@
if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
val->valueInt64 =
getIntField(mHealthdConfig->batteryCurrentNowPath);
- ret = NO_ERROR;
+ ret = OK;
} else {
ret = NAME_NOT_FOUND;
}
@@ -377,7 +377,7 @@
if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
val->valueInt64 =
getIntField(mHealthdConfig->batteryCurrentAvgPath);
- ret = NO_ERROR;
+ ret = OK;
} else {
ret = NAME_NOT_FOUND;
}
@@ -387,7 +387,7 @@
if (!mHealthdConfig->batteryCapacityPath.isEmpty()) {
val->valueInt64 =
getIntField(mHealthdConfig->batteryCapacityPath);
- ret = NO_ERROR;
+ ret = OK;
} else {
ret = NAME_NOT_FOUND;
}
@@ -403,7 +403,7 @@
case BATTERY_PROP_BATTERY_STATUS:
val->valueInt64 = getChargeStatus();
- ret = NO_ERROR;
+ ret = OK;
break;
default:
diff --git a/init/reboot.cpp b/init/reboot.cpp
index d6c5b94..a145797 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -309,15 +309,14 @@
auto shutdown_timeout = 0ms;
if (!SHUTDOWN_ZERO_TIMEOUT) {
- if (is_thermal_shutdown) {
- constexpr unsigned int thermal_shutdown_timeout = 1;
- shutdown_timeout = std::chrono::seconds(thermal_shutdown_timeout);
- } else {
- constexpr unsigned int shutdown_timeout_default = 6;
- auto shutdown_timeout_property = android::base::GetUintProperty(
- "ro.build.shutdown_timeout", shutdown_timeout_default);
- shutdown_timeout = std::chrono::seconds(shutdown_timeout_property);
+ constexpr unsigned int shutdown_timeout_default = 6;
+ constexpr unsigned int max_thermal_shutdown_timeout = 3;
+ auto shutdown_timeout_final = android::base::GetUintProperty("ro.build.shutdown_timeout",
+ shutdown_timeout_default);
+ if (is_thermal_shutdown && shutdown_timeout_final > max_thermal_shutdown_timeout) {
+ shutdown_timeout_final = max_thermal_shutdown_timeout;
}
+ shutdown_timeout = std::chrono::seconds(shutdown_timeout_final);
}
LOG(INFO) << "Shutdown timeout: " << shutdown_timeout.count() << " ms";
diff --git a/libcutils/partition_utils.cpp b/libcutils/partition_utils.cpp
index 6735d6c..2211ff6 100644
--- a/libcutils/partition_utils.cpp
+++ b/libcutils/partition_utils.cpp
@@ -25,7 +25,7 @@
#include <cutils/properties.h>
-static int only_one_char(char *buf, int len, char c)
+static int only_one_char(uint8_t *buf, int len, uint8_t c)
{
int i, ret;
@@ -41,7 +41,7 @@
int partition_wiped(char *source)
{
- char buf[4096];
+ uint8_t buf[4096];
int fd, ret;
if ((fd = open(source, O_RDONLY)) < 0) {
diff --git a/libpixelflinger/codeflinger/ARMAssembler.cpp b/libpixelflinger/codeflinger/ARMAssembler.cpp
index ac009a9..f47b6e4 100644
--- a/libpixelflinger/codeflinger/ARMAssembler.cpp
+++ b/libpixelflinger/codeflinger/ARMAssembler.cpp
@@ -171,7 +171,7 @@
}
mAssembly->resize( int(pc()-base())*4 );
-
+
// the instruction cache is flushed by CodeCache
const int64_t duration = ggl_system_time() - mDuration;
const char * const format = "generated %s (%d ins) at [%p:%p] in %lld ns\n";
@@ -183,8 +183,8 @@
printf(format, name, int(pc()-base()), base(), pc(), duration);
disassemble(name);
}
-
- return NO_ERROR;
+
+ return OK;
}
uint32_t* ARMAssembler::pcForLabel(const char* label)
@@ -213,14 +213,14 @@
// multiply...
void ARMAssembler::MLA(int cc, int s,
int Rd, int Rm, int Rs, int Rn) {
- if (Rd == Rm) { int t = Rm; Rm=Rs; Rs=t; }
+ if (Rd == Rm) { int t = Rm; Rm=Rs; Rs=t; }
LOG_FATAL_IF(Rd==Rm, "MLA(r%u,r%u,r%u,r%u)", Rd,Rm,Rs,Rn);
*mPC++ = (cc<<28) | (1<<21) | (s<<20) |
(Rd<<16) | (Rn<<12) | (Rs<<8) | 0x90 | Rm;
}
void ARMAssembler::MUL(int cc, int s,
int Rd, int Rm, int Rs) {
- if (Rd == Rm) { int t = Rm; Rm=Rs; Rs=t; }
+ if (Rd == Rm) { int t = Rm; Rm=Rs; Rs=t; }
LOG_FATAL_IF(Rd==Rm, "MUL(r%u,r%u,r%u)", Rd,Rm,Rs);
*mPC++ = (cc<<28) | (s<<20) | (Rd<<16) | (Rs<<8) | 0x90 | Rm;
}
@@ -577,4 +577,3 @@
}
}; // namespace android
-
diff --git a/libpixelflinger/codeflinger/Arm64Assembler.cpp b/libpixelflinger/codeflinger/Arm64Assembler.cpp
index aebc129..8926776 100644
--- a/libpixelflinger/codeflinger/Arm64Assembler.cpp
+++ b/libpixelflinger/codeflinger/Arm64Assembler.cpp
@@ -325,7 +325,7 @@
printf(format, name, int(pc()-base()), base(), pc(), duration);
disassemble(name);
}
- return NO_ERROR;
+ return OK;
}
uint32_t* ArmToArm64Assembler::pcForLabel(const char* label)
@@ -1238,4 +1238,3 @@
}
}; // namespace android
-
diff --git a/libpixelflinger/codeflinger/MIPSAssembler.cpp b/libpixelflinger/codeflinger/MIPSAssembler.cpp
index 039a725..7de8cc1 100644
--- a/libpixelflinger/codeflinger/MIPSAssembler.cpp
+++ b/libpixelflinger/codeflinger/MIPSAssembler.cpp
@@ -1421,7 +1421,7 @@
disassemble(name);
}
- return NO_ERROR;
+ return OK;
}
uint32_t* MIPSAssembler::pcForLabel(const char* label)
@@ -1953,5 +1953,3 @@
}; // namespace android:
-
-
diff --git a/libsystem/include/system/camera.h b/libsystem/include/system/camera.h
index 7d79673..2ca90c3 100644
--- a/libsystem/include/system/camera.h
+++ b/libsystem/include/system/camera.h
@@ -158,8 +158,8 @@
*
* When any camera method returns error, the client can use ping command
* to see if the camera has been taken away by other clients. If the result
- * is NO_ERROR, it means the camera hardware is not released. If the result
- * is not NO_ERROR, the camera has been released and the existing client
+ * is OK, it means the camera hardware is not released. If the result
+ * is not OK, the camera has been released and the existing client
* can silently finish itself or show a dialog.
*/
CAMERA_CMD_PING = 9,
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index 24ea7aa..9dc2699 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -374,6 +374,7 @@
continue;
if (!if_indextoname(* (int *) RTA_DATA(rta), dev))
return false;
+ continue;
default:
continue;
}
diff --git a/libunwindstack/DexFiles.cpp b/libunwindstack/DexFiles.cpp
index 430f6c5..17e2526 100644
--- a/libunwindstack/DexFiles.cpp
+++ b/libunwindstack/DexFiles.cpp
@@ -126,7 +126,7 @@
const std::string dex_debug_name("__dex_debug_descriptor");
for (MapInfo* info : *maps) {
- if (!(info->flags & PROT_EXEC) || !(info->flags & PROT_READ) || info->offset != 0) {
+ if (!(info->flags & PROT_READ) || info->offset != 0) {
continue;
}
diff --git a/libunwindstack/JitDebug.cpp b/libunwindstack/JitDebug.cpp
index 0c319ec..821aacf 100644
--- a/libunwindstack/JitDebug.cpp
+++ b/libunwindstack/JitDebug.cpp
@@ -174,7 +174,7 @@
const std::string descriptor_name("__jit_debug_descriptor");
for (MapInfo* info : *maps) {
- if (!(info->flags & PROT_EXEC) || !(info->flags & PROT_READ) || info->offset != 0) {
+ if (!(info->flags & PROT_READ) || info->offset != 0) {
continue;
}
@@ -194,10 +194,9 @@
Elf* elf = info->GetElf(memory_, true);
uint64_t descriptor_addr;
- if (elf->GetGlobalVariable(descriptor_name, &descriptor_addr)) {
- // Search for the first non-zero entry.
- descriptor_addr += info->start;
- entry_addr_ = (this->*read_descriptor_func_)(descriptor_addr);
+ // Find first non-empty entry (libart might be loaded multiple times).
+ if (elf->GetGlobalVariable(descriptor_name, &descriptor_addr) && descriptor_addr != 0) {
+ entry_addr_ = (this->*read_descriptor_func_)(descriptor_addr + info->start);
if (entry_addr_ != 0) {
break;
}
diff --git a/libunwindstack/tests/DexFilesTest.cpp b/libunwindstack/tests/DexFilesTest.cpp
index d029bb0..c6d7f33 100644
--- a/libunwindstack/tests/DexFilesTest.cpp
+++ b/libunwindstack/tests/DexFilesTest.cpp
@@ -46,17 +46,17 @@
maps_.reset(
new BufferMaps("1000-4000 ---s 00000000 00:00 0\n"
"4000-6000 r--s 00000000 00:00 0\n"
- "6000-8000 -w-s 00000000 00:00 0\n"
- "a000-c000 r-xp 00000000 00:00 0\n"
- "c000-f000 rwxp 00000000 00:00 0\n"
- "f000-11000 r-xp 00000000 00:00 0\n"
+ "6000-8000 -wxs 00000000 00:00 0\n"
+ "a000-c000 r--p 00000000 00:00 0\n"
+ "c000-f000 rw-p 00000000 00:00 0\n"
+ "f000-11000 r--p 00000000 00:00 0\n"
"100000-110000 rw-p 0000000 00:00 0\n"
"200000-210000 rw-p 0000000 00:00 0\n"
"300000-400000 rw-p 0000000 00:00 0\n"));
ASSERT_TRUE(maps_->Parse());
- // Global variable in a section that is not readable/executable.
- MapInfo* map_info = maps_->Get(kMapGlobalNonReadableExectable);
+ // Global variable in a section that is not readable.
+ MapInfo* map_info = maps_->Get(kMapGlobalNonReadable);
ASSERT_TRUE(map_info != nullptr);
MemoryFake* memory = new MemoryFake;
ElfFake* elf = new ElfFake(memory);
@@ -95,7 +95,7 @@
void WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t prev, uint64_t dex_file);
void WriteDex(uint64_t dex_file);
- static constexpr size_t kMapGlobalNonReadableExectable = 3;
+ static constexpr size_t kMapGlobalNonReadable = 2;
static constexpr size_t kMapGlobalSetToZero = 4;
static constexpr size_t kMapGlobal = 5;
static constexpr size_t kMapDexFileEntries = 7;
diff --git a/libunwindstack/tests/JitDebugTest.cpp b/libunwindstack/tests/JitDebugTest.cpp
index c1c45f8..66f0859 100644
--- a/libunwindstack/tests/JitDebugTest.cpp
+++ b/libunwindstack/tests/JitDebugTest.cpp
@@ -45,11 +45,11 @@
maps_.reset(
new BufferMaps("1000-4000 ---s 00000000 00:00 0\n"
"4000-6000 r--s 00000000 00:00 0\n"
- "6000-8000 -w-s 00000000 00:00 0\n"
+ "6000-8000 -wxs 00000000 00:00 0\n"
"a000-c000 --xp 00000000 00:00 0\n"
- "c000-f000 rwxp 00000000 00:00 0\n"
- "f000-11000 r-xp 00000000 00:00 0\n"
- "12000-14000 r-xp 00000000 00:00 0\n"
+ "c000-f000 rw-p 00000000 00:00 0\n"
+ "f000-11000 r--p 00000000 00:00 0\n"
+ "12000-14000 r--p 00000000 00:00 0\n"
"100000-110000 rw-p 0000000 00:00 0\n"
"200000-210000 rw-p 0000000 00:00 0\n"));
ASSERT_TRUE(maps_->Parse());
diff --git a/libutils/PropertyMap.cpp b/libutils/PropertyMap.cpp
index b8c065d..f00272a 100644
--- a/libutils/PropertyMap.cpp
+++ b/libutils/PropertyMap.cpp
@@ -208,7 +208,7 @@
mTokenizer->nextLine();
}
- return NO_ERROR;
+ return OK;
}
} // namespace android
diff --git a/libutils/String16.cpp b/libutils/String16.cpp
index 5c0b406..818b171 100644
--- a/libutils/String16.cpp
+++ b/libutils/String16.cpp
@@ -157,12 +157,12 @@
if (begin >= N) {
SharedBuffer::bufferFromData(mString)->release();
mString = getEmptyString();
- return NO_ERROR;
+ return OK;
}
if ((begin+len) > N) len = N-begin;
if (begin == 0 && len == N) {
setTo(other);
- return NO_ERROR;
+ return OK;
}
if (&other == this) {
@@ -191,7 +191,7 @@
memmove(str, other, len*sizeof(char16_t));
str[len] = 0;
mString = str;
- return NO_ERROR;
+ return OK;
}
return NO_MEMORY;
}
@@ -202,9 +202,9 @@
const size_t otherLen = other.size();
if (myLen == 0) {
setTo(other);
- return NO_ERROR;
+ return OK;
} else if (otherLen == 0) {
- return NO_ERROR;
+ return OK;
}
if (myLen >= SIZE_MAX / sizeof(char16_t) - otherLen) {
@@ -218,7 +218,7 @@
char16_t* str = (char16_t*)buf->data();
memcpy(str+myLen, other, (otherLen+1)*sizeof(char16_t));
mString = str;
- return NO_ERROR;
+ return OK;
}
return NO_MEMORY;
}
@@ -228,9 +228,9 @@
const size_t myLen = size();
if (myLen == 0) {
setTo(chrs, otherLen);
- return NO_ERROR;
+ return OK;
} else if (otherLen == 0) {
- return NO_ERROR;
+ return OK;
}
if (myLen >= SIZE_MAX / sizeof(char16_t) - otherLen) {
@@ -245,7 +245,7 @@
memcpy(str+myLen, chrs, otherLen*sizeof(char16_t));
str[myLen+otherLen] = 0;
mString = str;
- return NO_ERROR;
+ return OK;
}
return NO_MEMORY;
}
@@ -260,9 +260,9 @@
const size_t myLen = size();
if (myLen == 0) {
return setTo(chrs, len);
- return NO_ERROR;
+ return OK;
} else if (len == 0) {
- return NO_ERROR;
+ return OK;
}
if (pos > myLen) pos = myLen;
@@ -286,7 +286,7 @@
#if 0
printf("Result (%d chrs): %s\n", size(), String8(*this).string());
#endif
- return NO_ERROR;
+ return OK;
}
return NO_MEMORY;
}
@@ -357,7 +357,7 @@
edit[i] = tolower((char)v);
}
}
- return NO_ERROR;
+ return OK;
}
status_t String16::replaceAll(char16_t replaceThis, char16_t withThis)
@@ -378,7 +378,7 @@
edit[i] = withThis;
}
}
- return NO_ERROR;
+ return OK;
}
status_t String16::remove(size_t len, size_t begin)
@@ -387,11 +387,11 @@
if (begin >= N) {
SharedBuffer::bufferFromData(mString)->release();
mString = getEmptyString();
- return NO_ERROR;
+ return OK;
}
if ((begin+len) > N) len = N-begin;
if (begin == 0 && len == N) {
- return NO_ERROR;
+ return OK;
}
if (begin > 0) {
@@ -410,7 +410,7 @@
char16_t* str = (char16_t*)buf->data();
str[len] = 0;
mString = str;
- return NO_ERROR;
+ return OK;
}
return NO_MEMORY;
}
diff --git a/libutils/String8.cpp b/libutils/String8.cpp
index 8d318f7..0025c56 100644
--- a/libutils/String8.cpp
+++ b/libutils/String8.cpp
@@ -230,7 +230,7 @@
const char *newString = allocFromUTF8(other, strlen(other));
SharedBuffer::bufferFromData(mString)->release();
mString = newString;
- if (mString) return NO_ERROR;
+ if (mString) return OK;
mString = getEmptyString();
return NO_MEMORY;
@@ -241,7 +241,7 @@
const char *newString = allocFromUTF8(other, len);
SharedBuffer::bufferFromData(mString)->release();
mString = newString;
- if (mString) return NO_ERROR;
+ if (mString) return OK;
mString = getEmptyString();
return NO_MEMORY;
@@ -252,7 +252,7 @@
const char *newString = allocFromUTF16(other, len);
SharedBuffer::bufferFromData(mString)->release();
mString = newString;
- if (mString) return NO_ERROR;
+ if (mString) return OK;
mString = getEmptyString();
return NO_MEMORY;
@@ -263,7 +263,7 @@
const char *newString = allocFromUTF32(other, len);
SharedBuffer::bufferFromData(mString)->release();
mString = newString;
- if (mString) return NO_ERROR;
+ if (mString) return OK;
mString = getEmptyString();
return NO_MEMORY;
@@ -274,9 +274,9 @@
const size_t otherLen = other.bytes();
if (bytes() == 0) {
setTo(other);
- return NO_ERROR;
+ return OK;
} else if (otherLen == 0) {
- return NO_ERROR;
+ return OK;
}
return real_append(other.string(), otherLen);
@@ -292,7 +292,7 @@
if (bytes() == 0) {
return setTo(other, otherLen);
} else if (otherLen == 0) {
- return NO_ERROR;
+ return OK;
}
return real_append(other, otherLen);
@@ -311,7 +311,7 @@
status_t String8::appendFormatV(const char* fmt, va_list args)
{
- int n, result = NO_ERROR;
+ int n, result = OK;
va_list tmp_args;
/* args is undefined after vsnprintf.
@@ -346,7 +346,7 @@
str += myLen;
memcpy(str, other, otherLen);
str[otherLen] = '\0';
- return NO_ERROR;
+ return OK;
}
return NO_MEMORY;
}
@@ -382,7 +382,7 @@
mString = str;
}
- return NO_ERROR;
+ return OK;
}
ssize_t String8::find(const char* other, size_t start) const
diff --git a/libutils/Threads.cpp b/libutils/Threads.cpp
index 43ec6c1..64bc402 100644
--- a/libutils/Threads.cpp
+++ b/libutils/Threads.cpp
@@ -379,7 +379,7 @@
{
DWORD dwWaitResult;
dwWaitResult = WaitForSingleObject((HANDLE) mState, INFINITE);
- return dwWaitResult != WAIT_OBJECT_0 ? -1 : NO_ERROR;
+ return dwWaitResult != WAIT_OBJECT_0 ? -1 : OK;
}
void Mutex::unlock()
@@ -506,7 +506,7 @@
ReleaseMutex(condState->internalMutex);
WaitForSingleObject(hMutex, INFINITE);
- return res == WAIT_OBJECT_0 ? NO_ERROR : -1;
+ return res == WAIT_OBJECT_0 ? OK : -1;
}
} WinCondition;
@@ -639,13 +639,15 @@
*/
Thread::Thread(bool canCallJava)
- : mCanCallJava(canCallJava),
- mThread(thread_id_t(-1)),
- mLock("Thread::mLock"),
- mStatus(NO_ERROR),
- mExitPending(false), mRunning(false)
+ : mCanCallJava(canCallJava),
+ mThread(thread_id_t(-1)),
+ mLock("Thread::mLock"),
+ mStatus(OK),
+ mExitPending(false),
+ mRunning(false)
#if defined(__ANDROID__)
- , mTid(-1)
+ ,
+ mTid(-1)
#endif
{
}
@@ -656,7 +658,7 @@
status_t Thread::readyToRun()
{
- return NO_ERROR;
+ return OK;
}
status_t Thread::run(const char* name, int32_t priority, size_t stack)
@@ -672,7 +674,7 @@
// reset status and exitPending to their default value, so we can
// try again after an error happened (either below, or in readyToRun())
- mStatus = NO_ERROR;
+ mStatus = OK;
mExitPending = false;
mThread = thread_id_t(-1);
@@ -700,10 +702,10 @@
}
// Do not refer to mStatus here: The thread is already running (may, in fact
- // already have exited with a valid mStatus result). The NO_ERROR indication
+ // already have exited with a valid mStatus result). The OK indication
// here merely indicates successfully starting the thread and does not
// imply successful termination/execution.
- return NO_ERROR;
+ return OK;
// Exiting scope of mLock is a memory barrier and allows new thread to run
}
@@ -728,7 +730,7 @@
if (first) {
first = false;
self->mStatus = self->readyToRun();
- result = (self->mStatus == NO_ERROR);
+ result = (self->mStatus == OK);
if (result && !self->exitPending()) {
// Binder threads (and maybe others) rely on threadLoop
diff --git a/libutils/Tokenizer.cpp b/libutils/Tokenizer.cpp
index f73d699..98dd2fd 100644
--- a/libutils/Tokenizer.cpp
+++ b/libutils/Tokenizer.cpp
@@ -48,7 +48,7 @@
status_t Tokenizer::open(const String8& filename, Tokenizer** outTokenizer) {
*outTokenizer = nullptr;
- int result = NO_ERROR;
+ int result = OK;
int fd = ::open(filename.string(), O_RDONLY);
if (fd < 0) {
result = -errno;
diff --git a/libutils/VectorImpl.cpp b/libutils/VectorImpl.cpp
index e16f88d..c97a19b 100644
--- a/libutils/VectorImpl.cpp
+++ b/libutils/VectorImpl.cpp
@@ -61,7 +61,7 @@
"[%p] subclasses of VectorImpl must call finish_vector()"
" in their destructor. Leaking %d bytes.",
this, (int)(mCount*mItemSize));
- // We can't call _do_destroy() here because the vtable is already gone.
+ // We can't call _do_destroy() here because the vtable is already gone.
}
VectorImpl& VectorImpl::operator = (const VectorImpl& rhs)
@@ -197,7 +197,7 @@
_do_copy(temp, item, 1);
ssize_t j = i-1;
- void* next = reinterpret_cast<char*>(array) + mItemSize*(i);
+ void* next = reinterpret_cast<char*>(array) + mItemSize*(i);
do {
_do_destroy(next, 1);
_do_copy(next, curr, 1);
@@ -214,13 +214,13 @@
}
i++;
}
-
+
if (temp) {
_do_destroy(temp, 1);
free(temp);
}
}
- return NO_ERROR;
+ return OK;
}
void VectorImpl::pop()
@@ -354,7 +354,7 @@
}
ssize_t VectorImpl::resize(size_t size) {
- ssize_t result = NO_ERROR;
+ ssize_t result = OK;
if (size > mCount) {
result = insertAt(mCount, size - mCount);
} else if (size < mCount) {
@@ -370,7 +370,7 @@
if (sb->release(SharedBuffer::eKeepStorage) == 1) {
_do_destroy(mStorage, mCount);
SharedBuffer::dealloc(sb);
- }
+ }
}
}
@@ -644,13 +644,13 @@
}
}
}
- return NO_ERROR;
+ return OK;
}
ssize_t SortedVectorImpl::merge(const SortedVectorImpl& vector)
{
// we've merging a sorted vector... nice!
- ssize_t err = NO_ERROR;
+ ssize_t err = OK;
if (!vector.isEmpty()) {
// first take care of the case where the vectors are sorted together
if (do_compare(vector.itemLocation(vector.size()-1), arrayImpl()) <= 0) {
@@ -677,4 +677,3 @@
/*****************************************************************************/
}; // namespace android
-
diff --git a/libutils/include/utils/Errors.h b/libutils/include/utils/Errors.h
index 7093a20..7aafe42 100644
--- a/libutils/include/utils/Errors.h
+++ b/libutils/include/utils/Errors.h
@@ -43,8 +43,8 @@
#endif
enum {
- OK = 0, // Everything's swell.
- NO_ERROR = 0, // No errors.
+ OK = 0, // Preferred constant for checking success.
+ NO_ERROR = OK, // Deprecated synonym for `OK`. Prefer `OK` because it doesn't conflict with Windows.
UNKNOWN_ERROR = (-2147483647-1), // INT32_MIN value
diff --git a/libutils/include/utils/Flattenable.h b/libutils/include/utils/Flattenable.h
index 0a19019..9d00602 100644
--- a/libutils/include/utils/Flattenable.h
+++ b/libutils/include/utils/Flattenable.h
@@ -190,11 +190,11 @@
inline status_t flatten(void* buffer, size_t size) const {
if (size < sizeof(T)) return NO_MEMORY;
memcpy(buffer, static_cast<T const*>(this), sizeof(T));
- return NO_ERROR;
+ return OK;
}
inline status_t unflatten(void const* buffer, size_t) {
memcpy(static_cast<T*>(this), buffer, sizeof(T));
- return NO_ERROR;
+ return OK;
}
};
diff --git a/libutils/include/utils/Functor.h b/libutils/include/utils/Functor.h
index c0c8d57..c458699 100644
--- a/libutils/include/utils/Functor.h
+++ b/libutils/include/utils/Functor.h
@@ -29,7 +29,7 @@
public:
Functor() {}
virtual ~Functor() {}
- virtual status_t operator ()(int /*what*/, void* /*data*/) { return NO_ERROR; }
+ virtual status_t operator()(int /*what*/, void* /*data*/) { return OK; }
};
} // namespace android
diff --git a/libutils/include/utils/Tokenizer.h b/libutils/include/utils/Tokenizer.h
index bb25f37..61c5ff7 100644
--- a/libutils/include/utils/Tokenizer.h
+++ b/libutils/include/utils/Tokenizer.h
@@ -37,7 +37,7 @@
/**
* Opens a file and maps it into memory.
*
- * Returns NO_ERROR and a tokenizer for the file, if successful.
+ * Returns OK and a tokenizer for the file, if successful.
* Otherwise returns an error and sets outTokenizer to NULL.
*/
static status_t open(const String8& filename, Tokenizer** outTokenizer);
@@ -45,7 +45,7 @@
/**
* Prepares to tokenize the contents of a string.
*
- * Returns NO_ERROR and a tokenizer for the string, if successful.
+ * Returns OK and a tokenizer for the string, if successful.
* Otherwise returns an error and sets outTokenizer to NULL.
*/
static status_t fromContents(const String8& filename,
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index fd3f602..3308adf 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -23,11 +23,21 @@
"-D_FILE_OFFSET_BITS=64",
],
cppflags: [
- "-Wold-style-cast",
// Incorrectly warns when C++11 empty brace {} initializer is used.
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61489
"-Wno-missing-field-initializers",
],
+
+ // Enable -Wold-style-cast only for non-Windows targets. _islower_l,
+ // _isupper_l etc. in MinGW locale_win32.h (included from
+ // libcxx/include/__locale) has an old-style-cast.
+ target: {
+ not_windows: {
+ cppflags: [
+ "-Wold-style-cast",
+ ],
+ },
+ },
}
cc_defaults {
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 1980dc6..8b68dca 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -822,7 +822,7 @@
}
#ifdef LMKD_LOG_STATS
-static void memory_stat_parse_line(char *line, struct memory_stat *mem_st) {
+static void memory_stat_parse_line(char* line, struct memory_stat* mem_st) {
char key[LINE_MAX + 1];
int64_t value;
@@ -844,17 +844,10 @@
mem_st->swap_in_bytes = value;
}
-static int memory_stat_parse(struct memory_stat *mem_st, int pid, uid_t uid) {
+static int memory_stat_from_cgroup(struct memory_stat* mem_st, int pid, uid_t uid) {
FILE *fp;
char buf[PATH_MAX];
- /*
- * Per-application memory.stat files are available only when
- * per-application memcgs are enabled.
- */
- if (!per_app_memcg)
- return -1;
-
snprintf(buf, sizeof(buf), MEMCG_PROCESS_MEMORY_STAT_PATH, uid, pid);
fp = fopen(buf, "r");
@@ -864,13 +857,50 @@
return -1;
}
- while (fgets(buf, PAGE_SIZE, fp) != NULL ) {
+ while (fgets(buf, PAGE_SIZE, fp) != NULL) {
memory_stat_parse_line(buf, mem_st);
}
fclose(fp);
return 0;
}
+
+static int memory_stat_from_procfs(struct memory_stat* mem_st, int pid) {
+ char path[PATH_MAX];
+ char buffer[PROC_STAT_BUFFER_SIZE];
+ int fd, ret;
+
+ snprintf(path, sizeof(path), PROC_STAT_FILE_PATH, pid);
+ if ((fd = open(path, O_RDONLY | O_CLOEXEC)) < 0) {
+ ALOGE("%s open failed: %s", path, strerror(errno));
+ return -1;
+ }
+
+ ret = read(fd, buffer, sizeof(buffer));
+ if (ret < 0) {
+ ALOGE("%s read failed: %s", path, strerror(errno));
+ close(fd);
+ return -1;
+ }
+ close(fd);
+
+ // field 10 is pgfault
+ // field 12 is pgmajfault
+ // field 24 is rss_in_pages
+ int64_t pgfault = 0, pgmajfault = 0, rss_in_pages = 0;
+ if (sscanf(buffer,
+ "%*u %*s %*s %*d %*d %*d %*d %*d %*d %" SCNd64 " %*d "
+ "%" SCNd64 " %*d %*u %*u %*d %*d %*d %*d %*d %*d "
+ "%*d %*d %" SCNd64 "",
+ &pgfault, &pgmajfault, &rss_in_pages) != 3) {
+ return -1;
+ }
+ mem_st->pgfault = pgfault;
+ mem_st->pgmajfault = pgmajfault;
+ mem_st->rss_in_bytes = (rss_in_pages * PAGE_SIZE);
+
+ return 0;
+}
#endif
/* /prop/zoneinfo parsing routines */
@@ -1125,7 +1155,11 @@
#ifdef LMKD_LOG_STATS
if (enable_stats_log) {
- memory_stat_parse_result = memory_stat_parse(&mem_st, pid, uid);
+ if (per_app_memcg) {
+ memory_stat_parse_result = memory_stat_from_cgroup(&mem_st, pid, uid);
+ } else {
+ memory_stat_parse_result = memory_stat_from_procfs(&mem_st, pid);
+ }
}
#endif
@@ -1148,6 +1182,9 @@
stats_write_lmk_kill_occurred(log_ctx, LMK_KILL_OCCURRED, uid, taskname,
procp->oomadj, mem_st.pgfault, mem_st.pgmajfault, mem_st.rss_in_bytes,
mem_st.cache_in_bytes, mem_st.swap_in_bytes);
+ } else if (enable_stats_log) {
+ stats_write_lmk_kill_occurred(log_ctx, LMK_KILL_OCCURRED, uid, taskname, procp->oomadj,
+ -1, -1, tasksize * BYTES_IN_KILOBYTE, -1, -1);
}
#endif
return tasksize;
diff --git a/lmkd/statslog.h b/lmkd/statslog.h
index edebb19..8458480 100644
--- a/lmkd/statslog.h
+++ b/lmkd/statslog.h
@@ -67,6 +67,9 @@
};
#define MEMCG_PROCESS_MEMORY_STAT_PATH "/dev/memcg/apps/uid_%u/pid_%u/memory.stat"
+#define PROC_STAT_FILE_PATH "/proc/%d/stat"
+#define PROC_STAT_BUFFER_SIZE 1024
+#define BYTES_IN_KILOBYTE 1024
/**
* Logs the change in LMKD state which is used as start/stop boundaries for logging
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 6a6a8f9..9aaad8f 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -398,6 +398,10 @@
class_start early_hal
on post-fs-data
+ # Start checkpoint before we touch data
+ start vold
+ exec - system system -- /system/bin/vdc checkpoint prepareCheckpoint
+
# We chown/chmod /data again so because mount is run as root + defaults
chown system system /data
chmod 0771 /data
@@ -405,8 +409,6 @@
restorecon /data
# Make sure we have the device encryption key.
- start vold
- exec - system system -- /system/bin/vdc checkpoint prepareDriveForCheckpoint /data
installkey /data
# Start bootcharting as soon as possible after the data partition is
diff --git a/storaged/storaged_service.cpp b/storaged/storaged_service.cpp
index 17ea25b..45f1d4d 100644
--- a/storaged/storaged_service.cpp
+++ b/storaged/storaged_service.cpp
@@ -161,7 +161,7 @@
storaged_sp->update_uid_io_interval(time_window);
}
- return NO_ERROR;
+ return OK;
}
binder::Status StoragedService::onUserStarted(int32_t userId) {
diff --git a/storaged/uid_info.cpp b/storaged/uid_info.cpp
index 58e3fd2..0f718de 100644
--- a/storaged/uid_info.cpp
+++ b/storaged/uid_info.cpp
@@ -32,7 +32,7 @@
parcel->writeCString(task_it.second.comm.c_str());
parcel->write(&task_it.second.io, sizeof(task_it.second.io));
}
- return NO_ERROR;
+ return OK;
}
status_t UidInfo::readFromParcel(const Parcel* parcel) {
@@ -48,5 +48,5 @@
parcel->read(&task.io, sizeof(task.io));
tasks[task.pid] = task;
}
- return NO_ERROR;
+ return OK;
}