Merge changes I16ea9e32,Ib53b5d3e

* changes:
  init: make fatal reboot target configurable
  init: dump stack when aborting
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index 04422f9..c523893 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -33,6 +33,7 @@
 ##  Helper Variables
 ##
 
+EMPTY=""
 SPACE=" "
 # A _real_ embedded tab character
 TAB="`echo | tr '\n' '\t'`"
@@ -50,6 +51,9 @@
 start_time=`date +%s`
 ACTIVE_SLOT=
 
+ADB_WAIT=3m
+FASTBOOT_WAIT=2m
+
 ##
 ##  Helper Functions
 ##
@@ -131,10 +135,30 @@
 adb_logcat() {
   echo "${RED}[     INFO ]${NORMAL} logcat ${@}" >&2 &&
   adb logcat "${@}" </dev/null |
+    tr -d '\r' |
     grep -v 'logd    : logdr: UID=' |
     sed -e '${/------- beginning of kernel/d}' -e 's/^[0-1][0-9]-[0-3][0-9] //'
 }
 
+[ "USAGE: avc_check >/dev/stderr
+
+Returns: worrisome avc violations" ]
+avc_check() {
+  if ! ${overlayfs_supported:-false}; then
+    return
+  fi
+  local L=`adb_logcat -b all -v brief -d \
+                      -e 'context=u:object_r:unlabeled:s0' 2>/dev/null |
+             sed -n 's/.*avc: //p' |
+             sort -u`
+  if [ -z "${L}" ]; then
+    return
+  fi
+  echo "${ORANGE}[  WARNING ]${NORMAL} unlabeled sepolicy violations:" >&2
+  echo "${L}" |
+    sed 's/^/             /' >&2
+}
+
 [ "USAGE: get_property <prop>
 
 Returns the property value" ]
@@ -173,7 +197,8 @@
 
 Returns: true if the reboot command succeeded" ]
 adb_reboot() {
-  adb reboot remount-test || true
+  avc_check
+  adb reboot remount-test </dev/null || true
   sleep 2
 }
 
@@ -240,10 +265,13 @@
 
 Returns: waits until the device has returned for adb or optional timeout" ]
 adb_wait() {
+  local start=`date +%s`
+  local duration=
   local ret
   if [ -n "${1}" ]; then
     USB_DEVICE=`usb_devnum --next`
-    echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}"
+    duration=`format_duration ${1}`
+    echo -n ". . . waiting ${duration}" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}"
     timeout --preserve-status --signal=KILL ${1} adb wait-for-device 2>/dev/null
     ret=${?}
     echo -n "                                                                             ${CR}"
@@ -258,9 +286,45 @@
       echo "${ORANGE}[  WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" >&2
     fi
   fi
+  local end=`date +%s`
+  local diff_time=`expr ${end} - ${start}`
+  local _print_time=${print_time}
+  if [ ${diff_time} -lt 15 ]; then
+    _print_time=false
+  fi
+  diff_time=`format_duration ${diff_time}`
+  if [ "${diff_time}" = "${duration}" ]; then
+    _print_time=false
+  fi
+
+  local reason=
+  if inAdb; then
+    reason=`get_property ro.boot.bootreason`
+  fi
+  case ${reason} in
+    reboot*)
+      reason=
+      ;;
+    ${EMPTY})
+      ;;
+    *)
+      reason=" for boot reason ${reason}"
+      ;;
+  esac
+  if ${_print_time} || [ -n "${reason}" ]; then
+    echo "${BLUE}[     INFO ]${NORMAL} adb wait duration ${diff_time}${reason}"
+  fi >&2
+
   return ${ret}
 }
 
