Merge "libbinder should not be included in APEX"
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 443f885..eaa84f5 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -170,6 +170,7 @@
         { OPT,      "events/clk/clk_disable/enable" },
         { OPT,      "events/clk/clk_enable/enable" },
         { OPT,      "events/power/cpu_frequency_limits/enable" },
+        { OPT,      "events/power/suspend_resume/enable" },
     } },
     { "membus",     "Memory Bus Utilization", 0, {
         { REQ,      "events/memory_bus/enable" },
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index f1426b6..6e460a0 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -49,6 +49,8 @@
     chmod 0666 /sys/kernel/tracing/events/power/cpu_frequency_limits/enable
     chmod 0666 /sys/kernel/debug/tracing/events/power/gpu_frequency/enable
     chmod 0666 /sys/kernel/tracing/events/power/gpu_frequency/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/power/suspend_resume/enable
+    chmod 0666 /sys/kernel/tracing/events/power/suspend_resume/enable
     chmod 0666 /sys/kernel/debug/tracing/events/cpufreq_interactive/enable
     chmod 0666 /sys/kernel/tracing/events/cpufreq_interactive/enable
     chmod 0666 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin/enable
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index 8d383f5..93bbe90 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -93,7 +93,6 @@
         "libutils",
     ],
     srcs: [
-        "DumpstateSectionReporter.cpp",
         "DumpstateService.cpp",
     ],
     static_libs: [
diff --git a/cmds/dumpstate/DumpstateSectionReporter.cpp b/cmds/dumpstate/DumpstateSectionReporter.cpp
deleted file mode 100644
index f814bde..0000000
--- a/cmds/dumpstate/DumpstateSectionReporter.cpp
+++ /dev/null
@@ -1,42 +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 "dumpstate"
-
-#include "DumpstateSectionReporter.h"
-
-namespace android {
-namespace os {
-namespace dumpstate {
-
-DumpstateSectionReporter::DumpstateSectionReporter(const std::string& title,
-                                                   sp<android::os::IDumpstateListener> listener,
-                                                   bool sendReport)
-    : title_(title), listener_(listener), sendReport_(sendReport), status_(OK), size_(-1) {
-    started_ = std::chrono::steady_clock::now();
-}
-
-DumpstateSectionReporter::~DumpstateSectionReporter() {
-    if ((listener_ != nullptr) && (sendReport_)) {
-        auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
-            std::chrono::steady_clock::now() - started_);
-        listener_->onSectionComplete(title_, status_, size_, (int32_t)elapsed.count());
-    }
-}
-
-}  // namespace dumpstate
-}  // namespace os
-}  // namespace android
diff --git a/cmds/dumpstate/DumpstateSectionReporter.h b/cmds/dumpstate/DumpstateSectionReporter.h
deleted file mode 100644
index e971de8..0000000
--- a/cmds/dumpstate/DumpstateSectionReporter.h
+++ /dev/null
@@ -1,65 +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 ANDROID_OS_DUMPSTATESECTIONREPORTER_H_
-#define ANDROID_OS_DUMPSTATESECTIONREPORTER_H_
-
-#include <android/os/IDumpstateListener.h>
-#include <utils/StrongPointer.h>
-
-namespace android {
-namespace os {
-namespace dumpstate {
-
-
-/*
- * Helper class used to report per section details to a listener.
- *
- * Typical usage:
- *
- *    DumpstateSectionReporter sectionReporter(title, listener, sendReport);
- *    sectionReporter.setSize(5000);
- *
- */
-class DumpstateSectionReporter {
-  public:
-    DumpstateSectionReporter(const std::string& title, sp<android::os::IDumpstateListener> listener,
-                             bool sendReport);
-
-    ~DumpstateSectionReporter();
-
-    void setStatus(status_t status) {
-        status_ = status;
-    }
-
-    void setSize(int size) {
-        size_ = size;
-    }
-
-  private:
-    std::string title_;
-    android::sp<android::os::IDumpstateListener> listener_;
-    bool sendReport_;
-    status_t status_;
-    int size_;
-    std::chrono::time_point<std::chrono::steady_clock> started_;
-};
-
-}  // namespace dumpstate
-}  // namespace os
-}  // namespace android
-
-#endif  // ANDROID_OS_DUMPSTATESECTIONREPORTER_H_
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index 37ba4f9..f98df99 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -200,8 +200,7 @@
     dprintf(fd, "id: %d\n", ds_->id_);
     dprintf(fd, "pid: %d\n", ds_->pid_);
     dprintf(fd, "update_progress: %s\n", ds_->options_->do_progress_updates ? "true" : "false");
-    dprintf(fd, "update_progress_threshold: %d\n", ds_->update_progress_threshold_);
-    dprintf(fd, "last_updated_progress: %d\n", ds_->last_updated_progress_);
+    dprintf(fd, "last_percent_progress: %d\n", ds_->last_reported_percent_progress_);
     dprintf(fd, "progress:\n");
     ds_->progress_->Dump(fd, "  ");
     dprintf(fd, "args: %s\n", ds_->options_->args.c_str());
diff --git a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
index ea1e467..e486460 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
@@ -61,21 +61,4 @@
      * Called when taking bugreport finishes successfully.
      */
     void onFinished();
-
-    // TODO(b/111441001): Remove old methods when not used anymore.
-    void onProgressUpdated(int progress);
-    void onMaxProgressUpdated(int maxProgress);
-
-    /**
-     * Called after every section is complete.
-     *
-     * @param  name          section name
-     * @param  status        values from status_t
-     *                       {@code OK} section completed successfully
-     *                       {@code TIMEOUT} dump timed out
-     *                       {@code != OK} error
-     * @param  size          size in bytes, may be invalid if status != OK
-     * @param  durationMs    duration in ms
-     */
-    void onSectionComplete(@utf8InCpp String name, int status, int size, int durationMs);
 }
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index bdb1363..e296eaa 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -43,10 +43,12 @@
 #include <unistd.h>
 
 #include <chrono>
+#include <cmath>
 #include <fstream>
 #include <functional>
 #include <future>
 #include <memory>
+#include <numeric>
 #include <regex>
 #include <set>
 #include <string>
@@ -77,7 +79,6 @@
 #include <serviceutils/PriorityDumper.h>
 #include <utils/StrongPointer.h>
 #include "DumpstateInternal.h"
-#include "DumpstateSectionReporter.h"
 #include "DumpstateService.h"
 #include "dumpstate.h"
 
@@ -102,7 +103,6 @@
 using android::os::IDumpstateListener;
 using android::os::dumpstate::CommandOptions;
 using android::os::dumpstate::DumpFileToFd;
-using android::os::dumpstate::DumpstateSectionReporter;
 using android::os::dumpstate::PropertiesHelper;
 
 // Keep in sync with
@@ -115,8 +115,9 @@
 // TODO: temporary variables and functions used during C++ refactoring
 static Dumpstate& ds = Dumpstate::GetInstance();
 static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
-                      const CommandOptions& options = CommandOptions::DEFAULT) {
-    return ds.RunCommand(title, full_command, options);
+                      const CommandOptions& options = CommandOptions::DEFAULT,
+                      bool verbose_duration = false) {
+    return ds.RunCommand(title, full_command, options, verbose_duration);
 }
 
 // Reasonable value for max stats.
@@ -867,17 +868,17 @@
     RunCommand(
         "EVENT LOG",
         {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
-        CommandOptions::WithTimeoutInMs(timeout_ms).Build());
+        CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
     timeout_ms = logcat_timeout({"stats"});
     RunCommand(
         "STATS LOG",
         {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
-        CommandOptions::WithTimeoutInMs(timeout_ms).Build());
+        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());
+        CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
 
     RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
 
@@ -1016,7 +1017,6 @@
         RETURN_IF_USER_DENIED_CONSENT();
         std::string path(title);
         path.append(" - ").append(String8(service).c_str());
-        DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
         size_t bytes_written = 0;
         status_t status = dumpsys.startDumpThread(service, args);
         if (status == OK) {
@@ -1024,12 +1024,10 @@
             std::chrono::duration<double> elapsed_seconds;
             status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
                                        /* as_proto = */ false, elapsed_seconds, bytes_written);
-            section_reporter.setSize(bytes_written);
             dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
             bool dump_complete = (status == OK);
             dumpsys.stopDumpThread(dump_complete);
         }
-        section_reporter.setStatus(status);
 
         auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
             std::chrono::steady_clock::now() - start);
@@ -1092,7 +1090,6 @@
             path.append("_HIGH");
         }
         path.append(kProtoExt);
-        DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
         status_t status = dumpsys.startDumpThread(service, args);
         if (status == OK) {
             status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
@@ -1101,8 +1098,6 @@
         }
         ZipWriter::FileEntry file_entry;
         ds.zip_writer_->GetLastEntry(&file_entry);
-        section_reporter.setSize(file_entry.compressed_size);
-        section_reporter.setStatus(status);
 
         auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
             std::chrono::steady_clock::now() - start);
@@ -1209,6 +1204,45 @@
     }
 }
 
