Merge "Fix Deadlock Issue On AppFuseBridge" into rvc-dev
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 1dcc9e4..22d1284 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -301,10 +301,13 @@
     return true;
 }
 
+static bool needs_block_encryption(const FstabEntry& entry);
+static bool should_use_metadata_encryption(const FstabEntry& entry);
+
 // Read the primary superblock from an ext4 filesystem.  On failure return
 // false.  If it's not an ext4 filesystem, also set FS_STAT_INVALID_MAGIC.
-static bool read_ext4_superblock(const std::string& blk_device, struct ext4_super_block* sb,
-                                 int* fs_stat) {
+static bool read_ext4_superblock(const std::string& blk_device, const FstabEntry& entry,
+                                 struct ext4_super_block* sb, int* fs_stat) {
     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(blk_device.c_str(), O_RDONLY | O_CLOEXEC)));
 
     if (fd < 0) {
@@ -321,7 +324,29 @@
         LINFO << "Invalid ext4 superblock on '" << blk_device << "'";
         // not a valid fs, tune2fs, fsck, and mount  will all fail.
         *fs_stat |= FS_STAT_INVALID_MAGIC;
-        return false;
+
+        bool encrypted = should_use_metadata_encryption(entry) || needs_block_encryption(entry);
+        if (entry.mount_point == "/data" &&
+            (!encrypted || android::base::StartsWith(blk_device, "/dev/block/dm-"))) {
+            // try backup superblock, if main superblock is corrupted
+            for (unsigned int blocksize = EXT4_MIN_BLOCK_SIZE; blocksize <= EXT4_MAX_BLOCK_SIZE;
+                 blocksize *= 2) {
+                uint64_t superblock = blocksize * 8;
+                if (blocksize == EXT4_MIN_BLOCK_SIZE) superblock++;
+
+                if (TEMP_FAILURE_RETRY(pread(fd, sb, sizeof(*sb), superblock * blocksize)) !=
+                    sizeof(*sb)) {
+                    PERROR << "Can't read '" << blk_device << "' superblock";
+                    return false;
+                }
+                if (is_ext4_superblock_valid(sb) &&
+                    (1 << (10 + sb->s_log_block_size) == blocksize)) {
+                    *fs_stat &= ~FS_STAT_INVALID_MAGIC;
+                    break;
+                }
+            }
+        }
+        if (*fs_stat & FS_STAT_INVALID_MAGIC) return false;
     }
     *fs_stat |= FS_STAT_IS_EXT4;
     LINFO << "superblock s_max_mnt_count:" << sb->s_max_mnt_count << "," << blk_device;
