Merge "Throttle reboot from native watchdog" into main
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 235fdfd..2529516 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -373,7 +373,6 @@
 
     sanitize: {
         memtag_heap: true,
-        memtag_stack: true,
     },
 
     shared_libs: [
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 526e2ca..7c52e6e 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -610,7 +610,7 @@
   setjmp(jump_buf);
 }
 
-TEST_F(CrasherTest, mte_illegal_setjmp) {
+TEST_F(CrasherTest, DISABLED_mte_illegal_setjmp) {
   // This setjmp is illegal because it jumps back into a function that already returned.
   // Quoting man 3 setjmp:
   //     If the function which called setjmp() returns before longjmp() is
@@ -1874,8 +1874,8 @@
   StartProcess([&recoverable]() {
     const char* env[] = {"GWP_ASAN_SAMPLE_RATE=1", "GWP_ASAN_PROCESS_SAMPLING=1",
                          "GWP_ASAN_MAX_ALLOCS=40000", nullptr, nullptr};
-    if (recoverable) {
-      env[3] = "GWP_ASAN_RECOVERABLE=true";
+    if (!recoverable) {
+      env[3] = "GWP_ASAN_RECOVERABLE=false";
     }
     std::string test_name = ::testing::UnitTest::GetInstance()->current_test_info()->name();
     test_name = std::regex_replace(test_name, std::regex("run_gwp_asan_test"),
diff --git a/fastboot/fuzzer/Android.bp b/fastboot/fuzzer/Android.bp
index a898070..59533fa 100644
--- a/fastboot/fuzzer/Android.bp
+++ b/fastboot/fuzzer/Android.bp
@@ -55,7 +55,10 @@
     ],
     fuzz_config: {
         cc: [
-            "android-media-fuzzing-reports@google.com",
+            "dvander@google.com",
+            "elsk@google.com",
+            "enh@google.com",
+            "zhangkelvin@google.com",
         ],
         componentid: 533764,
         hotlists: [
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_compress.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_compress.h
index ac04245..21dc666 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_compress.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_compress.h
@@ -17,7 +17,6 @@
 #pragma once
 
 #include <memory>
-#include <vector>
 #include "libsnapshot/cow_format.h"
 
 namespace android {
@@ -25,27 +24,30 @@
 
 class ICompressor {
   public:
-    explicit ICompressor(uint32_t compression_level, uint32_t block_size)
+    explicit ICompressor(const int32_t compression_level, const uint32_t block_size)
         : compression_level_(compression_level), block_size_(block_size) {}
 
     virtual ~ICompressor() {}
     // Factory methods for compression methods.
-    static std::unique_ptr<ICompressor> Gz(uint32_t compression_level, const int32_t block_size);
-    static std::unique_ptr<ICompressor> Brotli(uint32_t compression_level,
-                                               const int32_t block_size);
-    static std::unique_ptr<ICompressor> Lz4(uint32_t compression_level, const int32_t block_size);
-    static std::unique_ptr<ICompressor> Zstd(uint32_t compression_level, const int32_t block_size);
+    static std::unique_ptr<ICompressor> Gz(const int32_t compression_level,
+                                           const uint32_t block_size);
+    static std::unique_ptr<ICompressor> Brotli(const int32_t compression_level,
+                                               const uint32_t block_size);
+    static std::unique_ptr<ICompressor> Lz4(const int32_t compression_level,
+                                            const uint32_t block_size);
+    static std::unique_ptr<ICompressor> Zstd(const int32_t compression_level,
+                                             const uint32_t block_size);
 
     static std::unique_ptr<ICompressor> Create(CowCompression compression,
-                                               const int32_t block_size);
+                                               const uint32_t block_size);
 
-    uint32_t GetCompressionLevel() const { return compression_level_; }
+    int32_t GetCompressionLevel() const { return compression_level_; }
     uint32_t GetBlockSize() const { return block_size_; }
     [[nodiscard]] virtual std::vector<uint8_t> Compress(const void* data, size_t length) const = 0;
 
   private:
-    uint32_t compression_level_;
-    uint32_t block_size_;
+    const int32_t compression_level_;
+    const uint32_t block_size_;
 };
 }  // namespace snapshot
 }  // namespace android
\ No newline at end of file
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
index 6865b19..6a7153d 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
@@ -293,7 +293,7 @@
 };
 struct CowCompression {
     CowCompressionAlgorithm algorithm = kCowCompressNone;
-    uint32_t compression_level = 0;
+    int32_t compression_level = 0;
 };
 
 static constexpr uint8_t kCowReadAheadNotStarted = 0;
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
index 0205f50..bff5257 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
@@ -17,6 +17,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <cstdint>
 #include <limits>
 #include <memory>
 #include <queue>
@@ -57,7 +58,7 @@
 }
 
 std::unique_ptr<ICompressor> ICompressor::Create(CowCompression compression,
-                                                 const int32_t block_size) {
+                                                 const uint32_t block_size) {
     switch (compression.algorithm) {
         case kCowCompressLz4:
             return ICompressor::Lz4(compression.compression_level, block_size);
@@ -101,7 +102,7 @@
 
 class GzCompressor final : public ICompressor {
   public:
-    GzCompressor(uint32_t compression_level, const uint32_t block_size)
+    GzCompressor(int32_t compression_level, const uint32_t block_size)
         : ICompressor(compression_level, block_size){};
 
     std::vector<uint8_t> Compress(const void* data, size_t length) const override {
@@ -122,7 +123,7 @@
 
 class Lz4Compressor final : public ICompressor {
   public:
-    Lz4Compressor(uint32_t compression_level, const uint32_t block_size)
+    Lz4Compressor(int32_t compression_level, const uint32_t block_size)
         : ICompressor(compression_level, block_size){};
 
     std::vector<uint8_t> Compress(const void* data, size_t length) const override {
@@ -154,7 +155,7 @@
 
 class BrotliCompressor final : public ICompressor {
   public:
-    BrotliCompressor(uint32_t compression_level, const uint32_t block_size)
+    BrotliCompressor(int32_t compression_level, const uint32_t block_size)
         : ICompressor(compression_level, block_size){};
 
     std::vector<uint8_t> Compress(const void* data, size_t length) const override {
@@ -180,7 +181,7 @@
 
 class ZstdCompressor final : public ICompressor {
   public:
-    ZstdCompressor(uint32_t compression_level, const uint32_t block_size)
+    ZstdCompressor(int32_t compression_level, const uint32_t block_size)
         : ICompressor(compression_level, block_size),
           zstd_context_(ZSTD_createCCtx(), ZSTD_freeCCtx) {
         ZSTD_CCtx_setParameter(zstd_context_.get(), ZSTD_c_compressionLevel, compression_level);
@@ -318,22 +319,23 @@
     }
 }
 
-std::unique_ptr<ICompressor> ICompressor::Brotli(uint32_t compression_level,
-                                                 const int32_t block_size) {
+std::unique_ptr<ICompressor> ICompressor::Brotli(const int32_t compression_level,
+                                                 const uint32_t block_size) {
     return std::make_unique<BrotliCompressor>(compression_level, block_size);
 }
 
-std::unique_ptr<ICompressor> ICompressor::Gz(uint32_t compression_level, const int32_t block_size) {
+std::unique_ptr<ICompressor> ICompressor::Gz(const int32_t compression_level,
+                                             const uint32_t block_size) {
     return std::make_unique<GzCompressor>(compression_level, block_size);
 }
 
-std::unique_ptr<ICompressor> ICompressor::Lz4(uint32_t compression_level,
-                                              const int32_t block_size) {
+std::unique_ptr<ICompressor> ICompressor::Lz4(const int32_t compression_level,
+                                              const uint32_t block_size) {
     return std::make_unique<Lz4Compressor>(compression_level, block_size);
 }
 
-std::unique_ptr<ICompressor> ICompressor::Zstd(uint32_t compression_level,
-                                               const int32_t block_size) {
+std::unique_ptr<ICompressor> ICompressor::Zstd(const int32_t compression_level,
+                                               const uint32_t block_size) {
     return std::make_unique<ZstdCompressor>(compression_level, block_size);
 }
 
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
index d0864e0..0993dba 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
@@ -134,7 +134,7 @@
         return false;
     }
     if (parts.size() > 1) {
-        if (!android::base::ParseUint(parts[1], &compression_.compression_level)) {
+        if (!android::base::ParseInt(parts[1], &compression_.compression_level)) {
             LOG(ERROR) << "failed to parse compression level invalid type: " << parts[1];
             return false;
         }
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
index 73deafb..95398e4 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
@@ -149,7 +149,7 @@
     }
 
     if (parts.size() > 1) {
-        if (!android::base::ParseUint(parts[1], &compression_.compression_level)) {
+        if (!android::base::ParseInt(parts[1], &compression_.compression_level)) {
             LOG(ERROR) << "failed to parse compression level invalid type: " << parts[1];
             return false;
         }
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index de91bd2..7ca53ad 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -24,7 +24,6 @@
 #include <filesystem>
 #include <optional>
 #include <thread>
-#include <unordered_set>
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
@@ -46,7 +45,6 @@
 #include <android/snapshot/snapshot.pb.h>
 #include <libsnapshot/snapshot_stats.h>
 #include "device_info.h"
-#include "libsnapshot_cow/parser_v2.h"
 #include "partition_cow_creator.h"
 #include "snapshot_metadata_updater.h"
 #include "utility.h"
@@ -3309,7 +3307,7 @@
             compression_algorithm = "gz";
         }
         LOG(INFO) << "using compression algorithm: " << compression_algorithm
-                   << ", max compressible block size: " << compression_factor;
+                  << ", max compressible block size: " << compression_factor;
     }
 
     PartitionCowCreator cow_creator{
diff --git a/fs_mgr/tests/vts_fs_test.cpp b/fs_mgr/tests/vts_fs_test.cpp
index 9503072..f55cadb 100644
--- a/fs_mgr/tests/vts_fs_test.cpp
+++ b/fs_mgr/tests/vts_fs_test.cpp
@@ -74,6 +74,7 @@
     ASSERT_EQ(access("/sys/fs/erofs", F_OK), 0);
 }
 
+// @VsrTest = 3.7.10
 TEST(fs, PartitionTypes) {
     // Requirements only apply to Android 13+, 5.10+ devices.
     int vsr_level = GetVsrLevel();
diff --git a/init/Android.bp b/init/Android.bp
index d4b7fab..ff82f7f 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -255,7 +255,10 @@
 
 cc_library_static {
     name: "libinit.microdroid",
-    defaults: ["libinit_defaults"],
+    defaults: [
+        "avf_build_flags_cc",
+        "libinit_defaults",
+    ],
     cflags: ["-DMICRODROID=1"],
 }
 
@@ -315,7 +318,10 @@
 
 cc_binary {
     name: "init_second_stage.microdroid",
-    defaults: ["init_second_stage_defaults"],
+    defaults: [
+        "avf_build_flags_cc",
+        "init_second_stage_defaults",
+    ],
     static_libs: ["libinit.microdroid"],
     cflags: ["-DMICRODROID=1"],
     installable: false,
diff --git a/init/persistent_properties.cpp b/init/persistent_properties.cpp
index 59e57b9..1d17e3c 100644
--- a/init/persistent_properties.cpp
+++ b/init/persistent_properties.cpp
@@ -236,6 +236,9 @@
                            persistent_properties->mutable_properties()->end(),
                            [&name](const auto& record) { return record.name() == name; });
     if (it != persistent_properties->mutable_properties()->end()) {
+        if (it->value() == value) {
+            return;
+        }
         it->set_name(name);
         it->set_value(value);
     } else {
diff --git a/init/persistent_properties_test.cpp b/init/persistent_properties_test.cpp
index 5763050..97865d7 100644
--- a/init/persistent_properties_test.cpp
+++ b/init/persistent_properties_test.cpp
@@ -17,6 +17,9 @@
 #include "persistent_properties.h"
 
 #include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 #include <vector>
 
@@ -155,6 +158,31 @@
     EXPECT_FALSE(it == read_back_properties.properties().end());
 }
 
+TEST(persistent_properties, NopUpdateDoesntWriteFile) {
+    TemporaryFile tf;
+    ASSERT_TRUE(tf.fd != -1);
+    persistent_property_filename = tf.path;
+
+    auto last_modified = [&tf]() -> time_t {
+        struct stat buf;
+        EXPECT_EQ(fstat(tf.fd, &buf), 0);
+        return buf.st_mtime;
+    };
+
+    std::vector<std::pair<std::string, std::string>> persistent_properties = {
+            {"persist.sys.locale", "en-US"},
+            {"persist.sys.timezone", "America/Los_Angeles"},
+    };
+    ASSERT_RESULT_OK(
+            WritePersistentPropertyFile(VectorToPersistentProperties(persistent_properties)));
+
+    time_t t = last_modified();
+    sleep(2);
+    WritePersistentProperty("persist.sys.locale", "en-US");
+    // Ensure that the file was not modified
+    ASSERT_EQ(last_modified(), t);
+}
+
 TEST(persistent_properties, RejectNonPersistProperty) {
     TemporaryFile tf;
     ASSERT_TRUE(tf.fd != -1);
diff --git a/init/selinux.cpp b/init/selinux.cpp
index e191b60..c2d9b8d 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -66,6 +66,7 @@
 #include <android-base/result.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
+#include <android/avf_cc_flags.h>
 #include <fs_avb/fs_avb.h>
 #include <fs_mgr.h>
 #include <libgsi/libgsi.h>
@@ -702,6 +703,15 @@
 
     SelinuxSetEnforcement();
 
+    if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
+        // We run restorecon of /microdroid_resources while we are still in kernel context to avoid
+        // granting init `tmpfs:file relabelfrom` capability.
+        const int flags = SELINUX_ANDROID_RESTORECON_RECURSE;
+        if (selinux_android_restorecon("/microdroid_resources", flags) == -1) {
+            PLOG(FATAL) << "restorecon of /microdroid_resources failed";
+        }
+    }
+
     // We're in the kernel domain and want to transition to the init domain.  File systems that
     // store SELabels in their xattrs, such as ext4 do not need an explicit restorecon here,
     // but other file systems do.  In particular, this is needed for ramdisks such as the
diff --git a/libvendorsupport/include_llndk/android/llndk-versioning.h b/libvendorsupport/include_llndk/android/llndk-versioning.h
index 58cd18d..cf82fb7 100644
--- a/libvendorsupport/include_llndk/android/llndk-versioning.h
+++ b/libvendorsupport/include_llndk/android/llndk-versioning.h
@@ -14,22 +14,18 @@
 
 #pragma once
 
-/* As a vendor default header included in all vendor modules, this header MUST NOT include other
- * header files or any declarations. Only macros are allowed.
- */
-#if defined(__ANDROID_VENDOR__)
-
 // LLNDK (https://source.android.com/docs/core/architecture/vndk/build-system#ll-ndk) is similar to
 // NDK, but uses its own versioning of YYYYMM format for vendor builds. The LLNDK symbols are
-// enabled when the vendor api level is equal to or newer than the ro.board.api_level.
-#define __INTRODUCED_IN_LLNDK(vendor_api_level)                                             \
-    _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wgcc-compat\"")   \
-            __attribute__((enable_if(                                                       \
-                    __ANDROID_VENDOR_API__ >= vendor_api_level,                             \
-                    "available in vendor API level " #vendor_api_level " that "             \
-                    "is newer than the current vendor API level. Guard the API "            \
-                    "call with '#if (__ANDROID_VENDOR_API__ >= " #vendor_api_level ")'."))) \
-            _Pragma("clang diagnostic pop")
+// enabled when the vendor api level is equal to or newer than the ro.board.api_level. These symbols
+// must be annotated in map.txt files with the `# llndk=YYYYMM` annotation. They also must be marked
+// with `__INTRODUCED_IN_LLNDK(YYYYMM)` in the header files. It leaves a no-op annotation for ABI
+// analysis.
+#if !defined(__INTRODUCED_IN_LLNDK)
+#define __INTRODUCED_IN_LLNDK(vendor_api_level) \
+    __attribute__((annotate("introduced_in_llndk=" #vendor_api_level)))
+#endif
+
+#if defined(__ANDROID_VENDOR__)
 
 // Use this macro as an `if` statement to call an API that are available to both NDK and LLNDK.
 // This returns true for the vendor modules if the vendor_api_level is less than or equal to the
@@ -39,13 +35,6 @@
 
 #else  // __ANDROID_VENDOR__
 
-// __INTRODUCED_IN_LLNDK is for LLNDK only but not for NDK. Ignore this for non-vendor modules.
-// It leaves a no-op annotation for ABI analysis.
-#if !defined(__INTRODUCED_IN_LLNDK)
-#define __INTRODUCED_IN_LLNDK(vendor_api_level) \
-    __attribute__((annotate("introduced_in_llndk=" #vendor_api_level)))
-#endif
-
 // For non-vendor modules, API_LEVEL_AT_LEAST is replaced with __builtin_available(sdk_api_level) to
 // guard the API for __INTRODUCED_IN.
 #if !defined(API_LEVEL_AT_LEAST)
diff --git a/rootdir/init.rc b/rootdir/init.rc
index d4cd4b8..1af46c1 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -648,6 +648,8 @@
     mkdir /metadata/aconfig 0775 root system
     mkdir /metadata/aconfig/flags 0770 root system
     mkdir /metadata/aconfig/boot 0775 root system
+
+    mkdir /metadata/aconfig_test_missions 0775 root system
     exec_start aconfigd-init
     start aconfigd
 
@@ -1031,7 +1033,7 @@
     perform_apex_config
 
     # Create directories for boot animation.
-    mkdir /data/misc/bootanim 0755 system system encryption=DeleteIfNecessary
+    mkdir /data/misc/bootanim 0755 system system
 
     exec_start derive_sdk
 
diff --git a/trusty/libtrusty/tipc-test/tipc_test.c b/trusty/libtrusty/tipc-test/tipc_test.c
index 1eac9cf..3cf0c05 100644
--- a/trusty/libtrusty/tipc-test/tipc_test.c
+++ b/trusty/libtrusty/tipc-test/tipc_test.c
@@ -1041,7 +1041,7 @@
     }
     avg /= params->bench;
 
-    fprintf(stderr, BENCH_RESULT_TPL, params->test_name, min, max, avg, cold, min, max, avg, cold);
+    printf(BENCH_RESULT_TPL, params->test_name, min, max, avg, cold, min, max, avg, cold);
     return rc;
 }