+static void DumpExternalFragmentationInfo() {
+    struct stat st;
+    if (stat("/proc/buddyinfo", &st) != 0) {
+        MYLOGE("Unable to dump external fragmentation info\n");
+        return;
+    }
+
+    printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
+    std::ifstream ifs("/proc/buddyinfo");
+    auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
+    for (std::string line; std::getline(ifs, line);) {
+        std::smatch match_results;
+        if (std::regex_match(line, match_results, unusable_index_regex)) {
+            std::stringstream free_pages(std::string{match_results[3]});
+            std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
+                                                  std::istream_iterator<int>());
+
+            int total_free_pages = 0;
+            for (size_t i = 0; i < free_pages_per_order.size(); i++) {
+                total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
+            }
+
+            printf("Node %s, zone %8s", match_results[1].str().c_str(),
+                   match_results[2].str().c_str());
+
+            int usable_free_pages = total_free_pages;
+            for (size_t i = 0; i < free_pages_per_order.size(); i++) {
+                auto unusable_index = (total_free_pages - usable_free_pages) /
+                        static_cast<double>(total_free_pages);
+                printf(" %5.3f", unusable_index);
+                usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
+            }
+
+            printf("\n");
+        }
+    }
+    printf("\n");
+}
+
 // Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
 // via the consent they are shown. Ignores other errors that occur while running various
 // commands. The consent checking is currently done around long running tasks, which happen to
@@ -1222,7 +1256,6 @@
     dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
     RunCommand("UPTIME", {"uptime"});
     DumpBlockStatFiles();
-    dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
     DumpFile("MEMORY INFO", "/proc/meminfo");
     RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
                             "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
@@ -1235,11 +1268,10 @@
     DumpFile("ZONEINFO", "/proc/zoneinfo");
     DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
     DumpFile("BUDDYINFO", "/proc/buddyinfo");
-    DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
+    DumpExternalFragmentationInfo();
 
     DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
     DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
-    DumpFile("KERNEL SYNC", "/d/sync");
 
     RunCommand("PROCESSES AND THREADS",
                {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
@@ -1477,6 +1509,8 @@
 static void DumpstateRadioCommon() {
     DumpIpTablesAsRoot();
 
+    ds.AddDir(LOGPERSIST_DATA_DIR, false);
+
     if (!DropRootUser()) {
         return;
     }
@@ -1487,6 +1521,7 @@
     DoKmsg();
     DumpIpAddrAndRules();
     dump_route_tables();
+    DumpHals();
 
     RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
                CommandOptions::WithTimeout(10).Build());
@@ -1556,8 +1591,6 @@
     RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
                SEC_TO_MSEC(10));
 
-    DumpHals();
-
     printf("========================================================\n");
     printf("== dumpstate: done (id %d)\n", ds.id_);
     printf("========================================================\n");
@@ -2772,6 +2805,7 @@
 Dumpstate::Dumpstate(const std::string& version)
     : pid_(getpid()),
       options_(new Dumpstate::DumpOptions()),
+      last_reported_percent_progress_(0),
       version_(version),
       now_(time(nullptr)) {
 }
@@ -2781,8 +2815,8 @@
     return singleton_;
 }
 
-DurationReporter::DurationReporter(const std::string& title, bool logcat_only)
-    : title_(title), logcat_only_(logcat_only) {
+DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose)
+    : title_(title), logcat_only_(logcat_only), verbose_(verbose) {
     if (!title_.empty()) {
         started_ = Nanotime();
     }
@@ -2791,7 +2825,7 @@
 DurationReporter::~DurationReporter() {
     if (!title_.empty()) {
         float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
-        if (elapsed < .5f) {
+        if (elapsed < .5f && !verbose_) {
             return;
         }
         MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
@@ -3384,8 +3418,8 @@
 }
 
 int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
-                          const CommandOptions& options) {
-    DurationReporter duration_reporter(title);
+                          const CommandOptions& options, bool verbose_duration) {
+    DurationReporter duration_reporter(title, false /* logcat_only */, verbose_duration);
 
     int status = RunCommandToFd(STDOUT_FILENO, title, full_command, options);
 
@@ -3534,31 +3568,25 @@
     }
 
     // Always update progess so stats can be tuned...
-    bool max_changed = progress_->Inc(delta_sec);
+    progress_->Inc(delta_sec);
 
     // ...but only notifiy listeners when necessary.
     if (!options_->do_progress_updates) return;
 
     int progress = progress_->Get();
     int max = progress_->GetMax();
+    int percent = 100 * progress / max;
 
-    // adjusts max on the fly
-    if (max_changed && listener_ != nullptr) {
-        listener_->onMaxProgressUpdated(max);
-    }
-
-    int32_t last_update_delta = progress - last_updated_progress_;
-    if (last_updated_progress_ > 0 && last_update_delta < update_progress_threshold_) {
+    if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
         return;
     }
-    last_updated_progress_ = progress;
+    last_reported_percent_progress_ = percent;
 
     if (control_socket_fd_ >= 0) {
         dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
         fsync(control_socket_fd_);
     }
 
-    int percent = 100 * progress / max;
     if (listener_ != nullptr) {
         if (percent % 5 == 0) {
             // We don't want to spam logcat, so only log multiples of 5.
@@ -3570,8 +3598,6 @@
             fprintf(stderr, "Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(),
                     progress, max, percent);
         }
-        // TODO(b/111441001): Remove in favor of onProgress
-        listener_->onProgressUpdated(progress);
 
         listener_->onProgress(percent);
     }
@@ -3604,110 +3630,3 @@
     }
     return info.st_mtime;
 }
-
-void dump_emmc_ecsd(const char *ext_csd_path) {
-    // List of interesting offsets
-    struct hex {
-        char str[2];
-    };
-    static const size_t EXT_CSD_REV = 192 * sizeof(hex);
-    static const size_t EXT_PRE_EOL_INFO = 267 * sizeof(hex);
-    static const size_t EXT_DEVICE_LIFE_TIME_EST_TYP_A = 268 * sizeof(hex);
-    static const size_t EXT_DEVICE_LIFE_TIME_EST_TYP_B = 269 * sizeof(hex);
-
-    std::string buffer;
-    if (!android::base::ReadFileToString(ext_csd_path, &buffer)) {
-        return;
-    }
-
-    printf("------ %s Extended CSD ------\n", ext_csd_path);
-
-    if (buffer.length() < (EXT_CSD_REV + sizeof(hex))) {
-        printf("*** %s: truncated content %zu\n\n", ext_csd_path, buffer.length());
-        return;
-    }
-
-    int ext_csd_rev = 0;
-    std::string sub = buffer.substr(EXT_CSD_REV, sizeof(hex));
-    if (sscanf(sub.c_str(), "%2x", &ext_csd_rev) != 1) {
-        printf("*** %s: EXT_CSD_REV parse error \"%s\"\n\n", ext_csd_path, sub.c_str());
-        return;
-    }
-
-    static const char *ver_str[] = {
-        "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0"
-    };
-    printf("rev 1.%d (MMC %s)\n", ext_csd_rev,
-           (ext_csd_rev < (int)(sizeof(ver_str) / sizeof(ver_str[0]))) ? ver_str[ext_csd_rev]
-                                                                       : "Unknown");
-    if (ext_csd_rev < 7) {
-        printf("\n");
-        return;
-    }
-
-    if (buffer.length() < (EXT_PRE_EOL_INFO + sizeof(hex))) {
-        printf("*** %s: truncated content %zu\n\n", ext_csd_path, buffer.length());
-        return;
-    }
-
-    int ext_pre_eol_info = 0;
-    sub = buffer.substr(EXT_PRE_EOL_INFO, sizeof(hex));
-    if (sscanf(sub.c_str(), "%2x", &ext_pre_eol_info) != 1) {
-        printf("*** %s: PRE_EOL_INFO parse error \"%s\"\n\n", ext_csd_path, sub.c_str());
-        return;
-    }
-
-    static const char *eol_str[] = {
-        "Undefined",
-        "Normal",
-        "Warning (consumed 80% of reserve)",
-        "Urgent (consumed 90% of reserve)"
-    };
-    printf(
-        "PRE_EOL_INFO %d (MMC %s)\n", ext_pre_eol_info,
-        eol_str[(ext_pre_eol_info < (int)(sizeof(eol_str) / sizeof(eol_str[0]))) ? ext_pre_eol_info
-                                                                                 : 0]);
-
-    for (size_t lifetime = EXT_DEVICE_LIFE_TIME_EST_TYP_A;
-            lifetime <= EXT_DEVICE_LIFE_TIME_EST_TYP_B;
-            lifetime += sizeof(hex)) {
-        int ext_device_life_time_est;
-        static const char *est_str[] = {
-            "Undefined",
-            "0-10% of device lifetime used",
-            "10-20% of device lifetime used",
-            "20-30% of device lifetime used",
-            "30-40% of device lifetime used",
-            "40-50% of device lifetime used",
-            "50-60% of device lifetime used",
-            "60-70% of device lifetime used",
-            "70-80% of device lifetime used",
-            "80-90% of device lifetime used",
-            "90-100% of device lifetime used",
-            "Exceeded the maximum estimated device lifetime",
-        };
-
-        if (buffer.length() < (lifetime + sizeof(hex))) {
-            printf("*** %s: truncated content %zu\n", ext_csd_path, buffer.length());
-            break;
-        }
-
-        ext_device_life_time_est = 0;
-        sub = buffer.substr(lifetime, sizeof(hex));
-        if (sscanf(sub.c_str(), "%2x", &ext_device_life_time_est) != 1) {
-            printf("*** %s: DEVICE_LIFE_TIME_EST_TYP_%c parse error \"%s\"\n", ext_csd_path,
-                   (unsigned)((lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) / sizeof(hex)) + 'A',
-                   sub.c_str());
-            continue;
-        }
-        printf("DEVICE_LIFE_TIME_EST_TYP_%c %d (MMC %s)\n",
-               (unsigned)((lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) / sizeof(hex)) + 'A',
-               ext_device_life_time_est,
-               est_str[(ext_device_life_time_est < (int)(sizeof(est_str) / sizeof(est_str[0])))
-                           ? ext_device_life_time_est
-                           : 0]);
-    }
-
-    printf("\n");
-}
-
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index ae6a721..82bf821 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -73,13 +73,15 @@
  */
 class DurationReporter {
   public:
-    explicit DurationReporter(const std::string& title, bool logcat_only = false);
+    explicit DurationReporter(const std::string& title, bool logcat_only = false,
+                              bool verbose = false);
 
     ~DurationReporter();
 
   private:
     std::string title_;
     bool logcat_only_;
+    bool verbose_;
     uint64_t started_;
 
     DISALLOW_COPY_AND_ASSIGN(DurationReporter);
@@ -224,7 +226,8 @@
      */
     int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
                    const android::os::dumpstate::CommandOptions& options =
-                       android::os::dumpstate::CommandOptions::DEFAULT);
+                       android::os::dumpstate::CommandOptions::DEFAULT,
+                   bool verbose_duration = false);
 
     /*
      * Runs `dumpsys` with the given arguments, automatically setting its timeout
@@ -400,12 +403,8 @@
     // Runtime options.
     std::unique_ptr<DumpOptions> options_;
 
-    // How frequently the progess should be updated;the listener will only be notificated when the
-    // delta from the previous update is more than the threshold.
-    int32_t update_progress_threshold_ = 100;
-
-    // Last progress that triggered a listener updated
-    int32_t last_updated_progress_;
+    // Last progress that was sent to the listener [0-100].
+    int last_reported_percent_progress_ = 0;
 
     // Whether it should take an screenshot earlier in the process.
     bool do_early_screenshot_ = false;
@@ -585,9 +584,6 @@
 /** Gets the last modification time of a file, or default time if file is not found. */
 time_t get_mtime(int fd, time_t default_mtime);
 