@@ -663,7 +688,7 @@
     if (is_extfs(entry.fs_type)) {
         struct ext4_super_block sb;
 
-        if (read_ext4_superblock(blk_device, &sb, &fs_stat)) {
+        if (read_ext4_superblock(blk_device, entry, &sb, &fs_stat)) {
             if ((sb.s_feature_incompat & EXT4_FEATURE_INCOMPAT_RECOVER) != 0 ||
                 (sb.s_state & EXT4_VALID_FS) == 0) {
                 LINFO << "Filesystem on " << blk_device << " was not cleanly shutdown; "
@@ -693,7 +718,7 @@
          entry.fs_mgr_flags.fs_verity || entry.fs_mgr_flags.ext_meta_csum)) {
         struct ext4_super_block sb;
 
-        if (read_ext4_superblock(blk_device, &sb, &fs_stat)) {
+        if (read_ext4_superblock(blk_device, entry, &sb, &fs_stat)) {
             tune_reserved_size(blk_device, entry, &sb, &fs_stat);
             tune_encrypt(blk_device, entry, &sb, &fs_stat);
             tune_verity(blk_device, entry, &sb, &fs_stat);
diff --git a/fs_mgr/liblp/device_test.cpp b/fs_mgr/liblp/device_test.cpp
index 99bff6e..382d53d 100644
--- a/fs_mgr/liblp/device_test.cpp
+++ b/fs_mgr/liblp/device_test.cpp
@@ -56,10 +56,6 @@
 
     // Having an alignment offset > alignment doesn't really make sense.
     EXPECT_LT(device_info.alignment_offset, device_info.alignment);
-
-    if (IPropertyFetcher::GetInstance()->GetBoolProperty("ro.virtual_ab.enabled", false)) {
-        EXPECT_EQ(device_info.alignment_offset, 0);
-    }
 }
 
 TEST_F(DeviceTest, ReadSuperPartitionCurrentSlot) {
diff --git a/fs_mgr/libsnapshot/test_helpers.cpp b/fs_mgr/libsnapshot/test_helpers.cpp
index f82a602..de3d912 100644
--- a/fs_mgr/libsnapshot/test_helpers.cpp
+++ b/fs_mgr/libsnapshot/test_helpers.cpp
@@ -52,10 +52,19 @@
 
 bool TestPartitionOpener::GetInfo(const std::string& partition_name,
                                   android::fs_mgr::BlockDeviceInfo* info) const {
-    if (partition_name == "super") {
-        return PartitionOpener::GetInfo(fake_super_path_, info);
+    if (partition_name != "super") {
+        return PartitionOpener::GetInfo(partition_name, info);
     }
-    return PartitionOpener::GetInfo(partition_name, info);
+
+    if (PartitionOpener::GetInfo(fake_super_path_, info)) {
+        // SnapshotUpdateTest uses a relatively small super partition, which requires a small
+        // alignment and 0 offset to work. For the purpose of this test, hardcode the alignment
+        // and offset. This test isn't about testing liblp or libdm.
+        info->alignment_offset = 0;
+        info->alignment = std::min<uint32_t>(info->alignment, static_cast<uint32_t>(128_KiB));
+        return true;
+    }
+    return false;
 }
 
 std::string TestPartitionOpener::GetDeviceString(const std::string& partition_name) const {
diff --git a/liblog/pmsg_reader.cpp b/liblog/pmsg_reader.cpp
index d006ba4..3bdc30f 100644
--- a/liblog/pmsg_reader.cpp
+++ b/liblog/pmsg_reader.cpp
@@ -96,7 +96,7 @@
           ((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))) {
-      char* msg = reinterpret_cast<char*>(&log_msg->entry) + log_msg->entry.hdr_size;
+      char* msg = reinterpret_cast<char*>(&log_msg->entry) + sizeof(log_msg->entry);
       *msg = buf.prio;
       fd = atomic_load(&logger_list->fd);
       if (fd <= 0) {
diff --git a/libstats/socket/Android.bp b/libstats/socket/Android.bp
index 2bf0261..bf79ea2 100644
--- a/libstats/socket/Android.bp
+++ b/libstats/socket/Android.bp
@@ -89,25 +89,6 @@
     min_sdk_version: "29",
 }
 
-cc_benchmark {
-    name: "libstatssocket_benchmark",
-    srcs: [
-        "benchmark/main.cpp",
-        "benchmark/stats_event_benchmark.cpp",
-    ],
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-    static_libs: [
-        "libstatssocket_private",
-    ],
-    shared_libs: [
-        "libcutils",
-        "libgtest_prod",
-    ],
-}
-
 cc_test {
     name: "libstatssocket_test",
     srcs: [
@@ -128,7 +109,7 @@
     ],
     test_suites: ["device-tests", "mts"],
     test_config: "libstatssocket_test.xml",
-    //TODO(b/153588990): Remove when the build system properly separates 
+    //TODO(b/153588990): Remove when the build system properly separates.
     //32bit and 64bit architectures.
     compile_multilib: "both",
     multilib: {
diff --git a/libstats/socket/benchmark/main.cpp b/libstats/socket/benchmark/main.cpp
deleted file mode 100644
index 5ebdf6e..0000000
--- a/libstats/socket/benchmark/main.cpp
+++ /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.
- */
-
-#include <benchmark/benchmark.h>
-
-BENCHMARK_MAIN();
diff --git a/libstats/socket/benchmark/stats_event_benchmark.cpp b/libstats/socket/benchmark/stats_event_benchmark.cpp
deleted file mode 100644
index 3fc6e55..0000000
--- a/libstats/socket/benchmark/stats_event_benchmark.cpp
+++ /dev/null
@@ -1,54 +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 "benchmark/benchmark.h"
-#include "stats_event.h"
-
-static AStatsEvent* constructStatsEvent() {
-    AStatsEvent* event = AStatsEvent_obtain();
-    AStatsEvent_setAtomId(event, 100);
-
-    // randomly sample atom size
-    int numElements = rand() % 800;
-    for (int i = 0; i < numElements; i++) {
-        AStatsEvent_writeInt32(event, i);
-    }
-
-    return event;
-}
-
-static void BM_stats_event_truncate_buffer(benchmark::State& state) {
-    while (state.KeepRunning()) {
-        AStatsEvent* event = constructStatsEvent();
-        AStatsEvent_build(event);
-        AStatsEvent_write(event);
-        AStatsEvent_release(event);
-    }
-}
-
-BENCHMARK(BM_stats_event_truncate_buffer);
-
-static void BM_stats_event_full_buffer(benchmark::State& state) {
-    while (state.KeepRunning()) {
-        AStatsEvent* event = constructStatsEvent();
-        AStatsEvent_truncateBuffer(event, false);
-        AStatsEvent_build(event);
-        AStatsEvent_write(event);
-        AStatsEvent_release(event);
-    }
-}
-
-BENCHMARK(BM_stats_event_full_buffer);
diff --git a/libstats/socket/include/stats_event.h b/libstats/socket/include/stats_event.h
index 601a181..3d3baf9 100644
--- a/libstats/socket/include/stats_event.h
+++ b/libstats/socket/include/stats_event.h
@@ -157,9 +157,6 @@
 uint8_t* AStatsEvent_getBuffer(AStatsEvent* event, size_t* size);
 uint32_t AStatsEvent_getErrors(AStatsEvent* event);
 
-// exposed for benchmarking only
-void AStatsEvent_truncateBuffer(struct AStatsEvent* event, bool truncate);
-
 #ifdef __cplusplus
 }
 #endif  // __CPLUSPLUS
diff --git a/libstats/socket/stats_event.c b/libstats/socket/stats_event.c
index a94b3a1..f3e8087 100644
--- a/libstats/socket/stats_event.c
+++ b/libstats/socket/stats_event.c
@@ -76,7 +76,6 @@
     uint32_t numElements;
     uint32_t atomId;
     uint32_t errors;
-    bool truncate;
     bool built;
     size_t bufSize;
 };
@@ -95,7 +94,6 @@
     event->numElements = 0;
     event->atomId = 0;
     event->errors = 0;
-    event->truncate = true;  // truncate for both pulled and pushed atoms
     event->built = false;
     event->bufSize = MAX_PUSH_EVENT_PAYLOAD;
     event->buf = (uint8_t*)calloc(event->bufSize, 1);
@@ -318,10 +316,6 @@
     return event->errors;
 }
 
-void AStatsEvent_truncateBuffer(AStatsEvent* event, bool truncate) {
-    event->truncate = truncate;
-}
-
 static void build_internal(AStatsEvent* event, const bool push) {
     if (event->numElements > MAX_BYTE_VALUE) event->errors |= ERROR_TOO_MANY_FIELDS;
     if (0 == event->atomId) event->errors |= ERROR_NO_ATOM_ID;
@@ -341,13 +335,6 @@
     }
 
     event->buf[POS_NUM_ELEMENTS] = event->numElements;
-
-    // Truncate the buffer to the appropriate length in order to limit our
-    // memory usage.
-    if (event->truncate) {
-        event->buf = (uint8_t*)realloc(event->buf, event->numBytesWritten);
-        event->bufSize = event->numBytesWritten;
-    }
 }
 
 void AStatsEvent_build(AStatsEvent* event) {
diff --git a/libstats/socket/tests/stats_event_test.cpp b/libstats/socket/tests/stats_event_test.cpp
index cc25521..9a1fac8 100644
--- a/libstats/socket/tests/stats_event_test.cpp
+++ b/libstats/socket/tests/stats_event_test.cpp
@@ -18,7 +18,7 @@
 #include <gtest/gtest.h>
 #include <utils/SystemClock.h>
 
-// Keep in sync stats_event.c. Consider moving to separate header file to avoid duplication.
+// Keep in sync with stats_event.c. Consider moving to separate header file to avoid duplication.
 /* ERRORS */
 #define ERROR_NO_TIMESTAMP 0x1
 #define ERROR_NO_ATOM_ID 0x2