Merge "Expose libtombstone_proto srcs."
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 51afcc2..68a43cf 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -153,14 +153,14 @@
   }
 
   struct timeval tv = {
-    .tv_sec = 1,
-    .tv_usec = 0,
+      .tv_sec = 1 * android::base::TimeoutMultiplier(),
+      .tv_usec = 0,
   };
   if (setsockopt(amfd.get(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) {
     PLOG(ERROR) << "failed to set send timeout on activity manager socket";
     return false;
   }
-  tv.tv_sec = 3;  // 3 seconds on handshake read
+  tv.tv_sec = 3 * android::base::TimeoutMultiplier();  // 3 seconds on handshake read
   if (setsockopt(amfd.get(), SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
     PLOG(ERROR) << "failed to set receive timeout on activity manager socket";
     return false;
@@ -447,7 +447,7 @@
   //
   // Note: processes with many threads and minidebug-info can take a bit to
   //       unwind, do not make this too small. b/62828735
-  alarm(30);
+  alarm(30 * android::base::TimeoutMultiplier());
 
   // Get the process name (aka cmdline).
   std::string process_name = get_process_name(g_target_thread);
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index b9d6606..65820bd 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -311,7 +311,7 @@
 
   if (mte_supported()) {
     // Test that the default TAGGED_ADDR_CTRL value is set.
-    ASSERT_MATCH(result, R"(tagged_addr_ctrl: 000000000007fff5)");
+    ASSERT_MATCH(result, R"(tagged_addr_ctrl: 000000000007fff3)");
   }
 }
 
diff --git a/debuggerd/tombstoned/intercept_manager.cpp b/debuggerd/tombstoned/intercept_manager.cpp
index 437639e..4d4646a 100644
--- a/debuggerd/tombstoned/intercept_manager.cpp
+++ b/debuggerd/tombstoned/intercept_manager.cpp
@@ -26,6 +26,7 @@
 
 #include <android-base/cmsg.h>
 #include <android-base/logging.h>
+#include <android-base/properties.h>
 #include <android-base/unique_fd.h>
 
 #include "protocol.h"
@@ -162,7 +163,7 @@
     event_assign(intercept->intercept_event, intercept_manager->base, sockfd, EV_READ | EV_TIMEOUT,
                  intercept_close_cb, arg);
 
-    struct timeval timeout = { .tv_sec = 10, .tv_usec = 0 };
+    struct timeval timeout = {.tv_sec = 10 * android::base::TimeoutMultiplier(), .tv_usec = 0};
     event_add(intercept->intercept_event, &timeout);
   }
 
@@ -178,7 +179,7 @@
   intercept->intercept_manager = static_cast<InterceptManager*>(arg);
   intercept->sockfd.reset(sockfd);
 
-  struct timeval timeout = { 1, 0 };
+  struct timeval timeout = {1 * android::base::TimeoutMultiplier(), 0};
   event_base* base = evconnlistener_get_base(listener);
   event* intercept_event =
     event_new(base, sockfd, EV_TIMEOUT | EV_READ, intercept_request_cb, intercept);
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index f057260..3e0c47c 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -320,7 +320,7 @@
   }
 
   // TODO: Make this configurable by the interceptor?
-  struct timeval timeout = {10, 0};
+  struct timeval timeout = {10 * android::base::TimeoutMultiplier(), 0};
 
   event_base* base = event_get_base(crash->crash_event);
 
@@ -340,7 +340,7 @@
 
   // TODO: Make sure that only java crashes come in on the java socket
   // and only native crashes on the native socket.
-  struct timeval timeout = { 1, 0 };
+  struct timeval timeout = {1 * android::base::TimeoutMultiplier(), 0};
   event* crash_event = event_new(base, sockfd, EV_TIMEOUT | EV_READ, crash_request_cb, crash);
   crash->crash_socket_fd.reset(sockfd);
   crash->crash_event = crash_event;
diff --git a/fs_mgr/libsnapshot/snapuserd.cpp b/fs_mgr/libsnapshot/snapuserd.cpp
index ceba8ab..82db0d3 100644
--- a/fs_mgr/libsnapshot/snapuserd.cpp
+++ b/fs_mgr/libsnapshot/snapuserd.cpp
@@ -391,8 +391,6 @@
     }
 
     if (*copy_op) {
-        SNAP_LOG(ERROR) << "Invalid batch merge of copy ops: merged_ops_cur_iter: "
-                        << merged_ops_cur_iter;
         CHECK(merged_ops_cur_iter == 1);
     }
     return merged_ops_cur_iter;
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index 2433833..0df8cf0 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -213,6 +213,13 @@
     return ${ret}
 }
 
