Merge "healthd: BatteryMonitor: Fix compiler warning"
diff --git a/adb/daemon/remount_service.cpp b/adb/daemon/remount_service.cpp
index ae02525..2dcfb53 100644
--- a/adb/daemon/remount_service.cpp
+++ b/adb/daemon/remount_service.cpp
@@ -78,7 +78,13 @@
     std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
                                                                fs_mgr_free_fstab);
     struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab.get(), dir);
-    return rec ? rec->blk_device : "";
+    if (!rec) {
+        return "";
+    }
+    if (fs_mgr_is_logical(rec)) {
+        fs_mgr_update_logical_partition(rec);
+    }
+    return rec->blk_device;
 }
 
 // The proc entry for / is full of lies, so check fstab instead.
@@ -87,7 +93,7 @@
     if (is_root) {
         return find_fstab_mount(dir);
     } else {
-       return find_proc_mount(dir);
+        return find_proc_mount(dir);
     }
 }
 
@@ -155,11 +161,12 @@
         return true;
     }
     bool is_root = strcmp(dir, "/") == 0;
-    if (is_root && !find_mount("/system", false).empty()) {
-        dir = "/system";
-        is_root = false;
-    }
     std::string dev = find_mount(dir, is_root);
+    if (is_root && dev.empty()) {
+        // The fstab entry will be /system if the device switched roots during
+        // first-stage init.
+        dev = find_mount("/system", true);
+    }
     // Even if the device for the root is not found, we still try to remount it
     // as rw. This typically only happens when running Android in a container:
     // the root will almost always be in a loop device, which is dynamic, so
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index cd2dc04..4e3879b 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -19,6 +19,7 @@
 #include <fcntl.h>
 
 #if !defined(_WIN32)
+#include <dirent.h>
 #include <sys/socket.h>
 #endif
 
@@ -211,6 +212,17 @@
   return file;
 }
 
+// Using fdopendir with unique_fd correctly is more annoying than it should be,
+// because fdopen doesn't close the file descriptor received upon failure.
+inline DIR* Fdopendir(unique_fd&& ufd) {
+  int fd = ufd.release();
+  DIR* dir = fdopendir(fd);
+  if (dir == nullptr) {
+    close(fd);
+  }
+  return dir;
+}
+
 #endif  // !defined(_WIN32)
 
 }  // namespace base
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index 6e45133..11c838a 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -329,7 +329,6 @@
 
   private:
     std::string super_device_;
-    uint32_t slot_number_;
     std::unique_ptr<MetadataBuilder> builder_;
 };
 
@@ -341,8 +340,8 @@
     super_device_ = *super_device;
 
     std::string slot = device->GetCurrentSlot();
-    slot_number_ = SlotNumberForSlotSuffix(slot);
-    builder_ = MetadataBuilder::New(super_device_, slot_number_);
+    uint32_t slot_number = SlotNumberForSlotSuffix(slot);
+    builder_ = MetadataBuilder::New(super_device_, slot_number);
 }
 
 bool PartitionBuilder::Write() {
@@ -350,7 +349,11 @@
     if (!metadata) {
         return false;
     }
-    return UpdatePartitionTable(super_device_, *metadata.get(), slot_number_);
+    bool ok = true;
+    for (uint32_t i = 0; i < metadata->geometry.metadata_slot_count; i++) {
+        ok &= UpdatePartitionTable(super_device_, *metadata.get(), i);
+    }
+    return ok;
 }
 
 bool CreatePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args) {
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index ae2e2fe..c321fe3 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1588,6 +1588,25 @@
     return true;
 }
 