-/* Dumps eMMC Extended CSD data. */
-void dump_emmc_ecsd(const char *ext_csd_path);
-
 /** Gets command-line arguments. */
 void format_args(int argc, const char *argv[], std::string *args);
 
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index f7acaf1..181046a 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -167,26 +167,6 @@
         return binder::Status::ok();
     }
 
-    binder::Status onProgressUpdated(int32_t progress) override {
-        dprintf(out_fd_, "\rIn progress %d/%d", progress, max_progress_);
-        return binder::Status::ok();
-    }
-
-    binder::Status onMaxProgressUpdated(int32_t max_progress) override {
-        std::lock_guard<std::mutex> lock(lock_);
-        max_progress_ = max_progress;
-        return binder::Status::ok();
-    }
-
-    binder::Status onSectionComplete(const ::std::string& name, int32_t, int32_t size_bytes,
-                                     int32_t) override {
-        std::lock_guard<std::mutex> lock(lock_);
-        if (sections_.get() != nullptr) {
-            sections_->push_back({name, size_bytes});
-        }
-        return binder::Status::ok();
-    }
-
     bool getIsFinished() {
         std::lock_guard<std::mutex> lock(lock_);
         return is_finished_;
@@ -199,7 +179,6 @@
 
   private:
     int out_fd_;
-    int max_progress_ = 5000;
     int error_code_ = -1;
     bool is_finished_ = false;
     std::shared_ptr<std::vector<SectionInfo>> sections_;
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 4e6b084..cff1d43 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -62,10 +62,6 @@
     MOCK_METHOD1(onProgress, binder::Status(int32_t progress));
     MOCK_METHOD1(onError, binder::Status(int32_t error_code));
     MOCK_METHOD0(onFinished, binder::Status());
-    MOCK_METHOD1(onProgressUpdated, binder::Status(int32_t progress));
-    MOCK_METHOD1(onMaxProgressUpdated, binder::Status(int32_t max_progress));
-    MOCK_METHOD4(onSectionComplete, binder::Status(const ::std::string& name, int32_t status,
-                                                   int32_t size, int32_t durationMs));
 
   protected:
     MOCK_METHOD0(onAsBinder, IBinder*());
@@ -590,7 +586,6 @@
         SetDryRun(false);
         SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)"));
         ds.progress_.reset(new Progress());
-        ds.update_progress_threshold_ = 0;
         ds.options_.reset(new Dumpstate::DumpOptions());
     }
 
@@ -615,10 +610,9 @@
         return status;
     }
 
-    void SetProgress(long progress, long initial_max, long threshold = 0) {
+    void SetProgress(long progress, long initial_max) {
+        ds.last_reported_percent_progress_ = 0;
         ds.options_->do_progress_updates = true;
-        ds.update_progress_threshold_ = threshold;
-        ds.last_updated_progress_ = 0;
         ds.progress_.reset(new Progress(initial_max, progress, 1.2));
     }
 
@@ -796,73 +790,36 @@
     ds.listener_name_ = "FoxMulder";
     SetProgress(0, 30);
 
-    EXPECT_CALL(*listener, onProgressUpdated(20));
     EXPECT_CALL(*listener, onProgress(66));  // 20/30 %
     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build()));
     std::string progress_message = GetProgressMessage(ds.listener_name_, 20, 30);
     EXPECT_THAT(out, StrEq("stdout\n"));
     EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
 
-    EXPECT_CALL(*listener, onProgressUpdated(30));
-    EXPECT_CALL(*listener, onProgress(100));  // 35/35 %
-    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Build()));
-    progress_message = GetProgressMessage(ds.listener_name_, 30, 30);
-    EXPECT_THAT(out, StrEq("stdout\n"));
-    EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
-
-    // Run a command that will increase maximum timeout.
-    EXPECT_CALL(*listener, onProgressUpdated(31));
-    EXPECT_CALL(*listener, onMaxProgressUpdated(37));
-    EXPECT_CALL(*listener, onProgress(83));  // 31/37 %
-    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
-    progress_message = GetProgressMessage(ds.listener_name_, 31, 37, 30);  // 20% increase
+    EXPECT_CALL(*listener, onProgress(80));  // 24/30 %
+    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
+    progress_message = GetProgressMessage(ds.listener_name_, 24, 30);
     EXPECT_THAT(out, StrEq("stdout\n"));
     EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
 
     // Make sure command ran while in dry_run is counted.
     SetDryRun(true);
-    EXPECT_CALL(*listener, onProgressUpdated(35));
-    EXPECT_CALL(*listener, onProgress(94));  // 35/37 %
-    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
-    progress_message = GetProgressMessage(ds.listener_name_, 35, 37);
+    EXPECT_CALL(*listener, onProgress(90));  // 27/30 %
+    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build()));
+    progress_message = GetProgressMessage(ds.listener_name_, 27, 30);
     EXPECT_THAT(out, IsEmpty());
     EXPECT_THAT(err, StrEq(progress_message));
 
-    ds.listener_.clear();
-}
-
-TEST_F(DumpstateTest, RunCommandProgressIgnoreThreshold) {
-    sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
-    ds.listener_ = listener;
-    ds.listener_name_ = "FoxMulder";
-    SetProgress(0, 8, 5);  // 8 max, 5 threshold
-
-    // First update should always be sent.
-    EXPECT_CALL(*listener, onProgressUpdated(1));
-    EXPECT_CALL(*listener, onProgress(12));  // 1/12 %
-    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
-    std::string progress_message = GetProgressMessage(ds.listener_name_, 1, 8);
+    SetDryRun(false);
+    EXPECT_CALL(*listener, onProgress(96));  // 29/30 %
+    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(2).Build()));
+    progress_message = GetProgressMessage(ds.listener_name_, 29, 30);
     EXPECT_THAT(out, StrEq("stdout\n"));
     EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
 
-    // Fourth update should be ignored because it's between the threshold (5 -1 = 4 < 5).
-    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
-    EXPECT_THAT(out, StrEq("stdout\n"));
-    EXPECT_THAT(err, StrEq("stderr\n"));
-
-    // Third update should be sent because it reaches threshold (6 - 1 = 5).
-    EXPECT_CALL(*listener, onProgressUpdated(6));
-    EXPECT_CALL(*listener, onProgress(75));  // 6/8 %
+    EXPECT_CALL(*listener, onProgress(100));  // 30/30 %
     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
-    progress_message = GetProgressMessage(ds.listener_name_, 6, 8);
-    EXPECT_THAT(out, StrEq("stdout\n"));
-    EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
-
-    // Fourth update should be ignored because it's between the threshold (9 - 6 = 3 < 5).
-    // But max update should be sent.
-    EXPECT_CALL(*listener, onMaxProgressUpdated(10));  // 9 * 120% = 10.8 = 10
-    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build()));
-    progress_message = GetProgressMessage(ds.listener_name_, 9, 10, 8, false);
+    progress_message = GetProgressMessage(ds.listener_name_, 30, 30);
     EXPECT_THAT(out, StrEq("stdout\n"));
     EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
 
@@ -1090,7 +1047,6 @@
     ds.listener_name_ = "FoxMulder";
     SetProgress(0, 30);
 
-    EXPECT_CALL(*listener, onProgressUpdated(5));
     EXPECT_CALL(*listener, onProgress(16));  // 5/30 %
     EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
 
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 73780ec..0212bc5 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -275,7 +275,7 @@
             writer.StartEntry("primary.prof", ZipWriter::kCompress);
             writer.FinishEntry();
             writer.Finish();
-            close(fd);
+            fclose(file);
           }
 
         // Create the app user data.
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 4760818..c4aed95 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -71,6 +71,7 @@
         "ProcessInfoService.cpp",
         "ProcessState.cpp",
         "Static.cpp",