+[ "USAGE: adb_test <expression>
+
+Returns: exit status of the test expression" ]
+adb_test() {
+  adb_sh test "${@}" </dev/null
+}
+
 [ "USAGE: adb_reboot
 
 Returns: true if the reboot command succeeded" ]
@@ -956,7 +963,7 @@
     if inAdb; then
       reboot=false
       for d in ${OVERLAYFS_BACKING}; do
-        if adb_su ls -d /${d}/overlay </dev/null >/dev/null 2>/dev/null; then
+        if adb_test -d /${d}/overlay; then
           adb_su rm -rf /${d}/overlay </dev/null
           reboot=true
         fi
@@ -1010,7 +1017,10 @@
 echo "${GREEN}[ RUN      ]${NORMAL} Testing kernel support for overlayfs" >&2
 
 adb_wait || die "wait for device failed"
-adb_sh ls -d /sys/module/overlay </dev/null >/dev/null 2>/dev/null ||
+adb_root ||
+  die "initial setup"
+
+adb_test -d /sys/module/overlay ||
   adb_sh grep "nodev${TAB}overlay" /proc/filesystems </dev/null >/dev/null 2>/dev/null &&
   echo "${GREEN}[       OK ]${NORMAL} overlay module present" >&2 ||
   (
@@ -1019,7 +1029,7 @@
   ) ||
   overlayfs_supported=false
 if ${overlayfs_supported}; then
-  adb_su ls /sys/module/overlay/parameters/override_creds </dev/null >/dev/null 2>/dev/null &&
+  adb_test -f /sys/module/overlay/parameters/override_creds &&
     echo "${GREEN}[       OK ]${NORMAL} overlay module supports override_creds" >&2 ||
     case `adb_sh uname -r </dev/null` in
       4.[456789].* | 4.[1-9][0-9]* | [56789].*)
@@ -1032,9 +1042,6 @@
     esac
 fi
 
-adb_root ||
-  die "initial setup"
-
 echo "${GREEN}[ RUN      ]${NORMAL} Checking current overlayfs status" >&2
 
 # We can not universally use adb enable-verity to ensure device is
@@ -1044,7 +1051,7 @@
 # having to go through enable-verity transition.
 reboot=false
 for d in ${OVERLAYFS_BACKING}; do
-  if adb_sh ls -d /${d}/overlay </dev/null >/dev/null 2>/dev/null; then
+  if adb_test -d /${d}/overlay; then
     echo "${YELLOW}[  WARNING ]${NORMAL} /${d}/overlay is setup, surgically wiping" >&2
     adb_sh rm -rf /${d}/overlay </dev/null ||
       die "/${d}/overlay wipe"
@@ -1220,7 +1227,7 @@
     die "scratch size"
   echo "${BLUE}[     INFO ]${NORMAL} scratch size ${scratch_size}KB" >&2
   for d in ${OVERLAYFS_BACKING}; do
-    if adb_sh ls -d /${d}/overlay/system/upper </dev/null >/dev/null 2>/dev/null; then
+    if adb_test -d /${d}/overlay/system/upper; then
       echo "${BLUE}[     INFO ]${NORMAL} /${d}/overlay is setup" >&2
     fi
   done
@@ -1656,8 +1663,10 @@
 # This also saves a lot of 'noise' from the command doing a mkfs on backing
 # storage and all the related tuning and adjustment.
 for d in ${OVERLAYFS_BACKING}; do
-  adb_su rm -rf /${d}/overlay </dev/null ||
-    die "/${d}/overlay wipe"
+  if adb_test -d /${d}/overlay; then
+    adb_su rm -rf /${d}/overlay </dev/null ||
+      die "/${d}/overlay wipe"
+  fi
 done
 adb_reboot &&
   adb_wait ${ADB_WAIT} ||
diff --git a/gatekeeperd/Android.bp b/gatekeeperd/Android.bp
index 2d9a820..d1046df 100644
--- a/gatekeeperd/Android.bp
+++ b/gatekeeperd/Android.bp
@@ -41,7 +41,7 @@
         "libhidlbase",
         "android.hardware.gatekeeper@1.0",
         "libgatekeeper_aidl",
-        "android.hardware.security.keymint-unstable-ndk_platform",
+        "android.hardware.security.keymint-V1-ndk_platform",
         "android.security.authorization-ndk_platform",
     ],
 
diff --git a/init/service.cpp b/init/service.cpp
index cfb8284..f6ce094 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -127,7 +127,8 @@
 
 static bool AreRuntimeApexesReady() {
     struct stat buf;
-    return stat("/apex/com.android.runtime/", &buf) == 0;
+    return stat("/apex/com.android.art/", &buf) == 0 &&
+           stat("/apex/com.android.runtime/", &buf) == 0;
 }
 
 unsigned long Service::next_start_order_ = 1;
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index d46aeab..c75e538 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -167,7 +167,6 @@
         "canned_fs_config.cpp",
         "iosched_policy.cpp",
         "load_file.cpp",
