Merge changes from topic "apex_remount"
* changes:
adbd: replace remount_service with an exec of /system/bin/remount.
Move remount to PRODUCT_PACKAGES_DEBUG.
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index e5a4917..9ebab74 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -248,6 +248,12 @@
prop_port = android::base::GetProperty("persist.adb.tcp.port", "");
}
+#if !defined(__ANDROID__)
+ if (prop_port.empty() && getenv("ADBD_PORT")) {
+ prop_port = getenv("ADBD_PORT");
+ }
+#endif
+
int port;
if (sscanf(prop_port.c_str(), "%d", &port) == 1 && port > 0) {
D("using port=%d", port);
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index 1a5b435..7e35a2f 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -195,7 +195,10 @@
return false;
}
- InterceptRequest req = {.pid = pid, .dump_type = dump_type};
+ InterceptRequest req = {
+ .dump_type = dump_type,
+ .pid = pid,
+ };
if (!set_timeout(sockfd)) {
PLOG(ERROR) << "libdebugger_client: failed to set timeout";
return false;
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index c9a193c..99729dc 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -101,7 +101,10 @@
FAIL() << "failed to contact tombstoned: " << strerror(errno);
}
- InterceptRequest req = {.pid = target_pid, .dump_type = intercept_type};
+ InterceptRequest req = {
+ .dump_type = intercept_type,
+ .pid = target_pid,
+ };
unique_fd output_pipe_write;
if (!Pipe(output_fd, &output_pipe_write)) {
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 598ea85..b90ca80 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -525,8 +525,8 @@
log_signal_summary(info);
debugger_thread_info thread_info = {
- .pseudothread_tid = -1,
.crashing_tid = __gettid(),
+ .pseudothread_tid = -1,
.siginfo = info,
.ucontext = context,
.abort_msg = reinterpret_cast<uintptr_t>(abort_message),
diff --git a/debuggerd/libdebuggerd/test/tombstone_test.cpp b/debuggerd/libdebuggerd/test/tombstone_test.cpp
index 88c206f..9dea7ac 100644
--- a/debuggerd/libdebuggerd/test/tombstone_test.cpp
+++ b/debuggerd/libdebuggerd/test/tombstone_test.cpp
@@ -345,9 +345,9 @@
TEST_F(TombstoneTest, dump_thread_info_uid) {
dump_thread_info(&log_, ThreadInfo{.uid = 1,
- .pid = 2,
.tid = 3,
.thread_name = "some_thread",
+ .pid = 2,
.process_name = "some_process"});
std::string expected = "pid: 2, tid: 3, name: some_thread >>> some_process <<<\nuid: 1\n";
ASSERT_STREQ(expected.c_str(), amfd_data_.c_str());
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index c1a8dae..2ff5243 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -686,13 +686,14 @@
if (entries.empty()) {
FstabEntry entry = {
.blk_device = partition,
+ // .logical_partition_name is required to look up AVB Hashtree descriptors.
+ .logical_partition_name = "system",
.mount_point = mount_point,
.fs_type = "ext4",
.flags = MS_RDONLY,
.fs_options = "barrier=1",
.avb_keys = kGsiKeys,
- // .logical_partition_name is required to look up AVB Hashtree descriptors.
- .logical_partition_name = "system"};
+ };
entry.fs_mgr_flags.wait = true;
entry.fs_mgr_flags.logical = true;
entry.fs_mgr_flags.first_stage_mount = true;
diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp
index dd95a5e..3ce909e 100644
--- a/fs_mgr/libdm/Android.bp
+++ b/fs_mgr/libdm/Android.bp
@@ -79,3 +79,19 @@
require_root: true,
test_min_api_level: 29,
}
+
+cc_fuzz {
+ name: "dm_table_fuzzer",
+ defaults: ["fs_mgr_defaults"],
+ srcs: [
+ "dm_linear_fuzzer.cpp",
+ "test_util.cpp",
+ ],
+ static_libs: [
+ "libdm",
+ "libbase",
+ "libext2_uuid",
+ "libfs_mgr",
+ "liblog",
+ ],
+}
diff --git a/fs_mgr/libdm/dm_linear_fuzzer.cpp b/fs_mgr/libdm/dm_linear_fuzzer.cpp
new file mode 100644
index 0000000..b119635
--- /dev/null
+++ b/fs_mgr/libdm/dm_linear_fuzzer.cpp
@@ -0,0 +1,139 @@
+/*
+ * 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 <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <chrono>
+
+#include <android-base/file.h>
+#include <android-base/unique_fd.h>
+#include <libdm/dm_table.h>
+#include <libdm/loop_control.h>
+
+#include "test_util.h"
+
+using namespace android;
+using namespace android::base;
+using namespace android::dm;
+using namespace std;
+using namespace std::chrono_literals;
+
+/*
+ * This test aims at making the library crash, so these functions are not
+ * really useful.
+ * Keeping them here for future use.
+ */
+template <class T, class C>
+void ASSERT_EQ(const T& /*a*/, const C& /*b*/) {
+ // if (a != b) {}
+}
+
+template <class T>
+void ASSERT_FALSE(const T& /*a*/) {
+ // if (a) {}
+}
+
+template <class T, class C>
+void ASSERT_GE(const T& /*a*/, const C& /*b*/) {
+ // if (a < b) {}
+}
+
+template <class T, class C>
+void ASSERT_NE(const T& /*a*/, const C& /*b*/) {
+ // if (a == b) {}
+}
+
+template <class T>
+void ASSERT_TRUE(const T& /*a*/) {
+ // if (!a) {}
+}
+
+template <class T, class C>
+void EXPECT_EQ(const T& a, const C& b) {
+ ASSERT_EQ(a, b);
+}
+
+template <class T>
+void EXPECT_TRUE(const T& a) {
+ ASSERT_TRUE(a);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ uint64_t val[6];
+
+ if (size != sizeof(*val)) {
+ return 0;
+ }
+
+ memcpy(&val, &data[0], sizeof(*val));
+
+ unique_fd tmp1(CreateTempFile("file_1", 4096));
+ ASSERT_GE(tmp1, 0);
+ unique_fd tmp2(CreateTempFile("file_2", 4096));
+ ASSERT_GE(tmp2, 0);
+
+ LoopDevice loop_a(tmp1, 10s);
+ ASSERT_TRUE(loop_a.valid());
+ LoopDevice loop_b(tmp2, 10s);
+ ASSERT_TRUE(loop_b.valid());
+
+ // Define a 2-sector device, with each sector mapping to the first sector
+ // of one of our loop devices.
+ DmTable table;
+ ASSERT_TRUE(table.Emplace<DmTargetLinear>(val[0], val[1], loop_a.device(), val[2]));
+ ASSERT_TRUE(table.Emplace<DmTargetLinear>(val[3], val[4], loop_b.device(), val[5]));
+ ASSERT_TRUE(table.valid());
+ ASSERT_EQ(2u, table.num_sectors());
+
+ TempDevice dev("libdm-test-dm-linear", table);
+ ASSERT_TRUE(dev.valid());
+ ASSERT_FALSE(dev.path().empty());
+
+ auto& dm = DeviceMapper::Instance();
+
+ dev_t dev_number;
+ ASSERT_TRUE(dm.GetDeviceNumber(dev.name(), &dev_number));
+ ASSERT_NE(dev_number, 0);
+
+ std::string dev_string;
+ ASSERT_TRUE(dm.GetDeviceString(dev.name(), &dev_string));
+ ASSERT_FALSE(dev_string.empty());
+
+ // Test GetTableStatus.
+ vector<DeviceMapper::TargetInfo> targets;
+ ASSERT_TRUE(dm.GetTableStatus(dev.name(), &targets));
+ ASSERT_EQ(targets.size(), 2);
+ EXPECT_EQ(strcmp(targets[0].spec.target_type, "linear"), 0);
+ EXPECT_TRUE(targets[0].data.empty());
+ EXPECT_EQ(targets[0].spec.sector_start, 0);
+ EXPECT_EQ(targets[0].spec.length, 1);
+ EXPECT_EQ(strcmp(targets[1].spec.target_type, "linear"), 0);
+ EXPECT_TRUE(targets[1].data.empty());
+ EXPECT_EQ(targets[1].spec.sector_start, 1);
+ EXPECT_EQ(targets[1].spec.length, 1);
+
+ // Test GetTargetType().
+ EXPECT_EQ(DeviceMapper::GetTargetType(targets[0].spec), std::string{"linear"});
+ EXPECT_EQ(DeviceMapper::GetTargetType(targets[1].spec), std::string{"linear"});
+
+ // Normally the TestDevice destructor would delete this, but at least one
+ // test should ensure that device deletion works.
+ ASSERT_TRUE(dev.Destroy());
+
+ return 0;
+}
diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp
index 39c908d..ed2fa83 100644
--- a/fs_mgr/libdm/dm_test.cpp
+++ b/fs_mgr/libdm/dm_test.cpp
@@ -47,50 +47,6 @@
ASSERT_TRUE(dm.GetTargetByName("linear", &info));
}
-// Helper to ensure that device mapper devices are released.
-class TempDevice {
- public:
- TempDevice(const std::string& name, const DmTable& table)
- : dm_(DeviceMapper::Instance()), name_(name), valid_(false) {
- valid_ = dm_.CreateDevice(name, table, &path_, 5s);
- }
- TempDevice(TempDevice&& other) noexcept
- : dm_(other.dm_), name_(other.name_), path_(other.path_), valid_(other.valid_) {
- other.valid_ = false;
- }
- ~TempDevice() {
- if (valid_) {
- dm_.DeleteDevice(name_);
- }
- }
- bool Destroy() {
- if (!valid_) {
- return false;
- }
- valid_ = false;
- return dm_.DeleteDevice(name_);
- }
- std::string path() const { return path_; }
- const std::string& name() const { return name_; }
- bool valid() const { return valid_; }
-
- TempDevice(const TempDevice&) = delete;
- TempDevice& operator=(const TempDevice&) = delete;
-
- TempDevice& operator=(TempDevice&& other) noexcept {
- name_ = other.name_;
- valid_ = other.valid_;
- other.valid_ = false;
- return *this;
- }
-
- private:
- DeviceMapper& dm_;
- std::string name_;
- std::string path_;
- bool valid_;
-};
-
TEST(libdm, DmLinear) {
unique_fd tmp1(CreateTempFile("file_1", 4096));
ASSERT_GE(tmp1, 0);
diff --git a/fs_mgr/libdm/test_util.h b/fs_mgr/libdm/test_util.h
index 96b051c..6671364 100644
--- a/fs_mgr/libdm/test_util.h
+++ b/fs_mgr/libdm/test_util.h
@@ -20,8 +20,12 @@
#include <android-base/unique_fd.h>
#include <stddef.h>
+#include <chrono>
#include <string>
+#include <libdm/dm.h>
+#include <libdm/dm_table.h>
+
namespace android {
namespace dm {
@@ -29,6 +33,50 @@
// created with a fixed size.
android::base::unique_fd CreateTempFile(const std::string& name, size_t size);
+// Helper to ensure that device mapper devices are released.
+class TempDevice {
+ public:
+ TempDevice(const std::string& name, const DmTable& table)
+ : dm_(DeviceMapper::Instance()), name_(name), valid_(false) {
+ valid_ = dm_.CreateDevice(name, table, &path_, std::chrono::seconds(5));
+ }
+ TempDevice(TempDevice&& other) noexcept
+ : dm_(other.dm_), name_(other.name_), path_(other.path_), valid_(other.valid_) {
+ other.valid_ = false;
+ }
+ ~TempDevice() {
+ if (valid_) {
+ dm_.DeleteDevice(name_);
+ }
+ }
+ bool Destroy() {
+ if (!valid_) {
+ return false;
+ }
+ valid_ = false;
+ return dm_.DeleteDevice(name_);
+ }
+ std::string path() const { return path_; }
+ const std::string& name() const { return name_; }
+ bool valid() const { return valid_; }
+
+ TempDevice(const TempDevice&) = delete;
+ TempDevice& operator=(const TempDevice&) = delete;
+
+ TempDevice& operator=(TempDevice&& other) noexcept {
+ name_ = other.name_;
+ valid_ = other.valid_;
+ other.valid_ = false;
+ return *this;
+ }
+
+ private:
+ DeviceMapper& dm_;
+ std::string name_;
+ std::string path_;
+ bool valid_;
+};
+
} // namespace dm
} // namespace android
diff --git a/fs_mgr/libfs_avb/tests/avb_util_test.cpp b/fs_mgr/libfs_avb/tests/avb_util_test.cpp
index 0d342d3..784eb9c 100644
--- a/fs_mgr/libfs_avb/tests/avb_util_test.cpp
+++ b/fs_mgr/libfs_avb/tests/avb_util_test.cpp
@@ -101,10 +101,10 @@
TEST_F(AvbUtilTest, DeriveAvbPartitionName) {
// The fstab_entry to test.
FstabEntry fstab_entry = {
- .blk_device = "/dev/block/dm-1", // a dm-linear device (logical)
- .mount_point = "/system",
- .fs_type = "ext4",
- .logical_partition_name = "system",
+ .blk_device = "/dev/block/dm-1", // a dm-linear device (logical)
+ .logical_partition_name = "system",
+ .mount_point = "/system",
+ .fs_type = "ext4",
};
// Logical partitions.
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index 7405039..54350a5 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -171,7 +171,8 @@
std::unique_ptr<MetadataBuilder> MetadataBuilder::NewForUpdate(const IPartitionOpener& opener,
const std::string& source_partition,
uint32_t source_slot_number,
- uint32_t target_slot_number) {
+ uint32_t target_slot_number,
+ bool always_keep_source_slot) {
auto metadata = ReadMetadata(opener, source_partition, source_slot_number);
if (!metadata) {
return nullptr;
@@ -189,7 +190,8 @@
}
}
- if (IPropertyFetcher::GetInstance()->GetBoolProperty("ro.virtual_ab.enabled", false)) {
+ if (IPropertyFetcher::GetInstance()->GetBoolProperty("ro.virtual_ab.enabled", false) &&
+ !always_keep_source_slot) {
if (!UpdateMetadataForInPlaceSnapshot(metadata.get(), source_slot_number,
target_slot_number)) {
return nullptr;
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index b43ccf0..1e9d636 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -209,10 +209,13 @@
// metadata may not have the target slot's devices listed yet, in which
// case, it is automatically upgraded to include all available block
// devices.
+ // If |always_keep_source_slot| is set, on a Virtual A/B device, source slot
+ // partitions are kept. This is useful when applying a downgrade package.
static std::unique_ptr<MetadataBuilder> NewForUpdate(const IPartitionOpener& opener,
const std::string& source_partition,
uint32_t source_slot_number,
- uint32_t target_slot_number);
+ uint32_t target_slot_number,
+ bool always_keep_source_slot = false);
// Import an existing table for modification. If the table is not valid, for
// example it contains duplicate partition names, then nullptr is returned.
diff --git a/fs_mgr/libsnapshot/dm_snapshot_internals.h b/fs_mgr/libsnapshot/dm_snapshot_internals.h
new file mode 100644
index 0000000..4903de1
--- /dev/null
+++ b/fs_mgr/libsnapshot/dm_snapshot_internals.h
@@ -0,0 +1,133 @@
+// 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 <stdint.h>
+
+#include <vector>
+
+namespace android {
+namespace snapshot {
+
+class DmSnapCowSizeCalculator {
+ public:
+ DmSnapCowSizeCalculator(unsigned int sector_bytes, unsigned int chunk_sectors)
+ : sector_bytes_(sector_bytes),
+ chunk_sectors_(chunk_sectors),
+ exceptions_per_chunk(chunk_sectors_ * sector_bytes_ / (64 * 2 / 8)) {}
+
+ void WriteByte(uint64_t address) { WriteSector(address / sector_bytes_); }
+ void WriteSector(uint64_t sector) { WriteChunk(sector / chunk_sectors_); }
+ void WriteChunk(uint64_t chunk_id) {
+ if (modified_chunks_.size() <= chunk_id) {
+ modified_chunks_.resize(chunk_id + 1, false);
+ }
+ modified_chunks_[chunk_id] = true;
+ }
+
+ uint64_t cow_size_bytes() const { return cow_size_sectors() * sector_bytes_; }
+ uint64_t cow_size_sectors() const { return cow_size_chunks() * chunk_sectors_; }
+
+ /*
+ * The COW device has a precise internal structure as follows:
+ *
+ * - header (1 chunk)
+ * - #0 map and chunks
+ * - map (1 chunk)
+ * - chunks addressable by previous map (exceptions_per_chunk)
+ * - #1 map and chunks
+ * - map (1 chunk)
+ * - chunks addressable by previous map (exceptions_per_chunk)
+ * ...
+ * - #n: map and chunks
+ * - map (1 chunk)
+ * - chunks addressable by previous map (exceptions_per_chunk)
+ * - 1 extra chunk
+ */
+ uint64_t cow_size_chunks() const {
+ uint64_t modified_chunks_count = 0;
+ uint64_t cow_chunks = 0;
+
+ for (const auto& c : modified_chunks_) {
+ if (c) {
+ ++modified_chunks_count;
+ }
+ }
+
+ /* disk header + padding = 1 chunk */
+ cow_chunks += 1;
+
+ /* snapshot modified chunks */
+ cow_chunks += modified_chunks_count;
+
+ /* snapshot chunks index metadata */
+ cow_chunks += 1 + modified_chunks_count / exceptions_per_chunk;
+
+ return cow_chunks;
+ }
+
+ private:
+ /*
+ * Size of each sector in bytes.
+ */
+ const uint64_t sector_bytes_;
+
+ /*
+ * Size of each chunk in sectors.
+ */
+ const uint64_t chunk_sectors_;
+
+ /*
+ * The COW device stores tables to map the modified chunks. Each table
+ * has the size of exactly 1 chunk.
+ * Each row of the table (also called exception in the kernel) contains two
+ * 64 bit indices to identify the corresponding chunk, and this 128 bit row
+ * size is a constant.
+ * The number of exceptions that each table can contain determines the
+ * number of data chunks that separate two consecutive tables. This value
+ * is then fundamental to compute the space overhead introduced by the
+ * tables in COW devices.
+ */
+ const uint64_t exceptions_per_chunk;
+
+ /*
+ * |modified_chunks_| is a container that keeps trace of the modified
+ * chunks.
+ * Multiple options were considered when choosing the most appropriate data
+ * structure for this container. Here follows a summary of why vector<bool>
+ * has been chosen, taking as a reference a snapshot partition of 4 GiB and
+ * chunk size of 4 KiB.
+ * - std::set<uint64_t> is very space-efficient for a small number of
+ * operations, but if the whole snapshot is changed, it would need to
+ * store
+ * 4 GiB / 4 KiB * (64 bit / 8) = 8 MiB
+ * just for the data, plus the additional data overhead for the red-black
+ * tree used for data sorting (if each rb-tree element stores 3 address
+ * and the word-aligne color, the total size grows to 32 MiB).
+ * - std::bitset<N> is not a good fit because requires a priori knowledge,
+ * at compile time, of the bitset size.
+ * - std::vector<bool> is a special case of vector, which uses a data
+ * compression that allows reducing the space utilization of each element
+ * to 1 bit. In detail, this data structure is composed of a resizable
+ * array of words, each of them representing a bitmap. On a 64 bit
+ * device, modifying the whole 4 GiB snapshot grows this container up to
+ * 4 * GiB / 4 KiB / 64 = 64 KiB
+ * that, even if is the same space requirement to change a single byte at
+ * the highest address of the snapshot, is a very affordable space
+ * requirement.
+ */
+ std::vector<bool> modified_chunks_;
+};
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/partition_cow_creator_test.cpp b/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
index feb3c2d..f683f5b 100644
--- a/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
+++ b/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
@@ -17,6 +17,7 @@
#include <liblp/builder.h>
#include <liblp/property_fetcher.h>
+#include "dm_snapshot_internals.h"
#include "partition_cow_creator.h"
#include "test_helpers.h"
@@ -32,17 +33,20 @@
};
TEST_F(PartitionCowCreatorTest, IntersectSelf) {
- auto builder_a = MetadataBuilder::New(1024 * 1024, 1024, 2);
+ constexpr uint64_t initial_size = 1_MiB;
+ constexpr uint64_t final_size = 40_KiB;
+
+ auto builder_a = MetadataBuilder::New(initial_size, 1_KiB, 2);
ASSERT_NE(builder_a, nullptr);
auto system_a = builder_a->AddPartition("system_a", LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system_a, nullptr);
- ASSERT_TRUE(builder_a->ResizePartition(system_a, 40 * 1024));
+ ASSERT_TRUE(builder_a->ResizePartition(system_a, final_size));
- auto builder_b = MetadataBuilder::New(1024 * 1024, 1024, 2);
+ auto builder_b = MetadataBuilder::New(initial_size, 1_KiB, 2);
ASSERT_NE(builder_b, nullptr);
auto system_b = builder_b->AddPartition("system_b", LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system_b, nullptr);
- ASSERT_TRUE(builder_b->ResizePartition(system_b, 40 * 1024));
+ ASSERT_TRUE(builder_b->ResizePartition(system_b, final_size));
PartitionCowCreator creator{.target_metadata = builder_b.get(),
.target_suffix = "_b",
@@ -51,8 +55,8 @@
.current_suffix = "_a"};
auto ret = creator.Run();
ASSERT_TRUE(ret.has_value());
- ASSERT_EQ(40 * 1024, ret->snapshot_status.device_size());
- ASSERT_EQ(40 * 1024, ret->snapshot_status.snapshot_size());
+ ASSERT_EQ(final_size, ret->snapshot_status.device_size());
+ ASSERT_EQ(final_size, ret->snapshot_status.snapshot_size());
}
TEST_F(PartitionCowCreatorTest, Holes) {
@@ -64,7 +68,7 @@
BlockDeviceInfo super_device("super", kSuperSize, 0, 0, 4_KiB);
std::vector<BlockDeviceInfo> devices = {super_device};
- auto source = MetadataBuilder::New(devices, "super", 1024, 2);
+ auto source = MetadataBuilder::New(devices, "super", 1_KiB, 2);
auto system = source->AddPartition("system_a", 0);
ASSERT_NE(nullptr, system);
ASSERT_TRUE(source->ResizePartition(system, big_size));
@@ -96,5 +100,31 @@
ASSERT_TRUE(ret.has_value());
}
+TEST(DmSnapshotInternals, CowSizeCalculator) {
+ DmSnapCowSizeCalculator cc(512, 8);
+ unsigned long int b;
+
+ // Empty COW
+ ASSERT_EQ(cc.cow_size_sectors(), 16);
+
+ // First chunk written
+ for (b = 0; b < 4_KiB; ++b) {
+ cc.WriteByte(b);
+ ASSERT_EQ(cc.cow_size_sectors(), 24);
+ }
+
+ // Second chunk written
+ for (b = 4_KiB; b < 8_KiB; ++b) {
+ cc.WriteByte(b);
+ ASSERT_EQ(cc.cow_size_sectors(), 32);
+ }
+
+ // Leave a hole and write 5th chunk
+ for (b = 16_KiB; b < 20_KiB; ++b) {
+ cc.WriteByte(b);
+ ASSERT_EQ(cc.cow_size_sectors(), 40);
+ }
+}
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 5b758c9..395fb40 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -71,8 +71,6 @@
using namespace std::chrono_literals;
using namespace std::string_literals;
-// Unit is sectors, this is a 4K chunk.
-static constexpr uint32_t kSnapshotChunkSize = 8;
static constexpr char kBootIndicatorPath[] = "/metadata/ota/snapshot-boot";
class DeviceInfo final : public SnapshotManager::IDeviceInfo {
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index fd7754e..aea12be 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -203,9 +203,9 @@
.block_device = fake_super,
.metadata = metadata.get(),
.partition = &partition,
- .device_name = GetPartitionName(partition) + "-base",
.force_writable = true,
.timeout_ms = 10s,
+ .device_name = GetPartitionName(partition) + "-base",
};
std::string ignore_path;
if (!CreateLogicalPartition(params, &ignore_path)) {
diff --git a/fs_mgr/libsnapshot/test_helpers.cpp b/fs_mgr/libsnapshot/test_helpers.cpp
index 1a6a593..539c5c5 100644
--- a/fs_mgr/libsnapshot/test_helpers.cpp
+++ b/fs_mgr/libsnapshot/test_helpers.cpp
@@ -92,21 +92,14 @@
}
std::optional<std::string> GetHash(const std::string& path) {
- unique_fd fd(open(path.c_str(), O_RDONLY));
- char buf[4096];
+ std::string content;
+ if (!android::base::ReadFileToString(path, &content, true)) {
+ PLOG(ERROR) << "Cannot access " << path;
+ return std::nullopt;
+ }
SHA256_CTX ctx;
SHA256_Init(&ctx);
- while (true) {
- ssize_t n = TEMP_FAILURE_RETRY(read(fd.get(), buf, sizeof(buf)));
- if (n < 0) {
- PLOG(ERROR) << "Cannot read " << path;
- return std::nullopt;
- }
- if (n == 0) {
- break;
- }
- SHA256_Update(&ctx, buf, n);
- }
+ SHA256_Update(&ctx, content.c_str(), content.size());
uint8_t out[32];
SHA256_Final(out, &ctx);
return ToHexString(out, sizeof(out));
diff --git a/fs_mgr/libsnapshot/utility.h b/fs_mgr/libsnapshot/utility.h
index 75c694c..3051184 100644
--- a/fs_mgr/libsnapshot/utility.h
+++ b/fs_mgr/libsnapshot/utility.h
@@ -27,6 +27,9 @@
namespace android {
namespace snapshot {
+// Unit is sectors, this is a 4K chunk.
+static constexpr uint32_t kSnapshotChunkSize = 8;
+
struct AutoDevice {
virtual ~AutoDevice(){};
void Release();
diff --git a/init/action_parser.cpp b/init/action_parser.cpp
index 9736824..a8e1e09 100644
--- a/init/action_parser.cpp
+++ b/init/action_parser.cpp
@@ -16,11 +16,14 @@
#include "action_parser.h"
+#include <ctype.h>
+
#include <android-base/properties.h>
#include <android-base/strings.h>
#if defined(__ANDROID__)
#include "property_service.h"
+#include "selinux.h"
#else
#include "host_init_stubs.h"
#endif
@@ -77,6 +80,17 @@
return {};
}
+Result<void> ValidateEventTrigger(const std::string& event_trigger) {
+ if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_R__) {
+ for (const char& c : event_trigger) {
+ if (c != '_' && c != '-' && !std::isalnum(c)) {
+ return Error() << "Illegal character '" << c << "' in '" << event_trigger << "'";
+ }
+ }
+ }
+ return {};
+}
+
Result<void> ParseTriggers(const std::vector<std::string>& args, Subcontext* subcontext,
std::string* event_trigger,
std::map<std::string, std::string>* property_triggers) {
@@ -103,6 +117,9 @@
if (!event_trigger->empty()) {
return Error() << "multiple event triggers are not allowed";
}
+ if (auto result = ValidateEventTrigger(args[i]); !result) {
+ return result;
+ }
*event_trigger = args[i];
}
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 42211b2..2f2ead0 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -138,7 +138,14 @@
if (!write_bootloader_message(options, &err)) {
return Error() << "Failed to set bootloader message: " << err;
}
- property_set("sys.powerctl", "reboot,recovery");
+ // This function should only be reached from init and not from vendor_init, and we want to
+ // immediately trigger reboot instead of relaying through property_service. Older devices may
+ // still have paths that reach here from vendor_init, so we keep the property_set as a fallback.
+ if (getpid() == 1) {
+ TriggerShutdown("reboot,recovery");
+ } else {
+ property_set("sys.powerctl", "reboot,recovery");
+ }
return {};
}
diff --git a/init/host_init_stubs.h b/init/host_init_stubs.h
index 71f78a5..5dd5cf1 100644
--- a/init/host_init_stubs.h
+++ b/init/host_init_stubs.h
@@ -35,7 +35,7 @@
namespace init {
// init.h
-inline void EnterShutdown(const std::string&) {
+inline void TriggerShutdown(const std::string&) {
abort();
}
diff --git a/init/init.cpp b/init/init.cpp
index ab6dbcf..f775d8f 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -179,7 +179,7 @@
waiting_for_prop.reset();
}
-void EnterShutdown(const std::string& command) {
+void TriggerShutdown(const std::string& command) {
// We can't call HandlePowerctlMessage() directly in this function,
// because it modifies the contents of the action queue, which can cause the action queue
// to get into a bad state if this function is called from a command being executed by the
@@ -197,7 +197,7 @@
// In non-thermal-shutdown case, 'shutdown' trigger will be fired to let device specific
// commands to be executed.
if (name == "sys.powerctl") {
- EnterShutdown(value);
+ TriggerShutdown(value);
}
if (property_triggers_enabled) ActionManager::GetInstance().QueuePropertyChange(name, value);
diff --git a/init/init.h b/init/init.h
index c7918e7..d884a94 100644
--- a/init/init.h
+++ b/init/init.h
@@ -31,7 +31,7 @@
Parser CreateParser(ActionManager& action_manager, ServiceList& service_list);
Parser CreateServiceOnlyParser(ServiceList& service_list);
-void EnterShutdown(const std::string& command);
+void TriggerShutdown(const std::string& command);
bool start_waiting_for_property(const char *name, const char *value);
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 315d584..9f63e4f 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -93,6 +93,26 @@
EXPECT_TRUE(expect_true);
}
+TEST(init, WrongEventTrigger) {
+ std::string init_script =
+ R"init(
+on boot:
+pass_test
+)init";
+
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ ASSERT_TRUE(android::base::WriteStringToFd(init_script, tf.fd));
+
+ ActionManager am;
+
+ Parser parser;
+ parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
+
+ ASSERT_TRUE(parser.ParseConfig(tf.path));
+ ASSERT_EQ(1u, parser.parse_error_count());
+}
+
TEST(init, EventTriggerOrder) {
std::string init_script =
R"init(
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 41965a1..d77b975 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -22,6 +22,7 @@
#include <linux/loop.h>
#include <mntent.h>
#include <semaphore.h>
+#include <stdlib.h>
#include <sys/cdefs.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
@@ -31,6 +32,7 @@
#include <sys/types.h>
#include <sys/wait.h>
+#include <chrono>
#include <memory>
#include <set>
#include <thread>
@@ -41,6 +43,7 @@
#include <android-base/logging.h>
#include <android-base/macros.h>
#include <android-base/properties.h>
+#include <android-base/scopeguard.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <bootloader_message/bootloader_message.h>
@@ -59,6 +62,7 @@
#include "service.h"
#include "service_list.h"
#include "sigchld_handler.h"
+#include "util.h"
#define PROC_SYSRQ "/proc/sysrq-trigger"
@@ -75,6 +79,19 @@
static bool shutting_down = false;
+static const std::set<std::string> kDebuggingServices{"tombstoned", "logd", "adbd", "console"};
+
+static std::vector<Service*> GetDebuggingServices(bool only_post_data) {
+ std::vector<Service*> ret;
+ ret.reserve(kDebuggingServices.size());
+ for (const auto& s : ServiceList::GetInstance()) {
+ if (kDebuggingServices.count(s->name()) && (!only_post_data || s->is_post_data())) {
+ ret.push_back(s.get());
+ }
+ }
+ return ret;
+}
+
// represents umount status during reboot / shutdown.
enum UmountStat {
/* umount succeeded. */
@@ -446,6 +463,49 @@
LOG(INFO) << "zram_backing_dev: `" << backing_dev << "` is cleared successfully.";
}
+// Stops given services, waits for them to be stopped for |timeout| ms.
+// If terminate is true, then SIGTERM is sent to services, otherwise SIGKILL is sent.
+static void StopServices(const std::vector<Service*>& services, std::chrono::milliseconds timeout,
+ bool terminate) {
+ LOG(INFO) << "Stopping " << services.size() << " services by sending "
+ << (terminate ? "SIGTERM" : "SIGKILL");
+ std::vector<pid_t> pids;
+ pids.reserve(services.size());
+ for (const auto& s : services) {
+ if (s->pid() > 0) {
+ pids.push_back(s->pid());
+ }
+ if (terminate) {
+ s->Terminate();
+ } else {
+ s->Stop();
+ }
+ }
+ if (timeout > 0ms) {
+ WaitToBeReaped(pids, timeout);
+ } else {
+ // Even if we don't to wait for services to stop, we still optimistically reap zombies.
+ ReapAnyOutstandingChildren();
+ }
+}
+
+// Like StopServices, but also logs all the services that failed to stop after the provided timeout.
+// Returns number of violators.
+static int StopServicesAndLogViolations(const std::vector<Service*>& services,
+ std::chrono::milliseconds timeout, bool terminate) {
+ StopServices(services, timeout, terminate);
+ int still_running = 0;
+ for (const auto& s : services) {
+ if (s->IsRunning()) {
+ LOG(ERROR) << "[service-misbehaving] : service '" << s->name() << "' is still running "
+ << timeout.count() << "ms after receiving "
+ << (terminate ? "SIGTERM" : "SIGKILL");
+ still_running++;
+ }
+ }
+ return still_running;
+}
+
//* Reboot / shutdown the system.
// cmd ANDROID_RB_* as defined in android_reboot.h
// reason Reason string like "reboot", "shutdown,userrequested"
@@ -510,12 +570,13 @@
// Start reboot monitor thread
sem_post(&reboot_semaphore);
- // keep debugging tools until non critical ones are all gone.
- const std::set<std::string> kill_after_apps{"tombstoned", "logd", "adbd"};
// watchdogd is a vendor specific component but should be alive to complete shutdown safely.
const std::set<std::string> to_starts{"watchdogd"};
+ std::vector<Service*> stop_first;
+ stop_first.reserve(ServiceList::GetInstance().services().size());
for (const auto& s : ServiceList::GetInstance()) {
- if (kill_after_apps.count(s->name())) {
+ if (kDebuggingServices.count(s->name())) {
+ // keep debugging tools until non critical ones are all gone.
s->SetShutdownCritical();
} else if (to_starts.count(s->name())) {
if (auto result = s->Start(); !result) {
@@ -529,6 +590,8 @@
LOG(ERROR) << "Could not start shutdown critical service '" << s->name()
<< "': " << result.error();
}
+ } else {
+ stop_first.push_back(s.get());
}
}
@@ -571,49 +634,12 @@
// optional shutdown step
// 1. terminate all services except shutdown critical ones. wait for delay to finish
if (shutdown_timeout > 0ms) {
- LOG(INFO) << "terminating init services";
-
- // Ask all services to terminate except shutdown critical ones.
- for (const auto& s : ServiceList::GetInstance().services_in_shutdown_order()) {
- if (!s->IsShutdownCritical()) s->Terminate();
- }
-
- int service_count = 0;
- // Only wait up to half of timeout here
- auto termination_wait_timeout = shutdown_timeout / 2;
- while (t.duration() < termination_wait_timeout) {
- ReapAnyOutstandingChildren();
-
- service_count = 0;
- for (const auto& s : ServiceList::GetInstance()) {
- // Count the number of services running except shutdown critical.
- // Exclude the console as it will ignore the SIGTERM signal
- // and not exit.
- // Note: SVC_CONSOLE actually means "requires console" but
- // it is only used by the shell.
- if (!s->IsShutdownCritical() && s->pid() != 0 && (s->flags() & SVC_CONSOLE) == 0) {
- service_count++;
- }
- }
-
- if (service_count == 0) {
- // All terminable services terminated. We can exit early.
- break;
- }
-
- // Wait a bit before recounting the number or running services.
- std::this_thread::sleep_for(50ms);
- }
- LOG(INFO) << "Terminating running services took " << t
- << " with remaining services:" << service_count;
+ StopServicesAndLogViolations(stop_first, shutdown_timeout / 2, true /* SIGTERM */);
}
-
- // minimum safety steps before restarting
- // 2. kill all services except ones that are necessary for the shutdown sequence.
- for (const auto& s : ServiceList::GetInstance().services_in_shutdown_order()) {
- if (!s->IsShutdownCritical()) s->Stop();
- }
+ // Send SIGKILL to ones that didn't terminate cleanly.
+ StopServicesAndLogViolations(stop_first, 0ms, false /* SIGKILL */);
SubcontextTerminate();
+ // Reap subcontext pids.
ReapAnyOutstandingChildren();
// 3. send volume shutdown to vold
@@ -625,9 +651,7 @@
LOG(INFO) << "vold not running, skipping vold shutdown";
}
// logcat stopped here
- for (const auto& s : ServiceList::GetInstance().services_in_shutdown_order()) {
- if (kill_after_apps.count(s->name())) s->Stop();
- }
+ StopServices(GetDebuggingServices(false /* only_post_data */), 0ms, false /* SIGKILL */);
// 4. sync, try umount, and optionally run fsck for user shutdown
{
Timer sync_timer;
@@ -660,6 +684,7 @@
}
static void EnterShutdown() {
+ LOG(INFO) << "Entering shutdown mode";
shutting_down = true;
// Skip wait for prop if it is in progress
ResetWaitForProp();
@@ -675,21 +700,61 @@
}
static void LeaveShutdown() {
+ LOG(INFO) << "Leaving shutdown mode";
shutting_down = false;
SendStartSendingMessagesMessage();
}
-static void DoUserspaceReboot() {
+static Result<void> DoUserspaceReboot() {
+ LOG(INFO) << "Userspace reboot initiated";
+ auto guard = android::base::make_scope_guard([] {
+ // Leave shutdown so that we can handle a full reboot.
+ LeaveShutdown();
+ TriggerShutdown("reboot,abort-userspace-reboot");
+ });
// Triggering userspace-reboot-requested will result in a bunch of set_prop
// actions. We should make sure, that all of them are propagated before
// proceeding with userspace reboot.
// TODO(b/135984674): implement proper synchronization logic.
std::this_thread::sleep_for(500ms);
EnterShutdown();
- // TODO(b/135984674): tear down post-data services
- LeaveShutdown();
+ std::vector<Service*> stop_first;
+ // Remember the services that were enabled. We will need to manually enable them again otherwise
+ // triggers like class_start won't restart them.
+ std::vector<Service*> were_enabled;
+ stop_first.reserve(ServiceList::GetInstance().services().size());
+ for (const auto& s : ServiceList::GetInstance().services_in_shutdown_order()) {
+ if (s->is_post_data() && !kDebuggingServices.count(s->name())) {
+ stop_first.push_back(s);
+ }
+ if (s->is_post_data() && s->IsEnabled()) {
+ were_enabled.push_back(s);
+ }
+ }
+ // TODO(b/135984674): do we need shutdown animation for userspace reboot?
+ // TODO(b/135984674): control userspace timeout via read-only property?
+ StopServicesAndLogViolations(stop_first, 10s, true /* SIGTERM */);
+ if (int r = StopServicesAndLogViolations(stop_first, 20s, false /* SIGKILL */); r > 0) {
+ // TODO(b/135984674): store information about offending services for debugging.
+ return Error() << r << " post-data services are still running";
+ }
// TODO(b/135984674): remount userdata
+ if (int r = StopServicesAndLogViolations(GetDebuggingServices(true /* only_post_data */), 5s,
+ false /* SIGKILL */);
+ r > 0) {
+ // TODO(b/135984674): store information about offending services for debugging.
+ return Error() << r << " debugging services are still running";
+ }
+ // TODO(b/135984674): deactivate APEX modules and switch back to bootstrap namespace.
+ // Re-enable services
+ for (const auto& s : were_enabled) {
+ LOG(INFO) << "Re-enabling service '" << s->name() << "'";
+ s->Enable();
+ }
+ LeaveShutdown();
ActionManager::GetInstance().QueueEventTrigger("userspace-reboot-resume");
+ guard.Disable(); // Go on with userspace reboot.
+ return {};
}
static void HandleUserspaceReboot() {
@@ -697,10 +762,7 @@
auto& am = ActionManager::GetInstance();
am.ClearQueue();
am.QueueEventTrigger("userspace-reboot-requested");
- auto handler = [](const BuiltinArguments&) {
- DoUserspaceReboot();
- return Result<void>{};
- };
+ auto handler = [](const BuiltinArguments&) { return DoUserspaceReboot(); };
am.QueueBuiltinAction(handler, "userspace-reboot");
}
diff --git a/init/service.cpp b/init/service.cpp
index a2db070..c8568a0 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -255,7 +255,7 @@
if ((siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) && on_failure_reboot_target_) {
LOG(ERROR) << "Service with 'reboot_on_failure' option failed, shutting down system.";
- EnterShutdown(*on_failure_reboot_target_);
+ TriggerShutdown(*on_failure_reboot_target_);
}
if (flags_ & SVC_EXEC) UnSetExec();
@@ -335,7 +335,7 @@
Result<void> Service::ExecStart() {
auto reboot_on_failure = make_scope_guard([this] {
if (on_failure_reboot_target_) {
- EnterShutdown(*on_failure_reboot_target_);
+ TriggerShutdown(*on_failure_reboot_target_);
}
});
@@ -366,7 +366,7 @@
Result<void> Service::Start() {
auto reboot_on_failure = make_scope_guard([this] {
if (on_failure_reboot_target_) {
- EnterShutdown(*on_failure_reboot_target_);
+ TriggerShutdown(*on_failure_reboot_target_);
}
});
diff --git a/init/service.h b/init/service.h
index 788f792..272c9f9 100644
--- a/init/service.h
+++ b/init/service.h
@@ -75,6 +75,7 @@
const std::vector<std::string>& args);
bool IsRunning() { return (flags_ & SVC_RUNNING) != 0; }
+ bool IsEnabled() { return (flags_ & SVC_DISABLED) == 0; }
Result<void> ExecStart();
Result<void> Start();
Result<void> StartIfNotDisabled();
diff --git a/init/sigchld_handler.cpp b/init/sigchld_handler.cpp
index 984235d..9b2c7d9 100644
--- a/init/sigchld_handler.cpp
+++ b/init/sigchld_handler.cpp
@@ -28,28 +28,31 @@
#include <android-base/scopeguard.h>
#include <android-base/stringprintf.h>
+#include <thread>
+
#include "init.h"
#include "service.h"
#include "service_list.h"
-using android::base::StringPrintf;
using android::base::boot_clock;
using android::base::make_scope_guard;
+using android::base::StringPrintf;
+using android::base::Timer;
namespace android {
namespace init {
-static bool ReapOneProcess() {
+static pid_t ReapOneProcess() {
siginfo_t siginfo = {};
// This returns a zombie pid or informs us that there are no zombies left to be reaped.
// It does NOT reap the pid; that is done below.
if (TEMP_FAILURE_RETRY(waitid(P_ALL, 0, &siginfo, WEXITED | WNOHANG | WNOWAIT)) != 0) {
PLOG(ERROR) << "waitid failed";
- return false;
+ return 0;
}
auto pid = siginfo.si_pid;
- if (pid == 0) return false;
+ if (pid == 0) return 0;
// At this point we know we have a zombie pid, so we use this scopeguard to reap the pid
// whenever the function returns from this point forward.
@@ -92,7 +95,7 @@
LOG(INFO) << name << " received signal " << siginfo.si_status << wait_string;
}
- if (!service) return true;
+ if (!service) return pid;
service->Reap(siginfo);
@@ -100,13 +103,33 @@
ServiceList::GetInstance().RemoveService(*service);
}
- return true;
+ return pid;
}
void ReapAnyOutstandingChildren() {
- while (ReapOneProcess()) {
+ while (ReapOneProcess() != 0) {
}
}
+void WaitToBeReaped(const std::vector<pid_t>& pids, std::chrono::milliseconds timeout) {
+ Timer t;
+ std::vector<pid_t> alive_pids(pids.begin(), pids.end());
+ while (!alive_pids.empty() && t.duration() < timeout) {
+ pid_t pid;
+ while ((pid = ReapOneProcess()) != 0) {
+ auto it = std::find(alive_pids.begin(), alive_pids.end(), pid);
+ if (it != alive_pids.end()) {
+ alive_pids.erase(it);
+ }
+ }
+ if (alive_pids.empty()) {
+ break;
+ }
+ std::this_thread::sleep_for(50ms);
+ }
+ LOG(INFO) << "Waiting for " << pids.size() << " pids to be reaped took " << t << " with "
+ << alive_pids.size() << " of them still running";
+}
+
} // namespace init
} // namespace android
diff --git a/init/sigchld_handler.h b/init/sigchld_handler.h
index 30063f2..fac1020 100644
--- a/init/sigchld_handler.h
+++ b/init/sigchld_handler.h
@@ -17,11 +17,16 @@
#ifndef _INIT_SIGCHLD_HANDLER_H_
#define _INIT_SIGCHLD_HANDLER_H_
+#include <chrono>
+#include <vector>
+
namespace android {
namespace init {
void ReapAnyOutstandingChildren();
+void WaitToBeReaped(const std::vector<pid_t>& pids, std::chrono::milliseconds timeout);
+
} // namespace init
} // namespace android
diff --git a/libcutils/sched_policy_test.cpp b/libcutils/sched_policy_test.cpp
index a321c90..b9e2832 100644
--- a/libcutils/sched_policy_test.cpp
+++ b/libcutils/sched_policy_test.cpp
@@ -107,6 +107,18 @@
TEST(SchedPolicy, get_sched_policy_name) {
EXPECT_STREQ("bg", get_sched_policy_name(SP_BACKGROUND));
- EXPECT_STREQ("error", get_sched_policy_name(SchedPolicy(-2)));
- EXPECT_STREQ("error", get_sched_policy_name(SP_CNT));
+ EXPECT_EQ(nullptr, get_sched_policy_name(SchedPolicy(-2)));
+ EXPECT_EQ(nullptr, get_sched_policy_name(SP_CNT));
+}
+
+TEST(SchedPolicy, get_cpuset_policy_profile_name) {
+ EXPECT_STREQ("CPUSET_SP_BACKGROUND", get_cpuset_policy_profile_name(SP_BACKGROUND));
+ EXPECT_EQ(nullptr, get_cpuset_policy_profile_name(SchedPolicy(-2)));
+ EXPECT_EQ(nullptr, get_cpuset_policy_profile_name(SP_CNT));
+}
+
+TEST(SchedPolicy, get_sched_policy_profile_name) {
+ EXPECT_STREQ("SCHED_SP_BACKGROUND", get_sched_policy_profile_name(SP_BACKGROUND));
+ EXPECT_EQ(nullptr, get_sched_policy_profile_name(SchedPolicy(-2)));
+ EXPECT_EQ(nullptr, get_sched_policy_profile_name(SP_CNT));
}
diff --git a/libcutils/trace-dev.cpp b/libcutils/trace-dev.cpp
index 4da8215..bff16c1 100644
--- a/libcutils/trace-dev.cpp
+++ b/libcutils/trace-dev.cpp
@@ -34,12 +34,9 @@
if (atrace_marker_fd == -1) {
ALOGE("Error opening trace file: %s (%d)", strerror(errno), errno);
atrace_enabled_tags = 0;
- goto done;
+ } else {
+ atrace_enabled_tags = atrace_get_property();
}
-
- atrace_enabled_tags = atrace_get_property();
-
-done:
atomic_store_explicit(&atrace_is_ready, true, memory_order_release);
}
diff --git a/liblog/include/android/log.h b/liblog/include/android/log.h
index 935590d..2e6210e 100644
--- a/liblog/include/android/log.h
+++ b/liblog/include/android/log.h
@@ -96,20 +96,14 @@
* [printf(3)](http://man7.org/linux/man-pages/man3/printf.3.html).
*/
int __android_log_print(int prio, const char* tag, const char* fmt, ...)
-#if defined(__GNUC__)
- __attribute__((__format__(printf, 3, 4)))
-#endif
- ;
+ __attribute__((__format__(printf, 3, 4)));
/**
* Equivalent to `__android_log_print`, but taking a `va_list`.
* (If `__android_log_print` is like `printf`, this is like `vprintf`.)
*/
int __android_log_vprint(int prio, const char* tag, const char* fmt, va_list ap)
-#if defined(__GNUC__)
- __attribute__((__format__(printf, 3, 0)))
-#endif
- ;
+ __attribute__((__format__(printf, 3, 0)));
/**
* Writes an assertion failure to the log (as `ANDROID_LOG_FATAL`) and to
@@ -127,13 +121,8 @@
* including the source filename and line number more conveniently than this
* function.
*/
-void __android_log_assert(const char* cond, const char* tag, const char* fmt,
- ...)
-#if defined(__GNUC__)
- __attribute__((__noreturn__))
- __attribute__((__format__(printf, 3, 4)))
-#endif
- ;
+void __android_log_assert(const char* cond, const char* tag, const char* fmt, ...)
+ __attribute__((__noreturn__)) __attribute__((__format__(printf, 3, 4)));
#ifndef log_id_t_defined
#define log_id_t_defined
@@ -171,8 +160,7 @@
*
* Apps should use __android_log_write() instead.
*/
-int __android_log_buf_write(int bufID, int prio, const char* tag,
- const char* text);
+int __android_log_buf_write(int bufID, int prio, const char* tag, const char* text);
/**
* Writes a formatted string to log buffer `id`,
@@ -182,12 +170,8 @@
*
* Apps should use __android_log_print() instead.
*/
-int __android_log_buf_print(int bufID, int prio, const char* tag,
- const char* fmt, ...)
-#if defined(__GNUC__)
- __attribute__((__format__(printf, 4, 5)))
-#endif
- ;
+int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt, ...)
+ __attribute__((__format__(printf, 4, 5)));
#ifdef __cplusplus
}
diff --git a/liblog/include/log/event_tag_map.h b/liblog/include/log/event_tag_map.h
index 2687b3a..f7ec208 100644
--- a/liblog/include/log/event_tag_map.h
+++ b/liblog/include/log/event_tag_map.h
@@ -16,6 +16,8 @@
#pragma once
+#include <stddef.h>
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/liblog/include/log/log.h b/liblog/include/log/log.h
index 5928649..90d1e76 100644
--- a/liblog/include/log/log.h
+++ b/liblog/include/log/log.h
@@ -22,7 +22,6 @@
#endif
#include <stdint.h> /* uint16_t, int32_t */
#include <stdio.h>
-#include <sys/types.h>
#include <time.h>
#include <unistd.h>
@@ -65,21 +64,6 @@
#endif
#endif
-/* --------------------------------------------------------------------- */
-
-/*
- * This file uses ", ## __VA_ARGS__" zero-argument token pasting to
- * work around issues with debug-only syntax errors in assertions
- * that are missing format strings. See commit
- * 19299904343daf191267564fe32e6cd5c165cd42
- */
-#if defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
-#endif
-
-/* --------------------------------------------------------------------- */
-
/*
* Event logging.
*/
@@ -164,10 +148,6 @@
*/
void __android_log_close(void);
-#if defined(__clang__)
-#pragma clang diagnostic pop
-#endif
-
#ifdef __cplusplus
}
#endif
diff --git a/liblog/include/log/log_event_list.h b/liblog/include/log/log_event_list.h
index 636d417..deadf20 100644
--- a/liblog/include/log/log_event_list.h
+++ b/liblog/include/log/log_event_list.h
@@ -36,16 +36,11 @@
/*
* The opaque context used to manipulate lists of events.
*/
-#ifndef __android_log_context_defined
-#define __android_log_context_defined
typedef struct android_log_context_internal* android_log_context;
-#endif
/*
* Elements returned when reading a list of events.
*/
-#ifndef __android_log_list_element_defined
-#define __android_log_list_element_defined
typedef struct {
AndroidEventLogType type;
uint16_t complete;
@@ -57,7 +52,6 @@
float float32;
} data;
} android_log_list_element;
-#endif
/*
* Creates a context associated with an event tag to write elements to
@@ -104,8 +98,6 @@
int android_log_destroy(android_log_context* ctx);
#ifdef __cplusplus
-#ifndef __class_android_log_event_list_defined
-#define __class_android_log_event_list_defined
/* android_log_list C++ helpers */
extern "C++" {
class android_log_event_list {
@@ -280,7 +272,6 @@
};
}
#endif
-#endif
#ifdef __cplusplus
}
diff --git a/liblog/include/log/log_id.h b/liblog/include/log/log_id.h
index c052a50..4c6d809 100644
--- a/liblog/include/log/log_id.h
+++ b/liblog/include/log/log_id.h
@@ -45,12 +45,8 @@
*/
int __android_log_buf_write(int bufID, int prio, const char* tag,
const char* text);
-int __android_log_buf_print(int bufID, int prio, const char* tag,
- const char* fmt, ...)
-#if defined(__GNUC__)
- __attribute__((__format__(printf, 4, 5)))
-#endif
- ;
+int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt, ...)
+ __attribute__((__format__(printf, 4, 5)));
/*
* log_id_t helpers
diff --git a/liblog/include/log/log_read.h b/liblog/include/log/log_read.h
index fdef306..2079e7a 100644
--- a/liblog/include/log/log_read.h
+++ b/liblog/include/log/log_read.h
@@ -53,8 +53,6 @@
/*
* The userspace structure for version 1 of the logger_entry ABI.
*/
-#ifndef __struct_logger_entry_defined
-#define __struct_logger_entry_defined
struct logger_entry {
uint16_t len; /* length of the payload */
uint16_t __pad; /* no matter what, we get 2 bytes of padding */
@@ -64,13 +62,10 @@
int32_t nsec; /* nanoseconds */
char msg[0]; /* the entry's payload */
};
-#endif
/*
* The userspace structure for version 2 of the logger_entry ABI.
*/
-#ifndef __struct_logger_entry_v2_defined
-#define __struct_logger_entry_v2_defined
struct logger_entry_v2 {
uint16_t len; /* length of the payload */
uint16_t hdr_size; /* sizeof(struct logger_entry_v2) */
@@ -81,13 +76,10 @@
uint32_t euid; /* effective UID of logger */
char msg[0]; /* the entry's payload */
} __attribute__((__packed__));
-#endif
/*
* The userspace structure for version 3 of the logger_entry ABI.
*/
-#ifndef __struct_logger_entry_v3_defined
-#define __struct_logger_entry_v3_defined
struct logger_entry_v3 {
uint16_t len; /* length of the payload */
uint16_t hdr_size; /* sizeof(struct logger_entry_v3) */
@@ -98,13 +90,10 @@
uint32_t lid; /* log id of the payload */
char msg[0]; /* the entry's payload */
} __attribute__((__packed__));
-#endif
/*
* The userspace structure for version 4 of the logger_entry ABI.
*/
-#ifndef __struct_logger_entry_v4_defined
-#define __struct_logger_entry_v4_defined
struct logger_entry_v4 {
uint16_t len; /* length of the payload */
uint16_t hdr_size; /* sizeof(struct logger_entry_v4) */
@@ -116,7 +105,6 @@
uint32_t uid; /* generating process's uid */
char msg[0]; /* the entry's payload */
};
-#endif
#pragma clang diagnostic pop
/*
@@ -133,8 +121,6 @@
*/
#define LOGGER_ENTRY_MAX_LEN (5 * 1024)
-#ifndef __struct_log_msg_defined
-#define __struct_log_msg_defined
struct log_msg {
union {
unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1];
@@ -191,7 +177,6 @@
}
#endif
};
-#endif
struct logger;
diff --git a/liblog/include/log/log_time.h b/liblog/include/log/log_time.h
index 09c9910..6b4458c 100644
--- a/liblog/include/log/log_time.h
+++ b/liblog/include/log/log_time.h
@@ -24,9 +24,6 @@
#define US_PER_SEC 1000000ULL
#define MS_PER_SEC 1000ULL
-#ifndef __struct_log_time_defined
-#define __struct_log_time_defined
-
#define LOG_TIME_SEC(t) ((t)->tv_sec)
/* next power of two after NS_PER_SEC */
#define LOG_TIME_NSEC(t) ((t)->tv_nsec & (UINT32_MAX >> 2))
@@ -35,11 +32,6 @@
extern "C" {
-/*
- * NB: we did NOT define a copy constructor. This will result in structure
- * no longer being compatible with pass-by-value which is desired
- * efficient behavior. Also, pass-by-reference breaks C/C++ ABI.
- */
struct log_time {
public:
uint32_t tv_sec = 0; /* good to Feb 5 2106 */
@@ -169,5 +161,3 @@
} __attribute__((__packed__)) log_time;
#endif /* __cplusplus */
-
-#endif /* __struct_log_time_defined */
diff --git a/liblog/include/log/logprint.h b/liblog/include/log/logprint.h
index 8f4b187..7dfd914 100644
--- a/liblog/include/log/logprint.h
+++ b/liblog/include/log/logprint.h
@@ -16,7 +16,8 @@
#pragma once
-#include <pthread.h>
+#include <stdint.h>
+#include <sys/types.h>
#include <android/log.h>
#include <log/event_tag_map.h>
diff --git a/liblog/pmsg_reader.cpp b/liblog/pmsg_reader.cpp
index 9c5bc95..ce923f3 100644
--- a/liblog/pmsg_reader.cpp
+++ b/liblog/pmsg_reader.cpp
@@ -62,58 +62,9 @@
return -EBADF;
}
-/* Determine the credentials of the caller */
-static bool uid_has_log_permission(uid_t uid) {
- return (uid == AID_SYSTEM) || (uid == AID_LOG) || (uid == AID_ROOT) || (uid == AID_LOGD);
-}
-
-static uid_t get_best_effective_uid() {
- uid_t euid;
- uid_t uid;
- gid_t gid;
- ssize_t i;
- static uid_t last_uid = (uid_t)-1;
-
- if (last_uid != (uid_t)-1) {
- return last_uid;
- }
- uid = __android_log_uid();
- if (uid_has_log_permission(uid)) {
- return last_uid = uid;
- }
- euid = geteuid();
- if (uid_has_log_permission(euid)) {
- return last_uid = euid;
- }
- gid = getgid();
- if (uid_has_log_permission(gid)) {
- return last_uid = gid;
- }
- gid = getegid();
- if (uid_has_log_permission(gid)) {
- return last_uid = gid;
- }
- i = getgroups((size_t)0, NULL);
- if (i > 0) {
- gid_t list[i];
-
- getgroups(i, list);
- while (--i >= 0) {
- if (uid_has_log_permission(list[i])) {
- return last_uid = list[i];
- }
- }
- }
- return last_uid = uid;
-}
-
static int pmsgClear(struct android_log_logger* logger __unused,
struct android_log_transport_context* transp __unused) {
- if (uid_has_log_permission(get_best_effective_uid())) {
- return unlink("/sys/fs/pstore/pmsg-ramoops-0");
- }
- errno = EPERM;
- return -1;
+ return unlink("/sys/fs/pstore/pmsg-ramoops-0");
}
/*
@@ -128,14 +79,12 @@
struct android_log_transport_context* transp, struct log_msg* log_msg) {
ssize_t ret;
off_t current, next;
- uid_t uid;
struct __attribute__((__packed__)) {
android_pmsg_log_header_t p;
android_log_header_t l;
uint8_t prio;
} buf;
static uint8_t preread_count;
- bool is_system;
memset(log_msg, 0, sizeof(*log_msg));
@@ -195,37 +144,30 @@
((logger_list->start.tv_sec != buf.l.realtime.tv_sec) ||
(logger_list->start.tv_nsec <= buf.l.realtime.tv_nsec)))) &&
(!logger_list->pid || (logger_list->pid == buf.p.pid))) {
- uid = get_best_effective_uid();
- is_system = uid_has_log_permission(uid);
- if (is_system || (uid == buf.p.uid)) {
- char* msg = is_system ? log_msg->entry_v4.msg : log_msg->entry_v3.msg;
- *msg = buf.prio;
- fd = atomic_load(&transp->context.fd);
- if (fd <= 0) {
- return -EBADF;
- }
- ret = TEMP_FAILURE_RETRY(read(fd, msg + sizeof(buf.prio), buf.p.len - sizeof(buf)));
- if (ret < 0) {
- return -errno;
- }
- if (ret != (ssize_t)(buf.p.len - sizeof(buf))) {
- return -EIO;
- }
-
- log_msg->entry_v4.len = buf.p.len - sizeof(buf) + sizeof(buf.prio);
- log_msg->entry_v4.hdr_size =
- is_system ? sizeof(log_msg->entry_v4) : sizeof(log_msg->entry_v3);
- log_msg->entry_v4.pid = buf.p.pid;
- log_msg->entry_v4.tid = buf.l.tid;
- log_msg->entry_v4.sec = buf.l.realtime.tv_sec;
- log_msg->entry_v4.nsec = buf.l.realtime.tv_nsec;
- log_msg->entry_v4.lid = buf.l.id;
- if (is_system) {
- log_msg->entry_v4.uid = buf.p.uid;
- }
-
- return ret + sizeof(buf.prio) + log_msg->entry_v4.hdr_size;
+ char* msg = log_msg->entry_v4.msg;
+ *msg = buf.prio;
+ fd = atomic_load(&transp->context.fd);
+ if (fd <= 0) {
+ return -EBADF;
}
+ ret = TEMP_FAILURE_RETRY(read(fd, msg + sizeof(buf.prio), buf.p.len - sizeof(buf)));
+ if (ret < 0) {
+ return -errno;
+ }
+ if (ret != (ssize_t)(buf.p.len - sizeof(buf))) {
+ return -EIO;
+ }
+
+ log_msg->entry_v4.len = buf.p.len - sizeof(buf) + sizeof(buf.prio);
+ log_msg->entry_v4.hdr_size = sizeof(log_msg->entry_v4);
+ log_msg->entry_v4.pid = buf.p.pid;
+ log_msg->entry_v4.tid = buf.l.tid;
+ log_msg->entry_v4.sec = buf.l.realtime.tv_sec;
+ log_msg->entry_v4.nsec = buf.l.realtime.tv_nsec;
+ log_msg->entry_v4.lid = buf.l.id;
+ log_msg->entry_v4.uid = buf.p.uid;
+
+ return ret + sizeof(buf.prio) + log_msg->entry_v4.hdr_size;
}
fd = atomic_load(&transp->context.fd);
@@ -273,13 +215,7 @@
struct android_log_transport_context transp;
struct content {
struct listnode node;
- union {
- struct logger_entry_v4 entry;
- struct logger_entry_v4 entry_v4;
- struct logger_entry_v3 entry_v3;
- struct logger_entry_v2 entry_v2;
- struct logger_entry entry_v1;
- };
+ struct logger_entry_v4 entry;
} * content;
struct names {
struct listnode node;
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index 4642b9b..56892a2 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -17,6 +17,7 @@
#include <fcntl.h>
#include <inttypes.h>
#include <poll.h>
+#include <sched.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index cfcfd99..94c4fbb 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -27,10 +27,12 @@
#include <sys/types.h>
#include <unistd.h>
+#include <memory>
#include <string>
#include <android-base/file.h>
#include <android-base/macros.h>
+#include <android-base/scopeguard.h>
#include <android-base/stringprintf.h>
#ifdef __ANDROID__ // includes sys/properties.h which does not exist outside
#include <cutils/properties.h>
@@ -42,6 +44,8 @@
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
+using android::base::make_scope_guard;
+
// #define ENABLE_FLAKY_TESTS
// enhanced version of LOG_FAILURE_RETRY to add support for EAGAIN and
@@ -58,6 +62,80 @@
_rc; \
})
+// std::unique_ptr doesn't let you provide a pointer to a deleter (android_logger_list_close()) if
+// the type (struct logger_list) is an incomplete type, so we create ListCloser instead.
+struct ListCloser {
+ void operator()(struct logger_list* list) { android_logger_list_close(list); }
+};
+
+// This function is meant to be used for most log tests, it does the following:
+// 1) Open the log_buffer with a blocking reader
+// 2) Write the messages via write_messages
+// 3) Set an alarm for 2 seconds as a timeout
+// 4) Read until check_message returns true, which should be used to indicate the target message
+// is found
+// 5) Open log_buffer with a non_blocking reader and dump all messages
+// 6) Count the number of times check_messages returns true for these messages and assert it's
+// only 1.
+template <typename FWrite, typename FCheck>
+static void RunLogTests(log_id_t log_buffer, FWrite write_messages, FCheck check_message) {
+ pid_t pid = getpid();
+
+ auto logger_list = std::unique_ptr<struct logger_list, ListCloser>{
+ android_logger_list_open(log_buffer, ANDROID_LOG_RDONLY, 1000, pid)};
+ ASSERT_TRUE(logger_list);
+
+ write_messages();
+
+ alarm(2);
+ auto alarm_guard = android::base::make_scope_guard([] { alarm(0); });
+ bool found = false;
+ while (!found) {
+ log_msg log_msg;
+ ASSERT_GT(android_logger_list_read(logger_list.get(), &log_msg), 0);
+
+ ASSERT_EQ(log_buffer, log_msg.id());
+ ASSERT_EQ(pid, log_msg.entry.pid);
+
+ // TODO: Should this be an assert?
+ if (log_msg.msg() == nullptr) {
+ continue;
+ }
+
+ check_message(log_msg, &found);
+ }
+
+ auto logger_list_non_block = std::unique_ptr<struct logger_list, ListCloser>{
+ android_logger_list_open(log_buffer, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)};
+ ASSERT_TRUE(logger_list_non_block);
+
+ size_t count = 0;
+ while (true) {
+ log_msg log_msg;
+ auto ret = android_logger_list_read(logger_list_non_block.get(), &log_msg);
+ if (ret == -EAGAIN) {
+ break;
+ }
+ ASSERT_GT(ret, 0);
+
+ ASSERT_EQ(log_buffer, log_msg.id());
+ ASSERT_EQ(pid, log_msg.entry.pid);
+
+ // TODO: Should this be an assert?
+ if (log_msg.msg() == nullptr) {
+ continue;
+ }
+
+ found = false;
+ check_message(log_msg, &found);
+ if (found) {
+ ++count;
+ }
+ }
+
+ EXPECT_EQ(1U, count);
+}
+
TEST(liblog, __android_log_btwrite) {
int intBuf = 0xDEADBEEF;
EXPECT_LT(0,
@@ -65,14 +143,11 @@
long long longBuf = 0xDEADBEEFA55A5AA5;
EXPECT_LT(
0, __android_log_btwrite(0, EVENT_TYPE_LONG, &longBuf, sizeof(longBuf)));
- usleep(1000);
char Buf[] = "\20\0\0\0DeAdBeEfA55a5aA5";
EXPECT_LT(0,
__android_log_btwrite(0, EVENT_TYPE_STRING, Buf, sizeof(Buf) - 1));
- usleep(1000);
}
-#ifdef ENABLE_FLAKY_TESTS
#if defined(__ANDROID__)
static std::string popenToString(const std::string& command) {
std::string ret;
@@ -141,81 +216,63 @@
static bool tested__android_log_close;
#endif
-#endif // ENABLE_FLAKY_TESTS
TEST(liblog, __android_log_btwrite__android_logger_list_read) {
#ifdef __ANDROID__
- struct logger_list* logger_list;
-
- pid_t pid = getpid();
-
- ASSERT_TRUE(NULL !=
- (logger_list = android_logger_list_open(
- LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
- 1000, pid)));
-
log_time ts(CLOCK_MONOTONIC);
- EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
-#ifdef ENABLE_FLAKY_TESTS
- // Check that we can close and reopen the logger
- bool logdwActiveAfter__android_log_btwrite;
- if (getuid() == AID_ROOT) {
- tested__android_log_close = true;
-#ifndef NO_PSTORE
- bool pmsgActiveAfter__android_log_btwrite = isPmsgActive();
- EXPECT_TRUE(pmsgActiveAfter__android_log_btwrite);
-#endif /* NO_PSTORE */
- logdwActiveAfter__android_log_btwrite = isLogdwActive();
- EXPECT_TRUE(logdwActiveAfter__android_log_btwrite);
- } else if (!tested__android_log_close) {
- fprintf(stderr, "WARNING: can not test __android_log_close()\n");
- }
- __android_log_close();
- if (getuid() == AID_ROOT) {
-#ifndef NO_PSTORE
- bool pmsgActiveAfter__android_log_close = isPmsgActive();
- EXPECT_FALSE(pmsgActiveAfter__android_log_close);
-#endif /* NO_PSTORE */
- bool logdwActiveAfter__android_log_close = isLogdwActive();
- EXPECT_FALSE(logdwActiveAfter__android_log_close);
- }
-#endif // ENABLE_FLAKY_TESTS
+ log_time ts1(ts);
- log_time ts1(CLOCK_MONOTONIC);
- EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1)));
-#ifdef ENABLE_FLAKY_TESTS
- if (getuid() == AID_ROOT) {
+ auto write_function = [&] {
+ EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
+ // Check that we can close and reopen the logger
+ bool logdwActiveAfter__android_log_btwrite;
+ if (getuid() == AID_ROOT) {
+ tested__android_log_close = true;
#ifndef NO_PSTORE
- bool pmsgActiveAfter__android_log_btwrite = isPmsgActive();
- EXPECT_TRUE(pmsgActiveAfter__android_log_btwrite);
+ bool pmsgActiveAfter__android_log_btwrite = isPmsgActive();
+ EXPECT_TRUE(pmsgActiveAfter__android_log_btwrite);
#endif /* NO_PSTORE */
- logdwActiveAfter__android_log_btwrite = isLogdwActive();
- EXPECT_TRUE(logdwActiveAfter__android_log_btwrite);
- }
-#endif // ENABLE_FLAKY_TESTS
- usleep(1000000);
+ logdwActiveAfter__android_log_btwrite = isLogdwActive();
+ EXPECT_TRUE(logdwActiveAfter__android_log_btwrite);
+ } else if (!tested__android_log_close) {
+ fprintf(stderr, "WARNING: can not test __android_log_close()\n");
+ }
+ __android_log_close();
+ if (getuid() == AID_ROOT) {
+#ifndef NO_PSTORE
+ bool pmsgActiveAfter__android_log_close = isPmsgActive();
+ EXPECT_FALSE(pmsgActiveAfter__android_log_close);
+#endif /* NO_PSTORE */
+ bool logdwActiveAfter__android_log_close = isLogdwActive();
+ EXPECT_FALSE(logdwActiveAfter__android_log_close);
+ }
+
+ ts1 = log_time(CLOCK_MONOTONIC);
+ EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1)));
+ if (getuid() == AID_ROOT) {
+#ifndef NO_PSTORE
+ bool pmsgActiveAfter__android_log_btwrite = isPmsgActive();
+ EXPECT_TRUE(pmsgActiveAfter__android_log_btwrite);
+#endif /* NO_PSTORE */
+ logdwActiveAfter__android_log_btwrite = isLogdwActive();
+ EXPECT_TRUE(logdwActiveAfter__android_log_btwrite);
+ }
+ };
int count = 0;
int second_count = 0;
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) {
- break;
- }
-
- EXPECT_EQ(log_msg.entry.pid, pid);
-
+ auto check_function = [&](log_msg log_msg, bool* found) {
if ((log_msg.entry.len != sizeof(android_log_event_long_t)) ||
(log_msg.id() != LOG_ID_EVENTS)) {
- continue;
+ return;
}
android_log_event_long_t* eventData;
eventData = reinterpret_cast<android_log_event_long_t*>(log_msg.msg());
if (!eventData || (eventData->payload.type != EVENT_TYPE_LONG)) {
- continue;
+ return;
}
log_time tx(reinterpret_cast<char*>(&eventData->payload.data));
@@ -224,12 +281,50 @@
} else if (ts1 == tx) {
++second_count;
}
- }
- EXPECT_EQ(1, count);
- EXPECT_EQ(1, second_count);
+ if (count == 1 && second_count == 1) {
+ count = 0;
+ second_count = 0;
+ *found = true;
+ }
+ };
- android_logger_list_close(logger_list);
+ RunLogTests(LOG_ID_EVENTS, write_function, check_function);
+
+#else
+ GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+}
+
+TEST(liblog, __android_log_write__android_logger_list_read) {
+#ifdef __ANDROID__
+ pid_t pid = getpid();
+
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ std::string buf = android::base::StringPrintf("pid=%u ts=%ld.%09ld", pid, ts.tv_sec, ts.tv_nsec);
+ static const char tag[] = "liblog.__android_log_write__android_logger_list_read";
+ static const char prio = ANDROID_LOG_DEBUG;
+
+ std::string expected_message =
+ std::string(&prio, sizeof(prio)) + tag + std::string("", 1) + buf + std::string("", 1);
+
+ auto write_function = [&] { ASSERT_LT(0, __android_log_write(prio, tag, buf.c_str())); };
+
+ auto check_function = [&](log_msg log_msg, bool* found) {
+ if (log_msg.entry.len != expected_message.length()) {
+ return;
+ }
+
+ if (expected_message != std::string(log_msg.msg(), log_msg.entry.len)) {
+ return;
+ }
+
+ *found = true;
+ };
+
+ RunLogTests(LOG_ID_MAIN, write_function, check_function);
+
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
@@ -237,18 +332,10 @@
static void bswrite_test(const char* message) {
#ifdef __ANDROID__
- struct logger_list* logger_list;
-
pid_t pid = getpid();
- ASSERT_TRUE(NULL !=
- (logger_list = android_logger_list_open(
- LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
- 1000, pid)));
-
log_time ts(android_log_clockid());
- EXPECT_LT(0, __android_log_bswrite(0, message));
size_t num_lines = 1, size = 0, length = 0, total = 0;
const char* cp = message;
while (*cp) {
@@ -270,36 +357,25 @@
++cp;
++total;
}
- usleep(1000000);
- int count = 0;
+ auto write_function = [&] { EXPECT_LT(0, __android_log_bswrite(0, message)); };
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) {
- break;
- }
-
- EXPECT_EQ(log_msg.entry.pid, pid);
-
- if ((log_msg.entry.sec < (ts.tv_sec - 1)) ||
- ((ts.tv_sec + 1) < log_msg.entry.sec) ||
- ((size_t)log_msg.entry.len !=
- (sizeof(android_log_event_string_t) + length)) ||
- (log_msg.id() != LOG_ID_EVENTS)) {
- continue;
+ auto check_function = [&](log_msg log_msg, bool* found) {
+ if ((size_t)log_msg.entry.len != (sizeof(android_log_event_string_t) + length) ||
+ log_msg.id() != LOG_ID_EVENTS) {
+ return;
}
android_log_event_string_t* eventData;
eventData = reinterpret_cast<android_log_event_string_t*>(log_msg.msg());
if (!eventData || (eventData->type != EVENT_TYPE_STRING)) {
- continue;
+ return;
}
size_t len = eventData->length;
if (len == total) {
- ++count;
+ *found = true;
AndroidLogFormat* logformat = android_log_format_new();
EXPECT_TRUE(NULL != logformat);
@@ -326,11 +402,10 @@
}
android_log_format_free(logformat);
}
- }
+ };
- EXPECT_EQ(1, count);
+ RunLogTests(LOG_ID_EVENTS, write_function, check_function);
- android_logger_list_close(logger_list);
#else
message = NULL;
GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -359,20 +434,14 @@
static void buf_write_test(const char* message) {
#ifdef __ANDROID__
- struct logger_list* logger_list;
-
pid_t pid = getpid();
- ASSERT_TRUE(
- NULL !=
- (logger_list = android_logger_list_open(
- LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
static const char tag[] = "TEST__android_log_buf_write";
log_time ts(android_log_clockid());
- EXPECT_LT(
- 0, __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO, tag, message));
+ auto write_function = [&] {
+ EXPECT_LT(0, __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO, tag, message));
+ };
size_t num_lines = 1, size = 0, length = 0;
const char* cp = message;
while (*cp) {
@@ -389,26 +458,13 @@
}
++cp;
}
- usleep(1000000);
- int count = 0;
-
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) {
- break;
+ auto check_function = [&](log_msg log_msg, bool* found) {
+ if ((size_t)log_msg.entry.len != (sizeof(tag) + length + 2) || log_msg.id() != LOG_ID_MAIN) {
+ return;
}
- ASSERT_EQ(log_msg.entry.pid, pid);
-
- if ((log_msg.entry.sec < (ts.tv_sec - 1)) ||
- ((ts.tv_sec + 1) < log_msg.entry.sec) ||
- ((size_t)log_msg.entry.len != (sizeof(tag) + length + 2)) ||
- (log_msg.id() != LOG_ID_MAIN)) {
- continue;
- }
-
- ++count;
+ *found = true;
AndroidLogFormat* logformat = android_log_format_new();
EXPECT_TRUE(NULL != logformat);
@@ -425,11 +481,10 @@
android_log_printLogLine(logformat, fileno(stderr), &entry));
}
android_log_format_free(logformat);
- }
+ };
- EXPECT_EQ(1, count);
+ RunLogTests(LOG_ID_MAIN, write_function, check_function);
- android_logger_list_close(logger_list);
#else
message = NULL;
GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -892,7 +947,6 @@
when you depart from me, sorrow abides and happiness\n\
takes his leave.";
-#ifdef ENABLE_FLAKY_TESTS
TEST(liblog, max_payload) {
#ifdef __ANDROID__
static const char max_payload_tag[] = "TEST_max_payload_and_longish_tag_XXXX";
@@ -903,32 +957,17 @@
memcpy(tag, max_payload_tag, sizeof(tag));
snprintf(tag + sizeof(tag) - 5, 5, "%04X", pid & 0xFFFF);
- LOG_FAILURE_RETRY(__android_log_buf_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO,
- tag, max_payload_buf));
- sleep(2);
+ auto write_function = [&] {
+ LOG_FAILURE_RETRY(
+ __android_log_buf_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO, tag, max_payload_buf));
+ };
- struct logger_list* logger_list;
-
- ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
- LOG_ID_SYSTEM, ANDROID_LOG_RDONLY, 100, 0)));
-
- bool matches = false;
ssize_t max_len = 0;
-
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) {
- break;
- }
-
- if ((log_msg.entry.pid != pid) || (log_msg.id() != LOG_ID_SYSTEM)) {
- continue;
- }
-
+ auto check_function = [&](log_msg log_msg, bool* found) {
char* data = log_msg.msg();
if (!data || strcmp(++data, tag)) {
- continue;
+ return;
}
data += strlen(data) + 1;
@@ -945,57 +984,31 @@
}
if (max_len > 512) {
- matches = true;
- break;
+ *found = true;
}
- }
+ };
- android_logger_list_close(logger_list);
-
- EXPECT_EQ(true, matches);
+ RunLogTests(LOG_ID_SYSTEM, write_function, check_function);
EXPECT_LE(SIZEOF_MAX_PAYLOAD_BUF, static_cast<size_t>(max_len));
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // ENABLE_FLAKY_TESTS
TEST(liblog, __android_log_buf_print__maxtag) {
#ifdef __ANDROID__
- struct logger_list* logger_list;
+ auto write_function = [&] {
+ EXPECT_LT(0, __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_INFO, max_payload_buf,
+ max_payload_buf));
+ };
- pid_t pid = getpid();
-
- ASSERT_TRUE(
- NULL !=
- (logger_list = android_logger_list_open(
- LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
- log_time ts(android_log_clockid());
-
- EXPECT_LT(0, __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_INFO,
- max_payload_buf, max_payload_buf));
- usleep(1000000);
-
- int count = 0;
-
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) {
- break;
+ auto check_function = [&](log_msg log_msg, bool* found) {
+ if ((size_t)log_msg.entry.len < LOGGER_ENTRY_MAX_PAYLOAD) {
+ return;
}
- ASSERT_EQ(log_msg.entry.pid, pid);
-
- if ((log_msg.entry.sec < (ts.tv_sec - 1)) ||
- ((ts.tv_sec + 1) < log_msg.entry.sec) ||
- ((size_t)log_msg.entry.len < LOGGER_ENTRY_MAX_PAYLOAD) ||
- (log_msg.id() != LOG_ID_MAIN)) {
- continue;
- }
-
- ++count;
+ *found = true;
AndroidLogFormat* logformat = android_log_format_new();
EXPECT_TRUE(NULL != logformat);
@@ -1013,16 +1026,18 @@
EXPECT_GT(LOGGER_ENTRY_MAX_PAYLOAD * 13 / 8, printLogLine);
}
android_log_format_free(logformat);
- }
+ };
- EXPECT_EQ(1, count);
+ RunLogTests(LOG_ID_MAIN, write_function, check_function);
- android_logger_list_close(logger_list);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
+// TODO: This test is tautological. android_logger_list_read() calls recv() with
+// LOGGER_ENTRY_MAX_PAYLOAD as its size argument, so it's not possible for this test to read a
+// payload larger than that size.
TEST(liblog, too_big_payload) {
#ifdef __ANDROID__
pid_t pid = getpid();
@@ -1032,32 +1047,18 @@
snprintf(tag + sizeof(tag) - 5, 5, "%04X", pid & 0xFFFF);
std::string longString(3266519, 'x');
+ ssize_t ret;
- ssize_t ret = LOG_FAILURE_RETRY(__android_log_buf_write(
- LOG_ID_SYSTEM, ANDROID_LOG_INFO, tag, longString.c_str()));
+ auto write_function = [&] {
+ ret = LOG_FAILURE_RETRY(
+ __android_log_buf_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO, tag, longString.c_str()));
+ };
- struct logger_list* logger_list;
-
- ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
- LOG_ID_SYSTEM,
- ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 100, 0)));
-
- ssize_t max_len = 0;
-
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) {
- break;
- }
-
- if ((log_msg.entry.pid != pid) || (log_msg.id() != LOG_ID_SYSTEM)) {
- continue;
- }
-
+ auto check_function = [&](log_msg log_msg, bool* found) {
char* data = log_msg.msg();
if (!data || strcmp(++data, tag)) {
- continue;
+ return;
}
data += strlen(data) + 1;
@@ -1069,33 +1070,38 @@
++right;
}
- if (max_len <= (left - data)) {
- max_len = left - data + 1;
+ ssize_t len = left - data + 1;
+ // Check that we don't see any entries larger than the max payload.
+ EXPECT_LE(static_cast<size_t>(len), LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag));
+
+ // Once we've found our expected entry, break.
+ if (len == LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag)) {
+ EXPECT_EQ(ret, len + static_cast<ssize_t>(sizeof(big_payload_tag)));
+ *found = true;
}
- }
+ };
- android_logger_list_close(logger_list);
+ RunLogTests(LOG_ID_SYSTEM, write_function, check_function);
- EXPECT_LE(LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag),
- static_cast<size_t>(max_len));
-
- // SLOP: Allow the underlying interface to optionally place a
- // terminating nul at the LOGGER_ENTRY_MAX_PAYLOAD's last byte
- // or not.
- if (ret == (max_len + static_cast<ssize_t>(sizeof(big_payload_tag)) - 1)) {
- --max_len;
- }
- EXPECT_EQ(ret, max_len + static_cast<ssize_t>(sizeof(big_payload_tag)));
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#ifdef ENABLE_FLAKY_TESTS
TEST(liblog, dual_reader) {
#ifdef __ANDROID__
+ static const int expected_count1 = 25;
+ static const int expected_count2 = 25;
- static const int num = 25;
+ pid_t pid = getpid();
+
+ auto logger_list1 = std::unique_ptr<struct logger_list, ListCloser>{
+ android_logger_list_open(LOG_ID_MAIN, ANDROID_LOG_RDONLY, expected_count1, pid)};
+ ASSERT_TRUE(logger_list1);
+
+ auto logger_list2 = std::unique_ptr<struct logger_list, ListCloser>{
+ android_logger_list_open(LOG_ID_MAIN, ANDROID_LOG_RDONLY, expected_count2, pid)};
+ ASSERT_TRUE(logger_list2);
for (int i = 25; i > 0; --i) {
static const char fmt[] = "dual_reader %02d";
@@ -1104,32 +1110,46 @@
LOG_FAILURE_RETRY(__android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO,
"liblog", buffer));
}
- usleep(1000000);
- struct logger_list* logger_list1;
- ASSERT_TRUE(NULL != (logger_list1 = android_logger_list_open(
- LOG_ID_MAIN,
- ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, num, 0)));
+ alarm(2);
+ auto alarm_guard = android::base::make_scope_guard([] { alarm(0); });
- struct logger_list* logger_list2;
+ // Wait until we see all messages with the blocking reader.
+ int count1 = 0;
+ int count2 = 0;
- if (NULL == (logger_list2 = android_logger_list_open(
- LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
- num - 10, 0))) {
- android_logger_list_close(logger_list1);
- ASSERT_TRUE(NULL != logger_list2);
+ while (count1 != expected_count2 || count2 != expected_count2) {
+ log_msg log_msg;
+ if (count1 < expected_count1) {
+ ASSERT_GT(android_logger_list_read(logger_list1.get(), &log_msg), 0);
+ count1++;
+ }
+ if (count2 < expected_count2) {
+ ASSERT_GT(android_logger_list_read(logger_list2.get(), &log_msg), 0);
+ count2++;
+ }
}
- int count1 = 0;
+ // Test again with the nonblocking reader.
+ auto logger_list_non_block1 =
+ std::unique_ptr<struct logger_list, ListCloser>{android_logger_list_open(
+ LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, expected_count1, pid)};
+ ASSERT_TRUE(logger_list_non_block1);
+
+ auto logger_list_non_block2 =
+ std::unique_ptr<struct logger_list, ListCloser>{android_logger_list_open(
+ LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, expected_count2, pid)};
+ ASSERT_TRUE(logger_list_non_block2);
+ count1 = 0;
+ count2 = 0;
bool done1 = false;
- int count2 = 0;
bool done2 = false;
- do {
+ while (!done1 || !done2) {
log_msg log_msg;
if (!done1) {
- if (android_logger_list_read(logger_list1, &log_msg) <= 0) {
+ if (android_logger_list_read(logger_list_non_block1.get(), &log_msg) <= 0) {
done1 = true;
} else {
++count1;
@@ -1137,26 +1157,21 @@
}
if (!done2) {
- if (android_logger_list_read(logger_list2, &log_msg) <= 0) {
+ if (android_logger_list_read(logger_list_non_block2.get(), &log_msg) <= 0) {
done2 = true;
} else {
++count2;
}
}
- } while ((!done1) || (!done2));
+ }
- android_logger_list_close(logger_list1);
- android_logger_list_close(logger_list2);
-
- EXPECT_EQ(num, count1);
- EXPECT_EQ(num - 10, count2);
+ EXPECT_EQ(expected_count1, count1);
+ EXPECT_EQ(expected_count2, count2);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // ENABLE_FLAKY_TESTS
-#ifdef ENABLE_FLAKY_TESTS
static bool checkPriForTag(AndroidLogFormat* p_format, const char* tag,
android_LogPriority pri) {
return android_log_shouldPrintLine(p_format, tag, pri) &&
@@ -1232,7 +1247,6 @@
android_log_format_free(p_format);
}
-#endif // ENABLE_FLAKY_TESTS
#ifdef ENABLE_FLAKY_TESTS
TEST(liblog, is_loggable) {
@@ -1886,101 +1900,71 @@
#endif // ENABLE_FLAKY_TESTS
#ifdef __ANDROID__
-static void android_errorWriteWithInfoLog_helper(int TAG, const char* SUBTAG,
- int UID, const char* payload,
- int DATA_LEN, int& count) {
- struct logger_list* logger_list;
+static void android_errorWriteWithInfoLog_helper(int tag, const char* subtag, int uid,
+ const char* payload, int data_len) {
+ auto write_function = [&] {
+ int ret = android_errorWriteWithInfoLog(tag, subtag, uid, payload, data_len);
+ ASSERT_LT(0, ret);
+ };
- pid_t pid = getpid();
-
- count = 0;
-
- ASSERT_TRUE(NULL !=
- (logger_list = android_logger_list_open(
- LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
- 1000, pid)));
-
- int retval_android_errorWriteWithinInfoLog =
- android_errorWriteWithInfoLog(TAG, SUBTAG, UID, payload, DATA_LEN);
- if (payload) {
- ASSERT_LT(0, retval_android_errorWriteWithinInfoLog);
- } else {
- ASSERT_GT(0, retval_android_errorWriteWithinInfoLog);
- }
-
- sleep(2);
-
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) {
- break;
- }
-
- char* eventData = log_msg.msg();
- if (!eventData) {
- continue;
- }
-
- char* original = eventData;
+ auto check_function = [&](log_msg log_msg, bool* found) {
+ char* event_data = log_msg.msg();
+ char* original = event_data;
// Tag
- auto* event_header = reinterpret_cast<android_event_header_t*>(eventData);
- eventData += sizeof(android_event_header_t);
-
- if (event_header->tag != TAG) {
- continue;
- }
-
- if (!payload) {
- // This tag should not have been written because the data was null
- ++count;
- break;
+ auto* event_header = reinterpret_cast<android_event_header_t*>(event_data);
+ event_data += sizeof(android_event_header_t);
+ if (event_header->tag != tag) {
+ return;
}
// List type
- auto* event_list = reinterpret_cast<android_event_list_t*>(eventData);
+ auto* event_list = reinterpret_cast<android_event_list_t*>(event_data);
ASSERT_EQ(EVENT_TYPE_LIST, event_list->type);
ASSERT_EQ(3, event_list->element_count);
- eventData += sizeof(android_event_list_t);
+ event_data += sizeof(android_event_list_t);
// Element #1: string type for subtag
- auto* event_string_subtag = reinterpret_cast<android_event_string_t*>(eventData);
+ auto* event_string_subtag = reinterpret_cast<android_event_string_t*>(event_data);
ASSERT_EQ(EVENT_TYPE_STRING, event_string_subtag->type);
- unsigned subtag_len = strlen(SUBTAG);
- if (subtag_len > 32) subtag_len = 32;
- ASSERT_EQ(static_cast<int32_t>(subtag_len), event_string_subtag->length);
- if (memcmp(SUBTAG, &event_string_subtag->data, subtag_len)) {
- continue;
+ int32_t subtag_len = strlen(subtag);
+ if (subtag_len > 32) {
+ subtag_len = 32;
}
- eventData += sizeof(android_event_string_t) + subtag_len;
+ ASSERT_EQ(subtag_len, event_string_subtag->length);
+ if (memcmp(subtag, &event_string_subtag->data, subtag_len)) {
+ return;
+ }
+ event_data += sizeof(android_event_string_t) + subtag_len;
// Element #2: int type for uid
- auto* event_int_uid = reinterpret_cast<android_event_int_t*>(eventData);
+ auto* event_int_uid = reinterpret_cast<android_event_int_t*>(event_data);
ASSERT_EQ(EVENT_TYPE_INT, event_int_uid->type);
- ASSERT_EQ(UID, event_int_uid->data);
- eventData += sizeof(android_event_int_t);
+ ASSERT_EQ(uid, event_int_uid->data);
+ event_data += sizeof(android_event_int_t);
// Element #3: string type for data
- auto* event_string_data = reinterpret_cast<android_event_string_t*>(eventData);
+ auto* event_string_data = reinterpret_cast<android_event_string_t*>(event_data);
ASSERT_EQ(EVENT_TYPE_STRING, event_string_data->type);
- size_t dataLen = event_string_data->length;
- if (DATA_LEN < 512) ASSERT_EQ(DATA_LEN, (int)dataLen);
- if (memcmp(payload, &event_string_data->data, dataLen)) {
- continue;
+ int32_t message_data_len = event_string_data->length;
+ if (data_len < 512) {
+ ASSERT_EQ(data_len, message_data_len);
}
- eventData += sizeof(android_event_string_t);
+ if (memcmp(payload, &event_string_data->data, message_data_len) != 0) {
+ return;
+ }
+ event_data += sizeof(android_event_string_t);
- if (DATA_LEN >= 512) {
- eventData += dataLen;
+ if (data_len >= 512) {
+ event_data += message_data_len;
// 4 bytes for the tag, and max_payload_buf should be truncated.
- ASSERT_LE(4 + 512, eventData - original); // worst expectations
- ASSERT_GT(4 + DATA_LEN, eventData - original); // must be truncated
+ ASSERT_LE(4 + 512, event_data - original); // worst expectations
+ ASSERT_GT(4 + data_len, event_data - original); // must be truncated
}
+ *found = true;
+ };
- ++count;
- }
-
- android_logger_list_close(logger_list);
+ RunLogTests(LOG_ID_EVENTS, write_function, check_function);
}
#endif
@@ -1995,10 +1979,7 @@
TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__typical) {
#ifdef __ANDROID__
- int count;
- android_errorWriteWithInfoLog_helper(UNIQUE_TAG(1), "test-subtag", -1,
- max_payload_buf, 200, count);
- EXPECT_EQ(1, count);
+ android_errorWriteWithInfoLog_helper(UNIQUE_TAG(1), "test-subtag", -1, max_payload_buf, 200);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
@@ -2007,23 +1988,20 @@
TEST(liblog,
android_errorWriteWithInfoLog__android_logger_list_read__data_too_large) {
#ifdef __ANDROID__
- int count;
- android_errorWriteWithInfoLog_helper(UNIQUE_TAG(2), "test-subtag", -1,
- max_payload_buf, sizeof(max_payload_buf),
- count);
- EXPECT_EQ(1, count);
+ android_errorWriteWithInfoLog_helper(UNIQUE_TAG(2), "test-subtag", -1, max_payload_buf,
+ sizeof(max_payload_buf));
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
+// TODO: Do we need to check that we didn't actually write anything if we return a failure here?
TEST(liblog,
android_errorWriteWithInfoLog__android_logger_list_read__null_data) {
#ifdef __ANDROID__
- int count;
- android_errorWriteWithInfoLog_helper(UNIQUE_TAG(3), "test-subtag", -1, NULL,
- 200, count);
- EXPECT_EQ(0, count);
+ int retval_android_errorWriteWithinInfoLog =
+ android_errorWriteWithInfoLog(UNIQUE_TAG(3), "test-subtag", -1, nullptr, 200);
+ ASSERT_GT(0, retval_android_errorWriteWithinInfoLog);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
@@ -2032,11 +2010,8 @@
TEST(liblog,
android_errorWriteWithInfoLog__android_logger_list_read__subtag_too_long) {
#ifdef __ANDROID__
- int count;
android_errorWriteWithInfoLog_helper(
- UNIQUE_TAG(4), "abcdefghijklmnopqrstuvwxyz now i know my abc", -1,
- max_payload_buf, 200, count);
- EXPECT_EQ(1, count);
+ UNIQUE_TAG(4), "abcdefghijklmnopqrstuvwxyz now i know my abc", -1, max_payload_buf, 200);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
@@ -2050,124 +2025,44 @@
buf_write_test(max_payload_buf);
}
-#ifdef __ANDROID__
-static void android_errorWriteLog_helper(int TAG, const char* SUBTAG,
- int& count) {
- struct logger_list* logger_list;
-
- pid_t pid = getpid();
-
- count = 0;
-
- // Do a Before and After on the count to measure the effect. Decrement
- // what we find in Before to set the stage.
- ASSERT_TRUE(NULL !=
- (logger_list = android_logger_list_open(
- LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
- 1000, pid)));
-
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) break;
-
- char* eventData = log_msg.msg();
- if (!eventData) continue;
-
- // Tag
- auto* event_header = reinterpret_cast<android_event_header_t*>(eventData);
- eventData += sizeof(android_event_header_t);
-
- if (event_header->tag != TAG) {
- continue;
- }
-
- if (!SUBTAG) {
- // This tag should not have been written because the data was null
- --count;
- break;
- }
-
- // List type
- eventData++;
- // Number of elements in list
- eventData++;
- // Element #1: string type for subtag
- eventData++;
-
- eventData += 4;
-
- if (memcmp(SUBTAG, eventData, strlen(SUBTAG))) continue;
- --count;
- }
-
- android_logger_list_close(logger_list);
-
- // Do an After on the count to measure the effect.
- ASSERT_TRUE(NULL !=
- (logger_list = android_logger_list_open(
- LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
- 1000, pid)));
-
- int retval_android_errorWriteLog = android_errorWriteLog(TAG, SUBTAG);
- if (SUBTAG) {
- ASSERT_LT(0, retval_android_errorWriteLog);
- } else {
- ASSERT_GT(0, retval_android_errorWriteLog);
- }
-
- sleep(2);
-
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) {
- break;
- }
-
- char* eventData = log_msg.msg();
- if (!eventData) {
- continue;
- }
-
- // Tag
- auto* event_header = reinterpret_cast<android_event_header_t*>(eventData);
- eventData += sizeof(android_event_header_t);
-
- if (event_header->tag != TAG) {
- continue;
- }
-
- if (!SUBTAG) {
- // This tag should not have been written because the data was null
- ++count;
- break;
- }
-
- // List type
- auto* event_list = reinterpret_cast<android_event_list_t*>(eventData);
- ASSERT_EQ(EVENT_TYPE_LIST, event_list->type);
- ASSERT_EQ(3, event_list->element_count);
- eventData += sizeof(android_event_list_t);
-
- // Element #1: string type for subtag
- auto* event_string = reinterpret_cast<android_event_string_t*>(eventData);
- ASSERT_EQ(EVENT_TYPE_STRING, event_string->type);
- ASSERT_EQ(static_cast<int32_t>(strlen(SUBTAG)), event_string->length);
-
- if (memcmp(SUBTAG, &event_string->data, strlen(SUBTAG))) {
- continue;
- }
- ++count;
- }
-
- android_logger_list_close(logger_list);
-}
-#endif
-
TEST(liblog, android_errorWriteLog__android_logger_list_read__success) {
#ifdef __ANDROID__
- int count;
- android_errorWriteLog_helper(UNIQUE_TAG(5), "test-subtag", count);
- EXPECT_EQ(1, count);
+ int kTag = UNIQUE_TAG(5);
+ const char* kSubTag = "test-subtag";
+
+ auto write_function = [&] {
+ int retval_android_errorWriteLog = android_errorWriteLog(kTag, kSubTag);
+ ASSERT_LT(0, retval_android_errorWriteLog);
+ };
+
+ auto check_function = [&](log_msg log_msg, bool* found) {
+ char* event_data = log_msg.msg();
+
+ // Tag
+ auto* event_header = reinterpret_cast<android_event_header_t*>(event_data);
+ event_data += sizeof(android_event_header_t);
+ if (event_header->tag != kTag) {
+ return;
+ }
+
+ // List type
+ auto* event_list = reinterpret_cast<android_event_list_t*>(event_data);
+ ASSERT_EQ(EVENT_TYPE_LIST, event_list->type);
+ ASSERT_EQ(3, event_list->element_count);
+ event_data += sizeof(android_event_list_t);
+
+ // Element #1: string type for subtag
+ auto* event_string_subtag = reinterpret_cast<android_event_string_t*>(event_data);
+ ASSERT_EQ(EVENT_TYPE_STRING, event_string_subtag->type);
+ int32_t subtag_len = strlen(kSubTag);
+ ASSERT_EQ(subtag_len, event_string_subtag->length);
+ if (memcmp(kSubTag, &event_string_subtag->data, subtag_len) == 0) {
+ *found = true;
+ }
+ };
+
+ RunLogTests(LOG_ID_EVENTS, write_function, check_function);
+
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
@@ -2175,9 +2070,7 @@
TEST(liblog, android_errorWriteLog__android_logger_list_read__null_subtag) {
#ifdef __ANDROID__
- int count;
- android_errorWriteLog_helper(UNIQUE_TAG(6), NULL, count);
- EXPECT_EQ(0, count);
+ EXPECT_LT(android_errorWriteLog(UNIQUE_TAG(6), nullptr), 0);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
@@ -2595,52 +2488,21 @@
static void create_android_logger(const char* (*fn)(uint32_t tag,
size_t& expected_len)) {
- struct logger_list* logger_list;
+ size_t expected_len;
+ const char* expected_string;
+ auto write_function = [&] {
+ expected_string = (*fn)(1005, expected_len);
+ ASSERT_NE(nullptr, expected_string);
+ };
pid_t pid = getpid();
-
- ASSERT_TRUE(NULL !=
- (logger_list = android_logger_list_open(
- LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
- 1000, pid)));
-
-#ifdef __ANDROID__
- log_time ts(android_log_clockid());
-#else
- log_time ts(CLOCK_REALTIME);
-#endif
-
- size_t expected_len;
- const char* expected_string = (*fn)(1005, expected_len);
-
- if (!expected_string) {
- android_logger_list_close(logger_list);
- return;
- }
-
- usleep(1000000);
-
- int count = 0;
-
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) {
- break;
- }
-
- ASSERT_EQ(log_msg.entry.pid, pid);
-
- if ((log_msg.entry.sec < (ts.tv_sec - 1)) ||
- ((ts.tv_sec + 1) < log_msg.entry.sec) ||
- ((size_t)log_msg.entry.len != expected_len) ||
- (log_msg.id() != LOG_ID_EVENTS)) {
- continue;
+ auto check_function = [&](log_msg log_msg, bool* found) {
+ if (static_cast<size_t>(log_msg.entry.len) != expected_len) {
+ return;
}
char* eventData = log_msg.msg();
- ++count;
-
AndroidLogFormat* logformat = android_log_format_new();
EXPECT_TRUE(NULL != logformat);
AndroidLogEntry entry;
@@ -2676,11 +2538,10 @@
}
EXPECT_EQ(0, buffer_to_string);
EXPECT_STREQ(expected_string, msgBuf);
- }
+ *found = true;
+ };
- EXPECT_EQ(1, count);
-
- android_logger_list_close(logger_list);
+ RunLogTests(LOG_ID_EVENTS, write_function, check_function);
}
#endif
@@ -2764,7 +2625,6 @@
#endif
}
-#ifdef ENABLE_FLAKY_TESTS
TEST(liblog, create_android_logger_overflow) {
android_log_context ctx;
@@ -2791,7 +2651,6 @@
EXPECT_LE(0, android_log_destroy(&ctx));
ASSERT_TRUE(NULL == ctx);
}
-#endif // ENABLE_FLAKY_TESTS
#ifdef ENABLE_FLAKY_TESTS
#ifdef __ANDROID__
@@ -2932,7 +2791,6 @@
}
#endif // ENABLE_FLAKY_TESTS
-#ifdef ENABLE_FLAKY_TESTS
TEST(liblog, android_lookupEventTagNum) {
#ifdef __ANDROID__
EventTagMap* map = android_openEventTagMap(NULL);
@@ -2949,4 +2807,3 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // ENABLE_FLAKY_TESTS
diff --git a/liblog/tests/log_read_test.cpp b/liblog/tests/log_read_test.cpp
index 443c3ea..1be99aa 100644
--- a/liblog/tests/log_read_test.cpp
+++ b/liblog/tests/log_read_test.cpp
@@ -29,54 +29,6 @@
// Do not use anything in log/log_time.h despite side effects of the above.
#include <private/android_logger.h>
-TEST(liblog, __android_log_write__android_logger_list_read) {
-#ifdef __ANDROID__
- pid_t pid = getpid();
-
- struct logger_list* logger_list;
- ASSERT_TRUE(
- NULL !=
- (logger_list = android_logger_list_open(
- LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
- struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- std::string buf = android::base::StringPrintf("pid=%u ts=%ld.%09ld", pid,
- ts.tv_sec, ts.tv_nsec);
- static const char tag[] =
- "liblog.__android_log_write__android_logger_list_read";
- static const char prio = ANDROID_LOG_DEBUG;
- ASSERT_LT(0, __android_log_write(prio, tag, buf.c_str()));
- usleep(1000000);
-
- buf = std::string(&prio, sizeof(prio)) + tag + std::string("", 1) + buf +
- std::string("", 1);
-
- int count = 0;
-
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) break;
-
- EXPECT_EQ(log_msg.entry.pid, pid);
- // There may be a future where we leak "liblog" tagged LOG_ID_EVENT
- // binary messages through so that logger losses can be correlated?
- EXPECT_EQ(log_msg.id(), LOG_ID_MAIN);
-
- if (log_msg.entry.len != buf.length()) continue;
-
- if (buf != std::string(log_msg.msg(), log_msg.entry.len)) continue;
-
- ++count;
- }
- android_logger_list_close(logger_list);
-
- EXPECT_EQ(1, count);
-#else
- GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
-}
-
TEST(liblog, android_logger_get_) {
#ifdef __ANDROID__
// This test assumes the log buffers are filled with noise from
diff --git a/libmeminfo/include/meminfo/procmeminfo.h b/libmeminfo/include/meminfo/procmeminfo.h
index f782ec5..8c1280f 100644
--- a/libmeminfo/include/meminfo/procmeminfo.h
+++ b/libmeminfo/include/meminfo/procmeminfo.h
@@ -48,6 +48,10 @@
// Same as Maps() except, do not read the usage stats for each map.
const std::vector<Vma>& MapsWithoutUsageStats();
+ // If MapsWithoutUsageStats was called, this function will fill in
+ // usage stats for this single vma.
+ bool FillInVmaStats(Vma& vma);
+
// Collect all 'vma' or 'maps' from /proc/<pid>/smaps and store them in 'maps_'. Returns a
// constant reference to the vma vector after the collection is done.
//
diff --git a/libmeminfo/libmeminfo_test.cpp b/libmeminfo/libmeminfo_test.cpp
index cf5341d..378a4cd 100644
--- a/libmeminfo/libmeminfo_test.cpp
+++ b/libmeminfo/libmeminfo_test.cpp
@@ -101,6 +101,33 @@
}
}
+TEST(ProcMemInfo, MapsUsageFillInLater) {
+ ProcMemInfo proc_mem(pid);
+ const std::vector<Vma>& maps = proc_mem.MapsWithoutUsageStats();
+ EXPECT_FALSE(maps.empty());
+ for (auto& map : maps) {
+ Vma update_map(map);
+ ASSERT_EQ(map.start, update_map.start);
+ ASSERT_EQ(map.end, update_map.end);
+ ASSERT_EQ(map.offset, update_map.offset);
+ ASSERT_EQ(map.flags, update_map.flags);
+ ASSERT_EQ(map.name, update_map.name);
+ ASSERT_EQ(0, update_map.usage.vss);
+ ASSERT_EQ(0, update_map.usage.rss);
+ ASSERT_EQ(0, update_map.usage.pss);
+ ASSERT_EQ(0, update_map.usage.uss);
+ ASSERT_EQ(0, update_map.usage.swap);
+ ASSERT_EQ(0, update_map.usage.swap_pss);
+ ASSERT_EQ(0, update_map.usage.private_clean);
+ ASSERT_EQ(0, update_map.usage.private_dirty);
+ ASSERT_EQ(0, update_map.usage.shared_clean);
+ ASSERT_EQ(0, update_map.usage.shared_dirty);
+ ASSERT_TRUE(proc_mem.FillInVmaStats(update_map));
+ // Check that at least one usage stat was updated.
+ ASSERT_NE(0, update_map.usage.vss);
+ }
+}
+
TEST(ProcMemInfo, PageMapPresent) {
static constexpr size_t kNumPages = 20;
size_t pagesize = getpagesize();
diff --git a/libmeminfo/procmeminfo.cpp b/libmeminfo/procmeminfo.cpp
index 6f68ab4..9e9a705 100644
--- a/libmeminfo/procmeminfo.cpp
+++ b/libmeminfo/procmeminfo.cpp
@@ -244,6 +244,15 @@
return true;
}
+static int GetPagemapFd(pid_t pid) {
+ std::string pagemap_file = ::android::base::StringPrintf("/proc/%d/pagemap", pid);
+ int fd = TEMP_FAILURE_RETRY(open(pagemap_file.c_str(), O_RDONLY | O_CLOEXEC));
+ if (fd == -1) {
+ PLOG(ERROR) << "Failed to open " << pagemap_file;
+ }
+ return fd;
+}
+
bool ProcMemInfo::ReadMaps(bool get_wss, bool use_pageidle, bool get_usage_stats) {
// Each object reads /proc/<pid>/maps only once. This is done to make sure programs that are
// running for the lifetime of the system can recycle the objects and don't have to
@@ -269,11 +278,8 @@
return true;
}
- std::string pagemap_file = ::android::base::StringPrintf("/proc/%d/pagemap", pid_);
- ::android::base::unique_fd pagemap_fd(
- TEMP_FAILURE_RETRY(open(pagemap_file.c_str(), O_RDONLY | O_CLOEXEC)));
- if (pagemap_fd < 0) {
- PLOG(ERROR) << "Failed to open " << pagemap_file;
+ ::android::base::unique_fd pagemap_fd(GetPagemapFd(pid_));
+ if (pagemap_fd == -1) {
return false;
}
@@ -290,6 +296,20 @@
return true;
}
+bool ProcMemInfo::FillInVmaStats(Vma& vma) {
+ ::android::base::unique_fd pagemap_fd(GetPagemapFd(pid_));
+ if (pagemap_fd == -1) {
+ return false;
+ }
+
+ if (!ReadVmaStats(pagemap_fd.get(), vma, get_wss_, false)) {
+ LOG(ERROR) << "Failed to read page map for vma " << vma.name << "[" << vma.start << "-"
+ << vma.end << "]";
+ return false;
+ }
+ return true;
+}
+
bool ProcMemInfo::ReadVmaStats(int pagemap_fd, Vma& vma, bool get_wss, bool use_pageidle) {
PageAcct& pinfo = PageAcct::Instance();
if (get_wss && use_pageidle && !pinfo.InitPageAcct(true)) {
diff --git a/libmeminfo/tools/showmap.cpp b/libmeminfo/tools/showmap.cpp
index 8ea2108..72ab0f3 100644
--- a/libmeminfo/tools/showmap.cpp
+++ b/libmeminfo/tools/showmap.cpp
@@ -18,6 +18,7 @@
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
+#include <sys/mman.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <unistd.h>
@@ -139,6 +140,9 @@
if (!g_verbose && !g_show_addr) {
printf(" # ");
}
+ if (g_verbose) {
+ printf(" flags ");
+ }
printf(" object\n");
}
@@ -150,6 +154,9 @@
if (!g_verbose && !g_show_addr) {
printf("---- ");
}
+ if (g_verbose) {
+ printf("------ ");
+ }
printf("------------------------------\n");
}
@@ -169,6 +176,18 @@
if (!g_verbose && !g_show_addr) {
printf("%4" PRIu32 " ", v.count);
}
+ if (g_verbose) {
+ if (total) {
+ printf(" ");
+ } else {
+ std::string flags_str("---");
+ if (v.vma.flags & PROT_READ) flags_str[0] = 'r';
+ if (v.vma.flags & PROT_WRITE) flags_str[1] = 'w';
+ if (v.vma.flags & PROT_EXEC) flags_str[2] = 'x';
+
+ printf("%6s ", flags_str.c_str());
+ }
+ }
}
static int showmap(void) {
diff --git a/libnativebridge/.clang-format b/libnativebridge/.clang-format
deleted file mode 120000
index fd0645f..0000000
--- a/libnativebridge/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-../.clang-format-2
\ No newline at end of file
diff --git a/libnativebridge/Android.bp b/libnativebridge/Android.bp
deleted file mode 100644
index c97845d..0000000
--- a/libnativebridge/Android.bp
+++ /dev/null
@@ -1,65 +0,0 @@
-cc_defaults {
- name: "libnativebridge-defaults",
- cflags: [
- "-Werror",
- "-Wall",
- ],
- cppflags: [
- "-fvisibility=protected",
- ],
- header_libs: ["libnativebridge-headers"],
- export_header_lib_headers: ["libnativebridge-headers"],
-}
-
-cc_library_headers {
- name: "libnativebridge-headers",
-
- host_supported: true,
- export_include_dirs: ["include"],
-}
-
-cc_library {
- name: "libnativebridge",
- defaults: ["libnativebridge-defaults"],
- // TODO(oth): remove after moving under art/ (b/137364733)
- visibility: ["//visibility:public"],
-
- host_supported: true,
- srcs: ["native_bridge.cc"],
- header_libs: [
- "libbase_headers",
- ],
- shared_libs: [
- "liblog",
- ],
- // TODO(jiyong): remove this line after aosp/885921 lands
- export_include_dirs: ["include"],
-
- target: {
- android: {
- version_script: "libnativebridge.map.txt",
- },
- linux: {
- version_script: "libnativebridge.map.txt",
- },
- },
-
- stubs: {
- symbol_file: "libnativebridge.map.txt",
- versions: ["1"],
- },
-}
-
-// TODO(b/124250621): eliminate the need for this library
-cc_library {
- name: "libnativebridge_lazy",
- defaults: ["libnativebridge-defaults"],
- // TODO(oth): remove after moving under art/ (b/137364733)
- visibility: ["//visibility:public"],
-
- host_supported: false,
- srcs: ["native_bridge_lazy.cc"],
- required: ["libnativebridge"],
-}
-
-subdirs = ["tests"]
diff --git a/libnativebridge/CPPLINT.cfg b/libnativebridge/CPPLINT.cfg
deleted file mode 100644
index 578047b..0000000
--- a/libnativebridge/CPPLINT.cfg
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
-filter=-build/header_guard
-filter=-whitespace/comments
-filter=-whitespace/parens
diff --git a/libnativebridge/OWNERS b/libnativebridge/OWNERS
deleted file mode 100644
index daf87f4..0000000
--- a/libnativebridge/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-dimitry@google.com
-eaeltsin@google.com
-ngeoffray@google.com
-oth@google.com
diff --git a/libnativebridge/include/nativebridge/native_bridge.h b/libnativebridge/include/nativebridge/native_bridge.h
deleted file mode 100644
index e9c9500..0000000
--- a/libnativebridge/include/nativebridge/native_bridge.h
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef NATIVE_BRIDGE_H_
-#define NATIVE_BRIDGE_H_
-
-#include <signal.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include "jni.h"
-
-#ifdef __cplusplus
-namespace android {
-extern "C" {
-#endif // __cplusplus
-
-struct NativeBridgeRuntimeCallbacks;
-struct NativeBridgeRuntimeValues;
-
-// Function pointer type for sigaction. This is mostly the signature of a signal handler, except
-// for the return type. The runtime needs to know whether the signal was handled or should be given
-// to the chain.
-typedef bool (*NativeBridgeSignalHandlerFn)(int, siginfo_t*, void*);
-
-// Open the native bridge, if any. Should be called by Runtime::Init(). A null library filename
-// signals that we do not want to load a native bridge.
-bool LoadNativeBridge(const char* native_bridge_library_filename,
- const struct NativeBridgeRuntimeCallbacks* runtime_callbacks);
-
-// Quick check whether a native bridge will be needed. This is based off of the instruction set
-// of the process.
-bool NeedsNativeBridge(const char* instruction_set);
-
-// Do the early initialization part of the native bridge, if necessary. This should be done under
-// high privileges.
-bool PreInitializeNativeBridge(const char* app_data_dir, const char* instruction_set);
-
-// Initialize the native bridge, if any. Should be called by Runtime::DidForkFromZygote. The JNIEnv*
-// will be used to modify the app environment for the bridge.
-bool InitializeNativeBridge(JNIEnv* env, const char* instruction_set);
-
-// Unload the native bridge, if any. Should be called by Runtime::DidForkFromZygote.
-void UnloadNativeBridge();
-
-// Check whether a native bridge is available (opened or initialized). Requires a prior call to
-// LoadNativeBridge.
-bool NativeBridgeAvailable();
-
-// Check whether a native bridge is available (initialized). Requires a prior call to
-// LoadNativeBridge & InitializeNativeBridge.
-bool NativeBridgeInitialized();
-
-// Load a shared library that is supported by the native bridge.
-//
-// Starting with v3, NativeBridge has two scenarios: with/without namespace.
-// Use NativeBridgeLoadLibraryExt() instead in namespace scenario.
-void* NativeBridgeLoadLibrary(const char* libpath, int flag);
-
-// Get a native bridge trampoline for specified native method.
-void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty, uint32_t len);
-
-// True if native library paths are valid and is for an ABI that is supported by native bridge.
-// The *libpath* must point to a library.
-//
-// Starting with v3, NativeBridge has two scenarios: with/without namespace.
-// Use NativeBridgeIsPathSupported() instead in namespace scenario.
-bool NativeBridgeIsSupported(const char* libpath);
-
-// Returns the version number of the native bridge. This information is available after a
-// successful LoadNativeBridge() and before closing it, that is, as long as NativeBridgeAvailable()
-// returns true. Returns 0 otherwise.
-uint32_t NativeBridgeGetVersion();
-
-// Returns a signal handler that the bridge would like to be managed. Only valid for a native
-// bridge supporting the version 2 interface. Will return null if the bridge does not support
-// version 2, or if it doesn't have a signal handler it wants to be known.
-NativeBridgeSignalHandlerFn NativeBridgeGetSignalHandler(int signal);
-
-// Returns whether we have seen a native bridge error. This could happen because the library
-// was not found, rejected, could not be initialized and so on.
-//
-// This functionality is mainly for testing.
-bool NativeBridgeError();
-
-// Returns whether a given string is acceptable as a native bridge library filename.
-//
-// This functionality is exposed mainly for testing.
-bool NativeBridgeNameAcceptable(const char* native_bridge_library_filename);
-
-// Decrements the reference count on the dynamic library handler. If the reference count drops
-// to zero then the dynamic library is unloaded. Returns 0 on success and non-zero on error.
-int NativeBridgeUnloadLibrary(void* handle);
-
-// Get last error message of native bridge when fail to load library or search symbol.
-// This is reflection of dlerror() for native bridge.
-const char* NativeBridgeGetError();
-
-struct native_bridge_namespace_t;
-
-// True if native library paths are valid and is for an ABI that is supported by native bridge.
-// Different from NativeBridgeIsSupported(), the *path* here must be a directory containing
-// libraries of an ABI.
-//
-// Starting with v3, NativeBridge has two scenarios: with/without namespace.
-// Use NativeBridgeIsSupported() instead in non-namespace scenario.
-bool NativeBridgeIsPathSupported(const char* path);
-
-// Initializes anonymous namespace.
-// NativeBridge's peer of android_init_anonymous_namespace() of dynamic linker.
-//
-// The anonymous namespace is used in the case when a NativeBridge implementation
-// cannot identify the caller of dlopen/dlsym which happens for the code not loaded
-// by dynamic linker; for example calls from the mono-compiled code.
-//
-// Starting with v3, NativeBridge has two scenarios: with/without namespace.
-// Should not use in non-namespace scenario.
-bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
- const char* anon_ns_library_path);
-
-// Create new namespace in which native libraries will be loaded.
-// NativeBridge's peer of android_create_namespace() of dynamic linker.
-//
-// The libraries in the namespace are searched by folowing order:
-// 1. ld_library_path (Think of this as namespace-local LD_LIBRARY_PATH)
-// 2. In directories specified by DT_RUNPATH of the "needed by" binary.
-// 3. deault_library_path (This of this as namespace-local default library path)
-//
-// Starting with v3, NativeBridge has two scenarios: with/without namespace.
-// Should not use in non-namespace scenario.
-struct native_bridge_namespace_t* NativeBridgeCreateNamespace(
- const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
- const char* permitted_when_isolated_path, struct native_bridge_namespace_t* parent_ns);
-
-// Creates a link which shares some libraries from one namespace to another.
-// NativeBridge's peer of android_link_namespaces() of dynamic linker.
-//
-// Starting with v3, NativeBridge has two scenarios: with/without namespace.
-// Should not use in non-namespace scenario.
-bool NativeBridgeLinkNamespaces(struct native_bridge_namespace_t* from,
- struct native_bridge_namespace_t* to,
- const char* shared_libs_sonames);
-
-// Load a shared library with namespace key that is supported by the native bridge.
-// NativeBridge's peer of android_dlopen_ext() of dynamic linker, only supports namespace
-// extension.
-//
-// Starting with v3, NativeBridge has two scenarios: with/without namespace.
-// Use NativeBridgeLoadLibrary() instead in non-namespace scenario.
-void* NativeBridgeLoadLibraryExt(const char* libpath, int flag,
- struct native_bridge_namespace_t* ns);
-
-// Returns exported namespace by the name. This is a reflection of
-// android_get_exported_namespace function. Introduced in v5.
-struct native_bridge_namespace_t* NativeBridgeGetExportedNamespace(const char* name);
-
-// Native bridge interfaces to runtime.
-struct NativeBridgeCallbacks {
- // Version number of the interface.
- uint32_t version;
-
- // Initialize native bridge. Native bridge's internal implementation must ensure MT safety and
- // that the native bridge is initialized only once. Thus it is OK to call this interface for an
- // already initialized native bridge.
- //
- // Parameters:
- // runtime_cbs [IN] the pointer to NativeBridgeRuntimeCallbacks.
- // Returns:
- // true if initialization was successful.
- bool (*initialize)(const struct NativeBridgeRuntimeCallbacks* runtime_cbs,
- const char* private_dir, const char* instruction_set);
-
- // Load a shared library that is supported by the native bridge.
- //
- // Parameters:
- // libpath [IN] path to the shared library
- // flag [IN] the stardard RTLD_XXX defined in bionic dlfcn.h
- // Returns:
- // The opaque handle of the shared library if sucessful, otherwise NULL
- //
- // Starting with v3, NativeBridge has two scenarios: with/without namespace.
- // Use loadLibraryExt instead in namespace scenario.
- void* (*loadLibrary)(const char* libpath, int flag);
-
- // Get a native bridge trampoline for specified native method. The trampoline has same
- // sigature as the native method.
- //
- // Parameters:
- // handle [IN] the handle returned from loadLibrary
- // shorty [IN] short descriptor of native method
- // len [IN] length of shorty
- // Returns:
- // address of trampoline if successful, otherwise NULL
- void* (*getTrampoline)(void* handle, const char* name, const char* shorty, uint32_t len);
-
- // Check whether native library is valid and is for an ABI that is supported by native bridge.
- //
- // Parameters:
- // libpath [IN] path to the shared library
- // Returns:
- // TRUE if library is supported by native bridge, FALSE otherwise
- //
- // Starting with v3, NativeBridge has two scenarios: with/without namespace.
- // Use isPathSupported instead in namespace scenario.
- bool (*isSupported)(const char* libpath);
-
- // Provide environment values required by the app running with native bridge according to the
- // instruction set.
- //
- // Parameters:
- // instruction_set [IN] the instruction set of the app
- // Returns:
- // NULL if not supported by native bridge.
- // Otherwise, return all environment values to be set after fork.
- const struct NativeBridgeRuntimeValues* (*getAppEnv)(const char* instruction_set);
-
- // Added callbacks in version 2.
-
- // Check whether the bridge is compatible with the given version. A bridge may decide not to be
- // forwards- or backwards-compatible, and libnativebridge will then stop using it.
- //
- // Parameters:
- // bridge_version [IN] the version of libnativebridge.
- // Returns:
- // true if the native bridge supports the given version of libnativebridge.
- bool (*isCompatibleWith)(uint32_t bridge_version);
-
- // A callback to retrieve a native bridge's signal handler for the specified signal. The runtime
- // will ensure that the signal handler is being called after the runtime's own handler, but before
- // all chained handlers. The native bridge should not try to install the handler by itself, as
- // that will potentially lead to cycles.
- //
- // Parameters:
- // signal [IN] the signal for which the handler is asked for. Currently, only SIGSEGV is
- // supported by the runtime.
- // Returns:
- // NULL if the native bridge doesn't use a handler or doesn't want it to be managed by the
- // runtime.
- // Otherwise, a pointer to the signal handler.
- NativeBridgeSignalHandlerFn (*getSignalHandler)(int signal);
-
- // Added callbacks in version 3.
-
- // Decrements the reference count on the dynamic library handler. If the reference count drops
- // to zero then the dynamic library is unloaded.
- //
- // Parameters:
- // handle [IN] the handler of a dynamic library.
- //
- // Returns:
- // 0 on success, and nonzero on error.
- int (*unloadLibrary)(void* handle);
-
- // Dump the last failure message of native bridge when fail to load library or search symbol.
- //
- // Parameters:
- //
- // Returns:
- // A string describing the most recent error that occurred when load library
- // or lookup symbol via native bridge.
- const char* (*getError)();
-
- // Check whether library paths are supported by native bridge.
- //
- // Parameters:
- // library_path [IN] search paths for native libraries (directories separated by ':')
- // Returns:
- // TRUE if libraries within search paths are supported by native bridge, FALSE otherwise
- //
- // Starting with v3, NativeBridge has two scenarios: with/without namespace.
- // Use isSupported instead in non-namespace scenario.
- bool (*isPathSupported)(const char* library_path);
-
- // Initializes anonymous namespace at native bridge side.
- // NativeBridge's peer of android_init_anonymous_namespace() of dynamic linker.
- //
- // The anonymous namespace is used in the case when a NativeBridge implementation
- // cannot identify the caller of dlopen/dlsym which happens for the code not loaded
- // by dynamic linker; for example calls from the mono-compiled code.
- //
- // Parameters:
- // public_ns_sonames [IN] the name of "public" libraries.
- // anon_ns_library_path [IN] the library search path of (anonymous) namespace.
- // Returns:
- // true if the pass is ok.
- // Otherwise, false.
- //
- // Starting with v3, NativeBridge has two scenarios: with/without namespace.
- // Should not use in non-namespace scenario.
- bool (*initAnonymousNamespace)(const char* public_ns_sonames, const char* anon_ns_library_path);
-
- // Create new namespace in which native libraries will be loaded.
- // NativeBridge's peer of android_create_namespace() of dynamic linker.
- //
- // Parameters:
- // name [IN] the name of the namespace.
- // ld_library_path [IN] the first set of library search paths of the namespace.
- // default_library_path [IN] the second set of library search path of the namespace.
- // type [IN] the attribute of the namespace.
- // permitted_when_isolated_path [IN] the permitted path for isolated namespace(if it is).
- // parent_ns [IN] the pointer of the parent namespace to be inherited from.
- // Returns:
- // native_bridge_namespace_t* for created namespace or nullptr in the case of error.
- //
- // Starting with v3, NativeBridge has two scenarios: with/without namespace.
- // Should not use in non-namespace scenario.
- struct native_bridge_namespace_t* (*createNamespace)(const char* name,
- const char* ld_library_path,
- const char* default_library_path,
- uint64_t type,
- const char* permitted_when_isolated_path,
- struct native_bridge_namespace_t* parent_ns);
-
- // Creates a link which shares some libraries from one namespace to another.
- // NativeBridge's peer of android_link_namespaces() of dynamic linker.
- //
- // Parameters:
- // from [IN] the namespace where libraries are accessed.
- // to [IN] the namespace where libraries are loaded.
- // shared_libs_sonames [IN] the libraries to be shared.
- //
- // Returns:
- // Whether successed or not.
- //
- // Starting with v3, NativeBridge has two scenarios: with/without namespace.
- // Should not use in non-namespace scenario.
- bool (*linkNamespaces)(struct native_bridge_namespace_t* from,
- struct native_bridge_namespace_t* to, const char* shared_libs_sonames);
-
- // Load a shared library within a namespace.
- // NativeBridge's peer of android_dlopen_ext() of dynamic linker, only supports namespace
- // extension.
- //
- // Parameters:
- // libpath [IN] path to the shared library
- // flag [IN] the stardard RTLD_XXX defined in bionic dlfcn.h
- // ns [IN] the pointer of the namespace in which the library should be loaded.
- // Returns:
- // The opaque handle of the shared library if sucessful, otherwise NULL
- //
- // Starting with v3, NativeBridge has two scenarios: with/without namespace.
- // Use loadLibrary instead in non-namespace scenario.
- void* (*loadLibraryExt)(const char* libpath, int flag, struct native_bridge_namespace_t* ns);
-
- // Get native bridge version of vendor namespace.
- // The vendor namespace is the namespace used to load vendor public libraries.
- // With O release this namespace can be different from the default namespace.
- // For the devices without enable vendor namespaces this function should return null
- //
- // Returns:
- // vendor namespace or null if it was not set up for the device
- //
- // Starting with v5 (Android Q) this function is no longer used.
- // Use getExportedNamespace() below.
- struct native_bridge_namespace_t* (*getVendorNamespace)();
-
- // Get native bridge version of exported namespace. Peer of
- // android_get_exported_namespace(const char*) function.
- //
- // Returns:
- // exported namespace or null if it was not set up for the device
- struct native_bridge_namespace_t* (*getExportedNamespace)(const char* name);
-};
-
-// Runtime interfaces to native bridge.
-struct NativeBridgeRuntimeCallbacks {
- // Get shorty of a Java method. The shorty is supposed to be persistent in memory.
- //
- // Parameters:
- // env [IN] pointer to JNIenv.
- // mid [IN] Java methodID.
- // Returns:
- // short descriptor for method.
- const char* (*getMethodShorty)(JNIEnv* env, jmethodID mid);
-
- // Get number of native methods for specified class.
- //
- // Parameters:
- // env [IN] pointer to JNIenv.
- // clazz [IN] Java class object.
- // Returns:
- // number of native methods.
- uint32_t (*getNativeMethodCount)(JNIEnv* env, jclass clazz);
-
- // Get at most 'method_count' native methods for specified class 'clazz'. Results are outputed
- // via 'methods' [OUT]. The signature pointer in JNINativeMethod is reused as the method shorty.
- //
- // Parameters:
- // env [IN] pointer to JNIenv.
- // clazz [IN] Java class object.
- // methods [OUT] array of method with the name, shorty, and fnPtr.
- // method_count [IN] max number of elements in methods.
- // Returns:
- // number of method it actually wrote to methods.
- uint32_t (*getNativeMethods)(JNIEnv* env, jclass clazz, JNINativeMethod* methods,
- uint32_t method_count);
-};
-
-#ifdef __cplusplus
-} // extern "C"
-} // namespace android
-#endif // __cplusplus
-
-#endif // NATIVE_BRIDGE_H_
diff --git a/libnativebridge/libnativebridge.map.txt b/libnativebridge/libnativebridge.map.txt
deleted file mode 100644
index a6841a3..0000000
--- a/libnativebridge/libnativebridge.map.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# 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.
-#
-
-# TODO(b/122710865): Most of these uses come from libnativeloader, which should be bundled
-# together with libnativebridge in the APEX. Once this happens, prune this list.
-LIBNATIVEBRIDGE_1 {
- global:
- NativeBridgeIsSupported;
- NativeBridgeLoadLibrary;
- NativeBridgeUnloadLibrary;
- NativeBridgeGetError;
- NativeBridgeIsPathSupported;
- NativeBridgeCreateNamespace;
- NativeBridgeGetExportedNamespace;
- NativeBridgeLinkNamespaces;
- NativeBridgeLoadLibraryExt;
- NativeBridgeInitAnonymousNamespace;
- NativeBridgeInitialized;
- NativeBridgeGetTrampoline;
- LoadNativeBridge;
- PreInitializeNativeBridge;
- InitializeNativeBridge;
- NativeBridgeGetVersion;
- NativeBridgeGetSignalHandler;
- UnloadNativeBridge;
- NativeBridgeAvailable;
- NeedsNativeBridge;
- NativeBridgeError;
- NativeBridgeNameAcceptable;
- local:
- *;
-};
diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc
deleted file mode 100644
index 9adba9a..0000000
--- a/libnativebridge/native_bridge.cc
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#define LOG_TAG "nativebridge"
-
-#include "nativebridge/native_bridge.h"
-
-#include <dlfcn.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <cstring>
-
-#include <android-base/macros.h>
-#include <log/log.h>
-
-namespace android {
-
-#ifdef __APPLE__
-template <typename T>
-void UNUSED(const T&) {}
-#endif
-
-extern "C" {
-
-// Environment values required by the apps running with native bridge.
-struct NativeBridgeRuntimeValues {
- const char* os_arch;
- const char* cpu_abi;
- const char* cpu_abi2;
- const char* *supported_abis;
- int32_t abi_count;
-};
-
-// The symbol name exposed by native-bridge with the type of NativeBridgeCallbacks.
-static constexpr const char* kNativeBridgeInterfaceSymbol = "NativeBridgeItf";
-
-enum class NativeBridgeState {
- kNotSetup, // Initial state.
- kOpened, // After successful dlopen.
- kPreInitialized, // After successful pre-initialization.
- kInitialized, // After successful initialization.
- kClosed // Closed or errors.
-};
-
-static constexpr const char* kNotSetupString = "kNotSetup";
-static constexpr const char* kOpenedString = "kOpened";
-static constexpr const char* kPreInitializedString = "kPreInitialized";
-static constexpr const char* kInitializedString = "kInitialized";
-static constexpr const char* kClosedString = "kClosed";
-
-static const char* GetNativeBridgeStateString(NativeBridgeState state) {
- switch (state) {
- case NativeBridgeState::kNotSetup:
- return kNotSetupString;
-
- case NativeBridgeState::kOpened:
- return kOpenedString;
-
- case NativeBridgeState::kPreInitialized:
- return kPreInitializedString;
-
- case NativeBridgeState::kInitialized:
- return kInitializedString;
-
- case NativeBridgeState::kClosed:
- return kClosedString;
- }
-}
-
-// Current state of the native bridge.
-static NativeBridgeState state = NativeBridgeState::kNotSetup;
-
-// The version of NativeBridge implementation.
-// Different Nativebridge interface needs the service of different version of
-// Nativebridge implementation.
-// Used by isCompatibleWith() which is introduced in v2.
-enum NativeBridgeImplementationVersion {
- // first version, not used.
- DEFAULT_VERSION = 1,
- // The version which signal semantic is introduced.
- SIGNAL_VERSION = 2,
- // The version which namespace semantic is introduced.
- NAMESPACE_VERSION = 3,
- // The version with vendor namespaces
- VENDOR_NAMESPACE_VERSION = 4,
- // The version with runtime namespaces
- RUNTIME_NAMESPACE_VERSION = 5,
-};
-
-// Whether we had an error at some point.
-static bool had_error = false;
-
-// Handle of the loaded library.
-static void* native_bridge_handle = nullptr;
-// Pointer to the callbacks. Available as soon as LoadNativeBridge succeeds, but only initialized
-// later.
-static const NativeBridgeCallbacks* callbacks = nullptr;
-// Callbacks provided by the environment to the bridge. Passed to LoadNativeBridge.
-static const NativeBridgeRuntimeCallbacks* runtime_callbacks = nullptr;
-
-// The app's code cache directory.
-static char* app_code_cache_dir = nullptr;
-
-// Code cache directory (relative to the application private directory)
-// Ideally we'd like to call into framework to retrieve this name. However that's considered an
-// implementation detail and will require either hacks or consistent refactorings. We compromise
-// and hard code the directory name again here.
-static constexpr const char* kCodeCacheDir = "code_cache";
-
-// Characters allowed in a native bridge filename. The first character must
-// be in [a-zA-Z] (expected 'l' for "libx"). The rest must be in [a-zA-Z0-9._-].
-static bool CharacterAllowed(char c, bool first) {
- if (first) {
- return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
- } else {
- return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') ||
- (c == '.') || (c == '_') || (c == '-');
- }
-}
-
-static void ReleaseAppCodeCacheDir() {
- if (app_code_cache_dir != nullptr) {
- delete[] app_code_cache_dir;
- app_code_cache_dir = nullptr;
- }
-}
-
-// We only allow simple names for the library. It is supposed to be a file in
-// /system/lib or /vendor/lib. Only allow a small range of characters, that is
-// names consisting of [a-zA-Z0-9._-] and starting with [a-zA-Z].
-bool NativeBridgeNameAcceptable(const char* nb_library_filename) {
- const char* ptr = nb_library_filename;
- if (*ptr == 0) {
- // Emptry string. Allowed, means no native bridge.
- return true;
- } else {
- // First character must be [a-zA-Z].
- if (!CharacterAllowed(*ptr, true)) {
- // Found an invalid fist character, don't accept.
- ALOGE("Native bridge library %s has been rejected for first character %c",
- nb_library_filename,
- *ptr);
- return false;
- } else {
- // For the rest, be more liberal.
- ptr++;
- while (*ptr != 0) {
- if (!CharacterAllowed(*ptr, false)) {
- // Found an invalid character, don't accept.
- ALOGE("Native bridge library %s has been rejected for %c", nb_library_filename, *ptr);
- return false;
- }
- ptr++;
- }
- }
- return true;
- }
-}
-
-// The policy of invoking Nativebridge changed in v3 with/without namespace.
-// Suggest Nativebridge implementation not maintain backward-compatible.
-static bool isCompatibleWith(const uint32_t version) {
- // Libnativebridge is now designed to be forward-compatible. So only "0" is an unsupported
- // version.
- if (callbacks == nullptr || callbacks->version == 0 || version == 0) {
- return false;
- }
-
- // If this is a v2+ bridge, it may not be forwards- or backwards-compatible. Check.
- if (callbacks->version >= SIGNAL_VERSION) {
- return callbacks->isCompatibleWith(version);
- }
-
- return true;
-}
-
-static void CloseNativeBridge(bool with_error) {
- state = NativeBridgeState::kClosed;
- had_error |= with_error;
- ReleaseAppCodeCacheDir();
-}
-
-bool LoadNativeBridge(const char* nb_library_filename,
- const NativeBridgeRuntimeCallbacks* runtime_cbs) {
- // We expect only one place that calls LoadNativeBridge: Runtime::Init. At that point we are not
- // multi-threaded, so we do not need locking here.
-
- if (state != NativeBridgeState::kNotSetup) {
- // Setup has been called before. Ignore this call.
- if (nb_library_filename != nullptr) { // Avoids some log-spam for dalvikvm.
- ALOGW("Called LoadNativeBridge for an already set up native bridge. State is %s.",
- GetNativeBridgeStateString(state));
- }
- // Note: counts as an error, even though the bridge may be functional.
- had_error = true;
- return false;
- }
-
- if (nb_library_filename == nullptr || *nb_library_filename == 0) {
- CloseNativeBridge(false);
- return false;
- } else {
- if (!NativeBridgeNameAcceptable(nb_library_filename)) {
- CloseNativeBridge(true);
- } else {
- // Try to open the library.
- void* handle = dlopen(nb_library_filename, RTLD_LAZY);
- if (handle != nullptr) {
- callbacks = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle,
- kNativeBridgeInterfaceSymbol));
- if (callbacks != nullptr) {
- if (isCompatibleWith(NAMESPACE_VERSION)) {
- // Store the handle for later.
- native_bridge_handle = handle;
- } else {
- callbacks = nullptr;
- dlclose(handle);
- ALOGW("Unsupported native bridge interface.");
- }
- } else {
- dlclose(handle);
- }
- }
-
- // Two failure conditions: could not find library (dlopen failed), or could not find native
- // bridge interface (dlsym failed). Both are an error and close the native bridge.
- if (callbacks == nullptr) {
- CloseNativeBridge(true);
- } else {
- runtime_callbacks = runtime_cbs;
- state = NativeBridgeState::kOpened;
- }
- }
- return state == NativeBridgeState::kOpened;
- }
-}
-
-bool NeedsNativeBridge(const char* instruction_set) {
- if (instruction_set == nullptr) {
- ALOGE("Null instruction set in NeedsNativeBridge.");
- return false;
- }
- return strncmp(instruction_set, ABI_STRING, strlen(ABI_STRING) + 1) != 0;
-}
-
-bool PreInitializeNativeBridge(const char* app_data_dir_in, const char* instruction_set) {
- if (state != NativeBridgeState::kOpened) {
- ALOGE("Invalid state: native bridge is expected to be opened.");
- CloseNativeBridge(true);
- return false;
- }
-
- if (app_data_dir_in == nullptr) {
- ALOGE("Application private directory cannot be null.");
- CloseNativeBridge(true);
- return false;
- }
-
- // Create the path to the application code cache directory.
- // The memory will be release after Initialization or when the native bridge is closed.
- const size_t len = strlen(app_data_dir_in) + strlen(kCodeCacheDir) + 2; // '\0' + '/'
- app_code_cache_dir = new char[len];
- snprintf(app_code_cache_dir, len, "%s/%s", app_data_dir_in, kCodeCacheDir);
-
- // Bind-mount /system/lib{,64}/<isa>/cpuinfo to /proc/cpuinfo.
- // Failure is not fatal and will keep the native bridge in kPreInitialized.
- state = NativeBridgeState::kPreInitialized;
-
-#ifndef __APPLE__
- if (instruction_set == nullptr) {
- return true;
- }
- size_t isa_len = strlen(instruction_set);
- if (isa_len > 10) {
- // 10 is a loose upper bound on the currently known instruction sets (a tight bound is 7 for
- // x86_64 [including the trailing \0]). This is so we don't have to change here if there will
- // be another instruction set in the future.
- ALOGW("Instruction set %s is malformed, must be less than or equal to 10 characters.",
- instruction_set);
- return true;
- }
-
- // If the file does not exist, the mount command will fail,
- // so we save the extra file existence check.
- char cpuinfo_path[1024];
-
-#if defined(__ANDROID__)
- snprintf(cpuinfo_path, sizeof(cpuinfo_path), "/system/lib"
-#ifdef __LP64__
- "64"
-#endif // __LP64__
- "/%s/cpuinfo", instruction_set);
-#else // !__ANDROID__
- // To be able to test on the host, we hardwire a relative path.
- snprintf(cpuinfo_path, sizeof(cpuinfo_path), "./cpuinfo");
-#endif
-
- // Bind-mount.
- if (TEMP_FAILURE_RETRY(mount(cpuinfo_path, // Source.
- "/proc/cpuinfo", // Target.
- nullptr, // FS type.
- MS_BIND, // Mount flags: bind mount.
- nullptr)) == -1) { // "Data."
- ALOGW("Failed to bind-mount %s as /proc/cpuinfo: %s", cpuinfo_path, strerror(errno));
- }
-#else // __APPLE__
- UNUSED(instruction_set);
- ALOGW("Mac OS does not support bind-mounting. Host simulation of native bridge impossible.");
-#endif
-
- return true;
-}
-
-static void SetCpuAbi(JNIEnv* env, jclass build_class, const char* field, const char* value) {
- if (value != nullptr) {
- jfieldID field_id = env->GetStaticFieldID(build_class, field, "Ljava/lang/String;");
- if (field_id == nullptr) {
- env->ExceptionClear();
- ALOGW("Could not find %s field.", field);
- return;
- }
-
- jstring str = env->NewStringUTF(value);
- if (str == nullptr) {
- env->ExceptionClear();
- ALOGW("Could not create string %s.", value);
- return;
- }
-
- env->SetStaticObjectField(build_class, field_id, str);
- }
-}
-
-// Set up the environment for the bridged app.
-static void SetupEnvironment(const NativeBridgeCallbacks* callbacks, JNIEnv* env, const char* isa) {
- // Need a JNIEnv* to do anything.
- if (env == nullptr) {
- ALOGW("No JNIEnv* to set up app environment.");
- return;
- }
-
- // Query the bridge for environment values.
- const struct NativeBridgeRuntimeValues* env_values = callbacks->getAppEnv(isa);
- if (env_values == nullptr) {
- return;
- }
-
- // Keep the JNIEnv clean.
- jint success = env->PushLocalFrame(16); // That should be small and large enough.
- if (success < 0) {
- // Out of memory, really borked.
- ALOGW("Out of memory while setting up app environment.");
- env->ExceptionClear();
- return;
- }
-
- // Reset CPU_ABI & CPU_ABI2 to values required by the apps running with native bridge.
- if (env_values->cpu_abi != nullptr || env_values->cpu_abi2 != nullptr ||
- env_values->abi_count >= 0) {
- jclass bclass_id = env->FindClass("android/os/Build");
- if (bclass_id != nullptr) {
- SetCpuAbi(env, bclass_id, "CPU_ABI", env_values->cpu_abi);
- SetCpuAbi(env, bclass_id, "CPU_ABI2", env_values->cpu_abi2);
- } else {
- // For example in a host test environment.
- env->ExceptionClear();
- ALOGW("Could not find Build class.");
- }
- }
-
- if (env_values->os_arch != nullptr) {
- jclass sclass_id = env->FindClass("java/lang/System");
- if (sclass_id != nullptr) {
- jmethodID set_prop_id = env->GetStaticMethodID(sclass_id, "setUnchangeableSystemProperty",
- "(Ljava/lang/String;Ljava/lang/String;)V");
- if (set_prop_id != nullptr) {
- // Init os.arch to the value reqired by the apps running with native bridge.
- env->CallStaticVoidMethod(sclass_id, set_prop_id, env->NewStringUTF("os.arch"),
- env->NewStringUTF(env_values->os_arch));
- } else {
- env->ExceptionClear();
- ALOGW("Could not find System#setUnchangeableSystemProperty.");
- }
- } else {
- env->ExceptionClear();
- ALOGW("Could not find System class.");
- }
- }
-
- // Make it pristine again.
- env->PopLocalFrame(nullptr);
-}
-
-bool InitializeNativeBridge(JNIEnv* env, const char* instruction_set) {
- // We expect only one place that calls InitializeNativeBridge: Runtime::DidForkFromZygote. At that
- // point we are not multi-threaded, so we do not need locking here.
-
- if (state == NativeBridgeState::kPreInitialized) {
- // Check for code cache: if it doesn't exist try to create it.
- struct stat st;
- if (stat(app_code_cache_dir, &st) == -1) {
- if (errno == ENOENT) {
- if (mkdir(app_code_cache_dir, S_IRWXU | S_IRWXG | S_IXOTH) == -1) {
- ALOGW("Cannot create code cache directory %s: %s.", app_code_cache_dir, strerror(errno));
- ReleaseAppCodeCacheDir();
- }
- } else {
- ALOGW("Cannot stat code cache directory %s: %s.", app_code_cache_dir, strerror(errno));
- ReleaseAppCodeCacheDir();
- }
- } else if (!S_ISDIR(st.st_mode)) {
- ALOGW("Code cache is not a directory %s.", app_code_cache_dir);
- ReleaseAppCodeCacheDir();
- }
-
- // If we're still PreInitialized (dind't fail the code cache checks) try to initialize.
- if (state == NativeBridgeState::kPreInitialized) {
- if (callbacks->initialize(runtime_callbacks, app_code_cache_dir, instruction_set)) {
- SetupEnvironment(callbacks, env, instruction_set);
- state = NativeBridgeState::kInitialized;
- // We no longer need the code cache path, release the memory.
- ReleaseAppCodeCacheDir();
- } else {
- // Unload the library.
- dlclose(native_bridge_handle);
- CloseNativeBridge(true);
- }
- }
- } else {
- CloseNativeBridge(true);
- }
-
- return state == NativeBridgeState::kInitialized;
-}
-
-void UnloadNativeBridge() {
- // We expect only one place that calls UnloadNativeBridge: Runtime::DidForkFromZygote. At that
- // point we are not multi-threaded, so we do not need locking here.
-
- switch(state) {
- case NativeBridgeState::kOpened:
- case NativeBridgeState::kPreInitialized:
- case NativeBridgeState::kInitialized:
- // Unload.
- dlclose(native_bridge_handle);
- CloseNativeBridge(false);
- break;
-
- case NativeBridgeState::kNotSetup:
- // Not even set up. Error.
- CloseNativeBridge(true);
- break;
-
- case NativeBridgeState::kClosed:
- // Ignore.
- break;
- }
-}
-
-bool NativeBridgeError() {
- return had_error;
-}
-
-bool NativeBridgeAvailable() {
- return state == NativeBridgeState::kOpened
- || state == NativeBridgeState::kPreInitialized
- || state == NativeBridgeState::kInitialized;
-}
-
-bool NativeBridgeInitialized() {
- // Calls of this are supposed to happen in a state where the native bridge is stable, i.e., after
- // Runtime::DidForkFromZygote. In that case we do not need a lock.
- return state == NativeBridgeState::kInitialized;
-}
-
-void* NativeBridgeLoadLibrary(const char* libpath, int flag) {
- if (NativeBridgeInitialized()) {
- return callbacks->loadLibrary(libpath, flag);
- }
- return nullptr;
-}
-
-void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty,
- uint32_t len) {
- if (NativeBridgeInitialized()) {
- return callbacks->getTrampoline(handle, name, shorty, len);
- }
- return nullptr;
-}
-
-bool NativeBridgeIsSupported(const char* libpath) {
- if (NativeBridgeInitialized()) {
- return callbacks->isSupported(libpath);
- }
- return false;
-}
-
-uint32_t NativeBridgeGetVersion() {
- if (NativeBridgeAvailable()) {
- return callbacks->version;
- }
- return 0;
-}
-
-NativeBridgeSignalHandlerFn NativeBridgeGetSignalHandler(int signal) {
- if (NativeBridgeInitialized()) {
- if (isCompatibleWith(SIGNAL_VERSION)) {
- return callbacks->getSignalHandler(signal);
- } else {
- ALOGE("not compatible with version %d, cannot get signal handler", SIGNAL_VERSION);
- }
- }
- return nullptr;
-}
-
-int NativeBridgeUnloadLibrary(void* handle) {
- if (NativeBridgeInitialized()) {
- if (isCompatibleWith(NAMESPACE_VERSION)) {
- return callbacks->unloadLibrary(handle);
- } else {
- ALOGE("not compatible with version %d, cannot unload library", NAMESPACE_VERSION);
- }
- }
- return -1;
-}
-
-const char* NativeBridgeGetError() {
- if (NativeBridgeInitialized()) {
- if (isCompatibleWith(NAMESPACE_VERSION)) {
- return callbacks->getError();
- } else {
- return "native bridge implementation is not compatible with version 3, cannot get message";
- }
- }
- return "native bridge is not initialized";
-}
-
-bool NativeBridgeIsPathSupported(const char* path) {
- if (NativeBridgeInitialized()) {
- if (isCompatibleWith(NAMESPACE_VERSION)) {
- return callbacks->isPathSupported(path);
- } else {
- ALOGE("not compatible with version %d, cannot check via library path", NAMESPACE_VERSION);
- }
- }
- return false;
-}
-
-bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
- const char* anon_ns_library_path) {
- if (NativeBridgeInitialized()) {
- if (isCompatibleWith(NAMESPACE_VERSION)) {
- return callbacks->initAnonymousNamespace(public_ns_sonames, anon_ns_library_path);
- } else {
- ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION);
- }
- }
-
- return false;
-}
-
-native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name,
- const char* ld_library_path,
- const char* default_library_path,
- uint64_t type,
- const char* permitted_when_isolated_path,
- native_bridge_namespace_t* parent_ns) {
- if (NativeBridgeInitialized()) {
- if (isCompatibleWith(NAMESPACE_VERSION)) {
- return callbacks->createNamespace(name,
- ld_library_path,
- default_library_path,
- type,
- permitted_when_isolated_path,
- parent_ns);
- } else {
- ALOGE("not compatible with version %d, cannot create namespace %s", NAMESPACE_VERSION, name);
- }
- }
-
- return nullptr;
-}
-
-bool NativeBridgeLinkNamespaces(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
- const char* shared_libs_sonames) {
- if (NativeBridgeInitialized()) {
- if (isCompatibleWith(NAMESPACE_VERSION)) {
- return callbacks->linkNamespaces(from, to, shared_libs_sonames);
- } else {
- ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION);
- }
- }
-
- return false;
-}
-
-native_bridge_namespace_t* NativeBridgeGetExportedNamespace(const char* name) {
- if (!NativeBridgeInitialized()) {
- return nullptr;
- }
-
- if (isCompatibleWith(RUNTIME_NAMESPACE_VERSION)) {
- return callbacks->getExportedNamespace(name);
- }
-
- // sphal is vendor namespace name -> use v4 callback in the case NB callbacks
- // are not compatible with v5
- if (isCompatibleWith(VENDOR_NAMESPACE_VERSION) && name != nullptr && strcmp("sphal", name) == 0) {
- return callbacks->getVendorNamespace();
- }
-
- return nullptr;
-}
-
-void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns) {
- if (NativeBridgeInitialized()) {
- if (isCompatibleWith(NAMESPACE_VERSION)) {
- return callbacks->loadLibraryExt(libpath, flag, ns);
- } else {
- ALOGE("not compatible with version %d, cannot load library in namespace", NAMESPACE_VERSION);
- }
- }
- return nullptr;
-}
-
-} // extern "C"
-
-} // namespace android
diff --git a/libnativebridge/native_bridge_lazy.cc b/libnativebridge/native_bridge_lazy.cc
deleted file mode 100644
index 94c8084..0000000
--- a/libnativebridge/native_bridge_lazy.cc
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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 "nativebridge/native_bridge.h"
-#define LOG_TAG "nativebridge"
-
-#include <dlfcn.h>
-#include <errno.h>
-#include <string.h>
-
-#include <log/log.h>
-
-namespace android {
-
-namespace {
-
-void* GetLibHandle() {
- static void* handle = dlopen("libnativebridge.so", RTLD_NOW);
- LOG_FATAL_IF(handle == nullptr, "Failed to load libnativebridge.so: %s", dlerror());
- return handle;
-}
-
-template <typename FuncPtr>
-FuncPtr GetFuncPtr(const char* function_name) {
- auto f = reinterpret_cast<FuncPtr>(dlsym(GetLibHandle(), function_name));
- LOG_FATAL_IF(f == nullptr, "Failed to get address of %s: %s", function_name, dlerror());
- return f;
-}
-
-#define GET_FUNC_PTR(name) GetFuncPtr<decltype(&name)>(#name)
-
-} // namespace
-
-bool LoadNativeBridge(const char* native_bridge_library_filename,
- const struct NativeBridgeRuntimeCallbacks* runtime_callbacks) {
- static auto f = GET_FUNC_PTR(LoadNativeBridge);
- return f(native_bridge_library_filename, runtime_callbacks);
-}
-
-bool NeedsNativeBridge(const char* instruction_set) {
- static auto f = GET_FUNC_PTR(NeedsNativeBridge);
- return f(instruction_set);
-}
-
-bool PreInitializeNativeBridge(const char* app_data_dir, const char* instruction_set) {
- static auto f = GET_FUNC_PTR(PreInitializeNativeBridge);
- return f(app_data_dir, instruction_set);
-}
-
-bool InitializeNativeBridge(JNIEnv* env, const char* instruction_set) {
- static auto f = GET_FUNC_PTR(InitializeNativeBridge);
- return f(env, instruction_set);
-}
-
-void UnloadNativeBridge() {
- static auto f = GET_FUNC_PTR(UnloadNativeBridge);
- return f();
-}
-
-bool NativeBridgeAvailable() {
- static auto f = GET_FUNC_PTR(NativeBridgeAvailable);
- return f();
-}
-
-bool NativeBridgeInitialized() {
- static auto f = GET_FUNC_PTR(NativeBridgeInitialized);
- return f();
-}
-
-void* NativeBridgeLoadLibrary(const char* libpath, int flag) {
- static auto f = GET_FUNC_PTR(NativeBridgeLoadLibrary);
- return f(libpath, flag);
-}
-
-void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty, uint32_t len) {
- static auto f = GET_FUNC_PTR(NativeBridgeGetTrampoline);
- return f(handle, name, shorty, len);
-}
-
-bool NativeBridgeIsSupported(const char* libpath) {
- static auto f = GET_FUNC_PTR(NativeBridgeIsSupported);
- return f(libpath);
-}
-
-uint32_t NativeBridgeGetVersion() {
- static auto f = GET_FUNC_PTR(NativeBridgeGetVersion);
- return f();
-}
-
-NativeBridgeSignalHandlerFn NativeBridgeGetSignalHandler(int signal) {
- static auto f = GET_FUNC_PTR(NativeBridgeGetSignalHandler);
- return f(signal);
-}
-
-bool NativeBridgeError() {
- static auto f = GET_FUNC_PTR(NativeBridgeError);
- return f();
-}
-
-bool NativeBridgeNameAcceptable(const char* native_bridge_library_filename) {
- static auto f = GET_FUNC_PTR(NativeBridgeNameAcceptable);
- return f(native_bridge_library_filename);
-}
-
-int NativeBridgeUnloadLibrary(void* handle) {
- static auto f = GET_FUNC_PTR(NativeBridgeUnloadLibrary);
- return f(handle);
-}
-
-const char* NativeBridgeGetError() {
- static auto f = GET_FUNC_PTR(NativeBridgeGetError);
- return f();
-}
-
-bool NativeBridgeIsPathSupported(const char* path) {
- static auto f = GET_FUNC_PTR(NativeBridgeIsPathSupported);
- return f(path);
-}
-
-bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
- const char* anon_ns_library_path) {
- static auto f = GET_FUNC_PTR(NativeBridgeInitAnonymousNamespace);
- return f(public_ns_sonames, anon_ns_library_path);
-}
-
-struct native_bridge_namespace_t* NativeBridgeCreateNamespace(
- const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
- const char* permitted_when_isolated_path, struct native_bridge_namespace_t* parent_ns) {
- static auto f = GET_FUNC_PTR(NativeBridgeCreateNamespace);
- return f(name, ld_library_path, default_library_path, type, permitted_when_isolated_path,
- parent_ns);
-}
-
-bool NativeBridgeLinkNamespaces(struct native_bridge_namespace_t* from,
- struct native_bridge_namespace_t* to,
- const char* shared_libs_sonames) {
- static auto f = GET_FUNC_PTR(NativeBridgeLinkNamespaces);
- return f(from, to, shared_libs_sonames);
-}
-
-void* NativeBridgeLoadLibraryExt(const char* libpath, int flag,
- struct native_bridge_namespace_t* ns) {
- static auto f = GET_FUNC_PTR(NativeBridgeLoadLibraryExt);
- return f(libpath, flag, ns);
-}
-
-struct native_bridge_namespace_t* NativeBridgeGetVendorNamespace() {
- static auto f = GET_FUNC_PTR(NativeBridgeGetVendorNamespace);
- return f();
-}
-
-#undef GET_FUNC_PTR
-
-} // namespace android
diff --git a/libnativebridge/tests/Android.bp b/libnativebridge/tests/Android.bp
deleted file mode 100644
index 2bb8467..0000000
--- a/libnativebridge/tests/Android.bp
+++ /dev/null
@@ -1,110 +0,0 @@
-//
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-cc_defaults {
- name: "libnativebridge-dummy-defaults",
-
- host_supported: true,
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- ],
- header_libs: ["libnativebridge-headers"],
- cppflags: ["-fvisibility=protected"],
-}
-
-cc_library_shared {
- name: "libnativebridge-dummy",
- srcs: ["DummyNativeBridge.cpp"],
- defaults: ["libnativebridge-dummy-defaults"],
-}
-
-cc_library_shared {
- name: "libnativebridge2-dummy",
- srcs: ["DummyNativeBridge2.cpp"],
- defaults: ["libnativebridge-dummy-defaults"],
-}
-
-cc_library_shared {
- name: "libnativebridge3-dummy",
- srcs: ["DummyNativeBridge3.cpp"],
- defaults: ["libnativebridge-dummy-defaults"],
-}
-
-// Build the unit tests.
-cc_defaults {
- name: "libnativebridge-tests-defaults",
- test_per_src: true,
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- srcs: [
- "CodeCacheCreate_test.cpp",
- "CodeCacheExists_test.cpp",
- "CodeCacheStatFail_test.cpp",
- "CompleteFlow_test.cpp",
- "InvalidCharsNativeBridge_test.cpp",
- "NativeBridge2Signal_test.cpp",
- "NativeBridgeVersion_test.cpp",
- "NeedsNativeBridge_test.cpp",
- "PreInitializeNativeBridge_test.cpp",
- "PreInitializeNativeBridgeFail1_test.cpp",
- "PreInitializeNativeBridgeFail2_test.cpp",
- "ReSetupNativeBridge_test.cpp",
- "UnavailableNativeBridge_test.cpp",
- "ValidNameNativeBridge_test.cpp",
- "NativeBridge3UnloadLibrary_test.cpp",
- "NativeBridge3GetError_test.cpp",
- "NativeBridge3IsPathSupported_test.cpp",
- "NativeBridge3InitAnonymousNamespace_test.cpp",
- "NativeBridge3CreateNamespace_test.cpp",
- "NativeBridge3LoadLibraryExt_test.cpp",
- ],
-
- shared_libs: [
- "liblog",
- "libnativebridge-dummy",
- ],
- header_libs: ["libbase_headers"],
-}
-
-cc_test {
- name: "libnativebridge-tests",
- defaults: ["libnativebridge-tests-defaults"],
- host_supported: true,
- shared_libs: ["libnativebridge"],
-}
-
-cc_test {
- name: "libnativebridge-lazy-tests",
- defaults: ["libnativebridge-tests-defaults"],
- shared_libs: ["libnativebridge_lazy"],
-}
-
-// Build the test for the C API.
-cc_test {
- name: "libnativebridge-api-tests",
- host_supported: true,
- test_per_src: true,
- srcs: [
- "NativeBridgeApi.c",
- ],
- header_libs: ["libnativebridge-headers"],
-}
diff --git a/libnativebridge/tests/CodeCacheCreate_test.cpp b/libnativebridge/tests/CodeCacheCreate_test.cpp
deleted file mode 100644
index 58270c4..0000000
--- a/libnativebridge/tests/CodeCacheCreate_test.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2014 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 "NativeBridgeTest.h"
-
-#include <errno.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-namespace android {
-
-// Tests that the bridge initialization creates the code_cache if it doesn't
-// exists.
-TEST_F(NativeBridgeTest, CodeCacheCreate) {
- // Make sure that code_cache does not exists
- struct stat st;
- ASSERT_EQ(-1, stat(kCodeCache, &st));
- ASSERT_EQ(ENOENT, errno);
-
- // Init
- ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
- ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
- ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_FALSE(NativeBridgeError());
-
- // Check that code_cache was created
- ASSERT_EQ(0, stat(kCodeCache, &st));
- ASSERT_TRUE(S_ISDIR(st.st_mode));
-
- // Clean up
- UnloadNativeBridge();
- ASSERT_EQ(0, rmdir(kCodeCache));
-
- ASSERT_FALSE(NativeBridgeError());
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/CodeCacheExists_test.cpp b/libnativebridge/tests/CodeCacheExists_test.cpp
deleted file mode 100644
index 8ba0158..0000000
--- a/libnativebridge/tests/CodeCacheExists_test.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2014 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 "NativeBridgeTest.h"
-
-#include <errno.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-namespace android {
-
-// Tests that the bridge is initialized without errors if the code_cache already
-// exists.
-TEST_F(NativeBridgeTest, CodeCacheExists) {
- // Make sure that code_cache does not exists
- struct stat st;
- ASSERT_EQ(-1, stat(kCodeCache, &st));
- ASSERT_EQ(ENOENT, errno);
-
- // Create the code_cache
- ASSERT_EQ(0, mkdir(kCodeCache, S_IRWXU | S_IRWXG | S_IXOTH));
-
- // Init
- ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
- ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
- ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_FALSE(NativeBridgeError());
-
- // Check that the code cache is still there
- ASSERT_EQ(0, stat(kCodeCache, &st));
- ASSERT_TRUE(S_ISDIR(st.st_mode));
-
- // Clean up
- UnloadNativeBridge();
- ASSERT_EQ(0, rmdir(kCodeCache));
-
- ASSERT_FALSE(NativeBridgeError());
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/CodeCacheStatFail_test.cpp b/libnativebridge/tests/CodeCacheStatFail_test.cpp
deleted file mode 100644
index 4ea519e..0000000
--- a/libnativebridge/tests/CodeCacheStatFail_test.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2014 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 "NativeBridgeTest.h"
-
-#include <errno.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-namespace android {
-
-// Tests that the bridge is initialized without errors if the code_cache is
-// existed as a file.
-TEST_F(NativeBridgeTest, CodeCacheStatFail) {
- int fd = creat(kCodeCache, O_RDWR);
- ASSERT_NE(-1, fd);
- close(fd);
-
- struct stat st;
- ASSERT_EQ(-1, stat(kCodeCacheStatFail, &st));
- ASSERT_EQ(ENOTDIR, errno);
-
- // Init
- ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
- ASSERT_TRUE(PreInitializeNativeBridge(kCodeCacheStatFail, "isa"));
- ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_FALSE(NativeBridgeError());
-
- // Clean up
- UnloadNativeBridge();
-
- ASSERT_FALSE(NativeBridgeError());
- unlink(kCodeCache);
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/CompleteFlow_test.cpp b/libnativebridge/tests/CompleteFlow_test.cpp
deleted file mode 100644
index b033792..0000000
--- a/libnativebridge/tests/CompleteFlow_test.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2014 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 "NativeBridgeTest.h"
-
-#include <unistd.h>
-
-namespace android {
-
-TEST_F(NativeBridgeTest, CompleteFlow) {
- // Init
- ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
-
- // Basic calls to check that nothing crashes
- ASSERT_FALSE(NativeBridgeIsSupported(nullptr));
- ASSERT_EQ(nullptr, NativeBridgeLoadLibrary(nullptr, 0));
- ASSERT_EQ(nullptr, NativeBridgeGetTrampoline(nullptr, nullptr, nullptr, 0));
-
- // Unload
- UnloadNativeBridge();
-
- ASSERT_FALSE(NativeBridgeAvailable());
- ASSERT_FALSE(NativeBridgeError());
-
- // Clean-up code_cache
- ASSERT_EQ(0, rmdir(kCodeCache));
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/DummyNativeBridge.cpp b/libnativebridge/tests/DummyNativeBridge.cpp
deleted file mode 100644
index b9894f6..0000000
--- a/libnativebridge/tests/DummyNativeBridge.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-// A dummy implementation of the native-bridge interface.
-
-#include "nativebridge/native_bridge.h"
-
-// NativeBridgeCallbacks implementations
-extern "C" bool native_bridge_initialize(const android::NativeBridgeRuntimeCallbacks* /* art_cbs */,
- const char* /* app_code_cache_dir */,
- const char* /* isa */) {
- return true;
-}
-
-extern "C" void* native_bridge_loadLibrary(const char* /* libpath */, int /* flag */) {
- return nullptr;
-}
-
-extern "C" void* native_bridge_getTrampoline(void* /* handle */, const char* /* name */,
- const char* /* shorty */, uint32_t /* len */) {
- return nullptr;
-}
-
-extern "C" bool native_bridge_isSupported(const char* /* libpath */) {
- return false;
-}
-
-extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge_getAppEnv(
- const char* /* abi */) {
- return nullptr;
-}
-
-android::NativeBridgeCallbacks NativeBridgeItf {
- .version = 1,
- .initialize = &native_bridge_initialize,
- .loadLibrary = &native_bridge_loadLibrary,
- .getTrampoline = &native_bridge_getTrampoline,
- .isSupported = &native_bridge_isSupported,
- .getAppEnv = &native_bridge_getAppEnv
-};
diff --git a/libnativebridge/tests/DummyNativeBridge2.cpp b/libnativebridge/tests/DummyNativeBridge2.cpp
deleted file mode 100644
index 6920c74..0000000
--- a/libnativebridge/tests/DummyNativeBridge2.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-// A dummy implementation of the native-bridge interface.
-
-#include "nativebridge/native_bridge.h"
-
-#include <signal.h>
-
-// NativeBridgeCallbacks implementations
-extern "C" bool native_bridge2_initialize(const android::NativeBridgeRuntimeCallbacks* /* art_cbs */,
- const char* /* app_code_cache_dir */,
- const char* /* isa */) {
- return true;
-}
-
-extern "C" void* native_bridge2_loadLibrary(const char* /* libpath */, int /* flag */) {
- return nullptr;
-}
-
-extern "C" void* native_bridge2_getTrampoline(void* /* handle */, const char* /* name */,
- const char* /* shorty */, uint32_t /* len */) {
- return nullptr;
-}
-
-extern "C" bool native_bridge2_isSupported(const char* /* libpath */) {
- return false;
-}
-
-extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge2_getAppEnv(
- const char* /* abi */) {
- return nullptr;
-}
-
-extern "C" bool native_bridge2_is_compatible_compatible_with(uint32_t version) {
- // For testing, allow 1 and 2, but disallow 3+.
- return version <= 2;
-}
-
-static bool native_bridge2_dummy_signal_handler(int, siginfo_t*, void*) {
- // TODO: Implement something here. We'd either have to have a death test with a log here, or
- // we'd have to be able to resume after the faulting instruction...
- return true;
-}
-
-extern "C" android::NativeBridgeSignalHandlerFn native_bridge2_get_signal_handler(int signal) {
- if (signal == SIGSEGV) {
- return &native_bridge2_dummy_signal_handler;
- }
- return nullptr;
-}
-
-android::NativeBridgeCallbacks NativeBridgeItf {
- .version = 2,
- .initialize = &native_bridge2_initialize,
- .loadLibrary = &native_bridge2_loadLibrary,
- .getTrampoline = &native_bridge2_getTrampoline,
- .isSupported = &native_bridge2_isSupported,
- .getAppEnv = &native_bridge2_getAppEnv,
- .isCompatibleWith = &native_bridge2_is_compatible_compatible_with,
- .getSignalHandler = &native_bridge2_get_signal_handler
-};
-
diff --git a/libnativebridge/tests/DummyNativeBridge3.cpp b/libnativebridge/tests/DummyNativeBridge3.cpp
deleted file mode 100644
index 4ef1c82..0000000
--- a/libnativebridge/tests/DummyNativeBridge3.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-// A dummy implementation of the native-bridge interface.
-
-#include "nativebridge/native_bridge.h"
-
-#include <signal.h>
-
-// NativeBridgeCallbacks implementations
-extern "C" bool native_bridge3_initialize(
- const android::NativeBridgeRuntimeCallbacks* /* art_cbs */,
- const char* /* app_code_cache_dir */,
- const char* /* isa */) {
- return true;
-}
-
-extern "C" void* native_bridge3_loadLibrary(const char* /* libpath */, int /* flag */) {
- return nullptr;
-}
-
-extern "C" void* native_bridge3_getTrampoline(void* /* handle */, const char* /* name */,
- const char* /* shorty */, uint32_t /* len */) {
- return nullptr;
-}
-
-extern "C" bool native_bridge3_isSupported(const char* /* libpath */) {
- return false;
-}
-
-extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge3_getAppEnv(
- const char* /* abi */) {
- return nullptr;
-}
-
-extern "C" bool native_bridge3_isCompatibleWith(uint32_t version) {
- // For testing, allow 1-3, but disallow 4+.
- return version <= 3;
-}
-
-static bool native_bridge3_dummy_signal_handler(int, siginfo_t*, void*) {
- // TODO: Implement something here. We'd either have to have a death test with a log here, or
- // we'd have to be able to resume after the faulting instruction...
- return true;
-}
-
-extern "C" android::NativeBridgeSignalHandlerFn native_bridge3_getSignalHandler(int signal) {
- if (signal == SIGSEGV) {
- return &native_bridge3_dummy_signal_handler;
- }
- return nullptr;
-}
-
-extern "C" int native_bridge3_unloadLibrary(void* /* handle */) {
- return 0;
-}
-
-extern "C" const char* native_bridge3_getError() {
- return nullptr;
-}
-
-extern "C" bool native_bridge3_isPathSupported(const char* /* path */) {
- return true;
-}
-
-extern "C" bool native_bridge3_initAnonymousNamespace(const char* /* public_ns_sonames */,
- const char* /* anon_ns_library_path */) {
- return true;
-}
-
-extern "C" android::native_bridge_namespace_t*
-native_bridge3_createNamespace(const char* /* name */,
- const char* /* ld_library_path */,
- const char* /* default_library_path */,
- uint64_t /* type */,
- const char* /* permitted_when_isolated_path */,
- android::native_bridge_namespace_t* /* parent_ns */) {
- return nullptr;
-}
-
-extern "C" bool native_bridge3_linkNamespaces(android::native_bridge_namespace_t* /* from */,
- android::native_bridge_namespace_t* /* to */,
- const char* /* shared_libs_soname */) {
- return true;
-}
-
-extern "C" void* native_bridge3_loadLibraryExt(const char* /* libpath */,
- int /* flag */,
- android::native_bridge_namespace_t* /* ns */) {
- return nullptr;
-}
-
-android::NativeBridgeCallbacks NativeBridgeItf{
- // v1
- .version = 3,
- .initialize = &native_bridge3_initialize,
- .loadLibrary = &native_bridge3_loadLibrary,
- .getTrampoline = &native_bridge3_getTrampoline,
- .isSupported = &native_bridge3_isSupported,
- .getAppEnv = &native_bridge3_getAppEnv,
- // v2
- .isCompatibleWith = &native_bridge3_isCompatibleWith,
- .getSignalHandler = &native_bridge3_getSignalHandler,
- // v3
- .unloadLibrary = &native_bridge3_unloadLibrary,
- .getError = &native_bridge3_getError,
- .isPathSupported = &native_bridge3_isPathSupported,
- .initAnonymousNamespace = &native_bridge3_initAnonymousNamespace,
- .createNamespace = &native_bridge3_createNamespace,
- .linkNamespaces = &native_bridge3_linkNamespaces,
- .loadLibraryExt = &native_bridge3_loadLibraryExt};
diff --git a/libnativebridge/tests/InvalidCharsNativeBridge_test.cpp b/libnativebridge/tests/InvalidCharsNativeBridge_test.cpp
deleted file mode 100644
index 8f7973d..0000000
--- a/libnativebridge/tests/InvalidCharsNativeBridge_test.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2014 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 "NativeBridgeTest.h"
-
-namespace android {
-
-static const char* kTestName = "../librandom$@-bridge_not.existing.so";
-
-TEST_F(NativeBridgeTest, InvalidChars) {
- // Do one test actually calling setup.
- EXPECT_EQ(false, NativeBridgeError());
- LoadNativeBridge(kTestName, nullptr);
- // This should lead to an error for invalid characters.
- EXPECT_EQ(true, NativeBridgeError());
-
- // Further tests need to use NativeBridgeNameAcceptable, as the error
- // state can't be changed back.
- EXPECT_EQ(false, NativeBridgeNameAcceptable("."));
- EXPECT_EQ(false, NativeBridgeNameAcceptable(".."));
- EXPECT_EQ(false, NativeBridgeNameAcceptable("_"));
- EXPECT_EQ(false, NativeBridgeNameAcceptable("-"));
- EXPECT_EQ(false, NativeBridgeNameAcceptable("lib@.so"));
- EXPECT_EQ(false, NativeBridgeNameAcceptable("lib$.so"));
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/NativeBridge2Signal_test.cpp b/libnativebridge/tests/NativeBridge2Signal_test.cpp
deleted file mode 100644
index 44e45e3..0000000
--- a/libnativebridge/tests/NativeBridge2Signal_test.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2014 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 "NativeBridgeTest.h"
-
-#include <signal.h>
-#include <unistd.h>
-
-namespace android {
-
-constexpr const char* kNativeBridgeLibrary2 = "libnativebridge2-dummy.so";
-
-TEST_F(NativeBridgeTest, V2_Signal) {
- // Init
- ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary2, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
-
- ASSERT_EQ(2U, NativeBridgeGetVersion());
- ASSERT_NE(nullptr, NativeBridgeGetSignalHandler(SIGSEGV));
-
- // Clean-up code_cache
- ASSERT_EQ(0, rmdir(kCodeCache));
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/NativeBridge3CreateNamespace_test.cpp b/libnativebridge/tests/NativeBridge3CreateNamespace_test.cpp
deleted file mode 100644
index 668d942..0000000
--- a/libnativebridge/tests/NativeBridge3CreateNamespace_test.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2016 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 "NativeBridgeTest.h"
-
-namespace android {
-
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
-TEST_F(NativeBridgeTest, V3_CreateNamespace) {
- // Init
- ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
-
- ASSERT_EQ(3U, NativeBridgeGetVersion());
- ASSERT_EQ(nullptr, NativeBridgeCreateNamespace(nullptr, nullptr, nullptr,
- 0, nullptr, nullptr));
-
- // Clean-up code_cache
- ASSERT_EQ(0, rmdir(kCodeCache));
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/NativeBridge3GetError_test.cpp b/libnativebridge/tests/NativeBridge3GetError_test.cpp
deleted file mode 100644
index 0b9f582..0000000
--- a/libnativebridge/tests/NativeBridge3GetError_test.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2016 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 "NativeBridgeTest.h"
-
-namespace android {
-
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
-TEST_F(NativeBridgeTest, V3_GetError) {
- // Init
- ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
-
- ASSERT_EQ(3U, NativeBridgeGetVersion());
- ASSERT_EQ(nullptr, NativeBridgeGetError());
-
- // Clean-up code_cache
- ASSERT_EQ(0, rmdir(kCodeCache));
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp b/libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp
deleted file mode 100644
index b0d6b09..0000000
--- a/libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2016 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 "NativeBridgeTest.h"
-
-namespace android {
-
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
-TEST_F(NativeBridgeTest, V3_InitAnonymousNamespace) {
- // Init
- ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
-
- ASSERT_EQ(3U, NativeBridgeGetVersion());
- ASSERT_EQ(true, NativeBridgeInitAnonymousNamespace(nullptr, nullptr));
-
- // Clean-up code_cache
- ASSERT_EQ(0, rmdir(kCodeCache));
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/NativeBridge3IsPathSupported_test.cpp b/libnativebridge/tests/NativeBridge3IsPathSupported_test.cpp
deleted file mode 100644
index 325e40b..0000000
--- a/libnativebridge/tests/NativeBridge3IsPathSupported_test.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2016 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 "NativeBridgeTest.h"
-
-namespace android {
-
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
-TEST_F(NativeBridgeTest, V3_IsPathSupported) {
- // Init
- ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
-
- ASSERT_EQ(3U, NativeBridgeGetVersion());
- ASSERT_EQ(true, NativeBridgeIsPathSupported(nullptr));
-
- // Clean-up code_cache
- ASSERT_EQ(0, rmdir(kCodeCache));
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/NativeBridge3LoadLibraryExt_test.cpp b/libnativebridge/tests/NativeBridge3LoadLibraryExt_test.cpp
deleted file mode 100644
index 4caeb44..0000000
--- a/libnativebridge/tests/NativeBridge3LoadLibraryExt_test.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2016 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 "NativeBridgeTest.h"
-
-namespace android {
-
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
-TEST_F(NativeBridgeTest, V3_LoadLibraryExt) {
- // Init
- ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
-
- ASSERT_EQ(3U, NativeBridgeGetVersion());
- ASSERT_EQ(nullptr, NativeBridgeLoadLibraryExt(nullptr, 0, nullptr));
-
- // Clean-up code_cache
- ASSERT_EQ(0, rmdir(kCodeCache));
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/NativeBridge3UnloadLibrary_test.cpp b/libnativebridge/tests/NativeBridge3UnloadLibrary_test.cpp
deleted file mode 100644
index 93a979c..0000000
--- a/libnativebridge/tests/NativeBridge3UnloadLibrary_test.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2016 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 "NativeBridgeTest.h"
-
-namespace android {
-
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
-TEST_F(NativeBridgeTest, V3_UnloadLibrary) {
- // Init
- ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
- ASSERT_TRUE(NativeBridgeAvailable());
- ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
- ASSERT_TRUE(NativeBridgeAvailable());
-
- ASSERT_EQ(3U, NativeBridgeGetVersion());
- ASSERT_EQ(0, NativeBridgeUnloadLibrary(nullptr));
-
- // Clean-up code_cache
- ASSERT_EQ(0, rmdir(kCodeCache));
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/NativeBridgeApi.c b/libnativebridge/tests/NativeBridgeApi.c
deleted file mode 100644
index 7ab71fe..0000000
--- a/libnativebridge/tests/NativeBridgeApi.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.
- */
-
-/* The main purpose of this test is to ensure this C header compiles in C, so
- * that no C++ features inadvertently leak into the C ABI. */
-#include "nativebridge/native_bridge.h"
-
-int main(int argc, char** argv) {
- (void)argc;
- (void)argv;
- return 0;
-}
diff --git a/libnativebridge/tests/NativeBridgeTest.h b/libnativebridge/tests/NativeBridgeTest.h
deleted file mode 100644
index 0f99816..0000000
--- a/libnativebridge/tests/NativeBridgeTest.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef NATIVE_BRIDGE_TEST_H_
-#define NATIVE_BRIDGE_TEST_H_
-
-#define LOG_TAG "NativeBridge_test"
-
-#include <nativebridge/native_bridge.h>
-#include <gtest/gtest.h>
-
-constexpr const char* kNativeBridgeLibrary = "libnativebridge-dummy.so";
-constexpr const char* kCodeCache = "./code_cache";
-constexpr const char* kCodeCacheStatFail = "./code_cache/temp";
-constexpr const char* kNativeBridgeLibrary2 = "libnativebridge2-dummy.so";
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
-namespace android {
-
-class NativeBridgeTest : public testing::Test {
-};
-
-}; // namespace android
-
-#endif // NATIVE_BRIDGE_H_
-
diff --git a/libnativebridge/tests/NativeBridgeVersion_test.cpp b/libnativebridge/tests/NativeBridgeVersion_test.cpp
deleted file mode 100644
index d3f9a80..0000000
--- a/libnativebridge/tests/NativeBridgeVersion_test.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2015 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 "NativeBridgeTest.h"
-
-#include <unistd.h>
-
-namespace android {
-
-TEST_F(NativeBridgeTest, Version) {
- // When a bridge isn't loaded, we expect 0.
- EXPECT_EQ(NativeBridgeGetVersion(), 0U);
-
- // After our dummy bridge has been loaded, we expect 1.
- ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
- EXPECT_EQ(NativeBridgeGetVersion(), 1U);
-
- // Unload
- UnloadNativeBridge();
-
- // Version information is gone.
- EXPECT_EQ(NativeBridgeGetVersion(), 0U);
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/NeedsNativeBridge_test.cpp b/libnativebridge/tests/NeedsNativeBridge_test.cpp
deleted file mode 100644
index c8ff743..0000000
--- a/libnativebridge/tests/NeedsNativeBridge_test.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2014 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 "NativeBridgeTest.h"
-
-#include <android-base/macros.h>
-
-namespace android {
-
-static const char* kISAs[] = { "arm", "arm64", "mips", "mips64", "x86", "x86_64", "random", "64arm",
- "64_x86", "64_x86_64", "", "reallylongstringabcd", nullptr };
-
-TEST_F(NativeBridgeTest, NeedsNativeBridge) {
- EXPECT_EQ(false, NeedsNativeBridge(ABI_STRING));
-
- const size_t kISACount = sizeof(kISAs) / sizeof(kISAs[0]);
- for (size_t i = 0; i < kISACount; i++) {
- EXPECT_EQ(kISAs[i] == nullptr ? false : strcmp(kISAs[i], ABI_STRING) != 0,
- NeedsNativeBridge(kISAs[i]));
- }
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/PreInitializeNativeBridgeFail1_test.cpp b/libnativebridge/tests/PreInitializeNativeBridgeFail1_test.cpp
deleted file mode 100644
index 5a2b0a1..0000000
--- a/libnativebridge/tests/PreInitializeNativeBridgeFail1_test.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2014 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 "NativeBridgeTest.h"
-
-#include <dlfcn.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-
-#include <cstdio>
-#include <cstring>
-
-#include <android/log.h>
-
-namespace android {
-
-TEST_F(NativeBridgeTest, PreInitializeNativeBridgeFail1) {
- // Needs a valid application directory.
- ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
- ASSERT_FALSE(PreInitializeNativeBridge(nullptr, "isa"));
- ASSERT_TRUE(NativeBridgeError());
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/PreInitializeNativeBridgeFail2_test.cpp b/libnativebridge/tests/PreInitializeNativeBridgeFail2_test.cpp
deleted file mode 100644
index af976b1..0000000
--- a/libnativebridge/tests/PreInitializeNativeBridgeFail2_test.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2014 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 <dlfcn.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-
-#include <cstdio>
-#include <cstring>
-
-#include <android/log.h>
-
-#include "NativeBridgeTest.h"
-
-namespace android {
-
-TEST_F(NativeBridgeTest, PreInitializeNativeBridgeFail2) {
- // Needs LoadNativeBridge() first
- ASSERT_FALSE(PreInitializeNativeBridge(nullptr, "isa"));
- ASSERT_TRUE(NativeBridgeError());
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/PreInitializeNativeBridge_test.cpp b/libnativebridge/tests/PreInitializeNativeBridge_test.cpp
deleted file mode 100644
index cd5a8e2..0000000
--- a/libnativebridge/tests/PreInitializeNativeBridge_test.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2014 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 <dlfcn.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-
-#include <cstdio>
-#include <cstring>
-
-#include <android/log.h>
-
-#include "NativeBridgeTest.h"
-
-namespace android {
-
-TEST_F(NativeBridgeTest, PreInitializeNativeBridge) {
- ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
-#if !defined(__APPLE__) // Mac OS does not support bind-mount.
-#if !defined(__ANDROID__) // Cannot write into the hard-wired location.
- static constexpr const char* kTestData = "PreInitializeNativeBridge test.";
-
- // Try to create our mount namespace.
- if (unshare(CLONE_NEWNS) != -1) {
- // Create a dummy file.
- FILE* cpuinfo = fopen("./cpuinfo", "w");
- ASSERT_NE(nullptr, cpuinfo) << strerror(errno);
- fprintf(cpuinfo, kTestData);
- fclose(cpuinfo);
-
- ASSERT_TRUE(PreInitializeNativeBridge("does not matter 1", "short 2"));
-
- // Read /proc/cpuinfo
- FILE* proc_cpuinfo = fopen("/proc/cpuinfo", "r");
- ASSERT_NE(nullptr, proc_cpuinfo) << strerror(errno);
- char buf[1024];
- EXPECT_NE(nullptr, fgets(buf, sizeof(buf), proc_cpuinfo)) << "Error reading.";
- fclose(proc_cpuinfo);
-
- EXPECT_EQ(0, strcmp(buf, kTestData));
-
- // Delete the file.
- ASSERT_EQ(0, unlink("./cpuinfo")) << "Error unlinking temporary file.";
- // Ending the test will tear down the mount namespace.
- } else {
- GTEST_LOG_(WARNING) << "Could not create mount namespace. Are you running this as root?";
- }
-#endif
-#endif
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/ReSetupNativeBridge_test.cpp b/libnativebridge/tests/ReSetupNativeBridge_test.cpp
deleted file mode 100644
index 944e5d7..0000000
--- a/libnativebridge/tests/ReSetupNativeBridge_test.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2014 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 "NativeBridgeTest.h"
-
-namespace android {
-
-TEST_F(NativeBridgeTest, ReSetup) {
- EXPECT_EQ(false, NativeBridgeError());
- LoadNativeBridge("", nullptr);
- EXPECT_EQ(false, NativeBridgeError());
- LoadNativeBridge("", nullptr);
- // This should lead to an error for trying to re-setup a native bridge.
- EXPECT_EQ(true, NativeBridgeError());
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/UnavailableNativeBridge_test.cpp b/libnativebridge/tests/UnavailableNativeBridge_test.cpp
deleted file mode 100644
index ad374a5..0000000
--- a/libnativebridge/tests/UnavailableNativeBridge_test.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2011 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 "NativeBridgeTest.h"
-
-namespace android {
-
-TEST_F(NativeBridgeTest, NoNativeBridge) {
- EXPECT_EQ(false, NativeBridgeAvailable());
- // Try to initialize. This should fail as we are not set up.
- EXPECT_EQ(false, InitializeNativeBridge(nullptr, nullptr));
- EXPECT_EQ(true, NativeBridgeError());
- EXPECT_EQ(false, NativeBridgeAvailable());
-}
-
-} // namespace android
diff --git a/libnativebridge/tests/ValidNameNativeBridge_test.cpp b/libnativebridge/tests/ValidNameNativeBridge_test.cpp
deleted file mode 100644
index 690be4a..0000000
--- a/libnativebridge/tests/ValidNameNativeBridge_test.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2011 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 <NativeBridgeTest.h>
-
-namespace android {
-
-static const char* kTestName = "librandom-bridge_not.existing.so";
-
-TEST_F(NativeBridgeTest, ValidName) {
- // Check that the name is acceptable.
- EXPECT_EQ(true, NativeBridgeNameAcceptable(kTestName));
-
- // Now check what happens on LoadNativeBridge.
- EXPECT_EQ(false, NativeBridgeError());
- LoadNativeBridge(kTestName, nullptr);
- // This will lead to an error as the library doesn't exist.
- EXPECT_EQ(true, NativeBridgeError());
- EXPECT_EQ(false, NativeBridgeAvailable());
-}
-
-} // namespace android
diff --git a/libnativeloader/.clang-format b/libnativeloader/.clang-format
deleted file mode 120000
index fd0645f..0000000
--- a/libnativeloader/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-../.clang-format-2
\ No newline at end of file
diff --git a/libnativeloader/Android.bp b/libnativeloader/Android.bp
deleted file mode 100644
index 2ee9d28..0000000
--- a/libnativeloader/Android.bp
+++ /dev/null
@@ -1,97 +0,0 @@
-// Shared library for target
-// ========================================================
-cc_defaults {
- name: "libnativeloader-defaults",
- cflags: [
- "-Werror",
- "-Wall",
- ],
- cppflags: [
- "-fvisibility=hidden",
- ],
- header_libs: ["libnativeloader-headers"],
- export_header_lib_headers: ["libnativeloader-headers"],
-}
-
-cc_library {
- name: "libnativeloader",
- defaults: ["libnativeloader-defaults"],
- // TODO(oth): remove after moving under art/ (b/137364733)
- visibility: ["//visibility:public"],
- host_supported: true,
- srcs: [
- "native_loader.cpp",
- ],
- shared_libs: [
- "libnativehelper",
- "liblog",
- "libnativebridge",
- "libbase",
- ],
- target: {
- android: {
- srcs: [
- "library_namespaces.cpp",
- "native_loader_namespace.cpp",
- "public_libraries.cpp",
- ],
- shared_libs: [
- "libdl_android",
- ],
- },
- },
- required: [
- "llndk.libraries.txt",
- "vndksp.libraries.txt",
- ],
- stubs: {
- symbol_file: "libnativeloader.map.txt",
- versions: ["1"],
- },
-}
-
-// TODO(b/124250621) eliminate the need for this library
-cc_library {
- name: "libnativeloader_lazy",
- defaults: ["libnativeloader-defaults"],
- // TODO(oth): remove after moving under art/ (b/137364733)
- visibility: ["//visibility:public"],
- host_supported: false,
- srcs: ["native_loader_lazy.cpp"],
- required: ["libnativeloader"],
-}
-
-cc_library_headers {
- name: "libnativeloader-headers",
- // TODO(oth): remove after moving under art/ (b/137364733)
- visibility: ["//visibility:public"],
- host_supported: true,
- export_include_dirs: ["include"],
-}
-
-cc_test {
- name: "libnativeloader_test",
- srcs: [
- "native_loader_test.cpp",
- "native_loader.cpp",
- "library_namespaces.cpp",
- "native_loader_namespace.cpp",
- "public_libraries.cpp",
- ],
- cflags: ["-DANDROID"],
- static_libs: [
- "libbase",
- "liblog",
- "libnativehelper",
- "libgmock",
- ],
- header_libs: [
- "libnativebridge-headers",
- "libnativeloader-headers",
- ],
- system_shared_libs: [
- "libc",
- "libm",
- ],
- test_suites: ["device-tests"],
-}
diff --git a/libnativeloader/CPPLINT.cfg b/libnativeloader/CPPLINT.cfg
deleted file mode 100644
index db98533..0000000
--- a/libnativeloader/CPPLINT.cfg
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
-filter=-build/header_guard
-filter=-readability/check
-filter=-build/namespaces
diff --git a/libnativeloader/OWNERS b/libnativeloader/OWNERS
deleted file mode 100644
index f735653..0000000
--- a/libnativeloader/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-dimitry@google.com
-jiyong@google.com
-ngeoffray@google.com
-oth@google.com
-mast@google.com
-rpl@google.com
diff --git a/libnativeloader/README.md b/libnativeloader/README.md
deleted file mode 100644
index 57b9001..0000000
--- a/libnativeloader/README.md
+++ /dev/null
@@ -1,84 +0,0 @@
-libnativeloader
-===============================================================================
-
-Overview
--------------------------------------------------------------------------------
-libnativeloader is responsible for loading native shared libraries (`*.so`
-files) inside the Android Runtime (ART). The native shared libraries could be
-app-provided JNI libraries or public native libraries like `libc.so` provided
-by the platform.
-
-The most typical use case of this library is calling `System.loadLibrary(name)`.
-When the method is called, the ART runtime delegates the call to this library
-along with the reference to the classloader where the call was made. Then this
-library finds the linker namespace (named `classloader-namespace`) that is
-associated with the given classloader, and tries to load the requested library
-from the namespace. The actual searching, loading, and linking of the library
-is performed by the dynamic linker.
-
-The linker namespace is created when an APK is loaded into the process, and is
-associated with the classloader that loaded the APK. The linker namespace is
-configured so that only the JNI libraries embedded in the APK is accessible
-from the namespace, thus preventing an APK from loading JNI libraries of other
-APKs.
-
-The linker namespace is also configured differently depending on other
-characteristics of the APK such as whether or not the APK is bundled with the
-platform. In case of the unbundled, i.e., downloaded or updated APK, only the
-public native libraries that is listed in `/system/etc/public.libraries.txt`
-are available from the platform, whereas in case of the bundled, all libraries
-under `/system/lib` are available (i.e. shared). In case when the unbundled
-app is from `/vendor` or `/product` partition, the app is additionally provided
-with the [VNDK-SP](https://source.android.com/devices/architecture/vndk#sp-hal)
-libraries. As the platform is getting modularized with
-[APEX](https://android.googlesource.com/platform/system/apex/+/refs/heads/master/docs/README.md),
-some libraries are no longer provided from platform, but from the APEXes which
-have their own linker namespaces. For example, ICU libraries `libicuuc.so` and
-`libicui18n.so` are from the runtime APEX.
-
-The list of public native libraries is not static. The default set of libraries
-are defined in AOSP, but partners can extend it to include their own libraries.
-Currently, following extensions are available:
-
-- `/vendor/etc/public.libraries.txt`: libraries in `/vendor/lib` that are
-specific to the underlying SoC, e.g. GPU, DSP, etc.
-- `/{system|product}/etc/public.libraries-<companyname>.txt`: libraries in
-`/{system|product}/lib` that a device manufacturer has newly added. The
-libraries should be named as `lib<name>.<companyname>.so` as in
-`libFoo.acme.so`.
-
-Note that, due to the naming constraint requiring `.<companyname>.so` suffix, it
-is prohibited for a device manufacturer to expose an AOSP-defined private
-library, e.g. libgui.so, libart.so, etc., to APKs.
-
-Lastly, libnativeloader is responsible for abstracting the two types of the
-dynamic linker interface: `libdl.so` and `libnativebridge.so`. The former is
-for non-translated, e.g. ARM-on-ARM, libraries, while the latter is for
-loading libraries in a translated environment such as ARM-on-x86.
-
-Implementation
--------------------------------------------------------------------------------
-Implementation wise, libnativeloader consists of four parts:
-
-- `native_loader.cpp`
-- `library_namespaces.cpp`
-- `native_loader_namespace.cpp`
-- `public_libraries.cpp`
-
-`native_loader.cpp` implements the public interface of this library. It is just
-a thin wrapper around `library_namespaces.cpp` and `native_loader_namespace.cpp`.
-
-`library_namespaces.cpp` implements the singleton class `LibraryNamespaces` which
-is a manager-like entity that is responsible for creating and configuring
-linker namespaces and finding an already created linker namespace for a given
-classloader.
-
-`native_loader_namespace.cpp` implements the class `NativeLoaderNamespace` that
-models a linker namespace. Its main job is to abstract the two types of the
-dynamic linker interface so that other parts of this library do not have to know
-the differences of the interfaces.
-
-`public_libraries.cpp` is responsible for reading `*.txt` files for the public
-native libraries from the various partitions. It can be considered as a part of
-`LibraryNamespaces` but is separated from it to hide the details of the parsing
-routines.
diff --git a/libnativeloader/TEST_MAPPING b/libnativeloader/TEST_MAPPING
deleted file mode 100644
index 7becb77..0000000
--- a/libnativeloader/TEST_MAPPING
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "presubmit": [
- {
- "name": "libnativeloader_test"
- }
- ],
- "imports": [
- {
- "path": "cts/tests/tests/jni"
- }
- ]
-}
diff --git a/libnativeloader/include/nativeloader/dlext_namespaces.h b/libnativeloader/include/nativeloader/dlext_namespaces.h
deleted file mode 100644
index 8937636..0000000
--- a/libnativeloader/include/nativeloader/dlext_namespaces.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __ANDROID_DLEXT_NAMESPACES_H__
-#define __ANDROID_DLEXT_NAMESPACES_H__
-
-#include <android/dlext.h>
-#include <stdbool.h>
-
-__BEGIN_DECLS
-
-enum {
- /* A regular namespace is the namespace with a custom search path that does
- * not impose any restrictions on the location of native libraries.
- */
- ANDROID_NAMESPACE_TYPE_REGULAR = 0,
-
- /* An isolated namespace requires all the libraries to be on the search path
- * or under permitted_when_isolated_path. The search path is the union of
- * ld_library_path and default_library_path.
- */
- ANDROID_NAMESPACE_TYPE_ISOLATED = 1,
-
- /* The shared namespace clones the list of libraries of the caller namespace upon creation
- * which means that they are shared between namespaces - the caller namespace and the new one
- * will use the same copy of a library if it was loaded prior to android_create_namespace call.
- *
- * Note that libraries loaded after the namespace is created will not be shared.
- *
- * Shared namespaces can be isolated or regular. Note that they do not inherit the search path nor
- * permitted_path from the caller's namespace.
- */
- ANDROID_NAMESPACE_TYPE_SHARED = 2,
-
- /* This flag instructs linker to enable grey-list workaround for the namespace.
- * See http://b/26394120 for details.
- */
- ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED = 0x08000000,
-
- /* This flag instructs linker to use this namespace as the anonymous
- * namespace. The anonymous namespace is used in the case when linker cannot
- * identify the caller of dlopen/dlsym. This happens for the code not loaded
- * by dynamic linker; for example calls from the mono-compiled code. There can
- * be only one anonymous namespace in a process. If there already is an
- * anonymous namespace in the process, using this flag when creating a new
- * namespace causes an error.
- */
- ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS = 0x10000000,
-
- ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED =
- ANDROID_NAMESPACE_TYPE_SHARED | ANDROID_NAMESPACE_TYPE_ISOLATED,
-};
-
-/*
- * Creates new linker namespace.
- * ld_library_path and default_library_path represent the search path
- * for the libraries in the namespace.
- *
- * The libraries in the namespace are searched by folowing order:
- * 1. ld_library_path (Think of this as namespace-local LD_LIBRARY_PATH)
- * 2. In directories specified by DT_RUNPATH of the "needed by" binary.
- * 3. deault_library_path (This of this as namespace-local default library path)
- *
- * When type is ANDROID_NAMESPACE_TYPE_ISOLATED the resulting namespace requires all of
- * the libraries to be on the search path or under the permitted_when_isolated_path;
- * the search_path is ld_library_path:default_library_path. Note that the
- * permitted_when_isolated_path path is not part of the search_path and
- * does not affect the search order. It is a way to allow loading libraries from specific
- * locations when using absolute path.
- * If a library or any of its dependencies are outside of the permitted_when_isolated_path
- * and search_path, and it is not part of the public namespace dlopen will fail.
- */
-extern struct android_namespace_t* android_create_namespace(
- const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
- const char* permitted_when_isolated_path, struct android_namespace_t* parent);
-
-/*
- * Creates a link between namespaces. Every link has list of sonames of
- * shared libraries. These are the libraries which are accessible from
- * namespace 'from' but loaded within namespace 'to' context.
- * When to namespace is nullptr this function establishes a link between
- * 'from' namespace and the default namespace.
- *
- * The lookup order of the libraries in namespaces with links is following:
- * 1. Look inside current namespace using 'this' namespace search path.
- * 2. Look in linked namespaces
- * 2.1. Perform soname check - if library soname is not in the list of shared
- * libraries sonames skip this link, otherwise
- * 2.2. Search library using linked namespace search path. Note that this
- * step will not go deeper into linked namespaces for this library but
- * will do so for DT_NEEDED libraries.
- */
-extern bool android_link_namespaces(struct android_namespace_t* from,
- struct android_namespace_t* to,
- const char* shared_libs_sonames);
-
-extern struct android_namespace_t* android_get_exported_namespace(const char* name);
-
-__END_DECLS
-
-#endif /* __ANDROID_DLEXT_NAMESPACES_H__ */
diff --git a/libnativeloader/include/nativeloader/native_loader.h b/libnativeloader/include/nativeloader/native_loader.h
deleted file mode 100644
index 51fb875..0000000
--- a/libnativeloader/include/nativeloader/native_loader.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef NATIVE_LOADER_H_
-#define NATIVE_LOADER_H_
-
-#include <stdbool.h>
-#include <stdint.h>
-#include "jni.h"
-#if defined(__ANDROID__)
-#include <android/dlext.h>
-#endif
-
-#ifdef __cplusplus
-namespace android {
-extern "C" {
-#endif // __cplusplus
-
-// README: the char** error message parameter being passed
-// to the methods below need to be freed through calling NativeLoaderFreeErrorMessage.
-// It's the caller's responsibility to call that method.
-
-__attribute__((visibility("default")))
-void InitializeNativeLoader();
-
-__attribute__((visibility("default"))) jstring CreateClassLoaderNamespace(
- JNIEnv* env, int32_t target_sdk_version, jobject class_loader, bool is_shared, jstring dex_path,
- jstring library_path, jstring permitted_path);
-
-__attribute__((visibility("default"))) void* OpenNativeLibrary(
- JNIEnv* env, int32_t target_sdk_version, const char* path, jobject class_loader,
- const char* caller_location, jstring library_path, bool* needs_native_bridge, char** error_msg);
-
-__attribute__((visibility("default"))) bool CloseNativeLibrary(void* handle,
- const bool needs_native_bridge,
- char** error_msg);
-
-__attribute__((visibility("default"))) void NativeLoaderFreeErrorMessage(char* msg);
-
-#if defined(__ANDROID__)
-// Look up linker namespace by class_loader. Returns nullptr if
-// there is no namespace associated with the class_loader.
-// TODO(b/79940628): move users to FindNativeLoaderNamespaceByClassLoader and remove this function.
-__attribute__((visibility("default"))) struct android_namespace_t* FindNamespaceByClassLoader(
- JNIEnv* env, jobject class_loader);
-// That version works with native bridge namespaces, but requires use of OpenNativeLibrary.
-struct NativeLoaderNamespace;
-__attribute__((visibility("default"))) struct NativeLoaderNamespace*
-FindNativeLoaderNamespaceByClassLoader(JNIEnv* env, jobject class_loader);
-// Load library. Unlinke OpenNativeLibrary above couldn't create namespace on demand, but does
-// not require access to JNIEnv either.
-__attribute__((visibility("default"))) void* OpenNativeLibraryInNamespace(
- struct NativeLoaderNamespace* ns, const char* path, bool* needs_native_bridge,
- char** error_msg);
-#endif
-
-__attribute__((visibility("default")))
-void ResetNativeLoader();
-
-#ifdef __cplusplus
-} // extern "C"
-} // namespace android
-#endif // __cplusplus
-
-#endif // NATIVE_BRIDGE_H_
diff --git a/libnativeloader/libnativeloader.map.txt b/libnativeloader/libnativeloader.map.txt
deleted file mode 100644
index 40c30bd..0000000
--- a/libnativeloader/libnativeloader.map.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# 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.
-#
-
-# TODO(b/122710865): Prune these uses once the runtime APEX is complete.
-LIBNATIVELOADER_1 {
- global:
- OpenNativeLibrary;
- InitializeNativeLoader;
- ResetNativeLoader;
- CloseNativeLibrary;
- OpenNativeLibraryInNamespace;
- FindNamespaceByClassLoader;
- FindNativeLoaderNamespaceByClassLoader;
- CreateClassLoaderNamespace;
- NativeLoaderFreeErrorMessage;
- local:
- *;
-};
diff --git a/libnativeloader/library_namespaces.cpp b/libnativeloader/library_namespaces.cpp
deleted file mode 100644
index 7246b97..0000000
--- a/libnativeloader/library_namespaces.cpp
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * 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 "library_namespaces.h"
-
-#include <dirent.h>
-#include <dlfcn.h>
-
-#include <regex>
-#include <string>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/macros.h>
-#include <android-base/properties.h>
-#include <android-base/strings.h>
-#include <nativehelper/ScopedUtfChars.h>
-
-#include "nativeloader/dlext_namespaces.h"
-#include "public_libraries.h"
-#include "utils.h"
-
-using android::base::Error;
-
-namespace android::nativeloader {
-
-namespace {
-// The device may be configured to have the vendor libraries loaded to a separate namespace.
-// For historical reasons this namespace was named sphal but effectively it is intended
-// to use to load vendor libraries to separate namespace with controlled interface between
-// vendor and system namespaces.
-constexpr const char* kVendorNamespaceName = "sphal";
-constexpr const char* kVndkNamespaceName = "vndk";
-constexpr const char* kArtNamespaceName = "art";
-constexpr const char* kNeuralNetworksNamespaceName = "neuralnetworks";
-
-// classloader-namespace is a linker namespace that is created for the loaded
-// app. To be specific, it is created for the app classloader. When
-// System.load() is called from a Java class that is loaded from the
-// classloader, the classloader-namespace namespace associated with that
-// classloader is selected for dlopen. The namespace is configured so that its
-// search path is set to the app-local JNI directory and it is linked to the
-// platform namespace with the names of libs listed in the public.libraries.txt.
-// This way an app can only load its own JNI libraries along with the public libs.
-constexpr const char* kClassloaderNamespaceName = "classloader-namespace";
-// Same thing for vendor APKs.
-constexpr const char* kVendorClassloaderNamespaceName = "vendor-classloader-namespace";
-
-// (http://b/27588281) This is a workaround for apps using custom classloaders and calling
-// System.load() with an absolute path which is outside of the classloader library search path.
-// This list includes all directories app is allowed to access this way.
-constexpr const char* kWhitelistedDirectories = "/data:/mnt/expand";
-
-constexpr const char* kVendorLibPath = "/vendor/" LIB;
-constexpr const char* kProductLibPath = "/product/" LIB ":/system/product/" LIB;
-
-const std::regex kVendorDexPathRegex("(^|:)/vendor/");
-const std::regex kProductDexPathRegex("(^|:)(/system)?/product/");
-
-// Define origin of APK if it is from vendor partition or product partition
-typedef enum {
- APK_ORIGIN_DEFAULT = 0,
- APK_ORIGIN_VENDOR = 1,
- APK_ORIGIN_PRODUCT = 2,
-} ApkOrigin;
-
-jobject GetParentClassLoader(JNIEnv* env, jobject class_loader) {
- jclass class_loader_class = env->FindClass("java/lang/ClassLoader");
- jmethodID get_parent =
- env->GetMethodID(class_loader_class, "getParent", "()Ljava/lang/ClassLoader;");
-
- return env->CallObjectMethod(class_loader, get_parent);
-}
-
-ApkOrigin GetApkOriginFromDexPath(JNIEnv* env, jstring dex_path) {
- ApkOrigin apk_origin = APK_ORIGIN_DEFAULT;
-
- if (dex_path != nullptr) {
- ScopedUtfChars dex_path_utf_chars(env, dex_path);
-
- if (std::regex_search(dex_path_utf_chars.c_str(), kVendorDexPathRegex)) {
- apk_origin = APK_ORIGIN_VENDOR;
- }
-
- if (std::regex_search(dex_path_utf_chars.c_str(), kProductDexPathRegex)) {
- LOG_ALWAYS_FATAL_IF(apk_origin == APK_ORIGIN_VENDOR,
- "Dex path contains both vendor and product partition : %s",
- dex_path_utf_chars.c_str());
-
- apk_origin = APK_ORIGIN_PRODUCT;
- }
- }
- return apk_origin;
-}
-
-} // namespace
-
-void LibraryNamespaces::Initialize() {
- // Once public namespace is initialized there is no
- // point in running this code - it will have no effect
- // on the current list of public libraries.
- if (initialized_) {
- return;
- }
-
- // android_init_namespaces() expects all the public libraries
- // to be loaded so that they can be found by soname alone.
- //
- // TODO(dimitry): this is a bit misleading since we do not know
- // if the vendor public library is going to be opened from /vendor/lib
- // we might as well end up loading them from /system/lib or /product/lib
- // For now we rely on CTS test to catch things like this but
- // it should probably be addressed in the future.
- for (const auto& soname : android::base::Split(preloadable_public_libraries(), ":")) {
- LOG_ALWAYS_FATAL_IF(dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE) == nullptr,
- "Error preloading public library %s: %s", soname.c_str(), dlerror());
- }
-}
-
-Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t target_sdk_version,
- jobject class_loader, bool is_shared,
- jstring dex_path,
- jstring java_library_path,
- jstring java_permitted_path) {
- std::string library_path; // empty string by default.
-
- if (java_library_path != nullptr) {
- ScopedUtfChars library_path_utf_chars(env, java_library_path);
- library_path = library_path_utf_chars.c_str();
- }
-
- ApkOrigin apk_origin = GetApkOriginFromDexPath(env, dex_path);
-
- // (http://b/27588281) This is a workaround for apps using custom
- // classloaders and calling System.load() with an absolute path which
- // is outside of the classloader library search path.
- //
- // This part effectively allows such a classloader to access anything
- // under /data and /mnt/expand
- std::string permitted_path = kWhitelistedDirectories;
-
- if (java_permitted_path != nullptr) {
- ScopedUtfChars path(env, java_permitted_path);
- if (path.c_str() != nullptr && path.size() > 0) {
- permitted_path = permitted_path + ":" + path.c_str();
- }
- }
-
- LOG_ALWAYS_FATAL_IF(FindNamespaceByClassLoader(env, class_loader) != nullptr,
- "There is already a namespace associated with this classloader");
-
- std::string system_exposed_libraries = default_public_libraries();
- const char* namespace_name = kClassloaderNamespaceName;
- bool unbundled_vendor_or_product_app = false;
- if ((apk_origin == APK_ORIGIN_VENDOR ||
- (apk_origin == APK_ORIGIN_PRODUCT && target_sdk_version > 29)) &&
- !is_shared) {
- unbundled_vendor_or_product_app = true;
- // For vendor / product apks, give access to the vendor / product lib even though
- // they are treated as unbundled; the libs and apks are still bundled
- // together in the vendor / product partition.
- const char* origin_partition;
- const char* origin_lib_path;
-
- switch (apk_origin) {
- case APK_ORIGIN_VENDOR:
- origin_partition = "vendor";
- origin_lib_path = kVendorLibPath;
- break;
- case APK_ORIGIN_PRODUCT:
- origin_partition = "product";
- origin_lib_path = kProductLibPath;
- break;
- default:
- origin_partition = "unknown";
- origin_lib_path = "";
- }
- library_path = library_path + ":" + origin_lib_path;
- permitted_path = permitted_path + ":" + origin_lib_path;
-
- // Also give access to LLNDK libraries since they are available to vendors
- system_exposed_libraries = system_exposed_libraries + ":" + llndk_libraries().c_str();
-
- // Different name is useful for debugging
- namespace_name = kVendorClassloaderNamespaceName;
- ALOGD("classloader namespace configured for unbundled %s apk. library_path=%s",
- origin_partition, library_path.c_str());
- } else {
- // extended public libraries are NOT available to vendor apks, otherwise it
- // would be system->vendor violation.
- if (!extended_public_libraries().empty()) {
- system_exposed_libraries = system_exposed_libraries + ':' + extended_public_libraries();
- }
- }
-
- // Create the app namespace
- NativeLoaderNamespace* parent_ns = FindParentNamespaceByClassLoader(env, class_loader);
- // Heuristic: the first classloader with non-empty library_path is assumed to
- // be the main classloader for app
- // TODO(b/139178525) remove this heuristic by determining this in LoadedApk (or its
- // friends) and then passing it down to here.
- bool is_main_classloader = app_main_namespace_ == nullptr && !library_path.empty();
- // Policy: the namespace for the main classloader is also used as the
- // anonymous namespace.
- bool also_used_as_anonymous = is_main_classloader;
- // Note: this function is executed with g_namespaces_mutex held, thus no
- // racing here.
- auto app_ns = NativeLoaderNamespace::Create(
- namespace_name, library_path, permitted_path, parent_ns, is_shared,
- target_sdk_version < 24 /* is_greylist_enabled */, also_used_as_anonymous);
- if (!app_ns) {
- return app_ns.error();
- }
- // ... and link to other namespaces to allow access to some public libraries
- bool is_bridged = app_ns->IsBridged();
-
- auto platform_ns = NativeLoaderNamespace::GetPlatformNamespace(is_bridged);
- if (!platform_ns) {
- return platform_ns.error();
- }
-
- auto linked = app_ns->Link(*platform_ns, system_exposed_libraries);
- if (!linked) {
- return linked.error();
- }
-
- auto art_ns = NativeLoaderNamespace::GetExportedNamespace(kArtNamespaceName, is_bridged);
- // ART APEX does not exist on host, and under certain build conditions.
- if (art_ns) {
- linked = app_ns->Link(*art_ns, art_public_libraries());
- if (!linked) {
- return linked.error();
- }
- }
-
- // Give access to NNAPI libraries (apex-updated LLNDK library).
- auto nnapi_ns =
- NativeLoaderNamespace::GetExportedNamespace(kNeuralNetworksNamespaceName, is_bridged);
- if (nnapi_ns) {
- linked = app_ns->Link(*nnapi_ns, neuralnetworks_public_libraries());
- if (!linked) {
- return linked.error();
- }
- }
-
- // Give access to VNDK-SP libraries from the 'vndk' namespace.
- if (unbundled_vendor_or_product_app && !vndksp_libraries().empty()) {
- auto vndk_ns = NativeLoaderNamespace::GetExportedNamespace(kVndkNamespaceName, is_bridged);
- if (vndk_ns) {
- linked = app_ns->Link(*vndk_ns, vndksp_libraries());
- if (!linked) {
- return linked.error();
- }
- }
- }
-
- if (!vendor_public_libraries().empty()) {
- auto vendor_ns = NativeLoaderNamespace::GetExportedNamespace(kVendorNamespaceName, is_bridged);
- // when vendor_ns is not configured, link to the platform namespace
- auto target_ns = vendor_ns ? vendor_ns : platform_ns;
- if (target_ns) {
- linked = app_ns->Link(*target_ns, vendor_public_libraries());
- if (!linked) {
- return linked.error();
- }
- }
- }
-
- namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), *app_ns));
- if (is_main_classloader) {
- app_main_namespace_ = &(*app_ns);
- }
-
- return &(namespaces_.back().second);
-}
-
-NativeLoaderNamespace* LibraryNamespaces::FindNamespaceByClassLoader(JNIEnv* env,
- jobject class_loader) {
- auto it = std::find_if(namespaces_.begin(), namespaces_.end(),
- [&](const std::pair<jweak, NativeLoaderNamespace>& value) {
- return env->IsSameObject(value.first, class_loader);
- });
- if (it != namespaces_.end()) {
- return &it->second;
- }
-
- return nullptr;
-}
-
-NativeLoaderNamespace* LibraryNamespaces::FindParentNamespaceByClassLoader(JNIEnv* env,
- jobject class_loader) {
- jobject parent_class_loader = GetParentClassLoader(env, class_loader);
-
- while (parent_class_loader != nullptr) {
- NativeLoaderNamespace* ns;
- if ((ns = FindNamespaceByClassLoader(env, parent_class_loader)) != nullptr) {
- return ns;
- }
-
- parent_class_loader = GetParentClassLoader(env, parent_class_loader);
- }
-
- return nullptr;
-}
-
-} // namespace android::nativeloader
diff --git a/libnativeloader/library_namespaces.h b/libnativeloader/library_namespaces.h
deleted file mode 100644
index 7b3efff..0000000
--- a/libnativeloader/library_namespaces.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-#if !defined(__ANDROID__)
-#error "Not available for host"
-#endif
-
-#define LOG_TAG "nativeloader"
-
-#include "native_loader_namespace.h"
-
-#include <list>
-#include <string>
-
-#include <android-base/result.h>
-#include <jni.h>
-
-namespace android::nativeloader {
-
-using android::base::Result;
-
-// LibraryNamespaces is a singleton object that manages NativeLoaderNamespace
-// objects for an app process. Its main job is to create (and configure) a new
-// NativeLoaderNamespace object for a Java ClassLoader, and to find an existing
-// object for a given ClassLoader.
-class LibraryNamespaces {
- public:
- LibraryNamespaces() : initialized_(false), app_main_namespace_(nullptr) {}
-
- LibraryNamespaces(LibraryNamespaces&&) = default;
- LibraryNamespaces(const LibraryNamespaces&) = delete;
- LibraryNamespaces& operator=(const LibraryNamespaces&) = delete;
-
- void Initialize();
- void Reset() {
- namespaces_.clear();
- initialized_ = false;
- app_main_namespace_ = nullptr;
- }
- Result<NativeLoaderNamespace*> Create(JNIEnv* env, uint32_t target_sdk_version,
- jobject class_loader, bool is_shared, jstring dex_path,
- jstring java_library_path, jstring java_permitted_path);
- NativeLoaderNamespace* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader);
-
- private:
- Result<void> InitPublicNamespace(const char* library_path);
- NativeLoaderNamespace* FindParentNamespaceByClassLoader(JNIEnv* env, jobject class_loader);
-
- bool initialized_;
- NativeLoaderNamespace* app_main_namespace_;
- std::list<std::pair<jweak, NativeLoaderNamespace>> namespaces_;
-};
-
-} // namespace android::nativeloader
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
deleted file mode 100644
index 6d3c057..0000000
--- a/libnativeloader/native_loader.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#define LOG_TAG "nativeloader"
-
-#include "nativeloader/native_loader.h"
-
-#include <dlfcn.h>
-#include <sys/types.h>
-
-#include <memory>
-#include <mutex>
-#include <string>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/macros.h>
-#include <android-base/strings.h>
-#include <nativebridge/native_bridge.h>
-#include <nativehelper/ScopedUtfChars.h>
-
-#ifdef __ANDROID__
-#include <log/log.h>
-#include "library_namespaces.h"
-#include "nativeloader/dlext_namespaces.h"
-#endif
-
-namespace android {
-
-namespace {
-#if defined(__ANDROID__)
-using android::nativeloader::LibraryNamespaces;
-
-constexpr const char* kApexPath = "/apex/";
-
-std::mutex g_namespaces_mutex;
-LibraryNamespaces* g_namespaces = new LibraryNamespaces;
-
-android_namespace_t* FindExportedNamespace(const char* caller_location) {
- std::string location = caller_location;
- // Lots of implicit assumptions here: we expect `caller_location` to be of the form:
- // /apex/com.android...modulename/...
- //
- // And we extract from it 'modulename', which is the name of the linker namespace.
- if (android::base::StartsWith(location, kApexPath)) {
- size_t slash_index = location.find_first_of('/', strlen(kApexPath));
- LOG_ALWAYS_FATAL_IF((slash_index == std::string::npos),
- "Error finding namespace of apex: no slash in path %s", caller_location);
- size_t dot_index = location.find_last_of('.', slash_index);
- LOG_ALWAYS_FATAL_IF((dot_index == std::string::npos),
- "Error finding namespace of apex: no dot in apex name %s", caller_location);
- std::string name = location.substr(dot_index + 1, slash_index - dot_index - 1);
- android_namespace_t* boot_namespace = android_get_exported_namespace(name.c_str());
- LOG_ALWAYS_FATAL_IF((boot_namespace == nullptr),
- "Error finding namespace of apex: no namespace called %s", name.c_str());
- return boot_namespace;
- }
- return nullptr;
-}
-#endif // #if defined(__ANDROID__)
-} // namespace
-
-void InitializeNativeLoader() {
-#if defined(__ANDROID__)
- std::lock_guard<std::mutex> guard(g_namespaces_mutex);
- g_namespaces->Initialize();
-#endif
-}
-
-void ResetNativeLoader() {
-#if defined(__ANDROID__)
- std::lock_guard<std::mutex> guard(g_namespaces_mutex);
- g_namespaces->Reset();
-#endif
-}
-
-jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
- bool is_shared, jstring dex_path, jstring library_path,
- jstring permitted_path) {
-#if defined(__ANDROID__)
- std::lock_guard<std::mutex> guard(g_namespaces_mutex);
- auto ns = g_namespaces->Create(env, target_sdk_version, class_loader, is_shared, dex_path,
- library_path, permitted_path);
- if (!ns) {
- return env->NewStringUTF(ns.error().message().c_str());
- }
-#else
- UNUSED(env, target_sdk_version, class_loader, is_shared, dex_path, library_path, permitted_path);
-#endif
- return nullptr;
-}
-
-void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
- jobject class_loader, const char* caller_location, jstring library_path,
- bool* needs_native_bridge, char** error_msg) {
-#if defined(__ANDROID__)
- UNUSED(target_sdk_version);
- if (class_loader == nullptr) {
- *needs_native_bridge = false;
- if (caller_location != nullptr) {
- android_namespace_t* boot_namespace = FindExportedNamespace(caller_location);
- if (boot_namespace != nullptr) {
- const android_dlextinfo dlextinfo = {
- .flags = ANDROID_DLEXT_USE_NAMESPACE,
- .library_namespace = boot_namespace,
- };
- void* handle = android_dlopen_ext(path, RTLD_NOW, &dlextinfo);
- if (handle == nullptr) {
- *error_msg = strdup(dlerror());
- }
- return handle;
- }
- }
- void* handle = dlopen(path, RTLD_NOW);
- if (handle == nullptr) {
- *error_msg = strdup(dlerror());
- }
- return handle;
- }
-
- std::lock_guard<std::mutex> guard(g_namespaces_mutex);
- NativeLoaderNamespace* ns;
-
- if ((ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader)) == nullptr) {
- // This is the case where the classloader was not created by ApplicationLoaders
- // In this case we create an isolated not-shared namespace for it.
- Result<NativeLoaderNamespace*> isolated_ns =
- g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */, nullptr,
- library_path, nullptr);
- if (!isolated_ns) {
- *error_msg = strdup(isolated_ns.error().message().c_str());
- return nullptr;
- } else {
- ns = *isolated_ns;
- }
- }
-
- return OpenNativeLibraryInNamespace(ns, path, needs_native_bridge, error_msg);
-#else
- UNUSED(env, target_sdk_version, class_loader, caller_location);
-
- // Do some best effort to emulate library-path support. It will not
- // work for dependencies.
- //
- // Note: null has a special meaning and must be preserved.
- std::string c_library_path; // Empty string by default.
- if (library_path != nullptr && path != nullptr && path[0] != '/') {
- ScopedUtfChars library_path_utf_chars(env, library_path);
- c_library_path = library_path_utf_chars.c_str();
- }
-
- std::vector<std::string> library_paths = base::Split(c_library_path, ":");
-
- for (const std::string& lib_path : library_paths) {
- *needs_native_bridge = false;
- const char* path_arg;
- std::string complete_path;
- if (path == nullptr) {
- // Preserve null.
- path_arg = nullptr;
- } else {
- complete_path = lib_path;
- if (!complete_path.empty()) {
- complete_path.append("/");
- }
- complete_path.append(path);
- path_arg = complete_path.c_str();
- }
- void* handle = dlopen(path_arg, RTLD_NOW);
- if (handle != nullptr) {
- return handle;
- }
- if (NativeBridgeIsSupported(path_arg)) {
- *needs_native_bridge = true;
- handle = NativeBridgeLoadLibrary(path_arg, RTLD_NOW);
- if (handle != nullptr) {
- return handle;
- }
- *error_msg = strdup(NativeBridgeGetError());
- } else {
- *error_msg = strdup(dlerror());
- }
- }
- return nullptr;
-#endif
-}
-
-bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, char** error_msg) {
- bool success;
- if (needs_native_bridge) {
- success = (NativeBridgeUnloadLibrary(handle) == 0);
- if (!success) {
- *error_msg = strdup(NativeBridgeGetError());
- }
- } else {
- success = (dlclose(handle) == 0);
- if (!success) {
- *error_msg = strdup(dlerror());
- }
- }
-
- return success;
-}
-
-void NativeLoaderFreeErrorMessage(char* msg) {
- // The error messages get allocated through strdup, so we must call free on them.
- free(msg);
-}
-
-#if defined(__ANDROID__)
-void* OpenNativeLibraryInNamespace(NativeLoaderNamespace* ns, const char* path,
- bool* needs_native_bridge, char** error_msg) {
- auto handle = ns->Load(path);
- if (!handle && error_msg != nullptr) {
- *error_msg = strdup(handle.error().message().c_str());
- }
- if (needs_native_bridge != nullptr) {
- *needs_native_bridge = ns->IsBridged();
- }
- return handle ? *handle : nullptr;
-}
-
-// native_bridge_namespaces are not supported for callers of this function.
-// This function will return nullptr in the case when application is running
-// on native bridge.
-android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
- std::lock_guard<std::mutex> guard(g_namespaces_mutex);
- NativeLoaderNamespace* ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader);
- if (ns != nullptr && !ns->IsBridged()) {
- return ns->ToRawAndroidNamespace();
- }
- return nullptr;
-}
-
-NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
- std::lock_guard<std::mutex> guard(g_namespaces_mutex);
- return g_namespaces->FindNamespaceByClassLoader(env, class_loader);
-}
-#endif
-
-}; // namespace android
diff --git a/libnativeloader/native_loader_lazy.cpp b/libnativeloader/native_loader_lazy.cpp
deleted file mode 100644
index 2eb1203..0000000
--- a/libnativeloader/native_loader_lazy.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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 "nativeloader/native_loader.h"
-#define LOG_TAG "nativeloader"
-
-#include <dlfcn.h>
-#include <errno.h>
-#include <string.h>
-
-#include <log/log.h>
-
-namespace android {
-
-namespace {
-
-void* GetLibHandle() {
- static void* handle = dlopen("libnativeloader.so", RTLD_NOW);
- LOG_FATAL_IF(handle == nullptr, "Failed to load libnativeloader.so: %s", dlerror());
- return handle;
-}
-
-template <typename FuncPtr>
-FuncPtr GetFuncPtr(const char* function_name) {
- auto f = reinterpret_cast<FuncPtr>(dlsym(GetLibHandle(), function_name));
- LOG_FATAL_IF(f == nullptr, "Failed to get address of %s: %s", function_name, dlerror());
- return f;
-}
-
-#define GET_FUNC_PTR(name) GetFuncPtr<decltype(&name)>(#name)
-
-} // namespace
-
-void InitializeNativeLoader() {
- static auto f = GET_FUNC_PTR(InitializeNativeLoader);
- return f();
-}
-
-jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
- bool is_shared, jstring dex_path, jstring library_path,
- jstring permitted_path) {
- static auto f = GET_FUNC_PTR(CreateClassLoaderNamespace);
- return f(env, target_sdk_version, class_loader, is_shared, dex_path, library_path,
- permitted_path);
-}
-
-void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
- jobject class_loader, const char* caller_location, jstring library_path,
- bool* needs_native_bridge, char** error_msg) {
- static auto f = GET_FUNC_PTR(OpenNativeLibrary);
- return f(env, target_sdk_version, path, class_loader, caller_location, library_path,
- needs_native_bridge, error_msg);
-}
-
-bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, char** error_msg) {
- static auto f = GET_FUNC_PTR(CloseNativeLibrary);
- return f(handle, needs_native_bridge, error_msg);
-}
-
-void NativeLoaderFreeErrorMessage(char* msg) {
- static auto f = GET_FUNC_PTR(NativeLoaderFreeErrorMessage);
- return f(msg);
-}
-
-struct android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
- static auto f = GET_FUNC_PTR(FindNamespaceByClassLoader);
- return f(env, class_loader);
-}
-
-struct NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(JNIEnv* env,
- jobject class_loader) {
- static auto f = GET_FUNC_PTR(FindNativeLoaderNamespaceByClassLoader);
- return f(env, class_loader);
-}
-
-void* OpenNativeLibraryInNamespace(struct NativeLoaderNamespace* ns, const char* path,
- bool* needs_native_bridge, char** error_msg) {
- static auto f = GET_FUNC_PTR(OpenNativeLibraryInNamespace);
- return f(ns, path, needs_native_bridge, error_msg);
-}
-
-void ResetNativeLoader() {
- static auto f = GET_FUNC_PTR(ResetNativeLoader);
- return f();
-}
-
-#undef GET_FUNC_PTR
-
-} // namespace android
diff --git a/libnativeloader/native_loader_namespace.cpp b/libnativeloader/native_loader_namespace.cpp
deleted file mode 100644
index a81fddf..0000000
--- a/libnativeloader/native_loader_namespace.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "nativeloader"
-
-#include "native_loader_namespace.h"
-
-#include <dlfcn.h>
-
-#include <functional>
-
-#include <android-base/strings.h>
-#include <log/log.h>
-#include <nativebridge/native_bridge.h>
-
-#include "nativeloader/dlext_namespaces.h"
-
-using android::base::Error;
-using android::base::Errorf;
-
-namespace android {
-
-namespace {
-
-constexpr const char* kDefaultNamespaceName = "default";
-constexpr const char* kPlatformNamespaceName = "platform";
-
-std::string GetLinkerError(bool is_bridged) {
- const char* msg = is_bridged ? NativeBridgeGetError() : dlerror();
- if (msg == nullptr) {
- return "no error";
- }
- return std::string(msg);
-}
-
-} // namespace
-
-Result<NativeLoaderNamespace> NativeLoaderNamespace::GetExportedNamespace(const std::string& name,
- bool is_bridged) {
- if (!is_bridged) {
- auto raw = android_get_exported_namespace(name.c_str());
- if (raw != nullptr) {
- return NativeLoaderNamespace(name, raw);
- }
- } else {
- auto raw = NativeBridgeGetExportedNamespace(name.c_str());
- if (raw != nullptr) {
- return NativeLoaderNamespace(name, raw);
- }
- }
- return Errorf("namespace {} does not exist or exported", name);
-}
-
-// The platform namespace is called "default" for binaries in /system and
-// "platform" for those in the Runtime APEX. Try "platform" first since
-// "default" always exists.
-Result<NativeLoaderNamespace> NativeLoaderNamespace::GetPlatformNamespace(bool is_bridged) {
- auto ns = GetExportedNamespace(kPlatformNamespaceName, is_bridged);
- if (ns) return ns;
- ns = GetExportedNamespace(kDefaultNamespaceName, is_bridged);
- if (ns) return ns;
-
- // If nothing is found, return NativeLoaderNamespace constructed from nullptr.
- // nullptr also means default namespace to the linker.
- if (!is_bridged) {
- return NativeLoaderNamespace(kDefaultNamespaceName, static_cast<android_namespace_t*>(nullptr));
- } else {
- return NativeLoaderNamespace(kDefaultNamespaceName,
- static_cast<native_bridge_namespace_t*>(nullptr));
- }
-}
-
-Result<NativeLoaderNamespace> NativeLoaderNamespace::Create(
- const std::string& name, const std::string& search_paths, const std::string& permitted_paths,
- const NativeLoaderNamespace* parent, bool is_shared, bool is_greylist_enabled,
- bool also_used_as_anonymous) {
- bool is_bridged = false;
- if (parent != nullptr) {
- is_bridged = parent->IsBridged();
- } else if (!search_paths.empty()) {
- is_bridged = NativeBridgeIsPathSupported(search_paths.c_str());
- }
-
- // Fall back to the platform namespace if no parent is set.
- auto platform_ns = GetPlatformNamespace(is_bridged);
- if (!platform_ns) {
- return platform_ns.error();
- }
- const NativeLoaderNamespace& effective_parent = parent != nullptr ? *parent : *platform_ns;
-
- // All namespaces for apps are isolated
- uint64_t type = ANDROID_NAMESPACE_TYPE_ISOLATED;
-
- // The namespace is also used as the anonymous namespace
- // which is used when the linker fails to determine the caller address
- if (also_used_as_anonymous) {
- type |= ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS;
- }
-
- // Bundled apps have access to all system libraries that are currently loaded
- // in the default namespace
- if (is_shared) {
- type |= ANDROID_NAMESPACE_TYPE_SHARED;
- }
- if (is_greylist_enabled) {
- type |= ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED;
- }
-
- if (!is_bridged) {
- android_namespace_t* raw =
- android_create_namespace(name.c_str(), nullptr, search_paths.c_str(), type,
- permitted_paths.c_str(), effective_parent.ToRawAndroidNamespace());
- if (raw != nullptr) {
- return NativeLoaderNamespace(name, raw);
- }
- } else {
- native_bridge_namespace_t* raw = NativeBridgeCreateNamespace(
- name.c_str(), nullptr, search_paths.c_str(), type, permitted_paths.c_str(),
- effective_parent.ToRawNativeBridgeNamespace());
- if (raw != nullptr) {
- return NativeLoaderNamespace(name, raw);
- }
- }
- return Errorf("failed to create {} namespace name:{}, search_paths:{}, permitted_paths:{}",
- is_bridged ? "bridged" : "native", name, search_paths, permitted_paths);
-}
-
-Result<void> NativeLoaderNamespace::Link(const NativeLoaderNamespace& target,
- const std::string& shared_libs) const {
- LOG_ALWAYS_FATAL_IF(shared_libs.empty(), "empty share lib when linking %s to %s",
- this->name().c_str(), target.name().c_str());
- if (!IsBridged()) {
- if (android_link_namespaces(this->ToRawAndroidNamespace(), target.ToRawAndroidNamespace(),
- shared_libs.c_str())) {
- return {};
- }
- } else {
- if (NativeBridgeLinkNamespaces(this->ToRawNativeBridgeNamespace(),
- target.ToRawNativeBridgeNamespace(), shared_libs.c_str())) {
- return {};
- }
- }
- return Error() << GetLinkerError(IsBridged());
-}
-
-Result<void*> NativeLoaderNamespace::Load(const char* lib_name) const {
- if (!IsBridged()) {
- android_dlextinfo extinfo;
- extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
- extinfo.library_namespace = this->ToRawAndroidNamespace();
- void* handle = android_dlopen_ext(lib_name, RTLD_NOW, &extinfo);
- if (handle != nullptr) {
- return handle;
- }
- } else {
- void* handle =
- NativeBridgeLoadLibraryExt(lib_name, RTLD_NOW, this->ToRawNativeBridgeNamespace());
- if (handle != nullptr) {
- return handle;
- }
- }
- return Error() << GetLinkerError(IsBridged());
-}
-
-} // namespace android
diff --git a/libnativeloader/native_loader_namespace.h b/libnativeloader/native_loader_namespace.h
deleted file mode 100644
index 7200ee7..0000000
--- a/libnativeloader/native_loader_namespace.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-#if defined(__ANDROID__)
-
-#include <string>
-#include <variant>
-#include <vector>
-
-#include <android-base/logging.h>
-#include <android-base/result.h>
-#include <android/dlext.h>
-#include <log/log.h>
-#include <nativebridge/native_bridge.h>
-
-namespace android {
-
-using android::base::Result;
-
-// NativeLoaderNamespace abstracts a linker namespace for the native
-// architecture (ex: arm on arm) or the translated architecture (ex: arm on
-// x86). Instances of this class are managed by LibraryNamespaces object.
-struct NativeLoaderNamespace {
- public:
- static Result<NativeLoaderNamespace> Create(const std::string& name,
- const std::string& search_paths,
- const std::string& permitted_paths,
- const NativeLoaderNamespace* parent, bool is_shared,
- bool is_greylist_enabled,
- bool also_used_as_anonymous);
-
- NativeLoaderNamespace(NativeLoaderNamespace&&) = default;
- NativeLoaderNamespace(const NativeLoaderNamespace&) = default;
- NativeLoaderNamespace& operator=(const NativeLoaderNamespace&) = default;
-
- android_namespace_t* ToRawAndroidNamespace() const { return std::get<0>(raw_); }
- native_bridge_namespace_t* ToRawNativeBridgeNamespace() const { return std::get<1>(raw_); }
-
- std::string name() const { return name_; }
- bool IsBridged() const { return raw_.index() == 1; }
-
- Result<void> Link(const NativeLoaderNamespace& target, const std::string& shared_libs) const;
- Result<void*> Load(const char* lib_name) const;
-
- static Result<NativeLoaderNamespace> GetExportedNamespace(const std::string& name,
- bool is_bridged);
- static Result<NativeLoaderNamespace> GetPlatformNamespace(bool is_bridged);
-
- private:
- explicit NativeLoaderNamespace(const std::string& name, android_namespace_t* ns)
- : name_(name), raw_(ns) {}
- explicit NativeLoaderNamespace(const std::string& name, native_bridge_namespace_t* ns)
- : name_(name), raw_(ns) {}
-
- std::string name_;
- std::variant<android_namespace_t*, native_bridge_namespace_t*> raw_;
-};
-
-} // namespace android
-#endif // #if defined(__ANDROID__)
diff --git a/libnativeloader/native_loader_test.cpp b/libnativeloader/native_loader_test.cpp
deleted file mode 100644
index 8bd7386..0000000
--- a/libnativeloader/native_loader_test.cpp
+++ /dev/null
@@ -1,663 +0,0 @@
-/*
- * 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 <dlfcn.h>
-#include <memory>
-#include <unordered_map>
-
-#include <android-base/strings.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <jni.h>
-
-#include "native_loader_namespace.h"
-#include "nativeloader/dlext_namespaces.h"
-#include "nativeloader/native_loader.h"
-#include "public_libraries.h"
-
-using namespace ::testing;
-using namespace ::android::nativeloader::internal;
-
-namespace android {
-namespace nativeloader {
-
-// gmock interface that represents interested platform APIs on libdl and libnativebridge
-class Platform {
- public:
- virtual ~Platform() {}
-
- // libdl APIs
- virtual void* dlopen(const char* filename, int flags) = 0;
- virtual int dlclose(void* handle) = 0;
- virtual char* dlerror(void) = 0;
-
- // These mock_* are the APIs semantically the same across libdl and libnativebridge.
- // Instead of having two set of mock APIs for the two, define only one set with an additional
- // argument 'bool bridged' to identify the context (i.e., called for libdl or libnativebridge).
- typedef char* mock_namespace_handle;
- virtual bool mock_init_anonymous_namespace(bool bridged, const char* sonames,
- const char* search_paths) = 0;
- virtual mock_namespace_handle mock_create_namespace(
- bool bridged, const char* name, const char* ld_library_path, const char* default_library_path,
- uint64_t type, const char* permitted_when_isolated_path, mock_namespace_handle parent) = 0;
- virtual bool mock_link_namespaces(bool bridged, mock_namespace_handle from,
- mock_namespace_handle to, const char* sonames) = 0;
- virtual mock_namespace_handle mock_get_exported_namespace(bool bridged, const char* name) = 0;
- virtual void* mock_dlopen_ext(bool bridged, const char* filename, int flags,
- mock_namespace_handle ns) = 0;
-
- // libnativebridge APIs for which libdl has no corresponding APIs
- virtual bool NativeBridgeInitialized() = 0;
- virtual const char* NativeBridgeGetError() = 0;
- virtual bool NativeBridgeIsPathSupported(const char*) = 0;
- virtual bool NativeBridgeIsSupported(const char*) = 0;
-
- // To mock "ClassLoader Object.getParent()"
- virtual const char* JniObject_getParent(const char*) = 0;
-};
-
-// The mock does not actually create a namespace object. But simply casts the pointer to the
-// string for the namespace name as the handle to the namespace object.
-#define TO_ANDROID_NAMESPACE(str) \
- reinterpret_cast<struct android_namespace_t*>(const_cast<char*>(str))
-
-#define TO_BRIDGED_NAMESPACE(str) \
- reinterpret_cast<struct native_bridge_namespace_t*>(const_cast<char*>(str))
-
-#define TO_MOCK_NAMESPACE(ns) reinterpret_cast<Platform::mock_namespace_handle>(ns)
-
-// These represents built-in namespaces created by the linker according to ld.config.txt
-static std::unordered_map<std::string, Platform::mock_namespace_handle> namespaces = {
- {"platform", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("platform"))},
- {"default", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("default"))},
- {"art", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("art"))},
- {"sphal", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("sphal"))},
- {"vndk", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("vndk"))},
- {"neuralnetworks", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("neuralnetworks"))},
-};
-
-// The actual gmock object
-class MockPlatform : public Platform {
- public:
- explicit MockPlatform(bool is_bridged) : is_bridged_(is_bridged) {
- ON_CALL(*this, NativeBridgeIsSupported(_)).WillByDefault(Return(is_bridged_));
- ON_CALL(*this, NativeBridgeIsPathSupported(_)).WillByDefault(Return(is_bridged_));
- ON_CALL(*this, mock_get_exported_namespace(_, _))
- .WillByDefault(Invoke([](bool, const char* name) -> mock_namespace_handle {
- if (namespaces.find(name) != namespaces.end()) {
- return namespaces[name];
- }
- return TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("(namespace not found"));
- }));
- }
-
- // Mocking libdl APIs
- MOCK_METHOD2(dlopen, void*(const char*, int));
- MOCK_METHOD1(dlclose, int(void*));
- MOCK_METHOD0(dlerror, char*());
-
- // Mocking the common APIs
- MOCK_METHOD3(mock_init_anonymous_namespace, bool(bool, const char*, const char*));
- MOCK_METHOD7(mock_create_namespace,
- mock_namespace_handle(bool, const char*, const char*, const char*, uint64_t,
- const char*, mock_namespace_handle));
- MOCK_METHOD4(mock_link_namespaces,
- bool(bool, mock_namespace_handle, mock_namespace_handle, const char*));
- MOCK_METHOD2(mock_get_exported_namespace, mock_namespace_handle(bool, const char*));
- MOCK_METHOD4(mock_dlopen_ext, void*(bool, const char*, int, mock_namespace_handle));
-
- // Mocking libnativebridge APIs
- MOCK_METHOD0(NativeBridgeInitialized, bool());
- MOCK_METHOD0(NativeBridgeGetError, const char*());
- MOCK_METHOD1(NativeBridgeIsPathSupported, bool(const char*));
- MOCK_METHOD1(NativeBridgeIsSupported, bool(const char*));
-
- // Mocking "ClassLoader Object.getParent()"
- MOCK_METHOD1(JniObject_getParent, const char*(const char*));
-
- private:
- bool is_bridged_;
-};
-
-static std::unique_ptr<MockPlatform> mock;
-
-// Provide C wrappers for the mock object.
-extern "C" {
-void* dlopen(const char* file, int flag) {
- return mock->dlopen(file, flag);
-}
-
-int dlclose(void* handle) {
- return mock->dlclose(handle);
-}
-
-char* dlerror(void) {
- return mock->dlerror();
-}
-
-bool android_init_anonymous_namespace(const char* sonames, const char* search_path) {
- return mock->mock_init_anonymous_namespace(false, sonames, search_path);
-}
-
-struct android_namespace_t* android_create_namespace(const char* name, const char* ld_library_path,
- const char* default_library_path,
- uint64_t type,
- const char* permitted_when_isolated_path,
- struct android_namespace_t* parent) {
- return TO_ANDROID_NAMESPACE(
- mock->mock_create_namespace(false, name, ld_library_path, default_library_path, type,
- permitted_when_isolated_path, TO_MOCK_NAMESPACE(parent)));
-}
-
-bool android_link_namespaces(struct android_namespace_t* from, struct android_namespace_t* to,
- const char* sonames) {
- return mock->mock_link_namespaces(false, TO_MOCK_NAMESPACE(from), TO_MOCK_NAMESPACE(to), sonames);
-}
-
-struct android_namespace_t* android_get_exported_namespace(const char* name) {
- return TO_ANDROID_NAMESPACE(mock->mock_get_exported_namespace(false, name));
-}
-
-void* android_dlopen_ext(const char* filename, int flags, const android_dlextinfo* info) {
- return mock->mock_dlopen_ext(false, filename, flags, TO_MOCK_NAMESPACE(info->library_namespace));
-}
-
-// libnativebridge APIs
-bool NativeBridgeIsSupported(const char* libpath) {
- return mock->NativeBridgeIsSupported(libpath);
-}
-
-struct native_bridge_namespace_t* NativeBridgeGetExportedNamespace(const char* name) {
- return TO_BRIDGED_NAMESPACE(mock->mock_get_exported_namespace(true, name));
-}
-
-struct native_bridge_namespace_t* NativeBridgeCreateNamespace(
- const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
- const char* permitted_when_isolated_path, struct native_bridge_namespace_t* parent) {
- return TO_BRIDGED_NAMESPACE(
- mock->mock_create_namespace(true, name, ld_library_path, default_library_path, type,
- permitted_when_isolated_path, TO_MOCK_NAMESPACE(parent)));
-}
-
-bool NativeBridgeLinkNamespaces(struct native_bridge_namespace_t* from,
- struct native_bridge_namespace_t* to, const char* sonames) {
- return mock->mock_link_namespaces(true, TO_MOCK_NAMESPACE(from), TO_MOCK_NAMESPACE(to), sonames);
-}
-
-void* NativeBridgeLoadLibraryExt(const char* libpath, int flag,
- struct native_bridge_namespace_t* ns) {
- return mock->mock_dlopen_ext(true, libpath, flag, TO_MOCK_NAMESPACE(ns));
-}
-
-bool NativeBridgeInitialized() {
- return mock->NativeBridgeInitialized();
-}
-
-bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
- const char* anon_ns_library_path) {
- return mock->mock_init_anonymous_namespace(true, public_ns_sonames, anon_ns_library_path);
-}
-
-const char* NativeBridgeGetError() {
- return mock->NativeBridgeGetError();
-}
-
-bool NativeBridgeIsPathSupported(const char* path) {
- return mock->NativeBridgeIsPathSupported(path);
-}
-
-} // extern "C"
-
-// A very simple JNI mock.
-// jstring is a pointer to utf8 char array. We don't need utf16 char here.
-// jobject, jclass, and jmethodID are also a pointer to utf8 char array
-// Only a few JNI methods that are actually used in libnativeloader are mocked.
-JNINativeInterface* CreateJNINativeInterface() {
- JNINativeInterface* inf = new JNINativeInterface();
- memset(inf, 0, sizeof(JNINativeInterface));
-
- inf->GetStringUTFChars = [](JNIEnv*, jstring s, jboolean*) -> const char* {
- return reinterpret_cast<const char*>(s);
- };
-
- inf->ReleaseStringUTFChars = [](JNIEnv*, jstring, const char*) -> void { return; };
-
- inf->NewStringUTF = [](JNIEnv*, const char* bytes) -> jstring {
- return reinterpret_cast<jstring>(const_cast<char*>(bytes));
- };
-
- inf->FindClass = [](JNIEnv*, const char* name) -> jclass {
- return reinterpret_cast<jclass>(const_cast<char*>(name));
- };
-
- inf->CallObjectMethodV = [](JNIEnv*, jobject obj, jmethodID mid, va_list) -> jobject {
- if (strcmp("getParent", reinterpret_cast<const char*>(mid)) == 0) {
- // JniObject_getParent can be a valid jobject or nullptr if there is
- // no parent classloader.
- const char* ret = mock->JniObject_getParent(reinterpret_cast<const char*>(obj));
- return reinterpret_cast<jobject>(const_cast<char*>(ret));
- }
- return nullptr;
- };
-
- inf->GetMethodID = [](JNIEnv*, jclass, const char* name, const char*) -> jmethodID {
- return reinterpret_cast<jmethodID>(const_cast<char*>(name));
- };
-
- inf->NewWeakGlobalRef = [](JNIEnv*, jobject obj) -> jobject { return obj; };
-
- inf->IsSameObject = [](JNIEnv*, jobject a, jobject b) -> jboolean {
- return strcmp(reinterpret_cast<const char*>(a), reinterpret_cast<const char*>(b)) == 0;
- };
-
- return inf;
-}
-
-static void* const any_nonnull = reinterpret_cast<void*>(0x12345678);
-
-// Custom matcher for comparing namespace handles
-MATCHER_P(NsEq, other, "") {
- *result_listener << "comparing " << reinterpret_cast<const char*>(arg) << " and " << other;
- return strcmp(reinterpret_cast<const char*>(arg), reinterpret_cast<const char*>(other)) == 0;
-}
-
-/////////////////////////////////////////////////////////////////
-
-// Test fixture
-class NativeLoaderTest : public ::testing::TestWithParam<bool> {
- protected:
- bool IsBridged() { return GetParam(); }
-
- void SetUp() override {
- mock = std::make_unique<NiceMock<MockPlatform>>(IsBridged());
-
- env = std::make_unique<JNIEnv>();
- env->functions = CreateJNINativeInterface();
- }
-
- void SetExpectations() {
- std::vector<std::string> default_public_libs =
- android::base::Split(preloadable_public_libraries(), ":");
- for (auto l : default_public_libs) {
- EXPECT_CALL(*mock, dlopen(StrEq(l.c_str()), RTLD_NOW | RTLD_NODELETE))
- .WillOnce(Return(any_nonnull));
- }
- }
-
- void RunTest() { InitializeNativeLoader(); }
-
- void TearDown() override {
- ResetNativeLoader();
- delete env->functions;
- mock.reset();
- }
-
- std::unique_ptr<JNIEnv> env;
-};
-
-/////////////////////////////////////////////////////////////////
-
-TEST_P(NativeLoaderTest, InitializeLoadsDefaultPublicLibraries) {
- SetExpectations();
- RunTest();
-}
-
-INSTANTIATE_TEST_SUITE_P(NativeLoaderTests, NativeLoaderTest, testing::Bool());
-
-/////////////////////////////////////////////////////////////////
-
-class NativeLoaderTest_Create : public NativeLoaderTest {
- protected:
- // Test inputs (initialized to the default values). Overriding these
- // must be done before calling SetExpectations() and RunTest().
- uint32_t target_sdk_version = 29;
- std::string class_loader = "my_classloader";
- bool is_shared = false;
- std::string dex_path = "/data/app/foo/classes.dex";
- std::string library_path = "/data/app/foo/lib/arm";
- std::string permitted_path = "/data/app/foo/lib";
-
- // expected output (.. for the default test inputs)
- std::string expected_namespace_name = "classloader-namespace";
- uint64_t expected_namespace_flags =
- ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS;
- std::string expected_library_path = library_path;
- std::string expected_permitted_path = std::string("/data:/mnt/expand:") + permitted_path;
- std::string expected_parent_namespace = "platform";
- bool expected_link_with_platform_ns = true;
- bool expected_link_with_art_ns = true;
- bool expected_link_with_sphal_ns = !vendor_public_libraries().empty();
- bool expected_link_with_vndk_ns = false;
- bool expected_link_with_default_ns = false;
- bool expected_link_with_neuralnetworks_ns = true;
- std::string expected_shared_libs_to_platform_ns = default_public_libraries();
- std::string expected_shared_libs_to_art_ns = art_public_libraries();
- std::string expected_shared_libs_to_sphal_ns = vendor_public_libraries();
- std::string expected_shared_libs_to_vndk_ns = vndksp_libraries();
- std::string expected_shared_libs_to_default_ns = default_public_libraries();
- std::string expected_shared_libs_to_neuralnetworks_ns = neuralnetworks_public_libraries();
-
- void SetExpectations() {
- NativeLoaderTest::SetExpectations();
-
- ON_CALL(*mock, JniObject_getParent(StrEq(class_loader))).WillByDefault(Return(nullptr));
-
- EXPECT_CALL(*mock, NativeBridgeIsPathSupported(_)).Times(AnyNumber());
- EXPECT_CALL(*mock, NativeBridgeInitialized()).Times(AnyNumber());
-
- EXPECT_CALL(*mock, mock_create_namespace(
- Eq(IsBridged()), StrEq(expected_namespace_name), nullptr,
- StrEq(expected_library_path), expected_namespace_flags,
- StrEq(expected_permitted_path), NsEq(expected_parent_namespace.c_str())))
- .WillOnce(Return(TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE(dex_path.c_str()))));
- if (expected_link_with_platform_ns) {
- EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("platform"),
- StrEq(expected_shared_libs_to_platform_ns)))
- .WillOnce(Return(true));
- }
- if (expected_link_with_art_ns) {
- EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("art"),
- StrEq(expected_shared_libs_to_art_ns)))
- .WillOnce(Return(true));
- }
- if (expected_link_with_sphal_ns) {
- EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("sphal"),
- StrEq(expected_shared_libs_to_sphal_ns)))
- .WillOnce(Return(true));
- }
- if (expected_link_with_vndk_ns) {
- EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("vndk"),
- StrEq(expected_shared_libs_to_vndk_ns)))
- .WillOnce(Return(true));
- }
- if (expected_link_with_default_ns) {
- EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("default"),
- StrEq(expected_shared_libs_to_default_ns)))
- .WillOnce(Return(true));
- }
- if (expected_link_with_neuralnetworks_ns) {
- EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("neuralnetworks"),
- StrEq(expected_shared_libs_to_neuralnetworks_ns)))
- .WillOnce(Return(true));
- }
- }
-
- void RunTest() {
- NativeLoaderTest::RunTest();
-
- jstring err = CreateClassLoaderNamespace(
- env(), target_sdk_version, env()->NewStringUTF(class_loader.c_str()), is_shared,
- env()->NewStringUTF(dex_path.c_str()), env()->NewStringUTF(library_path.c_str()),
- env()->NewStringUTF(permitted_path.c_str()));
-
- // no error
- EXPECT_EQ(err, nullptr);
-
- if (!IsBridged()) {
- struct android_namespace_t* ns =
- FindNamespaceByClassLoader(env(), env()->NewStringUTF(class_loader.c_str()));
-
- // The created namespace is for this apk
- EXPECT_EQ(dex_path.c_str(), reinterpret_cast<const char*>(ns));
- } else {
- struct NativeLoaderNamespace* ns =
- FindNativeLoaderNamespaceByClassLoader(env(), env()->NewStringUTF(class_loader.c_str()));
-
- // The created namespace is for the this apk
- EXPECT_STREQ(dex_path.c_str(),
- reinterpret_cast<const char*>(ns->ToRawNativeBridgeNamespace()));
- }
- }
-
- JNIEnv* env() { return NativeLoaderTest::env.get(); }
-};
-
-TEST_P(NativeLoaderTest_Create, DownloadedApp) {
- SetExpectations();
- RunTest();
-}
-
-TEST_P(NativeLoaderTest_Create, BundledSystemApp) {
- dex_path = "/system/app/foo/foo.apk";
- is_shared = true;
-
- expected_namespace_flags |= ANDROID_NAMESPACE_TYPE_SHARED;
- SetExpectations();
- RunTest();
-}
-
-TEST_P(NativeLoaderTest_Create, BundledVendorApp) {
- dex_path = "/vendor/app/foo/foo.apk";
- is_shared = true;
-
- expected_namespace_flags |= ANDROID_NAMESPACE_TYPE_SHARED;
- SetExpectations();
- RunTest();
-}
-
-TEST_P(NativeLoaderTest_Create, UnbundledVendorApp) {
- dex_path = "/vendor/app/foo/foo.apk";
- is_shared = false;
-
- expected_namespace_name = "vendor-classloader-namespace";
- expected_library_path = expected_library_path + ":/vendor/lib";
- expected_permitted_path = expected_permitted_path + ":/vendor/lib";
- expected_shared_libs_to_platform_ns =
- expected_shared_libs_to_platform_ns + ":" + llndk_libraries();
- expected_link_with_vndk_ns = true;
- SetExpectations();
- RunTest();
-}
-
-TEST_P(NativeLoaderTest_Create, BundledProductApp_pre30) {
- dex_path = "/product/app/foo/foo.apk";
- is_shared = true;
-
- expected_namespace_flags |= ANDROID_NAMESPACE_TYPE_SHARED;
- SetExpectations();
- RunTest();
-}
-
-TEST_P(NativeLoaderTest_Create, BundledProductApp_post30) {
- dex_path = "/product/app/foo/foo.apk";
- is_shared = true;
- target_sdk_version = 30;
-
- expected_namespace_flags |= ANDROID_NAMESPACE_TYPE_SHARED;
- SetExpectations();
- RunTest();
-}
-
-TEST_P(NativeLoaderTest_Create, UnbundledProductApp_pre30) {
- dex_path = "/product/app/foo/foo.apk";
- is_shared = false;
- SetExpectations();
- RunTest();
-}
-
-TEST_P(NativeLoaderTest_Create, UnbundledProductApp_post30) {
- dex_path = "/product/app/foo/foo.apk";
- is_shared = false;
- target_sdk_version = 30;
-
- expected_namespace_name = "vendor-classloader-namespace";
- expected_library_path = expected_library_path + ":/product/lib:/system/product/lib";
- expected_permitted_path = expected_permitted_path + ":/product/lib:/system/product/lib";
- expected_shared_libs_to_platform_ns =
- expected_shared_libs_to_platform_ns + ":" + llndk_libraries();
- expected_link_with_vndk_ns = true;
- SetExpectations();
- RunTest();
-}
-
-TEST_P(NativeLoaderTest_Create, NamespaceForSharedLibIsNotUsedAsAnonymousNamespace) {
- if (IsBridged()) {
- // There is no shared lib in translated arch
- // TODO(jiyong): revisit this
- return;
- }
- // compared to apks, for java shared libs, library_path is empty; java shared
- // libs don't have their own native libs. They use platform's.
- library_path = "";
- expected_library_path = library_path;
- // no ALSO_USED_AS_ANONYMOUS
- expected_namespace_flags = ANDROID_NAMESPACE_TYPE_ISOLATED;
- SetExpectations();
- RunTest();
-}
-
-TEST_P(NativeLoaderTest_Create, TwoApks) {
- SetExpectations();
- const uint32_t second_app_target_sdk_version = 29;
- const std::string second_app_class_loader = "second_app_classloader";
- const bool second_app_is_shared = false;
- const std::string second_app_dex_path = "/data/app/bar/classes.dex";
- const std::string second_app_library_path = "/data/app/bar/lib/arm";
- const std::string second_app_permitted_path = "/data/app/bar/lib";
- const std::string expected_second_app_permitted_path =
- std::string("/data:/mnt/expand:") + second_app_permitted_path;
- const std::string expected_second_app_parent_namespace = "classloader-namespace";
- // no ALSO_USED_AS_ANONYMOUS
- const uint64_t expected_second_namespace_flags = ANDROID_NAMESPACE_TYPE_ISOLATED;
-
- // The scenario is that second app is loaded by the first app.
- // So the first app's classloader (`classloader`) is parent of the second
- // app's classloader.
- ON_CALL(*mock, JniObject_getParent(StrEq(second_app_class_loader)))
- .WillByDefault(Return(class_loader.c_str()));
-
- // namespace for the second app is created. Its parent is set to the namespace
- // of the first app.
- EXPECT_CALL(*mock, mock_create_namespace(
- Eq(IsBridged()), StrEq(expected_namespace_name), nullptr,
- StrEq(second_app_library_path), expected_second_namespace_flags,
- StrEq(expected_second_app_permitted_path), NsEq(dex_path.c_str())))
- .WillOnce(Return(TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE(second_app_dex_path.c_str()))));
- EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), NsEq(second_app_dex_path.c_str()), _, _))
- .WillRepeatedly(Return(true));
-
- RunTest();
- jstring err = CreateClassLoaderNamespace(
- env(), second_app_target_sdk_version, env()->NewStringUTF(second_app_class_loader.c_str()),
- second_app_is_shared, env()->NewStringUTF(second_app_dex_path.c_str()),
- env()->NewStringUTF(second_app_library_path.c_str()),
- env()->NewStringUTF(second_app_permitted_path.c_str()));
-
- // success
- EXPECT_EQ(err, nullptr);
-
- if (!IsBridged()) {
- struct android_namespace_t* ns =
- FindNamespaceByClassLoader(env(), env()->NewStringUTF(second_app_class_loader.c_str()));
-
- // The created namespace is for the second apk
- EXPECT_EQ(second_app_dex_path.c_str(), reinterpret_cast<const char*>(ns));
- } else {
- struct NativeLoaderNamespace* ns = FindNativeLoaderNamespaceByClassLoader(
- env(), env()->NewStringUTF(second_app_class_loader.c_str()));
-
- // The created namespace is for the second apk
- EXPECT_STREQ(second_app_dex_path.c_str(),
- reinterpret_cast<const char*>(ns->ToRawNativeBridgeNamespace()));
- }
-}
-
-INSTANTIATE_TEST_SUITE_P(NativeLoaderTests_Create, NativeLoaderTest_Create, testing::Bool());
-
-const std::function<Result<bool>(const struct ConfigEntry&)> always_true =
- [](const struct ConfigEntry&) -> Result<bool> { return true; };
-
-TEST(NativeLoaderConfigParser, NamesAndComments) {
- const char file_content[] = R"(
-######
-
-libA.so
-#libB.so
-
-
- libC.so
-libD.so
- #### libE.so
-)";
- const std::vector<std::string> expected_result = {"libA.so", "libC.so", "libD.so"};
- Result<std::vector<std::string>> result = ParseConfig(file_content, always_true);
- ASSERT_TRUE(result) << result.error().message();
- ASSERT_EQ(expected_result, *result);
-}
-
-TEST(NativeLoaderConfigParser, WithBitness) {
- const char file_content[] = R"(
-libA.so 32
-libB.so 64
-libC.so
-)";
-#if defined(__LP64__)
- const std::vector<std::string> expected_result = {"libB.so", "libC.so"};
-#else
- const std::vector<std::string> expected_result = {"libA.so", "libC.so"};
-#endif
- Result<std::vector<std::string>> result = ParseConfig(file_content, always_true);
- ASSERT_TRUE(result) << result.error().message();
- ASSERT_EQ(expected_result, *result);
-}
-
-TEST(NativeLoaderConfigParser, WithNoPreload) {
- const char file_content[] = R"(
-libA.so nopreload
-libB.so nopreload
-libC.so
-)";
-
- const std::vector<std::string> expected_result = {"libC.so"};
- Result<std::vector<std::string>> result =
- ParseConfig(file_content,
- [](const struct ConfigEntry& entry) -> Result<bool> { return !entry.nopreload; });
- ASSERT_TRUE(result) << result.error().message();
- ASSERT_EQ(expected_result, *result);
-}
-
-TEST(NativeLoaderConfigParser, WithNoPreloadAndBitness) {
- const char file_content[] = R"(
-libA.so nopreload 32
-libB.so 64 nopreload
-libC.so 32
-libD.so 64
-libE.so nopreload
-)";
-
-#if defined(__LP64__)
- const std::vector<std::string> expected_result = {"libD.so"};
-#else
- const std::vector<std::string> expected_result = {"libC.so"};
-#endif
- Result<std::vector<std::string>> result =
- ParseConfig(file_content,
- [](const struct ConfigEntry& entry) -> Result<bool> { return !entry.nopreload; });
- ASSERT_TRUE(result) << result.error().message();
- ASSERT_EQ(expected_result, *result);
-}
-
-TEST(NativeLoaderConfigParser, RejectMalformed) {
- ASSERT_FALSE(ParseConfig("libA.so 32 64", always_true));
- ASSERT_FALSE(ParseConfig("libA.so 32 32", always_true));
- ASSERT_FALSE(ParseConfig("libA.so 32 nopreload 64", always_true));
- ASSERT_FALSE(ParseConfig("32 libA.so nopreload", always_true));
- ASSERT_FALSE(ParseConfig("nopreload libA.so 32", always_true));
- ASSERT_FALSE(ParseConfig("libA.so nopreload # comment", always_true));
-}
-
-} // namespace nativeloader
-} // namespace android
diff --git a/libnativeloader/public_libraries.cpp b/libnativeloader/public_libraries.cpp
deleted file mode 100644
index 11c3070..0000000
--- a/libnativeloader/public_libraries.cpp
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "nativeloader"
-
-#include "public_libraries.h"
-
-#include <dirent.h>
-
-#include <algorithm>
-#include <memory>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/result.h>
-#include <android-base/strings.h>
-#include <log/log.h>
-
-#include "utils.h"
-
-namespace android::nativeloader {
-
-using namespace internal;
-using namespace ::std::string_literals;
-using android::base::ErrnoError;
-using android::base::Errorf;
-using android::base::Result;
-
-namespace {
-
-constexpr const char* kDefaultPublicLibrariesFile = "/etc/public.libraries.txt";
-constexpr const char* kExtendedPublicLibrariesFilePrefix = "public.libraries-";
-constexpr const char* kExtendedPublicLibrariesFileSuffix = ".txt";
-constexpr const char* kVendorPublicLibrariesFile = "/vendor/etc/public.libraries.txt";
-constexpr const char* kLlndkLibrariesFile = "/system/etc/llndk.libraries.txt";
-constexpr const char* kVndkLibrariesFile = "/system/etc/vndksp.libraries.txt";
-
-const std::vector<const std::string> kArtApexPublicLibraries = {
- "libicuuc.so",
- "libicui18n.so",
-};
-
-constexpr const char* kArtApexLibPath = "/apex/com.android.art/" LIB;
-
-constexpr const char* kNeuralNetworksApexPublicLibrary = "libneuralnetworks.so";
-
-// TODO(b/130388701): do we need this?
-std::string root_dir() {
- static const char* android_root_env = getenv("ANDROID_ROOT");
- return android_root_env != nullptr ? android_root_env : "/system";
-}
-
-bool debuggable() {
- static bool debuggable = android::base::GetBoolProperty("ro.debuggable", false);
- return debuggable;
-}
-
-std::string vndk_version_str() {
- static std::string version = android::base::GetProperty("ro.vndk.version", "");
- if (version != "" && version != "current") {
- return "." + version;
- }
- return "";
-}
-
-// For debuggable platform builds use ANDROID_ADDITIONAL_PUBLIC_LIBRARIES environment
-// variable to add libraries to the list. This is intended for platform tests only.
-std::string additional_public_libraries() {
- if (debuggable()) {
- const char* val = getenv("ANDROID_ADDITIONAL_PUBLIC_LIBRARIES");
- return val ? val : "";
- }
- return "";
-}
-
-void InsertVndkVersionStr(std::string* file_name) {
- CHECK(file_name != nullptr);
- size_t insert_pos = file_name->find_last_of(".");
- if (insert_pos == std::string::npos) {
- insert_pos = file_name->length();
- }
- file_name->insert(insert_pos, vndk_version_str());
-}
-
-const std::function<Result<bool>(const struct ConfigEntry&)> always_true =
- [](const struct ConfigEntry&) -> Result<bool> { return true; };
-
-Result<std::vector<std::string>> ReadConfig(
- const std::string& configFile,
- const std::function<Result<bool>(const ConfigEntry& /* entry */)>& filter_fn) {
- std::string file_content;
- if (!base::ReadFileToString(configFile, &file_content)) {
- return ErrnoError();
- }
- Result<std::vector<std::string>> result = ParseConfig(file_content, filter_fn);
- if (!result) {
- return Errorf("Cannot parse {}: {}", configFile, result.error().message());
- }
- return result;
-}
-
-void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonames) {
- std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(dirname), closedir);
- if (dir != nullptr) {
- // Failing to opening the dir is not an error, which can happen in
- // webview_zygote.
- while (struct dirent* ent = readdir(dir.get())) {
- if (ent->d_type != DT_REG && ent->d_type != DT_LNK) {
- continue;
- }
- const std::string filename(ent->d_name);
- std::string_view fn = filename;
- if (android::base::ConsumePrefix(&fn, kExtendedPublicLibrariesFilePrefix) &&
- android::base::ConsumeSuffix(&fn, kExtendedPublicLibrariesFileSuffix)) {
- const std::string company_name(fn);
- const std::string config_file_path = dirname + "/"s + filename;
- LOG_ALWAYS_FATAL_IF(
- company_name.empty(),
- "Error extracting company name from public native library list file path \"%s\"",
- config_file_path.c_str());
-
- auto ret = ReadConfig(
- config_file_path, [&company_name](const struct ConfigEntry& entry) -> Result<bool> {
- if (android::base::StartsWith(entry.soname, "lib") &&
- android::base::EndsWith(entry.soname, "." + company_name + ".so")) {
- return true;
- } else {
- return Errorf("Library name \"{}\" does not end with the company name {}.",
- entry.soname, company_name);
- }
- });
- if (ret) {
- sonames->insert(sonames->end(), ret->begin(), ret->end());
- } else {
- LOG_ALWAYS_FATAL("Error reading public native library list from \"%s\": %s",
- config_file_path.c_str(), ret.error().message().c_str());
- }
- }
- }
- }
-}
-
-static std::string InitDefaultPublicLibraries(bool for_preload) {
- std::string config_file = root_dir() + kDefaultPublicLibrariesFile;
- auto sonames =
- ReadConfig(config_file, [&for_preload](const struct ConfigEntry& entry) -> Result<bool> {
- if (for_preload) {
- return !entry.nopreload;
- } else {
- return true;
- }
- });
- if (!sonames) {
- LOG_ALWAYS_FATAL("Error reading public native library list from \"%s\": %s",
- config_file.c_str(), sonames.error().message().c_str());
- return "";
- }
-
- std::string additional_libs = additional_public_libraries();
- if (!additional_libs.empty()) {
- auto vec = base::Split(additional_libs, ":");
- std::copy(vec.begin(), vec.end(), std::back_inserter(*sonames));
- }
-
- // If this is for preloading libs, don't remove the libs from APEXes.
- if (for_preload) {
- return android::base::Join(*sonames, ':');
- }
-
- // Remove the public libs in the art namespace.
- // These libs are listed in public.android.txt, but we don't want the rest of android
- // in default namespace to dlopen the libs.
- // For example, libicuuc.so is exposed to classloader namespace from art namespace.
- // Unfortunately, it does not have stable C symbols, and default namespace should only use
- // stable symbols in libandroidicu.so. http://b/120786417
- for (const std::string& lib_name : kArtApexPublicLibraries) {
- std::string path(kArtApexLibPath);
- path.append("/").append(lib_name);
-
- struct stat s;
- // Do nothing if the path in /apex does not exist.
- // Runtime APEX must be mounted since libnativeloader is in the same APEX
- if (stat(path.c_str(), &s) != 0) {
- continue;
- }
-
- auto it = std::find(sonames->begin(), sonames->end(), lib_name);
- if (it != sonames->end()) {
- sonames->erase(it);
- }
- }
-
- // Remove the public libs in the nnapi namespace.
- auto it = std::find(sonames->begin(), sonames->end(), kNeuralNetworksApexPublicLibrary);
- if (it != sonames->end()) {
- sonames->erase(it);
- }
- return android::base::Join(*sonames, ':');
-}
-
-static std::string InitArtPublicLibraries() {
- CHECK(sizeof(kArtApexPublicLibraries) > 0);
- std::string list = android::base::Join(kArtApexPublicLibraries, ":");
-
- std::string additional_libs = additional_public_libraries();
- if (!additional_libs.empty()) {
- list = list + ':' + additional_libs;
- }
- return list;
-}
-
-static std::string InitVendorPublicLibraries() {
- // This file is optional, quietly ignore if the file does not exist.
- auto sonames = ReadConfig(kVendorPublicLibrariesFile, always_true);
- if (!sonames) {
- return "";
- }
- return android::base::Join(*sonames, ':');
-}
-
-// read /system/etc/public.libraries-<companyname>.txt and
-// /product/etc/public.libraries-<companyname>.txt which contain partner defined
-// system libs that are exposed to apps. The libs in the txt files must be
-// named as lib<name>.<companyname>.so.
-static std::string InitExtendedPublicLibraries() {
- std::vector<std::string> sonames;
- ReadExtensionLibraries("/system/etc", &sonames);
- ReadExtensionLibraries("/product/etc", &sonames);
- return android::base::Join(sonames, ':');
-}
-
-static std::string InitLlndkLibraries() {
- std::string config_file = kLlndkLibrariesFile;
- InsertVndkVersionStr(&config_file);
- auto sonames = ReadConfig(config_file, always_true);
- if (!sonames) {
- LOG_ALWAYS_FATAL("%s", sonames.error().message().c_str());
- return "";
- }
- return android::base::Join(*sonames, ':');
-}
-
-static std::string InitVndkspLibraries() {
- std::string config_file = kVndkLibrariesFile;
- InsertVndkVersionStr(&config_file);
- auto sonames = ReadConfig(config_file, always_true);
- if (!sonames) {
- LOG_ALWAYS_FATAL("%s", sonames.error().message().c_str());
- return "";
- }
- return android::base::Join(*sonames, ':');
-}
-
-static std::string InitNeuralNetworksPublicLibraries() {
- return kNeuralNetworksApexPublicLibrary;
-}
-
-} // namespace
-
-const std::string& preloadable_public_libraries() {
- static std::string list = InitDefaultPublicLibraries(/*for_preload*/ true);
- return list;
-}
-
-const std::string& default_public_libraries() {
- static std::string list = InitDefaultPublicLibraries(/*for_preload*/ false);
- return list;
-}
-
-const std::string& art_public_libraries() {
- static std::string list = InitArtPublicLibraries();
- return list;
-}
-
-const std::string& vendor_public_libraries() {
- static std::string list = InitVendorPublicLibraries();
- return list;
-}
-
-const std::string& extended_public_libraries() {
- static std::string list = InitExtendedPublicLibraries();
- return list;
-}
-
-const std::string& neuralnetworks_public_libraries() {
- static std::string list = InitNeuralNetworksPublicLibraries();
- return list;
-}
-
-const std::string& llndk_libraries() {
- static std::string list = InitLlndkLibraries();
- return list;
-}
-
-const std::string& vndksp_libraries() {
- static std::string list = InitVndkspLibraries();
- return list;
-}
-
-namespace internal {
-// Exported for testing
-Result<std::vector<std::string>> ParseConfig(
- const std::string& file_content,
- const std::function<Result<bool>(const ConfigEntry& /* entry */)>& filter_fn) {
- std::vector<std::string> lines = base::Split(file_content, "\n");
-
- std::vector<std::string> sonames;
- for (auto& line : lines) {
- auto trimmed_line = base::Trim(line);
- if (trimmed_line[0] == '#' || trimmed_line.empty()) {
- continue;
- }
-
- std::vector<std::string> tokens = android::base::Split(trimmed_line, " ");
- if (tokens.size() < 1 || tokens.size() > 3) {
- return Errorf("Malformed line \"{}\"", line);
- }
- struct ConfigEntry entry = {.soname = "", .nopreload = false, .bitness = ALL};
- size_t i = tokens.size();
- while (i-- > 0) {
- if (tokens[i] == "nopreload") {
- entry.nopreload = true;
- } else if (tokens[i] == "32" || tokens[i] == "64") {
- if (entry.bitness != ALL) {
- return Errorf("Malformed line \"{}\": bitness can be specified only once", line);
- }
- entry.bitness = tokens[i] == "32" ? ONLY_32 : ONLY_64;
- } else {
- if (i != 0) {
- return Errorf("Malformed line \"{}\"", line);
- }
- entry.soname = tokens[i];
- }
- }
-
- // skip 32-bit lib on 64-bit process and vice versa
-#if defined(__LP64__)
- if (entry.bitness == ONLY_32) continue;
-#else
- if (entry.bitness == ONLY_64) continue;
-#endif
-
- Result<bool> ret = filter_fn(entry);
- if (!ret) {
- return ret.error();
- }
- if (*ret) {
- // filter_fn has returned true.
- sonames.push_back(entry.soname);
- }
- }
- return sonames;
-}
-
-} // namespace internal
-
-} // namespace android::nativeloader
diff --git a/libnativeloader/public_libraries.h b/libnativeloader/public_libraries.h
deleted file mode 100644
index b892e6f..0000000
--- a/libnativeloader/public_libraries.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-
-#include <algorithm>
-#include <string>
-
-#include <android-base/result.h>
-
-namespace android::nativeloader {
-
-using android::base::Result;
-
-// These provide the list of libraries that are available to the namespace for apps.
-// Not all of the libraries are available to apps. Depending on the context,
-// e.g., if it is a vendor app or not, different set of libraries are made available.
-const std::string& preloadable_public_libraries();
-const std::string& default_public_libraries();
-const std::string& art_public_libraries();
-const std::string& vendor_public_libraries();
-const std::string& extended_public_libraries();
-const std::string& neuralnetworks_public_libraries();
-const std::string& llndk_libraries();
-const std::string& vndksp_libraries();
-
-// These are exported for testing
-namespace internal {
-
-enum Bitness { ALL = 0, ONLY_32, ONLY_64 };
-
-struct ConfigEntry {
- std::string soname;
- bool nopreload;
- Bitness bitness;
-};
-
-Result<std::vector<std::string>> ParseConfig(
- const std::string& file_content,
- const std::function<Result<bool>(const ConfigEntry& /* entry */)>& filter_fn);
-
-} // namespace internal
-
-} // namespace android::nativeloader
diff --git a/libnativeloader/test/Android.bp b/libnativeloader/test/Android.bp
deleted file mode 100644
index 4d5c53d..0000000
--- a/libnativeloader/test/Android.bp
+++ /dev/null
@@ -1,82 +0,0 @@
-//
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-cc_library {
- name: "libfoo.oem1",
- srcs: ["test.cpp"],
- cflags: ["-DLIBNAME=\"libfoo.oem1.so\""],
- shared_libs: [
- "libbase",
- ],
-}
-
-cc_library {
- name: "libbar.oem1",
- srcs: ["test.cpp"],
- cflags: ["-DLIBNAME=\"libbar.oem1.so\""],
- shared_libs: [
- "libbase",
- ],
-}
-
-cc_library {
- name: "libfoo.oem2",
- srcs: ["test.cpp"],
- cflags: ["-DLIBNAME=\"libfoo.oem2.so\""],
- shared_libs: [
- "libbase",
- ],
-}
-
-cc_library {
- name: "libbar.oem2",
- srcs: ["test.cpp"],
- cflags: ["-DLIBNAME=\"libbar.oem2.so\""],
- shared_libs: [
- "libbase",
- ],
-}
-
-cc_library {
- name: "libfoo.product1",
- srcs: ["test.cpp"],
- cflags: ["-DLIBNAME=\"libfoo.product1.so\""],
- product_specific: true,
- shared_libs: [
- "libbase",
- ],
-}
-
-cc_library {
- name: "libbar.product1",
- srcs: ["test.cpp"],
- cflags: ["-DLIBNAME=\"libbar.product1.so\""],
- product_specific: true,
- shared_libs: [
- "libbase",
- ],
-}
-
-// Build the test for the C API.
-cc_test {
- name: "libnativeloader-api-tests",
- host_supported: true,
- test_per_src: true,
- srcs: [
- "api_test.c",
- ],
- header_libs: ["libnativeloader-headers"],
-}
diff --git a/libnativeloader/test/Android.mk b/libnativeloader/test/Android.mk
deleted file mode 100644
index 65e7b09..0000000
--- a/libnativeloader/test/Android.mk
+++ /dev/null
@@ -1,57 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := public.libraries-oem1.txt
-LOCAL_SRC_FILES:= $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := public.libraries-oem2.txt
-LOCAL_SRC_FILES:= $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := public.libraries-product1.txt
-LOCAL_SRC_FILES:= $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := oemlibrarytest-system
-LOCAL_MODULE_TAGS := tests
-LOCAL_MANIFEST_FILE := system/AndroidManifest.xml
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SDK_VERSION := current
-LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_MODULE_PATH := $(TARGET_OUT_APPS)
-include $(BUILD_PACKAGE)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := oemlibrarytest-vendor
-LOCAL_MODULE_TAGS := tests
-LOCAL_MANIFEST_FILE := vendor/AndroidManifest.xml
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SDK_VERSION := current
-LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_APPS)
-include $(BUILD_PACKAGE)
diff --git a/libnativeloader/test/api_test.c b/libnativeloader/test/api_test.c
deleted file mode 100644
index e7025fd..0000000
--- a/libnativeloader/test/api_test.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.
- */
-
-/* The main purpose of this test is to ensure this C header compiles in C, so
- * that no C++ features inadvertently leak into the C ABI. */
-#include "nativeloader/native_loader.h"
-
-int main(int argc, char** argv) {
- (void)argc;
- (void)argv;
- return 0;
-}
diff --git a/libnativeloader/test/public.libraries-oem1.txt b/libnativeloader/test/public.libraries-oem1.txt
deleted file mode 100644
index f9433e2..0000000
--- a/libnativeloader/test/public.libraries-oem1.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-libfoo.oem1.so
-libbar.oem1.so
diff --git a/libnativeloader/test/public.libraries-oem2.txt b/libnativeloader/test/public.libraries-oem2.txt
deleted file mode 100644
index de6bdb0..0000000
--- a/libnativeloader/test/public.libraries-oem2.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-libfoo.oem2.so
-libbar.oem2.so
diff --git a/libnativeloader/test/public.libraries-product1.txt b/libnativeloader/test/public.libraries-product1.txt
deleted file mode 100644
index 358154c..0000000
--- a/libnativeloader/test/public.libraries-product1.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-libfoo.product1.so
-libbar.product1.so
diff --git a/libnativeloader/test/runtest.sh b/libnativeloader/test/runtest.sh
deleted file mode 100755
index 40beb5b..0000000
--- a/libnativeloader/test/runtest.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-adb root
-adb remount
-adb sync
-adb shell stop
-adb shell start
-sleep 5 # wait until device reboots
-adb logcat -c;
-adb shell am start -n android.test.app.system/android.test.app.TestActivity
-adb shell am start -n android.test.app.vendor/android.test.app.TestActivity
-adb logcat | grep android.test.app
diff --git a/libnativeloader/test/src/android/test/app/TestActivity.java b/libnativeloader/test/src/android/test/app/TestActivity.java
deleted file mode 100644
index a7a455d..0000000
--- a/libnativeloader/test/src/android/test/app/TestActivity.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.
- */
-
-package android.test.app;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.util.Log;
-
-public class TestActivity extends Activity {
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- tryLoadingLib("foo.oem1");
- tryLoadingLib("bar.oem1");
- tryLoadingLib("foo.oem2");
- tryLoadingLib("bar.oem2");
- tryLoadingLib("foo.product1");
- tryLoadingLib("bar.product1");
- }
-
- private void tryLoadingLib(String name) {
- try {
- System.loadLibrary(name);
- Log.d(getPackageName(), "library " + name + " is successfully loaded");
- } catch (UnsatisfiedLinkError e) {
- Log.d(getPackageName(), "failed to load libarary " + name, e);
- }
- }
-}
diff --git a/libnativeloader/test/system/AndroidManifest.xml b/libnativeloader/test/system/AndroidManifest.xml
deleted file mode 100644
index c304889..0000000
--- a/libnativeloader/test/system/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.test.app.system">
-
- <application>
- <activity android:name="android.test.app.TestActivity" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
-
-</manifest>
-
diff --git a/libnativeloader/test/test.cpp b/libnativeloader/test/test.cpp
deleted file mode 100644
index b166928..0000000
--- a/libnativeloader/test/test.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_TAG "oemlib"
-#include <android-base/logging.h>
-
-static __attribute__((constructor)) void test_lib_init() {
- LOG(DEBUG) << LIBNAME << " loaded";
-}
diff --git a/libnativeloader/test/vendor/AndroidManifest.xml b/libnativeloader/test/vendor/AndroidManifest.xml
deleted file mode 100644
index c4c1a9c..0000000
--- a/libnativeloader/test/vendor/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.test.app.vendor">
-
- <application>
- <activity android:name="android.test.app.TestActivity" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
-
-</manifest>
-
diff --git a/libnativeloader/utils.h b/libnativeloader/utils.h
deleted file mode 100644
index a1c2be5..0000000
--- a/libnativeloader/utils.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-
-namespace android::nativeloader {
-
-#if defined(__LP64__)
-#define LIB "lib64"
-#else
-#define LIB "lib"
-#endif
-
-} // namespace android::nativeloader
diff --git a/libprocessgroup/include/processgroup/sched_policy.h b/libprocessgroup/include/processgroup/sched_policy.h
index 3c498da..945d90c 100644
--- a/libprocessgroup/include/processgroup/sched_policy.h
+++ b/libprocessgroup/include/processgroup/sched_policy.h
@@ -70,11 +70,22 @@
extern int get_sched_policy(int tid, SchedPolicy* policy);
/* Return a displayable string corresponding to policy.
- * Return value: non-NULL NUL-terminated name of unspecified length;
+ * Return value: NUL-terminated name of unspecified length, nullptr if invalid;
* the caller is responsible for displaying the useful part of the string.
*/
extern const char* get_sched_policy_name(SchedPolicy policy);
+/* Return the aggregated task profile name corresponding to cpuset policy.
+ * Return value: NUL-terminated name of unspecified length, nullptr if invalid;
+ * the caller could use it to call SetTaskProfiles.
+ */
+extern const char* get_cpuset_policy_profile_name(SchedPolicy policy);
+
+/* Return the aggregated task profile name corresponding to sched policy.
+ * Return value: NUL-terminated name of unspecified length, nullptr if invalid;
+ * the caller could use it to call SetTaskProfiles.
+ */
+extern const char* get_sched_policy_profile_name(SchedPolicy policy);
#ifdef __cplusplus
}
#endif
diff --git a/libprocessgroup/sched_policy.cpp b/libprocessgroup/sched_policy.cpp
index 6b0ab87..16339d3 100644
--- a/libprocessgroup/sched_policy.cpp
+++ b/libprocessgroup/sched_policy.cpp
@@ -212,7 +212,45 @@
};
static_assert(arraysize(kSchedPolicyNames) == SP_CNT, "missing name");
if (policy < SP_BACKGROUND || policy >= SP_CNT) {
- return "error";
+ return nullptr;
}
return kSchedPolicyNames[policy];
}
+
+const char* get_cpuset_policy_profile_name(SchedPolicy policy) {
+ /*
+ * cpuset profile array for:
+ * SP_DEFAULT(-1), SP_BACKGROUND(0), SP_FOREGROUND(1),
+ * SP_SYSTEM(2), SP_AUDIO_APP(3), SP_AUDIO_SYS(4),
+ * SP_TOP_APP(5), SP_RT_APP(6), SP_RESTRICTED(7)
+ * index is policy + 1
+ * this need keep in sync with SchedPolicy enum
+ */
+ static constexpr const char* kCpusetProfiles[SP_CNT + 1] = {
+ "CPUSET_SP_DEFAULT", "CPUSET_SP_BACKGROUND", "CPUSET_SP_FOREGROUND",
+ "CPUSET_SP_SYSTEM", "CPUSET_SP_FOREGROUND", "CPUSET_SP_FOREGROUND",
+ "CPUSET_SP_TOP_APP", "CPUSET_SP_DEFAULT", "CPUSET_SP_RESTRICTED"};
+ if (policy < SP_DEFAULT || policy >= SP_CNT) {
+ return nullptr;
+ }
+ return kCpusetProfiles[policy + 1];
+}
+
+const char* get_sched_policy_profile_name(SchedPolicy policy) {
+ /*
+ * sched profile array for:
+ * SP_DEFAULT(-1), SP_BACKGROUND(0), SP_FOREGROUND(1),
+ * SP_SYSTEM(2), SP_AUDIO_APP(3), SP_AUDIO_SYS(4),
+ * SP_TOP_APP(5), SP_RT_APP(6), SP_RESTRICTED(7)
+ * index is policy + 1
+ * this need keep in sync with SchedPolicy enum
+ */
+ static constexpr const char* kSchedProfiles[SP_CNT + 1] = {
+ "SCHED_SP_DEFAULT", "SCHED_SP_BACKGROUND", "SCHED_SP_FOREGROUND",
+ "SCHED_SP_DEFAULT", "SCHED_SP_FOREGROUND", "SCHED_SP_FOREGROUND",
+ "SCHED_SP_TOP_APP", "SCHED_SP_RT_APP", "SCHED_SP_DEFAULT"};
+ if (policy < SP_DEFAULT || policy >= SP_CNT) {
+ return nullptr;
+ }
+ return kSchedProfiles[policy + 1];
+}
diff --git a/libunwindstack/AndroidVersions.md b/libunwindstack/AndroidVersions.md
new file mode 100644
index 0000000..234f639
--- /dev/null
+++ b/libunwindstack/AndroidVersions.md
@@ -0,0 +1,116 @@
+# Unwinder Support Per Android Release
+This document describes the changes in the way the libunwindstack
+unwinder works on different Android versions. It does not describe
+every change in the code made between different versions, but is
+meant to allow an app developer to know what might be supported
+on different versions. It also describes the different way an unwind
+will display on different versions of Android.
+
+## Android P
+libunwindstack was first introduced in Android P.
+
+* Supports up to and including Dwarf 4 unwinding information.
+ See http://dwarfstd.org/ for Dwarf standards.
+* Supports Arm exidx unwinding.
+* Supports the gdb JIT unwinding interface, which is how ART creates unwinding
+ information for the JIT'd Java frames.
+* Supports special frames added to represent an ART Java interpreter frame.
+ ART has marked the dex pc using cfi information that the unwinder
+ understands and handles by adding a new frame in the stacktrace.
+
+## Note
+By default, lld creates two separate maps of the elf in memory, one read-only
+and one read/executable. The libunwindstack on P and the unwinder on older
+versions of Android will not unwind properly in this case. For apps that
+target Android P or older, make sure that `-Wl,--no-rosegment` is
+included in linker arguments when using lld.
+
+## Android Q
+* Fix bug (b/109824792) that handled load bias data incorrectly when
+ FDEs use pc relative addressing in the eh\_frame\_hdr.
+ Unfortunately, this wasn't fixed correctly in Q since it assumes
+ that the bias is coming from the program header for the executable
+ load. The real fix was to use the bias from the actual section data and
+ is not completely fixed until Android R. For apps targeting Android Q,
+ if it is being compiled with the llvm linker lld, it might be necessary
+ to add the linker option `-Wl,-zseparate-code` to avoid creating an elf
+ created this way.
+* Change the way the exidx section offset is found (b/110704153). Before
+ the p\_vaddr value from the program header minus the load bias was used
+ to find the start of the exidx data. Changed to use the p\_offset since
+ it doesn't require any load bias manipulations.
+* Fix bug handling of dwarf sections without any header (b/110235461).
+ Previously, the code assumed that FDEs are non-overlapping, and the FDEs
+ are always in sorted order from low pc to high pc. Thus the code would
+ read the entire set of CIEs/FDEs and then do a binary search to find
+ the appropriate FDE for a given pc. Now the code does a sequential read
+ and stops when it finds the FDE for a pc. It also understands the
+ overlapping FDEs, so find the first FDE that matches a pc. In practice,
+ elf files with this format only ever occurs if the file was generated
+ without an eh\_frame/eh\_frame\_hdr section and only a debug\_frame. The
+ other way this has been observed is when running simpleperf to unwind since
+ sometimes there is not enough information in the eh\_frame for all points
+ in the executable. On Android P, this would result in some incorrect
+ unwinds coming from simpleperf. Nearly all crashes from Android P should
+ be correct since the eh\_frame information was enough to do the unwind
+ properly.
+* Be permissive of badly formed elf files. Previously, any detected error
+ would result in unwinds stopping even if there is enough valid information
+ to do an unwind.
+ * The code now allows program header/section header offsets to point
+ to unreadable memory. As long as the code can find the unwind tables,
+ that is good enough.
+ * The code allows program headers/section headers to be missing.
+ * Allow a symbol table section header to point to invalid symbol table
+ values.
+* Support for the linker read-only segment option (b/109657296).
+ This is a feature of lld whereby there are two sections that
+ contain elf data. The first is read-only and contains the elf header data,
+ and the second is read-execute or execute only that
+ contains the executable code from the elf. Before this, the unwinder
+ always assumed that there was only a single read-execute section that
+ contained the elf header data and the executable code.
+* Build ID information for elf objects added. This will display the
+ NT\_GNU\_BUILD\_ID note found in elf files. This information can be used
+ to identify the exact version of a shared library to help get symbol
+ information when looking at a crash.
+* Add support for displaying the soname from an apk frame. Previously,
+ a frame map name would be only the apk, but now if the shared library
+ in the apk has set a soname, the map name will be `app.apk!libexample.so`
+ instead of only `app.apk`.
+* Minimal support for Dwarf 5. This merely treats a Dwarf 5 version
+ elf file as Dwarf 4. It does not support the new dwarf ops in Dwarf 5.
+ Since the new ops are not likely to be used very often, this allows
+ continuing to unwind even when encountering Dwarf 5 elf files.
+* Fix bug in pc handling of signal frames (b/130302288). In the previous
+ version, the pc would be wrong in the signal frame. The rest of the
+ unwind was correct, only the frame in the signal handler was incorrect
+ in Android P.
+* Detect when an elf file is not readable so that a message can be
+ displayed indicating that. This can happen when an app puts the shared
+ libraries in non-standard locations that are not readable due to
+ security restrictions (selinux rules).
+
+## Android R
+* Display the offsets for Java interpreter frames. If this frame came
+ from a non-zero offset map, no offset is printed. Previously, the
+ line would look like:
+
+ #17 pc 00500d7a GoogleCamera.apk (com.google.camera.AndroidPriorityThread.run+10)
+
+ to:
+
+ #17 pc 00500d7a GoogleCamera.apk (offset 0x11d0000) (com.google.camera.AndroidPriorityThread.run+10)
+* Fix bug where the load bias was set from the first PT\_LOAD program
+ header that has a zero p\_offset value. Now it is set from the first
+ executable PT\_LOAD program header. This has only ever been a problem
+ for host executables compiled for the x86\_64 architecture.
+* Switched to the libc++ demangler for function names. Previously, the
+ demangler used was not complete, so some less common demangled function
+ names would not be properly demangled or the function name would not be
+ demangled at all.
+* Fix bug in load bias handling. If the unwind information in the eh\_frame
+ or eh\_frame\_hdr does not have the same bias as the executable section,
+ and uses pc relative FDEs, the unwind will be incorrect. This tends
+ to truncate unwinds since the unwinder could not find the correct unwind
+ information for a given pc.
diff --git a/libunwindstack/tests/DwarfSectionTest.cpp b/libunwindstack/tests/DwarfSectionTest.cpp
index 6df2bae..953dc75 100644
--- a/libunwindstack/tests/DwarfSectionTest.cpp
+++ b/libunwindstack/tests/DwarfSectionTest.cpp
@@ -30,23 +30,24 @@
MockDwarfSection(Memory* memory) : DwarfSection(memory) {}
virtual ~MockDwarfSection() = default;
- MOCK_METHOD3(Init, bool(uint64_t, uint64_t, int64_t));
+ MOCK_METHOD(bool, Init, (uint64_t, uint64_t, int64_t), (override));
- MOCK_METHOD5(Eval, bool(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*));
+ MOCK_METHOD(bool, Eval, (const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*),
+ (override));
- MOCK_METHOD3(Log, bool(uint8_t, uint64_t, const DwarfFde*));
+ MOCK_METHOD(bool, Log, (uint8_t, uint64_t, const DwarfFde*), (override));
- MOCK_METHOD1(GetFdes, void(std::vector<const DwarfFde*>*));
+ MOCK_METHOD(void, GetFdes, (std::vector<const DwarfFde*>*), (override));
- MOCK_METHOD1(GetFdeFromPc, const DwarfFde*(uint64_t));
+ MOCK_METHOD(const DwarfFde*, GetFdeFromPc, (uint64_t), (override));
- MOCK_METHOD3(GetCfaLocationInfo, bool(uint64_t, const DwarfFde*, dwarf_loc_regs_t*));
+ MOCK_METHOD(bool, GetCfaLocationInfo, (uint64_t, const DwarfFde*, dwarf_loc_regs_t*), (override));
- MOCK_METHOD1(GetCieOffsetFromFde32, uint64_t(uint32_t));
+ MOCK_METHOD(uint64_t, GetCieOffsetFromFde32, (uint32_t), (override));
- MOCK_METHOD1(GetCieOffsetFromFde64, uint64_t(uint64_t));
+ MOCK_METHOD(uint64_t, GetCieOffsetFromFde64, (uint64_t), (override));
- MOCK_METHOD1(AdjustPcFromFde, uint64_t(uint64_t));
+ MOCK_METHOD(uint64_t, AdjustPcFromFde, (uint64_t), (override));
};
class DwarfSectionTest : public ::testing::Test {
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index 8c1eade..e6728a0 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -316,9 +316,9 @@
bool GetFunctionName(uint64_t, std::string*, uint64_t*) override { return false; }
std::string GetBuildID() override { return ""; }
- MOCK_METHOD4(Step, bool(uint64_t, Regs*, Memory*, bool*));
- MOCK_METHOD2(GetGlobalVariable, bool(const std::string&, uint64_t*));
- MOCK_METHOD1(IsValidPc, bool(uint64_t));
+ MOCK_METHOD(bool, Step, (uint64_t, Regs*, Memory*, bool*), (override));
+ MOCK_METHOD(bool, GetGlobalVariable, (const std::string&, uint64_t*), (override));
+ MOCK_METHOD(bool, IsValidPc, (uint64_t), (override));
void MockSetDynamicOffset(uint64_t offset) { dynamic_offset_ = offset; }
void MockSetDynamicVaddr(uint64_t vaddr) { dynamic_vaddr_ = vaddr; }
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index e286877..9de7ff7 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -2743,9 +2743,7 @@
* at one per sec.
*/
poll_params->poll_start_tm = curr_tm;
- if (poll_params->poll_handler != handler_info) {
- poll_params->poll_handler = handler_info;
- }
+ poll_params->poll_handler = handler_info;
break;
case POLLING_STOP:
poll_params->poll_handler = NULL;
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 9cbc7c4..ba05a06 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -1185,7 +1185,7 @@
unlock();
// range locking in LastLogTimes looks after us
- curr = element->flushTo(reader, this, privileged, sameTid);
+ curr = element->flushTo(reader, this, sameTid);
if (curr == element->FLUSH_ERROR) {
return curr;
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index 82c4fb9..5c43e18 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -244,14 +244,10 @@
return retval;
}
-log_time LogBufferElement::flushTo(SocketClient* reader, LogBuffer* parent,
- bool privileged, bool lastSame) {
- struct logger_entry_v4 entry;
+log_time LogBufferElement::flushTo(SocketClient* reader, LogBuffer* parent, bool lastSame) {
+ struct logger_entry_v4 entry = {};
- memset(&entry, 0, sizeof(struct logger_entry_v4));
-
- entry.hdr_size = privileged ? sizeof(struct logger_entry_v4)
- : sizeof(struct logger_entry_v3);
+ entry.hdr_size = sizeof(struct logger_entry_v4);
entry.lid = mLogId;
entry.pid = mPid;
entry.tid = mTid;
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index da4991b..fd790e4 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LOGD_LOG_BUFFER_ELEMENT_H__
-#define _LOGD_LOG_BUFFER_ELEMENT_H__
+#pragma once
#include <stdatomic.h>
#include <stdint.h>
@@ -96,8 +95,5 @@
}
static const log_time FLUSH_ERROR;
- log_time flushTo(SocketClient* writer, LogBuffer* parent, bool privileged,
- bool lastSame);
+ log_time flushTo(SocketClient* writer, LogBuffer* parent, bool lastSame);
};
-
-#endif
diff --git a/rootdir/etc/public.libraries.android.txt b/rootdir/etc/public.libraries.android.txt
index 27e855f..405f5a9 100644
--- a/rootdir/etc/public.libraries.android.txt
+++ b/rootdir/etc/public.libraries.android.txt
@@ -17,7 +17,7 @@
libmediandk.so
libm.so
libnativewindow.so
-libneuralnetworks.so
+libneuralnetworks.so nopreload
libOpenMAXAL.so
libOpenSLES.so
libRS.so
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 4f9b93e..c5bf1603 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -918,11 +918,14 @@
on init && property:ro.debuggable=1
start console
-on userspace-reboot:
+on userspace-reboot
# TODO(b/135984674): reset all necessary properties here.
setprop sys.init.userspace_reboot_in_progress 1
+ setprop sys.boot_completed 0
+ setprop sys.init.updatable_crashing 0
+ setprop apexd.status 0
-on userspace-reboot-resume:
+on userspace-reboot-resume
# TODO(b/135984674): remount userdata and reset checkpointing
trigger nonencrypted
trigger post-fs-data