Merge "Update the header path for ext4_utils."
am: 5bc3ce85cf

Change-Id: I962e2c4b311ea93c12de8be26b7a228fae1b1b22
diff --git a/adb/Android.mk b/adb/Android.mk
index e17240b..6ea0ab7 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -182,10 +182,6 @@
 LOCAL_CFLAGS_darwin := $(LIBADB_darwin_CFLAGS)
 LOCAL_SRC_FILES := \
     $(LIBADB_TEST_SRCS) \
-    adb_client.cpp \
-    bugreport.cpp \
-    bugreport_test.cpp \
-    line_printer.cpp \
     services.cpp \
     shell_service_protocol.cpp \
     shell_service_protocol_test.cpp \
@@ -201,7 +197,6 @@
     libcrypto \
     libcutils \
     libdiagnose_usb \
-    libgmock_host \
 
 # Set entrypoint to wmain from sysdeps_win32.cpp instead of main
 LOCAL_LDFLAGS_windows := -municode
@@ -230,7 +225,6 @@
 
 LOCAL_SRC_FILES := \
     adb_client.cpp \
-    bugreport.cpp \
     client/main.cpp \
     console.cpp \
     commandline.cpp \
diff --git a/adb/adb.h b/adb/adb.h
index 8064c17..bd9c4f0 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -205,6 +205,8 @@
 int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol);
 #endif
 
+int adb_commandline(int argc, const char **argv);
+
 ConnectionState connection_state(atransport *t);
 
 extern const char* adb_device_banner;
diff --git a/adb/adb_client.h b/adb/adb_client.h
index d35d705..9e6f1c2 100644
--- a/adb/adb_client.h
+++ b/adb/adb_client.h
@@ -18,7 +18,6 @@
 #define _ADB_CLIENT_H_
 
 #include "adb.h"
-#include "sysdeps.h"
 #include "transport.h"
 
 #include <string>