-        "memory.cpp",
         "native_handle.cpp",
         "properties.cpp",
         "record_stream.cpp",
diff --git a/libcutils/include/cutils/memory.h b/libcutils/include/cutils/memory.h
index 0fba53c..c6476c1 100644
--- a/libcutils/include/cutils/memory.h
+++ b/libcutils/include/cutils/memory.h
@@ -28,9 +28,6 @@
 size_t strlcpy(char *dst, const char *src, size_t size);
 #endif
 
-// Disables memory mitigations for the entire process, and logs appropriately.
-void process_disable_memory_mitigations();
-
 #ifdef __cplusplus
 } // extern "C"
 #endif
diff --git a/libcutils/memory.cpp b/libcutils/memory.cpp
deleted file mode 100644
index 5a410c2..0000000
--- a/libcutils/memory.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <cutils/memory.h>
-
-#include <log/log.h>
-
-#if !defined(__APPLE__)
-#include <malloc.h>
-#endif
-
-void process_disable_memory_mitigations() {
-    bool success = false;
-#ifdef __BIONIC__
-    success = mallopt(M_BIONIC_DISABLE_MEMORY_MITIGATIONS, 0);
-#endif
-
-    // TODO: if b/158870657 is fixed and scudo is used globally,
-    // we can assert on failure rather than just log.
-    if (success) {
-        ALOGI("Disabled memory mitigations for process.");
-    } else {
-        ALOGE("Could not disable memory mitigations for process.");
-    }
-}
diff --git a/llkd/libllkd.cpp b/llkd/libllkd.cpp
index a24d900..9f3e218 100644
--- a/llkd/libllkd.cpp
+++ b/llkd/libllkd.cpp
@@ -962,7 +962,7 @@
     //
     // This alarm is effectively the live lock detection of llkd, as
     // we understandably can not monitor ourselves otherwise.
-    ::alarm(duration_cast<seconds>(llkTimeoutMs * 2).count());
+    ::alarm(duration_cast<seconds>(llkTimeoutMs * 2 * android::base::TimeoutMultiplier()).count());
 
     // kernel jiffy precision fastest acquisition
     static timespec last;
diff --git a/shell_and_utilities/README.md b/shell_and_utilities/README.md
index d169d29..f339553 100644
--- a/shell_and_utilities/README.md
+++ b/shell_and_utilities/README.md
@@ -26,7 +26,8 @@
 because the toolbox implementations did have bugs fixed and options added
 over the years. Gingerbread's rm, for example, supported `-r`/`-R` but not
 `-f`. But this gives you an idea of what was available in any given release,
-and how usable it was likely to be.
+and how usable it was likely to be. (**Bold** marks where we switched to toybox
+or first added something to toybox.)
 
 Also note that in any given release `toybox` probably contains more
 commands than there are symlinks for in `/system/bin`. You can get the
@@ -118,18 +119,18 @@
 toolbox: getevent iftop ioctl log nandread newfs\_msdos ps prlimit
 sendevent start stop top
 
-toybox (0.7.0-ish): acpi base64 basename blockdev bzcat cal cat chcon chgrp chmod
-chown chroot cksum clear comm cmp cp cpio cut date df dirname dmesg
-dos2unix du echo env expand expr fallocate false find flock free
+toybox (0.7.0-ish): acpi **base64** basename blockdev bzcat cal cat chcon chgrp chmod
+chown chroot cksum clear comm cmp cp cpio cut date **df** dirname dmesg
+dos2unix **du** echo env expand expr fallocate false find **flock** free
 getenforce getprop groups head hostname hwclock id ifconfig inotifyd
-insmod ionice iorenice kill killall load\_policy ln logname losetup ls
-lsmod lsof lsusb md5sum mkdir mknod mkswap mktemp modinfo more mount
+insmod **ionice** **iorenice** kill **killall** load\_policy ln logname losetup **ls**
+lsmod **lsof** lsusb md5sum mkdir mknod mkswap mktemp modinfo more *mount*
 mountpoint mv netstat nice nl nohup od paste patch pgrep pidof pkill
-pmap printenv printf pwd readlink realpath renice restorecon rm rmdir
+pmap printenv printf pwd readlink realpath **renice** restorecon rm rmdir
 rmmod route runcon sed seq setenforce setprop setsid sha1sum sleep sort
 split stat strings swapoff swapon sync sysctl tac tail tar taskset tee
-time timeout touch tr true truncate tty ulimit umount uname uniq unix2dos
-uptime usleep vmstat wc which whoami xargs xxd yes
+time timeout touch tr true truncate **tty** **ulimit** umount uname uniq unix2dos
+**uptime** usleep vmstat wc which whoami xargs **xxd** yes
 
 
 ## Android 8.0 (Oreo)
