Merge "libbinder_rs: Treat previously associated Binder as remote"
diff --git a/cmds/bugreportz/bugreportz.cpp b/cmds/bugreportz/bugreportz.cpp
index ded0ed3..203d748 100644
--- a/cmds/bugreportz/bugreportz.cpp
+++ b/cmds/bugreportz/bugreportz.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+#include "bugreportz.h"
+
+#include <android-base/file.h>
+#include <android-base/strings.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -22,11 +26,6 @@
 
 #include <string>
 
-#include <android-base/file.h>
-#include <android-base/strings.h>
-
-#include "bugreportz.h"
-
 static constexpr char BEGIN_PREFIX[] = "BEGIN:";
 static constexpr char PROGRESS_PREFIX[] = "PROGRESS:";
 
@@ -70,6 +69,30 @@
     }
     // Process final line, in case it didn't finish with newline
     write_line(line, show_progress);
+    return EXIT_SUCCESS;
+}
 
+int bugreportz_stream(int s) {
+    while (1) {
+        char buffer[65536];
+        ssize_t bytes_read = TEMP_FAILURE_RETRY(read(s, buffer, sizeof(buffer)));
+        if (bytes_read == 0) {
+            break;
+        } else if (bytes_read == -1) {
+            // EAGAIN really means time out, so change the errno.
+            if (errno == EAGAIN) {
+                errno = ETIMEDOUT;
+            }
+            printf("FAIL:Bugreport read terminated abnormally (%s)\n", strerror(errno));
+            return EXIT_FAILURE;
+        }
+
+        if (!android::base::WriteFully(android::base::borrowed_fd(STDOUT_FILENO), buffer,
+                                       bytes_read)) {
+            printf("Failed to write data to stdout: trying to send %zd bytes (%s)\n", bytes_read,
+                   strerror(errno));
+            return EXIT_FAILURE;
+        }
+    }
     return EXIT_SUCCESS;
 }
diff --git a/cmds/bugreportz/bugreportz.h b/cmds/bugreportz/bugreportz.h
index 7af289b..cdeceae 100644
--- a/cmds/bugreportz/bugreportz.h
+++ b/cmds/bugreportz/bugreportz.h
@@ -19,4 +19,8 @@
 // Ownership of the socket is not transferred.
 int bugreportz(int s, bool show_progress);
 
+// Calls dumpstate using the given socket and write the file content to stdout
+// instead of file location. Ownership of the socket is not transferred.
+int bugreportz_stream(int s);
+
 #endif  // BUGREPORTZ_H
diff --git a/cmds/bugreportz/main.cpp b/cmds/bugreportz/main.cpp
index 1d48e08..cd2652c 100644
--- a/cmds/bugreportz/main.cpp
+++ b/cmds/bugreportz/main.cpp
@@ -26,13 +26,14 @@
 
 #include "bugreportz.h"
 
-static constexpr char VERSION[] = "1.1";
+static constexpr char VERSION[] = "1.2";
 
 static void show_usage() {
     fprintf(stderr,
-            "usage: bugreportz [-hpv]\n"
+            "usage: bugreportz [-hpsv]\n"
             "  -h: to display this help message\n"
             "  -p: display progress\n"
+            "  -s: stream content to standard output\n"
             "  -v: to display the version\n"
             "  or no arguments to generate a zipped bugreport\n");
 }
