Merge "[vts-core] Add VtsKernelBinderTest to vts-core suite."
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index db297a0..e048a19 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -7,6 +7,7 @@
                cmds/idlcli/
                include/input/
                libs/binder/ndk/
+               libs/binderthreadstate/
                libs/graphicsenv/
                libs/gui/
                libs/input/
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 4d98520..310b5ce 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -135,6 +135,11 @@
 static char cmdline_buf[16384] = "(unknown)";
 static const char *dump_traces_path = nullptr;
 static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
+// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
+// it's often the case that they time out far too quickly for consent with such a hefty dialog for
+// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
+// roughly match full reports' durations.
+static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
 
 // TODO: variables and functions below should be part of dumpstate object
 
@@ -149,6 +154,7 @@
 #define RECOVERY_DATA_DIR "/data/misc/recovery"
 #define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
 #define LOGPERSIST_DATA_DIR "/data/misc/logd"
+#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
 #define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
 #define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
 #define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
@@ -890,6 +896,14 @@
                CommandOptions::WithTimeoutInMs(timeout_ms).Build());
 }
 
+static void DoRadioLogcat() {
+    unsigned long timeout_ms = logcat_timeout({"radio"});
+    RunCommand(
+        "RADIO LOG",
+        {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
+        CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
+}
+
 static void DoLogcat() {
     unsigned long timeout_ms;
     // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
@@ -908,11 +922,7 @@
         "STATS LOG",
         {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
         CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
-    timeout_ms = logcat_timeout({"radio"});
-    RunCommand(
-        "RADIO LOG",
-        {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
-        CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
+    DoRadioLogcat();
 
     RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
 
@@ -1413,11 +1423,14 @@
     RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
 
     /* Binder state is expensive to look at as it uses a lot of memory. */
-    DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
-    DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
-    DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
-    DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
-    DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
+    std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
+            "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
+
+    DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
+    DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
+    DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
+    DumpFile("BINDER STATS", binder_logs_dir + "/stats");
+    DumpFile("BINDER STATE", binder_logs_dir + "/state");
 
     /* Add window and surface trace files. */
     if (!PropertiesHelper::IsUserBuild()) {
@@ -1561,6 +1574,7 @@
         ds.AddDir(PROFILE_DATA_DIR_CUR, true);
         ds.AddDir(PROFILE_DATA_DIR_REF, true);
     }
+    ds.AddDir(PREREBOOT_DATA_DIR, false);
     add_mountinfo();
     DumpIpTablesAsRoot();
     DumpDynamicPartitionInfo();
@@ -1599,8 +1613,10 @@
     return status;
 }
 
-// This method collects common dumpsys for telephony and wifi
-static void DumpstateRadioCommon() {
+// This method collects common dumpsys for telephony and wifi. Typically, wifi
+// reports are fine to include all information, but telephony reports on user
+// builds need to strip some content (see DumpstateTelephonyOnly).
+static void DumpstateRadioCommon(bool include_sensitive_info = true) {
     DumpIpTablesAsRoot();
 
     ds.AddDir(LOGPERSIST_DATA_DIR, false);
@@ -1609,26 +1625,51 @@
         return;
     }
 
-    do_dmesg();
-    DoLogcat();
+    // We need to be picky about some stuff for telephony reports on user builds.
+    if (!include_sensitive_info) {
+        // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
+        DoRadioLogcat();
+    } else {
+        // Contains various system properties and process startup info.
+        do_dmesg();
+        // Logs other than the radio buffer may contain package/component names and potential PII.
+        DoLogcat();
+        // Too broad for connectivity problems.
+        DoKmsg();
+        // Contains unrelated hardware info (camera, NFC, biometrics, ...).
+        DumpHals();
+    }
+
     DumpPacketStats();
-    DoKmsg();
     DumpIpAddrAndRules();
     dump_route_tables();
-    DumpHals();
-
     RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
                CommandOptions::WithTimeout(10).Build());
 }
 
-// This method collects dumpsys for telephony debugging only
+// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
+// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
+// for what can be included on user builds: all reported information MUST directly relate to
+// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
+// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
+// names are not), and MUST NOT contain logs of user application traffic.
+// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
 static void DumpstateTelephonyOnly() {
     DurationReporter duration_reporter("DUMPSTATE");
+
     const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
 
-    DumpstateRadioCommon();
+    const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
 
-    RunCommand("SYSTEM PROPERTIES", {"getprop"});
+    DumpstateRadioCommon(include_sensitive_info);
+
+    if (include_sensitive_info) {
+        // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
+        // really cherrypick all of the connectivity-related ones. Apps generally have no business
+        // reading these anyway, and there should be APIs to supply the info in a more app-friendly
+        // way.
+        RunCommand("SYSTEM PROPERTIES", {"getprop"});
+    }
 
     printf("========================================================\n");
     printf("== Android Framework Services\n");
@@ -1636,15 +1677,28 @@
 
     RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
                SEC_TO_MSEC(10));
-    RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
-               SEC_TO_MSEC(10));
-    RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
+    // TODO(b/146521742) build out an argument to include bound services here for user builds
     RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
                SEC_TO_MSEC(10));
     RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
                SEC_TO_MSEC(10));
-    RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
+    RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
+    RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
                SEC_TO_MSEC(10));
+    if (include_sensitive_info) {
+        // Contains raw IP addresses, omit from reports on user builds.
+        RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
+        // Contains raw destination IP/MAC addresses, omit from reports on user builds.
+        RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
+                   SEC_TO_MSEC(10));
+        // Contains package/component names, omit from reports on user builds.
+        RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
+                   SEC_TO_MSEC(10));
+        // Contains package names, but should be relatively simple to remove them (also contains
+        // UIDs already), omit from reports on user builds.
+        RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
+                   SEC_TO_MSEC(10));
+    }
 
     printf("========================================================\n");
     printf("== Running Application Services\n");
@@ -1652,18 +1706,24 @@
 
     RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
 
-    printf("========================================================\n");
-    printf("== Running Application Services (non-platform)\n");
-    printf("========================================================\n");
+    if (include_sensitive_info) {
+        printf("========================================================\n");
+        printf("== Running Application Services (non-platform)\n");
+        printf("========================================================\n");
 
-    RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
-            DUMPSYS_COMPONENTS_OPTIONS);
+        // Contains package/component names and potential PII, omit from reports on user builds.
+        // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
+        // carrier_config dumpsys instead.
+        RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
+                   DUMPSYS_COMPONENTS_OPTIONS);
 
-    printf("========================================================\n");
-    printf("== Checkins\n");
-    printf("========================================================\n");
+        printf("========================================================\n");
+        printf("== Checkins\n");
+        printf("========================================================\n");
 
-    RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
+        // Contains package/component names, omit from reports on user builds.
+        RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
+    }
 
     printf("========================================================\n");
     printf("== dumpstate: done (id %d)\n", ds.id_);
@@ -2275,6 +2335,7 @@
             break;
         case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
             options->telephony_only = true;
+            options->do_progress_updates = true;
             options->do_fb = false;
             options->do_broadcast = true;
             break;