diff --git a/adb/bugreport.cpp b/adb/bugreport.cpp
deleted file mode 100644
index c348dd5..0000000
--- a/adb/bugreport.cpp
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define TRACE_TAG ADB
-
-#include "bugreport.h"
-
-#include <string>
-#include <vector>
-
-#include <android-base/strings.h>
-
-#include "sysdeps.h"
-#include "adb_utils.h"
-#include "file_sync_service.h"
-
-static constexpr char BUGZ_BEGIN_PREFIX[] = "BEGIN:";
-static constexpr char BUGZ_PROGRESS_PREFIX[] = "PROGRESS:";
-static constexpr char BUGZ_PROGRESS_SEPARATOR[] = "/";
-static constexpr char BUGZ_OK_PREFIX[] = "OK:";
-static constexpr char BUGZ_FAIL_PREFIX[] = "FAIL:";
-
-// Custom callback used to handle the output of zipped bugreports.
-class BugreportStandardStreamsCallback : public StandardStreamsCallbackInterface {
-  public:
-    BugreportStandardStreamsCallback(const std::string& dest_dir, const std::string& dest_file,
-                                     bool show_progress, Bugreport* br)
-        : br_(br),
-          src_file_(),
-          dest_dir_(dest_dir),
-          dest_file_(dest_file),
-          line_message_(),
-          invalid_lines_(),
-          show_progress_(show_progress),
-          status_(0),
-          line_() {
-        SetLineMessage("generating");
-    }
-
-    void OnStdout(const char* buffer, int length) {
-        for (int i = 0; i < length; i++) {
-            char c = buffer[i];
-            if (c == '\n') {
-                ProcessLine(line_);
-                line_.clear();
-            } else {
-                line_.append(1, c);
-            }
-        }
-    }
-
-    void OnStderr(const char* buffer, int length) {
-        OnStream(nullptr, stderr, buffer, length);
-    }
-    int Done(int unused_) {
-        // Process remaining line, if any.
-        ProcessLine(line_);
-
-        // Warn about invalid lines, if any.
-        if (!invalid_lines_.empty()) {
-            fprintf(stderr,
-                    "WARNING: bugreportz generated %zu line(s) with unknown commands, "
-                    "device might not support zipped bugreports:\n",
-                    invalid_lines_.size());
-            for (const auto& line : invalid_lines_) {
-                fprintf(stderr, "\t%s\n", line.c_str());
-            }
-            fprintf(stderr,
-                    "If the zipped bugreport was not generated, try 'adb bugreport' instead.\n");
-        }
-
-        // Pull the generated bug report.
-        if (status_ == 0) {
-            if (src_file_.empty()) {
-                fprintf(stderr, "bugreportz did not return a '%s' or '%s' line\n", BUGZ_OK_PREFIX,
-                        BUGZ_FAIL_PREFIX);
-                return -1;
-            }
-            std::string destination;
-            if (dest_dir_.empty()) {
-                destination = dest_file_;
-            } else {
-                destination = android::base::StringPrintf("%s%c%s", dest_dir_.c_str(),
-                                                          OS_PATH_SEPARATOR, dest_file_.c_str());
-            }
-            std::vector<const char*> srcs{src_file_.c_str()};
-            SetLineMessage("pulling");
-            status_ =
-                br_->DoSyncPull(srcs, destination.c_str(), true, line_message_.c_str()) ? 0 : 1;
-            if (status_ != 0) {
-                fprintf(stderr,
-                        "Bug report finished but could not be copied to '%s'.\n"
-                        "Try to run 'adb pull %s <directory>'\n"
-                        "to copy it to a directory that can be written.\n",
-                        destination.c_str(), src_file_.c_str());
-            }
-        }
-        return status_;
-    }
-
-  private:
-    void SetLineMessage(const std::string& action) {
-        line_message_ = action + " " + adb_basename(dest_file_);
-    }
-
-    void SetSrcFile(const std::string path) {
-        src_file_ = path;
-        if (!dest_dir_.empty()) {
-            // Only uses device-provided name when user passed a directory.
-            dest_file_ = adb_basename(path);
-            SetLineMessage("generating");
-        }
-    }
-
-    void ProcessLine(const std::string& line) {
-        if (line.empty()) return;
-
-        if (android::base::StartsWith(line, BUGZ_BEGIN_PREFIX)) {
-            SetSrcFile(&line[strlen(BUGZ_BEGIN_PREFIX)]);
-        } else if (android::base::StartsWith(line, BUGZ_OK_PREFIX)) {
-            SetSrcFile(&line[strlen(BUGZ_OK_PREFIX)]);
-        } else if (android::base::StartsWith(line, BUGZ_FAIL_PREFIX)) {
-            const char* error_message = &line[strlen(BUGZ_FAIL_PREFIX)];
-            fprintf(stderr, "Device failed to take a zipped bugreport: %s\n", error_message);
-            status_ = -1;
-        } else if (show_progress_ && android::base::StartsWith(line, BUGZ_PROGRESS_PREFIX)) {
-            // progress_line should have the following format:
-            //
-            // BUGZ_PROGRESS_PREFIX:PROGRESS/TOTAL
-            //
-            size_t idx1 = line.rfind(BUGZ_PROGRESS_PREFIX) + strlen(BUGZ_PROGRESS_PREFIX);
-            size_t idx2 = line.rfind(BUGZ_PROGRESS_SEPARATOR);
-            int progress = std::stoi(line.substr(idx1, (idx2 - idx1)));
-            int total = std::stoi(line.substr(idx2 + 1));
-            br_->UpdateProgress(line_message_, progress, total);
-        } else {
-            invalid_lines_.push_back(line);
-        }
-    }
-
-    Bugreport* br_;
-
-    // Path of bugreport on device.
-    std::string src_file_;
-
-    // Bugreport destination on host, depending on argument passed on constructor:
-    // - if argument is a directory, dest_dir_ is set with it and dest_file_ will be the name
-    //   of the bugreport reported by the device.
-    // - if argument is empty, dest_dir is set as the current directory and dest_file_ will be the
-    //   name of the bugreport reported by the device.
-    // - otherwise, dest_dir_ is not set and dest_file_ is set with the value passed on constructor.
-    std::string dest_dir_, dest_file_;
-
-    // Message displayed on LinePrinter, it's updated every time the destination above change.
-    std::string line_message_;
-
-    // Lines sent by bugreportz that contain invalid commands; will be displayed at the end.
-    std::vector<std::string> invalid_lines_;
-
-    // Whether PROGRESS_LINES should be interpreted as progress.
-    bool show_progress_;
-
-    // Overall process of the operation, as returned by Done().
-    int status_;
-
-    // Temporary buffer containing the characters read since the last newline (\n).
-    std::string line_;
-
-    DISALLOW_COPY_AND_ASSIGN(BugreportStandardStreamsCallback);
-};
-
-// Implemented in commandline.cpp
-int usage();
-
-int Bugreport::DoIt(TransportType transport_type, const char* serial, int argc, const char** argv) {
-    if (argc > 2) return usage();
-
-    // Gets bugreportz version.
-    std::string bugz_stdout, bugz_stderr;
-    DefaultStandardStreamsCallback version_callback(&bugz_stdout, &bugz_stderr);
-    int status = SendShellCommand(transport_type, serial, "bugreportz -v", false, &version_callback);
-    std::string bugz_version = android::base::Trim(bugz_stderr);
-    std::string bugz_output = android::base::Trim(bugz_stdout);
-
-    if (status != 0 || bugz_version.empty()) {
-        D("'bugreportz' -v results: status=%d, stdout='%s', stderr='%s'", status,
-          bugz_output.c_str(), bugz_version.c_str());
-        if (argc == 1) {
-            // Device does not support bugreportz: if called as 'adb bugreport', just falls out to
-            // the flat-file version.
-            fprintf(stderr,
-                    "Failed to get bugreportz version, which is only available on devices "
-                    "running Android 7.0 or later.\nTrying a plain-text bug report instead.\n");
-            return SendShellCommand(transport_type, serial, "bugreport", false);
-        }
-
-        // But if user explicitly asked for a zipped bug report, fails instead (otherwise calling
-        // 'bugreport' would generate a lot of output the user might not be prepared to handle).
-        fprintf(stderr,
-                "Failed to get bugreportz version: 'bugreportz -v' returned '%s' (code %d).\n"
-                "If the device does not run Android 7.0 or above, try 'adb bugreport' instead.\n",
-                bugz_output.c_str(), status);
-        return status != 0 ? status : -1;
-    }
-
-    std::string dest_file, dest_dir;
-
-    if (argc == 1) {
-        // No args - use current directory
-        if (!getcwd(&dest_dir)) {
-            perror("adb: getcwd failed");
-            return 1;
-        }
-    } else {
-        // Check whether argument is a directory or file
-        if (directory_exists(argv[1])) {
-            dest_dir = argv[1];
-        } else {
-            dest_file = argv[1];
-        }
-    }
-
-    if (dest_file.empty()) {
-        // Uses a default value until device provides the proper name
-        dest_file = "bugreport.zip";
-    } else {
-        if (!android::base::EndsWith(dest_file, ".zip")) {
-            // TODO: use a case-insensitive comparison (like EndsWithIgnoreCase
-            dest_file += ".zip";
-        }
-    }
-
-    bool show_progress = true;
-    std::string bugz_command = "bugreportz -p";
-    if (bugz_version == "1.0") {
-        // 1.0 does not support progress notifications, so print a disclaimer
-        // message instead.
-        fprintf(stderr,
-                "Bugreport is in progress and it could take minutes to complete.\n"
-                "Please be patient and do not cancel or disconnect your device "
-                "until it completes.\n");
-        show_progress = false;
-        bugz_command = "bugreportz";
-    }
-    BugreportStandardStreamsCallback bugz_callback(dest_dir, dest_file, show_progress, this);
-    return SendShellCommand(transport_type, serial, bugz_command, false, &bugz_callback);
-}
-
-void Bugreport::UpdateProgress(const std::string& message, int progress, int total) {
-    int progress_percentage = (progress * 100 / total);
-    line_printer_.Print(
-        android::base::StringPrintf("[%3d%%] %s", progress_percentage, message.c_str()),
-        LinePrinter::INFO);
-}
-
-int Bugreport::SendShellCommand(TransportType transport_type, const char* serial,
-                                const std::string& command, bool disable_shell_protocol,
-                                StandardStreamsCallbackInterface* callback) {
-    return send_shell_command(transport_type, serial, command, disable_shell_protocol, callback);
-}
-
-bool Bugreport::DoSyncPull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs,
-                           const char* name) {
-    return do_sync_pull(srcs, dst, copy_attrs, name);
-}
diff --git a/adb/bugreport.h b/adb/bugreport.h
deleted file mode 100644
index ee99cbc..0000000
--- a/adb/bugreport.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BUGREPORT_H
-#define BUGREPORT_H
-
-#include <vector>
-
-#include "adb.h"
-#include "commandline.h"
-#include "line_printer.h"
-
-class Bugreport {
-    friend class BugreportStandardStreamsCallback;
-
-  public:
-    Bugreport() : line_printer_() {
-    }
-    int DoIt(TransportType transport_type, const char* serial, int argc, const char** argv);
-
-  protected:
-    // Functions below are abstractions of external functions so they can be
-    // mocked on tests.
-    virtual int SendShellCommand(
-        TransportType transport_type, const char* serial, const std::string& command,
-        bool disable_shell_protocol,
-        StandardStreamsCallbackInterface* callback = &DEFAULT_STANDARD_STREAMS_CALLBACK);
-
-    virtual bool DoSyncPull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs,
-                            const char* name);
-
-  private:
-    virtual void UpdateProgress(const std::string& file_name, int progress, int total);
-    LinePrinter line_printer_;
-    DISALLOW_COPY_AND_ASSIGN(Bugreport);
-};
-
-#endif  // BUGREPORT_H
diff --git a/adb/bugreport_test.cpp b/adb/bugreport_test.cpp
deleted file mode 100644
index 1129285..0000000
--- a/adb/bugreport_test.cpp
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright (C) 2016 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 "bugreport.h"
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include <android-base/strings.h>
-#include <android-base/test_utils.h>
-
-#include "sysdeps.h"
-#include "adb_utils.h"
-
-using ::testing::_;
-using ::testing::Action;
-using ::testing::ActionInterface;
-using ::testing::DoAll;
-using ::testing::ElementsAre;
-using ::testing::HasSubstr;
-using ::testing::MakeAction;
-using ::testing::Return;
-using ::testing::StrEq;
-using ::testing::WithArg;
-using ::testing::internal::CaptureStderr;
-using ::testing::internal::CaptureStdout;
-using ::testing::internal::GetCapturedStderr;
-using ::testing::internal::GetCapturedStdout;
-
-// Empty function so tests don't need to be linked against file_sync_service.cpp, which requires
-// SELinux and its transitive dependencies...
-bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs,
-                  const char* name) {
-    ADD_FAILURE() << "do_sync_pull() should have been mocked";
-    return false;
-}
-
-// Empty functions so tests don't need to be linked against commandline.cpp
-DefaultStandardStreamsCallback DEFAULT_STANDARD_STREAMS_CALLBACK(nullptr, nullptr);
-int usage() {
-    return -42;
-}
-int send_shell_command(TransportType transport_type, const char* serial, const std::string& command,
-                       bool disable_shell_protocol, StandardStreamsCallbackInterface* callback) {
-    ADD_FAILURE() << "send_shell_command() should have been mocked";
-    return -42;
-}
-
-enum StreamType {
-    kStreamStdout,
-    kStreamStderr,
-};
-
-// gmock black magic to provide a WithArg<4>(WriteOnStdout(output)) matcher
-typedef void OnStandardStreamsCallbackFunction(StandardStreamsCallbackInterface*);
-
-class OnStandardStreamsCallbackAction : public ActionInterface<OnStandardStreamsCallbackFunction> {
-  public:
-    explicit OnStandardStreamsCallbackAction(StreamType type, const std::string& output)
-        : type_(type), output_(output) {
-    }
-    virtual Result Perform(const ArgumentTuple& args) {
-        if (type_ == kStreamStdout) {
-            ::std::tr1::get<0>(args)->OnStdout(output_.c_str(), output_.size());
-        }
-        if (type_ == kStreamStderr) {
-            ::std::tr1::get<0>(args)->OnStderr(output_.c_str(), output_.size());
-        }
-    }
-
-  private:
-    StreamType type_;
-    std::string output_;
-};
-
-// Matcher used to emulated StandardStreamsCallbackInterface.OnStdout(buffer,
-// length)
-Action<OnStandardStreamsCallbackFunction> WriteOnStdout(const std::string& output) {
-    return MakeAction(new OnStandardStreamsCallbackAction(kStreamStdout, output));
-}
-
-// Matcher used to emulated StandardStreamsCallbackInterface.OnStderr(buffer,
-// length)
-Action<OnStandardStreamsCallbackFunction> WriteOnStderr(const std::string& output) {
-    return MakeAction(new OnStandardStreamsCallbackAction(kStreamStderr, output));
-}
-
-typedef int CallbackDoneFunction(StandardStreamsCallbackInterface*);
-
-class CallbackDoneAction : public ActionInterface<CallbackDoneFunction> {
-  public:
-    explicit CallbackDoneAction(int status) : status_(status) {
-    }
-    virtual Result Perform(const ArgumentTuple& args) {
-        int status = ::std::tr1::get<0>(args)->Done(status_);
-        return status;
-    }
-
-  private:
-    int status_;
-};
-
-// Matcher used to emulated StandardStreamsCallbackInterface.Done(status)
-Action<CallbackDoneFunction> ReturnCallbackDone(int status = -1337) {
-    return MakeAction(new CallbackDoneAction(status));
-}
-
-class BugreportMock : public Bugreport {
-  public:
-    MOCK_METHOD5(SendShellCommand,
-                 int(TransportType transport_type, const char* serial, const std::string& command,
-                     bool disable_shell_protocol, StandardStreamsCallbackInterface* callback));
-    MOCK_METHOD4(DoSyncPull, bool(const std::vector<const char*>& srcs, const char* dst,
-                                  bool copy_attrs, const char* name));
-    MOCK_METHOD3(UpdateProgress, void(const std::string&, int, int));
-};
-
-class BugreportTest : public ::testing::Test {
-  public:
-    void SetUp() {
-        if (!getcwd(&cwd_)) {
-            ADD_FAILURE() << "getcwd failed: " << strerror(errno);
-            return;
-        }
-    }
-
-    void ExpectBugreportzVersion(const std::string& version) {
-        EXPECT_CALL(br_,
-                    SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -v", false, _))
-            .WillOnce(DoAll(WithArg<4>(WriteOnStderr(version.c_str())),
-                            WithArg<4>(ReturnCallbackDone(0))));
-    }
-
-    void ExpectProgress(int progress, int total, const std::string& file = "file.zip") {
-        EXPECT_CALL(br_, UpdateProgress(StrEq("generating " + file), progress, total));
-    }
-
-    BugreportMock br_;
-    std::string cwd_;  // TODO: make it static
-};
-
-// Tests when called with invalid number of arguments
-TEST_F(BugreportTest, InvalidNumberArgs) {
-    const char* args[] = {"bugreport", "to", "principal"};
-    ASSERT_EQ(-42, br_.DoIt(kTransportLocal, "HannibalLecter", 3, args));
-}
-
-// Tests the 'adb bugreport' option when the device does not support 'bugreportz' - it falls back
-// to the flat-file format ('bugreport' binary on device)
-TEST_F(BugreportTest, NoArgumentsPreNDevice) {
-    // clang-format off
-    EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -v", false, _))
-        .WillOnce(DoAll(WithArg<4>(WriteOnStderr("")),
-                        // Write some bogus output on stdout to make sure it's ignored
-                        WithArg<4>(WriteOnStdout("Dude, where is my bugreportz?")),
-                        WithArg<4>(ReturnCallbackDone(0))));
-    // clang-format on
-    std::string bugreport = "Reported the bug was.";
-    CaptureStdout();
-    EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreport", false, _))
-        .WillOnce(DoAll(WithArg<4>(WriteOnStdout(bugreport)), Return(0)));
-
-    const char* args[] = {"bugreport"};
-    ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 1, args));
-    ASSERT_THAT(GetCapturedStdout(), StrEq(bugreport));
-}
-
-// Tests the 'adb bugreport' option when the device supports 'bugreportz' version 1.0 - it will
-// save the bugreport in the current directory with the name provided by the device.
-TEST_F(BugreportTest, NoArgumentsNDevice) {
-    ExpectBugreportzVersion("1.0");
-
-    std::string dest_file =
-        android::base::StringPrintf("%s%cda_bugreport.zip", cwd_.c_str(), OS_PATH_SEPARATOR);
-    EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
-        .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip")),
-                        WithArg<4>(ReturnCallbackDone())));
-    EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
-                                true, StrEq("pulling da_bugreport.zip")))
-        .WillOnce(Return(true));
-
-    const char* args[] = {"bugreport"};
-    ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 1, args));
-}
-
-// Tests the 'adb bugreport' option when the device supports 'bugreportz' version 1.1 - it will
-// save the bugreport in the current directory with the name provided by the device.
-TEST_F(BugreportTest, NoArgumentsPostNDevice) {
-    ExpectBugreportzVersion("1.1");
-    std::string dest_file =
-        android::base::StringPrintf("%s%cda_bugreport.zip", cwd_.c_str(), OS_PATH_SEPARATOR);
-    ExpectProgress(50, 100, "da_bugreport.zip");
-    EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
-        .WillOnce(DoAll(WithArg<4>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
-                        WithArg<4>(WriteOnStdout("PROGRESS:50/100\n")),
-                        WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip\n")),
-                        WithArg<4>(ReturnCallbackDone())));
-    EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
-                                true, StrEq("pulling da_bugreport.zip")))
-        .WillOnce(Return(true));
-
-    const char* args[] = {"bugreport"};
-    ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 1, args));
-}
-
-// Tests 'adb bugreport file.zip' when it succeeds and device does not support progress.
-TEST_F(BugreportTest, OkNDevice) {
-    ExpectBugreportzVersion("1.0");
-    EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
-        .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")),
-                        WithArg<4>(ReturnCallbackDone())));
-    EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
-                                true, StrEq("pulling file.zip")))
-        .WillOnce(Return(true));
-
-    const char* args[] = {"bugreport", "file.zip"};
-    ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
-}
-
-// Tests 'adb bugreport file.zip' when it succeeds but response was sent in
-// multiple buffer writers and without progress updates.
-TEST_F(BugreportTest, OkNDeviceSplitBuffer) {
-    ExpectBugreportzVersion("1.0");
-    EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
-        .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device")),
-                        WithArg<4>(WriteOnStdout("/bugreport.zip")),
-                        WithArg<4>(ReturnCallbackDone())));
-    EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
-                                true, StrEq("pulling file.zip")))
-        .WillOnce(Return(true));
-
-    const char* args[] = {"bugreport", "file.zip"};
-    ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
-}
-
-// Tests 'adb bugreport file.zip' when it succeeds and displays progress.
-TEST_F(BugreportTest, OkProgress) {
-    ExpectBugreportzVersion("1.1");
-    ExpectProgress(1, 100);
-    ExpectProgress(10, 100);
-    ExpectProgress(50, 100);
-    ExpectProgress(99, 100);
-    // clang-format off
-    EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
-        // NOTE: DoAll accepts at most 10 arguments, and we're almost reached that limit...
-        .WillOnce(DoAll(
-            // Name might change on OK, so make sure the right one is picked.
-            WithArg<4>(WriteOnStdout("BEGIN:/device/bugreport___NOT.zip\n")),
-            // Progress line in one write
-            WithArg<4>(WriteOnStdout("PROGRESS:1/100\n")),
-            // Add some bogus lines
-            WithArg<4>(WriteOnStdout("\nDUDE:SWEET\n\nBLA\n\nBLA\nBLA\n\n")),
-            // Multiple progress lines in one write
-            WithArg<4>(WriteOnStdout("PROGRESS:10/100\nPROGRESS:50/100\n")),
-            // Progress line in multiple writes
-            WithArg<4>(WriteOnStdout("PROG")),
-            WithArg<4>(WriteOnStdout("RESS:99")),
-            WithArg<4>(WriteOnStdout("/100\n")),
-            // Split last message as well, just in case
-            WithArg<4>(WriteOnStdout("OK:/device/bugreport")),
-            WithArg<4>(WriteOnStdout(".zip")),
-            WithArg<4>(ReturnCallbackDone())));
-    // clang-format on
-    EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
-                                true, StrEq("pulling file.zip")))
-        .WillOnce(Return(true));
-
-    const char* args[] = {"bugreport", "file.zip"};
-    ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
-}
-
-// Tests 'adb bugreport dir' when it succeeds and destination is a directory.
-TEST_F(BugreportTest, OkDirectory) {
-    ExpectBugreportzVersion("1.1");
-    TemporaryDir td;
-    std::string dest_file =
-        android::base::StringPrintf("%s%cda_bugreport.zip", td.path, OS_PATH_SEPARATOR);
-
-    EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
-        .WillOnce(DoAll(WithArg<4>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
-                        WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip")),
-                        WithArg<4>(ReturnCallbackDone())));
-    EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
-                                true, StrEq("pulling da_bugreport.zip")))
-        .WillOnce(Return(true));
-
-    const char* args[] = {"bugreport", td.path};
-    ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
-}
-
-// Tests 'adb bugreport file' when it succeeds
-TEST_F(BugreportTest, OkNoExtension) {
-    ExpectBugreportzVersion("1.1");
-    EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
-        .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip\n")),
-                        WithArg<4>(ReturnCallbackDone())));
-    EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
-                                true, StrEq("pulling file.zip")))
-        .WillOnce(Return(true));
-
-    const char* args[] = {"bugreport", "file"};
-    ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
-}
-
-// Tests 'adb bugreport dir' when it succeeds and destination is a directory and device runs N.
-TEST_F(BugreportTest, OkNDeviceDirectory) {
-    ExpectBugreportzVersion("1.0");
-    TemporaryDir td;
-    std::string dest_file =
-        android::base::StringPrintf("%s%cda_bugreport.zip", td.path, OS_PATH_SEPARATOR);
-
-    EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
-        .WillOnce(DoAll(WithArg<4>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
-                        WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip")),
-                        WithArg<4>(ReturnCallbackDone())));
-    EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
-                                true, StrEq("pulling da_bugreport.zip")))
-        .WillOnce(Return(true));
-
-    const char* args[] = {"bugreport", td.path};
-    ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
-}
-
-// Tests 'adb bugreport file.zip' when the bugreport itself failed
-TEST_F(BugreportTest, BugreportzReturnedFail) {
-    ExpectBugreportzVersion("1.1");
-    EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
-        .WillOnce(
-            DoAll(WithArg<4>(WriteOnStdout("FAIL:D'OH!\n")), WithArg<4>(ReturnCallbackDone())));
-
-    CaptureStderr();
-    const char* args[] = {"bugreport", "file.zip"};
-    ASSERT_EQ(-1, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
-    ASSERT_THAT(GetCapturedStderr(), HasSubstr("D'OH!"));
-}
-
-// Tests 'adb bugreport file.zip' when the bugreport itself failed but response
-// was sent in
-// multiple buffer writes
-TEST_F(BugreportTest, BugreportzReturnedFailSplitBuffer) {
-    ExpectBugreportzVersion("1.1");
-    EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
-        .WillOnce(DoAll(WithArg<4>(WriteOnStdout("FAIL")), WithArg<4>(WriteOnStdout(":D'OH!\n")),
-                        WithArg<4>(ReturnCallbackDone())));
-
-    CaptureStderr();
-    const char* args[] = {"bugreport", "file.zip"};
-    ASSERT_EQ(-1, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
-    ASSERT_THAT(GetCapturedStderr(), HasSubstr("D'OH!"));
-}
-
-// Tests 'adb bugreport file.zip' when the bugreportz returned an unsupported
-// response.
-TEST_F(BugreportTest, BugreportzReturnedUnsupported) {
-    ExpectBugreportzVersion("1.1");
-    EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
-        .WillOnce(DoAll(WithArg<4>(WriteOnStdout("bugreportz? What am I, a zombie?")),
-                        WithArg<4>(ReturnCallbackDone())));
-
-    CaptureStderr();
-    const char* args[] = {"bugreport", "file.zip"};
-    ASSERT_EQ(-1, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
-    ASSERT_THAT(GetCapturedStderr(), HasSubstr("bugreportz? What am I, a zombie?"));
-}
-
-// Tests 'adb bugreport file.zip' when the bugreportz -v command failed
-TEST_F(BugreportTest, BugreportzVersionFailed) {
-    EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -v", false, _))
-        .WillOnce(Return(666));
-
-    const char* args[] = {"bugreport", "file.zip"};
-    ASSERT_EQ(666, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
-}
-
-// Tests 'adb bugreport file.zip' when the bugreportz -v returns status 0 but with no output.
-TEST_F(BugreportTest, BugreportzVersionEmpty) {
-    ExpectBugreportzVersion("");
-
-    const char* args[] = {"bugreport", "file.zip"};
-    ASSERT_EQ(-1, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
-}
-
-// Tests 'adb bugreport file.zip' when the main bugreportz command failed
-TEST_F(BugreportTest, BugreportzFailed) {
-    ExpectBugreportzVersion("1.1");
-    EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
-        .WillOnce(Return(666));
-
-    const char* args[] = {"bugreport", "file.zip"};
-    ASSERT_EQ(666, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
-}
-
-// Tests 'adb bugreport file.zip' when the bugreport could not be pulled
-TEST_F(BugreportTest, PullFails) {
-    ExpectBugreportzVersion("1.1");
-    EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
-        .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")),
-                        WithArg<4>(ReturnCallbackDone())));
-    EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
-                                true, HasSubstr("file.zip")))
-        .WillOnce(Return(false));
-
-    const char* args[] = {"bugreport", "file.zip"};
-    ASSERT_EQ(1, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
-}
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 4ec0fc2..fb06bd9 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -32,7 +32,6 @@
 #include "adb_auth.h"
 #include "adb_listeners.h"
 #include "adb_utils.h"
-#include "commandline.h"
 #include "transport.h"
 
 static std::string GetLogFilePath() {
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 54e254a..5c8eee7 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -54,11 +54,10 @@
 #include "adb_io.h"
 #include "adb_unique_fd.h"
 #include "adb_utils.h"
-#include "bugreport.h"
-#include "commandline.h"
 #include "file_sync_service.h"
 #include "services.h"
 #include "shell_service.h"
+#include "transport.h"
 
 static int install_app(TransportType t, const char* serial, int argc, const char** argv);
 static int install_multiple_app(TransportType t, const char* serial, int argc, const char** argv);
@@ -69,7 +68,8 @@
 static auto& gProductOutPath = *new std::string();
 extern int gListenAll;
 
-DefaultStandardStreamsCallback DEFAULT_STANDARD_STREAMS_CALLBACK(nullptr, nullptr);
+static constexpr char BUGZ_OK_PREFIX[] = "OK:";
+static constexpr char BUGZ_FAIL_PREFIX[] = "FAIL:";
 
 static std::string product_file(const char *extra) {
     if (gProductOutPath.empty()) {
@@ -229,7 +229,7 @@
     // clang-format on
 }
 
-int usage() {
+static int usage() {
     help();
     return 1;
 }
@@ -267,14 +267,17 @@
 // this expects that incoming data will use the shell protocol, in which case
 // stdout/stderr are routed independently and the remote exit code will be
 // returned.
-// if |callback| is non-null, stdout/stderr output will be handled by it.
-int read_and_dump(int fd, bool use_shell_protocol = false,
-                  StandardStreamsCallbackInterface* callback = &DEFAULT_STANDARD_STREAMS_CALLBACK) {
+// if |output| is non-null, stdout will be appended to it instead.
+// if |err| is non-null, stderr will be appended to it instead.
+static int read_and_dump(int fd, bool use_shell_protocol=false, std::string* output=nullptr,
+                         std::string* err=nullptr) {
     int exit_code = 0;
     if (fd < 0) return exit_code;
 
     std::unique_ptr<ShellProtocol> protocol;
     int length = 0;
+    FILE* outfile = stdout;
+    std::string* outstring = output;
 
     char raw_buffer[BUFSIZ];
     char* buffer_ptr = raw_buffer;
@@ -292,13 +295,14 @@
             if (!protocol->Read()) {
                 break;
             }
-            length = protocol->data_length();
             switch (protocol->id()) {
                 case ShellProtocol::kIdStdout:
-                    callback->OnStdout(buffer_ptr, length);
+                    outfile = stdout;
+                    outstring = output;
                     break;
                 case ShellProtocol::kIdStderr:
-                    callback->OnStderr(buffer_ptr, length);
+                    outfile = stderr;
+                    outstring = err;
                     break;
                 case ShellProtocol::kIdExit:
                     exit_code = protocol->data()[0];
@@ -314,11 +318,17 @@
             if (length <= 0) {
                 break;
             }
-            callback->OnStdout(buffer_ptr, length);
+        }
+
+        if (outstring == nullptr) {
+            fwrite(buffer_ptr, 1, length, outfile);
+            fflush(outfile);
+        } else {
+            outstring->append(buffer_ptr, length);
         }
     }
 
-    return callback->Done(exit_code);
+    return exit_code;
 }
 
 static void read_status_line(int fd, char* buf, size_t count)
@@ -336,7 +346,19 @@
     *buf = '\0';
 }
 
-static void stdinout_raw_prologue(int inFd, int outFd, int& old_stdin_mode, int& old_stdout_mode) {
+static void copy_to_file(int inFd, int outFd) {
+    const size_t BUFSIZE = 32 * 1024;
+    char* buf = (char*) malloc(BUFSIZE);
+    if (buf == nullptr) fatal("couldn't allocate buffer for copy_to_file");
+    int len;
+    long total = 0;
+#ifdef _WIN32
+    int old_stdin_mode = -1;
+    int old_stdout_mode = -1;
+#endif
+
+    D("copy_to_file(%d -> %d)", inFd, outFd);
+
     if (inFd == STDIN_FILENO) {
         stdin_raw_init();
 #ifdef _WIN32
@@ -355,39 +377,6 @@
         }
     }
 #endif
-}
-
-static void stdinout_raw_epilogue(int inFd, int outFd, int old_stdin_mode, int old_stdout_mode) {
-    if (inFd == STDIN_FILENO) {
-        stdin_raw_restore();
-#ifdef _WIN32
-        if (_setmode(STDIN_FILENO, old_stdin_mode) == -1) {
-            fatal_errno("could not restore stdin mode");
-        }
-#endif
-    }
-
-#ifdef _WIN32
-    if (outFd == STDOUT_FILENO) {
-        if (_setmode(STDOUT_FILENO, old_stdout_mode) == -1) {
-            fatal_errno("could not restore stdout mode");
-        }
-    }
-#endif
-}
-
-static void copy_to_file(int inFd, int outFd) {
-    const size_t BUFSIZE = 32 * 1024;
-    char* buf = (char*) malloc(BUFSIZE);
-    if (buf == nullptr) fatal("couldn't allocate buffer for copy_to_file");
-    int len;
-    long total = 0;
-    int old_stdin_mode = -1;
-    int old_stdout_mode = -1;
-
-    D("copy_to_file(%d -> %d)", inFd, outFd);
-
-    stdinout_raw_prologue(inFd, outFd, old_stdin_mode, old_stdout_mode);
 
     while (true) {
         if (inFd == STDIN_FILENO) {
@@ -412,7 +401,22 @@
         total += len;
     }
 
-    stdinout_raw_epilogue(inFd, outFd, old_stdin_mode, old_stdout_mode);
+    if (inFd == STDIN_FILENO) {
+        stdin_raw_restore();
+#ifdef _WIN32
+        if (_setmode(STDIN_FILENO, old_stdin_mode) == -1) {
+            fatal_errno("could not restore stdin mode");
+        }
+#endif
+    }
+
+#ifdef _WIN32
+    if (outFd == STDOUT_FILENO) {
+        if (_setmode(STDOUT_FILENO, old_stdout_mode) == -1) {
+            fatal_errno("could not restore stdout mode");
+        }
+    }
+#endif
 
     D("copy_to_file() finished after %lu bytes", total);
     free(buf);
@@ -1084,16 +1088,20 @@
     return true;
 }
 
-int send_shell_command(TransportType transport_type, const char* serial, const std::string& command,
-                       bool disable_shell_protocol, StandardStreamsCallbackInterface* callback) {
+// Connects to the device "shell" service with |command| and prints the
+// resulting output.
+static int send_shell_command(TransportType transport_type, const char* serial,
+                              const std::string& command,
+                              bool disable_shell_protocol,
+                              std::string* output=nullptr,
+                              std::string* err=nullptr) {
     int fd;
     bool use_shell_protocol = false;
 
     while (true) {
         bool attempt_connection = true;
 
-        // Use shell protocol if it's supported and the caller doesn't explicitly
-        // disable it.
+        // Use shell protocol if it's supported and the caller doesn't explicitly disable it.
         if (!disable_shell_protocol) {
             FeatureSet features;
             std::string error;
@@ -1115,13 +1123,13 @@
             }
         }
 
-        fprintf(stderr, "- waiting for device -\n");
+        fprintf(stderr,"- waiting for device -\n");
         if (!wait_for_device("wait-for-device", transport_type, serial)) {
             return 1;
         }
     }
 
-    int exit_code = read_and_dump(fd, use_shell_protocol, callback);
+    int exit_code = read_and_dump(fd, use_shell_protocol, output, err);
 
     if (adb_close(fd) < 0) {
         PLOG(ERROR) << "failure closing FD " << fd;
@@ -1130,6 +1138,45 @@
     return exit_code;
 }
 
+static int bugreport(TransportType transport_type, const char* serial, int argc,
+                     const char** argv) {
+    if (argc == 1) return send_shell_command(transport_type, serial, "bugreport", false);
+    if (argc != 2) return usage();
+
+    // Zipped bugreport option - will call 'bugreportz', which prints the location of the generated
+    // file, then pull it to the destination file provided by the user.
+    std::string dest_file = argv[1];
+    if (!android::base::EndsWith(argv[1], ".zip")) {
+        // TODO: use a case-insensitive comparison (like EndsWithIgnoreCase
+        dest_file += ".zip";
+    }
+    std::string output;
+
+    fprintf(stderr, "Bugreport is in progress and it could take minutes to complete.\n"
+            "Please be patient and do not cancel or disconnect your device until it completes.\n");
+    int status = send_shell_command(transport_type, serial, "bugreportz", false, &output, nullptr);
+    if (status != 0 || output.empty()) return status;
+    output = android::base::Trim(output);
+
+    if (android::base::StartsWith(output, BUGZ_OK_PREFIX)) {
+        const char* zip_file = &output[strlen(BUGZ_OK_PREFIX)];
+        std::vector<const char*> srcs{zip_file};
+        status = do_sync_pull(srcs, dest_file.c_str(), true, dest_file.c_str()) ? 0 : 1;
+        if (status != 0) {
+            fprintf(stderr, "Could not copy file '%s' to '%s'\n", zip_file, dest_file.c_str());
+        }
+        return status;
+    }
+    if (android::base::StartsWith(output, BUGZ_FAIL_PREFIX)) {
+        const char* error_message = &output[strlen(BUGZ_FAIL_PREFIX)];
+        fprintf(stderr, "Device failed to take a zipped bugreport: %s\n", error_message);
+        return -1;
+    }
+    fprintf(stderr, "Unexpected string (%s) returned by bugreportz, "
+            "device probably does not support -z option\n", output.c_str());
+    return -1;
+}
+
 static int logcat(TransportType transport, const char* serial, int argc, const char** argv) {
     char* log_tags = getenv("ANDROID_LOG_TAGS");
     std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
@@ -1150,29 +1197,6 @@
     return send_shell_command(transport, serial, cmd, true);
 }
 
-static void write_zeros(int bytes, int fd) {
-    int old_stdin_mode = -1;
-    int old_stdout_mode = -1;
-    char* buf = (char*) calloc(1, bytes);
-    if (buf == nullptr) fatal("couldn't allocate buffer for write_zeros");
-
-    D("write_zeros(%d) -> %d", bytes, fd);
-
-    stdinout_raw_prologue(-1, fd, old_stdin_mode, old_stdout_mode);
-
-    if (fd == STDOUT_FILENO) {
-        fwrite(buf, 1, bytes, stdout);
-        fflush(stdout);
-    } else {
-        adb_write(fd, buf, bytes);
-    }
-
-    stdinout_raw_prologue(-1, fd, old_stdin_mode, old_stdout_mode);
-
-    D("write_zeros() finished");
-    free(buf);
-}
-
 static int backup(int argc, const char** argv) {
     const char* filename = "backup.ab";
 
@@ -1253,9 +1277,6 @@
     printf("Now unlock your device and confirm the restore operation.\n");
     copy_to_file(tarFd, fd);
 
-    // Provide an in-band EOD marker in case the archive file is malformed
-    write_zeros(512*2, fd);
-
     // Wait until the other side finishes, or it'll get sent SIGHUP.
     copy_to_file(fd, STDOUT_FILENO);
 
@@ -1291,7 +1312,7 @@
     if (hint.find_first_of(OS_PATH_SEPARATORS) != std::string::npos) {  // NOLINT
         std::string cwd;
         if (!getcwd(&cwd)) {
-            perror("adb: getcwd failed");
+            fprintf(stderr, "adb: getcwd failed: %s\n", strerror(errno));
             return "";
         }
         return android::base::StringPrintf("%s%c%s", cwd.c_str(), OS_PATH_SEPARATOR, hint.c_str());
@@ -1391,16 +1412,6 @@
 #endif
 }
 
-static bool _use_legacy_install() {
-    FeatureSet features;
-    std::string error;
-    if (!adb_get_feature_set(&features, &error)) {
-        fprintf(stderr, "error: %s\n", error.c_str());
-        return true;
-    }
-    return !CanUseFeature(features, kFeatureCmd);
-}
-
 int adb_commandline(int argc, const char **argv) {
     int no_daemon = 0;
     int is_daemon = 0;
@@ -1722,8 +1733,7 @@
     } else if (!strcmp(argv[0], "root") || !strcmp(argv[0], "unroot")) {
         return adb_root(argv[0]) ? 0 : 1;
     } else if (!strcmp(argv[0], "bugreport")) {
-        Bugreport bugreport;
-        return bugreport.DoIt(transport_type, serial, argc, argv);
+        return bugreport(transport_type, serial, argc, argv);
     } else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
         bool reverse = !strcmp(argv[0], "reverse");
         ++argv;
@@ -1817,10 +1827,17 @@
     }
     else if (!strcmp(argv[0], "install")) {
         if (argc < 2) return usage();
-        if (_use_legacy_install()) {
-            return install_app_legacy(transport_type, serial, argc, argv);
+        FeatureSet features;
+        std::string error;
+        if (!adb_get_feature_set(&features, &error)) {
+            fprintf(stderr, "error: %s\n", error.c_str());
+            return 1;
         }
-        return install_app(transport_type, serial, argc, argv);
+
+        if (CanUseFeature(features, kFeatureCmd)) {
+            return install_app(transport_type, serial, argc, argv);
+        }
+        return install_app_legacy(transport_type, serial, argc, argv);
     }
     else if (!strcmp(argv[0], "install-multiple")) {
         if (argc < 2) return usage();
@@ -1828,10 +1845,17 @@
     }
     else if (!strcmp(argv[0], "uninstall")) {
         if (argc < 2) return usage();
-        if (_use_legacy_install()) {
-            return uninstall_app_legacy(transport_type, serial, argc, argv);
+        FeatureSet features;
+        std::string error;
+        if (!adb_get_feature_set(&features, &error)) {
+            fprintf(stderr, "error: %s\n", error.c_str());
+            return 1;
         }
-        return uninstall_app(transport_type, serial, argc, argv);
+
+        if (CanUseFeature(features, kFeatureCmd)) {
+            return uninstall_app(transport_type, serial, argc, argv);
+        }
+        return uninstall_app_legacy(transport_type, serial, argc, argv);
     }
     else if (!strcmp(argv[0], "sync")) {
         std::string src;
@@ -2045,6 +2069,7 @@
     int i;
     struct stat sb;
     uint64_t total_size = 0;
+
     // Find all APK arguments starting at end.
     // All other arguments passed through verbatim.
     int first_apk = -1;
@@ -2069,14 +2094,7 @@
         return 1;
     }
 
-    std::string install_cmd;
-    if (_use_legacy_install()) {
-        install_cmd = "exec:pm";
-    } else {
-        install_cmd = "exec:cmd package";
-    }
-
-    std::string cmd = android::base::StringPrintf("%s install-create -S %" PRIu64, install_cmd.c_str(), total_size);
+    std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
     for (i = 1; i < first_apk; i++) {
         cmd += " " + escape_arg(argv[i]);
     }
@@ -2118,8 +2136,8 @@
         }
 
         std::string cmd = android::base::StringPrintf(
-                "%s install-write -S %" PRIu64 " %d %d_%s -",
-                install_cmd.c_str(), static_cast<uint64_t>(sb.st_size), session_id, i, adb_basename(file).c_str());
+                "exec:pm install-write -S %" PRIu64 " %d %d_%s -",
+                static_cast<uint64_t>(sb.st_size), session_id, i, adb_basename(file).c_str());
 
         int localFd = adb_open(file, O_RDONLY);
         if (localFd < 0) {
@@ -2154,8 +2172,8 @@
 finalize_session:
     // Commit session if we streamed everything okay; otherwise abandon
     std::string service =
-            android::base::StringPrintf("%s install-%s %d",
-                                        install_cmd.c_str(), success ? "commit" : "abandon", session_id);
+            android::base::StringPrintf("exec:pm install-%s %d",
+                                        success ? "commit" : "abandon", session_id);
     fd = adb_connect(service, &error);
     if (fd < 0) {
         fprintf(stderr, "Connect error for finalize: %s\n", error.c_str());
diff --git a/adb/commandline.h b/adb/commandline.h
deleted file mode 100644
index 0cf655c..0000000
--- a/adb/commandline.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COMMANDLINE_H
-#define COMMANDLINE_H
-
-#include "adb.h"
-
-// Callback used to handle the standard streams (stdout and stderr) sent by the
-// device's upon receiving a command.
-//
-class StandardStreamsCallbackInterface {
-  public:
-    StandardStreamsCallbackInterface() {
-    }
-    // Handles the stdout output from devices supporting the Shell protocol.
-    virtual void OnStdout(const char* buffer, int length) = 0;
-
-    // Handles the stderr output from devices supporting the Shell protocol.
-    virtual void OnStderr(const char* buffer, int length) = 0;
-
-    // Indicates the communication is finished and returns the appropriate error
-    // code.
-    //
-    // |status| has the status code returning by the underlying communication
-    // channels
-    virtual int Done(int status) = 0;
-
-  protected:
-    static void OnStream(std::string* string, FILE* stream, const char* buffer, int length) {
-        if (string != nullptr) {
-            string->append(buffer, length);
-        } else {
-            fwrite(buffer, 1, length, stream);
-            fflush(stream);
-        }
-    }
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(StandardStreamsCallbackInterface);
-};
-
-// Default implementation that redirects the streams to the equilavent host
-// stream or to a string
-// passed to the constructor.
-class DefaultStandardStreamsCallback : public StandardStreamsCallbackInterface {
-  public:
-    // If |stdout_str| is non-null, OnStdout will append to it.
-    // If |stderr_str| is non-null, OnStderr will append to it.
-    DefaultStandardStreamsCallback(std::string* stdout_str, std::string* stderr_str)
-        : stdout_str_(stdout_str), stderr_str_(stderr_str) {
-    }
-
-    void OnStdout(const char* buffer, int length) {
-        OnStream(stdout_str_, stdout, buffer, length);
-    }
-
-    void OnStderr(const char* buffer, int length) {
-        OnStream(stderr_str_, stderr, buffer, length);
-    }
-
-    int Done(int status) {
-        return status;
-    }
-
-  private:
-    std::string* stdout_str_;
-    std::string* stderr_str_;
-
-    DISALLOW_COPY_AND_ASSIGN(DefaultStandardStreamsCallback);
-};
-
-// Singleton.
-extern DefaultStandardStreamsCallback DEFAULT_STANDARD_STREAMS_CALLBACK;
-
-int adb_commandline(int argc, const char** argv);
-int usage();
-
-// Connects to the device "shell" service with |command| and prints the
-// resulting output.
-// if |callback| is non-null, stdout/stderr output will be handled by it.
-int send_shell_command(TransportType transport_type, const char* serial, const std::string& command,
-                       bool disable_shell_protocol, StandardStreamsCallbackInterface* callback =
-                                                        &DEFAULT_STANDARD_STREAMS_CALLBACK);
-
-#endif  // COMMANDLINE_H