-std::string fs_mgr_get_super_partition_name(int /* slot */) {
+std::string fs_mgr_get_super_partition_name(int slot) {
+    // Devices upgrading to dynamic partitions are allowed to specify a super
+    // partition name, assumed to be A/B (non-A/B retrofit is not supported).
+    // For devices launching with dynamic partition support, the partition
+    // name must be "super".
+    std::string super_partition;
+    if (fs_mgr_get_boot_config_from_kernel_cmdline("super_partition", &super_partition)) {
+        std::string suffix;
+        if (slot == 0) {
+            suffix = "_a";
+        } else if (slot == 1) {
+            suffix = "_b";
+        } else if (slot == -1) {
+            suffix = fs_mgr_get_slot_suffix();
+        }
+        if (suffix.empty()) {
+            LFATAL << "Super partition name can only be overridden on A/B devices.";
+        }
+        return super_partition + suffix;
+    }
     return LP_METADATA_DEFAULT_PARTITION_NAME;
 }
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index f06b819..49ecc06 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -20,6 +20,7 @@
 #include <linux/fs.h>
 #include <selinux/selinux.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/mount.h>
 #include <sys/param.h>
@@ -692,13 +693,21 @@
         errno = 0;
     }
 
-    auto ret = system((mnt_type == "f2fs")
-                              ? ((kMkF2fs + " -d1 " + scratch_device).c_str())
-                              : ((kMkExt4 + " -b 4096 -t ext4 -m 0 -M " + kScratchMountPoint +
-                                  " -O has_journal " + scratch_device)
-                                         .c_str()));
+    // Force mkfs by design for overlay support of adb remount, simplify and
+    // thus do not rely on fsck to correct problems that could creep in.
+    auto command = ""s;
+    if (mnt_type == "f2fs") {
+        command = kMkF2fs + " -w 4096 -f -d1 -l" + android::base::Basename(kScratchMountPoint);
+    } else if (mnt_type == "ext4") {
+        command = kMkExt4 + " -b 4096 -t ext4 -m 0 -O has_journal -M " + kScratchMountPoint;
+    } else {
+        LERROR << mnt_type << " has no mkfs cookbook";
+        return false;
+    }
+    command += " " + scratch_device;
+    auto ret = system(command.c_str());
     if (ret) {
-        LERROR << "make " << mnt_type << " filesystem on " << scratch_device << " error=" << ret;
+        LERROR << "make " << mnt_type << " filesystem on " << scratch_device << " return=" << ret;
         return false;
     }
 
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 5e83cfb..23a92d3 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -39,11 +39,13 @@
 #define LINFO    LOG(INFO) << FS_MGR_TAG
 #define LWARNING LOG(WARNING) << FS_MGR_TAG
 #define LERROR   LOG(ERROR) << FS_MGR_TAG
+#define LFATAL LOG(FATAL) << FS_MGR_TAG
 
 // Logs a message with strerror(errno) at the end
 #define PINFO    PLOG(INFO) << FS_MGR_TAG
 #define PWARNING PLOG(WARNING) << FS_MGR_TAG
 #define PERROR   PLOG(ERROR) << FS_MGR_TAG
+#define PFATAL PLOG(FATAL) << FS_MGR_TAG
 
 #define CRYPTO_TMPFS_OPTIONS "size=512m,mode=0771,uid=1000,gid=1000"
 
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index b6a8eef..6b908d3 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -198,39 +198,80 @@
 
 # Do something
 adb_wait || die "wait for device failed"
-adb_sh ls -d /sys/module/overlay </dev/null || die "overlay module not present"
-adb_su ls /sys/module/overlay/parameters/override_creds </dev/null ||
+adb_sh ls -d /sys/module/overlay </dev/null >/dev/null &&
+  echo "${GREEN}[       OK ]${NORMAL} overlay module present" >&2 ||
+  die "overlay module not present"
+adb_su ls /sys/module/overlay/parameters/override_creds </dev/null >/dev/null &&
+  echo "${GREEN}[       OK ]${NORMAL} overlay module supports override_creds" >&2 ||
   die "overlay module can not be used on ANDROID"
 adb_root &&