@@ -141,19 +142,19 @@
 toolbox: getevent newfs\_msdos
 
 toybox (0.7.3-ish): acpi base64 basename blockdev cal cat chcon chgrp chmod chown
-chroot chrt cksum clear cmp comm cp cpio cut date df diff dirname dmesg
-dos2unix du echo env expand expr fallocate false file find flock free
-getenforce getprop groups gunzip gzip head hostname hwclock id ifconfig
-inotifyd insmod ionice iorenice kill killall ln load\_policy log logname
-losetup ls lsmod lsof lspci lsusb md5sum microcom mkdir mkfifo mknod
-mkswap mktemp modinfo modprobe more mount mountpoint mv netstat nice
-nl nohup od paste patch pgrep pidof pkill pmap printenv printf ps pwd
-readlink realpath renice restorecon rm rmdir rmmod runcon sed sendevent
-seq setenforce setprop setsid sha1sum sha224sum sha256sum sha384sum
-sha512sum sleep sort split start stat stop strings swapoff swapon sync
-sysctl tac tail tar taskset tee time timeout top touch tr true truncate
-tty ulimit umount uname uniq unix2dos uptime usleep uudecode uuencode
-vmstat wc which whoami xargs xxd yes zcat
+chroot chrt cksum clear cmp comm cp cpio cut date df **diff** dirname dmesg
+dos2unix du echo env expand expr fallocate false **file** find flock free
+getenforce getprop groups **gunzip** **gzip** head hostname hwclock id ifconfig
+inotifyd insmod ionice iorenice kill killall ln load\_policy **log** logname
+losetup ls lsmod lsof **lspci** lsusb md5sum **microcom** mkdir **mkfifo** mknod
+mkswap mktemp modinfo **modprobe** more mount mountpoint mv netstat nice
+nl nohup od paste patch pgrep pidof pkill pmap printenv printf **ps** pwd
+readlink realpath renice restorecon rm rmdir rmmod runcon sed **sendevent**
+seq setenforce setprop setsid sha1sum **sha224sum** **sha256sum** **sha384sum**
+**sha512sum** sleep sort split start stat stop strings swapoff swapon sync
+sysctl tac tail tar taskset tee time timeout **top** touch tr true truncate
+tty ulimit umount uname uniq unix2dos uptime usleep **uudecode** **uuencode**
+vmstat wc which whoami xargs xxd yes **zcat**
 
 
 ## Android 9.0 (Pie)
@@ -168,7 +169,7 @@
 
 toybox (0.7.6-ish): acpi base64 basename blockdev cal cat chcon chgrp chmod chown
 chroot chrt cksum clear cmp comm cp cpio cut date df diff dirname dmesg
-dos2unix du echo env expand expr fallocate false file find flock fmt free
+dos2unix du echo env expand expr fallocate false file find flock **fmt** free
 getenforce groups gunzip gzip head hostname hwclock id ifconfig inotifyd
 insmod ionice iorenice kill killall ln load\_policy log logname losetup ls
 lsmod lsof lspci lsusb md5sum microcom mkdir mkfifo mknod mkswap mktemp
@@ -176,7 +177,7 @@
 patch pgrep pidof pkill pmap printenv printf ps pwd readlink realpath
 renice restorecon rm rmdir rmmod runcon sed sendevent seq setenforce
 setprop setsid sha1sum sha224sum sha256sum sha384sum sha512sum sleep
-sort split start stat stop strings stty swapoff swapon sync sysctl tac
+sort split start stat stop strings **stty** swapoff swapon sync sysctl tac
 tail tar taskset tee time timeout top touch tr true truncate tty ulimit
 umount uname uniq unix2dos uptime usleep uudecode uuencode vmstat wc
 which whoami xargs xxd yes zcat
@@ -192,24 +193,24 @@
 
 toolbox: getevent getprop
 
-toybox (0.8.0-ish): acpi base64 basename bc blkid blockdev cal cat chattr chcon chgrp
+toybox (0.8.0-ish): acpi base64 basename **bc** **blkid** blockdev cal cat **chattr** chcon chgrp
 chmod chown chroot chrt cksum clear cmp comm cp cpio cut date dd df