@@ -2825,8 +2886,13 @@
     if (consent_result == UserConsentResult::UNAVAILABLE) {
         // User has not responded yet.
         uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
-        if (elapsed_ms < USER_CONSENT_TIMEOUT_MS) {
-            uint delay_seconds = (USER_CONSENT_TIMEOUT_MS - elapsed_ms) / 1000;
+        // Telephony is a fast report type, particularly on user builds where information may be
+        // more aggressively limited. To give the user time to read the consent dialog, increase the
+        // timeout.
+        uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
+                                                       : USER_CONSENT_TIMEOUT_MS;
+        if (elapsed_ms < timeout_ms) {
+            uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
             MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
             sleep(delay_seconds);
         }
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index cff1d43..99d482f 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -372,12 +372,12 @@
     EXPECT_TRUE(options_.do_broadcast);
     EXPECT_TRUE(options_.do_zip_file);
     EXPECT_TRUE(options_.telephony_only);
+    EXPECT_TRUE(options_.do_progress_updates);
 
     // Other options retain default values
     EXPECT_TRUE(options_.do_vibrate);
     EXPECT_FALSE(options_.use_control_socket);
     EXPECT_FALSE(options_.show_header_only);
-    EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
     EXPECT_FALSE(options_.use_socket);
 }
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 5597bcd..a427c8d 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -29,6 +29,7 @@
 #include <utils/Log.h>
 #include <utils/Vector.h>
 
+#include <iostream>
 #include <fcntl.h>
 #include <getopt.h>
 #include <stdio.h>
@@ -231,14 +232,14 @@
     const size_t N = services.size();
     if (N > 1) {
         // first print a list of the current services
-        aout << "Currently running services:" << endl;
+        std::cout << "Currently running services:" << std::endl;
 
         for (size_t i=0; i<N; i++) {
             sp<IBinder> service = sm_->checkService(services[i]);
 
             if (service != nullptr) {
                 bool skipped = IsSkipped(skippedServices, services[i]);
-                aout << "  " << services[i] << (skipped ? " (skipped)" : "") << endl;
+                std::cout << "  " << services[i] << (skipped ? " (skipped)" : "") << std::endl;
             }
         }
     }
@@ -263,10 +264,10 @@
                           asProto, elapsedDuration, bytesWritten);
 
             if (status == TIMED_OUT) {
-                aout << endl
+                std::cout << std::endl
                      << "*** SERVICE '" << serviceName << "' DUMP TIMEOUT (" << timeoutArgMs
-                     << "ms) EXPIRED ***" << endl
-                     << endl;
+                     << "ms) EXPIRED ***" << std::endl
+                     << std::endl;
             }
 
             if (addSeparator) {
@@ -332,14 +333,14 @@
                                   const Vector<String16>& args) {
     sp<IBinder> service = sm_->checkService(serviceName);
     if (service == nullptr) {
-        aerr << "Can't find service: " << serviceName << endl;
+        std::cerr << "Can't find service: " << serviceName << std::endl;
         return NAME_NOT_FOUND;
     }
 
     int sfd[2];
     if (pipe(sfd) != 0) {
-        aerr << "Failed to create pipe to dump service info for " << serviceName << ": "
-             << strerror(errno) << endl;
+        std::cerr << "Failed to create pipe to dump service info for " << serviceName << ": "
+             << strerror(errno) << std::endl;
         return -errno;
     }
 
@@ -359,13 +360,13 @@
             err = dumpPidToFd(service, remote_end);
             break;
         default:
-            aerr << "Unknown dump type" << static_cast<int>(type) << endl;
+            std::cerr << "Unknown dump type" << static_cast<int>(type) << std::endl;
             return;
         }
 
         if (err != OK) {
-            aerr << "Error dumping service info status_t: " << statusToString(err) << " "
-                 << serviceName << endl;
+            std::cerr << "Error dumping service info status_t: " << statusToString(err) << " "
+                 << serviceName << std::endl;
         }
     });
     return OK;
@@ -422,8 +423,8 @@
 
         int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
         if (rc < 0) {
-            aerr << "Error in poll while dumping service " << serviceName << " : "
-                 << strerror(errno) << endl;
+            std::cerr << "Error in poll while dumping service " << serviceName << " : "
+                 << strerror(errno) << std::endl;
             status = -errno;
             break;
         } else if (rc == 0) {
@@ -434,8 +435,8 @@
         char buf[4096];
         rc = TEMP_FAILURE_RETRY(read(redirectFd_.get(), buf, sizeof(buf)));
         if (rc < 0) {
-            aerr << "Failed to read while dumping service " << serviceName << ": "
-                 << strerror(errno) << endl;
+            std::cerr << "Failed to read while dumping service " << serviceName << ": "
+                 << strerror(errno) << std::endl;
             status = -errno;
             break;
         } else if (rc == 0) {
@@ -444,8 +445,8 @@
         }
 
         if (!WriteFully(fd, buf, rc)) {
-            aerr << "Failed to write while dumping service " << serviceName << ": "
-                 << strerror(errno) << endl;
+            std::cerr << "Failed to write while dumping service " << serviceName << ": "
+                 << strerror(errno) << std::endl;
             status = -errno;
             break;
         }
diff --git a/cmds/dumpsys/main.cpp b/cmds/dumpsys/main.cpp
index 8ba0eba..fa4cc97 100644
--- a/cmds/dumpsys/main.cpp
+++ b/cmds/dumpsys/main.cpp
@@ -21,10 +21,9 @@
 #include "dumpsys.h"
 
 #include <binder/IServiceManager.h>
-#include <binder/TextOutput.h>
 
+#include <iostream>
 #include <signal.h>
-#include <stdio.h>
 
 using namespace android;
 
@@ -34,7 +33,7 @@
     fflush(stdout);
     if (sm == nullptr) {
         ALOGE("Unable to get default service manager!");
-        aerr << "dumpsys: Unable to get default service manager!" << endl;
+        std::cerr << "dumpsys: Unable to get default service manager!" << std::endl;
         return 20;
     }
 
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index f95e445..70bbc33 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -299,9 +299,10 @@
 // Namespace for Android Runtime flags applied during boot time.
 static const char* RUNTIME_NATIVE_BOOT_NAMESPACE = "runtime_native_boot";
 // Feature flag name for running the JIT in Zygote experiment, b/119800099.
-static const char* ENABLE_APEX_IMAGE = "enable_apex_image";
-// Location of the apex image.
-static const char* kApexImage = "/system/framework/apex.art";
+static const char* ENABLE_JITZYGOTE_IMAGE = "enable_apex_image";
+// Location of the JIT Zygote image.
+static const char* kJitZygoteImage =
+    "boot.art:/nonx/boot-framework.art!/system/etc/boot-image.prof";
 
 // Phenotype property name for enabling profiling the boot class path.
 static const char* PROFILE_BOOT_CLASS_PATH = "profilebootclasspath";
@@ -405,9 +406,9 @@
                 GetBoolProperty(kMinidebugInfoSystemProperty, kMinidebugInfoSystemPropertyDefault);
 
         std::string boot_image;
-        std::string use_apex_image =
+        std::string use_jitzygote_image =
             server_configurable_flags::GetServerConfigurableFlag(RUNTIME_NATIVE_BOOT_NAMESPACE,
-                                                                 ENABLE_APEX_IMAGE,
+                                                                 ENABLE_JITZYGOTE_IMAGE,
                                                                  /*default_value=*/ "");
 
         std::string profile_boot_class_path = GetProperty("dalvik.vm.profilebootclasspath", "");
@@ -417,10 +418,10 @@
                 PROFILE_BOOT_CLASS_PATH,
                 /*default_value=*/ profile_boot_class_path);
 