-  adb_wait &&
-  D=`adb disable-verity 2>&1` ||
-    die "setup for overlay"
+  adb_wait ||
+  die "initial setup"
+reboot=false
+OVERLAYFS_BACKING="cache mnt/scratch"
+for d in ${OVERLAYFS_BACKING}; do
+  if adb_sh ls -d /${d}/overlay </dev/null >/dev/null 2>&1; then
+    echo "${ORANGE}[  WARNING ]${NORMAL} /${d}/overlay is setup, wiping" >&2
+    adb_sh rm -rf /${d}/overlay </dev/null ||
+      die "/${d}/overlay wipe"
+    reboot=true
+  fi
+done
+if ${reboot}; then
+  echo "${ORANGE}[  WARNING ]${NORMAL} rebooting before test" >&2
+  adb_reboot &&
+    adb_wait 2m &&
+    adb_root &&
+    adb_wait ||
+    die "reboot after wipe"
+fi
+D=`adb_sh df -k </dev/null` &&
+  H=`echo "${D}" | head -1` &&
+  D=`echo "${D}" | grep "^overlay "` &&
+  echo "${H}" &&
+  echo "${D}" &&
+  echo "${ORANGE}[  WARNING ]${NORMAL} overlays present before setup" >&2 ||
+  echo "${GREEN}[       OK ]${NORMAL} no overlay present before setup" >&2
+
+D=`adb disable-verity 2>&1` ||
+  die "setup for overlay ${D}"
 echo "${D}"
 if [ X"${D}" != X"${D##*using overlayfs}" ]; then
   echo "${GREEN}[       OK ]${NORMAL} using overlayfs" >&2
 fi
-if adb_sh ls -d /data/overlay </dev/null >/dev/null 2>&1; then
-  echo "/data/overlay setup, clearing out" >&2
-  adb_sh rm -rf /data/overlay </dev/null ||
-    die "/data/overlay removal"
-fi
-adb_sh ls -d /cache/overlay </dev/null >/dev/null 2>&1 ||
-  adb_sh ls -d /mnt/scratch/overlay </dev/null >/dev/null 2>&1 ||
-  die "overlay directory setup"
 adb_reboot &&
   adb_wait &&
-  adb_sh df -k </dev/null | head -1 &&
-  adb_sh df -k </dev/null | grep "^overlay " ||
+  D=`adb_sh df -k </dev/null` &&
+  H=`echo "${D}" | head -1` &&
+  D=`echo "${D}" | grep "^overlay "` &&
+  echo "${H}" &&
+  echo "${D}" ||
   die "overlay takeover failed"
-adb_sh df -k </dev/null | grep "^overlay .* /system\$" >/dev/null ||
+echo "${D}" | grep "^overlay .* /system\$" >/dev/null ||
   echo "${ORANGE}[  WARNING ]${NORMAL} overlay takeover before remount not complete" >&2
 
 adb_root &&
   adb_wait &&
   adb remount &&