+        "Stability.cpp",
         "Status.cpp",
         "TextOutput.cpp",
         "IpPrefix.cpp",
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 1729d6a..221c002 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -81,6 +81,24 @@
     return target->transact(SHELL_COMMAND_TRANSACTION, send, &reply);
 }
 
+status_t IBinder::getExtension(sp<IBinder>* out) {
+    BBinder* local = this->localBinder();
+    if (local != nullptr) {
+        *out = local->getExtension();
+        return OK;
+    }
+
+    BpBinder* proxy = this->remoteBinder();
+    LOG_ALWAYS_FATAL_IF(proxy == nullptr);
+
+    Parcel data;
+    Parcel reply;
+    status_t status = transact(EXTENSION_TRANSACTION, data, &reply);
+    if (status != OK) return status;
+
+    return reply.readNullableStrongBinder(out);
+}
+
 // ---------------------------------------------------------------------------
 
 class BBinder::Extras
@@ -88,6 +106,7 @@
 public:
     // unlocked objects
     bool mRequestingSid = false;
+    sp<IBinder> mExtension;
 
     // for below objects
     Mutex mLock;
@@ -130,11 +149,15 @@
         case PING_TRANSACTION:
             err = pingBinder();
             break;
+        case EXTENSION_TRANSACTION:
+            err = reply->writeStrongBinder(getExtension());
+            break;
         default:
             err = onTransact(code, data, reply, flags);
             break;
     }
 
+    // In case this is being transacted on in the same process.
     if (reply != nullptr) {
         reply->setDataPosition(0);
     }
@@ -221,6 +244,17 @@
     e->mRequestingSid = true;
 }
 
+sp<IBinder> BBinder::getExtension() {
+    Extras* e = mExtras.load(std::memory_order_acquire);
+    if (e == nullptr) return nullptr;
+    return e->mExtension;
+}
+
+void BBinder::setExtension(const sp<IBinder>& extension) {
+    Extras* e = getOrCreateExtras();
+    e->mExtension = extension;
+}
+
 BBinder::~BBinder()
 {
     Extras* e = mExtras.load(std::memory_order_relaxed);
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 5ceb218..425ece3 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -21,6 +21,7 @@
 
 #include <binder/IPCThreadState.h>
 #include <binder/IResultReceiver.h>
+#include <binder/Stability.h>
 #include <cutils/compiler.h>
 #include <utils/Log.h>
 
@@ -213,9 +214,22 @@
 {
     // Once a binder has died, it will never come back to life.
     if (mAlive) {
+        // user transactions require a given stability level
+        // Cannot add requirement w/o SM update
+        // if (code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION) {
+        //     using android::internal::Stability;
+
+        //     auto stability = Stability::get(this);
+
+        //     if (CC_UNLIKELY(!Stability::check(stability, Stability::kLocalStability))) {
+        //         return BAD_TYPE;
+        //     }
+        // }
+
         status_t status = IPCThreadState::self()->transact(
             mHandle, code, data, reply, flags);
         if (status == DEAD_OBJECT) mAlive = 0;
+
         return status;
     }
 
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index aa9d188..485869e 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -35,6 +35,7 @@
 #include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
 #include <binder/ProcessState.h>
+#include <binder/Stability.h>
 #include <binder/Status.h>
 #include <binder/TextOutput.h>
 
@@ -164,14 +165,34 @@
     ALOGE("Invalid object type 0x%08x", obj.hdr.type);
 }
 
-inline static status_t finish_flatten_binder(
-    const sp<IBinder>& /*binder*/, const flat_binder_object& flat, Parcel* out)
+status_t Parcel::finishFlattenBinder(
+    const sp<IBinder>& /*binder*/, const flat_binder_object& flat)
 {
-    return out->writeObject(flat, false);
+    status_t status = writeObject(flat, false);
+    if (status != OK) return status;
+
+    // internal::Stability::tryMarkCompilationUnit(binder.get());
+    // Cannot change wire protocol w/o SM update
+    // return writeInt32(internal::Stability::get(binder.get()));
+    return OK;
 }
 
-static status_t flatten_binder(const sp<ProcessState>& /*proc*/,
-    const sp<IBinder>& binder, Parcel* out)
+status_t Parcel::finishUnflattenBinder(
+    const sp<IBinder>& binder, sp<IBinder>* out) const
+{
+    // int32_t stability;
+    // Cannot change wire protocol w/o SM update
+    // status_t status = readInt32(&stability);
+    // if (status != OK) return status;
+
+    // status = internal::Stability::set(binder.get(), stability, true /*log*/);
+    // if (status != OK) return status;
+
+    *out = binder;
+    return OK;
+}
+
+status_t Parcel::flattenBinder(const sp<IBinder>& binder)
 {
     flat_binder_object obj;
 
@@ -209,30 +230,24 @@
         obj.cookie = 0;
     }
 
-    return finish_flatten_binder(binder, obj, out);
+    return finishFlattenBinder(binder, obj);
 }
 