-diff dirname dmesg dos2unix du echo egrep env expand expr fallocate
-false fgrep file find flock fmt free freeramdisk fsfreeze getconf
-getenforce getfattr grep groups gunzip gzip head help hostname hwclock
-i2cdetect i2cdump i2cget i2cset iconv id ifconfig inotifyd insmod
-install ionice iorenice iotop kill killall ln load\_policy log logname
-losetup ls lsattr lsmod lsof lspci lsusb makedevs md5sum microcom
+diff dirname dmesg dos2unix du echo **egrep** env expand expr fallocate
+false **fgrep** file find flock fmt free **freeramdisk** **fsfreeze** **getconf**
+getenforce **getfattr** grep groups gunzip gzip head **help** hostname hwclock
+**i2cdetect** **i2cdump** **i2cget** **i2cset** **iconv** id ifconfig inotifyd insmod
+**install** ionice iorenice **iotop** kill killall ln load\_policy log logname
+losetup ls **lsattr** lsmod lsof lspci lsusb **makedevs** md5sum microcom
 mkdir mkfifo mknod mkswap mktemp modinfo modprobe more mount mountpoint
-mv nbd-client nc netcat netstat nice nl nohup nproc nsenter od partprobe
-paste patch pgrep pidof ping ping6 pivot\_root pkill pmap printenv
-printf prlimit ps pwd pwdx readlink realpath renice restorecon rev
-rfkill rm rmdir rmmod runcon sed sendevent seq setenforce setfattr
+mv **nbd-client** **nc** **netcat** netstat nice nl nohup **nproc** **nsenter** od **partprobe**
+paste patch pgrep pidof **ping** **ping6** **pivot\_root** pkill pmap printenv
+printf **prlimit** ps pwd **pwdx** readlink realpath renice restorecon **rev**
+**rfkill** rm rmdir rmmod runcon sed sendevent seq setenforce **setfattr**
 setprop setsid sha1sum sha224sum sha256sum sha384sum sha512sum sleep
 sort split start stat stop strings stty swapoff swapon sync sysctl
-tac tail tar taskset tee time timeout top touch tr traceroute traceroute6
-true truncate tty tunctl ulimit umount uname uniq unix2dos unlink
-unshare uptime usleep uudecode uuencode uuidgen vconfig vmstat watch
+tac tail tar taskset tee time timeout top touch tr **traceroute** **traceroute6**
+true truncate tty **tunctl** ulimit umount uname uniq unix2dos **unlink**
+**unshare** uptime usleep uudecode uuencode **uuidgen** **vconfig** vmstat **watch**
 wc which whoami xargs xxd yes zcat
 
 ## Android 11 ("R")
@@ -225,21 +226,53 @@
 toolbox: getevent getprop setprop start stop
 
 toybox (0.8.3-ish): acpi base64 basename blkid blockdev cal cat chattr chcon chgrp chmod
-chown chroot chrt cksum clear cmp comm cp cpio cut date dd devmem
+chown chroot chrt cksum clear cmp comm cp cpio cut date dd **devmem**
 df diff dirname dmesg dos2unix du echo egrep env expand expr fallocate
-false fgrep file find flock fmt free freeramdisk fsfreeze fsync getconf
-getenforce getfattr getopt grep groups gunzip gzip head help hostname
+false fgrep file find flock fmt free freeramdisk fsfreeze **fsync** getconf
+getenforce getfattr **getopt** grep groups gunzip gzip head help hostname
 hwclock i2cdetect i2cdump i2cget i2cset iconv id ifconfig inotifyd
 insmod install ionice iorenice iotop kill killall ln load\_policy log
 logname losetup ls lsattr lsmod lsof lspci lsusb makedevs md5sum microcom
 mkdir mkfifo mknod mkswap mktemp modinfo modprobe more mount mountpoint
 mv nbd-client nc netcat netstat nice nl nohup nproc nsenter od partprobe
 paste patch pgrep pidof ping ping6 pivot\_root pkill pmap printenv
-printf prlimit ps pwd pwdx readelf readlink realpath renice restorecon
+printf prlimit ps pwd pwdx **readelf** readlink realpath renice restorecon
 rev rfkill rm rmdir rmmod runcon sed sendevent seq setenforce setfattr
 setsid sha1sum sha224sum sha256sum sha384sum sha512sum sleep sort
 split stat strings stty swapoff swapon sync sysctl tac tail tar taskset
 tee time timeout top touch tr traceroute traceroute6 true truncate
 tty tunctl ulimit umount uname uniq unix2dos unlink unshare uptime
-usleep uudecode uuencode uuidgen vconfig vi vmstat watch wc which
+usleep uudecode uuencode uuidgen vconfig **vi** vmstat watch wc which
 whoami xargs xxd yes zcat