+[ "USAGE: adb_user > /dev/stdout
+
+Returns: the adb daemon user" ]
+adb_user() {
+  adb_sh echo '${USER}' </dev/null
+}
+
 [ "USAGE: usb_status > stdout 2> stderr
 
 Assumes referenced right after adb_wait or fastboot_wait failued.
@@ -276,7 +340,7 @@
   elif inRecovery; then
     echo "(In recovery mode)"
   elif inAdb; then
-    echo "(In adb mode)"
+    echo "(In adb mode `adb_user`)"
   else
     echo "(USB stack borken for ${USB_ADDRESS})"
     USB_DEVICE=`usb_devnum`
@@ -366,17 +430,68 @@
   inFastboot || inAdb || inRecovery
 }
 
+wait_for_screen_timeout=900
+[ "USAGE: wait_for_screen [-n] [TIMEOUT]
+
+-n - echo newline at exit
+TIMEOUT - default `format_duration ${wait_for_screen_timeout}`" ]
+wait_for_screen() {
+  exit_function=true
+  if [ X"-n" = X"${1}" ]; then
+    exit_function=echo
+    shift
+  fi
+  timeout=${wait_for_screen_timeout}
+  if [ ${#} -gt 0 ]; then
+    timeout=${1}
+    shift
+  fi
+  counter=0
+  while true; do
+    if inFastboot; then
+      fastboot reboot
+    elif inAdb; then
+      if [ 0 != ${counter} ]; then
+        adb_wait
+      fi
+      if [ -n "`get_property sys.boot.reason`" ]
+      then
+        vals=`get_property |
+              sed -n 's/[[]sys[.]\(boot_completed\|logbootcomplete\)[]]: [[]\([01]\)[]]$/\1=\2/p'`
+        if [ "${vals}" = "`echo boot_completed=1 ; echo logbootcomplete=1`" ]
+        then
+          sleep 1
+          break
+        fi
+        if [ "${vals}" = "`echo logbootcomplete=1 ; echo boot_completed=1`" ]
+        then
+          sleep 1
+          break
+        fi
+      fi
+    fi
+    counter=`expr ${counter} + 1`
+    if [ ${counter} -gt ${timeout} ]; then
+      ${exit_function}
+      echo "ERROR: wait_for_screen() timed out (`format_duration ${timeout}`)" >&2
+      return 1
+    fi
+    sleep 1
+  done
+  ${exit_function}
+}
+
 [ "USAGE: adb_root
 
 NB: This can be flakey on devices due to USB state
 
 Returns: true if device in root state" ]
 adb_root() {
-  [ root != "`adb_sh echo '${USER}' </dev/null`" ] || return 0
+  [ root != "`adb_user`" ] || return 0
   adb root >/dev/null </dev/null 2>/dev/null
   sleep 2
-  adb_wait 2m &&
-    [ root = "`adb_sh echo '${USER}' </dev/null`" ]
+  adb_wait ${ADB_WAIT} &&
+    [ root = "`adb_user`" ]
 }
 
 [ "USAGE: adb_unroot
@@ -385,11 +500,11 @@
 
 Returns: true if device in un root state" ]
 adb_unroot() {
-  [ root = "`adb_sh echo '${USER}' </dev/null`" ] || return 0
+  [ root = "`adb_user`" ] || return 0
   adb unroot >/dev/null </dev/null 2>/dev/null
   sleep 2
-  adb_wait 2m &&
-    [ root != "`adb_sh echo '${USER}' </dev/null`" ]
+  adb_wait ${ADB_WAIT} &&
+    [ root != "`adb_user`" ]
 }
 
 [ "USAGE: fastboot_getvar var expected >/dev/stderr
@@ -540,6 +655,30 @@
   return 0
 }
 
+[ "USAGE: EXPECT_NE <lval> <rval> [--warning [message]]
+
+Returns true if lval matches rval" ]
+EXPECT_NE() {
+  local lval="${1}"
+  local rval="${2}"
+  shift 2
+  local error=1
+  local prefix="${RED}[    ERROR ]${NORMAL}"
+  if [ X"${1}" = X"--warning" ]; then
+      prefix="${RED}[  WARNING ]${NORMAL}"
+      error=0
+      shift 1
+  fi
+  if [ X"${rval}" = X"${lval}" ]; then
+    echo "${prefix} did not expect \"${lval}\" ${*}" >&2
+    return ${error}
+  fi
+  if [ -n "${*}" ] ; then
+    echo "${prefix} ok \"${lval}\" not \"${rval}\" ${*}" >&2
+  fi
+  return 0
+}
+
 [ "USAGE: check_eq <lval> <rval> [--warning [message]]
 
 Exits if (regex) lval mismatches rval" ]
@@ -555,6 +694,21 @@
     die "${@}"
 }
 
+[ "USAGE: check_ne <lval> <rval> [--warning [message]]
+
+Exits if lval matches rval" ]
+check_ne() {
+  local lval="${1}"
+  local rval="${2}"
+  shift 2
+  if [ X"${1}" = X"--warning" ]; then
+      EXPECT_NE "${lval}" "${rval}" ${*}
+      return
+  fi
+  EXPECT_NE "${lval}" "${rval}" ||
+    die "${@}"
+}
+
 [ "USAGE: skip_administrative_mounts [data] < /proc/mounts
 
 Filters out all administrative (eg: sysfs) mounts uninteresting to the test" ]
@@ -645,7 +799,7 @@
 inRecovery && die "device in recovery mode"
 if ! inAdb; then
   echo "${ORANGE}[  WARNING ]${NORMAL} device not in adb mode" >&2
-  adb_wait 2m
+  adb_wait ${ADB_WAIT}
 fi
 inAdb || die "specified device not in adb mode"
 isDebuggable || die "device not a debug build"
@@ -697,6 +851,8 @@
     esac
   done
 
+# If reboot too soon after fresh flash, could trip device update failure logic
+wait_for_screen
 # Can we test remount -R command?
 overlayfs_supported=true
 if [ "orange" = "`get_property ro.boot.verifiedbootstate`" -a \
@@ -705,19 +861,20 @@
     ${overlayfs_supported} || return 0
     inFastboot &&
       fastboot reboot &&
-      adb_wait 2m
+      adb_wait ${ADB_WAIT}
     inAdb &&
       adb_root &&
       adb enable-verity >/dev/null 2>/dev/null &&
       adb_reboot &&
-      adb_wait 2m
+      adb_wait ${ADB_WAIT}
   }
 
   echo "${GREEN}[ RUN      ]${NORMAL} Testing adb shell su root remount -R command" >&2
 
+  avc_check
   adb_su remount -R system </dev/null || true
   sleep 2
-  adb_wait 2m ||
+  adb_wait ${ADB_WAIT} ||
     die "waiting for device after remount -R `usb_status`"
   if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \
        "2" = "`get_property partition.system.verified`" ]; then
@@ -775,7 +932,7 @@
 if ${reboot}; then
   echo "${ORANGE}[  WARNING ]${NORMAL} rebooting before test" >&2
   adb_reboot &&
-    adb_wait 2m ||
+    adb_wait ${ADB_WAIT} ||
     die "lost device after reboot after wipe `usb_status`"
   adb_root ||
     die "lost device after elevation to root after wipe `usb_status`"
@@ -840,7 +997,7 @@
   echo "${GREEN}[     INFO ]${NORMAL} rebooting as requested" >&2
   L=`adb_logcat -b all -v nsec -t ${T} 2>&1`
   adb_reboot &&
-    adb_wait 2m ||
+    adb_wait ${ADB_WAIT} ||
     die "lost device after reboot requested `usb_status`"
   adb_root ||
     die "lost device after elevation to root `usb_status`"
@@ -881,6 +1038,11 @@
 
 echo "${GREEN}[ RUN      ]${NORMAL} remount" >&2
 
+# Feed log with selinux denials as baseline before overlays
+adb_unroot
+adb_sh find /system /vendor </dev/null >/dev/null 2>/dev/null
+adb_root
+
 D=`adb remount 2>&1`
 ret=${?}
 echo "${D}"
@@ -981,6 +1143,26 @@
 B="`adb_cat /vendor/hello`" ||
   die "vendor hello"
 check_eq "${A}" "${B}" /vendor before reboot
+SYSTEM_DEVT=`adb_sh stat --format=%D /system/hello </dev/null`
+VENDOR_DEVT=`adb_sh stat --format=%D /vendor/hello </dev/null`
+SYSTEM_INO=`adb_sh stat --format=%i /system/hello </dev/null`
+VENDOR_INO=`adb_sh stat --format=%i /vendor/hello </dev/null`
+BASE_SYSTEM_DEVT=`adb_sh stat --format=%D /system/bin/stat </dev/null`
+BASE_VENDOR_DEVT=`adb_sh stat --format=%D /vendor/bin/stat </dev/null`
+check_eq "${SYSTEM_DEVT%[0-9a-fA-F][0-9a-fA-F]}" "${VENDOR_DEVT%[0-9a-fA-F][0-9a-fA-F]}" vendor and system devt
+check_ne "${SYSTEM_INO}" "${VENDOR_INO}" vendor and system inode
+if ${overlayfs_needed}; then
+  check_ne "${SYSTEM_DEVT}" "${BASE_SYSTEM_DEVT}" system devt
+  check_ne "${VENDOR_DEVT}" "${BASE_VENDOR_DEVT}" vendor devt
+else
+  check_eq "${SYSTEM_DEVT}" "${BASE_SYSTEM_DEVT}" system devt
+  check_eq "${VENDOR_DEVT}" "${BASE_VENDOR_DEVT}" vendor devt
+fi
+check_ne "${BASE_SYSTEM_DEVT}" "${BASE_VENDOR_DEVT}" --warning system/vendor devt
+[ -n "${SYSTEM_DEVT%[0-9a-fA-F][0-9a-fA-F]}" ] ||
+  die "system devt ${SYSTEM_DEVT} is major 0"
+[ -n "${VENDOR_DEVT%[0-9a-fA-F][0-9a-fA-F]}" ] ||
+  die "vendor devt ${SYSTEM_DEVT} is major 0"
 
 # Download libc.so, append some gargage, push back, and check if the file
 # is updated.
@@ -1004,12 +1186,12 @@
 fixup_from_recovery() {
   inRecovery || return 1
   echo "${ORANGE}[    ERROR ]${NORMAL} Device in recovery" >&2
-  adb reboot
-  adb_wait 2m
+  adb reboot </dev/null
+  adb_wait ${ADB_WAIT}
 }
 
 adb_reboot &&
-  adb_wait 2m ||
+  adb_wait ${ADB_WAIT} ||
   fixup_from_recovery ||
   die "reboot after override content added failed `usb_status`"
 
@@ -1033,6 +1215,9 @@
   B="`adb_cat /vendor/hello 2>&1`"
   check_eq "cat: /vendor/hello: Permission denied" "${B}" vendor after reboot w/o root
   echo "${GREEN}[       OK ]${NORMAL} /vendor content correct MAC after reboot" >&2
+  # Feed unprivileged log with selinux denials as a result of overlays
+  wait_for_screen
+  adb_sh find /system /vendor </dev/null >/dev/null 2>/dev/null
 fi
 B="`adb_cat /system/hello`"
 check_eq "${A}" "${B}" /system after reboot
@@ -1044,6 +1229,17 @@
 check_eq "${A}" "${B}" vendor after reboot
 echo "${GREEN}[       OK ]${NORMAL} /vendor content remains after reboot" >&2
 
+check_eq "${SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/hello </dev/null`" system devt after reboot
+check_eq "${VENDOR_DEVT}" "`adb_sh stat --format=%D /vendor/hello </dev/null`" vendor devt after reboot
+check_eq "${SYSTEM_INO}" "`adb_sh stat --format=%i /system/hello </dev/null`" system inode after reboot
+check_eq "${VENDOR_INO}" "`adb_sh stat --format=%i /vendor/hello </dev/null`" vendor inode after reboot
+check_eq "${BASE_SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/bin/stat </dev/null`" base system devt after reboot
+check_eq "${BASE_VENDOR_DEVT}" "`adb_sh stat --format=%D /vendor/bin/stat </dev/null`" base system devt after reboot
+check_eq "${BASE_SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/xbin/su </dev/null`" devt for su after reboot
+
+# Feed log with selinux denials as a result of overlays
+adb_sh find /system /vendor </dev/null >/dev/null 2>/dev/null
+
 # Check if the updated libc.so is persistent after reboot.
 adb_root &&
   adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice >/dev/null ||
@@ -1073,10 +1269,17 @@
   echo "${ORANGE}[  WARNING ]${NORMAL} wrong vendor image, skipping"
 elif [ -z "${ANDROID_HOST_OUT}" ]; then
   echo "${ORANGE}[  WARNING ]${NORMAL} please run lunch, skipping"
+elif ! (
+          adb_cat /vendor/build.prop |
+          cmp -s ${ANDROID_PRODUCT_OUT}/vendor/build.prop
+       ) >/dev/null 2>/dev/null; then
+  echo "${ORANGE}[  WARNING ]${NORMAL} vendor image signature mismatch, skipping"
 else
-  adb reboot fastboot ||
+  wait_for_screen
+  avc_check
+  adb reboot fastboot </dev/null ||
     die "fastbootd not supported (wrong adb in path?)"
-  any_wait 2m &&
+  any_wait ${ADB_WAIT} &&
     inFastboot ||
     die "reboot into fastboot to flash vendor `usb_status` (bad bootloader?)"
   fastboot flash vendor ||
@@ -1117,7 +1320,7 @@
   fastboot reboot ||
     die "can not reboot out of fastboot"
   echo "${ORANGE}[  WARNING ]${NORMAL} adb after fastboot"
-  adb_wait 2m ||
+  adb_wait ${ADB_WAIT} ||
     fixup_from_recovery ||
     die "did not reboot after flash `usb_status`"
   if ${overlayfs_needed}; then
@@ -1150,8 +1353,15 @@
     check_eq "cat: /vendor/hello: No such file or directory" "${B}" \
              --warning vendor content after flash vendor
   fi
+
+  check_eq "${SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/hello </dev/null`" system devt after reboot
+  check_eq "${SYSTEM_INO}" "`adb_sh stat --format=%i /system/hello </dev/null`" system inode after reboot
+  check_eq "${BASE_SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/bin/stat </dev/null`" base system devt after reboot
+  check_eq "${BASE_SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/xbin/su </dev/null`" devt for su after reboot
+
 fi
 
+wait_for_screen
 echo "${GREEN}[ RUN      ]${NORMAL} remove test content (cleanup)" >&2
 
 T=`adb_date`
@@ -1163,7 +1373,7 @@
   echo "${ORANGE}[  WARNING ]${NORMAL} adb remount requires a reboot after partial flash (legacy avb)"
   L=`adb_logcat -b all -v nsec -t ${T} 2>&1`
   adb_reboot &&
-    adb_wait 2m &&
+    adb_wait ${ADB_WAIT} &&
     adb_root ||
     die "failed to reboot"
   T=`adb_date`
@@ -1185,14 +1395,15 @@
 
   echo "${GREEN}[ RUN      ]${NORMAL} test fastboot flash to ${scratch_partition} recovery" >&2
 
-  adb reboot fastboot ||
+  avc_check
+  adb reboot fastboot </dev/null ||
     die "Reboot into fastbootd"
   img=${TMPDIR}/adb-remount-test-${$}.img
   cleanup() {
     rm ${img}
   }
   dd if=/dev/zero of=${img} bs=4096 count=16 2>/dev/null &&
-    fastboot_wait 2m ||
+    fastboot_wait ${FASTBOOT_WAIT} ||
     die "reboot into fastboot `usb_status`"
   fastboot flash --force ${scratch_partition} ${img}
   err=${?}
@@ -1204,7 +1415,7 @@
     die "can not reboot out of fastboot"
   [ 0 -eq ${err} ] ||
     die "fastboot flash ${scratch_partition}"
-  adb_wait 2m &&
+  adb_wait ${ADB_WAIT} &&
     adb_root ||
     die "did not reboot after flash"
   T=`adb_date`
@@ -1214,7 +1425,7 @@
   then
     echo "${ORANGE}[  WARNING ]${NORMAL} adb disable-verity requires a reboot after partial flash"
     adb_reboot &&
-      adb_wait 2m &&
+      adb_wait ${ADB_WAIT} &&
       adb_root ||
       die "failed to reboot"
     T=`adb_date`
@@ -1252,12 +1463,12 @@
     fastboot --set-active=${ACTIVE_SLOT}
   fi
   fastboot reboot
-  adb_wait 2m
+  adb_wait ${ADB_WAIT}
 }
 
 # Prerequisite is a prepped device from above.
 adb_reboot &&
-  adb_wait 2m ||
+  adb_wait ${ADB_WAIT} ||
   fixup_from_fastboot ||
   die "lost device after reboot to ro state `usb_status`"
 adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null &&
@@ -1270,7 +1481,7 @@
 
 # Prerequisite is a prepped device from above.
 adb_reboot &&
-  adb_wait 2m ||
+  adb_wait ${ADB_WAIT} ||
   fixup_from_fastboot ||
   die "lost device after reboot to ro state `usb_status`"
 adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null &&
@@ -1291,7 +1502,7 @@
     die "/${d}/overlay wipe"
 done
 adb_reboot &&
-  adb_wait 2m ||
+  adb_wait ${ADB_WAIT} ||
   fixup_from_fastboot ||
   die "lost device after reboot after wipe `usb_status`"
 adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null &&
@@ -1309,9 +1520,10 @@
 
 if [ ${err} = 0 ] && ${overlayfs_supported}; then
   echo "${GREEN}[ RUN      ]${NORMAL} test 'adb remount -R'" >&2
+  avc_check
   adb_root &&
     adb remount -R &&
-    adb_wait 2m ||
+    adb_wait ${ADB_WAIT} ||
     die "adb remount -R"
   if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \
        "2" = "`get_property partition.system.verified`" ]; then
diff --git a/init/mount_namespace.cpp b/init/mount_namespace.cpp
index 5305dc7..12144c1 100644
--- a/init/mount_namespace.cpp
+++ b/init/mount_namespace.cpp
@@ -79,6 +79,38 @@
     return updatable;
 }
 
+static bool ActivateFlattenedApexesIfPossible() {
+    if (IsRecoveryMode() || IsApexUpdatable()) {
+        return true;
+    }
+
+    constexpr const char kSystemApex[] = "/system/apex";
+    constexpr const char kApexTop[] = "/apex";
+    if (mount(kSystemApex, kApexTop, nullptr, MS_BIND, nullptr) != 0) {
+        PLOG(ERROR) << "Could not bind mount " << kSystemApex << " to " << kApexTop;
+        return false;
+    }
+
+    // Special casing for the runtime APEX
+    constexpr const char kRuntimeApexMountPath[] = "/system/apex/com.android.runtime";
+    static const std::vector<std::string> kRuntimeApexDirNames = {"com.android.runtime.release",
+                                                                  "com.android.runtime.debug"};
+    bool success = false;
+    for (const auto& name : kRuntimeApexDirNames) {
+        std::string path = std::string(kSystemApex) + "/" + name;
+        if (access(path.c_str(), F_OK) == 0) {
+            if (mount(path.c_str(), kRuntimeApexMountPath, nullptr, MS_BIND, nullptr) == 0) {
+                success = true;
+                break;
+            }
+        }
+    }
+    if (!success) {
+        PLOG(ERROR) << "Failed to bind mount the runtime APEX to " << kRuntimeApexMountPath;
+    }
+    return success;
+}
+
 static android::base::unique_fd bootstrap_ns_fd;
 static android::base::unique_fd default_ns_fd;
 
@@ -129,6 +161,8 @@
         default_ns_id = GetMountNamespaceId();
     }
 
+    success &= ActivateFlattenedApexesIfPossible();
+
     LOG(INFO) << "SetupMountNamespaces done";
     return success;
 }
diff --git a/init/service.cpp b/init/service.cpp
index 6887d7b..3e865a7 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -46,6 +46,7 @@
 #include "util.h"
 
 #if defined(__ANDROID__)
+#include <ApexProperties.sysprop.h>
 #include <android/api-level.h>
 #include <sys/system_properties.h>
 
@@ -372,10 +373,17 @@
         return;
     }
 
+#if defined(__ANDROID__)
+    static bool is_apex_updatable = android::sysprop::ApexProperties::updatable().value_or(false);
+#else
+    static bool is_apex_updatable = false;
+#endif
+    const bool is_process_updatable = !pre_apexd_ && is_apex_updatable;
+
     // If we crash > 4 times in 4 minutes or before boot_completed,
     // reboot into bootloader or set crashing property
     boot_clock::time_point now = boot_clock::now();
-    if (((flags_ & SVC_CRITICAL) || !pre_apexd_) && !(flags_ & SVC_RESTART)) {
+    if (((flags_ & SVC_CRITICAL) || is_process_updatable) && !(flags_ & SVC_RESTART)) {
         bool boot_completed = android::base::GetBoolProperty("sys.boot_completed", false);
         if (now < time_crashed_ + 4min || !boot_completed) {
             if (++crash_count_ > 4) {
diff --git a/logcat/logcatd.rc b/logcat/logcatd.rc
index 07040b0..25104eb 100644
--- a/logcat/logcatd.rc
+++ b/logcat/logcatd.rc
@@ -4,10 +4,15 @@
 # Make sure any property changes are only performed with /data mounted, after
 # post-fs-data state because otherwise behavior is undefined. The exceptions
 # are device adjustments for logcatd service properties (persist.* overrides
-# notwithstanding) for logd.logpersistd.size and logd.logpersistd.buffer.
+# notwithstanding) for logd.logpersistd.size logd.logpersistd.rotate_kbytes and
+# logd.logpersistd.buffer.
 
 # persist to non-persistent trampolines to permit device properties can be
 # overridden when /data mounts, or during runtime.
+on property:persist.logd.logpersistd.count=*
+    # expect /init to report failure if property empty (default)
+    setprop persist.logd.logpersistd.size ${persist.logd.logpersistd.count}
+
 on property:persist.logd.logpersistd.size=256
     setprop persist.logd.logpersistd.size ""
     setprop logd.logpersistd.size ""
@@ -16,6 +21,14 @@
     # expect /init to report failure if property empty (default)
     setprop logd.logpersistd.size ${persist.logd.logpersistd.size}
 
+on property:persist.logd.logpersistd.rotate_kbytes=1024
+    setprop persist.logd.logpersistd.rotate_kbytes ""
+    setprop logd.logpersistd.rotate_kbytes ""
+
+on property:persist.logd.logpersistd.rotate_kbytes=*
+   # expect /init to report failure if property empty (default)
+   setprop logd.logpersistd.rotate_kbytes ${persist.logd.logpersistd.rotate_kbytes}
+
 on property:persist.logd.logpersistd.buffer=all
     setprop persist.logd.logpersistd.buffer ""
     setprop logd.logpersistd.buffer ""
@@ -54,7 +67,7 @@
     stop logcatd
 
 # logcatd service
-service logcatd /system/bin/logcatd -L -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256} --id=${ro.build.id}
+service logcatd /system/bin/logcatd -L -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r ${logd.logpersistd.rotate_kbytes:-1024} -n ${logd.logpersistd.size:-256} --id=${ro.build.id}
     class late_start
     disabled
     # logd for write to /data/misc/logd, log group for read from log daemon
diff --git a/logd/README.property b/logd/README.property
index da5f96f..d2a2cbb 100644
--- a/logd/README.property
+++ b/logd/README.property
@@ -17,10 +17,13 @@
 					 Responds to logcatd, clear and stop.
 logd.logpersistd.buffer          persist logpersistd buffers to collect
 logd.logpersistd.size            persist logpersistd size in MB
+logd.logpersistd.rotate_kbytes   	 persist logpersistd outout file size in KB.
 persist.logd.logpersistd   string        Enable logpersist daemon, "logcatd"
                                          turns on logcat -f in logd context.
 persist.logd.logpersistd.buffer    all   logpersistd buffers to collect
 persist.logd.logpersistd.size      256   logpersistd size in MB
+persist.logd.logpersistd.count     256   sets max number of rotated logs to <count>.
+persist.logd.logpersistd.rotate_kbytes   1024  logpersistd output file size in KB
 persist.logd.size          number  ro    Global default size of the buffer for
                                          all log ids at initial startup, at
                                          runtime use: logcat -b all -G <value>