-inline static status_t finish_unflatten_binder(
-    BpBinder* /*proxy*/, const flat_binder_object& /*flat*/,
-    const Parcel& /*in*/)
+status_t Parcel::unflattenBinder(sp<IBinder>* out) const
 {
-    return NO_ERROR;
-}
-
-static status_t unflatten_binder(const sp<ProcessState>& proc,
-    const Parcel& in, sp<IBinder>* out)
-{
-    const flat_binder_object* flat = in.readObject(false);
+    const flat_binder_object* flat = readObject(false);
 
     if (flat) {
         switch (flat->hdr.type) {
-            case BINDER_TYPE_BINDER:
-                *out = reinterpret_cast<IBinder*>(flat->cookie);
-                return finish_unflatten_binder(nullptr, *flat, in);
-            case BINDER_TYPE_HANDLE:
-                *out = proc->getStrongProxyForHandle(flat->handle);
-                return finish_unflatten_binder(
-                    static_cast<BpBinder*>(out->get()), *flat, in);
+            case BINDER_TYPE_BINDER: {
+                sp<IBinder> binder = reinterpret_cast<IBinder*>(flat->cookie);
+                return finishUnflattenBinder(binder, out);
+            }
+            case BINDER_TYPE_HANDLE: {
+                sp<IBinder> binder =
+                    ProcessState::self()->getStrongProxyForHandle(flat->handle);
+                return finishUnflattenBinder(binder, out);
+            }
         }
     }
     return BAD_TYPE;
@@ -965,7 +980,7 @@
 
 status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
 {
-    return flatten_binder(ProcessState::self(), val, this);
+    return flattenBinder(val);
 }
 
 status_t Parcel::writeStrongBinderVector(const std::vector<sp<IBinder>>& val)
@@ -1782,8 +1797,8 @@
 
 const char* Parcel::readCString() const
 {
-    const size_t avail = mDataSize-mDataPos;
-    if (avail > 0) {
+    if (mDataPos < mDataSize) {
+        const size_t avail = mDataSize-mDataPos;
         const char* str = reinterpret_cast<const char*>(mData+mDataPos);
         // is the string's trailing NUL within the parcel's valid bounds?
         const char* eos = reinterpret_cast<const char*>(memchr(str, 0, avail));
@@ -1903,7 +1918,7 @@
 
 status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
 {
-    return unflatten_binder(ProcessState::self(), *this, val);
+    return unflattenBinder(val);
 }
 
 sp<IBinder> Parcel::readStrongBinder() const
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 1e1bc3a..07db50f 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -21,6 +21,7 @@
 #include <binder/BpBinder.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
+#include <binder/Stability.h>
 #include <cutils/atomic.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
@@ -109,7 +110,13 @@
 
 sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
 {
-    return getStrongProxyForHandle(0);
+    sp<IBinder> context = getStrongProxyForHandle(0);
+
+    // The root object is special since we get it directly from the driver, it is never
+    // written by Parcell::writeStrongBinder.
+    internal::Stability::tryMarkCompilationUnit(context.get());
+
+    return context;
 }
 
 void ProcessState::startThreadPool()
diff --git a/libs/binder/Stability.cpp b/libs/binder/Stability.cpp
new file mode 100644
index 0000000..b6f10c8
--- /dev/null
+++ b/libs/binder/Stability.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2019 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 <binder/Stability.h>
+
+namespace android {
+namespace internal {
+
+void Stability::markCompilationUnit(IBinder* binder) {
+    status_t result = set(binder, kLocalStability, true /*log*/);
+    LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
+}
+
+void Stability::markVintf(IBinder* binder) {
+    status_t result = set(binder, Level::VINTF, true /*log*/);
+    LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
+}
+
+void Stability::debugLogStability(const std::string& tag, const sp<IBinder>& binder) {
+    ALOGE("%s: stability is %s", tag.c_str(), stabilityString(get(binder.get())).c_str());
+}
+
+void Stability::markVndk(IBinder* binder) {
+    status_t result = set(binder, Level::VENDOR, true /*log*/);
+    LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
+}
+
+void Stability::tryMarkCompilationUnit(IBinder* binder) {
+    (void) set(binder, kLocalStability, false /*log*/);
+}
+
+status_t Stability::set(IBinder* binder, int32_t stability, bool log) {
+    Level currentStability = get(binder);
+
+    // null binder is always written w/ 'UNDECLARED' stability
+    if (binder == nullptr) {
+        if (stability == UNDECLARED) {
+            return OK;
+        } else {
+            if (log) {
+                ALOGE("Null binder written with stability %s.",
+                    stabilityString(stability).c_str());
+            }
+            return BAD_TYPE;
+        }
+    }
+
+    if (!isDeclaredStability(stability)) {
+        if (log) {
+            ALOGE("Can only set known stability, not %d.", stability);
+        }
+        return BAD_TYPE;
+    }
+
+    if (currentStability != Level::UNDECLARED && currentStability != stability) {
+        if (log) {
+            ALOGE("Interface being set with %s but it is already marked as %s.",
+                stabilityString(stability).c_str(), stabilityString(currentStability).c_str());
+        }
+        return BAD_TYPE;
+    }
+
+    if (currentStability == stability) return OK;
+
+    binder->attachObject(
+        reinterpret_cast<void*>(&Stability::get),
+        reinterpret_cast<void*>(stability),
+        nullptr /*cleanupCookie*/,
+        nullptr /*cleanup function*/);
+
+    return OK;
+}
+
+Stability::Level Stability::get(IBinder* binder) {
+    if (binder == nullptr) return UNDECLARED;
+
+    return static_cast<Level>(reinterpret_cast<intptr_t>(
+        binder->findObject(reinterpret_cast<void*>(&Stability::get))));
+}
+
+bool Stability::check(int32_t provided, Level required) {
+    bool stable = (provided & required) == required;
+
+    if (!isDeclaredStability(provided) && provided != UNDECLARED) {
+        ALOGE("Unknown stability when checking interface stability %d.", provided);
+
+        stable = false;
+    }
+
+    if (!stable) {
+        ALOGE("Cannot do a user transaction on a %s binder in a %s context.",
+            stabilityString(provided).c_str(),
+            stabilityString(required).c_str());
+    }
+
+    return stable;
+}
+
+bool Stability::isDeclaredStability(int32_t stability) {
+    return stability == VENDOR || stability == SYSTEM || stability == VINTF;
+}
+
+std::string Stability::stabilityString(int32_t stability) {
+    switch (stability) {
+        case Level::UNDECLARED: return "undeclared stability";
+        case Level::VENDOR: return "vendor stability";
+        case Level::SYSTEM: return "system stability";
+        case Level::VINTF: return "vintf stability";
+    }
+    return "unknown stability " + std::to_string(stability);
+}
+
+}  // namespace internal
+}  // namespace stability
\ No newline at end of file
diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp
index 8b33a56..0ad99ce 100644
--- a/libs/binder/Status.cpp
+++ b/libs/binder/Status.cpp
@@ -102,13 +102,23 @@
     // Skip over fat response headers.  Not used (or propagated) in native code.
     if (mException == EX_HAS_REPLY_HEADER) {
         // Note that the header size includes the 4 byte size field.
-        const int32_t header_start = parcel.dataPosition();
+        const size_t header_start = parcel.dataPosition();
+        // Get available size before reading more
+        const size_t header_avail = parcel.dataAvail();
+
         int32_t header_size;
         status = parcel.readInt32(&header_size);
         if (status != OK) {
             setFromStatusT(status);
             return status;
         }
+
+        if (header_size < 0 || static_cast<size_t>(header_size) > header_avail) {
+            android_errorWriteLog(0x534e4554, "132650049");
+            setFromStatusT(UNKNOWN_ERROR);
+            return UNKNOWN_ERROR;
+        }
+
         parcel.setDataPosition(header_start + header_size);
         // And fat response headers are currently only used when there are no
         // exceptions, so act like there was no error.
@@ -135,19 +145,36 @@
         setFromStatusT(status);
         return status;
     }
+    if (remote_stack_trace_header_size < 0 ||
+        static_cast<size_t>(remote_stack_trace_header_size) > parcel.dataAvail()) {
+
+        android_errorWriteLog(0x534e4554, "132650049");
+        setFromStatusT(UNKNOWN_ERROR);
+        return UNKNOWN_ERROR;
+    }
     parcel.setDataPosition(parcel.dataPosition() + remote_stack_trace_header_size);
 
     if (mException == EX_SERVICE_SPECIFIC) {
         status = parcel.readInt32(&mErrorCode);
     } else if (mException == EX_PARCELABLE) {
         // Skip over the blob of Parcelable data
-        const int32_t header_start = parcel.dataPosition();
+        const size_t header_start = parcel.dataPosition();
+        // Get available size before reading more
+        const size_t header_avail = parcel.dataAvail();
+
         int32_t header_size;
         status = parcel.readInt32(&header_size);
         if (status != OK) {
             setFromStatusT(status);
             return status;
         }
+
+        if (header_size < 0 || static_cast<size_t>(header_size) > header_avail) {
+            android_errorWriteLog(0x534e4554, "132650049");
+            setFromStatusT(UNKNOWN_ERROR);
+            return UNKNOWN_ERROR;
+        }
+
         parcel.setDataPosition(header_start + header_size);
     }
     if (status != OK) {
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 1537e69..1095c7f 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -38,7 +38,7 @@
     virtual status_t    transact(   uint32_t code,
                                     const Parcel& data,
                                     Parcel* reply,
-                                    uint32_t flags = 0);
+                                    uint32_t flags = 0) final;
 
     // NOLINTNEXTLINE(google-default-arguments)
     virtual status_t    linkToDeath(const sp<DeathRecipient>& recipient,
@@ -64,6 +64,10 @@
     // This must be called before the object is sent to another process. Not thread safe.
     void                setRequestingSid(bool requestSid);
 
+    sp<IBinder>         getExtension();
+    // This must be called before the object is sent to another process. Not thread safe.
+    void                setExtension(const sp<IBinder>& extension);
+
 protected:
     virtual             ~BBinder();
 
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index e71541b..28599f4 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -45,7 +45,7 @@
     virtual status_t    transact(   uint32_t code,
                                     const Parcel& data,
                                     Parcel* reply,
-                                    uint32_t flags = 0);
+                                    uint32_t flags = 0) final;
 
     // NOLINTNEXTLINE(google-default-arguments)
     virtual status_t    linkToDeath(const sp<DeathRecipient>& recipient,
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index aa44285..408037e 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -59,6 +59,7 @@
         SHELL_COMMAND_TRANSACTION = B_PACK_CHARS('_','C','M','D'),
         INTERFACE_TRANSACTION   = B_PACK_CHARS('_', 'N', 'T', 'F'),
         SYSPROPS_TRANSACTION    = B_PACK_CHARS('_', 'S', 'P', 'R'),
+        EXTENSION_TRANSACTION   = B_PACK_CHARS('_', 'E', 'X', 'T'),
 
         // Corresponds to TF_ONE_WAY -- an asynchronous call.
         FLAG_ONEWAY             = 0x00000001
@@ -86,6 +87,49 @@
                                          Vector<String16>& args, const sp<IShellCallback>& callback,
                                          const sp<IResultReceiver>& resultReceiver);
 
+    /**
+     * This allows someone to add their own additions to an interface without
+     * having to modify the original interface.
+     *
+     * For instance, imagine if we have this interface:
+     *     interface IFoo { void doFoo(); }
+     *
+     * If an unrelated owner (perhaps in a downstream codebase) wants to make a
+     * change to the interface, they have two options:
+     *
+     * A). Historical option that has proven to be BAD! Only the original
+     *     author of an interface should change an interface. If someone
+     *     downstream wants additional functionality, they should not ever
+     *     change the interface or use this method.
+     *
+     *    BAD TO DO:  interface IFoo {                       BAD TO DO
+     *    BAD TO DO:      void doFoo();                      BAD TO DO
+     *    BAD TO DO: +    void doBar(); // adding a method   BAD TO DO
+     *    BAD TO DO:  }                                      BAD TO DO
+     *
+     * B). Option that this method enables!
+     *     Leave the original interface unchanged (do not change IFoo!).
+     *     Instead, create a new interface in a downstream package:
+     *
+     *         package com.<name>; // new functionality in a new package
+     *         interface IBar { void doBar(); }
+     *
+     *     When registering the interface, add:
+     *         sp<MyFoo> foo = new MyFoo; // class in AOSP codebase
+     *         sp<MyBar> bar = new MyBar; // custom extension class
+     *         foo->setExtension(bar);    // use method in BBinder
+     *
+     *     Then, clients of IFoo can get this extension:
+     *         sp<IBinder> binder = ...;
+     *         sp<IFoo> foo = interface_cast<IFoo>(binder); // handle if null
+     *         sp<IBinder> barBinder;
+     *         ... handle error ... = binder->getExtension(&barBinder);
+     *         sp<IBar> bar = interface_cast<IBar>(barBinder);
+     *         // if bar is null, then there is no extension or a different
+     *         // type of extension
+     */
+    status_t                getExtension(sp<IBinder>* out);
+
     // NOLINTNEXTLINE(google-default-arguments)
     virtual status_t        transact(   uint32_t code,
                                         const Parcel& data,
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 3c56fcb..c8f82a3 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -67,7 +67,7 @@
     status_t            setDataSize(size_t size);
     void                setDataPosition(size_t pos) const;
     status_t            setDataCapacity(size_t size);
-    
+
     status_t            setData(const uint8_t* buffer, size_t len);
 
     status_t            appendFrom(const Parcel *parcel,
@@ -408,7 +408,13 @@
     void                initState();
     void                scanForFds() const;
     status_t            validateReadData(size_t len) const;
-                        
+
+    status_t            finishFlattenBinder(const sp<IBinder>& binder,
+                                            const flat_binder_object& flat);
+    status_t            finishUnflattenBinder(const sp<IBinder>& binder, sp<IBinder>* out) const;
+    status_t            flattenBinder(const sp<IBinder>& binder);
+    status_t            unflattenBinder(sp<IBinder>* out) const;
+
     template<class T>
     status_t            readAligned(T *pArg) const;
 
diff --git a/libs/binder/include/binder/Stability.h b/libs/binder/include/binder/Stability.h
new file mode 100644
index 0000000..f8240e4
--- /dev/null
+++ b/libs/binder/include/binder/Stability.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2019 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 <binder/IBinder.h>
+#include <string>
+
+namespace android {
+
+class BpBinder;
+class ProcessState;
+
+namespace internal {
+
+// WARNING: These APIs are only ever expected to be called by auto-generated code.
+//     Instead of calling them, you should set the stability of a .aidl interface
+class Stability final {
+public:
+    // WARNING: This is only ever expected to be called by auto-generated code. You likely want to
+    // change or modify the stability class of the interface you are using.
+    // This must be called as soon as the binder in question is constructed. No thread safety
+    // is provided.
+    // E.g. stability is according to libbinder compilation unit
+    static void markCompilationUnit(IBinder* binder);
+    // WARNING: This is only ever expected to be called by auto-generated code. You likely want to
+    // change or modify the stability class of the interface you are using.
+    // This must be called as soon as the binder in question is constructed. No thread safety
+    // is provided.
+    // E.g. stability is according to libbinder_ndk or Java SDK AND the interface
+    //     expressed here is guaranteed to be stable for multiple years (Stable AIDL)
+    static void markVintf(IBinder* binder);
+
+    // WARNING: for debugging only
+    static void debugLogStability(const std::string& tag, const sp<IBinder>& binder);
+
+    // WARNING: This is only ever expected to be called by auto-generated code or tests.
+    // You likely want to change or modify the stability of the interface you are using.
+    // This must be called as soon as the binder in question is constructed. No thread safety
+    // is provided.
+    // E.g. stability is according to libbinder_ndk or Java SDK AND the interface
+    //     expressed here is guaranteed to be stable for multiple years (Stable AIDL)
+    // If this is called when __ANDROID_VNDK__ is not defined, then it is UB and will likely
+    // break the device during GSI or other tests.
+    static void markVndk(IBinder* binder);
+
+private:
+    // Parcel needs to read/write stability level in an unstable format.
+    friend ::android::Parcel;
+
+    // only expose internal APIs inside of libbinder, for checking stability
+    friend ::android::BpBinder;
+
+    // so that it can mark the context object (only the root object doesn't go
+    // through Parcel)
+    friend ::android::ProcessState;
+
+    static void tryMarkCompilationUnit(IBinder* binder);
+
+    enum Level : int32_t {
+        UNDECLARED = 0,
+
+        VENDOR = 0b000011,
+        SYSTEM = 0b001100,
+        VINTF = 0b111111,
+    };
+
+#ifdef __ANDROID_VNDK__
+    static constexpr Level kLocalStability = Level::VENDOR;
+#else
+    static constexpr Level kLocalStability = Level::SYSTEM;
+#endif
+
+    // applies stability to binder if stability level is known
+    __attribute__((warn_unused_result))
+    static status_t set(IBinder* binder, int32_t stability, bool log);
+
+    static Level get(IBinder* binder);
+
+    static bool check(int32_t provided, Level required);
+
+    static bool isDeclaredStability(int32_t stability);
+    static std::string stabilityString(int32_t stability);
+
+    Stability();
+};
+
+}  // namespace internal
+}  // namespace android
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 6da3086..734a928 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-cc_library {
+cc_library_shared {
     name: "libbinder_ndk",
 
     export_include_dirs: [
         "include_ndk",
-        "include_apex",
+        "include_platform",
     ],
 
     cflags: [
@@ -33,6 +33,7 @@
         "ibinder_jni.cpp",
         "parcel.cpp",
         "process.cpp",
+        "stability.cpp",
         "status.cpp",
         "service_manager.cpp",
     ],
@@ -54,7 +55,7 @@
     version_script: "libbinder_ndk.map.txt",
     stubs: {
         symbol_file: "libbinder_ndk.map.txt",
-        versions: ["29"],
+        versions: ["29", "30"],
     },
 }
 
@@ -79,6 +80,6 @@
     symbol_file: "libbinder_ndk.map.txt",
     export_include_dirs: [
         "include_ndk",
-        "include_apex",
+        "include_platform",
     ],
 }
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index bd6886d..b06ca86 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -589,3 +589,40 @@
 
     recipient->decStrong(nullptr);
 }
+
+binder_status_t AIBinder_getExtension(AIBinder* binder, AIBinder** outExt) {
+    if (binder == nullptr || outExt == nullptr) {
+        if (outExt != nullptr) {
+            *outExt = nullptr;
+        }
+        return STATUS_UNEXPECTED_NULL;
+    }
+
+    sp<IBinder> ext;
+    status_t res = binder->getBinder()->getExtension(&ext);
+
+    if (res != android::OK) {
+        *outExt = nullptr;
+        return PruneStatusT(res);
+    }
+
+    sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(ext);
+    if (ret != nullptr) ret->incStrong(binder);
+
+    *outExt = ret.get();
+    return STATUS_OK;
+}
+
+binder_status_t AIBinder_setExtension(AIBinder* binder, AIBinder* ext) {
+    if (binder == nullptr || ext == nullptr) {
+        return STATUS_UNEXPECTED_NULL;
+    }
+
+    ABBinder* rawBinder = binder->asABBinder();
+    if (rawBinder == nullptr) {
+        return STATUS_INVALID_OPERATION;
+    }
+
+    rawBinder->setExtension(ext->getBinder());
+    return STATUS_OK;
+}
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index 80d1254..160739b 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -510,6 +510,76 @@
 void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) __INTRODUCED_IN(29);
 
 #endif  //__ANDROID_API__ >= __ANDROID_API_Q__
+
+#if __ANDROID_API__ >= __ANDROID_API_R__
+
+/**
+ * Gets the extension registered with AIBinder_setExtension.
+ *
+ * See AIBinder_setExtension.
+ *
+ * \param binder the object to get the extension of.
+ * \param outExt the returned extension object. Will be null if there is no extension set or
+ * non-null with one strong ref count.
+ *
+ * \return error of getting the interface (may be a transaction error if this is
+ * remote binder). STATUS_UNEXPECTED_NULL if binder is null.
+ */
+binder_status_t AIBinder_getExtension(AIBinder* binder, AIBinder** outExt) __INTRODUCED_IN(30);
+
+/**
+ * Gets the extension of a binder interface. This allows a downstream developer to add
+ * an extension to an interface without modifying its interface file. This should be
+ * called immediately when the object is created before it is passed to another thread.
+ * No thread safety is required.
+ *
+ * For instance, imagine if we have this interface:
+ *     interface IFoo { void doFoo(); }
+ *
+ * A). Historical option that has proven to be BAD! Only the original
+ *     author of an interface should change an interface. If someone
+ *     downstream wants additional functionality, they should not ever
+ *     change the interface or use this method.
+ *
+ *    BAD TO DO:  interface IFoo {                       BAD TO DO
+ *    BAD TO DO:      void doFoo();                      BAD TO DO
+ *    BAD TO DO: +    void doBar(); // adding a method   BAD TO DO
+ *    BAD TO DO:  }                                      BAD TO DO
+ *
+ * B). Option that this method enables.
+ *     Leave the original interface unchanged (do not change IFoo!).
+ *     Instead, create a new interface in a downstream package:
+ *
+ *         package com.<name>; // new functionality in a new package
+ *         interface IBar { void doBar(); }
+ *
+ *     When registering the interface, add:
+ *         std::shared_ptr<MyFoo> foo = new MyFoo; // class in AOSP codebase
+ *         std::shared_ptr<MyBar> bar = new MyBar; // custom extension class
+ *         ... = AIBinder_setExtension(foo->asBinder().get(), bar->asBinder().get());
+ *         // handle error
+ *
+ *     Then, clients of IFoo can get this extension:
+ *         SpAIBinder binder = ...;
+ *         std::shared_ptr<IFoo> foo = IFoo::fromBinder(binder); // handle if null
+ *         SpAIBinder barBinder;
+ *         ... = AIBinder_getExtension(barBinder.get());
+ *         // handle error
+ *         std::shared_ptr<IBar> bar = IBar::fromBinder(barBinder);
+ *         // type is checked with AIBinder_associateClass
+ *         // if bar is null, then there is no extension or a different
+ *         // type of extension
+ *
+ * \param binder the object to get the extension on. Must be local.
+ * \param ext the extension to set (binder will hold a strong reference to this)
+ *
+ * \return OK on success, STATUS_INVALID_OPERATION if binder is not local, STATUS_UNEXPECTED_NULL
+ * if either binder is null.
+ */
+binder_status_t AIBinder_setExtension(AIBinder* binder, AIBinder* ext) __INTRODUCED_IN(30);
+
+#endif  //__ANDROID_API__ >= __ANDROID_API_R__
+
 __END_DECLS
 
 /** @} */
diff --git a/libs/binder/ndk/include_apex/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
similarity index 100%
rename from libs/binder/ndk/include_apex/android/binder_manager.h
rename to libs/binder/ndk/include_platform/android/binder_manager.h
diff --git a/libs/binder/ndk/include_apex/android/binder_process.h b/libs/binder/ndk/include_platform/android/binder_process.h
similarity index 100%
rename from libs/binder/ndk/include_apex/android/binder_process.h
rename to libs/binder/ndk/include_platform/android/binder_process.h
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
new file mode 100644
index 0000000..e6aeb04
--- /dev/null
+++ b/libs/binder/ndk/include_platform/android/binder_stability.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 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
+
+#ifdef __ANDROID_VNDK__
+
+/**
+ * This interface has the stability of the vendor image.
+ */
+void AIBinder_markVendorStability(AIBinder* binder);
+
+static inline void AIBinder_markCompilationUnitStability(AIBinder* binder) {
+    AIBinder_markVendorStability(binder);
+}
+
+#else  // ndef defined __ANDROID_VNDK__
+
+/**
+ * This interface has the stability of the system image.
+ */
+void AIBinder_markSystemStability(AIBinder* binder);
+
+static inline void AIBinder_markCompilationUnitStability(AIBinder* binder) {
+    AIBinder_markSystemStability(binder);
+}
+
+#endif  // ifdef __ANDROID_VNDK__
+
+/**
+ * This interface has system<->vendor stability
+ */
+void AIBinder_markVintfStability(AIBinder* binder);
+
+__END_DECLS
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 4f685d1..d4d5387 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -98,3 +98,15 @@
   local:
     *;
 };
+
+LIBBINDER_NDK30 { # introduced=30
+  global:
+    AIBinder_getExtension;
+    AIBinder_setExtension;
+
+    AIBinder_markSystemStability; # apex
+    AIBinder_markVendorStability; # vndk
+    AIBinder_markVintfStability; # apex vndk
+  local:
+    *;
+};
diff --git a/libs/binder/ndk/stability.cpp b/libs/binder/ndk/stability.cpp
new file mode 100644
index 0000000..a5b3ece
--- /dev/null
+++ b/libs/binder/ndk/stability.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 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/binder_stability.h>
+
+#include <binder/Stability.h>
+#include "ibinder_internal.h"
+
+#include <log/log.h>
+
+using ::android::internal::Stability;
+
+#ifdef __ANDROID_VNDK__
+#error libbinder_ndk should only be built in a system context
+#endif
+
+#ifdef __ANDROID_NDK__
+#error libbinder_ndk should only be built in a system context
+#endif
+
+// explicit extern because symbol is only declared in header when __ANDROID_VNDK__
+extern "C" void AIBinder_markVendorStability(AIBinder* binder) {
+    Stability::markVndk(binder->getBinder().get());
+}
+
+void AIBinder_markSystemStability(AIBinder* binder) {
+    Stability::markCompilationUnit(binder->getBinder().get());
+}
+
+void AIBinder_markVintfStability(AIBinder* binder) {
+    Stability::markVintf(binder->getBinder().get());
+}
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
index 8cd4e03..bb1fe2f 100644
--- a/libs/binder/ndk/test/Android.bp
+++ b/libs/binder/ndk/test/Android.bp
@@ -44,10 +44,10 @@
         "libandroid_runtime_lazy",
         "libbase",
         "libbinder",
+        "libbinder_ndk",
         "libutils",
     ],
     static_libs: [
-        "libbinder_ndk",
         "test_libbinder_ndk_library",
     ],
 }
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 44a691d..bc457ce 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -137,3 +137,31 @@
     ],
     test_suites: ["device-tests"],
 }