@@ -43,10 +44,11 @@
 
 int main(int argc, char* argv[]) {
     bool show_progress = false;
+    bool stream_data = false;
     if (argc > 1) {
         /* parse arguments */
         int c;
-        while ((c = getopt(argc, argv, "hpv")) != -1) {
+        while ((c = getopt(argc, argv, "hpsv")) != -1) {
             switch (c) {
                 case 'h':
                     show_usage();
@@ -54,6 +56,9 @@
                 case 'p':
                     show_progress = true;
                     break;
+                case 's':
+                    stream_data = true;
+                    break;
                 case 'v':
                     show_version();
                     return EXIT_SUCCESS;
@@ -75,7 +80,11 @@
     // should be reused instead.
 
     // Start the dumpstatez service.
-    property_set("ctl.start", "dumpstatez");
+    if (stream_data) {
+        property_set("ctl.start", "dumpstate");
+    } else {
+        property_set("ctl.start", "dumpstatez");
+    }
 
     // Socket will not be available until service starts.
     int s = -1;
@@ -103,7 +112,12 @@
                 strerror(errno));
     }
 
-    int ret = bugreportz(s, show_progress);
+    int ret;
+    if (stream_data) {
+        ret = bugreportz_stream(s);
+    } else {
+        ret = bugreportz(s, show_progress);
+    }
 
     if (close(s) == -1) {
         fprintf(stderr, "WARNING: error closing socket: %s\n", strerror(errno));
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 616304c..67527b2 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -719,6 +719,9 @@
     return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
 }
 
+// Opens a socket and returns its file descriptor.
+static int open_socket(const char* service);
+
 Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
 }
 
@@ -2286,20 +2289,18 @@
 
 static void ShowUsage() {
     fprintf(stderr,
-            "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-d] [-p] "
-            "[-z] [-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
+            "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
+            "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
             "  -h: display this help message\n"
             "  -b: play sound file instead of vibrate, at beginning of job\n"
             "  -e: play sound file instead of vibrate, at end of job\n"
             "  -o: write to custom directory (only in limited mode)\n"
-            "  -d: append date to filename\n"
             "  -p: capture screenshot to filename.png\n"
-            "  -z: generate zipped file\n"
-            "  -s: write output to control socket (for init)\n"
-            "  -S: write file location to control socket (for init; requires -z)\n"
+            "  -s: write zipped file to control socket (for init)\n"
+            "  -S: write file location to control socket (for init)\n"
             "  -q: disable vibrate\n"
             "  -P: send broadcast when started and do progress updates\n"
-            "  -R: take bugreport in remote mode (requires -z and -d, shouldn't be used with -P)\n"
+            "  -R: take bugreport in remote mode (shouldn't be used with -P)\n"
             "  -w: start binder service and make it wait for a call to startBugreport\n"
             "  -L: output limited information that is safe for submission in feedback reports\n"
             "  -v: prints the dumpstate header and exit\n");
@@ -2398,21 +2399,17 @@
 
 /*
  * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
- * if we are writing zip files and adds the version file.
+ * and adds the version file. Return false if zip_file could not be open to write.
  */
-static void PrepareToWriteToFile() {
+static bool PrepareToWriteToFile() {
     MaybeResolveSymlink(&ds.bugreport_internal_dir_);
 
     std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
     std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
     ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
-    if (ds.options_->do_add_date) {
-        char date[80];
-        strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
-        ds.name_ = date;
-    } else {
-        ds.name_ = "undated";
-    }
+    char date[80];
+    strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
+    ds.name_ = date;
 
     if (ds.options_->telephony_only) {
         ds.base_name_ += "-telephony";
@@ -2439,18 +2436,17 @@
         destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
         ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
 
-    if (ds.options_->do_zip_file) {
-        ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
-        MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
-        create_parent_dirs(ds.path_.c_str());
-        ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
-        if (ds.zip_file == nullptr) {
-            MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
-        } else {
-            ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
-        }
-        ds.AddTextZipEntry("version.txt", ds.version_);
+    ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
+    MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
+    create_parent_dirs(ds.path_.c_str());
+    ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
+    if (ds.zip_file == nullptr) {
+        MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
+        return false;
     }
+    ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
+    ds.AddTextZipEntry("version.txt", ds.version_);
+    return true;
 }
 
 /*
@@ -2458,14 +2454,9 @@
  * printing zipped file status, etc.
  */
 static void FinalizeFile() {
-    bool do_text_file = true;
-    if (ds.options_->do_zip_file) {
-        if (!ds.FinishZipFile()) {
-            MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
-            do_text_file = true;
-        } else {
-            do_text_file = false;
-        }
+    bool do_text_file = !ds.FinishZipFile();
+    if (do_text_file) {
+        MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
     }
 
     std::string final_path = ds.path_;
@@ -2474,7 +2465,9 @@
         android::os::CopyFileToFile(ds.path_, final_path);
     }
 
-    if (ds.options_->use_control_socket) {
+    if (ds.options_->stream_to_socket) {
+        android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
+    } else if (ds.options_->progress_updates_to_socket) {
         if (do_text_file) {
             dprintf(ds.control_socket_fd_,
                     "FAIL:could not create zip file, check %s "
@@ -2530,7 +2523,6 @@
             break;
         case Dumpstate::BugreportMode::BUGREPORT_WEAR:
             options->do_progress_updates = true;
-            options->do_zip_file = true;
             options->do_screenshot = is_screenshot_requested;
             options->dumpstate_hal_mode = DumpstateMode::WEAR;
             break;
@@ -2543,7 +2535,6 @@
             break;
         case Dumpstate::BugreportMode::BUGREPORT_WIFI:
             options->wifi_only = true;
-            options->do_zip_file = true;
             options->do_screenshot = false;
             options->dumpstate_hal_mode = DumpstateMode::WIFI;
             break;
@@ -2554,11 +2545,11 @@
 
 static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
     MYLOGI(
-        "do_zip_file: %d do_vibrate: %d use_socket: %d use_control_socket: %d do_screenshot: %d "
+        "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
         "is_remote_mode: %d show_header_only: %d telephony_only: %d "
         "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s dumpstate_hal_mode: %s "
         "limited_only: %d args: %s\n",
-        options.do_zip_file, options.do_vibrate, options.use_socket, options.use_control_socket,
+        options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
         options.do_screenshot, options.is_remote_mode, options.show_header_only,
         options.telephony_only, options.wifi_only,
         options.do_progress_updates, options.bugreport_fd.get(), options.bugreport_mode.c_str(),
@@ -2569,11 +2560,6 @@
                                         const android::base::unique_fd& bugreport_fd_in,
                                         const android::base::unique_fd& screenshot_fd_in,
                                         bool is_screenshot_requested) {
-    // In the new API world, date is always added; output is always a zip file.
-    // TODO(111441001): remove these options once they are obsolete.
-    do_add_date = true;
-    do_zip_file = true;
-
     // Duplicate the fds because the passed in fds don't outlive the binder transaction.
     bugreport_fd.reset(dup(bugreport_fd_in.get()));
     screenshot_fd.reset(dup(screenshot_fd_in.get()));
@@ -2587,18 +2573,20 @@
     while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
         switch (c) {
             // clang-format off
-            case 'd': do_add_date = true;            break;
-            case 'z': do_zip_file = true;            break;
             case 'o': out_dir = optarg;              break;
-            case 's': use_socket = true;             break;
-            case 'S': use_control_socket = true;     break;
+            case 's': stream_to_socket = true;       break;
+            case 'S': progress_updates_to_socket = true;    break;
             case 'v': show_header_only = true;       break;
             case 'q': do_vibrate = false;            break;
             case 'p': do_screenshot = true;          break;
             case 'P': do_progress_updates = true;    break;
             case 'R': is_remote_mode = true;         break;
             case 'L': limited_only = true;           break;
-            case 'V':                                break;  // compatibility no-op
+            case 'V':
+            case 'd':
+            case 'z':
+                // compatibility no-op
+                break;
             case 'w':
                 // This was already processed
                 break;
@@ -2627,19 +2615,15 @@
 }
 
 bool Dumpstate::DumpOptions::ValidateOptions() const {
-    if (bugreport_fd.get() != -1 && !do_zip_file) {
+    if (bugreport_fd.get() != -1 && stream_to_socket) {
         return false;
     }
 
-    if ((do_zip_file || do_add_date || do_progress_updates) && !OutputToFile()) {
+    if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
         return false;
     }
 
-    if (use_control_socket && !do_zip_file) {
-        return false;
-    }
-
-    if (is_remote_mode && (do_progress_updates || !do_zip_file || !do_add_date)) {
+    if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
         return false;
     }
     return true;
@@ -2714,11 +2698,9 @@
  * The temporary bugreport is then populated via printfs, dumping contents of files and
  * output of commands to stdout.
  *
- * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
- * text file.
+ * A bunch of other files and dumps are added to the zip archive.
  *
- * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
- * gets added to the archive.
+ * The temporary bugreport file and the log file also get added to the archive.
  *
  * Bugreports are first generated in a local directory and later copied to the caller's fd
  * or directory if supplied.
@@ -2766,14 +2748,9 @@
     MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
             calling_uid, calling_package.c_str());
 
-    // Redirect output if needed
-    bool is_redirecting = options_->OutputToFile();
-
     // TODO: temporarily set progress until it's part of the Dumpstate constructor
     std::string stats_path =
-        is_redirecting
-            ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
-            : "";
+        android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
     progress_.reset(new Progress(stats_path));
 
     if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
@@ -2796,35 +2773,33 @@
 
     // If we are going to use a socket, do it as early as possible
     // to avoid timeouts from bugreport.
-    if (options_->use_socket) {
-        if (!redirect_to_socket(stdout, "dumpstate")) {
-            return ERROR;
-        }
-    }
-
-    if (options_->use_control_socket) {
+    if (options_->stream_to_socket || options_->progress_updates_to_socket) {
         MYLOGD("Opening control socket\n");
-        control_socket_fd_ = open_socket("dumpstate");
+        control_socket_fd_ = open_socket_fn_("dumpstate");
         if (control_socket_fd_ == -1) {
             return ERROR;
         }
-        options_->do_progress_updates = 1;
+        if (options_->progress_updates_to_socket) {
+            options_->do_progress_updates = 1;
+        }
     }
 
-    if (is_redirecting) {
-        PrepareToWriteToFile();
+    if (!PrepareToWriteToFile()) {
+        return ERROR;
+    }
 
-        if (options_->do_progress_updates) {
-            // clang-format off
-            std::vector<std::string> am_args = {
-                 "--receiver-permission", "android.permission.DUMP",
-            };
-            // clang-format on
-            // Send STARTED broadcast for apps that listen to bugreport generation events
-            SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
-            if (options_->use_control_socket) {
-                dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
-            }
+    // Interactive, wear & telephony modes are default to true.
+    // and may enable from cli option or when using control socket
+    if (options_->do_progress_updates) {
+        // clang-format off
+        std::vector<std::string> am_args = {
+                "--receiver-permission", "android.permission.DUMP",
+        };
+        // clang-format on
+        // Send STARTED broadcast for apps that listen to bugreport generation events
+        SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
+        if (options_->progress_updates_to_socket) {
+            dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
         }
     }
 
@@ -2839,40 +2814,38 @@
         Vibrate(150);
     }
 
-    if (options_->do_zip_file && zip_file != nullptr) {
+    if (zip_file != nullptr) {
         if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
             MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
-                   strerror(errno));
+                    strerror(errno));
         }
     }
 
     int dup_stdout_fd;
     int dup_stderr_fd;
-    if (is_redirecting) {
-        // Redirect stderr to log_path_ for debugging.
-        TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
-        if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
-            return ERROR;
-        }
-        if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
-            MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
-                   strerror(errno));
-        }
+    // Redirect stderr to log_path_ for debugging.
+    TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
+    if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
+        return ERROR;
+    }
+    if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
+        MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
+                strerror(errno));
+    }
 
-        // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
-        // moved into zip file later, if zipping.
-        TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
-        // TODO: why not write to a file instead of stdout to overcome this problem?
-        /* TODO: rather than generating a text file now and zipping it later,
-           it would be more efficient to redirect stdout to the zip entry
-           directly, but the libziparchive doesn't support that option yet. */
-        if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
-            return ERROR;
-        }
-        if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
-            MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
-                   tmp_path_.c_str(), strerror(errno));
-        }
+    // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
+    // moved into zip file later, if zipping.
+    TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
+    // TODO: why not write to a file instead of stdout to overcome this problem?
+    /* TODO: rather than generating a text file now and zipping it later,
+        it would be more efficient to redirect stdout to the zip entry
+        directly, but the libziparchive doesn't support that option yet. */
+    if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
+        return ERROR;
+    }
+    if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
+        MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
+                tmp_path_.c_str(), strerror(errno));
     }
 
     // Don't buffer stdout
@@ -2926,14 +2899,10 @@
     }
 
     /* close output if needed */
-    if (is_redirecting) {
-        TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
-    }
+    TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
 
     // Zip the (now complete) .tmp file within the internal directory.
-    if (options_->OutputToFile()) {
-        FinalizeFile();
-    }
+    FinalizeFile();
 
     // Share the final file with the caller if the user has consented or Shell is the caller.
     Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
@@ -2976,11 +2945,9 @@
     progress_->Save();
     MYLOGI("done (id %d)\n", id_);
 
-    if (is_redirecting) {
-        TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
-    }
+    TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
 
-    if (options_->use_control_socket && control_socket_fd_ != -1) {
+    if (control_socket_fd_ != -1) {
         MYLOGD("Closing control socket\n");
         close(control_socket_fd_);
     }
@@ -3051,10 +3018,7 @@
 }
 
 void Dumpstate::EnableParallelRunIfNeeded() {
-    // The thread pool needs to create temporary files to receive dump results.
-    // That's why we only enable it when the bugreport client chooses to output
-    // to a file.
-    if (!PropertiesHelper::IsParallelRun() || !options_->OutputToFile()) {
+    if (!PropertiesHelper::IsParallelRun()) {
         return;
     }
     dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
@@ -3199,7 +3163,8 @@
       options_(new Dumpstate::DumpOptions()),
       last_reported_percent_progress_(0),
       version_(version),
-      now_(time(nullptr)) {
+      now_(time(nullptr)),
+      open_socket_fn_(open_socket) {
 }
 
 Dumpstate& Dumpstate::GetInstance() {
@@ -3833,7 +3798,7 @@
     RunCommand(title, dumpsys, options, false, out_fd);
 }
 
-int open_socket(const char *service) {
+static int open_socket(const char* service) {
     int s = android_get_control_socket(service);
     if (s < 0) {
         MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
@@ -3868,19 +3833,6 @@
     return fd;
 }
 
-/* redirect output to a service control socket */
-bool redirect_to_socket(FILE* redirect, const char* service) {
-    int fd = open_socket(service);
-    if (fd == -1) {
-        return false;
-    }
-    fflush(redirect);
-    // TODO: handle dup2 failure
-    TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
-    close(fd);
-    return true;
-}
-
 // TODO: should call is_valid_output_file and/or be merged into it.
 void create_parent_dirs(const char *path) {
     char *chp = const_cast<char *> (path);
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 9582c9d..efe06dc 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -54,6 +54,7 @@
 
 class DumpstateTest;
 class ProgressTest;
+class ZippedBugReportStreamTest;
 
 }  // namespace dumpstate
 }  // namespace os
@@ -197,6 +198,7 @@
  */
 class Dumpstate {
     friend class android::os::dumpstate::DumpstateTest;
+    friend class android::os::dumpstate::ZippedBugReportStreamTest;
 
   public:
     enum RunStatus { OK, HELP, INVALID_INPUT, ERROR, USER_CONSENT_DENIED, USER_CONSENT_TIMED_OUT };
@@ -388,12 +390,11 @@
      * Structure to hold options that determine the behavior of dumpstate.
      */
     struct DumpOptions {
-        bool do_add_date = false;
-        bool do_zip_file = false;
         bool do_vibrate = true;
-        // Writes bugreport content to a socket; only flatfile format is supported.
-        bool use_socket = false;
-        bool use_control_socket = false;
+        // Writes bugreport zipped file to a socket.
+        bool stream_to_socket = false;
+        // Writes generation progress updates to a socket.
+        bool progress_updates_to_socket = false;
         bool do_screenshot = false;
         bool is_screenshot_copied = false;
         bool is_remote_mode = false;
@@ -434,13 +435,6 @@
         /* Returns true if the options set so far are consistent. */
         bool ValidateOptions() const;
 
-        /* Returns if options specified require writing bugreport to a file */
-        bool OutputToFile() const {
-            // If we are not writing to socket, we will write to a file. If bugreport_fd is
-            // specified, it is preferred. If not bugreport is written to /bugreports.
-            return !use_socket;
-        }
-
         /* Returns if options specified require writing to custom file location */
         bool OutputToCustomFile() {
             // Custom location is only honored in limited mode.
@@ -466,7 +460,8 @@
 
     std::unique_ptr<Progress> progress_;
 
-    // When set, defines a socket file-descriptor use to report progress to bugreportz.
+    // When set, defines a socket file-descriptor use to report progress to bugreportz
+    // or to stream the zipped file to.
     int control_socket_fd_ = -1;
 
     // Bugreport format version;
@@ -478,8 +473,8 @@
     // `bugreport-BUILD_ID`.
     std::string base_name_;
 
-    // Name is the suffix part of the bugreport files - it's typically the date (when invoked with
-    // `-d`), but it could be changed by the user..
+    // Name is the suffix part of the bugreport files - it's typically the date,
+    // but it could be changed by the user..
     std::string name_;
 
     std::string bugreport_internal_dir_ = DUMPSTATE_DIRECTORY;
@@ -568,6 +563,8 @@
     // called by Shell.
     RunStatus CopyBugreportIfUserConsented(int32_t calling_uid);
 
+    std::function<int(const char *)> open_socket_fn_;
+
     // Used by GetInstance() only.
     explicit Dumpstate(const std::string& version = VERSION_CURRENT);
 
@@ -601,16 +598,6 @@
 int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
                int (*dump_from_fd)(const char* title, const char* path, int fd));
 
-/** opens a socket and returns its file descriptor */
-int open_socket(const char *service);
-
-/*
- * Redirects 'redirect' to a service control socket.
- *
- * Returns true if redirect succeeds.
- */
-bool redirect_to_socket(FILE* redirect, const char* service);
-
 /*
  * Redirects 'redirect' to a file indicated by 'path', truncating it.
  *
diff --git a/cmds/dumpstate/dumpstate.rc b/cmds/dumpstate/dumpstate.rc
index e491a4b..a80da4e 100644
--- a/cmds/dumpstate/dumpstate.rc
+++ b/cmds/dumpstate/dumpstate.rc
@@ -11,7 +11,7 @@
 
 # dumpstatez generates a zipped bugreport but also uses a socket to print the file location once
 # it is finished.
-service dumpstatez /system/bin/dumpstate -S -d -z
+service dumpstatez /system/bin/dumpstate -S
     socket dumpstate stream 0660 shell log
     class main
     disabled
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index 1c6583e..23c0d95 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -212,9 +212,7 @@
     static void GenerateBugreport() {
         // clang-format off
         char* argv[] = {
-            (char*)"dumpstate",
-            (char*)"-d",
-            (char*)"-z"
+            (char*)"dumpstate"
         };
         // clang-format on
         sp<DumpstateListener> listener(new DumpstateListener(dup(fileno(stdout)), sections));
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 6b93692..306069f 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "dumpstate"
-#include <cutils/log.h>
+#define LOG_TAG "dumpstate_test"
 
 #include "DumpstateInternal.h"
 #include "DumpstateService.h"
@@ -24,6 +23,7 @@
 #include "DumpPool.h"
 
 #include <gmock/gmock.h>
+#include <gmock/gmock-matchers.h>
 #include <gtest/gtest.h>
 
 #include <fcntl.h>
@@ -39,7 +39,9 @@
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 #include <android/hardware/dumpstate/1.1/types.h>
+#include <cutils/log.h>
 #include <cutils/properties.h>
+#include <ziparchive/zip_archive.h>
 
 namespace android {
 namespace os {
@@ -176,11 +178,9 @@
 
     EXPECT_EQ(status, Dumpstate::RunStatus::OK);
 
-    EXPECT_FALSE(options_.do_add_date);
-    EXPECT_FALSE(options_.do_zip_file);
     EXPECT_EQ("", options_.out_dir);
-    EXPECT_FALSE(options_.use_socket);
-    EXPECT_FALSE(options_.use_control_socket);
+    EXPECT_FALSE(options_.stream_to_socket);
+    EXPECT_FALSE(options_.progress_updates_to_socket);
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_TRUE(options_.do_vibrate);
     EXPECT_FALSE(options_.do_screenshot);
@@ -195,17 +195,13 @@
     char* argv[] = {
         const_cast<char*>("dumpstatez"),
         const_cast<char*>("-S"),
-        const_cast<char*>("-d"),
-        const_cast<char*>("-z"),
     };
     // clang-format on
 
     Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
 
     EXPECT_EQ(status, Dumpstate::RunStatus::OK);
-    EXPECT_TRUE(options_.do_add_date);
-    EXPECT_TRUE(options_.do_zip_file);
-    EXPECT_TRUE(options_.use_control_socket);
+    EXPECT_TRUE(options_.progress_updates_to_socket);
 
     // Other options retain default values
     EXPECT_TRUE(options_.do_vibrate);
@@ -213,7 +209,7 @@
     EXPECT_FALSE(options_.do_screenshot);
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
-    EXPECT_FALSE(options_.use_socket);
+    EXPECT_FALSE(options_.stream_to_socket);
     EXPECT_FALSE(options_.limited_only);
     EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
 }
@@ -229,13 +225,11 @@
     Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
 
     EXPECT_EQ(status, Dumpstate::RunStatus::OK);
-    EXPECT_TRUE(options_.use_socket);
+    EXPECT_TRUE(options_.stream_to_socket);
 
     // Other options retain default values
     EXPECT_TRUE(options_.do_vibrate);
-    EXPECT_FALSE(options_.do_add_date);
-    EXPECT_FALSE(options_.do_zip_file);
-    EXPECT_FALSE(options_.use_control_socket);
+    EXPECT_FALSE(options_.progress_updates_to_socket);
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_FALSE(options_.do_screenshot);
     EXPECT_FALSE(options_.do_progress_updates);
@@ -246,105 +240,93 @@
 
 TEST_F(DumpOptionsTest, InitializeFullBugReport) {
     options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_FULL, fd, fd, true);
-    EXPECT_TRUE(options_.do_add_date);
     EXPECT_TRUE(options_.do_screenshot);
-    EXPECT_TRUE(options_.do_zip_file);
     EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::FULL);
 
     // Other options retain default values
     EXPECT_TRUE(options_.do_vibrate);
-    EXPECT_FALSE(options_.use_control_socket);
+    EXPECT_FALSE(options_.progress_updates_to_socket);
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
-    EXPECT_FALSE(options_.use_socket);
+    EXPECT_FALSE(options_.stream_to_socket);
     EXPECT_FALSE(options_.limited_only);
 }
 
 TEST_F(DumpOptionsTest, InitializeInteractiveBugReport) {
     options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, fd, fd, true);
-    EXPECT_TRUE(options_.do_add_date);
-    EXPECT_TRUE(options_.do_zip_file);
     EXPECT_TRUE(options_.do_progress_updates);
     EXPECT_TRUE(options_.do_screenshot);
     EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::INTERACTIVE);
 
     // Other options retain default values
     EXPECT_TRUE(options_.do_vibrate);
-    EXPECT_FALSE(options_.use_control_socket);
+    EXPECT_FALSE(options_.progress_updates_to_socket);
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_FALSE(options_.is_remote_mode);
-    EXPECT_FALSE(options_.use_socket);
+    EXPECT_FALSE(options_.stream_to_socket);
     EXPECT_FALSE(options_.limited_only);
 }
 
 TEST_F(DumpOptionsTest, InitializeRemoteBugReport) {
     options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_REMOTE, fd, fd, false);
-    EXPECT_TRUE(options_.do_add_date);
-    EXPECT_TRUE(options_.do_zip_file);
     EXPECT_TRUE(options_.is_remote_mode);
     EXPECT_FALSE(options_.do_vibrate);
     EXPECT_FALSE(options_.do_screenshot);
     EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::REMOTE);
 
     // Other options retain default values
-    EXPECT_FALSE(options_.use_control_socket);
+    EXPECT_FALSE(options_.progress_updates_to_socket);
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_FALSE(options_.do_progress_updates);
-    EXPECT_FALSE(options_.use_socket);
+    EXPECT_FALSE(options_.stream_to_socket);
     EXPECT_FALSE(options_.limited_only);
 }
 
 TEST_F(DumpOptionsTest, InitializeWearBugReport) {
     options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WEAR, fd, fd, true);
-    EXPECT_TRUE(options_.do_add_date);
     EXPECT_TRUE(options_.do_screenshot);
-    EXPECT_TRUE(options_.do_zip_file);
     EXPECT_TRUE(options_.do_progress_updates);
     EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::WEAR);
 
     // Other options retain default values
     EXPECT_TRUE(options_.do_vibrate);
-    EXPECT_FALSE(options_.use_control_socket);
+    EXPECT_FALSE(options_.progress_updates_to_socket);
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_FALSE(options_.is_remote_mode);
-    EXPECT_FALSE(options_.use_socket);
+    EXPECT_FALSE(options_.stream_to_socket);
     EXPECT_FALSE(options_.limited_only);
 }
 
 TEST_F(DumpOptionsTest, InitializeTelephonyBugReport) {
     options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_TELEPHONY, fd, fd, false);
-    EXPECT_TRUE(options_.do_add_date);
     EXPECT_FALSE(options_.do_screenshot);
-    EXPECT_TRUE(options_.do_zip_file);
     EXPECT_TRUE(options_.telephony_only);
     EXPECT_TRUE(options_.do_progress_updates);
     EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::CONNECTIVITY);
 
     // Other options retain default values
     EXPECT_TRUE(options_.do_vibrate);
-    EXPECT_FALSE(options_.use_control_socket);
+    EXPECT_FALSE(options_.progress_updates_to_socket);
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_FALSE(options_.is_remote_mode);
-    EXPECT_FALSE(options_.use_socket);
+    EXPECT_FALSE(options_.stream_to_socket);
     EXPECT_FALSE(options_.limited_only);
 }
 
 TEST_F(DumpOptionsTest, InitializeWifiBugReport) {
     options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WIFI, fd, fd, false);
-    EXPECT_TRUE(options_.do_add_date);
     EXPECT_FALSE(options_.do_screenshot);
-    EXPECT_TRUE(options_.do_zip_file);
     EXPECT_TRUE(options_.wifi_only);
     EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::WIFI);
 
     // Other options retain default values
     EXPECT_TRUE(options_.do_vibrate);
-    EXPECT_FALSE(options_.use_control_socket);
+    EXPECT_FALSE(options_.progress_updates_to_socket);
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
-    EXPECT_FALSE(options_.use_socket);
+    EXPECT_FALSE(options_.stream_to_socket);
     EXPECT_FALSE(options_.limited_only);
 }
 
@@ -353,8 +335,6 @@
     char* argv[] = {
         const_cast<char*>("dumpstatez"),
         const_cast<char*>("-S"),
-        const_cast<char*>("-d"),
-        const_cast<char*>("-z"),
         const_cast<char*>("-q"),
         const_cast<char*>("-L"),
         const_cast<char*>("-o abc")
@@ -364,9 +344,7 @@
     Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
 
     EXPECT_EQ(status, Dumpstate::RunStatus::OK);
-    EXPECT_TRUE(options_.do_add_date);
-    EXPECT_TRUE(options_.do_zip_file);
-    EXPECT_TRUE(options_.use_control_socket);
+    EXPECT_TRUE(options_.progress_updates_to_socket);
     EXPECT_FALSE(options_.do_vibrate);
     EXPECT_TRUE(options_.limited_only);
     EXPECT_EQ(" abc", std::string(options_.out_dir));
@@ -376,7 +354,7 @@
     EXPECT_FALSE(options_.do_screenshot);
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
-    EXPECT_FALSE(options_.use_socket);
+    EXPECT_FALSE(options_.stream_to_socket);
     EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
 }
 
@@ -393,18 +371,16 @@
     Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
 
     EXPECT_EQ(status, Dumpstate::RunStatus::OK);
-    EXPECT_TRUE(options_.do_add_date);
     EXPECT_TRUE(options_.do_screenshot);
-    EXPECT_TRUE(options_.do_zip_file);
     EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
 
     // Other options retain default values
     EXPECT_TRUE(options_.do_vibrate);
-    EXPECT_FALSE(options_.use_control_socket);
+    EXPECT_FALSE(options_.progress_updates_to_socket);
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
-    EXPECT_FALSE(options_.use_socket);
+    EXPECT_FALSE(options_.stream_to_socket);
     EXPECT_FALSE(options_.wifi_only);
     EXPECT_FALSE(options_.limited_only);
 }
@@ -413,8 +389,6 @@
     // clang-format off
     char* argv[] = {
         const_cast<char*>("dumpstate"),
-        const_cast<char*>("-d"),
-        const_cast<char*>("-z"),
         const_cast<char*>("-s"),
         const_cast<char*>("-S"),
 
@@ -424,11 +398,9 @@
     Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
 
     EXPECT_EQ(status, Dumpstate::RunStatus::OK);
-    EXPECT_TRUE(options_.do_add_date);
-    EXPECT_TRUE(options_.do_zip_file);
     // TODO: Maybe we should trim the filename
-    EXPECT_TRUE(options_.use_socket);
-    EXPECT_TRUE(options_.use_control_socket);
+    EXPECT_TRUE(options_.stream_to_socket);
+    EXPECT_TRUE(options_.progress_updates_to_socket);
 
     // Other options retain default values
     EXPECT_FALSE(options_.show_header_only);
@@ -462,10 +434,8 @@
     EXPECT_TRUE(options_.is_remote_mode);
 
     // Other options retain default values
-    EXPECT_FALSE(options_.do_add_date);
-    EXPECT_FALSE(options_.do_zip_file);
-    EXPECT_FALSE(options_.use_socket);
-    EXPECT_FALSE(options_.use_control_socket);
+    EXPECT_FALSE(options_.stream_to_socket);
+    EXPECT_FALSE(options_.progress_updates_to_socket);
     EXPECT_FALSE(options_.limited_only);
     EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
 }
@@ -498,40 +468,31 @@
     EXPECT_EQ(status, Dumpstate::RunStatus::INVALID_INPUT);
 }
 
-TEST_F(DumpOptionsTest, ValidateOptionsNeedOutfile1) {
-    options_.do_zip_file = true;
-    // Writing to socket = !writing to file.
-    options_.use_socket = true;
+TEST_F(DumpOptionsTest, ValidateOptionsSocketUsage1) {
+    options_.progress_updates_to_socket = true;
+    options_.stream_to_socket = true;
     EXPECT_FALSE(options_.ValidateOptions());
 
-    options_.use_socket = false;
+    options_.stream_to_socket = false;
     EXPECT_TRUE(options_.ValidateOptions());
 }
 
-TEST_F(DumpOptionsTest, ValidateOptionsNeedOutfile2) {
+TEST_F(DumpOptionsTest, ValidateOptionsSocketUsage2) {
     options_.do_progress_updates = true;
     // Writing to socket = !writing to file.
-    options_.use_socket = true;
+    options_.stream_to_socket = true;
     EXPECT_FALSE(options_.ValidateOptions());
 
-    options_.use_socket = false;
-    EXPECT_TRUE(options_.ValidateOptions());
-}
-
-TEST_F(DumpOptionsTest, ValidateOptionsNeedZipfile) {
-    options_.use_control_socket = true;
-    EXPECT_FALSE(options_.ValidateOptions());
-
-    options_.do_zip_file = true;
+    options_.stream_to_socket = false;
     EXPECT_TRUE(options_.ValidateOptions());
 }
 
 TEST_F(DumpOptionsTest, ValidateOptionsRemoteMode) {
+    options_.do_progress_updates = true;
     options_.is_remote_mode = true;
     EXPECT_FALSE(options_.ValidateOptions());
 
-    options_.do_zip_file = true;
-    options_.do_add_date = true;
+    options_.do_progress_updates = false;
     EXPECT_TRUE(options_.ValidateOptions());
 }
 
@@ -1018,23 +979,13 @@
     ds.listener_.clear();
 }
 
-TEST_F(DumpstateTest, DumpPool_withOutputToFileAndParallelRunEnabled_notNull) {
-    ds.options_->use_socket = false;
+TEST_F(DumpstateTest, DumpPool_withParallelRunEnabled_notNull) {
     SetParallelRun(true);
     EnableParallelRunIfNeeded();
-    EXPECT_TRUE(ds.options_->OutputToFile());
     EXPECT_TRUE(ds.zip_entry_tasks_);
     EXPECT_TRUE(ds.dump_pool_);
 }
 
-TEST_F(DumpstateTest, DumpPool_withNotOutputToFile_isNull) {
-    ds.options_->use_socket = true;
-    EnableParallelRunIfNeeded();
-    EXPECT_FALSE(ds.options_->OutputToFile());
-    EXPECT_FALSE(ds.zip_entry_tasks_);
-    EXPECT_FALSE(ds.dump_pool_);
-}
-
 TEST_F(DumpstateTest, DumpPool_withParallelRunDisabled_isNull) {
     SetParallelRun(false);
     EnableParallelRunIfNeeded();
@@ -1042,6 +993,69 @@
     EXPECT_FALSE(ds.dump_pool_);
 }
 
+class ZippedBugReportStreamTest : public DumpstateBaseTest {
+  public:
+    void SetUp() {
+        DumpstateBaseTest::SetUp();
+        ds_.options_.reset(new Dumpstate::DumpOptions());
+    }
+    void TearDown() {
+        CloseArchive(handle_);
+    }
+
+    // Set bugreport mode and options before here.
+    void GenerateBugreport() {
+        ds_.Initialize();
+        EXPECT_EQ(Dumpstate::RunStatus::OK, ds_.Run(/*calling_uid=*/-1, /*calling_package=*/""));
+    }
+
+    // Most bugreports droproot, ensure the file can be opened by shell to verify file content.
+    void CreateFd(const std::string& path, android::base::unique_fd* out_fd) {
+        out_fd->reset(TEMP_FAILURE_RETRY(open(path.c_str(),
+                                              O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
+                                              S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
+        ASSERT_GE(out_fd->get(), 0) << "could not create FD for path " << path;
+    }
+
+    void VerifyEntry(const ZipArchiveHandle archive, const std::string_view entry_name,
+                     ZipEntry* data) {
+        int32_t e = FindEntry(archive, entry_name, data);
+        EXPECT_EQ(0, e) << ErrorCodeString(e) << " entry name: " << entry_name;
+    }
+
+    // While testing dumpstate in process, using STDOUT may get confused about
+    // the internal fd redirection. Redirect to a dedicate fd to save content.
+    void RedirectOutputToFd(android::base::unique_fd& ufd) {
+        ds_.open_socket_fn_ = [&](const char*) -> int { return ufd.release(); };
+    };
+
+    Dumpstate& ds_ = Dumpstate::GetInstance();
+    ZipArchiveHandle handle_;
+};
+
+// Generate a quick wifi report redirected to a file, open it and verify entry exist.
+TEST_F(ZippedBugReportStreamTest, StreamWifiReport) {
+    std::string out_path = kTestDataPath + "out.zip";
+    android::base::unique_fd out_fd;
+    CreateFd(out_path, &out_fd);
+    ds_.options_->wifi_only = true;
+    ds_.options_->stream_to_socket = true;
+    RedirectOutputToFd(out_fd);
+
+    GenerateBugreport();
+    OpenArchive(out_path.c_str(), &handle_);
+
+    ZipEntry entry;
+    VerifyEntry(handle_, "main_entry.txt", &entry);
+    std::string bugreport_txt_name;
+    bugreport_txt_name.resize(entry.uncompressed_length);
+    ExtractToMemory(handle_, &entry, reinterpret_cast<uint8_t*>(bugreport_txt_name.data()),
+                    entry.uncompressed_length);
+    EXPECT_THAT(bugreport_txt_name,
+                testing::ContainsRegex("(bugreport-.+-wifi(-[[:digit:]]+){6}\\.txt)"));
+    VerifyEntry(handle_, bugreport_txt_name, &entry);
+}
+
 class DumpstateServiceTest : public DumpstateBaseTest {
   public:
     DumpstateService dss;
diff --git a/data/etc/android.hardware.uwb.xml b/data/etc/android.hardware.uwb.xml
new file mode 100644
index 0000000..794ba27
--- /dev/null
+++ b/data/etc/android.hardware.uwb.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<!-- Adds the feature indicating support for the Ultra Wideband API -->
+<permissions>
+    <feature name="android.hardware.uwb" />
+</permissions>
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index f4f036e..ee0259d 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -144,6 +144,7 @@
     cflags: [
         "-Wall",
         "-Wextra",
+        "-Wextra-semi",
         "-Werror",
         "-Wzero-as-null-pointer-constant",
         "-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION",
diff --git a/libs/binder/IActivityManager.cpp b/libs/binder/IActivityManager.cpp
index 1eb5363..b81995c 100644
--- a/libs/binder/IActivityManager.cpp
+++ b/libs/binder/IActivityManager.cpp
@@ -108,6 +108,6 @@
 
 // ------------------------------------------------------------------------------------
 
-IMPLEMENT_META_INTERFACE(ActivityManager, "android.app.IActivityManager");
+IMPLEMENT_META_INTERFACE(ActivityManager, "android.app.IActivityManager")
 
 } // namespace android
diff --git a/libs/binder/IAppOpsCallback.cpp b/libs/binder/IAppOpsCallback.cpp
index b9eb281..2b3f462 100644
--- a/libs/binder/IAppOpsCallback.cpp
+++ b/libs/binder/IAppOpsCallback.cpp
@@ -43,7 +43,7 @@
     }
 };
 
-IMPLEMENT_META_INTERFACE(AppOpsCallback, "com.android.internal.app.IAppOpsCallback");
+IMPLEMENT_META_INTERFACE(AppOpsCallback, "com.android.internal.app.IAppOpsCallback")
 
 // ----------------------------------------------------------------------
 
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index cd78866..1af5ab8 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -159,7 +159,7 @@
     }
 };
 
-IMPLEMENT_META_INTERFACE(AppOpsService, "com.android.internal.app.IAppOpsService");
+IMPLEMENT_META_INTERFACE(AppOpsService, "com.android.internal.app.IAppOpsService")
 
 // ----------------------------------------------------------------------
 
diff --git a/libs/binder/IBatteryStats.cpp b/libs/binder/IBatteryStats.cpp
index a47dbac..d0085df 100644
--- a/libs/binder/IBatteryStats.cpp
+++ b/libs/binder/IBatteryStats.cpp
@@ -130,7 +130,7 @@
 
 };
 
-IMPLEMENT_META_INTERFACE(BatteryStats, "com.android.internal.app.IBatteryStats");
+IMPLEMENT_META_INTERFACE(BatteryStats, "com.android.internal.app.IBatteryStats")
 
 // ----------------------------------------------------------------------
 
diff --git a/libs/binder/IMediaResourceMonitor.cpp b/libs/binder/IMediaResourceMonitor.cpp
index 5f3d670..f5fa817 100644
--- a/libs/binder/IMediaResourceMonitor.cpp
+++ b/libs/binder/IMediaResourceMonitor.cpp
@@ -38,7 +38,7 @@
     }
 };
 
