Merge "libbacktrace: Fix clang-tidy warning"
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index f00129a..c744fe4 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -136,11 +136,27 @@
UpdateState state = ReadUpdateState(file.get());
if (state == UpdateState::None) return true;
- if (state != UpdateState::Initiated) {
- LOG(ERROR) << "Cannot cancel update after it has completed or started merging";
- return false;
+
+ if (state == UpdateState::Initiated) {
+ LOG(INFO) << "Update has been initiated, now canceling";
+ return RemoveAllUpdateState(file.get());
}
- return RemoveAllUpdateState(file.get());
+
+ if (state == UpdateState::Unverified) {
+ // We completed an update, but it can still be canceled if we haven't booted into it.
+ auto boot_file = GetSnapshotBootIndicatorPath();
+ std::string contents;
+ if (!android::base::ReadFileToString(boot_file, &contents)) {
+ PLOG(WARNING) << "Cannot read " << boot_file << ", proceed to canceling the update:";
+ return RemoveAllUpdateState(file.get());
+ }
+ if (device_->GetSlotSuffix() == contents) {
+ LOG(INFO) << "Canceling a previously completed update";
+ return RemoveAllUpdateState(file.get());
+ }
+ }
+ LOG(ERROR) << "Cannot cancel update after it has completed or started merging";
+ return false;
}
bool SnapshotManager::RemoveAllUpdateState(LockedFile* lock) {
diff --git a/init/README.ueventd.md b/init/README.ueventd.md
index c592c37..7e90e0c 100644
--- a/init/README.ueventd.md
+++ b/init/README.ueventd.md
@@ -110,3 +110,9 @@
For boot time purposes, this is done in parallel across a set of child processes. `ueventd.cpp` in
this directory contains documentation on how the parallelization is done.
+
+There is an option to parallelize the restorecon function during cold boot as well. This should only
+be done for devices that do not use genfscon, which is the recommended method for labeling sysfs
+nodes. To enable this option, use the below line in a ueventd.rc script:
+
+ parallel_restorecon enabled
diff --git a/init/interface_utils.cpp b/init/interface_utils.cpp
index a54860f..ddbacd7 100644
--- a/init/interface_utils.cpp
+++ b/init/interface_utils.cpp
@@ -77,6 +77,12 @@
const InterfaceInheritanceHierarchyMap& hierarchy) {
std::set<FQName> interface_fqnames;
for (const std::string& instance : instances) {
+ // There is insufficient build-time information on AIDL interfaces to check them here
+ // TODO(b/139307527): Rework how services store interfaces to avoid excess string parsing
+ if (base::Split(instance, "/")[0] == "aidl") {
+ continue;
+ }
+
FqInstance fqinstance;
if (!fqinstance.setTo(instance)) {
return Error() << "Unable to parse interface instance '" << instance << "'";
diff --git a/init/service_parser.cpp b/init/service_parser.cpp
index dd552fb..543be23 100644
--- a/init/service_parser.cpp
+++ b/init/service_parser.cpp
@@ -145,17 +145,21 @@
const std::string& interface_name = args[1];
const std::string& instance_name = args[2];
- FQName fq_name;
- if (!FQName::parse(interface_name, &fq_name)) {
- return Error() << "Invalid fully-qualified name for interface '" << interface_name << "'";
- }
+ // AIDL services don't use fully qualified names and instead just use "interface aidl <name>"
+ if (interface_name != "aidl") {
+ FQName fq_name;
+ if (!FQName::parse(interface_name, &fq_name)) {
+ return Error() << "Invalid fully-qualified name for interface '" << interface_name
+ << "'";
+ }
- if (!fq_name.isFullyQualified()) {
- return Error() << "Interface name not fully-qualified '" << interface_name << "'";
- }
+ if (!fq_name.isFullyQualified()) {
+ return Error() << "Interface name not fully-qualified '" << interface_name << "'";
+ }
- if (fq_name.isValidValueName()) {
- return Error() << "Interface name must not be a value name '" << interface_name << "'";
+ if (fq_name.isValidValueName()) {
+ return Error() << "Interface name must not be a value name '" << interface_name << "'";
+ }
}
const std::string fullname = interface_name + "/" + instance_name;
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index cffc1b9..6741e2a 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -113,10 +113,12 @@
class ColdBoot {
public:
ColdBoot(UeventListener& uevent_listener,
- std::vector<std::unique_ptr<UeventHandler>>& uevent_handlers)
+ std::vector<std::unique_ptr<UeventHandler>>& uevent_handlers,
+ bool enable_parallel_restorecon)
: uevent_listener_(uevent_listener),
uevent_handlers_(uevent_handlers),
- num_handler_subprocesses_(std::thread::hardware_concurrency() ?: 4) {}
+ num_handler_subprocesses_(std::thread::hardware_concurrency() ?: 4),
+ enable_parallel_restorecon_(enable_parallel_restorecon) {}
void Run();
@@ -132,6 +134,8 @@
std::vector<std::unique_ptr<UeventHandler>>& uevent_handlers_;
unsigned int num_handler_subprocesses_;
+ bool enable_parallel_restorecon_;
+
std::vector<Uevent> uevent_queue_;
std::set<pid_t> subprocess_pids_;
@@ -155,7 +159,6 @@
selinux_android_restorecon(dir.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE);
}
- _exit(EXIT_SUCCESS);
}
void ColdBoot::GenerateRestoreCon(const std::string& directory) {
@@ -195,7 +198,10 @@
if (pid == 0) {
UeventHandlerMain(i, num_handler_subprocesses_);
- RestoreConHandler(i, num_handler_subprocesses_);
+ if (enable_parallel_restorecon_) {
+ RestoreConHandler(i, num_handler_subprocesses_);
+ }
+ _exit(EXIT_SUCCESS);
}
subprocess_pids_.emplace(pid);
@@ -240,14 +246,20 @@
RegenerateUevents();
- selinux_android_restorecon("/sys", 0);
- selinux_android_restorecon("/sys/devices", 0);
- GenerateRestoreCon("/sys");
- // takes long time for /sys/devices, parallelize it
- GenerateRestoreCon("/sys/devices");
+ if (enable_parallel_restorecon_) {
+ selinux_android_restorecon("/sys", 0);
+ selinux_android_restorecon("/sys/devices", 0);
+ GenerateRestoreCon("/sys");
+ // takes long time for /sys/devices, parallelize it
+ GenerateRestoreCon("/sys/devices");
+ }
ForkSubProcesses();
+ if (!enable_parallel_restorecon_) {
+ selinux_android_restorecon("/sys", SELINUX_ANDROID_RESTORECON_RECURSE);
+ }
+
WaitForSubProcesses();
android::base::SetProperty(kColdBootDoneProp, "true");
@@ -293,7 +305,8 @@
UeventListener uevent_listener(ueventd_configuration.uevent_socket_rcvbuf_size);
if (!android::base::GetBoolProperty(kColdBootDoneProp, false)) {
- ColdBoot cold_boot(uevent_listener, uevent_handlers);
+ ColdBoot cold_boot(uevent_listener, uevent_handlers,
+ ueventd_configuration.enable_parallel_restorecon);
cold_boot.Run();
}
diff --git a/init/ueventd_parser.cpp b/init/ueventd_parser.cpp
index 8ee0cce..1ca1715 100644
--- a/init/ueventd_parser.cpp
+++ b/init/ueventd_parser.cpp
@@ -88,18 +88,17 @@
return {};
}
-Result<void> ParseModaliasHandlingLine(std::vector<std::string>&& args,
- bool* enable_modalias_handling) {
+Result<void> ParseEnabledDisabledLine(std::vector<std::string>&& args, bool* feature) {
if (args.size() != 2) {
- return Error() << "modalias_handling lines take exactly one parameter";
+ return Error() << args[0] << " lines take exactly one parameter";
}
if (args[1] == "enabled") {
- *enable_modalias_handling = true;
+ *feature = true;
} else if (args[1] == "disabled") {
- *enable_modalias_handling = false;
+ *feature = false;
} else {
- return Error() << "modalias_handling takes either 'enabled' or 'disabled' as a parameter";
+ return Error() << args[0] << " takes either 'enabled' or 'disabled' as a parameter";
}
return {};
@@ -213,11 +212,14 @@
std::bind(ParseFirmwareDirectoriesLine, _1,
&ueventd_configuration.firmware_directories));
parser.AddSingleLineParser("modalias_handling",
- std::bind(ParseModaliasHandlingLine, _1,
+ std::bind(ParseEnabledDisabledLine, _1,
&ueventd_configuration.enable_modalias_handling));
parser.AddSingleLineParser("uevent_socket_rcvbuf_size",
std::bind(ParseUeventSocketRcvbufSizeLine, _1,
&ueventd_configuration.uevent_socket_rcvbuf_size));
+ parser.AddSingleLineParser("parallel_restorecon",
+ std::bind(ParseEnabledDisabledLine, _1,
+ &ueventd_configuration.enable_parallel_restorecon));
for (const auto& config : configs) {
parser.ParseConfig(config);
diff --git a/init/ueventd_parser.h b/init/ueventd_parser.h
index d476dec..b54dba8 100644
--- a/init/ueventd_parser.h
+++ b/init/ueventd_parser.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _INIT_UEVENTD_PARSER_H
-#define _INIT_UEVENTD_PARSER_H
+#pragma once
#include <string>
#include <vector>
@@ -32,11 +31,10 @@
std::vector<std::string> firmware_directories;
bool enable_modalias_handling = false;
size_t uevent_socket_rcvbuf_size = 0;
+ bool enable_parallel_restorecon = false;
};
UeventdConfiguration ParseConfig(const std::vector<std::string>& configs);
} // namespace init
} // namespace android
-
-#endif
diff --git a/init/ueventd_parser_test.cpp b/init/ueventd_parser_test.cpp
index 9c1cedf..885e79d 100644
--- a/init/ueventd_parser_test.cpp
+++ b/init/ueventd_parser_test.cpp
@@ -147,6 +147,24 @@
TestUeventdFile(ueventd_file, {{}, {}, {}, {}, false, 8 * 1024 * 1024});
}
+TEST(ueventd_parser, EnabledDisabledLines) {
+ auto ueventd_file = R"(
+modalias_handling enabled
+parallel_restorecon enabled
+modalias_handling disabled
+)";
+
+ TestUeventdFile(ueventd_file, {{}, {}, {}, {}, false, 0, true});
+
+ auto ueventd_file2 = R"(
+parallel_restorecon enabled
+modalias_handling enabled
+parallel_restorecon disabled
+)";
+
+ TestUeventdFile(ueventd_file2, {{}, {}, {}, {}, true, 0, false});
+}
+
TEST(ueventd_parser, AllTogether) {
auto ueventd_file = R"(
@@ -179,6 +197,8 @@
firmware_directories /more
uevent_socket_rcvbuf_size 6M
+modalias_handling enabled
+parallel_restorecon enabled
#ending comment
)";
@@ -211,7 +231,7 @@
size_t uevent_socket_rcvbuf_size = 6 * 1024 * 1024;
TestUeventdFile(ueventd_file, {subsystems, sysfs_permissions, permissions, firmware_directories,
- false, uevent_socket_rcvbuf_size});
+ true, uevent_socket_rcvbuf_size, true});
}
// All of these lines are ill-formed, so test that there is 0 output.
@@ -230,6 +250,13 @@
subsystem #no name
+modalias_handling
+modalias_handling enabled enabled
+modalias_handling blah
+
+parallel_restorecon
+parallel_restorecon enabled enabled
+parallel_restorecon blah
)";
TestUeventdFile(ueventd_file, {});
diff --git a/libion/tests/Android.bp b/libion/tests/Android.bp
index d3b4688..5600702 100644
--- a/libion/tests/Android.bp
+++ b/libion/tests/Android.bp
@@ -24,7 +24,8 @@
srcs: [
"allocate_test.cpp",
"exit_test.cpp",
- "heap_query.cpp",
+ "heap_query.cpp",
+ "system_heap.cpp",
"invalid_values_test.cpp",
"ion_test_fixture.cpp",
"map_test.cpp",
diff --git a/libion/tests/system_heap.cpp b/libion/tests/system_heap.cpp
new file mode 100644
index 0000000..fb63888
--- /dev/null
+++ b/libion/tests/system_heap.cpp
@@ -0,0 +1,44 @@
+/*
+ * 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 <unistd.h>
+
+#include <gtest/gtest.h>
+#include <iostream>
+
+#include <ion/ion.h>
+#include "ion_test_fixture.h"
+
+class SystemHeap : public IonTest {};
+
+TEST_F(SystemHeap, Presence) {
+ bool system_heap_found = false;
+ for (const auto& heap : ion_heaps) {
+ if (heap.type == ION_HEAP_TYPE_SYSTEM) {
+ system_heap_found = true;
+ EXPECT_TRUE((1 << heap.heap_id) & ION_HEAP_SYSTEM_MASK);
+ }
+ }
+ // We now expect the system heap to exist from Android
+ ASSERT_TRUE(system_heap_found);
+}
+
+TEST_F(SystemHeap, Allocate) {
+ int fd;
+ ASSERT_EQ(0, ion_alloc_fd(ionfd, getpagesize(), 0, ION_HEAP_SYSTEM_MASK, 0, &fd));
+ ASSERT_TRUE(fd != 0);
+ ASSERT_EQ(close(fd), 0); // free the buffer
+}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 0d3d4db..58db96c 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -445,7 +445,6 @@
mark_post_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