-        if (use_apex_image == "true" || profile_boot_class_path == "true") {
-          boot_image = StringPrintf("-Ximage:%s", kApexImage);
+        if (use_jitzygote_image == "true" || profile_boot_class_path == "true") {
+          boot_image = StringPrintf("--boot-image=%s", kJitZygoteImage);
         } else {
-          boot_image = MapPropertyToArg("dalvik.vm.boot-image", "-Ximage:%s");
+          boot_image = MapPropertyToArg("dalvik.vm.boot-image", "--boot-image=%s");
         }
 
         // clang FORTIFY doesn't let us use strlen in constant array bounds, so we
@@ -513,7 +514,8 @@
         AddArg(instruction_set_variant_arg);
         AddArg(instruction_set_features_arg);
 
-        AddRuntimeArg(boot_image);
+        AddArg(boot_image);
+
         AddRuntimeArg(bootclasspath);
         AddRuntimeArg(dex2oat_Xms_arg);
         AddRuntimeArg(dex2oat_Xmx_arg);
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index 3ff9d11..7c989f6 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -73,7 +73,7 @@
     for (const apex::ApexFile& apex_file : active_packages) {
         const std::string& package_path = apex_file.GetPath();
         base::Result<void> status = apex::deactivatePackage(package_path);
-        if (!status) {
+        if (!status.ok()) {
             LOG(ERROR) << "Failed to deactivate " << package_path << ": "
                        << status.error();
         }
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 1ee3853..bc541f4 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -138,7 +138,6 @@
         "liblog",
         "libcutils",
         "libutils",
-        "libbinderthreadstate",
     ],
 
     header_libs: [
@@ -171,7 +170,6 @@
     name: "libbinder_aidl_test_stub",
     local_include_dir: "aidl",
     srcs: [":libbinder_aidl"],
-    visibility: [":__subpackages__"],
     vendor_available: true,
     backend: {
         java: {
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 4981d7a..9e89c57 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -17,7 +17,6 @@
 #define LOG_TAG "IPCThreadState"
 
 #include <binder/IPCThreadState.h>
-#include <binderthreadstate/IPCThreadStateBase.h>
 
 #include <binder/Binder.h>
 #include <binder/BpBinder.h>
@@ -803,6 +802,7 @@
 
 IPCThreadState::IPCThreadState()
     : mProcess(ProcessState::self()),
+      mServingStackPointer(nullptr),
       mWorkSource(kUnsetWorkSource),
       mPropagateWorkSource(false),
       mStrictModePolicy(0),
@@ -813,7 +813,6 @@
     clearCaller();
     mIn.setDataCapacity(256);
     mOut.setDataCapacity(256);
-    mIPCThreadStateBase = IPCThreadStateBase::self();
 }
 
 IPCThreadState::~IPCThreadState()
@@ -1163,9 +1162,6 @@
                 "Not enough command data for brTRANSACTION");
             if (result != NO_ERROR) break;
 
-            //Record the fact that we're in a binder call.
-            mIPCThreadStateBase->pushCurrentState(
-                IPCThreadStateBase::CallState::BINDER);
             Parcel buffer;
             buffer.ipcSetDataReference(
                 reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
@@ -1173,6 +1169,9 @@
                 reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
                 tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);
 
+            const void* origServingStackPointer = mServingStackPointer;
+            mServingStackPointer = &origServingStackPointer; // anything on the stack
+
             const pid_t origPid = mCallingPid;
             const char* origSid = mCallingSid;
             const uid_t origUid = mCallingUid;
@@ -1223,7 +1222,6 @@
                 error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
             }
 
-            mIPCThreadStateBase->popCurrentState();
             //ALOGI("<<<< TRANSACT from pid %d restore pid %d sid %s uid %d\n",
             //     mCallingPid, origPid, (origSid ? origSid : "<N/A>"), origUid);
 
@@ -1232,9 +1230,15 @@
                 if (error < NO_ERROR) reply.setError(error);
                 sendReply(reply, 0);
             } else {
+                if (error != OK || reply.dataSize() != 0) {
+                    alog << "oneway function results will be dropped but finished with status "
+                         << statusToString(error)
+                         << " and parcel size " << reply.dataSize() << endl;
+                }
                 LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
             }
 
+            mServingStackPointer = origServingStackPointer;
             mCallingPid = origPid;
             mCallingSid = origSid;
             mCallingUid = origUid;
@@ -1290,8 +1294,8 @@
     return result;
 }
 
-bool IPCThreadState::isServingCall() const {
-    return mIPCThreadStateBase->getCurrentBinderCallState() == IPCThreadStateBase::CallState::BINDER;
+const void* IPCThreadState::getServingStackPointer() const {
+     return mServingStackPointer;
 }
 
 void IPCThreadState::threadDestructor(void *st)
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 328653a..9888b59 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -85,31 +85,36 @@
     sp<AidlServiceManager> mTheRealServiceManager;
 };
 
-static Mutex gDefaultServiceManagerLock;
+static std::once_flag gSmOnce;
 static sp<IServiceManager> gDefaultServiceManager;
 
 sp<IServiceManager> defaultServiceManager()
 {
-
-    if (gDefaultServiceManager != nullptr) return gDefaultServiceManager;
-
-    {
-        AutoMutex _l(gDefaultServiceManagerLock);
-        while (gDefaultServiceManager == nullptr) {
-            gDefaultServiceManager = new ServiceManagerShim(
-                interface_cast<AidlServiceManager>(
-                    ProcessState::self()->getContextObject(nullptr)));
-            if (gDefaultServiceManager == nullptr)
+    std::call_once(gSmOnce, []() {
+        sp<AidlServiceManager> sm = nullptr;
+        while (sm == nullptr) {
+            sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));
+            if (sm == nullptr) {
                 sleep(1);
+            }
         }
-    }
+
+        gDefaultServiceManager = new ServiceManagerShim(sm);
+    });
 
     return gDefaultServiceManager;
 }
 
 void setDefaultServiceManager(const sp<IServiceManager>& sm) {
-  AutoMutex _l(gDefaultServiceManagerLock);
-  gDefaultServiceManager = sm;
+    bool called = false;
+    std::call_once(gSmOnce, [&]() {
+        gDefaultServiceManager = sm;
+        called = true;
+    });
+
+    if (!called) {
+        LOG_ALWAYS_FATAL("setDefaultServiceManager() called after defaultServiceManager().");
+    }
 }
 
 #if !defined(__ANDROID_VNDK__) && defined(__ANDROID__)
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 9f71f3e..822247f 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2543,11 +2543,13 @@
             if (objectsSize == 0) {
                 free(mObjects);
                 mObjects = nullptr;
+                mObjectsCapacity = 0;
             } else {
                 binder_size_t* objects =
                     (binder_size_t*)realloc(mObjects, objectsSize*sizeof(binder_size_t));
                 if (objects) {
                     mObjects = objects;
+                    mObjectsCapacity = objectsSize;
                 }
             }
             mObjectsSize = objectsSize;
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index 7489afa..9aa7651 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -26,6 +26,9 @@
     },
     {
       "name": "aidl_lazy_test"
+    },
+    {
+      "name": "libbinderthreadstateutils_test"
     }
   ]
 }
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index ff9244e..4818889 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -29,8 +29,6 @@
 // ---------------------------------------------------------------------------
 namespace android {
 
-class IPCThreadStateBase;
-
 class IPCThreadState
 {
 public:
@@ -113,31 +111,12 @@
             // Service manager registration
             void                setTheContextObject(sp<BBinder> obj);
 
-            // Is this thread currently serving a binder call. This method
-            // returns true if while traversing backwards from the function call
-            // stack for this thread, we encounter a function serving a binder
-            // call before encountering a hwbinder call / hitting the end of the
-            // call stack.
-            // Eg: If thread T1 went through the following call pattern
-            //     1) T1 receives and executes hwbinder call H1.
-            //     2) While handling H1, T1 makes binder call B1.
-            //     3) The handler of B1, calls into T1 with a callback B2.
-            // If isServingCall() is called during H1 before 3), this method
-            // will return false, else true.
+            // WARNING: DO NOT USE THIS API
             //
-            //  ----
-            // | B2 | ---> While callback B2 is being handled, during 3).
-            //  ----
-            // | H1 | ---> While H1 is being handled.
-            //  ----
-            // Fig: Thread Call stack while handling B2
-            //
-            // This is since after 3), while traversing the thread call stack,
-            // we hit a binder call before a hwbinder call / end of stack. This
-            // method may be typically used to determine whether to use
-            // hardware::IPCThreadState methods or IPCThreadState methods to
-            // infer information about thread state.
-            bool                isServingCall() const;
+            // Returns a pointer to the stack from the last time a transaction
+            // was initiated by the kernel. Used to compare when making nested
+            // calls between multiple different transports.
+            const void*         getServingStackPointer() const;
 
             // The work source represents the UID of the process we should attribute the transaction
             // to. We use -1 to specify that the work source was not set using #setWorkSource.
@@ -181,6 +160,7 @@
             Parcel              mIn;
             Parcel              mOut;
             status_t            mLastError;
+            const void*         mServingStackPointer;
             pid_t               mCallingPid;
             const char*         mCallingSid;
             uid_t               mCallingUid;
@@ -191,7 +171,6 @@
             bool                mPropagateWorkSource;
             int32_t             mStrictModePolicy;
             int32_t             mLastTransactionBinderFlags;
-            IPCThreadStateBase  *mIPCThreadStateBase;
 
             ProcessState::CallRestriction mCallRestriction;
 };
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 31f022d..1d520c1 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -102,6 +102,9 @@
 
 /**
  * Directly set the default service manager. Only used for testing.
+ * Note that the caller is responsible for caling this method
+ * *before* any call to defaultServiceManager(); if the latter is
+ * called first, setDefaultServiceManager() will abort.
  */
 void setDefaultServiceManager(const sp<IServiceManager>& sm);
 
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index e752c45..75dcdc8 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -24,10 +24,13 @@
 
 #include <android-base/logging.h>
 #include <binder/IPCThreadState.h>
+#include <binder/IResultReceiver.h>
+#include <private/android_filesystem_config.h>
 
 using DeathRecipient = ::android::IBinder::DeathRecipient;
 
 using ::android::IBinder;
+using ::android::IResultReceiver;
 using ::android::Parcel;
 using ::android::sp;
 using ::android::status_t;
@@ -158,6 +161,45 @@
 
         binder_status_t status = getClass()->onTransact(this, code, &in, &out);
         return PruneStatusT(status);
+    } else if (code == SHELL_COMMAND_TRANSACTION) {
+        int in = data.readFileDescriptor();
+        int out = data.readFileDescriptor();
+        int err = data.readFileDescriptor();
+
+        int argc = data.readInt32();
+        std::vector<String8> utf8Args;          // owns memory of utf8s
+        std::vector<const char*> utf8Pointers;  // what can be passed over NDK API
+        for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
+            utf8Args.push_back(String8(data.readString16()));
+            utf8Pointers.push_back(utf8Args[i].c_str());
+        }
+
+        data.readStrongBinder();  // skip over the IShellCallback
+        sp<IResultReceiver> resultReceiver = IResultReceiver::asInterface(data.readStrongBinder());
+
+        // Shell commands should only be callable by ADB.
+        uid_t uid = AIBinder_getCallingUid();
+        if (uid != AID_ROOT && uid != AID_SHELL) {
+            if (resultReceiver != nullptr) {
+                resultReceiver->send(-1);
+            }
+            return STATUS_PERMISSION_DENIED;
+        }
+
+        // Check that the file descriptors are valid.
+        if (in == STATUS_BAD_TYPE || out == STATUS_BAD_TYPE || err == STATUS_BAD_TYPE) {
+            if (resultReceiver != nullptr) {
+                resultReceiver->send(-1);
+            }
+            return STATUS_BAD_VALUE;
+        }
+
+        binder_status_t status = getClass()->handleShellCommand(
+                this, in, out, err, utf8Pointers.data(), utf8Pointers.size());
+        if (resultReceiver != nullptr) {
+            resultReceiver->send(status);
+        }
+        return status;
     } else {
         return BBinder::onTransact(code, data, reply, flags);
     }