-IMPLEMENT_META_INTERFACE(MediaResourceMonitor, "android.media.IMediaResourceMonitor");
+IMPLEMENT_META_INTERFACE(MediaResourceMonitor, "android.media.IMediaResourceMonitor")
 
 // ----------------------------------------------------------------------
 
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index d8b44f9..cca8f81 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -223,7 +223,7 @@
 
 // ---------------------------------------------------------------------------
 
-IMPLEMENT_META_INTERFACE(Memory, "android.utils.IMemory");
+IMPLEMENT_META_INTERFACE(Memory, "android.utils.IMemory")
 
 BnMemory::BnMemory() {
 }
@@ -388,7 +388,7 @@
 
 // ---------------------------------------------------------------------------
 
-IMPLEMENT_META_INTERFACE(MemoryHeap, "android.utils.IMemoryHeap");
+IMPLEMENT_META_INTERFACE(MemoryHeap, "android.utils.IMemoryHeap")
 
 BnMemoryHeap::BnMemoryHeap() {
 }
diff --git a/libs/binder/IPermissionController.cpp b/libs/binder/IPermissionController.cpp
index d9bf3cc..f94f413 100644
--- a/libs/binder/IPermissionController.cpp
+++ b/libs/binder/IPermissionController.cpp
@@ -103,7 +103,7 @@
     }
 };
 
