logcatd: trampoline persist.logd.logpersistd to logd.logpersistd

(cherry pick from 2591d483c83a09eb8689e6e7869b4ac0bfe418db)

Best practices so that device can set logd.logpersistd properties.
Values can be overriden with trampolines for persist.logd.logpersistd
values except as designed for empty content to keep out of the way.

This allows us to set logd.logpersistd* for a non-persistent collection
that does not survive a reboot, and to use persist.logd.logpersistd*
for persistent collection that does survive a reboot.

Added logd.logpersistd.enable to gate when logpersist service can be
run allowing the properties to be adjusted safely prior to this state
as is the case for device property.

NB: /init will complain when trying to trampoline an empty property,
    this is acceptable for functionality, but may be considered
    annoying from the logging perspective.

Bug: 28788401
Bug: 28813587
Bug: 28936216
Bug: 29831823
Change-Id: I97317e8eedfae4daa8e3ef39e64e7c5c23d8b573
diff --git a/logcat/logcatd.rc b/logcat/logcatd.rc
index 7d70dd9..ce1a451 100644
--- a/logcat/logcatd.rc
+++ b/logcat/logcatd.rc
@@ -1,21 +1,62 @@
+#
+# init scriptures for logcatd persistent logging.
+#
+# 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.
+
+# persist to non-persistent trampolines to permit device properties can be
+# overridden when /data mounts, or during runtime.
+on property:persist.logd.logpersistd.size=256
+    setprop persist.logd.logpersistd.size ""
+    setprop logd.logpersistd.size ""
+
+on property:persist.logd.logpersistd.size=*
+    # expect /init to report failure if property empty (default)
+    setprop logd.logpersistd.size ${persist.logd.logpersistd.size}
+
+on property:persist.logd.logpersistd.buffer=all
+    setprop persist.logd.logpersistd.buffer ""
+    setprop logd.logpersistd.buffer ""
+
+on property:persist.logd.logpersistd.buffer=*
+    # expect /init to report failure if property empty (default)
+    setprop logd.logpersistd.buffer ${persist.logd.logpersistd.buffer}
+
 on property:persist.logd.logpersistd=logcatd
+    setprop logd.logpersistd logcatd
+
+# enable, prep and start logcatd service
+on load_persist_props_action
+    setprop logd.logpersistd.enable true
+
+on property:logd.logpersistd.enable=true && property:logd.logpersistd=logcatd
     # all exec/services are called with umask(077), so no gain beyond 0700
     mkdir /data/misc/logd 0700 logd log
     # logd for write to /data/misc/logd, log group for read from pstore (-L)
-    exec - logd log -- /system/bin/logcat -L -b ${persist.logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${persist.logd.logpersistd.size:-256}
+    exec - logd log -- /system/bin/logcat -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}
     start logcatd
 
-on property:persist.logd.logpersistd=clear
+# stop logcatd service and clear data
+on property:logd.logpersistd.enable=true && property:logd.logpersistd=clear
+    setprop persist.logd.logpersistd ""
     stop logcatd
     # logd for clear of only our files in /data/misc/logd
-    exec - logd log -- /system/bin/logcat -c -f /data/misc/logd/logcat -n ${persist.logd.logpersistd.size:-256}
-    setprop persist.logd.logpersistd ""
+    exec - logd log -- /system/bin/logcat -c -f /data/misc/logd/logcat -n ${logd.logpersistd.size:-256}
+    setprop logd.logpersistd ""
 
-on property:persist.logd.logpersistd=stop
+# stop logcatd service
+on property:logd.logpersistd=stop
+    setprop persist.logd.logpersistd ""
     stop logcatd
-    setprop persist.logd.logpersistd ""
+    setprop logd.logpersistd ""
 
-service logcatd /system/bin/logcat -b ${persist.logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${persist.logd.logpersistd.size:-256}
+on property:logd.logpersistd.enable=false
+    stop logcatd
+
+# logcatd service
+service logcatd /system/bin/logcat -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256}
     class late_start
     disabled
     # logd for write to /data/misc/logd, log group for read from log daemon
diff --git a/logcat/logpersist b/logcat/logpersist
index 0b8cb21..a0e27ce 100755
--- a/logcat/logpersist
+++ b/logcat/logpersist
@@ -8,8 +8,16 @@
    ;;
 esac
 
-data=/data/misc/logd
 property=persist.logd.logpersistd
+
+case `getprop ${property#persist.}.enable` in
+true) ;;
+*) echo "${progname} - Disabled"
+   exit 1
+   ;;
+esac
+
+data=/data/misc/logd
 service=logcatd
 size_default=256
 buffer_default=all