-  adb_sh df -k </dev/null | head -1 &&
-  adb_sh df -k </dev/null | grep "^overlay " &&
-  adb_sh df -k </dev/null | grep "^overlay .* /system\$" >/dev/null ||
+  D=`adb_sh df -k </dev/null` ||
+  die "can not collect filesystem data"
+if echo "${D}" | grep " /mnt/scratch" >/dev/null; then
+  echo "${ORANGE}[     INFO ]${NORMAL} using scratch dynamic partition for overrides" >&2
+  H=`adb_sh cat /proc/mounts | sed -n 's@\([^ ]*\) /mnt/scratch \([^ ]*\) .*@\2 on \1@p'`
+  [ -n "${H}" ] &&
+    echo "${ORANGE}[     INFO ]${NORMAL} scratch filesystem ${H}"
+fi
+for d in ${OVERLAYFS_BACKING}; do
+  if adb_sh ls -d /${d}/overlay/system/upper </dev/null >/dev/null 2>&1; then
+    echo "${ORANGE}[     INFO ]${NORMAL} /${d}/overlay is setup" >&2
+  fi
+done
+
+H=`echo "${D}" | head -1` &&
+  D=`echo "${D}" | grep "^overlay "` &&
+  echo "${H}" &&
+  echo "${D}" &&
+  echo "${D}" | grep "^overlay .* /system\$" >/dev/null ||
   die  "overlay takeover after remount"
 !(adb_sh grep "^overlay " /proc/mounts </dev/null | grep " overlay ro,") &&
   !(adb_sh grep " rw," /proc/mounts </dev/null |
@@ -275,11 +316,14 @@
 adb_wait &&
   adb_root &&
   adb_wait &&
-  adb_sh df -k </dev/null | head -1 &&
-  adb_sh df -k </dev/null | grep "^overlay " &&
-  adb_sh df -k </dev/null | grep "^overlay .* /system\$" >/dev/null ||
+  D=`adb_sh df -k </dev/null` &&
+  H=`echo "${D}" | head -1` &&
+  D=`echo "${D}" | grep "^overlay "` &&
+  echo "${H}" &&
+  echo "${D}" &&
+  echo "${D}" | grep "^overlay .* /system\$" >/dev/null ||
   die  "overlay system takeover after flash vendor"
-adb_sh df -k </dev/null | grep "^overlay .* /vendor\$" >/dev/null &&
+echo "${D}" | grep "^overlay .* /vendor\$" >/dev/null &&
   die  "overlay minus vendor takeover after flash vendor"
 B="`adb_cat /system/hello`" ||
   die "re-read system hello after flash vendor"
diff --git a/init/Android.mk b/init/Android.mk
index c85727c..dc46d21 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -90,6 +90,8 @@
     libcap \
 
 LOCAL_SANITIZE := signed-integer-overflow
+# First stage init is weird: it may start without stdout/stderr, and no /proc.
+LOCAL_NOSANITIZE := hwaddress
 include $(BUILD_EXECUTABLE)
 
 include $(CLEAR_VARS)
diff --git a/init/devices.cpp b/init/devices.cpp
index 58c8b2e..45b17a2 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -419,7 +419,7 @@
 }
 
 void DeviceHandler::ColdbootDone() {
-    skip_restorecon_ = true;
+    skip_restorecon_ = false;
 }
 
 DeviceHandler::DeviceHandler(std::vector<Permissions> dev_permissions,
diff --git a/liblog/include/android/log.h b/liblog/include/android/log.h
index ee9220d..b2f0ed9 100644
--- a/liblog/include/android/log.h
+++ b/liblog/include/android/log.h
@@ -14,25 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef _ANDROID_LOG_H
-#define _ANDROID_LOG_H
-
-/******************************************************************
- *
- * IMPORTANT NOTICE:
- *
- *   This file is part of Android's set of stable system headers
- *   exposed by the Android NDK (Native Development Kit) since
- *   platform release 1.5
- *
- *   Third-party source AND binary code relies on the definitions
- *   here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
- *
- *   - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
- *   - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
- *   - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
- *   - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
- */
+#pragma once
 
 /**
  * @addtogroup Logging
@@ -154,27 +136,51 @@
 
 #ifndef log_id_t_defined
 #define log_id_t_defined
+/**
+ * Identifies a specific log buffer for __android_log_buf_write()
+ * and __android_log_buf_print().
+ */
 typedef enum log_id {
   LOG_ID_MIN = 0,
 
+  /** The main log buffer. This is the only log buffer available to apps. */
   LOG_ID_MAIN = 0,
+  /** The radio log buffer. */
   LOG_ID_RADIO = 1,
+  /** The event log buffer. */
   LOG_ID_EVENTS = 2,
+  /** The system log buffer. */
   LOG_ID_SYSTEM = 3,
+  /** The crash log buffer. */
   LOG_ID_CRASH = 4,
+  /** The statistics log buffer. */
   LOG_ID_STATS = 5,
+  /** The security log buffer. */
   LOG_ID_SECURITY = 6,
-  LOG_ID_KERNEL = 7, /* place last, third-parties can not use it */
+  /** The kernel log buffer. */
+  LOG_ID_KERNEL = 7,
 
   LOG_ID_MAX
 } log_id_t;
 #endif
 
-/*
- * Send a simple string to the log.
+/**
+ * Writes the constant string `text` to the log buffer `id`,
+ * with priority `prio` and tag `tag`.
+ *
+ * Apps should use __android_log_write() instead.
  */
 int __android_log_buf_write(int bufID, int prio, const char* tag,
                             const char* text);
+
+/**
+ * Writes a formatted string to log buffer `id`,
+ * with priority `prio` and tag `tag`.
+ * The details of formatting are the same as for
+ * [printf(3)](http://man7.org/linux/man-pages/man3/printf.3.html).
+ *
+ * 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__)
@@ -187,5 +193,3 @@
 #endif
 
 /** @} */
-
-#endif /* _ANDROID_LOG_H */
diff --git a/llkd/README.md b/llkd/README.md
index e5be850..3da7a2f 100644
--- a/llkd/README.md
+++ b/llkd/README.md
@@ -44,7 +44,8 @@
 ABA detection since forward scheduling progress is allowed, thus the condition
 for the symbols are:
 
-- Check is looking for " " + __symbol__+ "0x" in /proc/<pid>/stack.
+- Check is looking for " __symbol__+0x" or " __symbol__.cfi+0x" in
+  /proc/__pid__/stack.
 - The __symbol__ should be rare and short lived enough that on a typical
   system the function is seen at most only once in a sample over the timeout
   period of ro.llk.stack.timeout_ms, samples occur every ro.llk.check_ms. This
@@ -88,7 +89,14 @@
 Android Properties llkd respond to (*prop*_ms parms are in milliseconds):
 
 #### ro.config.low_ram
-default false, if true do not sysrq t (dump all threads).
+device is configured with limited memory.
+
+#### ro.debuggable
+device is configured for userdebug or eng build.
+
+#### ro.llk.sysrq_t
+default not ro.config.low_ram, or ro.debuggable if property is "eng".
+if true do sysrq t (dump all threads).
 
 #### ro.llk.enable
 default false, allow live-lock daemon to be enabled.
@@ -121,14 +129,14 @@
 #### ro.llk.stack.timeout_ms
 default ro.llk.timeout_ms,
 checking for persistent stack symbols maximum timelimit.
-Only active on userdebug and eng builds.
+Only active on userdebug or eng builds.
 
 #### ro.llk.check_ms
 default 2 minutes samples of threads for D or Z.
 
 #### ro.llk.stack
-default cma_alloc,__get_user_pages, comma separated list of kernel symbols.
-The string "*false*" is the equivalent to an *empty* list.
+default cma_alloc,__get_user_pages,bit_wait_io comma separated list of kernel
+symbols.  The string "*false*" is the equivalent to an *empty* list.
 Look for kernel stack symbols that if ever persistently present can
 indicate a subsystem is locked up.
 Beware, check does not on purpose do forward scheduling ABA except by polling
@@ -136,11 +144,14 @@
 should be exceptionally rare and fleeting.
 One must be convinced that it is virtually *impossible* for symbol to show up
 persistently in all samples of the stack.
-Only active on userdebug and eng builds.
+Again, looks for a match for either " **symbol**+0x" or " **symbol**.cfi+0x"
+in stack expansion.
+Only available on userdebug or eng builds, limited privileges due to security
+concerns on user builds prevents this checking.
 
 #### ro.llk.blacklist.process
 default 0,1,2 (kernel, init and [kthreadd]) plus process names
-init,[kthreadd],[khungtaskd],lmkd,lmkd.llkd,llkd,watchdogd,
+init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd,
 [watchdogd],[watchdogd/0],...,[watchdogd/***get_nprocs**-1*].
 The string "*false*" is the equivalent to an *empty* list.
 Do not watch these processes.  A process can be comm, cmdline or pid reference.
@@ -160,7 +171,7 @@
 Do not watch processes that match this uid.
 
 #### ro.llk.blacklist.process.stack
-default process names init,lmkd,lmkd.llkd,llkd,keystore,logd.
+default process names init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd.
 The string "*false*" is the equivalent to an *empty* list.
 This subset of processes are not monitored for live lock stack signatures.
 Also prevents the sepolicy violation associated with processes that block
diff --git a/llkd/include/llkd.h b/llkd/include/llkd.h
index 2c62fca..b16b1d8 100644
--- a/llkd/include/llkd.h
+++ b/llkd/include/llkd.h
@@ -35,6 +35,8 @@
 #define LLK_ENABLE_DEFAULT             false /* "eng" and userdebug true */
 #define KHT_ENABLE_WRITEABLE_PROPERTY  "khungtask.enable"
 #define KHT_ENABLE_PROPERTY            "ro." KHT_ENABLE_WRITEABLE_PROPERTY
+#define LLK_ENABLE_SYSRQ_T_PROPERTY    "ro.llk.sysrq_t"
+#define LLK_ENABLE_SYSRQ_T_DEFAULT     true
 #define LLK_MLOCKALL_PROPERTY          "ro.llk.mlockall"
 #define LLK_MLOCKALL_DEFAULT           true
 #define LLK_KILLTEST_PROPERTY          "ro.llk.killtest"
@@ -48,7 +50,7 @@
 /* LLK_CHECK_MS_DEFAULT = actual timeout_ms / LLK_CHECKS_PER_TIMEOUT_DEFAULT */
 #define LLK_CHECKS_PER_TIMEOUT_DEFAULT 5
 #define LLK_CHECK_STACK_PROPERTY       "ro.llk.stack"
-#define LLK_CHECK_STACK_DEFAULT        "cma_alloc,__get_user_pages"
+#define LLK_CHECK_STACK_DEFAULT        "cma_alloc,__get_user_pages,bit_wait_io"
 #define LLK_BLACKLIST_PROCESS_PROPERTY "ro.llk.blacklist.process"
 #define LLK_BLACKLIST_PROCESS_DEFAULT  \
     "0,1,2,init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd,[watchdogd],[watchdogd/0]"
diff --git a/llkd/libllkd.cpp b/llkd/libllkd.cpp
index 2727aab..0827470 100644
--- a/llkd/libllkd.cpp
+++ b/llkd/libllkd.cpp
@@ -85,6 +85,7 @@
 milliseconds llkCheckMs;                             // checking interval to inspect any
                                                      // persistent live-locked states
 bool llkLowRam;                                      // ro.config.low_ram
+bool llkEnableSysrqT = LLK_ENABLE_SYSRQ_T_DEFAULT;   // sysrq stack trace dump
 bool khtEnable = LLK_ENABLE_DEFAULT;                 // [khungtaskd] panic
 // [khungtaskd] should have a timeout beyond the granularity of llkTimeoutMs.
 // Provides a wide angle of margin b/c khtTimeout is also its granularity.
@@ -509,8 +510,10 @@
     return android::base::Trim(content) == string;
 }
 
-void llkPanicKernel(bool dump, pid_t tid, const char* state) __noreturn;
-void llkPanicKernel(bool dump, pid_t tid, const char* state) {
+void llkPanicKernel(bool dump, pid_t tid, const char* state,
+                    const std::string& message = "") __noreturn;
+void llkPanicKernel(bool dump, pid_t tid, const char* state, const std::string& message) {
+    if (!message.empty()) LOG(ERROR) << message;
     auto sysrqTriggerFd = llkFileToWriteFd("/proc/sysrq-trigger");
     if (sysrqTriggerFd < 0) {
         // DYB
@@ -523,14 +526,24 @@
     if (dump) {
         // Show all locks that are held
         android::base::WriteStringToFd("d", sysrqTriggerFd);
+        // Show all waiting tasks
+        android::base::WriteStringToFd("w", sysrqTriggerFd);
         // This can trigger hardware watchdog, that is somewhat _ok_.
         // But useless if pstore configured for <256KB, low ram devices ...
-        if (!llkLowRam) {
+        if (llkEnableSysrqT) {
             android::base::WriteStringToFd("t", sysrqTriggerFd);
+            // Show all locks that are held (in case 't' overflows ramoops)
+            android::base::WriteStringToFd("d", sysrqTriggerFd);
+            // Show all waiting tasks (in case 't' overflows ramoops)
+            android::base::WriteStringToFd("w", sysrqTriggerFd);
         }
         ::usleep(200000);  // let everything settle
     }
-    llkWriteStringToFile("SysRq : Trigger a crash : 'livelock,"s + state + "'\n", "/dev/kmsg");
+    // SysRq message matches kernel format, and propagates through bootstat
+    // ultimately to the boot reason into panic,livelock,<state>.
+    llkWriteStringToFile(message + (message.empty() ? "" : "\n") +
+                                 "SysRq : Trigger a crash : 'livelock,"s + state + "'\n",
+                         "/dev/kmsg");
     android::base::WriteStringToFd("c", sysrqTriggerFd);
     // NOTREACHED
     // DYB
@@ -726,7 +739,8 @@
     char match = -1;
     for (const auto& stack : llkCheckStackSymbols) {
         if (++idx < 0) break;
-        if (kernel_stack.find(" "s + stack + "+0x") != std::string::npos) {
+        if ((kernel_stack.find(" "s + stack + "+0x") != std::string::npos) ||
+            (kernel_stack.find(" "s + stack + ".cfi+0x") != std::string::npos)) {
             match = idx;
             break;
         }
@@ -798,6 +812,7 @@
 
 void llkLogConfig(void) {
     LOG(INFO) << "ro.config.low_ram=" << llkFormat(llkLowRam) << "\n"
+              << LLK_ENABLE_SYSRQ_T_PROPERTY "=" << llkFormat(llkEnableSysrqT) << "\n"
               << LLK_ENABLE_PROPERTY "=" << llkFormat(llkEnable) << "\n"
               << KHT_ENABLE_PROPERTY "=" << llkFormat(khtEnable) << "\n"
               << LLK_MLOCKALL_PROPERTY "=" << llkFormat(llkMlockall) << "\n"
@@ -1089,10 +1104,12 @@
                 }
             }
             // We are here because we have confirmed kernel live-lock
-            LOG(ERROR) << state << ' ' << llkFormat(procp->count) << ' ' << ppid << "->" << pid
-                       << "->" << tid << ' ' << procp->getComm() << " [panic]";
+            const auto message = state + " "s + llkFormat(procp->count) + " " +
+                                 std::to_string(ppid) + "->" + std::to_string(pid) + "->" +
+                                 std::to_string(tid) + " " + procp->getComm() + " [panic]";
             llkPanicKernel(true, tid,
-                           (state == 'Z') ? "zombie" : (state == 'D') ? "driver" : "sleeping");
+                           (state == 'Z') ? "zombie" : (state == 'D') ? "driver" : "sleeping",
+                           message);
         }
         LOG(VERBOSE) << "+closedir()";
     }
@@ -1149,13 +1166,22 @@
     return duration_cast<milliseconds>(llkCheck()).count();
 }
 
+bool llkCheckEng(const std::string& property) {
+    return android::base::GetProperty(property, "eng") == "eng";
+}
+
 bool llkInit(const char* threadname) {
     auto debuggable = android::base::GetBoolProperty("ro.debuggable", false);
     llkLowRam = android::base::GetBoolProperty("ro.config.low_ram", false);
-    if (!LLK_ENABLE_DEFAULT && debuggable) {
-        llkEnable = android::base::GetProperty(LLK_ENABLE_PROPERTY, "eng") == "eng";
-        khtEnable = android::base::GetProperty(KHT_ENABLE_PROPERTY, "eng") == "eng";
+    llkEnableSysrqT &= !llkLowRam;
+    if (debuggable) {
+        llkEnableSysrqT |= llkCheckEng(LLK_ENABLE_SYSRQ_T_PROPERTY);
+        if (!LLK_ENABLE_DEFAULT) {  // NB: default is currently true ...
+            llkEnable |= llkCheckEng(LLK_ENABLE_PROPERTY);
+            khtEnable |= llkCheckEng(KHT_ENABLE_PROPERTY);
+        }
     }
+    llkEnableSysrqT = android::base::GetBoolProperty(LLK_ENABLE_SYSRQ_T_PROPERTY, llkEnableSysrqT);
     llkEnable = android::base::GetBoolProperty(LLK_ENABLE_PROPERTY, llkEnable);
     if (llkEnable && !llkTopDirectory.reset(procdir)) {
         // Most likely reason we could be here is llkd was started