-IMPLEMENT_META_INTERFACE(PermissionController, "android.os.IPermissionController");
+IMPLEMENT_META_INTERFACE(PermissionController, "android.os.IPermissionController")
 
 // ----------------------------------------------------------------------
 
diff --git a/libs/binder/IProcessInfoService.cpp b/libs/binder/IProcessInfoService.cpp
index a38a27a..570edb9 100644
--- a/libs/binder/IProcessInfoService.cpp
+++ b/libs/binder/IProcessInfoService.cpp
@@ -84,7 +84,7 @@
     }
 };
 
-IMPLEMENT_META_INTERFACE(ProcessInfoService, "android.os.IProcessInfoService");
+IMPLEMENT_META_INTERFACE(ProcessInfoService, "android.os.IProcessInfoService")
 
 // ----------------------------------------------------------------------
 
diff --git a/libs/binder/IResultReceiver.cpp b/libs/binder/IResultReceiver.cpp
index 556288c..cd92217 100644
--- a/libs/binder/IResultReceiver.cpp
+++ b/libs/binder/IResultReceiver.cpp
@@ -42,7 +42,7 @@
     }
 };
 
-IMPLEMENT_META_INTERFACE(ResultReceiver, "com.android.internal.os.IResultReceiver");
+IMPLEMENT_META_INTERFACE(ResultReceiver, "com.android.internal.os.IResultReceiver")
 
 // ----------------------------------------------------------------------
 