@@ -266,6 +308,13 @@
     clazz->onDump = onDump;
 }
 
+void AIBinder_Class_setHandleShellCommand(AIBinder_Class* clazz,
+                                          AIBinder_handleShellCommand handleShellCommand) {
+    CHECK(clazz != nullptr) << "setHandleShellCommand requires non-null clazz";
+
+    clazz->handleShellCommand = handleShellCommand;
+}
+
 void AIBinder_DeathRecipient::TransferDeathRecipient::binderDied(const wp<IBinder>& who) {
     CHECK(who == mWho);
 
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index 5cb68c2..5779427 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <android/binder_ibinder.h>
+#include <android/binder_shell.h>
 #include "ibinder_internal.h"
 
 #include <atomic>
@@ -115,6 +116,7 @@
 
     // optional methods for a class
     AIBinder_onDump onDump;
+    AIBinder_handleShellCommand handleShellCommand;
 
    private:
     // This must be a String16 since BBinder virtual getInterfaceDescriptor returns a reference to
diff --git a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
index 83a1048..7331ba2 100644
--- a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
@@ -30,6 +30,11 @@
 #include <android/binder_auto_utils.h>
 #include <android/binder_ibinder.h>
 
+#if __has_include(<android/binder_shell.h>)
+#include <android/binder_shell.h>
+#define HAS_BINDER_SHELL_COMMAND
+#endif  //_has_include
+
 #include <assert.h>
 
 #include <memory>
@@ -108,7 +113,15 @@
     /**
      * Dumps information about the interface. By default, dumps nothing.
      */
-    virtual inline binder_status_t dump(int /*fd*/, const char** /*args*/, uint32_t /*numArgs*/);
+    virtual inline binder_status_t dump(int fd, const char** args, uint32_t numArgs);
+
+#ifdef HAS_BINDER_SHELL_COMMAND
+    /**
+     * Process shell commands. By default, does nothing.
+     */
+    virtual inline binder_status_t handleShellCommand(int in, int out, int err, const char** argv,
+                                                      uint32_t argc);
+#endif
 
     /**
      * Interprets this binder as this underlying interface if this has stored an ICInterface in the
@@ -136,6 +149,11 @@
         static inline void onDestroy(void* userData);
         static inline binder_status_t onDump(AIBinder* binder, int fd, const char** args,
                                              uint32_t numArgs);
+
+#ifdef HAS_BINDER_SHELL_COMMAND
+        static inline binder_status_t handleShellCommand(AIBinder* binder, int in, int out, int err,
+                                                         const char** argv, uint32_t argc);
+#endif
     };
 };
 
@@ -191,6 +209,13 @@
     return STATUS_OK;
 }
 
+#ifdef HAS_BINDER_SHELL_COMMAND
+binder_status_t ICInterface::handleShellCommand(int /*in*/, int /*out*/, int /*err*/,
+                                                const char** /*argv*/, uint32_t /*argc*/) {
+    return STATUS_OK;
+}
+#endif
+
 std::shared_ptr<ICInterface> ICInterface::asInterface(AIBinder* binder) {
     return ICInterfaceData::getInterface(binder);
 }
@@ -203,9 +228,12 @@
         return nullptr;
     }
 
-    // We can't know if this method is overriden by a subclass interface, so we must register
-    // ourselves. The default (nothing to dump) is harmless.
+    // We can't know if these methods are overridden by a subclass interface, so we must register
+    // ourselves. The defaults are harmless.
     AIBinder_Class_setOnDump(clazz, ICInterfaceData::onDump);
+#ifdef HAS_BINDER_SHELL_COMMAND
+    AIBinder_Class_setHandleShellCommand(clazz, ICInterfaceData::handleShellCommand);
+#endif
     return clazz;
 }
 
@@ -234,6 +262,15 @@
     return interface->dump(fd, args, numArgs);
 }
 
+#ifdef HAS_BINDER_SHELL_COMMAND
+binder_status_t ICInterface::ICInterfaceData::handleShellCommand(AIBinder* binder, int in, int out,
+                                                                 int err, const char** argv,
+                                                                 uint32_t argc) {
+    std::shared_ptr<ICInterface> interface = getInterface(binder);
+    return interface->handleShellCommand(in, out, err, argv, argc);
+}
+#endif
+
 template <typename INTERFACE>
 SpAIBinder BnCInterface<INTERFACE>::asBinder() {
     std::lock_guard<std::mutex> l(mMutex);
diff --git a/libs/binder/ndk/include_platform/android/binder_shell.h b/libs/binder/ndk/include_platform/android/binder_shell.h
new file mode 100644
index 0000000..17b38b0
--- /dev/null
+++ b/libs/binder/ndk/include_platform/android/binder_shell.h
@@ -0,0 +1,55 @@
+/*
+ * 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 <android/binder_ibinder.h>
+
+__BEGIN_DECLS
+
+/**
+ * Function to execute a shell command.
+ *
+ * Available since API level 30.
+ *
+ * \param binder the binder executing the command
+ * \param in input file descriptor, should be flushed, ownership is not passed
+ * \param out output file descriptor, should be flushed, ownership is not passed
+ * \param err error file descriptor, should be flushed, ownership is not passed
+ * \param argv array of null-terminated strings for command (may be null if argc
+ * is 0)
+ * \param argc length of argv array
+ *
+ * \return binder_status_t result of transaction
+ */
+typedef binder_status_t (*AIBinder_handleShellCommand)(AIBinder* binder, int in, int out, int err,
+                                                       const char** argv, uint32_t argc);
+
+/**
+ * This sets the implementation of handleShellCommand for a class.
+ *
+ * If this isn't set, nothing will be executed when handleShellCommand is called.
+ *
+ * Available since API level 30.
+ *
+ * \param handleShellCommand function to call when a shell transaction is
+ * received
+ */
+void AIBinder_Class_setHandleShellCommand(AIBinder_Class* clazz,
+                                          AIBinder_handleShellCommand handleShellCommand)
+        __INTRODUCED_IN(30);
+
+__END_DECLS
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index f3158d7..7e72f22 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -110,6 +110,7 @@
     AIBinder_markSystemStability; # apex
     AIBinder_markVendorStability; # llndk
     AIBinder_markVintfStability; # apex llndk
+    AIBinder_Class_setHandleShellCommand; # apex llndk
   local:
     *;
 };
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
index 513d8c2..cb4b20f 100644
--- a/libs/binder/ndk/test/Android.bp
+++ b/libs/binder/ndk/test/Android.bp
@@ -60,6 +60,7 @@
     defaults: ["test_libbinder_ndk_test_defaults"],
     srcs: ["libbinder_ndk_unit_test.cpp"],
     static_libs: [
+        "IBinderNdkUnitTest-cpp",
         "IBinderNdkUnitTest-ndk_platform",
     ],
     test_suites: ["general-tests"],
