DO NOT MERGE: Refactored functions that copy sdout and stderr to strings to use a callback.
am: 0d4f0508c0 -s ours
Change-Id: I4e6d14b35be89869d6853d1d4ba155823fa207e1
diff --git a/adb/Android.mk b/adb/Android.mk
index 5a0780c..1aa3dc1 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -184,9 +184,6 @@
LOCAL_CFLAGS_darwin := $(LIBADB_darwin_CFLAGS)
LOCAL_SRC_FILES := \
$(LIBADB_TEST_SRCS) \
- adb_client.cpp \
- bugreport.cpp \
- bugreport_test.cpp \
services.cpp \
shell_service_protocol.cpp \
shell_service_protocol_test.cpp \
@@ -202,7 +199,6 @@
libcrypto \
libcutils \
libdiagnose_usb \
- libgmock_host \
# Set entrypoint to wmain from sysdeps_win32.cpp instead of main
LOCAL_LDFLAGS_windows := -municode
@@ -231,7 +227,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 cd6b7bd..9227eb1 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -203,6 +203,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 9f9eb1f..d5cd922 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 e267f0f..0000000
--- a/adb/bugreport.cpp
+++ /dev/null
@@ -1,104 +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 <string>
-
-#include <android-base/strings.h>
-
-#include "bugreport.h"
-#include "file_sync_service.h"
-
-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_file, Bugreport* br)
- : br_(br), dest_file_(dest_file), stdout_str_() {
- }
-
- void OnStdout(const char* buffer, int length) {
- std::string output;
- OnStream(&output, stdout, buffer, length);
- stdout_str_.append(output);
- }
-
- void OnStderr(const char* buffer, int length) {
- OnStream(nullptr, stderr, buffer, length);
- }
-
- int Done(int unused_) {
- int status = -1;
- std::string output = android::base::Trim(stdout_str_);
- 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 = br_->DoSyncPull(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());
- }
- } else 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);
- } else {
- fprintf(stderr,
- "Unexpected string (%s) returned by bugreportz, "
- "device probably does not support it\n",
- output.c_str());
- }
-
- return status;
- }
-
- private:
- Bugreport* br_;
- const std::string dest_file_;
- std::string stdout_str_;
-
- DISALLOW_COPY_AND_ASSIGN(BugreportStandardStreamsCallback);
-};
-
-int Bugreport::DoIt(TransportType transport_type, const char* serial, int argc, const char** argv) {
- if (argc == 1) return SendShellCommand(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";
- }
- 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");
- BugreportStandardStreamsCallback bugz_callback(dest_file, this);
- return SendShellCommand(transport_type, serial, "bugreportz", false, &bugz_callback);
-}
-
-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 1c39a9f..0000000
--- a/adb/bugreport.h
+++ /dev/null
@@ -1,48 +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"
-
-class Bugreport {
- friend class BugreportStandardStreamsCallback;
-
- public:
- Bugreport() {
- }
- 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:
- 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 15c6f83..0000000
--- a/adb/bugreport_test.cpp
+++ /dev/null
@@ -1,215 +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>
-
-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::GetCapturedStderr;
-
-// 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;
-}
-
-// gmock black magic to provide a WithArg<4>(WriteOnStdout(output)) matcher
-typedef void OnStandardStreamsCallbackFunction(StandardStreamsCallbackInterface*);
-
-class OnStandardStreamsCallbackAction : public ActionInterface<OnStandardStreamsCallbackFunction> {
- public:
- explicit OnStandardStreamsCallbackAction(const std::string& output) : output_(output) {
- }
- virtual Result Perform(const ArgumentTuple& args) {
- ::std::tr1::get<0>(args)->OnStdout(output_.c_str(), output_.size());
- }
-
- private:
- std::string output_;
-};
-
-Action<OnStandardStreamsCallbackFunction> WriteOnStdout(const std::string& output) {
- return MakeAction(new OnStandardStreamsCallbackAction(output));
-}
-
-typedef int CallbackDoneFunction(StandardStreamsCallbackInterface*);
-
-class CallbackDoneAction : public ActionInterface<CallbackDoneFunction> {
- public:
- virtual Result Perform(const ArgumentTuple& args) {
- int status = ::std::tr1::get<0>(args)->Done(123); // Value passed does not matter
- return status;
- }
-};
-
-Action<CallbackDoneFunction> ReturnCallbackDone() {
- return MakeAction(new CallbackDoneAction());
-}
-
-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));
-};
-
-class BugreportTest : public ::testing::Test {
- public:
- BugreportMock br_;
-};
-
-// Tests when called with invalid number of argumnts
-TEST_F(BugreportTest, InvalidNumberArgs) {
- const char* args[1024] = {"bugreport", "to", "principal"};
- ASSERT_EQ(-42, br_.DoIt(kTransportLocal, "HannibalLecter", 3, args));
-}
-
-// Tests the legacy 'adb bugreport' option
-TEST_F(BugreportTest, FlatFileFormat) {
- EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreport", false, _))
- .WillOnce(Return(0));
-
- const char* args[1024] = {"bugreport"};
- ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 1, args));
-}
-
-// Tests 'adb bugreport file.zip' when it succeeds
-TEST_F(BugreportTest, Ok) {
- 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("file.zip")))
- .WillOnce(Return(true));
-
- const char* args[1024] = {"bugreport", "file.zip"};
- ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
-}
-
-// Tests 'adb bugreport file' when it succeeds
-TEST_F(BugreportTest, OkNoExtension) {
- 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("file.zip")))
- .WillOnce(Return(true));
-
- const char* args[1024] = {"bugreport", "file"};
- 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.
-TEST_F(BugreportTest, OkSplitBuffer) {
- 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("file.zip")))
- .WillOnce(Return(true));
-
- const char* args[1024] = {"bugreport", "file.zip"};
- ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
-}
-
-// Tests 'adb bugreport file.zip' when the bugreport itself failed
-TEST_F(BugreportTest, BugreportzReturnedFail) {
- EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
- .WillOnce(DoAll(WithArg<4>(WriteOnStdout("FAIL:D'OH!")), WithArg<4>(ReturnCallbackDone())));
-
- CaptureStderr();
- const char* args[1024] = {"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) {
- EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
- .WillOnce(DoAll(WithArg<4>(WriteOnStdout("FAIL")), WithArg<4>(WriteOnStdout(":D'OH!")),
- WithArg<4>(ReturnCallbackDone())));
-
- CaptureStderr();
- const char* args[1024] = {"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) {
- EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
- .WillOnce(DoAll(WithArg<4>(WriteOnStdout("bugreportz? What am I, a zombie?")),
- WithArg<4>(ReturnCallbackDone())));
-
- CaptureStderr();
- const char* args[1024] = {"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 command fails
-TEST_F(BugreportTest, BugreportzFailed) {
- EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
- .WillOnce(Return(666));
-
- const char* args[1024] = {"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) {
- 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("file.zip")))
- .WillOnce(Return(false));
-
- const char* args[1024] = {"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 0c85fe5..e160169 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 74a3451..8aab389 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -52,11 +52,10 @@
#include "adb_client.h"
#include "adb_io.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);
@@ -67,7 +66,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()) {
@@ -254,7 +254,7 @@
);
}
-int usage() {
+static int usage() {
help();
return 1;
}
@@ -292,14 +292,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;
@@ -317,13 +320,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];
@@ -339,11 +343,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)
@@ -361,7 +371,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
@@ -380,39 +402,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) {
@@ -437,7 +426,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);
@@ -1109,16 +1113,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;
@@ -1140,13 +1148,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;
@@ -1155,6 +1163,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);
@@ -1175,29 +1222,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";
@@ -1278,9 +1302,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);
@@ -1416,16 +1437,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;
@@ -1726,8 +1737,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;
@@ -1821,10 +1831,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();
@@ -1832,10 +1849,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;
@@ -2049,6 +2073,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;
@@ -2073,14 +2098,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]);
}
@@ -2122,8 +2140,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) {
@@ -2158,8 +2176,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
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 840ac86..2922ec4 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -142,6 +142,10 @@
{ 00750, AID_ROOT, AID_SHELL, CAP_MASK_LONG(CAP_SETUID) | CAP_MASK_LONG(CAP_SETGID), "system/bin/run-as" },
{ 00700, AID_SYSTEM, AID_SHELL, CAP_MASK_LONG(CAP_BLOCK_SUSPEND), "system/bin/inputflinger" },
+ /* Support hostapd administering a network interface. */
+ { 00755, AID_WIFI, AID_WIFI, CAP_MASK_LONG(CAP_NET_ADMIN) |
+ CAP_MASK_LONG(CAP_NET_RAW), "system/bin/hostapd" },
+
{ 00750, AID_ROOT, AID_ROOT, 0, "system/bin/uncrypt" },
{ 00750, AID_ROOT, AID_ROOT, 0, "system/bin/install-recovery.sh" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin/*" },