diff --git a/libs/binder/IShellCallback.cpp b/libs/binder/IShellCallback.cpp
index a3e2b67..86dd5c4 100644
--- a/libs/binder/IShellCallback.cpp
+++ b/libs/binder/IShellCallback.cpp
@@ -52,7 +52,7 @@
     }
 };
 
-IMPLEMENT_META_INTERFACE(ShellCallback, "com.android.internal.os.IShellCallback");
+IMPLEMENT_META_INTERFACE(ShellCallback, "com.android.internal.os.IShellCallback")
 
 // ----------------------------------------------------------------------
 
diff --git a/libs/binder/IUidObserver.cpp b/libs/binder/IUidObserver.cpp
index 4714234..a1b08db 100644
--- a/libs/binder/IUidObserver.cpp
+++ b/libs/binder/IUidObserver.cpp
@@ -71,7 +71,7 @@
 
 // ----------------------------------------------------------------------
 
-IMPLEMENT_META_INTERFACE(UidObserver, "android.app.IUidObserver");
+IMPLEMENT_META_INTERFACE(UidObserver, "android.app.IUidObserver")
 
 // ----------------------------------------------------------------------
 
diff --git a/libs/binder/PermissionCache.cpp b/libs/binder/PermissionCache.cpp
index 75a6d22..6eae5ef 100644
--- a/libs/binder/PermissionCache.cpp
+++ b/libs/binder/PermissionCache.cpp
@@ -27,7 +27,7 @@
 
 // ----------------------------------------------------------------------------
 
-ANDROID_SINGLETON_STATIC_INSTANCE(PermissionCache) ;
+ANDROID_SINGLETON_STATIC_INSTANCE(PermissionCache)
 
 // ----------------------------------------------------------------------------
 
diff --git a/libs/binder/ProcessInfoService.cpp b/libs/binder/ProcessInfoService.cpp
index 00d6eef..f75141e 100644
--- a/libs/binder/ProcessInfoService.cpp
+++ b/libs/binder/ProcessInfoService.cpp
@@ -99,6 +99,6 @@
     }
 }
 
-ANDROID_SINGLETON_STATIC_INSTANCE(ProcessInfoService);
+ANDROID_SINGLETON_STATIC_INSTANCE(ProcessInfoService)
 
 } // namespace android
diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp
index db0f1c7..565f2e2 100644
--- a/libs/binder/Static.cpp
+++ b/libs/binder/Static.cpp
@@ -33,7 +33,7 @@
 {
 public:
     LogTextOutput() : BufferedTextOutput(MULTITHREADED) { }
-    virtual ~LogTextOutput() { };
+    virtual ~LogTextOutput() { }
 
 protected:
     virtual status_t writeLines(const struct iovec& vec, size_t N)
@@ -49,7 +49,7 @@
 {
 public:
     explicit FdTextOutput(int fd) : BufferedTextOutput(MULTITHREADED), mFD(fd) { }
-    virtual ~FdTextOutput() { };
+    virtual ~FdTextOutput() { }
 
 protected:
     virtual status_t writeLines(const struct iovec& vec, size_t N)
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index a0e28d2..2735315 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -28,7 +28,7 @@
 
 namespace internal {
 class Stability;
-};
+}
 
 using binder_proxy_limit_callback = void(*)(int);
 
diff --git a/libs/binder/include/binder/IShellCallback.h b/libs/binder/include/binder/IShellCallback.h
index 17e34db..6d3fe4a 100644
--- a/libs/binder/include/binder/IShellCallback.h
+++ b/libs/binder/include/binder/IShellCallback.h
@@ -25,7 +25,7 @@
 class IShellCallback : public IInterface
 {
 public:
-    DECLARE_META_INTERFACE(ShellCallback);
+    DECLARE_META_INTERFACE(ShellCallback)
 
     virtual int openFile(const String16& path, const String16& seLinuxContext,
             const String16& mode) = 0;
diff --git a/libs/binder/include/binder/IpPrefix.h b/libs/binder/include/binder/IpPrefix.h
index c1cd3c2..a8faa3f 100644
--- a/libs/binder/include/binder/IpPrefix.h
+++ b/libs/binder/include/binder/IpPrefix.h
@@ -73,8 +73,8 @@
 private:
     union InternalUnion {
         InternalUnion() = default;
-        explicit InternalUnion(const struct in6_addr &addr):mIn6Addr(addr) { };
-        explicit InternalUnion(const struct in_addr &addr):mInAddr(addr) { };
+        explicit InternalUnion(const struct in6_addr &addr):mIn6Addr(addr) { }
+        explicit InternalUnion(const struct in_addr &addr):mInAddr(addr) { }
         struct in6_addr mIn6Addr;
         struct in_addr mInAddr;
     } mUnion;
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 4b2d50d..cfe1f3a 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -131,7 +131,7 @@
     status_t            writeString8(const char* str, size_t len);
     status_t            writeString16(const String16& str);
     status_t            writeString16(const std::optional<String16>& str);
-    status_t            writeString16(const std::unique_ptr<String16>& str);
+    status_t            writeString16(const std::unique_ptr<String16>& str) __attribute__((deprecated("use std::optional version instead")));
     status_t            writeString16(const char16_t* str, size_t len);
     status_t            writeStrongBinder(const sp<IBinder>& val);
     status_t            writeInt32Array(size_t len, const int32_t *val);
@@ -143,48 +143,48 @@
     // Take a UTF8 encoded string, convert to UTF16, write it to the parcel.
     status_t            writeUtf8AsUtf16(const std::string& str);
     status_t            writeUtf8AsUtf16(const std::optional<std::string>& str);
-    status_t            writeUtf8AsUtf16(const std::unique_ptr<std::string>& str);
+    status_t            writeUtf8AsUtf16(const std::unique_ptr<std::string>& str) __attribute__((deprecated("use std::optional version instead")));
 
     status_t            writeByteVector(const std::optional<std::vector<int8_t>>& val);
-    status_t            writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val);
+    status_t            writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val) __attribute__((deprecated("use std::optional version instead")));
     status_t            writeByteVector(const std::vector<int8_t>& val);
     status_t            writeByteVector(const std::optional<std::vector<uint8_t>>& val);