diff --git a/libs/binder/ndk/test/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/test/libbinder_ndk_unit_test.cpp
index 51dd169..fd30d87 100644
--- a/libs/binder/ndk/test/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/test/libbinder_ndk_unit_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <IBinderNdkUnitTest.h>
 #include <aidl/BnBinderNdkUnitTest.h>
 #include <aidl/BnEmpty.h>
 #include <android-base/logging.h>
@@ -26,13 +27,16 @@
 // warning: this is assuming that libbinder_ndk is using the same copy
 // of libbinder that we are.
 #include <binder/IPCThreadState.h>
+#include <binder/IResultReceiver.h>
+#include <binder/IServiceManager.h>
+#include <binder/IShellCallback.h>
 
 #include <sys/prctl.h>
 #include <chrono>
 #include <condition_variable>
 #include <mutex>
 
-using ::android::sp;
+using namespace android;
 
 constexpr char kExistingNonNdkService[] = "SurfaceFlinger";
 constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest";
@@ -48,6 +52,14 @@
         android::IPCThreadState::self()->flushCommands();
         return ndk::ScopedAStatus::ok();
     }
+    binder_status_t handleShellCommand(int /*in*/, int out, int /*err*/, const char** args,
+                                       uint32_t numArgs) override {
+        for (uint32_t i = 0; i < numArgs; i++) {
+            dprintf(out, "%s", args[i]);
+        }
+        fsync(out);
+        return STATUS_OK;
+    }
 };
 
 int generatedService() {
@@ -296,6 +308,92 @@
     EXPECT_TRUE(destroyed);
 }
 