+
+## Android ("S")
+
+BSD: fsck\_msdos newfs\_msdos
+
+bzip2: bzcat bzip2 bunzip2
+
+gavinhoward/bc: bc
+
+one-true-awk: awk
+
+toolbox: getevent getprop setprop start stop
+
+toybox (0.8.4-ish): **[** acpi base64 basename **blkdiscard** blkid blockdev cal cat chattr chcon
+chgrp chmod chown chroot chrt cksum clear cmp comm cp cpio cut date
+dd devmem df diff dirname dmesg dos2unix du echo egrep env expand
+expr fallocate false fgrep file find flock fmt free freeramdisk fsfreeze
+fsync getconf getenforce getfattr getopt grep groups gunzip gzip head
+help hostname hwclock i2cdetect i2cdump i2cget i2cset iconv id ifconfig
+inotifyd insmod install ionice iorenice iotop kill killall ln load\_policy
+log logname losetup ls lsattr lsmod lsof lspci lsusb makedevs md5sum
+microcom mkdir mkfifo mknod mkswap mktemp modinfo modprobe more mount
+mountpoint mv nbd-client nc netcat netstat nice nl nohup nproc nsenter
+od partprobe paste patch pgrep pidof ping ping6 pivot\_root pkill pmap
+printenv printf prlimit ps pwd pwdx readelf readlink realpath renice
+restorecon rev rfkill rm rmdir rmmod **rtcwake** runcon sed sendevent
+seq setenforce setfattr setsid sha1sum sha224sum sha256sum sha384sum
+sha512sum sleep sort split stat strings stty swapoff swapon sync sysctl
+tac tail tar taskset tee **test** time timeout top touch tr traceroute
+traceroute6 true truncate tty tunctl ulimit umount uname uniq unix2dos
+unlink unshare uptime usleep uudecode uuencode uuidgen vconfig vi
+vmstat watch wc which whoami xargs xxd yes zcat
diff --git a/trusty/apploader/Android.bp b/trusty/apploader/Android.bp
new file mode 100644
index 0000000..7e97cb8
--- /dev/null
+++ b/trusty/apploader/Android.bp
@@ -0,0 +1,36 @@
+//
+// Copyright (C) 2020 The Android Open-Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_binary {
+    name: "trusty_apploader",
+    vendor: true,
+
+    srcs: [
+        "apploader.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libc",
+        "liblog",
+        "libtrusty",
+        "libdmabufheap",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+}
diff --git a/trusty/apploader/apploader.cpp b/trusty/apploader/apploader.cpp
new file mode 100644
index 0000000..5d5d882
--- /dev/null
+++ b/trusty/apploader/apploader.cpp
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "TrustyAppLoader"
+
+#include <BufferAllocator/BufferAllocator.h>
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/sendfile.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <trusty/tipc.h>
+#include <unistd.h>
+#include <algorithm>
+#include <string>
+
+#include "apploader_ipc.h"
+
+using android::base::unique_fd;
+using std::string;
+
+constexpr const char kTrustyDefaultDeviceName[] = "/dev/trusty-ipc-dev0";
+
+static const char* dev_name = kTrustyDefaultDeviceName;
+
+static const char* _sopts = "hs";
+static const struct option _lopts[] = {
+        {"help", no_argument, 0, 'h'},
+        {"dev", required_argument, 0, 'D'},
+        {0, 0, 0, 0},
+};
+
+static const char* usage =
+        "Usage: %s [options] package-file\n"
+        "\n"
+        "options:\n"
+        "  -h, --help            prints this message and exit\n"
+        "  -D, --dev name        Trusty device name\n"
+        "\n";
+
+static void print_usage_and_exit(const char* prog, int code) {
+    fprintf(stderr, usage, prog);
+    exit(code);
+}
+
+static void parse_options(int argc, char** argv) {
+    int c;
+    int oidx = 0;
+
+    while (1) {
+        c = getopt_long(argc, argv, _sopts, _lopts, &oidx);
+        if (c == -1) {
+            break; /* done */
+        }
+
+        switch (c) {
+            case 'h':
+                print_usage_and_exit(argv[0], EXIT_SUCCESS);
+                break;
+
+            case 'D':
+                dev_name = strdup(optarg);
+                break;
+
+            default:
+                print_usage_and_exit(argv[0], EXIT_FAILURE);
+        }
+    }
+}
+
+static unique_fd read_file(const char* file_name, off64_t* out_file_size) {
+    int rc;
+    long page_size = sysconf(_SC_PAGESIZE);
+    off64_t file_size, file_page_offset, file_page_size;
+    struct stat64 st;
+
+    unique_fd file_fd(TEMP_FAILURE_RETRY(open(file_name, O_RDONLY)));
+    if (!file_fd.ok()) {
+        fprintf(stderr, "Error opening file '%s': %s\n", file_name, strerror(errno));
+        return {};
+    }
+
+    rc = fstat64(file_fd, &st);
+    if (rc < 0) {
+        fprintf(stderr, "Error calling stat on file '%s': %s\n", file_name, strerror(errno));
+        return {};
+    }
+
+    assert(st.st_size >= 0);
+    file_size = st.st_size;
+
+    /* The dmabuf size needs to be a multiple of the page size */
+    file_page_offset = file_size & (page_size - 1);
+    if (file_page_offset) {
+        file_page_offset = page_size - file_page_offset;
+    }
+    if (__builtin_add_overflow(file_size, file_page_offset, &file_page_size)) {
+        fprintf(stderr, "Failed to page-align file size\n");
+        return {};
+    }
+
+    BufferAllocator alloc;
+    unique_fd dmabuf_fd(alloc.Alloc(kDmabufSystemHeapName, file_page_size));
+    if (!dmabuf_fd.ok()) {
+        fprintf(stderr, "Error creating dmabuf: %d\n", dmabuf_fd.get());
+        return dmabuf_fd;
+    }
+
+    void* shm = mmap(0, file_page_size, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf_fd, 0);
+    if (shm == MAP_FAILED) {
+        return {};
+    }
+
+    off64_t file_offset = 0;
+    while (file_offset < file_size) {
+        ssize_t num_read = TEMP_FAILURE_RETRY(
+                pread(file_fd, (char*)shm + file_offset, file_size - file_offset, file_offset));
+
+        if (num_read < 0) {
+            fprintf(stderr, "Error reading package file '%s': %s\n", file_name, strerror(errno));
+            break;
+        }
+
+        if (num_read == 0) {
+            fprintf(stderr, "Unexpected end of file '%s'\n", file_name);
+            break;
+        }
+
+        file_offset += (off64_t)num_read;
+    }
+
+    munmap(shm, file_page_size);
+
+    if (file_offset < file_size) {
+        return {};
+    }
+
+    assert(file_offset == file_size);
+    if (out_file_size) {
+        *out_file_size = file_size;
+    }
+
+    return dmabuf_fd;
+}
+
+static ssize_t send_load_message(int tipc_fd, int package_fd, off64_t package_size) {
+    struct apploader_header hdr = {
+            .cmd = APPLOADER_CMD_LOAD_APPLICATION,
+    };
+    struct apploader_load_app_req req = {
+            .package_size = static_cast<uint64_t>(package_size),
+    };
+    struct iovec tx[2] = {{&hdr, sizeof(hdr)}, {&req, sizeof(req)}};
+    struct trusty_shm shm = {
+            .fd = package_fd,
+            .transfer = TRUSTY_SHARE,
+    };
+    return tipc_send(tipc_fd, tx, 2, &shm, 1);
+}
+
+static ssize_t read_response(int tipc_fd) {
+    struct apploader_resp resp;
+    ssize_t rc = read(tipc_fd, &resp, sizeof(resp));
+    if (rc < 0) {
+        fprintf(stderr, "Failed to read response: %zd\n", rc);
+        return rc;
+    }
+
+    if (rc < sizeof(resp)) {
+        fprintf(stderr, "Not enough data in response: %zd\n", rc);
+        return -EIO;
+    }
+
+    if (resp.hdr.cmd != (APPLOADER_CMD_LOAD_APPLICATION | APPLOADER_RESP_BIT)) {
+        fprintf(stderr, "Invalid command in response: %u\n", resp.hdr.cmd);
+        return -EINVAL;
+    }
+
+    switch (resp.error) {
+        case APPLOADER_NO_ERROR:
+            break;
+        case APPLOADER_ERR_UNKNOWN_CMD:
+            fprintf(stderr, "Error: unknown command\n");
+            break;
+        case APPLOADER_ERR_INVALID_CMD:
+            fprintf(stderr, "Error: invalid command arguments\n");
+            break;
+        case APPLOADER_ERR_NO_MEMORY:
+            fprintf(stderr, "Error: out of Trusty memory\n");
+            break;
+        case APPLOADER_ERR_VERIFICATION_FAILED:
+            fprintf(stderr, "Error: failed to verify the package\n");
+            break;
+        case APPLOADER_ERR_LOADING_FAILED:
+            fprintf(stderr, "Error: failed to load the package\n");
+            break;
+        case APPLOADER_ERR_ALREADY_EXISTS:
+            fprintf(stderr, "Error: application already exists\n");
+            break;
+        case APPLOADER_ERR_INTERNAL:
+            fprintf(stderr, "Error: internal apploader error\n");
+            break;
+        default:
+            fprintf(stderr, "Unrecognized error: %u\n", resp.error);
+            break;
+    }
+
+    return static_cast<ssize_t>(resp.error);
+}
+
+static ssize_t send_app_package(const char* package_file_name) {
+    ssize_t rc = 0;
+    int tipc_fd = -1;
+    off64_t package_size;
+
+    unique_fd package_fd = read_file(package_file_name, &package_size);
+    if (!package_fd.ok()) {
+        rc = -1;
+        goto err_read_file;
+    }
+
+    tipc_fd = tipc_connect(dev_name, APPLOADER_PORT);
+    if (tipc_fd < 0) {
+        fprintf(stderr, "Failed to connect to Trusty app loader: %s\n", strerror(-tipc_fd));
+        rc = tipc_fd;
+        goto err_tipc_connect;
+    }
+
+    rc = send_load_message(tipc_fd, package_fd, package_size);
+    if (rc < 0) {
+        fprintf(stderr, "Failed to send package: %zd\n", rc);
+        goto err_send;
+    }
+
+    rc = read_response(tipc_fd);
+
+err_send:
+    tipc_close(tipc_fd);
+err_tipc_connect:
+err_read_file:
+    return rc;
+}
+
+int main(int argc, char** argv) {
+    parse_options(argc, argv);
+    if (optind + 1 != argc) {
+        print_usage_and_exit(argv[0], EXIT_FAILURE);
+    }
+
+    int rc = send_app_package(argv[optind]);
+    return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/trusty/apploader/apploader_ipc.h b/trusty/apploader/apploader_ipc.h
new file mode 100644
index 0000000..d8c915e
--- /dev/null
+++ b/trusty/apploader/apploader_ipc.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#define APPLOADER_PORT "com.android.trusty.apploader"
+
+enum apploader_command : uint32_t {
+    APPLOADER_REQ_SHIFT = 1,
+    APPLOADER_RESP_BIT = 1,
+
+    APPLOADER_CMD_LOAD_APPLICATION = (0 << APPLOADER_REQ_SHIFT),
+    APPLOADER_CMD_GET_VERSION = (1 << APPLOADER_REQ_SHIFT),
+    APPLOADER_CMD_UNLOAD_APPLICATION = (2 << APPLOADER_REQ_SHIFT),
+};
+
+/**
+ * enum apploader_error - error codes for apploader
+ * @APPLOADER_NO_ERROR:                 no error
+ * @APPLOADER_ERR_UNKNOWN_CMD:          unknown or not implemented command
+ * @APPLOADER_ERR_INVALID_CMD:          invalid arguments or inputs passed to
+ *                                      command
+ * @APPLOADER_ERR_NO_MEMORY:            failed to allocate memory
+ * @APPLOADER_ERR_VERIFICATION_FAILED:  failed to verify input application
+ *                                      package for any reason, e.g., signature
+ *                                      verification failed
+ * @APPLOADER_ERR_LOADING_FAILED:       Trusty kernel or apploader service
+ *                                      failed to load application
+ * @APPLOADER_ERR_ALREADY_EXISTS:       application has already been loaded
+ * @APPLOADER_ERR_INTERNAL:             miscellaneous or internal apploader
+ *                                      error not covered by the above
+ */
+enum apploader_error : uint32_t {
+    APPLOADER_NO_ERROR = 0,
+    APPLOADER_ERR_UNKNOWN_CMD,
+    APPLOADER_ERR_INVALID_CMD,
+    APPLOADER_ERR_NO_MEMORY,
+    APPLOADER_ERR_VERIFICATION_FAILED,
+    APPLOADER_ERR_LOADING_FAILED,
+    APPLOADER_ERR_ALREADY_EXISTS,
+    APPLOADER_ERR_INTERNAL,
+};
+
+/**
+ * apploader_header - Serial header for communicating with apploader
+ * @cmd: the command; one of &enum apploader_command values.
+ */
+struct apploader_header {
+    uint32_t cmd;
+} __packed;
+
+/**
+ * apploader_load_app_req - Serial arguments for LOAD_APPLICATION command
+ * @package_size: size of the application package.
+ *
+ * Load an application from a given memory region. The request message also
+ * contains a handle for a memfd that contains the application package.
+ *
+ * The response is a &struct apploader_resp with the error code or
+ * %APPLOADER_NO_ERROR on success.
+ */
+struct apploader_load_app_req {
+    uint64_t package_size;
+} __packed;
+
+/**
+ * apploader_resp - Common header for all apploader responses
+ * @hdr - header with command value.
+ * @error - error code returned by peer; one of &enum apploader_error values.
+ *
+ * This structure is followed by the response-specific payload, if the command
+ * has one.
+ */
+struct apploader_resp {
+    struct apploader_header hdr;
+    uint32_t error;
+} __packed;
diff --git a/trusty/trusty-base.mk b/trusty/trusty-base.mk
index fd8daa8..12521b0 100644
--- a/trusty/trusty-base.mk
+++ b/trusty/trusty-base.mk
@@ -24,7 +24,8 @@
 
 PRODUCT_PACKAGES += \
 	android.hardware.keymaster@4.0-service.trusty \
-	android.hardware.gatekeeper@1.0-service.trusty
+	android.hardware.gatekeeper@1.0-service.trusty \
+	trusty_apploader
 
 PRODUCT_PROPERTY_OVERRIDES += \
 	ro.hardware.keystore=trusty \