-    status_t            writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val);
+    status_t            writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val) __attribute__((deprecated("use std::optional version instead")));
     status_t            writeByteVector(const std::vector<uint8_t>& val);
     status_t            writeInt32Vector(const std::optional<std::vector<int32_t>>& val);
-    status_t            writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val);
+    status_t            writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val) __attribute__((deprecated("use std::optional version instead")));
     status_t            writeInt32Vector(const std::vector<int32_t>& val);
     status_t            writeInt64Vector(const std::optional<std::vector<int64_t>>& val);
-    status_t            writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val);
+    status_t            writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val) __attribute__((deprecated("use std::optional version instead")));
     status_t            writeInt64Vector(const std::vector<int64_t>& val);
     status_t            writeUint64Vector(const std::optional<std::vector<uint64_t>>& val);
-    status_t            writeUint64Vector(const std::unique_ptr<std::vector<uint64_t>>& val);
+    status_t            writeUint64Vector(const std::unique_ptr<std::vector<uint64_t>>& val) __attribute__((deprecated("use std::optional version instead")));
     status_t            writeUint64Vector(const std::vector<uint64_t>& val);
     status_t            writeFloatVector(const std::optional<std::vector<float>>& val);
-    status_t            writeFloatVector(const std::unique_ptr<std::vector<float>>& val);
+    status_t            writeFloatVector(const std::unique_ptr<std::vector<float>>& val) __attribute__((deprecated("use std::optional version instead")));
     status_t            writeFloatVector(const std::vector<float>& val);
     status_t            writeDoubleVector(const std::optional<std::vector<double>>& val);
-    status_t            writeDoubleVector(const std::unique_ptr<std::vector<double>>& val);
+    status_t            writeDoubleVector(const std::unique_ptr<std::vector<double>>& val) __attribute__((deprecated("use std::optional version instead")));
     status_t            writeDoubleVector(const std::vector<double>& val);
     status_t            writeBoolVector(const std::optional<std::vector<bool>>& val);
-    status_t            writeBoolVector(const std::unique_ptr<std::vector<bool>>& val);
+    status_t            writeBoolVector(const std::unique_ptr<std::vector<bool>>& val) __attribute__((deprecated("use std::optional version instead")));
     status_t            writeBoolVector(const std::vector<bool>& val);
     status_t            writeCharVector(const std::optional<std::vector<char16_t>>& val);
-    status_t            writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val);
+    status_t            writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val) __attribute__((deprecated("use std::optional version instead")));
     status_t            writeCharVector(const std::vector<char16_t>& val);
     status_t            writeString16Vector(
                             const std::optional<std::vector<std::optional<String16>>>& val);
     status_t            writeString16Vector(
-                            const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val);
+                            const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val) __attribute__((deprecated("use std::optional version instead")));
     status_t            writeString16Vector(const std::vector<String16>& val);
     status_t            writeUtf8VectorAsUtf16Vector(
                             const std::optional<std::vector<std::optional<std::string>>>& val);
     status_t            writeUtf8VectorAsUtf16Vector(
-                            const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val);
+                            const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val) __attribute__((deprecated("use std::optional version instead")));
     status_t            writeUtf8VectorAsUtf16Vector(const std::vector<std::string>& val);
 
     status_t            writeStrongBinderVector(const std::optional<std::vector<sp<IBinder>>>& val);
-    status_t            writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val);
+    status_t            writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val) __attribute__((deprecated("use std::optional version instead")));
     status_t            writeStrongBinderVector(const std::vector<sp<IBinder>>& val);
 
     // Write an Enum vector with underlying type int8_t.
@@ -194,21 +194,21 @@
     template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
     status_t            writeEnumVector(const std::optional<std::vector<T>>& val);
     template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            writeEnumVector(const std::unique_ptr<std::vector<T>>& val);
+    status_t            writeEnumVector(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead")));
     // Write an Enum vector with underlying type != int8_t.
     template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
     status_t            writeEnumVector(const std::vector<T>& val);
     template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
     status_t            writeEnumVector(const std::optional<std::vector<T>>& val);
     template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            writeEnumVector(const std::unique_ptr<std::vector<T>>& val);
+    status_t            writeEnumVector(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead")));
 
     template<typename T>
     status_t            writeParcelableVector(const std::optional<std::vector<std::optional<T>>>& val);
     template<typename T>
-    status_t            writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val);
+    status_t            writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead")));
     template<typename T>
-    status_t            writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val);
+    status_t            writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead")));
     template<typename T>
     status_t            writeParcelableVector(const std::shared_ptr<std::vector<std::optional<T>>>& val);
     template<typename T>
@@ -217,7 +217,7 @@
     template<typename T>
     status_t            writeNullableParcelable(const std::optional<T>& parcelable);
     template<typename T>
-    status_t            writeNullableParcelable(const std::unique_ptr<T>& parcelable);
+    status_t            writeNullableParcelable(const std::unique_ptr<T>& parcelable) __attribute__((deprecated("use std::optional version instead")));
 
     status_t            writeParcelable(const Parcelable& parcelable);
 
@@ -232,7 +232,7 @@
     template<typename T>
     status_t            writeVectorSize(const std::optional<std::vector<T>>& val);
     template<typename T>
-    status_t            writeVectorSize(const std::unique_ptr<std::vector<T>>& val);
+    status_t            writeVectorSize(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead")));
 
     // Place a native_handle into the parcel (the native_handle's file-
     // descriptors are dup'ed, so it is safe to delete the native_handle
@@ -269,7 +269,7 @@
     status_t            writeUniqueFileDescriptorVector(
                             const std::optional<std::vector<base::unique_fd>>& val);
     status_t            writeUniqueFileDescriptorVector(
-                            const std::unique_ptr<std::vector<base::unique_fd>>& val);
+                            const std::unique_ptr<std::vector<base::unique_fd>>& val) __attribute__((deprecated("use std::optional version instead")));
     status_t            writeUniqueFileDescriptorVector(
                             const std::vector<base::unique_fd>& val);
 
@@ -317,7 +317,7 @@
     // Read a UTF16 encoded string, convert to UTF8
     status_t            readUtf8FromUtf16(std::string* str) const;
     status_t            readUtf8FromUtf16(std::optional<std::string>* str) const;
-    status_t            readUtf8FromUtf16(std::unique_ptr<std::string>* str) const;
+    status_t            readUtf8FromUtf16(std::unique_ptr<std::string>* str) const __attribute__((deprecated("use std::optional version instead")));
 
     const char*         readCString() const;
     String8             readString8() const;
@@ -326,7 +326,7 @@
     String16            readString16() const;
     status_t            readString16(String16* pArg) const;
     status_t            readString16(std::optional<String16>* pArg) const;
-    status_t            readString16(std::unique_ptr<String16>* pArg) const;
+    status_t            readString16(std::unique_ptr<String16>* pArg) const __attribute__((deprecated("use std::optional version instead")));
     const char16_t*     readString16Inplace(size_t* outLen) const;
     sp<IBinder>         readStrongBinder() const;
     status_t            readStrongBinder(sp<IBinder>* val) const;
@@ -337,14 +337,14 @@
     template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
     status_t            readEnumVector(std::vector<T>* val) const;
     template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            readEnumVector(std::unique_ptr<std::vector<T>>* val) const;
+    status_t            readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")));
     template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
     status_t            readEnumVector(std::optional<std::vector<T>>* val) const;
     // Read an Enum vector with underlying type != int8_t.
     template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
     status_t            readEnumVector(std::vector<T>* val) const;
     template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            readEnumVector(std::unique_ptr<std::vector<T>>* val) const;
+    status_t            readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")));
     template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
     status_t            readEnumVector(std::optional<std::vector<T>>* val) const;
 