+
+aidl_interface {
+    name: "binderStabilityTestIface",
+    srcs: [
+        "IBinderStabilityTest.aidl",
+    ],
+}
+
+cc_test {
+    name: "binderStabilityTest",
+    defaults: ["binder_test_defaults"],
+    srcs: [
+        "binderStabilityTest.cpp",
+    ],
+
+    shared_libs: [
+        "libbinder_ndk",
+        "libbinder",
+        "liblog",
+        "libutils",
+    ],
+    static_libs: [
+        "binderStabilityTestIface-cpp",
+        "binderStabilityTestIface-ndk_platform",
+    ],
+
+    test_suites: ["device-tests"],
+}
diff --git a/libs/binder/tests/IBinderStabilityTest.aidl b/libs/binder/tests/IBinderStabilityTest.aidl
new file mode 100644
index 0000000..36e1c2c
--- /dev/null
+++ b/libs/binder/tests/IBinderStabilityTest.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
+// THIS IS ONLY FOR TESTING!
+interface IBinderStabilityTest {
+    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
+    // THIS IS ONLY FOR TESTING!
+    void sendBinder(IBinder binder);
+
+    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
+    // THIS IS ONLY FOR TESTING!
+    void sendAndCallBinder(IBinder binder);
+
+    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
+    // THIS IS ONLY FOR TESTING!
+    IBinder returnNoStabilityBinder();
+
+    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
+    // THIS IS ONLY FOR TESTING!
+    IBinder returnLocalStabilityBinder();
+
+    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
+    // THIS IS ONLY FOR TESTING!
+    IBinder returnVintfStabilityBinder();
+
+    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
+    // THIS IS ONLY FOR TESTING!
+    IBinder returnVendorStabilityBinder();
+}
+// DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
+// THIS IS ONLY FOR TESTING!
+// Construct and return a binder with a specific stability
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 4f0c969..5f8887b 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -766,6 +766,24 @@
     EXPECT_TRUE(strong_from_weak == nullptr);
 }
 