+class MyResultReceiver : public BnResultReceiver {
+   public:
+    Mutex mMutex;
+    Condition mCondition;
+    bool mHaveResult = false;
+    int32_t mResult = 0;
+
+    virtual void send(int32_t resultCode) {
+        AutoMutex _l(mMutex);
+        mResult = resultCode;
+        mHaveResult = true;
+        mCondition.signal();
+    }
+
+    int32_t waitForResult() {
+        AutoMutex _l(mMutex);
+        while (!mHaveResult) {
+            mCondition.wait(mMutex);
+        }
+        return mResult;
+    }
+};
+
+class MyShellCallback : public BnShellCallback {
+   public:
+    virtual int openFile(const String16& /*path*/, const String16& /*seLinuxContext*/,
+                         const String16& /*mode*/) {
+        // Empty implementation.
+        return 0;
+    }
+};
+
+bool ReadFdToString(int fd, std::string* content) {
+    char buf[64];
+    ssize_t n;
+    while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
+        content->append(buf, n);
+    }
+    return (n == 0) ? true : false;
+}
+
+std::string shellCmdToString(sp<IBinder> unitTestService, const std::vector<const char*>& args) {
+    int inFd[2] = {-1, -1};
+    int outFd[2] = {-1, -1};
+    int errFd[2] = {-1, -1};
+
+    EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, inFd));
+    EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, outFd));
+    EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, errFd));
+
+    sp<MyShellCallback> cb = new MyShellCallback();
+    sp<MyResultReceiver> resultReceiver = new MyResultReceiver();
+
+    Vector<String16> argsVec;
+    for (int i = 0; i < args.size(); i++) {
+        argsVec.add(String16(args[i]));
+    }
+    status_t error = IBinder::shellCommand(unitTestService, inFd[0], outFd[0], errFd[0], argsVec,
+                                           cb, resultReceiver);
+    EXPECT_EQ(error, android::OK);
+
+    status_t res = resultReceiver->waitForResult();
+    EXPECT_EQ(res, android::OK);
+
+    close(inFd[0]);
+    close(inFd[1]);
+    close(outFd[0]);
+    close(errFd[0]);
+    close(errFd[1]);
+
+    std::string ret;
+    EXPECT_TRUE(ReadFdToString(outFd[1], &ret));
+    close(outFd[1]);
+    return ret;
+}
+
+TEST(NdkBinder, UseHandleShellCommand) {
+    static const sp<android::IServiceManager> sm(android::defaultServiceManager());
+    sp<IBinder> testService = sm->getService(String16(kBinderNdkUnitTestService));
+
+    EXPECT_EQ("", shellCmdToString(testService, {}));
+    EXPECT_EQ("", shellCmdToString(testService, {"", ""}));
+    EXPECT_EQ("Hello world!", shellCmdToString(testService, {"Hello ", "world!"}));
+    EXPECT_EQ("CMD", shellCmdToString(testService, {"C", "M", "D"}));
+}
+
 int main(int argc, char* argv[]) {
     ::testing::InitGoogleTest(&argc, argv);
 
diff --git a/libs/binderthreadstate/1.0/Android.bp b/libs/binderthreadstate/1.0/Android.bp
new file mode 100644
index 0000000..ebdc932
--- /dev/null
+++ b/libs/binderthreadstate/1.0/Android.bp
@@ -0,0 +1,14 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "binderthreadstateutilstest@1.0",
+    root: "binderthreadstateutilstest",
+    system_ext_specific: true,
+    srcs: [
+        "IHidlStuff.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/libs/binderthreadstate/1.0/IHidlStuff.hal b/libs/binderthreadstate/1.0/IHidlStuff.hal
new file mode 100644
index 0000000..ffb6499
--- /dev/null
+++ b/libs/binderthreadstate/1.0/IHidlStuff.hal
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+package binderthreadstateutilstest@1.0;
+
+interface IHidlStuff {
+    callLocal();
+    call(int32_t idx);
+};
diff --git a/libs/binderthreadstate/Android.bp b/libs/binderthreadstate/Android.bp
index ee1a6a4..4655e1d 100644
--- a/libs/binderthreadstate/Android.bp
+++ b/libs/binderthreadstate/Android.bp
@@ -12,6 +12,59 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+// DO NOT ADD NEW USAGES OF THIS
+// See comments in header file.
+cc_library_static {
+    name: "libbinderthreadstateutils",
+    double_loadable: true,
+    vendor_available: true,
+    host_supported: true,
+
+    shared_libs: [
+        "libbinder",
+        "libhidlbase",  // libhwbinder is in here
+    ],
+
+    export_include_dirs: ["include"],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+}
+
+hidl_package_root {
+    name: "binderthreadstateutilstest",
+}
+
+aidl_interface {
+    name: "binderthreadstateutilstest.aidl",
+    srcs: ["IAidlStuff.aidl"],
+}
+
+cc_test {
+    name: "libbinderthreadstateutils_test",
+    srcs: ["test.cpp"],
+    static_libs: [
+        "binderthreadstateutilstest@1.0",
+        "binderthreadstateutilstest.aidl-cpp",
+        "libbinderthreadstateutils",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "libhidlbase",
+        "libutils",
+        "liblog",
+    ],
+    test_suites: [
+        "general-tests",
+    ],
+    require_root: true,
+}
+
+// TODO(b/148692216): remove empty lib
 cc_library {
     name: "libbinderthreadstate",
     recovery_available: true,
@@ -21,28 +74,4 @@
         support_system_process: true,
     },
     host_supported: true,
-
-    srcs: [
-        "IPCThreadStateBase.cpp",
-    ],
-
-    header_libs: [
-        "libbase_headers",
-        "libutils_headers",
-    ],
-
-    shared_libs: [
-        "liblog",
-    ],
-
-    export_include_dirs: ["include"],
-
-    sanitize: {
-        misc_undefined: ["integer"],
-    },
-
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
 }
diff --git a/libs/binderthreadstate/IAidlStuff.aidl b/libs/binderthreadstate/IAidlStuff.aidl
new file mode 100644
index 0000000..0c81c42
--- /dev/null
+++ b/libs/binderthreadstate/IAidlStuff.aidl
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+
+interface IAidlStuff {
+    void callLocal();
+    void call(int idx);
+}
diff --git a/libs/binderthreadstate/IPCThreadStateBase.cpp b/libs/binderthreadstate/IPCThreadStateBase.cpp
deleted file mode 100644
index fede151..0000000
--- a/libs/binderthreadstate/IPCThreadStateBase.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2018 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 "IPCThreadStateBase"
-
-#include <binderthreadstate/IPCThreadStateBase.h>
-#include <android-base/macros.h>
-
-#include <utils/Log.h>
-
-#include <errno.h>
-#include <inttypes.h>
-#include <pthread.h>
-
-namespace android {
-
-static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
-static bool gHaveTLS = false;
-static pthread_key_t gTLS = 0;
-
-IPCThreadStateBase::IPCThreadStateBase() {
-    pthread_setspecific(gTLS, this);
-}
-
-IPCThreadStateBase* IPCThreadStateBase::self()
-{
-    if (gHaveTLS) {
-restart:
-        const pthread_key_t k = gTLS;
-        IPCThreadStateBase* st = (IPCThreadStateBase*)pthread_getspecific(k);
-        if (st) return st;
-        return new IPCThreadStateBase;
-    }
-
-    pthread_mutex_lock(&gTLSMutex);
-    if (!gHaveTLS) {
-        int key_create_value = pthread_key_create(&gTLS, threadDestructor);
-        if (key_create_value != 0) {
-            pthread_mutex_unlock(&gTLSMutex);
-            ALOGW("IPCThreadStateBase::self() unable to create TLS key, expect a crash: %s\n",
-                    strerror(key_create_value));
-            return nullptr;
-        }
-        gHaveTLS = true;
-    }
-    pthread_mutex_unlock(&gTLSMutex);
-    goto restart;
-}
-
-void IPCThreadStateBase::pushCurrentState(CallState callState) {
-    mCallStateStack.emplace(callState);
-}
-
-IPCThreadStateBase::CallState IPCThreadStateBase::popCurrentState() {
-    ALOG_ASSERT(mCallStateStack.size > 0);
-    CallState val = mCallStateStack.top();
-    mCallStateStack.pop();
-    return val;
-}
-
-IPCThreadStateBase::CallState IPCThreadStateBase::getCurrentBinderCallState() {
-    if (mCallStateStack.size() > 0) {
-        return mCallStateStack.top();
-    }
-    return CallState::NONE;
-}
-
-void IPCThreadStateBase::threadDestructor(void *st)
-{
-    IPCThreadStateBase* const self = static_cast<IPCThreadStateBase*>(st);
-    if (self) {
-        delete self;
-    }
-}
-
-}; // namespace android
diff --git a/libs/binderthreadstate/TEST_MAPPING b/libs/binderthreadstate/TEST_MAPPING
new file mode 100644
index 0000000..2bd0463
--- /dev/null
+++ b/libs/binderthreadstate/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "libbinderthreadstateutils_test"
+    }
+  ]
+}
diff --git a/libs/binderthreadstate/include/binderthreadstate/CallerUtils.h b/libs/binderthreadstate/include/binderthreadstate/CallerUtils.h
new file mode 100644
index 0000000..a3e5026
--- /dev/null
+++ b/libs/binderthreadstate/include/binderthreadstate/CallerUtils.h
@@ -0,0 +1,50 @@
+/*
+ * 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
+
+// WARNING: DO NOT USE THIS
+// You should:
+// - have code know how it is handling things. Pass in caller information rather
+//   than assuming that code is running in a specific global context
+// - use AIDL exclusively in your stack (HIDL is no longer required anywhere)
+
+#include <binder/IPCThreadState.h>
+#include <hwbinder/IPCThreadState.h>
+
+namespace android {
+
+enum class BinderCallType {
+    NONE,
+    BINDER,
+    HWBINDER,
+};
+
+// Based on where we are in recursion of nested binder/hwbinder calls, determine
+// which one we are closer to.
+inline static BinderCallType getCurrentServingCall() {
+    const void* hwbinderSp = android::hardware::IPCThreadState::self()->getServingStackPointer();
+    const void* binderSp = android::IPCThreadState::self()->getServingStackPointer();
+
+    if (hwbinderSp == nullptr && binderSp == nullptr) return BinderCallType::NONE;
+    if (hwbinderSp == nullptr) return BinderCallType::BINDER;
+    if (binderSp == nullptr) return BinderCallType::HWBINDER;
+
+    if (hwbinderSp < binderSp) return BinderCallType::HWBINDER;
+    return BinderCallType::BINDER;
+}
+
+} // namespace android
diff --git a/libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h b/libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h
deleted file mode 100644
index 6fdcc84..0000000
--- a/libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef BINDER_THREADSTATE_IPC_THREADSTATE_BASE_H
-#define BINDER_THREADSTATE_IPC_THREADSTATE_BASE_H
-
-#include <stack>
-namespace android {
-
-class IPCThreadStateBase {
-public:
-    enum CallState {
-        HWBINDER,
-        BINDER,
-        NONE,
-    };
-    static IPCThreadStateBase* self();
-    void pushCurrentState(CallState callState);
-    CallState popCurrentState();
-    CallState getCurrentBinderCallState();
-
-private:
-    IPCThreadStateBase();
-    static void threadDestructor(void *st);
-
-    std::stack<CallState> mCallStateStack;
-};
-
-}; // namespace android
-
-#endif // BINDER_THREADSTATE_IPC_THREADSTATE_BASE_H
diff --git a/libs/binderthreadstate/test.cpp b/libs/binderthreadstate/test.cpp
new file mode 100644
index 0000000..68cc225
--- /dev/null
+++ b/libs/binderthreadstate/test.cpp
@@ -0,0 +1,195 @@
+/*
+ * 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 <BnAidlStuff.h>
+#include <android-base/logging.h>
+#include <binder/IServiceManager.h>
+#include <binderthreadstate/CallerUtils.h>
+#include <binderthreadstateutilstest/1.0/IHidlStuff.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlTransportSupport.h>
+#include <linux/prctl.h>
+#include <sys/prctl.h>
+
+using android::BinderCallType;
+using android::defaultServiceManager;
+using android::getCurrentServingCall;
+using android::getService;
+using android::OK;
+using android::sp;
+using android::String16;
+using android::binder::Status;
+using android::hardware::Return;
+using binderthreadstateutilstest::V1_0::IHidlStuff;
+
+constexpr size_t kP1Id = 1;
+constexpr size_t kP2Id = 2;
+
+// AIDL and HIDL are in separate namespaces so using same service names
+std::string id2name(size_t id) {
+    return "libbinderthreadstateutils-" + std::to_string(id);
+}
+
+// There are two servers calling each other recursively like this.
+//
+// P1           P2
+// |  --HIDL-->  |
+// |  <--HIDL--  |
+// |  --AIDL-->  |
+// |  <--AIDL--  |
+// |  --HIDL-->  |
+// |  <--HIDL--  |
+// |  --AIDL-->  |
+// |  <--AIDL--  |
+//   ..........
+//
+// Calls always come in pairs (AIDL returns AIDL, HIDL returns HIDL) because
+// this means that P1 always has a 'waitForResponse' call which can service the
+// returning call and continue the recursion. Of course, with more threads, more
+// complicated calls are possible, but this should do here.
+
+static void callHidl(size_t id, int32_t idx) {
+    auto stuff = IHidlStuff::getService(id2name(id));
+    CHECK(stuff->call(idx).isOk());
+}
+
+static void callAidl(size_t id, int32_t idx) {
+    sp<IAidlStuff> stuff;
+    CHECK(OK == android::getService<IAidlStuff>(String16(id2name(id).c_str()), &stuff));
+    CHECK(stuff->call(idx).isOk());
+}
+
+class HidlServer : public IHidlStuff {
+public:
+    HidlServer(size_t thisId, size_t otherId) : thisId(thisId), otherId(otherId) {}
+    size_t thisId;
+    size_t otherId;
+
+    Return<void> callLocal() {
+        CHECK(BinderCallType::NONE == getCurrentServingCall());
+        return android::hardware::Status::ok();
+    }
+    Return<void> call(int32_t idx) {
+        LOG(INFO) << "HidlServer CALL " << thisId << " to " << otherId << " at idx: " << idx
+                  << " with tid: " << gettid();
+        CHECK(BinderCallType::HWBINDER == getCurrentServingCall());
+        if (idx > 0) {
+            if (thisId == kP1Id && idx % 4 < 2) {
+                callHidl(otherId, idx - 1);
+            } else {
+                callAidl(otherId, idx - 1);
+            }
+        }
+        CHECK(BinderCallType::HWBINDER == getCurrentServingCall());
+        return android::hardware::Status::ok();
+    }
+};
+class AidlServer : public BnAidlStuff {
+public:
+    AidlServer(size_t thisId, size_t otherId) : thisId(thisId), otherId(otherId) {}
+    size_t thisId;
+    size_t otherId;
+
+    Status callLocal() {
+        CHECK(BinderCallType::NONE == getCurrentServingCall());
+        return Status::ok();
+    }
+    Status call(int32_t idx) {
+        LOG(INFO) << "AidlServer CALL " << thisId << " to " << otherId << " at idx: " << idx
+                  << " with tid: " << gettid();
+        CHECK(BinderCallType::BINDER == getCurrentServingCall());
+        if (idx > 0) {
+            if (thisId == kP2Id && idx % 4 < 2) {
+                callHidl(otherId, idx - 1);
+            } else {
+                callAidl(otherId, idx - 1);
+            }
+        }
+        CHECK(BinderCallType::BINDER == getCurrentServingCall());
+        return Status::ok();
+    }
+};
+
+TEST(BinderThreadState, LocalHidlCall) {
+    sp<IHidlStuff> server = new HidlServer(0, 0);
+    EXPECT_TRUE(server->callLocal().isOk());
+}
+
+TEST(BinderThreadState, LocalAidlCall) {
+    sp<IAidlStuff> server = new AidlServer(0, 0);
+    EXPECT_TRUE(server->callLocal().isOk());
+}
+
+TEST(BindThreadState, RemoteHidlCall) {
+    auto stuff = IHidlStuff::getService(id2name(kP1Id));
+    ASSERT_NE(nullptr, stuff);
+    ASSERT_TRUE(stuff->call(0).isOk());
+}
+TEST(BindThreadState, RemoteAidlCall) {
+    sp<IAidlStuff> stuff;
+    ASSERT_EQ(OK, android::getService<IAidlStuff>(String16(id2name(kP1Id).c_str()), &stuff));
+    ASSERT_NE(nullptr, stuff);
+    ASSERT_TRUE(stuff->call(0).isOk());
+}
+
+TEST(BindThreadState, RemoteNestedStartHidlCall) {
+    auto stuff = IHidlStuff::getService(id2name(kP1Id));
+    ASSERT_NE(nullptr, stuff);
+    ASSERT_TRUE(stuff->call(100).isOk());
+}
+TEST(BindThreadState, RemoteNestedStartAidlCall) {
+    sp<IAidlStuff> stuff;
+    ASSERT_EQ(OK, android::getService<IAidlStuff>(String16(id2name(kP1Id).c_str()), &stuff));
+    ASSERT_NE(nullptr, stuff);
+    EXPECT_TRUE(stuff->call(100).isOk());
+}
+
+int server(size_t thisId, size_t otherId) {
+    // AIDL
+    android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
+    sp<AidlServer> aidlServer = new AidlServer(thisId, otherId);
+    CHECK(OK == defaultServiceManager()->addService(String16(id2name(thisId).c_str()), aidlServer));
+    android::ProcessState::self()->startThreadPool();
+
+    // HIDL
+    setenv("TREBLE_TESTING_OVERRIDE", "true", true);
+    android::hardware::configureRpcThreadpool(1, true /*callerWillJoin*/);
+    sp<IHidlStuff> hidlServer = new HidlServer(thisId, otherId);
+    CHECK(OK == hidlServer->registerAsService(id2name(thisId).c_str()));
+    android::hardware::joinRpcThreadpool();
+
+    return EXIT_FAILURE;
+}
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    setenv("TREBLE_TESTING_OVERRIDE", "true", true);
+    if (fork() == 0) {
+        prctl(PR_SET_PDEATHSIG, SIGHUP);
+        return server(kP1Id, kP2Id);
+    }
+    if (fork() == 0) {
+        prctl(PR_SET_PDEATHSIG, SIGHUP);
+        return server(kP2Id, kP1Id);
+    }
+
+    android::waitForService<IAidlStuff>(String16(id2name(kP1Id).c_str()));
+    android::hardware::details::waitForHwService(IHidlStuff::descriptor, id2name(kP1Id).c_str());
+    android::waitForService<IAidlStuff>(String16(id2name(kP2Id).c_str()));
+    android::hardware::details::waitForHwService(IHidlStuff::descriptor, id2name(kP2Id).c_str());
+
+    return RUN_ALL_TESTS();
+}
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 166775b..ba3195a 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -186,6 +186,10 @@
         "libvndksupport",
     ],
 