@@ -353,7 +353,7 @@
                             std::optional<std::vector<std::optional<T>>>* val) const;
     template<typename T>
     status_t            readParcelableVector(
-                            std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const;
+                            std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const __attribute__((deprecated("use std::optional version instead")));
     template<typename T>
     status_t            readParcelableVector(std::vector<T>* val) const;
 
@@ -362,7 +362,7 @@
     template<typename T>
     status_t            readParcelable(std::optional<T>* parcelable) const;
     template<typename T>
-    status_t            readParcelable(std::unique_ptr<T>* parcelable) const;
+    status_t            readParcelable(std::unique_ptr<T>* parcelable) const __attribute__((deprecated("use std::optional version instead")));
 
     template<typename T>
     status_t            readStrongBinder(sp<T>* val) const;
@@ -371,45 +371,45 @@
     status_t            readNullableStrongBinder(sp<T>* val) const;
 
     status_t            readStrongBinderVector(std::optional<std::vector<sp<IBinder>>>* val) const;
-    status_t            readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const;
+    status_t            readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const __attribute__((deprecated("use std::optional version instead")));
     status_t            readStrongBinderVector(std::vector<sp<IBinder>>* val) const;
 
     status_t            readByteVector(std::optional<std::vector<int8_t>>* val) const;
-    status_t            readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const;
+    status_t            readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
     status_t            readByteVector(std::vector<int8_t>* val) const;
     status_t            readByteVector(std::optional<std::vector<uint8_t>>* val) const;
-    status_t            readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const;
+    status_t            readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
     status_t            readByteVector(std::vector<uint8_t>* val) const;
     status_t            readInt32Vector(std::optional<std::vector<int32_t>>* val) const;
-    status_t            readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const;
+    status_t            readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
     status_t            readInt32Vector(std::vector<int32_t>* val) const;
     status_t            readInt64Vector(std::optional<std::vector<int64_t>>* val) const;
-    status_t            readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const;
+    status_t            readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
     status_t            readInt64Vector(std::vector<int64_t>* val) const;
     status_t            readUint64Vector(std::optional<std::vector<uint64_t>>* val) const;
-    status_t            readUint64Vector(std::unique_ptr<std::vector<uint64_t>>* val) const;
+    status_t            readUint64Vector(std::unique_ptr<std::vector<uint64_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
     status_t            readUint64Vector(std::vector<uint64_t>* val) const;
     status_t            readFloatVector(std::optional<std::vector<float>>* val) const;
-    status_t            readFloatVector(std::unique_ptr<std::vector<float>>* val) const;
+    status_t            readFloatVector(std::unique_ptr<std::vector<float>>* val) const __attribute__((deprecated("use std::optional version instead")));
     status_t            readFloatVector(std::vector<float>* val) const;
     status_t            readDoubleVector(std::optional<std::vector<double>>* val) const;
-    status_t            readDoubleVector(std::unique_ptr<std::vector<double>>* val) const;
+    status_t            readDoubleVector(std::unique_ptr<std::vector<double>>* val) const __attribute__((deprecated("use std::optional version instead")));
     status_t            readDoubleVector(std::vector<double>* val) const;
     status_t            readBoolVector(std::optional<std::vector<bool>>* val) const;
-    status_t            readBoolVector(std::unique_ptr<std::vector<bool>>* val) const;
+    status_t            readBoolVector(std::unique_ptr<std::vector<bool>>* val) const __attribute__((deprecated("use std::optional version instead")));
     status_t            readBoolVector(std::vector<bool>* val) const;
     status_t            readCharVector(std::optional<std::vector<char16_t>>* val) const;
-    status_t            readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const;
+    status_t            readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
     status_t            readCharVector(std::vector<char16_t>* val) const;
     status_t            readString16Vector(
                             std::optional<std::vector<std::optional<String16>>>* val) const;
     status_t            readString16Vector(
-                            std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const;
+                            std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const __attribute__((deprecated("use std::optional version instead")));
     status_t            readString16Vector(std::vector<String16>* val) const;
     status_t            readUtf8VectorFromUtf16Vector(
                             std::optional<std::vector<std::optional<std::string>>>* val) const;
     status_t            readUtf8VectorFromUtf16Vector(
-                            std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const;
+                            std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const __attribute__((deprecated("use std::optional version instead")));
     status_t            readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const;
 
     template<typename T>
@@ -423,7 +423,7 @@
     template<typename T>
     status_t            resizeOutVector(std::optional<std::vector<T>>* val) const;
     template<typename T>
-    status_t            resizeOutVector(std::unique_ptr<std::vector<T>>* val) const;
+    status_t            resizeOutVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")));
     template<typename T>
     status_t            reserveOutVector(std::vector<T>* val, size_t* size) const;
     template<typename T>
@@ -431,7 +431,7 @@
                                          size_t* size) const;
     template<typename T>
     status_t            reserveOutVector(std::unique_ptr<std::vector<T>>* val,
-                                         size_t* size) const;
+                                         size_t* size) const __attribute__((deprecated("use std::optional version instead")));
 
     // Like Parcel.java's readExceptionCode().  Reads the first int32
     // off of a Parcel's header, returning 0 or the negative error
@@ -467,7 +467,7 @@
     status_t            readUniqueFileDescriptorVector(
                             std::optional<std::vector<base::unique_fd>>* val) const;
     status_t            readUniqueFileDescriptorVector(
-                            std::unique_ptr<std::vector<base::unique_fd>>* val) const;
+                            std::unique_ptr<std::vector<base::unique_fd>>* val) const __attribute__((deprecated("use std::optional version instead")));
     status_t            readUniqueFileDescriptorVector(
                             std::vector<base::unique_fd>* val) const;
 
@@ -561,7 +561,7 @@
                                                 status_t(Parcel::*read_func)(T*) const) const;
     template<typename T>
     status_t            readNullableTypedVector(std::unique_ptr<std::vector<T>>* val,
-                                                status_t(Parcel::*read_func)(T*) const) const;
+                                                status_t(Parcel::*read_func)(T*) const) const __attribute__((deprecated("use std::optional version instead")));
     template<typename T>
     status_t            readTypedVector(std::vector<T>* val,
                                         status_t(Parcel::*read_func)(T*) const) const;
@@ -573,13 +573,13 @@
                                                  status_t(Parcel::*write_func)(const T&));
     template<typename T>
     status_t            writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
-                                                 status_t(Parcel::*write_func)(const T&));
+                                                 status_t(Parcel::*write_func)(const T&)) __attribute__((deprecated("use std::optional version instead")));
     template<typename T>
     status_t            writeNullableTypedVector(const std::optional<std::vector<T>>& val,
                                                  status_t(Parcel::*write_func)(T));
     template<typename T>
     status_t            writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
-                                                 status_t(Parcel::*write_func)(T));
+                                                 status_t(Parcel::*write_func)(T)) __attribute__((deprecated("use std::optional version instead")));
     template<typename T>
     status_t            writeTypedVector(const std::vector<T>& val,
                                          status_t(Parcel::*write_func)(const T&));
diff --git a/libs/binder/include/binder/ParcelableHolder.h b/libs/binder/include/binder/ParcelableHolder.h
index 4ea3dd3..ce5027e 100644
--- a/libs/binder/include/binder/ParcelableHolder.h
+++ b/libs/binder/include/binder/ParcelableHolder.h
@@ -30,7 +30,7 @@
 class ParcelableHolder : public android::Parcelable {
 public:
     ParcelableHolder() = delete;
-    explicit ParcelableHolder(Stability stability) : mStability(stability){};
+    explicit ParcelableHolder(Stability stability) : mStability(stability){}
     virtual ~ParcelableHolder() = default;
     ParcelableHolder(const ParcelableHolder& other) {
         mParcelable = other.mParcelable;
@@ -40,7 +40,7 @@
             mParcelPtr->appendFrom(other.mParcelPtr.get(), 0, other.mParcelPtr->dataSize());
         }
         mStability = other.mStability;
-    };
+    }
 
     status_t writeToParcel(Parcel* parcel) const override;
     status_t readFromParcel(const Parcel* parcel) override;
diff --git a/libs/binder/parcel_fuzzer/binder.cpp b/libs/binder/parcel_fuzzer/binder.cpp
index a94f06f..394d222 100644
--- a/libs/binder/parcel_fuzzer/binder.cpp
+++ b/libs/binder/parcel_fuzzer/binder.cpp
@@ -86,6 +86,8 @@
     PARCEL_READ_WITH_STATUS(T, FUN), \
     PARCEL_READ_NO_STATUS(T, FUN)
 
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
 // clang-format off
 std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS {
     PARCEL_READ_NO_STATUS(size_t, dataSize),
@@ -289,3 +291,4 @@
     PARCEL_READ_WITH_STATUS(android::os::PersistableBundle, readParcelable),
 };
 // clang-format on