+TEST_F(BinderLibTest, LocalGetExtension) {
+    sp<BBinder> binder = new BBinder();
+    sp<IBinder> ext = new BBinder();
+    binder->setExtension(ext);
+    EXPECT_EQ(ext, binder->getExtension());
+}
+
+TEST_F(BinderLibTest, RemoteGetExtension) {
+    sp<IBinder> server = addServer();
+    ASSERT_TRUE(server != nullptr);
+
+    sp<IBinder> extension;
+    EXPECT_EQ(NO_ERROR, server->getExtension(&extension));
+    ASSERT_NE(nullptr, extension.get());
+
+    EXPECT_EQ(NO_ERROR, extension->pingBinder());
+}
+
 TEST_F(BinderLibTest, CheckHandleZeroBinderHighBitsZeroCookie) {
     status_t ret;
     Parcel data, reply;
@@ -1170,6 +1188,13 @@
     BinderLibTestService* testServicePtr;
     {
         sp<BinderLibTestService> testService = new BinderLibTestService(index);
+
+        /*
+         * Normally would also contain functionality as well, but we are only
+         * testing the extension mechanism.
+         */
+        testService->setExtension(new BBinder());
+
         /*
          * We need this below, but can't hold a sp<> because it prevents the
          * node from being cleaned up automatically. It's safe in this case
diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp
new file mode 100644
index 0000000..0336b9e
--- /dev/null
+++ b/libs/binder/tests/binderStabilityTest.cpp
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2019 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/binder_manager.h>
+#include <android/binder_stability.h>
+#include <binder/Binder.h>
+#include <binder/IBinder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/Stability.h>
+#include <gtest/gtest.h>
+
+#include <sys/prctl.h>
+
+#include "aidl/BnBinderStabilityTest.h"
+#include "BnBinderStabilityTest.h"
+
+using namespace android;
+using namespace ndk;
+using android::binder::Status;
+using android::internal::Stability; // for testing only!
+
+const String16 kSystemStabilityServer = String16("binder_stability_test_service_system");
+
+// This is handwritten so that we can test different stability levels w/o having the AIDL
+// compiler assign them. Hand-writing binder interfaces is considered a bad practice
+// sanity reasons. YOU SHOULD DEFINE AN AIDL INTERFACE INSTEAD!
+class BadStableBinder : public BBinder {
+public:
+    static constexpr uint32_t USER_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION;
+    static String16 kDescriptor;
+
+    bool gotUserTransaction = false;
+
+    static status_t doUserTransaction(const sp<IBinder>& binder) {
+        Parcel data, reply;
+        data.writeInterfaceToken(kDescriptor);
+        return binder->transact(USER_TRANSACTION, data, &reply, 0/*flags*/);
+    }
+
+    status_t onTransact(uint32_t code,
+            const Parcel& data, Parcel* reply, uint32_t flags) override {
+        if (code == USER_TRANSACTION) {
+            // not interested in this kind of stability. Make sure
+            // we have a test failure
+            LOG_ALWAYS_FATAL_IF(!data.enforceInterface(kDescriptor));
+
+            gotUserTransaction = true;
+
+            ALOGE("binder stability: Got user transaction");
+            return OK;
+        }
+        return BBinder::onTransact(code, data, reply, flags);
+    }
+
+    static sp<BadStableBinder> undef() {
+        sp<BadStableBinder> iface = new BadStableBinder();
+        return iface;
+    }
+
+    static sp<BadStableBinder> system() {
+        sp<BadStableBinder> iface = new BadStableBinder();
+        Stability::markCompilationUnit(iface.get()); // <- for test only
+        return iface;
+    }
+
+    static sp<BadStableBinder> vintf() {
+        sp<BadStableBinder> iface = new BadStableBinder();
+        Stability::markVintf(iface.get()); // <- for test only
+        return iface;
+    }
+
+    static sp<BadStableBinder> vendor() {
+        sp<BadStableBinder> iface = new BadStableBinder();
+        Stability::markVndk(iface.get()); // <- for test only
+        return iface;
+    }
+};
+String16 BadStableBinder::kDescriptor = String16("BadStableBinder.test");
+
+// NO! NO! NO! Do not even think of doing something like this!
+// This is for testing! If a class like this was actually used in production,
+// it would ruin everything!
+class MyBinderStabilityTest : public BnBinderStabilityTest {
+public:
+    Status sendBinder(const sp<IBinder>& /*binder*/) override {
+        return Status::ok();
+    }
+    Status sendAndCallBinder(const sp<IBinder>& binder) override {
+        Stability::debugLogStability("sendAndCallBinder got binder", binder);
+        return Status::fromExceptionCode(BadStableBinder::doUserTransaction(binder));
+    }
+    Status returnNoStabilityBinder(sp<IBinder>* _aidl_return) override {
+        *_aidl_return = BadStableBinder::undef();
+        return Status::ok();
+    }
+    Status returnLocalStabilityBinder(sp<IBinder>* _aidl_return) override {
+        *_aidl_return = BadStableBinder::system();
+        return Status::ok();
+    }
+    Status returnVintfStabilityBinder(sp<IBinder>* _aidl_return) override {
+        *_aidl_return = BadStableBinder::vintf();
+        return Status::ok();
+    }
+    Status returnVendorStabilityBinder(sp<IBinder>* _aidl_return) override {
+        *_aidl_return = BadStableBinder::vendor();
+        return Status::ok();
+    }
+};
+
+TEST(BinderStability, CantCallVendorBinderInSystemContext) {
+    sp<IBinder> serverBinder = android::defaultServiceManager()->getService(kSystemStabilityServer);
+    auto server = interface_cast<IBinderStabilityTest>(serverBinder);
+
+    ASSERT_NE(nullptr, server.get());
+    ASSERT_NE(nullptr, IInterface::asBinder(server)->remoteBinder());
+
+    EXPECT_TRUE(server->sendBinder(BadStableBinder::undef()).isOk());
+    EXPECT_TRUE(server->sendBinder(BadStableBinder::system()).isOk());
+    EXPECT_TRUE(server->sendBinder(BadStableBinder::vintf()).isOk());
+    EXPECT_TRUE(server->sendBinder(BadStableBinder::vendor()).isOk());
+
+    {
+        sp<BadStableBinder> binder = BadStableBinder::undef();
+        EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
+        EXPECT_TRUE(binder->gotUserTransaction);
+    }
+    {
+        sp<BadStableBinder> binder = BadStableBinder::system();
+        EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
+        EXPECT_TRUE(binder->gotUserTransaction);
+    }
+    {
+        sp<BadStableBinder> binder = BadStableBinder::vintf();
+        EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
+        EXPECT_TRUE(binder->gotUserTransaction);
+    }
+    {
+        // !!! user-defined transaction may not be stable for remote server !!!
+        // !!! so, it does not work !!!
+        sp<BadStableBinder> binder = BadStableBinder::vendor();
+        EXPECT_EQ(BAD_TYPE, server->sendAndCallBinder(binder).exceptionCode());
+        EXPECT_FALSE(binder->gotUserTransaction);
+    }
+
+    sp<IBinder> out;
+    EXPECT_TRUE(server->returnNoStabilityBinder(&out).isOk());
+    ASSERT_NE(nullptr, out.get());
+    EXPECT_EQ(OK, out->pingBinder());
+    EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out));
+
+    EXPECT_TRUE(server->returnLocalStabilityBinder(&out).isOk());
+    ASSERT_NE(nullptr, out.get());
+    EXPECT_EQ(OK, out->pingBinder());
+    EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out));
+
+    EXPECT_TRUE(server->returnVintfStabilityBinder(&out).isOk());
+    ASSERT_NE(nullptr, out.get());
+    EXPECT_EQ(OK, out->pingBinder());
+    EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out));
+
+    EXPECT_TRUE(server->returnVendorStabilityBinder(&out).isOk());
+    ASSERT_NE(nullptr, out.get());
+
+    // !!! libbinder-defined transaction works !!!
+    EXPECT_EQ(OK, out->pingBinder());
+
+    // !!! user-defined transaction may not be stable !!!
+    // !!! so, it does not work !!!
+    EXPECT_EQ(BAD_TYPE, BadStableBinder::doUserTransaction(out));
+}
+
+// This is handwritten so that we can test different stability levels w/o having the AIDL
+// compiler assign them. Hand-writing binder interfaces is considered a bad practice
+// sanity reasons. YOU SHOULD DEFINE AN AIDL INTERFACE INSTEAD!
+
+struct NdkBinderStable_DataClass {
+    bool gotUserTransaction = false;
+};
+void* NdkBadStableBinder_Class_onCreate(void* args) {
+    LOG_ALWAYS_FATAL_IF(args != nullptr, "Takes no args");
+    return static_cast<void*>(new NdkBinderStable_DataClass);
+}
+void NdkBadStableBinder_Class_onDestroy(void* userData) {
+    delete static_cast<NdkBinderStable_DataClass*>(userData);
+}
+NdkBinderStable_DataClass* NdkBadStableBinder_getUserData(AIBinder* binder) {
+    LOG_ALWAYS_FATAL_IF(binder == nullptr);
+    void* userData = AIBinder_getUserData(binder);
+    LOG_ALWAYS_FATAL_IF(userData == nullptr, "null data - binder is remote?");
+
+    return static_cast<NdkBinderStable_DataClass*>(userData);
+}
+binder_status_t NdkBadStableBinder_Class_onTransact(
+    AIBinder* binder, transaction_code_t code, const AParcel* /*in*/, AParcel* /*out*/) {
+
+    if (code == BadStableBinder::USER_TRANSACTION) {
+        ALOGE("ndk binder stability: Got user transaction");
+        NdkBadStableBinder_getUserData(binder)->gotUserTransaction = true;
+        return STATUS_OK;
+    }
+
+    return STATUS_UNKNOWN_TRANSACTION;
+}
+
+static AIBinder_Class* kNdkBadStableBinder =
+    AIBinder_Class_define(String8(BadStableBinder::kDescriptor).c_str(),
+                          NdkBadStableBinder_Class_onCreate,
+                          NdkBadStableBinder_Class_onDestroy,
+                          NdkBadStableBinder_Class_onTransact);
+
+// for testing only to get around __ANDROID_VNDK__ guard.
+extern "C" void AIBinder_markVendorStability(AIBinder* binder); // <- BAD DO NOT COPY
+
+TEST(BinderStability, NdkCantCallVendorBinderInSystemContext) {
+    SpAIBinder binder = SpAIBinder(AServiceManager_getService(
+        String8(kSystemStabilityServer).c_str()));
+
+    std::shared_ptr<aidl::IBinderStabilityTest> remoteServer =
+        aidl::IBinderStabilityTest::fromBinder(binder);
+
+    ASSERT_NE(nullptr, remoteServer.get());
+
+    SpAIBinder comp = SpAIBinder(AIBinder_new(kNdkBadStableBinder, nullptr /*args*/));
+    EXPECT_TRUE(remoteServer->sendBinder(comp).isOk());
+    EXPECT_TRUE(remoteServer->sendAndCallBinder(comp).isOk());
+    EXPECT_TRUE(NdkBadStableBinder_getUserData(comp.get())->gotUserTransaction);
+
+    SpAIBinder vendor = SpAIBinder(AIBinder_new(kNdkBadStableBinder, nullptr /*args*/));
+    AIBinder_markVendorStability(vendor.get());
+    EXPECT_TRUE(remoteServer->sendBinder(vendor).isOk());
+    EXPECT_FALSE(remoteServer->sendAndCallBinder(vendor).isOk());
+    EXPECT_FALSE(NdkBadStableBinder_getUserData(vendor.get())->gotUserTransaction);
+}
+
+class MarksStabilityInConstructor : public BBinder {
+public:
+    static bool gDestructed;
+
+    MarksStabilityInConstructor() {
+        Stability::markCompilationUnit(this);
+    }
+    ~MarksStabilityInConstructor() {
+        gDestructed = true;
+    }
+};
+bool MarksStabilityInConstructor::gDestructed = false;
+
+TEST(BinderStability, MarkingObjectNoDestructTest) {
+    ASSERT_FALSE(MarksStabilityInConstructor::gDestructed);
+
+    // best practice is to put this directly in an sp, but for this test, we
+    // want to explicitly check what happens before that happens
+    MarksStabilityInConstructor* binder = new MarksStabilityInConstructor();
+    ASSERT_FALSE(MarksStabilityInConstructor::gDestructed);
+
+    sp<MarksStabilityInConstructor> binderSp = binder;
+    ASSERT_FALSE(MarksStabilityInConstructor::gDestructed);
+
+    binderSp = nullptr;
+    ASSERT_TRUE(MarksStabilityInConstructor::gDestructed);
+}
+
+TEST(BinderStability, RemarkDies) {
+    ASSERT_DEATH({
+        sp<IBinder> binder = new BBinder();
+        Stability::markCompilationUnit(binder.get()); // <-- only called for tests
+        Stability::markVndk(binder.get()); // <-- only called for tests
+    }, "Should only mark known object.");
+}
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+
+    if (fork() == 0) {
+        // child process
+        prctl(PR_SET_PDEATHSIG, SIGHUP);
+
+        sp<IBinder> server = new MyBinderStabilityTest;
+        android::defaultServiceManager()->addService(kSystemStabilityServer, server);
+
+        IPCThreadState::self()->joinThreadPool(true);
+        exit(1);  // should not reach
+    }
+
+    // This is not racey. Just giving these services some time to register before we call
+    // getService which sleeps for much longer...
+    usleep(10000);
+
+    return RUN_ALL_TESTS();
+}
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 3db8a39..bb5c151 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1306,7 +1306,7 @@
     bool active = swapchain->surface.swapchain_handle == swapchain_handle;
     ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr;
 
-    if (swapchain->frame_timestamps_enabled) {
+    if (window && swapchain->frame_timestamps_enabled) {
         native_window_enable_frame_timestamps(window, false);
     }
     for (uint32_t i = 0; i < swapchain->num_images; i++)