+    static_libs: [
+        "libbinderthreadstateutils",
+    ],
+
     header_libs: [
         "libgui_headers",
         "libnativebase_headers",
diff --git a/libs/gui/BufferQueueThreadState.cpp b/libs/gui/BufferQueueThreadState.cpp
index 3b531ec..c13030b 100644
--- a/libs/gui/BufferQueueThreadState.cpp
+++ b/libs/gui/BufferQueueThreadState.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <binder/IPCThreadState.h>
+#include <binderthreadstate/CallerUtils.h>
 #include <hwbinder/IPCThreadState.h>
 #include <private/gui/BufferQueueThreadState.h>
 #include <unistd.h>
@@ -22,14 +23,14 @@
 namespace android {
 
 uid_t BufferQueueThreadState::getCallingUid() {
-    if (hardware::IPCThreadState::self()->isServingCall()) {
+    if (getCurrentServingCall() == BinderCallType::HWBINDER) {
         return hardware::IPCThreadState::self()->getCallingUid();
     }
     return IPCThreadState::self()->getCallingUid();
 }
 
 pid_t BufferQueueThreadState::getCallingPid() {
-    if (hardware::IPCThreadState::self()->isServingCall()) {
+    if (getCurrentServingCall() == BinderCallType::HWBINDER) {
         return hardware::IPCThreadState::self()->getCallingPid();
     }
     return IPCThreadState::self()->getCallingPid();
diff --git a/services/stats/Android.bp b/services/stats/Android.bp
new file mode 100644
index 0000000..1ce0524
--- /dev/null
+++ b/services/stats/Android.bp
@@ -0,0 +1,22 @@
+cc_library_shared {
+    name: "libstatshidl",
+    srcs: [
+        "StatsHal.cpp",
+    ],
+    cflags: ["-Wall", "-Werror"],
+    shared_libs: [
+        "android.frameworks.stats@1.0",
+        "libhidlbase",
+        "liblog",
+        "libstatslog",
+        "libstatssocket",
+        "libutils",
+    ],
+    export_include_dirs: [
+    	"include/",
+    ],
+    local_include_dirs: [
+        "include/stats",
+    ],
+    vintf_fragments: ["android.frameworks.stats@1.0-service.xml"]
+}
diff --git a/services/stats/OWNERS b/services/stats/OWNERS
new file mode 100644
index 0000000..a61babf
--- /dev/null
+++ b/services/stats/OWNERS
@@ -0,0 +1,9 @@
+jeffreyhuang@google.com
+joeo@google.com
+jtnguyen@google.com
+muhammadq@google.com
+ruchirr@google.com
+singhtejinder@google.com
+tsaichristine@google.com
+yaochen@google.com
+yro@google.com
diff --git a/services/stats/StatsHal.cpp b/services/stats/StatsHal.cpp
new file mode 100644
index 0000000..b775431
--- /dev/null
+++ b/services/stats/StatsHal.cpp
@@ -0,0 +1,124 @@
+/*
+ * 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 DEBUG false // STOPSHIP if true
+#define LOG_TAG "StatsHal"
+
+#include <log/log.h>
+#include <statslog.h>
+
+#include "StatsHal.h"
+
+namespace android {
+namespace frameworks {
+namespace stats {
+namespace V1_0 {
+namespace implementation {
+
+StatsHal::StatsHal() {}
+
+hardware::Return<void> StatsHal::reportSpeakerImpedance(
+        const SpeakerImpedance& speakerImpedance) {
+    android::util::stats_write(android::util::SPEAKER_IMPEDANCE_REPORTED,
+            speakerImpedance.speakerLocation, speakerImpedance.milliOhms);
+
+    return hardware::Void();
+}
+
+hardware::Return<void> StatsHal::reportHardwareFailed(const HardwareFailed& hardwareFailed) {
+    android::util::stats_write(android::util::HARDWARE_FAILED, int32_t(hardwareFailed.hardwareType),
+            hardwareFailed.hardwareLocation, int32_t(hardwareFailed.errorCode));
+
+    return hardware::Void();
+}
+
+hardware::Return<void> StatsHal::reportPhysicalDropDetected(
+        const PhysicalDropDetected& physicalDropDetected) {
+    android::util::stats_write(android::util::PHYSICAL_DROP_DETECTED,
+            int32_t(physicalDropDetected.confidencePctg), physicalDropDetected.accelPeak,
+            physicalDropDetected.freefallDuration);
+
+    return hardware::Void();
+}
+
+hardware::Return<void> StatsHal::reportChargeCycles(const ChargeCycles& chargeCycles) {
+    std::vector<int32_t> buckets = chargeCycles.cycleBucket;
+    int initialSize = buckets.size();
+    for (int i = 0; i < 10 - initialSize; i++) {
+        buckets.push_back(-1); // Push -1 for buckets that do not exist.
+    }
+    android::util::stats_write(android::util::CHARGE_CYCLES_REPORTED, buckets[0], buckets[1],
+            buckets[2], buckets[3], buckets[4], buckets[5], buckets[6], buckets[7], buckets[8],
+            buckets[9]);
+
+    return hardware::Void();
+}
+
+hardware::Return<void> StatsHal::reportBatteryHealthSnapshot(
+        const BatteryHealthSnapshotArgs& batteryHealthSnapshotArgs) {
+    android::util::stats_write(android::util::BATTERY_HEALTH_SNAPSHOT,
+            int32_t(batteryHealthSnapshotArgs.type), batteryHealthSnapshotArgs.temperatureDeciC,
+            batteryHealthSnapshotArgs.voltageMicroV, batteryHealthSnapshotArgs.currentMicroA,
+            batteryHealthSnapshotArgs.openCircuitVoltageMicroV,
+            batteryHealthSnapshotArgs.resistanceMicroOhm, batteryHealthSnapshotArgs.levelPercent);
+
+    return hardware::Void();
+}
+
+hardware::Return<void> StatsHal::reportSlowIo(const SlowIo& slowIo) {
+    android::util::stats_write(android::util::SLOW_IO, int32_t(slowIo.operation), slowIo.count);
+
+    return hardware::Void();
+}
+
+hardware::Return<void> StatsHal::reportBatteryCausedShutdown(
+        const BatteryCausedShutdown& batteryCausedShutdown) {
+    android::util::stats_write(android::util::BATTERY_CAUSED_SHUTDOWN,
+            batteryCausedShutdown.voltageMicroV);
+
+    return hardware::Void();
+}
+
+hardware::Return<void> StatsHal::reportUsbPortOverheatEvent(
+        const UsbPortOverheatEvent& usbPortOverheatEvent) {
+    android::util::stats_write(android::util::USB_PORT_OVERHEAT_EVENT_REPORTED,
+            usbPortOverheatEvent.plugTemperatureDeciC, usbPortOverheatEvent.maxTemperatureDeciC,
+            usbPortOverheatEvent.timeToOverheat, usbPortOverheatEvent.timeToHysteresis,
+            usbPortOverheatEvent.timeToInactive);
+
+    return hardware::Void();
+}
+
+hardware::Return<void> StatsHal::reportSpeechDspStat(
+        const SpeechDspStat& speechDspStat) {
+    android::util::stats_write(android::util::SPEECH_DSP_STAT_REPORTED,
+            speechDspStat.totalUptimeMillis, speechDspStat.totalDowntimeMillis,
+            speechDspStat.totalCrashCount, speechDspStat.totalRecoverCount);
+
+    return hardware::Void();
+}
+
+hardware::Return<void> StatsHal::reportVendorAtom(const VendorAtom& vendorAtom) {
+  ALOGW("reportVendorAtom unsupported");
+  std::string reverDomainName = vendorAtom.reverseDomainName;
+  return hardware::Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace stats
+}  // namespace frameworks
+}  // namespace android
diff --git a/services/stats/android.frameworks.stats@1.0-service.xml b/services/stats/android.frameworks.stats@1.0-service.xml
new file mode 100644
index 0000000..bb02f66
--- /dev/null
+++ b/services/stats/android.frameworks.stats@1.0-service.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="framework">
+    <hal>
+        <name>android.frameworks.stats</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IStats</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/services/stats/include/stats/StatsHal.h b/services/stats/include/stats/StatsHal.h
new file mode 100644
index 0000000..ad14263
--- /dev/null
+++ b/services/stats/include/stats/StatsHal.h
@@ -0,0 +1,97 @@
+/*
+ * 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 <android/frameworks/stats/1.0/IStats.h>
+#include <android/frameworks/stats/1.0/types.h>
+
+using namespace android::frameworks::stats::V1_0;
+
+namespace android {
+namespace frameworks {
+namespace stats {
+namespace V1_0 {
+namespace implementation {
+
+using android::hardware::Return;
+
+/**
+* Implements the Stats HAL
+*/
+class StatsHal : public IStats {
+public:
+    StatsHal();
+
+    /**
+     * Binder call to get SpeakerImpedance atom.
+     */
+    virtual Return<void> reportSpeakerImpedance(const SpeakerImpedance& speakerImpedance) override;
+
+    /**
+     * Binder call to get HardwareFailed atom.
+     */
+    virtual Return<void> reportHardwareFailed(const HardwareFailed& hardwareFailed) override;
+
+    /**
+     * Binder call to get PhysicalDropDetected atom.
+     */
+    virtual Return<void> reportPhysicalDropDetected(
+             const PhysicalDropDetected& physicalDropDetected) override;
+
+    /**
+     * Binder call to get ChargeCyclesReported atom.
+     */
+     virtual Return<void> reportChargeCycles(const ChargeCycles& chargeCycles) override;
+
+    /**
+     * Binder call to get BatteryHealthSnapshot atom.
+     */
+    virtual Return<void> reportBatteryHealthSnapshot(
+            const BatteryHealthSnapshotArgs& batteryHealthSnapshotArgs) override;
+
+    /**
+     * Binder call to get SlowIo atom.
+     */
+    virtual Return<void> reportSlowIo(const SlowIo& slowIo) override;
+
+    /**
+     * Binder call to get BatteryCausedShutdown atom.
+     */
+    virtual Return<void> reportBatteryCausedShutdown(
+            const BatteryCausedShutdown& batteryCausedShutdown) override;
+
+    /**
+     * Binder call to get UsbPortOverheatEvent atom.
+     */
+    virtual Return<void> reportUsbPortOverheatEvent(
+            const UsbPortOverheatEvent& usbPortOverheatEvent) override;
+
+    /**
+     * Binder call to get Speech DSP state atom.
+     */
+    virtual Return<void> reportSpeechDspStat(
+            const SpeechDspStat& speechDspStat) override;
+
+    /**
+     * Binder call to get vendor atom.
+     */
+    virtual Return<void> reportVendorAtom(const VendorAtom& vendorAtom) override;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace stats
+}  // namespace frameworks
+}  // namespace android