+#pragma clang diagnostic pop
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index 09f58cc..2f9d85e 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -184,7 +184,7 @@
 
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wexit-time-destructors"
-IMPLEMENT_META_INTERFACE(Callback, "android.gfx.tests.ICallback");
+IMPLEMENT_META_INTERFACE(Callback, "android.gfx.tests.ICallback")
 #pragma clang diagnostic pop
 
 class BnCallback : public SafeBnInterface<ICallback> {
@@ -373,7 +373,7 @@
 
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wexit-time-destructors"
-IMPLEMENT_META_INTERFACE(SafeInterfaceTest, "android.gfx.tests.ISafeInterfaceTest");
+IMPLEMENT_META_INTERFACE(SafeInterfaceTest, "android.gfx.tests.ISafeInterfaceTest")
 
 static sp<IBinder::DeathRecipient> getDeathRecipient() {
     static sp<IBinder::DeathRecipient> recipient = new ExitOnDeath;
diff --git a/libs/vibrator/Android.bp b/libs/vibrator/Android.bp
index e95a080..33ab8ba 100644
--- a/libs/vibrator/Android.bp
+++ b/libs/vibrator/Android.bp
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-cc_library_shared {
+cc_library {
     name: "libvibrator",
 
     shared_libs: [
@@ -45,4 +45,11 @@
     ],
 
     export_include_dirs: ["include"],
+
+    host_supported: true,
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
 }
diff --git a/libs/vibrator/fuzzer/Android.bp b/libs/vibrator/fuzzer/Android.bp
new file mode 100644
index 0000000..8020151
--- /dev/null
+++ b/libs/vibrator/fuzzer/Android.bp
@@ -0,0 +1,43 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ */
+
+cc_fuzz {
+    name: "vibrator_fuzzer",
+
+    host_supported: true,
+
+    srcs: [
+        "vibrator_fuzzer.cpp",
+    ],
+
+    static_libs: [
+        "liblog",
+        "libvibrator",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "libbase",
+        "libutils",
+    ],
+
+    fuzz_config: {
+        componentid: 155276,
+    },
+}
diff --git a/libs/vibrator/fuzzer/README.md b/libs/vibrator/fuzzer/README.md
new file mode 100644
index 0000000..43eb2d2
--- /dev/null
+++ b/libs/vibrator/fuzzer/README.md
@@ -0,0 +1,65 @@
+# Fuzzer for libvibrator
+
+## Plugin Design Considerations
+This fuzzer fuzzes native code present in libvibrator and does not cover the Java implementation ExternalVibration
+The fuzzer plugin is designed based on the understanding of the
+library and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+libvibrator supports the following parameters:
+1. Uid (parameter name: `uid`)
+2. Package Name (parameter name: `pkg`)
+3. Audio Content Type (parameter name: `content_type`)
+4. Audio Usage (parameter name: `usage`)
+5. Audio Source (parameter name: `source`)
+6. Audio flags (parameter name: `flags`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `uid` | `INT32_MIN` to `INT32_MAX` | Value obtained from FuzzedDataProvider |
+| `pkg`   | Any std::string value | Value obtained from FuzzedDataProvider |
+| `content_type`   | 0.`AUDIO_CONTENT_TYPE_UNKNOWN` 1.`AUDIO_CONTENT_TYPE_SPEECH` 2.`AUDIO_CONTENT_TYPE_MUSIC` 3.`AUDIO_CONTENT_TYPE_MOVIE` 4.`AUDIO_CONTENT_TYPE_SONIFICATION`| Value obtained from FuzzedDataProvider in the range 0 to 4|
+| `usage`   | 0.`AUDIO_USAGE_UNKNOWN` 1.`AUDIO_USAGE_MEDIA` 2.`AUDIO_USAGE_VOICE_COMMUNICATION` 3.`AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING` 4.`AUDIO_USAGE_ALARM` 5.`AUDIO_USAGE_NOTIFICATION` 6.`AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE`  7.`AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST` 8.`AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT` 9.`AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED` 10.`AUDIO_USAGE_NOTIFICATION_EVENT` 11.`AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY` 12.`AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE` 13.`AUDIO_USAGE_ASSISTANCE_SONIFICATION` 14.`AUDIO_USAGE_GAME` 15.`AUDIO_USAGE_VIRTUAL_SOURCE` 16.`AUDIO_USAGE_ASSISTANT` 17.`AUDIO_USAGE_CALL_ASSISTANT` 18.`AUDIO_USAGE_EMERGENCY` 19.`AUDIO_USAGE_SAFETY` 20.`AUDIO_USAGE_VEHICLE_STATUS` 21.`AUDIO_USAGE_ANNOUNCEMENT`| Value obtained from FuzzedDataProvider in the range 0 to 21|
+| `source`   |  0.`AUDIO_SOURCE_DEFAULT` 1.`AUDIO_SOURCE_MIC` 2.`AUDIO_SOURCE_VOICE_UPLINK` 3.`AUDIO_SOURCE_VOICE_DOWNLINK` 4.`AUDIO_SOURCE_VOICE_CALL` 5.`AUDIO_SOURCE_CAMCORDER` 6.`AUDIO_SOURCE_VOICE_RECOGNITION` 7.`AUDIO_SOURCE_VOICE_COMMUNICATION` 8.`AUDIO_SOURCE_REMOTE_SUBMIX` 9.`AUDIO_SOURCE_UNPROCESSED` 10.`AUDIO_SOURCE_VOICE_PERFORMANCE` 11.`AUDIO_SOURCE_ECHO_REFERENCE` 12.`AUDIO_SOURCE_FM_TUNER` | Value obtained from FuzzedDataProvider in the range 0 to 12 |
+| `flags`   | `UINT32_MIN` to `UINT32_MAX` | Value obtained from FuzzedDataProvider |
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin tolerates any kind of input (empty, huge,
+malformed, etc) and doesn't `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build vibrator_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+  $ mm -j$(nproc) vibrator_fuzzer
+```
+
+#### Steps to run
+Create a directory CORPUS_DIR and copy some files to that folder
+Push this directory to device.
+
+To run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/vibrator_fuzzer/vibrator_fuzzer CORPUS_DIR
+```
+
+To run on host
+```
+  $ $ANDROID_HOST_OUT/fuzz/x86_64/vibrator_fuzzer/vibrator_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/libs/vibrator/fuzzer/vibrator_fuzzer.cpp b/libs/vibrator/fuzzer/vibrator_fuzzer.cpp
new file mode 100644
index 0000000..68b3ca6
--- /dev/null
+++ b/libs/vibrator/fuzzer/vibrator_fuzzer.cpp
@@ -0,0 +1,130 @@
+/******************************************************************************
+ *
+ * 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 <binder/Parcel.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <vibrator/ExternalVibration.h>
+
+using namespace android;
+
+constexpr size_t MAX_STRING_LENGTH = 100;
+constexpr audio_content_type_t AUDIO_CONTENT_TYPE[] = {AUDIO_CONTENT_TYPE_UNKNOWN,
+                                                       AUDIO_CONTENT_TYPE_SPEECH,
+                                                       AUDIO_CONTENT_TYPE_MUSIC,
+                                                       AUDIO_CONTENT_TYPE_MOVIE,
+                                                       AUDIO_CONTENT_TYPE_SONIFICATION};
+constexpr audio_usage_t AUDIO_USAGE[] = {
+        AUDIO_USAGE_UNKNOWN,
+        AUDIO_USAGE_MEDIA,
+        AUDIO_USAGE_VOICE_COMMUNICATION,
+        AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
+        AUDIO_USAGE_ALARM,
+        AUDIO_USAGE_NOTIFICATION,
+        AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
+        AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
+        AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
+        AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
+        AUDIO_USAGE_NOTIFICATION_EVENT,
+        AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
+        AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+        AUDIO_USAGE_ASSISTANCE_SONIFICATION,
+        AUDIO_USAGE_GAME,
+        AUDIO_USAGE_VIRTUAL_SOURCE,
+        AUDIO_USAGE_ASSISTANT,
+        AUDIO_USAGE_CALL_ASSISTANT,
+        AUDIO_USAGE_EMERGENCY,
+        AUDIO_USAGE_SAFETY,
+        AUDIO_USAGE_VEHICLE_STATUS,
+        AUDIO_USAGE_ANNOUNCEMENT,
+};
+constexpr audio_source_t AUDIO_SOURCE[] = {
+        AUDIO_SOURCE_DEFAULT,           AUDIO_SOURCE_MIC,
+        AUDIO_SOURCE_VOICE_UPLINK,      AUDIO_SOURCE_VOICE_DOWNLINK,
+        AUDIO_SOURCE_VOICE_CALL,        AUDIO_SOURCE_CAMCORDER,
+        AUDIO_SOURCE_VOICE_RECOGNITION, AUDIO_SOURCE_VOICE_COMMUNICATION,
+        AUDIO_SOURCE_REMOTE_SUBMIX,     AUDIO_SOURCE_UNPROCESSED,
+        AUDIO_SOURCE_VOICE_PERFORMANCE, AUDIO_SOURCE_ECHO_REFERENCE,
+        AUDIO_SOURCE_FM_TUNER,
+};
+constexpr size_t NUM_AUDIO_CONTENT_TYPE = std::size(AUDIO_CONTENT_TYPE);
+constexpr size_t NUM_AUDIO_USAGE = std::size(AUDIO_USAGE);
+constexpr size_t NUM_AUDIO_SOURCE = std::size(AUDIO_SOURCE);
+
+class TestVibrationController : public os::IExternalVibrationController {
+public:
+    explicit TestVibrationController() {}
+    IBinder *onAsBinder() override { return nullptr; }
+    binder::Status mute(/*out*/ bool *ret) override {
+        *ret = false;
+        return binder::Status::ok();
+    };
+    binder::Status unmute(/*out*/ bool *ret) override {
+        *ret = false;
+        return binder::Status::ok();
+    };
+};
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    if (size < 1) {
+        return 0;
+    }
+    FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+    // Initialize the parameters using FuzzedDataProvider
+    int32_t uid = fdp.ConsumeIntegral<int32_t>();
+    std::string pkg = fdp.ConsumeRandomLengthString(MAX_STRING_LENGTH);
+    audio_attributes_t attributes;
+    attributes.content_type =
+            AUDIO_CONTENT_TYPE[fdp.ConsumeIntegralInRange<uint32_t>(0, NUM_AUDIO_CONTENT_TYPE - 1)];
+    attributes.usage = AUDIO_USAGE[fdp.ConsumeIntegralInRange<uint32_t>(0, NUM_AUDIO_USAGE - 1)];
+    attributes.source = AUDIO_SOURCE[fdp.ConsumeIntegralInRange<uint32_t>(0, NUM_AUDIO_SOURCE - 1)];
+    attributes.flags = static_cast<audio_flags_mask_t>(fdp.ConsumeIntegral<uint32_t>());
+
+    // Create an instance of TestVibrationController
+    sp<TestVibrationController> vibrationController = new TestVibrationController();
+    if (!vibrationController) {
+        return 0;
+    }
+
+    // Set all the parameters in the constructor call
+    sp<os::ExternalVibration> extVibration =
+            new os::ExternalVibration(uid, pkg, attributes, vibrationController);
+    if (!extVibration) {
+        return 0;
+    }
+
+    // Get all the parameters that were previously set
+    extVibration->getUid();
+    extVibration->getPackage();
+    extVibration->getAudioAttributes();
+    extVibration->getController();
+
+    // Set the parameters in a Parcel object and send it to libvibrator
+    // This parcel shall be read by libvibrator
+    Parcel parcel;
+    parcel.writeInt32(uid);
+    parcel.writeString16(String16(pkg.c_str()));
+    parcel.writeStrongBinder(IInterface::asBinder(vibrationController));
+    parcel.setDataPosition(0);
+    extVibration->readFromParcel(&parcel);
+
+    // Send a Parcel to libvibrator
+    // Parameters shall be written to this parcel by libvibrator
+    extVibration->writeToParcel(&parcel);
+    return 0;
+}
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 04a5c4f..0b541fb 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -781,12 +781,17 @@
         mOrientedRanges.clear();
     }
 
-    // Create pointer controller if needed.
+    // Create pointer controller if needed, and keep it around if Pointer Capture is enabled to
+    // preserve the cursor position.
     if (mDeviceMode == DeviceMode::POINTER ||
-        (mDeviceMode == DeviceMode::DIRECT && mConfig.showTouches)) {
+        (mDeviceMode == DeviceMode::DIRECT && mConfig.showTouches) ||
+        (mParameters.deviceType == Parameters::DeviceType::POINTER && mConfig.pointerCapture)) {
         if (mPointerController == nullptr) {
             mPointerController = getContext()->getPointerController(getDeviceId());
         }
+        if (mConfig.pointerCapture) {
+            mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
+        }
     } else {
         mPointerController.reset();
     }