Snap for 8953554 from 40548a48da4207ff4bb73d0c74f72a2084b9fa39 to mainline-tzdata4-release

Change-Id: Ieec8cad5c039e7632d59ce764a483504e89f089e
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index f4ba347..e113308 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -1463,6 +1463,29 @@
   ASSERT_BACKTRACE_FRAME(result, "bar");
 }
 
+TEST_F(CrasherTest, seccomp_tombstone_thread_abort) {
+  int intercept_result;
+  unique_fd output_fd;
+
+  static const auto dump_type = kDebuggerdTombstone;
+  StartProcess(
+      []() {
+        std::thread abort_thread([] { abort(); });
+        abort_thread.join();
+      },
+      &seccomp_fork);
+
+  StartIntercept(&output_fd, dump_type);
+  FinishCrasher();
+  AssertDeath(SIGABRT);
+  FinishIntercept(&intercept_result);
+  ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+  std::string result;
+  ConsumeFd(std::move(output_fd), &result);
+  ASSERT_BACKTRACE_FRAME(result, "abort");
+}
+
 TEST_F(CrasherTest, seccomp_backtrace) {
   int intercept_result;
   unique_fd output_fd;
diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp
index bee4a67..bd05837 100644
--- a/debuggerd/libdebuggerd/tombstone_proto.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto.cpp
@@ -455,7 +455,7 @@
   thread.set_tagged_addr_ctrl(thread_info.tagged_addr_ctrl);
   thread.set_pac_enabled_keys(thread_info.pac_enabled_keys);
 
-  if (thread_info.pid == getpid() && thread_info.pid != thread_info.tid) {
+  if (thread_info.registers == nullptr) {
     // Fallback path for non-main thread, doing unwind from running process.
     unwindstack::ThreadUnwinder thread_unwinder(kMaxFrames, unwinder->GetMaps());
     if (!thread_unwinder.Init()) {
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index a83f535..019b64a 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -3273,8 +3273,21 @@
                 snapuserd_client_ = nullptr;
             }
         } else {
-            status.set_userspace_snapshots(!IsDmSnapshotTestingEnabled());
-            if (IsDmSnapshotTestingEnabled()) {
+            bool userSnapshotsEnabled = true;
+            const std::string UNKNOWN = "unknown";
+            const std::string vendor_release = android::base::GetProperty(
+                    "ro.vendor.build.version.release_or_codename", UNKNOWN);
+
+            // No user-space snapshots if vendor partition is on Android 12
+            if (vendor_release.find("12") != std::string::npos) {
+                LOG(INFO) << "Userspace snapshots disabled as vendor partition is on Android: "
+                          << vendor_release;
+                userSnapshotsEnabled = false;
+            }
+
+            userSnapshotsEnabled = (userSnapshotsEnabled && !IsDmSnapshotTestingEnabled());
+            status.set_userspace_snapshots(userSnapshotsEnabled);
+            if (!userSnapshotsEnabled) {
                 is_snapshot_userspace_ = false;
                 LOG(INFO) << "User-space snapshots disabled for testing";
             } else {
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 36abf71..c145da7 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -91,7 +91,7 @@
 
 void MountMetadata();
 bool ShouldUseCompression();
-bool ShouldUseUserspaceSnapshots();
+bool IsDaemonRequired();
 
 class SnapshotTest : public ::testing::Test {
   public:
@@ -1208,7 +1208,7 @@
 
     // Initiate the merge and wait for it to be completed.
     ASSERT_TRUE(init->InitiateMerge());
-    ASSERT_EQ(init->IsSnapuserdRequired(), ShouldUseUserspaceSnapshots());
+    ASSERT_EQ(init->IsSnapuserdRequired(), IsDaemonRequired());
     {
         // We should have started in SECOND_PHASE since nothing shrinks.
         ASSERT_TRUE(AcquireLock());
@@ -1342,7 +1342,7 @@
 
     // Initiate the merge and wait for it to be completed.
     ASSERT_TRUE(init->InitiateMerge());
-    ASSERT_EQ(init->IsSnapuserdRequired(), ShouldUseUserspaceSnapshots());
+    ASSERT_EQ(init->IsSnapuserdRequired(), IsDaemonRequired());
     {
         // Check that the merge phase is FIRST_PHASE until at least one call
         // to ProcessUpdateState() occurs.
@@ -1450,7 +1450,7 @@
 
     // Initiate the merge and wait for it to be completed.
     ASSERT_TRUE(init->InitiateMerge());
-    ASSERT_EQ(init->IsSnapuserdRequired(), ShouldUseUserspaceSnapshots());
+    ASSERT_EQ(init->IsSnapuserdRequired(), IsDaemonRequired());
     {
         // Check that the merge phase is FIRST_PHASE until at least one call
         // to ProcessUpdateState() occurs.
@@ -2750,13 +2750,30 @@
     }
 }
 
-bool ShouldUseUserspaceSnapshots() {
+bool IsDaemonRequired() {
     if (FLAGS_force_config == "dmsnap") {
         return false;
     }
+
+    if (!IsCompressionEnabled()) {
+        return false;
+    }
+
+    const std::string UNKNOWN = "unknown";
+    const std::string vendor_release =
+            android::base::GetProperty("ro.vendor.build.version.release_or_codename", UNKNOWN);
+
+    // No userspace snapshots if vendor partition is on Android 12
+    // However, for GRF devices, snapuserd daemon will be on
+    // vendor ramdisk in Android 12.
+    if (vendor_release.find("12") != std::string::npos) {
+        return true;
+    }
+
     if (!FLAGS_force_config.empty()) {
         return true;
     }
+
     return IsUserspaceSnapshotsEnabled();
 }
 
diff --git a/fs_mgr/libsnapshot/vts_ota_config_test.cpp b/fs_mgr/libsnapshot/vts_ota_config_test.cpp
index afc2d81..02bcc34 100644
--- a/fs_mgr/libsnapshot/vts_ota_config_test.cpp
+++ b/fs_mgr/libsnapshot/vts_ota_config_test.cpp
@@ -17,7 +17,14 @@
 #include <android-base/properties.h>
 #include <gtest/gtest.h>
 
+static int GetVsrLevel() {
+    return android::base::GetIntProperty("ro.vendor.api_level", -1);
+}
+
 TEST(VAB, Enabled) {
     ASSERT_TRUE(android::base::GetBoolProperty("ro.virtual_ab.enabled", false));
+    if (GetVsrLevel() < __ANDROID_API_T__) {
+        GTEST_SKIP();
+    }
     ASSERT_TRUE(android::base::GetBoolProperty("ro.virtual_ab.userspace.snapshots.enabled", false));
 }
diff --git a/fs_mgr/tests/vts_fs_test.cpp b/fs_mgr/tests/vts_fs_test.cpp
index b5fac53..ae8e459 100644
--- a/fs_mgr/tests/vts_fs_test.cpp
+++ b/fs_mgr/tests/vts_fs_test.cpp
@@ -28,8 +28,8 @@
 }
 
 TEST(fs, ErofsSupported) {
-    // S and higher for this test.
-    if (GetVsrLevel() < __ANDROID_API_S__) {
+    // T-launch GKI kernels and higher must support EROFS.
+    if (GetVsrLevel() < __ANDROID_API_T__) {
         GTEST_SKIP();
     }
 
@@ -47,6 +47,8 @@
     std::string fs;
     ASSERT_TRUE(android::base::ReadFileToString("/proc/filesystems", &fs));
     EXPECT_THAT(fs, ::testing::HasSubstr("\terofs\n"));
+
+    ASSERT_EQ(access("/sys/fs/erofs", F_OK), 0);
 }
 
 TEST(fs, PartitionTypes) {
@@ -94,7 +96,13 @@
         }
 
         if (entry.flags & MS_RDONLY) {
-            EXPECT_EQ(entry.fs_type, "erofs") << entry.mount_point;
+            std::vector<std::string> allowed = {"erofs", "ext4"};
+            if (vsr_level == __ANDROID_API_T__) {
+                allowed.emplace_back("f2fs");
+            }
+
+            EXPECT_NE(std::find(allowed.begin(), allowed.end(), entry.fs_type), allowed.end())
+                    << entry.mount_point;
         } else {
             EXPECT_NE(entry.fs_type, "ext4") << entry.mount_point;
         }
diff --git a/init/service.cpp b/init/service.cpp
index 3fa935f..bd704cf 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -547,6 +547,10 @@
         if ((flags_ & SVC_ONESHOT) && disabled) {
             flags_ |= SVC_RESTART;
         }
+
+        LOG(INFO) << "service '" << name_
+                  << "' requested start, but it is already running (flags: " << flags_ << ")";
+
         // It is not an error to try to start a service that is already running.
         reboot_on_failure.Disable();
         return {};
diff --git a/init/snapuserd_transition.cpp b/init/snapuserd_transition.cpp
index 5deaf31..5c821b0 100644
--- a/init/snapuserd_transition.cpp
+++ b/init/snapuserd_transition.cpp
@@ -29,6 +29,7 @@
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/parseint.h>
+#include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 #include <cutils/sockets.h>
@@ -40,6 +41,7 @@
 #include <snapuserd/snapuserd_client.h>
 
 #include "block_dev_initializer.h"
+#include "lmkd_service.h"
 #include "service_utils.h"
 #include "util.h"
 
@@ -320,6 +322,14 @@
 
         LOG(INFO) << "Relaunched snapuserd with pid: " << pid;
 
+        // Since daemon is not started as a service, we have
+        // to explicitly set the OOM score to default which is unkillable
+        std::string oom_str = std::to_string(DEFAULT_OOM_SCORE_ADJUST);
+        std::string oom_file = android::base::StringPrintf("/proc/%d/oom_score_adj", pid);
+        if (!android::base::WriteStringToFile(oom_str, oom_file)) {
+            PLOG(ERROR) << "couldn't write oom_score_adj to snapuserd daemon with pid: " << pid;
+        }
+
         if (!TestSnapuserdIsReady()) {
             PLOG(FATAL) << "snapuserd daemon failed to launch";
         } else {
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index 8bb8652..bdb8075 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -137,6 +137,7 @@
 #define AID_JC_STRONGBOX 1088     /* Javacard Strongbox HAL - to manage omapi ARA rules */
 #define AID_JC_IDENTITYCRED 1089  /* Javacard Identity Cred HAL - to manage omapi ARA rules */
 #define AID_SDK_SANDBOX 1090      /* SDK sandbox virtual UID */
+#define AID_SECURITY_LOG_WRITER 1091 /* write to security log */
 /* Changes to this file must be made in AOSP, *not* in internal branches. */
 
 #define AID_SHELL 2000 /* adb and debug shell user */
diff --git a/libcutils/trace-container.cpp b/libcutils/trace-container.cpp
index 8901e4a..6202662 100644
--- a/libcutils/trace-container.cpp
+++ b/libcutils/trace-container.cpp
@@ -231,24 +231,24 @@
 
 void atrace_async_for_track_begin_body(const char* track_name, const char* name, int32_t cookie) {
     if (CC_LIKELY(atrace_use_container_sock)) {
-        WRITE_MSG_IN_CONTAINER("T", "|", "|%d", track_name, name, cookie);
+        WRITE_MSG_IN_CONTAINER("G", "|", "|%d", track_name, name, cookie);
         return;
     }
 
     if (atrace_marker_fd < 0) return;
 
-    WRITE_MSG("T|%d|", "|%" PRId32, track_name, name, cookie);
+    WRITE_MSG("G|%d|", "|%" PRId32, track_name, name, cookie);
 }
 
 void atrace_async_for_track_end_body(const char* track_name, const char* name, int32_t cookie) {
     if (CC_LIKELY(atrace_use_container_sock)) {
-        WRITE_MSG_IN_CONTAINER("U", "|", "|%d", track_name, name, cookie);
+        WRITE_MSG_IN_CONTAINER("H", "|", "|%d", track_name, name, cookie);
         return;
     }
 
     if (atrace_marker_fd < 0) return;
 
-    WRITE_MSG("U|%d|", "|%" PRId32, track_name, name, cookie);
+    WRITE_MSG("H|%d|", "|%" PRId32, track_name, name, cookie);
 }
 
 void atrace_instant_body(const char* name) {
diff --git a/libcutils/trace-dev.cpp b/libcutils/trace-dev.cpp
index eacc8ee..e9583fb 100644
--- a/libcutils/trace-dev.cpp
+++ b/libcutils/trace-dev.cpp
@@ -90,11 +90,11 @@
 }
 
 void atrace_async_for_track_begin_body(const char* track_name, const char* name, int32_t cookie) {
-    WRITE_MSG("T|%d|", "|%" PRId32, track_name, name, cookie);
+    WRITE_MSG("G|%d|", "|%" PRId32, track_name, name, cookie);
 }
 
 void atrace_async_for_track_end_body(const char* track_name, const char* name, int32_t cookie) {
-    WRITE_MSG("U|%d|", "|%" PRId32, track_name, name, cookie);
+    WRITE_MSG("H|%d|", "|%" PRId32, track_name, name, cookie);
 }
 
 void atrace_instant_body(const char* name) {
diff --git a/libcutils/trace-dev_test.cpp b/libcutils/trace-dev_test.cpp
index 841674a..d4a907d 100644
--- a/libcutils/trace-dev_test.cpp
+++ b/libcutils/trace-dev_test.cpp
@@ -202,13 +202,13 @@
 
     std::string actual;
     ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
-    std::string expected = android::base::StringPrintf("T|%d|fake_track|fake_name|12345", getpid());
+    std::string expected = android::base::StringPrintf("G|%d|fake_track|fake_name|12345", getpid());
     ASSERT_STREQ(expected.c_str(), actual.c_str());
 }
 
 TEST_F(TraceDevTest, atrace_async_for_track_begin_body_exact_track_name) {
     const int name_size = 5;
-    std::string expected = android::base::StringPrintf("T|%d|", getpid());
+    std::string expected = android::base::StringPrintf("G|%d|", getpid());
     std::string track_name =
             MakeName(ATRACE_MESSAGE_LENGTH - expected.length() - 1 - name_size - 6);
     atrace_async_for_track_begin_body(track_name.c_str(), "name", 12345);
@@ -224,7 +224,7 @@
     // Add a single character and verify name truncation
     ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
     track_name += '*';
-    expected = android::base::StringPrintf("T|%d|", getpid());
+    expected = android::base::StringPrintf("G|%d|", getpid());
     expected += track_name + "|nam|12345";
     atrace_async_for_track_begin_body(track_name.c_str(), "name", 12345);
     EXPECT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR));
@@ -234,7 +234,7 @@
 }
 
 TEST_F(TraceDevTest, atrace_async_for_track_begin_body_truncated_track_name) {
-    std::string expected = android::base::StringPrintf("T|%d|", getpid());
+    std::string expected = android::base::StringPrintf("G|%d|", getpid());
     std::string track_name = MakeName(2 * ATRACE_MESSAGE_LENGTH);
     atrace_async_for_track_begin_body(track_name.c_str(), "name", 12345);
 
@@ -250,7 +250,7 @@
 
 TEST_F(TraceDevTest, atrace_async_for_track_begin_body_exact_name) {
     const int track_name_size = 11;
-    std::string expected = android::base::StringPrintf("T|%d|", getpid());
+    std::string expected = android::base::StringPrintf("G|%d|", getpid());
     std::string name =
             MakeName(ATRACE_MESSAGE_LENGTH - expected.length() - 1 - track_name_size - 6);
     atrace_async_for_track_begin_body("track_name", name.c_str(), 12345);
@@ -274,7 +274,7 @@
 }
 
 TEST_F(TraceDevTest, atrace_async_for_track_begin_body_truncated_name) {
-    std::string expected = android::base::StringPrintf("T|%d|track_name|", getpid());
+    std::string expected = android::base::StringPrintf("G|%d|track_name|", getpid());
     std::string name = MakeName(2 * ATRACE_MESSAGE_LENGTH);
     atrace_async_for_track_begin_body("track_name", name.c_str(), 12345);
 
@@ -289,7 +289,7 @@
 }
 
 TEST_F(TraceDevTest, atrace_async_for_track_begin_body_truncated_both) {
-    std::string expected = android::base::StringPrintf("T|%d|", getpid());
+    std::string expected = android::base::StringPrintf("G|%d|", getpid());
     std::string name = MakeName(2 * ATRACE_MESSAGE_LENGTH);
     std::string track_name = MakeName(2 * ATRACE_MESSAGE_LENGTH);
     atrace_async_for_track_begin_body(track_name.c_str(), name.c_str(), 12345);
@@ -312,13 +312,13 @@
 
     std::string actual;
     ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
-    std::string expected = android::base::StringPrintf("U|%d|fake_track|fake_name|12345", getpid());
+    std::string expected = android::base::StringPrintf("H|%d|fake_track|fake_name|12345", getpid());
     ASSERT_STREQ(expected.c_str(), actual.c_str());
 }
 
 TEST_F(TraceDevTest, atrace_async_for_track_end_body_exact_track_name) {
     const int name_size = 5;
-    std::string expected = android::base::StringPrintf("U|%d|", getpid());
+    std::string expected = android::base::StringPrintf("H|%d|", getpid());
     std::string track_name =
             MakeName(ATRACE_MESSAGE_LENGTH - expected.length() - 1 - name_size - 6);
     atrace_async_for_track_end_body(track_name.c_str(), "name", 12345);
@@ -334,7 +334,7 @@
     // Add a single character and verify name truncation
     ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
     track_name += '*';
-    expected = android::base::StringPrintf("U|%d|", getpid());
+    expected = android::base::StringPrintf("H|%d|", getpid());
     expected += track_name + "|nam|12345";
     atrace_async_for_track_end_body(track_name.c_str(), "name", 12345);
     EXPECT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR));
@@ -344,7 +344,7 @@
 }
 
 TEST_F(TraceDevTest, atrace_async_for_track_end_body_truncated_track_name) {
-    std::string expected = android::base::StringPrintf("U|%d|", getpid());
+    std::string expected = android::base::StringPrintf("H|%d|", getpid());
     std::string track_name = MakeName(2 * ATRACE_MESSAGE_LENGTH);
     atrace_async_for_track_end_body(track_name.c_str(), "name", 12345);
 
@@ -360,7 +360,7 @@
 
 TEST_F(TraceDevTest, atrace_async_for_track_end_body_exact_name) {
     const int track_name_size = 11;
-    std::string expected = android::base::StringPrintf("U|%d|", getpid());
+    std::string expected = android::base::StringPrintf("H|%d|", getpid());
     std::string name =
             MakeName(ATRACE_MESSAGE_LENGTH - expected.length() - 1 - track_name_size - 6);
     atrace_async_for_track_end_body("track_name", name.c_str(), 12345);
@@ -384,7 +384,7 @@
 }
 
 TEST_F(TraceDevTest, atrace_async_for_track_end_body_truncated_name) {
-    std::string expected = android::base::StringPrintf("U|%d|track_name|", getpid());
+    std::string expected = android::base::StringPrintf("H|%d|track_name|", getpid());
     std::string name = MakeName(2 * ATRACE_MESSAGE_LENGTH);
     atrace_async_for_track_end_body("track_name", name.c_str(), 12345);
 
@@ -399,7 +399,7 @@
 }
 
 TEST_F(TraceDevTest, atrace_async_for_track_end_body_truncated_both) {
-    std::string expected = android::base::StringPrintf("U|%d|", getpid());
+    std::string expected = android::base::StringPrintf("H|%d|", getpid());
     std::string name = MakeName(2 * ATRACE_MESSAGE_LENGTH);
     std::string track_name = MakeName(2 * ATRACE_MESSAGE_LENGTH);
     atrace_async_for_track_end_body(track_name.c_str(), name.c_str(), 12345);
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 7d6a6c5..019a368 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -182,6 +182,10 @@
     min_sdk_version: "apex_inherit",
 
     afdo: true,
+
+    header_abi_checker: {
+        diff_flags: ["-allow-adding-removing-weak-symbols"],
+    },
 }
 
 cc_library {
diff --git a/storaged/storaged.cpp b/storaged/storaged.cpp
index 8cc8b59..cefef6e 100644
--- a/storaged/storaged.cpp
+++ b/storaged/storaged.cpp
@@ -333,7 +333,7 @@
             first_write = false;
         }
 
-        if (benchmark_size) {
+        if (benchmark_size && benchmark_time_ns) {
             int perf = benchmark_size * 1000000LLU / benchmark_time_ns;
             storage_info->update_perf_history(perf, system_clock::now());
         }
diff --git a/trusty/keymaster/TrustyKeymaster.cpp b/trusty/keymaster/TrustyKeymaster.cpp
index cdfbd90..e77940a 100644
--- a/trusty/keymaster/TrustyKeymaster.cpp
+++ b/trusty/keymaster/TrustyKeymaster.cpp
@@ -279,4 +279,10 @@
     return response;
 }
 
+GetRootOfTrustResponse TrustyKeymaster::GetRootOfTrust(const GetRootOfTrustRequest& request) {
+    GetRootOfTrustResponse response(message_version());
+    ForwardCommand(KM_GET_ROOT_OF_TRUST, request, &response);
+    return response;
+}
+
 }  // namespace keymaster
diff --git a/trusty/keymaster/include/trusty_keymaster/TrustyKeymaster.h b/trusty/keymaster/include/trusty_keymaster/TrustyKeymaster.h
index f80e02f..9f4f39b 100644
--- a/trusty/keymaster/include/trusty_keymaster/TrustyKeymaster.h
+++ b/trusty/keymaster/include/trusty_keymaster/TrustyKeymaster.h
@@ -66,6 +66,7 @@
     DeviceLockedResponse DeviceLocked(const DeviceLockedRequest& request);
     ConfigureVendorPatchlevelResponse ConfigureVendorPatchlevel(
             const ConfigureVendorPatchlevelRequest& request);
+    GetRootOfTrustResponse GetRootOfTrust(const GetRootOfTrustRequest& request);
 
     uint32_t message_version() const { return message_version_; }
 
diff --git a/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h b/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h
index fa475ae..bf0cb70 100644
--- a/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h
+++ b/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h
@@ -59,6 +59,7 @@
     KM_GENERATE_RKP_KEY             = (31 << KEYMASTER_REQ_SHIFT),
     KM_GENERATE_CSR                 = (32 << KEYMASTER_REQ_SHIFT),
     KM_CONFIGURE_VENDOR_PATCHLEVEL  = (33 << KEYMASTER_REQ_SHIFT),
+    KM_GET_ROOT_OF_TRUST            = (34 << KEYMASTER_REQ_SHIFT),
 
     // Bootloader/provisioning calls.
     KM_SET_BOOT_PARAMS = (0x1000 << KEYMASTER_REQ_SHIFT),
diff --git a/trusty/keymaster/keymint/TrustyKeyMintDevice.cpp b/trusty/keymaster/keymint/TrustyKeyMintDevice.cpp
index 44780e8..7d58162 100644
--- a/trusty/keymaster/keymint/TrustyKeyMintDevice.cpp
+++ b/trusty/keymaster/keymint/TrustyKeyMintDevice.cpp
@@ -325,9 +325,20 @@
     return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
 }
 
-ScopedAStatus TrustyKeyMintDevice::getRootOfTrust(const array<uint8_t, 16>& /* challenge */,
-                                                  vector<uint8_t>* /* rootOfTrust */) {
-    return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
+ScopedAStatus TrustyKeyMintDevice::getRootOfTrust(const array<uint8_t, 16>& challenge,
+                                                  vector<uint8_t>* rootOfTrust) {
+    if (!rootOfTrust) {
+        return kmError2ScopedAStatus(KM_ERROR_UNEXPECTED_NULL_POINTER);
+    }
+    keymaster::GetRootOfTrustRequest request(impl_->message_version(),
+                                             {challenge.begin(), challenge.end()});
+    keymaster::GetRootOfTrustResponse response = impl_->GetRootOfTrust(request);
+    if (response.error != KM_ERROR_OK) {
+        return kmError2ScopedAStatus(response.error);
+    }
+
+    *rootOfTrust = std::move(response.rootOfTrust);
+    return ScopedAStatus::ok();
 }
 
 ScopedAStatus TrustyKeyMintDevice::sendRootOfTrust(const vector<uint8_t>& /* rootOfTrust */) {
diff --git a/trusty/utils/acvp/acvp_ipc.h b/trusty/utils/acvp/acvp_ipc.h
index 8b48ae3..300e05a 100644
--- a/trusty/utils/acvp/acvp_ipc.h
+++ b/trusty/utils/acvp/acvp_ipc.h
@@ -27,7 +27,7 @@
 /*
  * Maximum number of arguments
  */
-#define ACVP_MAX_NUM_ARGUMENTS 8
+#define ACVP_MAX_NUM_ARGUMENTS 9
 
 /*
  * Maximum length of an algorithm name