@@ -69,11 +77,11 @@
   su logd xargs cat
   ;;
 *.start)
-  current_buffer="`getprop ${property}.buffer`"
-  current_size="`getprop ${property}.size`"
-  if [ "${service}" = "`getprop ${property}`" ]; then
+  current_buffer="`getprop ${property#persist.}.buffer`"
+  current_size="`getprop ${property#persist.}.size`"
+  if [ "${service}" = "`getprop ${property#persist.}`" ]; then
     if [ "true" = "${clear}" ]; then
-      setprop ${property} "clear"
+      setprop ${property#persist.} "clear"
     elif [ "${buffer}|${size}" != "${current_buffer}|${current_size}" ]; then
       echo   "ERROR: Changing existing collection parameters from" >&2
       if [ "${buffer}" != "${current_buffer}" ]; then
@@ -96,22 +104,30 @@
       exit 1
     fi
   elif [ "true" = "${clear}" ]; then
-    setprop ${property} "clear"
+    setprop ${property#persist.} "clear"
   fi
   if [ -n "${buffer}${current_buffer}" ]; then
     setprop ${property}.buffer "${buffer}"
+    if [ -z "${buffer}" ]; then
+      # deal with trampoline for empty properties
+      setprop ${property#persist.}.buffer ""
+    fi
   fi
   if [ -n "${size}${current_size}" ]; then
     setprop ${property}.size "${size}"
+    if [ -z "${size}" ]; then
+      # deal with trampoline for empty properties
+      setprop ${property#persist.}.size ""
+    fi
   fi
-  while [ "clear" = "`getprop ${property}`" ]; do
+  while [ "clear" = "`getprop ${property#persist.}`" ]; do
     continue
   done
   # ${service}.rc does the heavy lifting with the following trigger
   setprop ${property} ${service}
-  getprop ${property}
   # 20ms done, to permit process feedback check
   sleep 1
+  getprop ${property#persist.}
   # also generate an error return code if not found running, bonus
   ps -t | grep "${data##*/}.*${service%d}"
   ;;
@@ -124,13 +140,17 @@
   else
     setprop ${property} "stop"
   fi
-  if [ -n "`getprop ${property}.buffer`" ]; then
+  if [ -n "`getprop ${property#persist.}.buffer`" ]; then
     setprop ${property}.buffer ""
+    # deal with trampoline for empty properties
+    setprop ${property#persist.}.buffer ""
   fi
-  if [ -n "`getprop ${property}.size`" ]; then
+  if [ -n "`getprop ${property#persist.}.size`" ]; then
     setprop ${property}.size ""
+    # deal with trampoline for empty properties
+    setprop ${property#persist.}.size ""
   fi
-  while [ "clear" = "`getprop ${property}`" ]; do
+  while [ "clear" = "`getprop ${property#persist.}`" ]; do
     continue
   done
   ;;
diff --git a/logd/README.property b/logd/README.property
index 22f86b9..b2708e4 100644
--- a/logd/README.property
+++ b/logd/README.property
@@ -1,4 +1,4 @@
-The properties that logd responds to are:
+The properties that logd and friends react to are:
 
 name                       type default  description
 ro.logd.auditd             bool   true   Enable selinux audit daemon
@@ -10,8 +10,16 @@
 ro.logd.statistics         bool+ svelte+ Enable logcat -S statistics.
 ro.build.type              string        if user, logd.statistics &
                                          ro.logd.kernel default false.
+logd.logpersistd.enable    bool   auto   Safe to start logpersist daemon service
+logd.logpersistd          string persist Enable logpersist daemon, "logcatd"
+                                         turns on logcat -f in logd context.
+					 Responds to logcatd, clear and stop.
+logd.logpersistd.buffer          persist logpersistd buffers to collect
+logd.logpersistd.size            persist logpersistd size in MB
 persist.logd.logpersistd   string        Enable logpersist daemon, "logcatd"
-                                         turns on logcat -f in logd context
+                                         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.size          number  ro    Global default size of the buffer for
                                          all log ids at initial startup, at
                                          runtime use: logcat -b all -G <value>
@@ -45,6 +53,7 @@
 persist.log.tag.<tag>      string build  default for log.tag.<tag>
 
 NB:
+- auto - managed by /init
 - bool+ - "true", "false" and comma separated list of "eng" (forced false if
   ro.build.type is "user") or "svelte" (forced false if ro.config.low_ram is
   true).