Merge \\\"libnativeloader: convert Android.mk to Android.bp\\\" am: 5783dea065 am: 627112a87e
am: 3032c5ccbe
Change-Id: I6e0a190a24be3d7923607b9769dd1938b887f6a5
diff --git a/adb/Android.mk b/adb/Android.mk
index 0babf1d..0cdda3d 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -181,6 +181,10 @@
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 \
@@ -196,6 +200,7 @@
libcrypto_static \
libcutils \
libdiagnose_usb \
+ libgmock_host \
# Set entrypoint to wmain from sysdeps_win32.cpp instead of main
LOCAL_LDFLAGS_windows := -municode
@@ -224,6 +229,7 @@
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 9227eb1..cd6b7bd 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -203,8 +203,6 @@
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 d5cd922..9f9eb1f 100644
--- a/adb/adb_client.h
+++ b/adb/adb_client.h
@@ -18,6 +18,7 @@
#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
new file mode 100644
index 0000000..8a3eb08
--- /dev/null
+++ b/adb/bugreport.cpp
@@ -0,0 +1,179 @@
+/*
+ * 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:";
+static constexpr char BUGZ_PROGRESS_PREFIX[] = "PROGRESS:";
+static constexpr char BUGZ_PROGRESS_SEPARATOR[] = "/";
+
+// Custom callback used to handle the output of zipped bugreports.
+class BugreportStandardStreamsCallback : public StandardStreamsCallbackInterface {
+ public:
+ BugreportStandardStreamsCallback(const std::string& dest_file, bool show_progress, Bugreport* br)
+ : br_(br), dest_file_(dest_file), show_progress_(show_progress), status_(-1), line_() {
+ }
+
+ 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_);
+ // ..then return.
+ return status_;
+ }
+
+ private:
+ void ProcessLine(const std::string& line) {
+ if (line.empty()) return;
+
+ if (android::base::StartsWith(line, BUGZ_OK_PREFIX)) {
+ if (show_progress_) {
+ // Make sure pull message doesn't conflict with generation message.
+ br_->UpdateProgress(dest_file_, 100, 100, true);
+ }
+
+ const char* zip_file = &line[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(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(dest_file_, progress, total);
+ } else {
+ fprintf(stderr,
+ "WARNING: unexpected line (%s) returned by bugreportz, "
+ "device probably does not support zipped bugreports.\n"
+ "Try 'adb bugreport' instead.",
+ line.c_str());
+ }
+ }
+
+ Bugreport* br_;
+ const std::string dest_file_;
+ bool show_progress_;
+ 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 == 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";
+ }
+
+ // Gets bugreportz version.
+ std::string bugz_stderr;
+ DefaultStandardStreamsCallback version_callback(nullptr, &bugz_stderr);
+ int status = SendShellCommand(transport_type, serial, "bugreportz -v", false, &version_callback);
+
+ if (status != 0) {
+ fprintf(stderr,
+ "Failed to get bugreportz version: 'bugreport -v' returned '%s' "
+ "(code %d)."
+ "\nIf the device does not support it, try running 'adb bugreport' "
+ "to get a "
+ "flat-file bugreport.",
+ bugz_stderr.c_str(), status);
+ return status;
+ }
+ std::string bugz_version = android::base::Trim(bugz_stderr);
+
+ 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_file, show_progress, this);
+ return SendShellCommand(transport_type, serial, bugz_command, false, &bugz_callback);
+}
+
+void Bugreport::UpdateProgress(const std::string& file_name, int progress, int total,
+ bool keep_info_line) {
+ int progress_percentage = (progress * 100 / total);
+ line_printer_.Print(android::base::StringPrintf("[%3d%%] generating %s", progress_percentage,
+ file_name.c_str()),
+ LinePrinter::INFO);
+ if (keep_info_line) {
+ line_printer_.KeepInfoLine();
+ }
+}
+
+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
new file mode 100644
index 0000000..fd11a4a
--- /dev/null
+++ b/adb/bugreport.h
@@ -0,0 +1,52 @@
+/*
+ * 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,
+ bool keep_info_line = false);
+ LinePrinter line_printer_;
+ DISALLOW_COPY_AND_ASSIGN(Bugreport);
+};
+
+#endif // BUGREPORT_H
diff --git a/adb/bugreport_test.cpp b/adb/bugreport_test.cpp
new file mode 100644
index 0000000..e695b24
--- /dev/null
+++ b/adb/bugreport_test.cpp
@@ -0,0 +1,307 @@
+/*
+ * 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;
+}
+
+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_METHOD4(UpdateProgress, void(const std::string&, int, int, bool));
+};
+
+class BugreportTest : public ::testing::Test {
+ public:
+ void SetBugreportzVersion(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, bool keep_info_line = false) {
+ EXPECT_CALL(br_, UpdateProgress(StrEq("file.zip"), progress, total, keep_info_line));
+ }
+
+ 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 and device does not support
+// progress.
+TEST_F(BugreportTest, OkLegacy) {
+ SetBugreportzVersion("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("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 it succeeds but response was sent in
+// multiple buffer writers and without progress updates.
+TEST_F(BugreportTest, OkLegacySplitBuffer) {
+ SetBugreportzVersion("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("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 it succeeds and displays progress.
+TEST_F(BugreportTest, Ok) {
+ SetBugreportzVersion("1.1");
+ ExpectProgress(1, 100);
+ ExpectProgress(10, 100);
+ ExpectProgress(50, 100);
+ ExpectProgress(99, 100);
+ ExpectProgress(100, 100, true);
+ // clang-format off
+ EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
+ .WillOnce(DoAll(
+ // Progress line in one write
+ WithArg<4>(WriteOnStdout("PROGRESS:1/100\n")),
+ // Add some bogus lines
+ WithArg<4>(WriteOnStdout("\nDUDE:SWEET\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())));
+ 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) {
+ SetBugreportzVersion("1.1");
+ ExpectProgress(100, 100, true);
+ 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("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 the bugreport itself failed
+TEST_F(BugreportTest, BugreportzReturnedFail) {
+ SetBugreportzVersion("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[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) {
+ SetBugreportzVersion("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[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) {
+ SetBugreportzVersion("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[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 -v command failed
+TEST_F(BugreportTest, BugreportzVersionFailed) {
+ EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -v", 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 main bugreportz command failed
+TEST_F(BugreportTest, BugreportzFailed) {
+ SetBugreportzVersion("1.1");
+ EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", 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) {
+ SetBugreportzVersion("1.1");
+ ExpectProgress(100, 100, true);
+ 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, 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 d2ca44e..894ebd1 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -32,6 +32,7 @@
#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 eefbc83..ab05b63 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -52,10 +52,11 @@
#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);
@@ -66,8 +67,7 @@
static auto& gProductOutPath = *new std::string();
extern int gListenAll;
-static constexpr char BUGZ_OK_PREFIX[] = "OK:";
-static constexpr char BUGZ_FAIL_PREFIX[] = "FAIL:";
+DefaultStandardStreamsCallback DEFAULT_STANDARD_STREAMS_CALLBACK(nullptr, nullptr);
static std::string product_file(const char *extra) {
if (gProductOutPath.empty()) {
@@ -254,7 +254,7 @@
);
}
-static int usage() {
+int usage() {
help();
return 1;
}
@@ -292,17 +292,14 @@
// 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 |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) {
+// 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) {
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;
@@ -320,14 +317,13 @@
if (!protocol->Read()) {
break;
}
+ length = protocol->data_length();
switch (protocol->id()) {
case ShellProtocol::kIdStdout:
- outfile = stdout;
- outstring = output;
+ callback->OnStdout(buffer_ptr, length);
break;
case ShellProtocol::kIdStderr:
- outfile = stderr;
- outstring = err;
+ callback->OnStderr(buffer_ptr, length);
break;
case ShellProtocol::kIdExit:
exit_code = protocol->data()[0];
@@ -343,17 +339,11 @@
if (length <= 0) {
break;
}
- }
-
- if (outstring == nullptr) {
- fwrite(buffer_ptr, 1, length, outfile);
- fflush(outfile);
- } else {
- outstring->append(buffer_ptr, length);
+ callback->OnStdout(buffer_ptr, length);
}
}
- return exit_code;
+ return callback->Done(exit_code);
}
static void read_status_line(int fd, char* buf, size_t count)
@@ -371,19 +361,7 @@
*buf = '\0';
}
-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);
-
+static void stdinout_raw_prologue(int inFd, int outFd, int& old_stdin_mode, int& old_stdout_mode) {
if (inFd == STDIN_FILENO) {
stdin_raw_init();
#ifdef _WIN32
@@ -402,6 +380,39 @@
}
}
#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) {
@@ -426,22 +437,7 @@
total += len;
}
- 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
+ stdinout_raw_epilogue(inFd, outFd, old_stdin_mode, old_stdout_mode);
D("copy_to_file() finished after %lu bytes", total);
free(buf);
@@ -1113,20 +1109,16 @@
return true;
}
-// 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 send_shell_command(TransportType transport_type, const char* serial, const std::string& command,
+ bool disable_shell_protocol, StandardStreamsCallbackInterface* callback) {
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;
@@ -1148,13 +1140,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, output, err);
+ int exit_code = read_and_dump(fd, use_shell_protocol, callback);
if (adb_close(fd) < 0) {
PLOG(ERROR) << "failure closing FD " << fd;
@@ -1163,45 +1155,6 @@
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);
@@ -1222,6 +1175,29 @@
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";
@@ -1302,6 +1278,9 @@
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);
@@ -1746,7 +1725,8 @@
} else if (!strcmp(argv[0], "root") || !strcmp(argv[0], "unroot")) {
return adb_root(argv[0]) ? 0 : 1;
} else if (!strcmp(argv[0], "bugreport")) {
- return bugreport(transport_type, serial, argc, argv);
+ Bugreport bugreport;
+ return bugreport.DoIt(transport_type, serial, argc, argv);
} else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
bool reverse = !strcmp(argv[0], "reverse");
++argv;
diff --git a/adb/commandline.h b/adb/commandline.h
new file mode 100644
index 0000000..0cf655c
--- /dev/null
+++ b/adb/commandline.h
@@ -0,0 +1,99 @@
+/*
+ * 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/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index aeef43d..5dde490 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -99,20 +99,42 @@
};
static struct {
- char img_name[13];
- char sig_name[13];
+ char img_name[17];
+ char sig_name[17];
char part_name[9];
bool is_optional;
+ bool is_secondary;
} images[] = {
- {"boot.img", "boot.sig", "boot", false},
- {"recovery.img", "recovery.sig", "recovery", true},
- {"system.img", "system.sig", "system", false},
- {"vendor.img", "vendor.sig", "vendor", true},
+ {"boot.img", "boot.sig", "boot", false, false},
+ {"boot_other.img", "boot.sig", "boot", true, true},
+ {"recovery.img", "recovery.sig", "recovery", true, false},
+ {"system.img", "system.sig", "system", false, false},
+ {"system_other.img", "system.sig", "system", true, true},
+ {"vendor.img", "vendor.sig", "vendor", true, false},
+ {"vendor_other.img", "vendor.sig", "vendor", true, true},
};
-static std::string find_item(const char* item, const char* product) {
+static std::string find_item_given_name(const char* img_name, const char* product) {
+ char *dir;
+
+ if(product) {
+ std::string path = get_my_path();
+ return android::base::StringPrintf("%s/../../../target/product/%s/%s",
+ path.c_str(), product, img_name);
+ }
+
+ dir = getenv("ANDROID_PRODUCT_OUT");
+ if((dir == 0) || (dir[0] == 0)) {
+ die("neither -p product specified nor ANDROID_PRODUCT_OUT set");
+ }
+
+ return android::base::StringPrintf("%s/%s", dir, img_name);
+}
+
+std::string find_item(const char* item, const char* product) {
const char *fn;
- if (!strcmp(item,"boot")) {
+
+ if(!strcmp(item,"boot")) {
fn = "boot.img";
} else if(!strcmp(item,"recovery")) {
fn = "recovery.img";
@@ -131,19 +153,7 @@
return "";
}
- if (product) {
- std::string path = get_my_path();
- path.erase(path.find_last_of('/'));
- return android::base::StringPrintf("%s/../../../target/product/%s/%s",
- path.c_str(), product, fn);
- }
-
- char* dir = getenv("ANDROID_PRODUCT_OUT");
- if (dir == nullptr || dir[0] == '\0') {
- die("neither -p product specified nor ANDROID_PRODUCT_OUT set");
- }
-
- return android::base::StringPrintf("%s/%s", dir, fn);
+ return find_item_given_name(fn, product);
}
static int64_t get_file_size(int fd) {
@@ -309,8 +319,13 @@
"\n"
"commands:\n"
" update <filename> Reflash device from update.zip.\n"
+ " Sets the flashed slot as active.\n"
" flashall Flash boot, system, vendor, and --\n"
- " if found -- recovery.\n"
+ " if found -- recovery. If the device\n"
+ " supports slots, the slot that has\n"
+ " been flashed to is set as active.\n"
+ " Secondary images may be flashed to\n"
+ " an inactive slot.\n"
" flash <partition> [ <filename> ] Write a file to a flash partition.\n"
" flashing lock Locks the device. Prevents flashing.\n"
" flashing unlock Unlocks the device. Allows flashing\n"
@@ -333,7 +348,7 @@
" override the fs type and/or size\n"
" the bootloader reports.\n"
" getvar <variable> Display a bootloader variable.\n"
- " set_active <suffix> Sets the active slot. If slots are\n"
+ " set_active <slot> Sets the active slot. If slots are\n"
" not supported, this does nothing.\n"
" boot <kernel> [ <ramdisk> [ <second> ] ] Download and boot kernel.\n"
" flash:raw boot <kernel> [ <ramdisk> [ <second> ] ]\n"
@@ -370,19 +385,24 @@
" (default: 2048).\n"
" -S <size>[K|M|G] Automatically sparse files greater\n"
" than 'size'. 0 to disable.\n"
- " --slot <suffix> Specify slot suffix to be used if the\n"
- " device supports slots. This will be\n"
- " added to all partition names that use\n"
- " slots. 'all' can be given to refer\n"
- " to all slots. 'other' can be given to\n"
- " refer to a non-current slot. If this\n"
- " flag is not used, slotted partitions\n"
- " will default to the current active slot.\n"
- " -a, --set-active[=<suffix>] Sets the active slot. If no suffix is\n"
+ " --slot <slot> Specify slot name to be used if the\n"
+ " device supports slots. All operations\n"
+ " on partitions that support slots will\n"
+ " be done on the slot specified.\n"
+ " 'all' can be given to refer to all slots.\n"
+ " 'other' can be given to refer to a\n"
+ " non-current slot. If this flag is not\n"
+ " used, slotted partitions will default\n"
+ " to the current active slot.\n"
+ " -a, --set-active[=<slot>] Sets the active slot. If no slot is\n"
" provided, this will default to the value\n"
" given by --slot. If slots are not\n"
- " supported, this does nothing. This will\n"
- " run after all non-reboot commands.\n"
+ " supported, this sets the current slot\n"
+ " to be active. This will run after all\n"
+ " non-reboot commands.\n"
+ " --skip-secondary Will not flash secondary slots when\n"
+ " performing a flashall or update. This\n"
+ " will preserve data on other slots.\n"
#if !defined(_WIN32)
" --wipe-and-use-fbe On devices which support it,\n"
" erase userdata and cache, and\n"
@@ -839,83 +859,138 @@
}
}
-static std::vector<std::string> get_suffixes(Transport* transport) {
+static std::string get_current_slot(Transport* transport)
+{
+ std::string current_slot;
+ if (fb_getvar(transport, "current-slot", ¤t_slot)) {
+ if (current_slot == "_a") return "a"; // Legacy support
+ if (current_slot == "_b") return "b"; // Legacy support
+ return current_slot;
+ }
+ return "";
+}
+
+// Legacy support
+static std::vector<std::string> get_suffixes_obsolete(Transport* transport) {
std::vector<std::string> suffixes;
std::string suffix_list;
if (!fb_getvar(transport, "slot-suffixes", &suffix_list)) {
- die("Could not get suffixes.\n");
+ return suffixes;
}
- return android::base::Split(suffix_list, ",");
+ suffixes = android::base::Split(suffix_list, ",");
+ // Unfortunately some devices will return an error message in the
+ // guise of a valid value. If we only see only one suffix, it's probably
+ // not real.
+ if (suffixes.size() == 1) {
+ suffixes.clear();
+ }
+ return suffixes;
}
-static std::string verify_slot(Transport* transport, const char *slot, bool allow_all) {
- if (strcmp(slot, "all") == 0) {
+// Legacy support
+static bool supports_AB_obsolete(Transport* transport) {
+ return !get_suffixes_obsolete(transport).empty();
+}
+
+static int get_slot_count(Transport* transport) {
+ std::string var;
+ int count;
+ if (!fb_getvar(transport, "slot-count", &var)) {
+ if (supports_AB_obsolete(transport)) return 2; // Legacy support
+ }
+ if (!android::base::ParseInt(var.c_str(), &count)) return 0;
+ return count;
+}
+
+static bool supports_AB(Transport* transport) {
+ return get_slot_count(transport) >= 2;
+}
+
+// Given a current slot, this returns what the 'other' slot is.
+static std::string get_other_slot(const std::string& current_slot, int count) {
+ if (count == 0) return "";
+
+ char next = (current_slot[0] - 'a' + 1)%count + 'a';
+ return std::string(1, next);
+}
+
+static std::string get_other_slot(Transport* transport, const std::string& current_slot) {
+ return get_other_slot(current_slot, get_slot_count(transport));
+}
+
+static std::string get_other_slot(Transport* transport, int count) {
+ return get_other_slot(get_current_slot(transport), count);
+}
+
+static std::string get_other_slot(Transport* transport) {
+ return get_other_slot(get_current_slot(transport), get_slot_count(transport));
+}
+
+static std::string verify_slot(Transport* transport, const std::string& slot_name, bool allow_all) {
+ std::string slot = slot_name;
+ if (slot == "_a") slot = "a"; // Legacy support
+ if (slot == "_b") slot = "b"; // Legacy support
+ if (slot == "all") {
if (allow_all) {
return "all";
} else {
- std::vector<std::string> suffixes = get_suffixes(transport);
- if (!suffixes.empty()) {
- return suffixes[0];
+ int count = get_slot_count(transport);
+ if (count > 0) {
+ return "a";
} else {
die("No known slots.");
}
}
}
- std::vector<std::string> suffixes = get_suffixes(transport);
+ int count = get_slot_count(transport);
+ if (count == 0) die("Device does not support slots.\n");
- if (strcmp(slot, "other") == 0) {
- std::string current_slot;
- if (!fb_getvar(transport, "current-slot", ¤t_slot)) {
- die("Failed to identify current slot.");
+ if (slot == "other") {
+ std::string other = get_other_slot(transport, count);
+ if (other == "") {
+ die("No known slots.");
}
- if (!suffixes.empty()) {
- for (size_t i = 0; i < suffixes.size(); i++) {
- if (current_slot == suffixes[i])
- return suffixes[(i+1)%suffixes.size()];
- }
- } else {
- die("No known slots.");
- }
+ return other;
}
- for (const std::string &suffix : suffixes) {
- if (suffix == slot)
- return slot;
+ if (slot.size() == 1 && (slot[0]-'a' >= 0 && slot[0]-'a' < count)) return slot;
+
+ fprintf(stderr, "Slot %s does not exist. supported slots are:\n", slot.c_str());
+ for (int i=0; i<count; i++) {
+ fprintf(stderr, "%c\n", (char)(i + 'a'));
}
- fprintf(stderr, "Slot %s does not exist. supported slots are:\n", slot);
- for (const std::string &suffix : suffixes) {
- fprintf(stderr, "%s\n", suffix.c_str());
- }
+
exit(1);
}
-static std::string verify_slot(Transport* transport, const char *slot) {
+static std::string verify_slot(Transport* transport, const std::string& slot) {
return verify_slot(transport, slot, true);
}
-static void do_for_partition(Transport* transport, const char *part, const char *slot,
+static void do_for_partition(Transport* transport, const std::string& part, const std::string& slot,
std::function<void(const std::string&)> func, bool force_slot) {
std::string has_slot;
std::string current_slot;
- if (!fb_getvar(transport, std::string("has-slot:")+part, &has_slot)) {
+ if (!fb_getvar(transport, "has-slot:" + part, &has_slot)) {
/* If has-slot is not supported, the answer is no. */
has_slot = "no";
}
if (has_slot == "yes") {
- if (!slot || slot[0] == 0) {
- if (!fb_getvar(transport, "current-slot", ¤t_slot)) {
+ if (slot == "") {
+ current_slot = get_current_slot(transport);
+ if (current_slot == "") {
die("Failed to identify current slot.\n");
}
- func(std::string(part) + current_slot);
+ func(part + "_" + current_slot);
} else {
- func(std::string(part) + slot);
+ func(part + '_' + slot);
}
} else {
- if (force_slot && slot && slot[0]) {
+ if (force_slot && slot != "") {
fprintf(stderr, "Warning: %s does not support slots, and slot %s was requested.\n",
- part, slot);
+ part.c_str(), slot.c_str());
}
func(part);
}
@@ -926,18 +1001,17 @@
* partition names. If force_slot is true, it will fail if a slot is specified, and the given
* partition does not support slots.
*/
-static void do_for_partitions(Transport* transport, const char *part, const char *slot,
+static void do_for_partitions(Transport* transport, const std::string& part, const std::string& slot,
std::function<void(const std::string&)> func, bool force_slot) {
std::string has_slot;
- if (slot && strcmp(slot, "all") == 0) {
- if (!fb_getvar(transport, std::string("has-slot:") + part, &has_slot)) {
- die("Could not check if partition %s has slot.", part);
+ if (slot == "all") {
+ if (!fb_getvar(transport, "has-slot:" + part, &has_slot)) {
+ die("Could not check if partition %s has slot.", part.c_str());
}
if (has_slot == "yes") {
- std::vector<std::string> suffixes = get_suffixes(transport);
- for (std::string &suffix : suffixes) {
- do_for_partition(transport, part, suffix.c_str(), func, force_slot);
+ for (int i=0; i < get_slot_count(transport); i++) {
+ do_for_partition(transport, part, std::string(1, (char)(i + 'a')), func, force_slot);
}
} else {
do_for_partition(transport, part, "", func, force_slot);
@@ -964,7 +1038,28 @@
fb_queue_command("signature", "installing signature");
}
-static void do_update(Transport* transport, const char* filename, const char* slot_override, bool erase_first) {
+// Sets slot_override as the active slot. If slot_override is blank,
+// set current slot as active instead. This clears slot-unbootable.
+static void set_active(Transport* transport, const std::string& slot_override) {
+ std::string separator = "";
+ if (!supports_AB(transport)) {
+ if (supports_AB_obsolete(transport)) {
+ separator = "_"; // Legacy support
+ } else {
+ return;
+ }
+ }
+ if (slot_override != "") {
+ fb_set_active((separator + slot_override).c_str());
+ } else {
+ std::string current_slot = get_current_slot(transport);
+ if (current_slot != "") {
+ fb_set_active((separator + current_slot).c_str());
+ }
+ }
+}
+
+static void do_update(Transport* transport, const char* filename, const std::string& slot_override, bool erase_first, bool skip_secondary) {
queue_info_dump();
fb_queue_query_save("product", cur_product, sizeof(cur_product));
@@ -985,7 +1080,30 @@
setup_requirements(reinterpret_cast<char*>(data), sz);
+ std::string secondary;
+ if (!skip_secondary) {
+ if (slot_override != "") {
+ secondary = get_other_slot(transport, slot_override);
+ } else {
+ secondary = get_other_slot(transport);
+ }
+ if (secondary == "") {
+ if (supports_AB(transport)) {
+ fprintf(stderr, "Warning: Could not determine slot for secondary images. Ignoring.\n");
+ }
+ skip_secondary = true;
+ }
+ }
for (size_t i = 0; i < arraysize(images); ++i) {
+ const char* slot = slot_override.c_str();
+ if (images[i].is_secondary) {
+ if (!skip_secondary) {
+ slot = secondary.c_str();
+ } else {
+ continue;
+ }
+ }
+
int fd = unzip_to_file(zip, images[i].img_name);
if (fd == -1) {
if (images[i].is_optional) {
@@ -1010,10 +1128,15 @@
* program exits.
*/
};
- do_for_partitions(transport, images[i].part_name, slot_override, update, false);
+ do_for_partitions(transport, images[i].part_name, slot, update, false);
}
CloseArchive(zip);
+ if (slot_override == "all") {
+ set_active(transport, "a");
+ } else {
+ set_active(transport, slot_override);
+ }
}
static void do_send_signature(const char* filename) {
@@ -1033,26 +1156,49 @@
fb_queue_command("signature", "installing signature");
}
-static void do_flashall(Transport* transport, const char* slot_override, int erase_first) {
+static void do_flashall(Transport* transport, const std::string& slot_override, int erase_first, bool skip_secondary) {
+ std::string fname;
queue_info_dump();
fb_queue_query_save("product", cur_product, sizeof(cur_product));
- std::string fname = find_item("info", product);
+ fname = find_item("info", product);
if (fname.empty()) die("cannot find android-info.txt");
int64_t sz;
- void* data = load_file(fname, &sz);
+ void* data = load_file(fname.c_str(), &sz);
if (data == nullptr) die("could not load android-info.txt: %s", strerror(errno));
setup_requirements(reinterpret_cast<char*>(data), sz);
+ std::string secondary;
+ if (!skip_secondary) {
+ if (slot_override != "") {
+ secondary = get_other_slot(transport, slot_override);
+ } else {
+ secondary = get_other_slot(transport);
+ }
+ if (secondary == "") {
+ if (supports_AB(transport)) {
+ fprintf(stderr, "Warning: Could not determine slot for secondary images. Ignoring.\n");
+ }
+ skip_secondary = true;
+ }
+ }
+
for (size_t i = 0; i < arraysize(images); i++) {
- fname = find_item(images[i].part_name, product);
+ const char* slot = NULL;
+ if (images[i].is_secondary) {
+ if (!skip_secondary) slot = secondary.c_str();
+ } else {
+ slot = slot_override.c_str();
+ }
+ if (!slot) continue;
+ fname = find_item_given_name(images[i].img_name, product);
fastboot_buffer buf;
if (!load_buf(transport, fname.c_str(), &buf)) {
if (images[i].is_optional) continue;
- die("could not load '%s': %s", images[i].img_name, strerror(errno));
+ die("could not load %s\n", images[i].img_name);
}
auto flashall = [&](const std::string &partition) {
@@ -1062,7 +1208,13 @@
}
flash_buf(partition.c_str(), &buf);
};
- do_for_partitions(transport, images[i].part_name, slot_override, flashall, false);
+ do_for_partitions(transport, images[i].part_name, slot, flashall, false);
+ }
+
+ if (slot_override == "all") {
+ set_active(transport, "a");
+ } else {
+ set_active(transport, slot_override);
}
}
@@ -1242,6 +1394,7 @@
bool wants_reboot = false;
bool wants_reboot_bootloader = false;
bool wants_set_active = false;
+ bool skip_secondary = false;
bool erase_first = true;
bool set_fbe_marker = false;
void *data;
@@ -1266,6 +1419,7 @@
{"slot", required_argument, 0, 0},
{"set_active", optional_argument, 0, 'a'},
{"set-active", optional_argument, 0, 'a'},
+ {"skip-secondary", no_argument, 0, 0},
#if !defined(_WIN32)
{"wipe-and-use-fbe", no_argument, 0, 0},
#endif
@@ -1350,6 +1504,8 @@
return 0;
} else if (strcmp("slot", longopts[longindex].name) == 0) {
slot_override = std::string(optarg);
+ } else if (strcmp("skip-secondary", longopts[longindex].name) == 0 ) {
+ skip_secondary = true;
#if !defined(_WIN32)
} else if (strcmp("wipe-and-use-fbe", longopts[longindex].name) == 0) {
wants_wipe = true;
@@ -1390,17 +1546,23 @@
return 1;
}
- if (slot_override != "")
- slot_override = verify_slot(transport, slot_override.c_str());
- if (next_active != "")
- next_active = verify_slot(transport, next_active.c_str(), false);
+ if (!supports_AB(transport) && supports_AB_obsolete(transport)) {
+ fprintf(stderr, "Warning: Device A/B support is outdated. Bootloader update required.\n");
+ }
+ if (slot_override != "") slot_override = verify_slot(transport, slot_override);
+ if (next_active != "") next_active = verify_slot(transport, next_active, false);
if (wants_set_active) {
if (next_active == "") {
if (slot_override == "") {
- wants_set_active = false;
+ std::string current_slot;
+ if (fb_getvar(transport, "current-slot", ¤t_slot)) {
+ next_active = verify_slot(transport, current_slot, false);
+ } else {
+ wants_set_active = false;
+ }
} else {
- next_active = verify_slot(transport, slot_override.c_str(), false);
+ next_active = verify_slot(transport, slot_override, false);
}
}
}
@@ -1423,7 +1585,7 @@
fb_queue_erase(partition.c_str());
};
- do_for_partitions(transport, argv[1], slot_override.c_str(), erase, true);
+ do_for_partitions(transport, argv[1], slot_override, erase, true);
skip(2);
} else if(!strncmp(*argv, "format", strlen("format"))) {
char *overrides;
@@ -1459,7 +1621,7 @@
fb_perform_format(transport, partition.c_str(), 0,
type_override, size_override, "");
};
- do_for_partitions(transport, argv[1], slot_override.c_str(), format, true);
+ do_for_partitions(transport, argv[1], slot_override, format, true);
skip(2);
} else if(!strcmp(*argv, "signature")) {
require(2);
@@ -1526,7 +1688,7 @@
}
do_flash(transport, partition.c_str(), fname.c_str());
};
- do_for_partitions(transport, pname, slot_override.c_str(), flash, true);
+ do_for_partitions(transport, pname, slot_override, flash, true);
} else if(!strcmp(*argv, "flash:raw")) {
char *kname = argv[2];
char *rname = 0;
@@ -1546,23 +1708,32 @@
auto flashraw = [&](const std::string &partition) {
fb_queue_flash(partition.c_str(), data, sz);
};
- do_for_partitions(transport, argv[1], slot_override.c_str(), flashraw, true);
+ do_for_partitions(transport, argv[1], slot_override, flashraw, true);
} else if(!strcmp(*argv, "flashall")) {
skip(1);
- do_flashall(transport, slot_override.c_str(), erase_first);
+ if (slot_override == "all") {
+ fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
+ do_flashall(transport, slot_override, erase_first, true);
+ } else {
+ do_flashall(transport, slot_override, erase_first, skip_secondary);
+ }
wants_reboot = true;
} else if(!strcmp(*argv, "update")) {
+ bool slot_all = (slot_override == "all");
+ if (slot_all) {
+ fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
+ }
if (argc > 1) {
- do_update(transport, argv[1], slot_override.c_str(), erase_first);
+ do_update(transport, argv[1], slot_override, erase_first, skip_secondary || slot_all);
skip(2);
} else {
- do_update(transport, "update.zip", slot_override.c_str(), erase_first);
+ do_update(transport, "update.zip", slot_override, erase_first, skip_secondary || slot_all);
skip(1);
}
wants_reboot = 1;
} else if(!strcmp(*argv, "set_active")) {
require(2);
- std::string slot = verify_slot(transport, argv[1], false);
+ std::string slot = verify_slot(transport, std::string(argv[1]), false);
fb_set_active(slot.c_str());
skip(2);
} else if(!strcmp(*argv, "oem")) {
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index 6d44e06..45adb34 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -32,11 +32,12 @@
int partnum;
int swap_prio;
unsigned int zram_size;
+ unsigned int file_encryption_mode;
};
struct flag_list {
const char *name;
- unsigned flag;
+ unsigned int flag;
};
static struct flag_list mount_flags[] = {
@@ -63,7 +64,7 @@
{ "check", MF_CHECK },
{ "encryptable=",MF_CRYPT },
{ "forceencrypt=",MF_FORCECRYPT },
- { "fileencryption",MF_FILEENCRYPTION },
+ { "fileencryption=",MF_FILEENCRYPTION },
{ "forcefdeorfbe=",MF_FORCEFDEORFBE },
{ "nonremovable",MF_NONREMOVABLE },
{ "voldmanaged=",MF_VOLDMANAGED},
@@ -81,6 +82,15 @@
{ 0, 0 },
};
+#define EM_SOFTWARE 1
+#define EM_ICE 2
+
+static struct flag_list encryption_modes[] = {
+ {"software", EM_SOFTWARE},
+ {"ice", EM_ICE},
+ {0, 0}
+};
+
static uint64_t calculate_zram_size(unsigned int percentage)
{
uint64_t total;
@@ -147,6 +157,21 @@
* location of the keys. Get it and return it.
*/
flag_vals->key_loc = strdup(strchr(p, '=') + 1);
+ flag_vals->file_encryption_mode = EM_SOFTWARE;
+ } else if ((fl[i].flag == MF_FILEENCRYPTION) && flag_vals) {
+ /* The fileencryption flag is followed by an = and the
+ * type of the encryption. Get it and return it.
+ */
+ const struct flag_list *j;
+ const char *mode = strchr(p, '=') + 1;
+ for (j = encryption_modes; j->name; ++j) {
+ if (!strcmp(mode, j->name)) {
+ flag_vals->file_encryption_mode = j->flag;
+ }
+ }
+ if (flag_vals->file_encryption_mode == 0) {
+ ERROR("Unknown file encryption mode: %s\n", mode);
+ }
} else if ((fl[i].flag == MF_LENGTH) && flag_vals) {
/* The length flag is followed by an = and the
* size of the partition. Get it and return it.
@@ -337,6 +362,7 @@
fstab->recs[cnt].partnum = flag_vals.partnum;
fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
fstab->recs[cnt].zram_size = flag_vals.zram_size;
+ fstab->recs[cnt].file_encryption_mode = flag_vals.file_encryption_mode;
cnt++;
}
/* If an A/B partition, modify block device to be the real block device */
@@ -479,6 +505,17 @@
return fstab->fs_mgr_flags & MF_FILEENCRYPTION;
}
+const char* fs_mgr_get_file_encryption_mode(const struct fstab_rec *fstab)
+{
+ const struct flag_list *j;
+ for (j = encryption_modes; j->name; ++j) {
+ if (fstab->file_encryption_mode == j->flag) {
+ return j->name;
+ }
+ }
+ return NULL;
+}
+
int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab)
{
return fstab->fs_mgr_flags & MF_FORCEFDEORFBE;
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 25b023e..759c5e8 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -181,7 +181,7 @@
return -1;
}
-static void verity_ioctl_init(struct dm_ioctl *io, char *name, unsigned flags)
+static void verity_ioctl_init(struct dm_ioctl *io, const char *name, unsigned flags)
{
memset(io, 0, DM_BUF_SIZE);
io->data_size = DM_BUF_SIZE;
@@ -784,8 +784,9 @@
int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback)
{
alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
+ bool system_root = false;
char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
- char *mount_point;
+ const char *mount_point;
char propbuf[PROPERTY_VALUE_MAX];
char *status;
int fd = -1;
@@ -813,6 +814,9 @@
property_get("ro.hardware", propbuf, "");
snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf);
+ property_get("ro.build.system_root_image", propbuf, "");
+ system_root = !strcmp(propbuf, "true");
+
fstab = fs_mgr_read_fstab(fstab_filename);
if (!fstab) {
@@ -825,7 +829,12 @@
continue;
}
- mount_point = basename(fstab->recs[i].mount_point);
+ if (system_root && !strcmp(fstab->recs[i].mount_point, "/")) {
+ mount_point = "system";
+ } else {
+ mount_point = basename(fstab->recs[i].mount_point);
+ }
+
verity_ioctl_init(io, mount_point, 0);
if (ioctl(fd, DM_TABLE_STATUS, io)) {
@@ -836,7 +845,9 @@
status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
- callback(&fstab->recs[i], mount_point, mode, *status);
+ if (*status == 'C' || *status == 'V') {
+ callback(&fstab->recs[i], mount_point, mode, *status);
+ }
}
rc = 0;
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 3847011..6f2548d 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -66,6 +66,7 @@
int partnum;
int swap_prio;
unsigned int zram_size;
+ unsigned int file_encryption_mode;
};
// Callback function for verity status
@@ -86,6 +87,7 @@
#define FS_MGR_DOMNT_FAILED (-1)
#define FS_MGR_DOMNT_BUSY (-2)
+
int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
char *tmp_mount_point);
int fs_mgr_do_tmpfs_mount(char *n_name);
@@ -103,6 +105,7 @@
int fs_mgr_is_verified(const struct fstab_rec *fstab);
int fs_mgr_is_encryptable(const struct fstab_rec *fstab);
int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab);
+const char* fs_mgr_get_file_encryption_mode(const struct fstab_rec *fstab);
int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab);
int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab);
int fs_mgr_is_notrim(struct fstab_rec *fstab);
diff --git a/include/system/graphics.h b/include/system/graphics.h
index a9e451f..529a562 100644
--- a/include/system/graphics.h
+++ b/include/system/graphics.h
@@ -477,6 +477,102 @@
uint32_t reserved[8];
};
+/*
+ * Structures for describing flexible YUVA/RGBA formats for consumption by
+ * applications. Such flexible formats contain a plane for each component (e.g.
+ * red, green, blue), where each plane is laid out in a grid-like pattern
+ * occupying unique byte addresses and with consistent byte offsets between
+ * neighboring pixels.
+ *
+ * The android_flex_layout structure is used with any pixel format that can be
+ * represented by it, such as:
+ * - HAL_PIXEL_FORMAT_YCbCr_*_888
+ * - HAL_PIXEL_FORMAT_FLEX_RGB*_888
+ * - HAL_PIXEL_FORMAT_RGB[AX]_888[8],BGRA_8888,RGB_888
+ * - HAL_PIXEL_FORMAT_YV12,Y8,Y16,YCbCr_422_SP/I,YCrCb_420_SP
+ * - even implementation defined formats that can be represented by
+ * the structures
+ *
+ * Vertical increment (aka. row increment or stride) describes the distance in
+ * bytes from the first pixel of one row to the first pixel of the next row
+ * (below) for the component plane. This can be negative.
+ *
+ * Horizontal increment (aka. column or pixel increment) describes the distance
+ * in bytes from one pixel to the next pixel (to the right) on the same row for
+ * the component plane. This can be negative.
+ *
+ * Each plane can be subsampled either vertically or horizontally by
+ * a power-of-two factor.
+ *
+ * The bit-depth of each component can be arbitrary, as long as the pixels are
+ * laid out on whole bytes, in native byte-order, using the most significant
+ * bits of each unit.
+ */
+
+typedef enum android_flex_component {
+ /* luma */
+ FLEX_COMPONENT_Y = 1 << 0,
+ /* chroma blue */
+ FLEX_COMPONENT_Cb = 1 << 1,
+ /* chroma red */
+ FLEX_COMPONENT_Cr = 1 << 2,
+
+ /* red */
+ FLEX_COMPONENT_R = 1 << 10,
+ /* green */
+ FLEX_COMPONENT_G = 1 << 11,
+ /* blue */
+ FLEX_COMPONENT_B = 1 << 12,
+
+ /* alpha */
+ FLEX_COMPONENT_A = 1 << 30,
+} android_flex_component_t;
+
+typedef struct android_flex_plane {
+ /* pointer to the first byte of the top-left pixel of the plane. */
+ uint8_t *top_left;
+
+ android_flex_component_t component;
+
+ /* bits allocated for the component in each pixel. Must be a positive
+ multiple of 8. */
+ int32_t bits_per_component;
+ /* number of the most significant bits used in the format for this
+ component. Must be between 1 and bits_per_component, inclusive. */
+ int32_t bits_used;
+
+ /* horizontal increment */
+ int32_t h_increment;
+ /* vertical increment */
+ int32_t v_increment;
+ /* horizontal subsampling. Must be a positive power of 2. */
+ int32_t h_subsampling;
+ /* vertical subsampling. Must be a positive power of 2. */
+ int32_t v_subsampling;
+} android_flex_plane_t;
+
+typedef enum android_flex_format {
+ /* not a flexible format */
+ FLEX_FORMAT_INVALID = 0x0,
+ FLEX_FORMAT_Y = FLEX_COMPONENT_Y,
+ FLEX_FORMAT_YCbCr = FLEX_COMPONENT_Y | FLEX_COMPONENT_Cb | FLEX_COMPONENT_Cr,
+ FLEX_FORMAT_YCbCrA = FLEX_FORMAT_YCbCr | FLEX_COMPONENT_A,
+ FLEX_FORMAT_RGB = FLEX_COMPONENT_R | FLEX_COMPONENT_G | FLEX_COMPONENT_B,
+ FLEX_FORMAT_RGBA = FLEX_FORMAT_RGB | FLEX_COMPONENT_A,
+} android_flex_format_t;
+
+typedef struct android_flex_layout {
+ /* the kind of flexible format */
+ android_flex_format_t format;
+
+ /* number of planes; 0 for FLEX_FORMAT_INVALID */
+ uint32_t num_planes;
+ /* a plane for each component; ordered in increasing component value order.
+ E.g. FLEX_FORMAT_RGBA maps 0 -> R, 1 -> G, etc.
+ Can be NULL for FLEX_FORMAT_INVALID */
+ android_flex_plane_t *planes;
+} android_flex_layout_t;
+
/**
* Structure used to define depth point clouds for format HAL_PIXEL_FORMAT_BLOB
* with dataSpace value of HAL_DATASPACE_DEPTH.
@@ -1039,6 +1135,236 @@
} android_dataspace_t;
/*
+ * Color modes that may be supported by a display.
+ *
+ * Definitions:
+ * Rendering intent generally defines the goal in mapping a source (input)
+ * color to a destination device color for a given color mode.
+ *
+ * It is important to keep in mind three cases where mapping may be applied:
+ * 1. The source gamut is much smaller than the destination (display) gamut
+ * 2. The source gamut is much larger than the destination gamut (this will
+ * ordinarily be handled using colorimetric rendering, below)
+ * 3. The source and destination gamuts are roughly equal, although not
+ * completely overlapping
+ * Also, a common requirement for mappings is that skin tones should be
+ * preserved, or at least remain natural in appearance.
+ *
+ * Colorimetric Rendering Intent (All cases):
+ * Colorimetric indicates that colors should be preserved. In the case
+ * that the source gamut lies wholly within the destination gamut or is
+ * about the same (#1, #3), this will simply mean that no manipulations
+ * (no saturation boost, for example) are applied. In the case where some
+ * source colors lie outside the destination gamut (#2, #3), those will
+ * need to be mapped to colors that are within the destination gamut,
+ * while the already in-gamut colors remain unchanged.
+ *
+ * Non-colorimetric transforms can take many forms. There are no hard
+ * rules and it's left to the implementation to define.
+ * Two common intents are described below.
+ *
+ * Stretched-Gamut Enhancement Intent (Source < Destination):
+ * When the destination gamut is much larger than the source gamut (#1), the
+ * source primaries may be redefined to reflect the full extent of the
+ * destination space, or to reflect an intermediate gamut.
+ * Skin-tone preservation would likely be applied. An example might be sRGB
+ * input displayed on a DCI-P3 capable device, with skin-tone preservation.
+ *
+ * Within-Gamut Enhancement Intent (Source >= Destination):
+ * When the device (destination) gamut is not larger than the source gamut
+ * (#2 or #3), but the appearance of a larger gamut is desired, techniques
+ * such as saturation boost may be applied to the source colors. Skin-tone
+ * preservation may be applied. There is no unique method for within-gamut
+ * enhancement; it would be defined within a flexible color mode.
+ *
+ */
+typedef enum android_color_mode {
+
+ /*
+ * HAL_COLOR_MODE_DEFAULT is the "native" gamut of the display.
+ * White Point: Vendor/OEM defined
+ * Panel Gamma: Vendor/OEM defined (typically 2.2)
+ * Rendering Intent: Vendor/OEM defined (typically 'enhanced')
+ */
+ HAL_COLOR_MODE_NATIVE = 0,
+
+ /*
+ * HAL_COLOR_MODE_STANDARD_BT601_625 corresponds with display
+ * settings that implement the ITU-R Recommendation BT.601
+ * or Rec 601. Using 625 line version
+ * Rendering Intent: Colorimetric
+ * Primaries:
+ * x y
+ * green 0.290 0.600
+ * blue 0.150 0.060
+ * red 0.640 0.330
+ * white (D65) 0.3127 0.3290
+ *
+ * KR = 0.299, KB = 0.114. This adjusts the luminance interpretation
+ * for RGB conversion from the one purely determined by the primaries
+ * to minimize the color shift into RGB space that uses BT.709
+ * primaries.
+ *
+ * Gamma Correction (GC):
+ *
+ * if Vlinear < 0.018
+ * Vnonlinear = 4.500 * Vlinear
+ * else
+ * Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
+ */
+ HAL_COLOR_MODE_STANDARD_BT601_625 = 1,
+
+ /*
+ * Primaries:
+ * x y
+ * green 0.290 0.600
+ * blue 0.150 0.060
+ * red 0.640 0.330
+ * white (D65) 0.3127 0.3290
+ *
+ * Use the unadjusted KR = 0.222, KB = 0.071 luminance interpretation
+ * for RGB conversion.
+ *
+ * Gamma Correction (GC):
+ *
+ * if Vlinear < 0.018
+ * Vnonlinear = 4.500 * Vlinear
+ * else
+ * Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
+ */
+ HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED = 2,
+
+ /*
+ * Primaries:
+ * x y
+ * green 0.310 0.595
+ * blue 0.155 0.070
+ * red 0.630 0.340
+ * white (D65) 0.3127 0.3290
+ *
+ * KR = 0.299, KB = 0.114. This adjusts the luminance interpretation
+ * for RGB conversion from the one purely determined by the primaries
+ * to minimize the color shift into RGB space that uses BT.709
+ * primaries.
+ *
+ * Gamma Correction (GC):
+ *
+ * if Vlinear < 0.018
+ * Vnonlinear = 4.500 * Vlinear
+ * else
+ * Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
+ */
+ HAL_COLOR_MODE_STANDARD_BT601_525 = 3,
+
+ /*
+ * Primaries:
+ * x y
+ * green 0.310 0.595
+ * blue 0.155 0.070
+ * red 0.630 0.340
+ * white (D65) 0.3127 0.3290
+ *
+ * Use the unadjusted KR = 0.212, KB = 0.087 luminance interpretation
+ * for RGB conversion (as in SMPTE 240M).
+ *
+ * Gamma Correction (GC):
+ *
+ * if Vlinear < 0.018
+ * Vnonlinear = 4.500 * Vlinear
+ * else
+ * Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
+ */
+ HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED = 4,
+
+ /*
+ * HAL_COLOR_MODE_REC709 corresponds with display settings that implement
+ * the ITU-R Recommendation BT.709 / Rec. 709 for high-definition television.
+ * Rendering Intent: Colorimetric
+ * Primaries:
+ * x y
+ * green 0.300 0.600
+ * blue 0.150 0.060
+ * red 0.640 0.330
+ * white (D65) 0.3127 0.3290
+ *
+ * HDTV REC709 Inverse Gamma Correction (IGC): V represents normalized
+ * (with [0 to 1] range) value of R, G, or B.
+ *
+ * if Vnonlinear < 0.081
+ * Vlinear = Vnonlinear / 4.5
+ * else
+ * Vlinear = ((Vnonlinear + 0.099) / 1.099) ^ (1/0.45)
+ *
+ * HDTV REC709 Gamma Correction (GC):
+ *
+ * if Vlinear < 0.018
+ * Vnonlinear = 4.5 * Vlinear
+ * else
+ * Vnonlinear = 1.099 * (Vlinear) ^ 0.45 – 0.099
+ */
+ HAL_COLOR_MODE_STANDARD_BT709 = 5,
+
+ /*
+ * HAL_COLOR_MODE_DCI_P3 corresponds with display settings that implement
+ * SMPTE EG 432-1 and SMPTE RP 431-2
+ * Rendering Intent: Colorimetric
+ * Primaries:
+ * x y
+ * green 0.265 0.690
+ * blue 0.150 0.060
+ * red 0.680 0.320
+ * white (D65) 0.3127 0.3290
+ *
+ * Gamma: 2.2
+ */
+ HAL_COLOR_MODE_DCI_P3 = 6,
+
+ /*
+ * HAL_COLOR_MODE_SRGB corresponds with display settings that implement
+ * the sRGB color space. Uses the same primaries as ITU-R Recommendation
+ * BT.709
+ * Rendering Intent: Colorimetric
+ * Primaries:
+ * x y
+ * green 0.300 0.600
+ * blue 0.150 0.060
+ * red 0.640 0.330
+ * white (D65) 0.3127 0.3290
+ *
+ * PC/Internet (sRGB) Inverse Gamma Correction (IGC):
+ *
+ * if Vnonlinear ≤ 0.03928
+ * Vlinear = Vnonlinear / 12.92
+ * else
+ * Vlinear = ((Vnonlinear + 0.055)/1.055) ^ 2.4
+ *
+ * PC/Internet (sRGB) Gamma Correction (GC):
+ *
+ * if Vlinear ≤ 0.0031308
+ * Vnonlinear = 12.92 * Vlinear
+ * else
+ * Vnonlinear = 1.055 * (Vlinear)^(1/2.4) – 0.055
+ */
+ HAL_COLOR_MODE_SRGB = 7,
+
+ /*
+ * HAL_COLOR_MODE_ADOBE_RGB corresponds with the RGB color space developed
+ * by Adobe Systems, Inc. in 1998.
+ * Rendering Intent: Colorimetric
+ * Primaries:
+ * x y
+ * green 0.210 0.710
+ * blue 0.150 0.060
+ * red 0.640 0.330
+ * white (D65) 0.3127 0.3290
+ *
+ * Gamma: 2.2
+ */
+ HAL_COLOR_MODE_ADOBE_RGB = 8
+
+} android_color_mode_t;
+
+/*
* Color transforms that may be applied by hardware composer to the whole
* display.
*/
diff --git a/include/system/window.h b/include/system/window.h
index b8f33ff..33b7c3d 100644
--- a/include/system/window.h
+++ b/include/system/window.h
@@ -278,6 +278,16 @@
* age will be 0.
*/
NATIVE_WINDOW_BUFFER_AGE = 13,
+
+ /*
+ * Returns the duration of the last dequeueBuffer call in microseconds
+ */
+ NATIVE_WINDOW_LAST_DEQUEUE_DURATION = 14,
+
+ /*
+ * Returns the duration of the last queueBuffer call in microseconds
+ */
+ NATIVE_WINDOW_LAST_QUEUE_DURATION = 15,
};
/* Valid operations for the (*perform)() hook.
@@ -314,6 +324,7 @@
NATIVE_WINDOW_SET_SURFACE_DAMAGE = 20, /* private */
NATIVE_WINDOW_SET_SHARED_BUFFER_MODE = 21,
NATIVE_WINDOW_SET_AUTO_REFRESH = 22,
+ NATIVE_WINDOW_GET_FRAME_TIMESTAMPS = 23,
};
/* parameter for NATIVE_WINDOW_[API_][DIS]CONNECT */
@@ -976,6 +987,18 @@
return window->perform(window, NATIVE_WINDOW_SET_AUTO_REFRESH, autoRefresh);
}
+static inline int native_window_get_frame_timestamps(
+ struct ANativeWindow* window, uint32_t framesAgo,
+ int64_t* outPostedTime, int64_t* outAcquireTime,
+ int64_t* outRefreshStartTime, int64_t* outGlCompositionDoneTime,
+ int64_t* outDisplayRetireTime, int64_t* outReleaseTime)
+{
+ return window->perform(window, NATIVE_WINDOW_GET_FRAME_TIMESTAMPS,
+ framesAgo, outPostedTime, outAcquireTime, outRefreshStartTime,
+ outGlCompositionDoneTime, outDisplayRetireTime, outReleaseTime);
+}
+
+
__END_DECLS
#endif /* SYSTEM_CORE_INCLUDE_ANDROID_WINDOW_H */
diff --git a/init/Android.mk b/init/Android.mk
index f83924e..36a5713 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -83,7 +83,7 @@
LOCAL_STATIC_LIBRARIES := \
libinit \
- libbootloader_message_writer \
+ libbootloader_message \
libfs_mgr \
libfec \
libfec_rs \
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 4ba7f11..b227d40 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -48,7 +48,7 @@
#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <android-base/stringprintf.h>
-#include <bootloader_message_writer.h>
+#include <bootloader_message/bootloader_message.h>
#include <cutils/partition_utils.h>
#include <cutils/android_reboot.h>
#include <logwrap/logwrap.h>
@@ -346,6 +346,11 @@
return 0;
}
+/* umount <path> */
+static int do_umount(const std::vector<std::string>& args) {
+ return umount(args[1].c_str());
+}
+
static struct {
const char *name;
unsigned flag;
@@ -856,8 +861,12 @@
int ret = 0;
for (auto it = std::next(args.begin()); it != args.end(); ++it) {
- if (restorecon_recursive(it->c_str()) < 0)
+ /* The contents of CE paths are encrypted on FBE devices until user
+ * credentials are presented (filenames inside are mangled), so we need
+ * to delay restorecon of those until vold explicitly requests it. */
+ if (restorecon_recursive_skipce(it->c_str()) < 0) {
ret = -errno;
+ }
}
return ret;
}
@@ -944,6 +953,7 @@
{"mkdir", {1, 4, do_mkdir}},
{"mount_all", {1, kMax, do_mount_all}},
{"mount", {3, kMax, do_mount}},
+ {"umount", {1, 1, do_umount}},
{"powerctl", {1, 1, do_powerctl}},
{"restart", {1, 1, do_restart}},
{"restorecon", {1, kMax, do_restorecon}},
diff --git a/init/readme.txt b/init/readme.txt
index 7260775..cde4055 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -366,6 +366,9 @@
Trigger an event. Used to queue an action from another
action.
+umount <path>
+ Unmount the filesystem mounted at that path.
+
verity_load_state
Internal implementation detail used to load dm-verity state.
diff --git a/init/util.cpp b/init/util.cpp
index 6c1923f..80b2325 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -362,6 +362,12 @@
return selinux_android_restorecon(pathname, SELINUX_ANDROID_RESTORECON_RECURSE);
}
+int restorecon_recursive_skipce(const char* pathname)
+{
+ return selinux_android_restorecon(pathname,
+ SELINUX_ANDROID_RESTORECON_RECURSE | SELINUX_ANDROID_RESTORECON_SKIPCE);
+}
+
/*
* Writes hex_len hex characters (1/2 byte) to hex from bytes.
*/
diff --git a/init/util.h b/init/util.h
index 9d522cc..651e609 100644
--- a/init/util.h
+++ b/init/util.h
@@ -59,6 +59,7 @@
int make_dir(const char *path, mode_t mode);
int restorecon(const char *pathname);
int restorecon_recursive(const char *pathname);
+int restorecon_recursive_skipce(const char *pathname);
std::string bytes_to_hex(const uint8_t *bytes, size_t bytes_len);
bool is_dir(const char* pathname);
bool expand_props(const std::string& src, std::string* dst);
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 840ac86..9acfa58 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -91,6 +91,7 @@
{ 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/Music" },
{ 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest" },
{ 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest64" },
+ { 00775, AID_ROOT, AID_ROOT, 0, "data/preloads" },
{ 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },
{ 00755, AID_ROOT, AID_SYSTEM, 0, "mnt" },
{ 00755, AID_ROOT, AID_ROOT, 0, "root" },
@@ -142,6 +143,9 @@
{ 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 FIFO scheduling mode in SurfaceFlinger. */
+ { 00755, AID_SYSTEM, AID_GRAPHICS, CAP_MASK_LONG(CAP_SYS_NICE), "system/bin/surfaceflinger" },
+
{ 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/*" },
diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c
index 884ee17..6e6a9eb 100644
--- a/libcutils/sched_policy.c
+++ b/libcutils/sched_policy.c
@@ -66,9 +66,12 @@
static int bg_cpuset_fd = -1;
static int fg_cpuset_fd = -1;
static int ta_cpuset_fd = -1; // special cpuset for top app
+#endif
+
+// File descriptors open to /dev/stune/../tasks, setup by initialize, or -1 on error
static int bg_schedboost_fd = -1;
static int fg_schedboost_fd = -1;
-#endif
+static int ta_schedboost_fd = -1;
/* Add tid to the scheduling group defined by the policy */
static int add_tid_to_cgroup(int tid, int fd)
@@ -138,9 +141,11 @@
ta_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC);
#ifdef USE_SCHEDBOOST
+ filename = "/dev/stune/top-app/tasks";
+ ta_schedboost_fd = open(filename, O_WRONLY | O_CLOEXEC);
filename = "/dev/stune/foreground/tasks";
fg_schedboost_fd = open(filename, O_WRONLY | O_CLOEXEC);
- filename = "/dev/stune/tasks";
+ filename = "/dev/stune/background/tasks";
bg_schedboost_fd = open(filename, O_WRONLY | O_CLOEXEC);
#endif
}
@@ -298,11 +303,10 @@
break;
case SP_TOP_APP :
fd = ta_cpuset_fd;
- boost_fd = fg_schedboost_fd;
+ boost_fd = ta_schedboost_fd;
break;
case SP_SYSTEM:
fd = system_bg_cpuset_fd;
- boost_fd = bg_schedboost_fd;
break;
default:
boost_fd = fd = -1;
@@ -314,10 +318,12 @@
return -errno;
}
+#ifdef USE_SCHEDBOOST
if (boost_fd > 0 && add_tid_to_cgroup(tid, boost_fd) != 0) {
if (errno != ESRCH && errno != ENOENT)
return -errno;
}
+#endif
return 0;
#endif
@@ -374,19 +380,26 @@
#endif
if (__sys_supports_schedgroups) {
- int fd;
+ int fd = -1;
+ int boost_fd = -1;
switch (policy) {
case SP_BACKGROUND:
fd = bg_cgroup_fd;
+ boost_fd = bg_schedboost_fd;
break;
case SP_FOREGROUND:
case SP_AUDIO_APP:
case SP_AUDIO_SYS:
+ fd = fg_cgroup_fd;
+ boost_fd = fg_schedboost_fd;
+ break;
case SP_TOP_APP:
fd = fg_cgroup_fd;
+ boost_fd = ta_schedboost_fd;
break;
default:
fd = -1;
+ boost_fd = -1;
break;
}
@@ -395,6 +408,13 @@
if (errno != ESRCH && errno != ENOENT)
return -errno;
}
+
+#ifdef USE_SCHEDBOOST
+ if (boost_fd > 0 && add_tid_to_cgroup(tid, boost_fd) != 0) {
+ if (errno != ESRCH && errno != ENOENT)
+ return -errno;
+ }
+#endif
} else {
struct sched_param param;
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index ac2b128..a0b7499 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -401,7 +401,32 @@
}
}
-pid_t LogKlog::sniffPid(const char *cp, size_t len) {
+pid_t LogKlog::sniffPid(const char **buf, size_t len) {
+ const char *cp = *buf;
+ // HTC kernels with modified printk "c0 1648 "
+ if ((len > 9) &&
+ (cp[0] == 'c') &&
+ isdigit(cp[1]) &&
+ (isdigit(cp[2]) || (cp[2] == ' ')) &&
+ (cp[3] == ' ')) {
+ bool gotDigit = false;
+ int i;
+ for (i = 4; i < 9; ++i) {
+ if (isdigit(cp[i])) {
+ gotDigit = true;
+ } else if (gotDigit || (cp[i] != ' ')) {
+ break;
+ }
+ }
+ if ((i == 9) && (cp[i] == ' ')) {
+ int pid = 0;
+ char dummy;
+ if (sscanf(cp + 4, "%d%c", &pid, &dummy) == 2) {
+ *buf = cp + 10; // skip-it-all
+ return pid;
+ }
+ }
+ }
while (len) {
// Mediatek kernels with modified printk
if (*cp == '[') {
@@ -587,7 +612,7 @@
}
// Parse pid, tid and uid
- const pid_t pid = sniffPid(p, len - (p - buf));
+ const pid_t pid = sniffPid(&p, len - (p - buf));
const pid_t tid = pid;
const uid_t uid = pid ? logbuf->pidToUid(pid) : 0;
diff --git a/logd/LogKlog.h b/logd/LogKlog.h
index ee73b71..a4f871e 100644
--- a/logd/LogKlog.h
+++ b/logd/LogKlog.h
@@ -51,7 +51,7 @@
protected:
void sniffTime(log_time &now, const char **buf, size_t len, bool reverse);
- pid_t sniffPid(const char *buf, size_t len);
+ pid_t sniffPid(const char **buf, size_t len);
void calculateCorrection(const log_time &monotonic,
const char *real_string, size_t len);
virtual bool onDataAvailable(SocketClient *cli);
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index e060a2c..aa5a520 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -26,6 +26,7 @@
#######################################
# asan.options
ifneq ($(filter address,$(SANITIZE_TARGET)),)
+
include $(CLEAR_VARS)
LOCAL_MODULE := asan.options
@@ -34,6 +35,72 @@
LOCAL_MODULE_PATH := $(TARGET_OUT)
include $(BUILD_PREBUILT)
+
+# Modules for asan.options.X files.
+
+ASAN_OPTIONS_FILES :=
+
+define create-asan-options-module
+include $$(CLEAR_VARS)
+LOCAL_MODULE := asan.options.$(1)
+ASAN_OPTIONS_FILES += asan.options.$(1)
+LOCAL_MODULE_CLASS := ETC
+# The asan.options.off.template tries to turn off as much of ASAN as is possible.
+LOCAL_SRC_FILES := asan.options.off.template
+LOCAL_MODULE_PATH := $(TARGET_OUT)
+include $$(BUILD_PREBUILT)
+endef
+
+# Pretty comprehensive set of native services. This list is helpful if all that's to be checked is an
+# app.
+ifeq ($(SANITIZE_LITE),true)
+SANITIZE_ASAN_OPTIONS_FOR := \
+ adbd \
+ ATFWD-daemon \
+ audioserver \
+ bridgemgrd \
+ cameraserver \
+ cnd \
+ debuggerd \
+ debuggerd64 \
+ dex2oat \
+ drmserver \
+ fingerprintd \
+ gatekeeperd \
+ installd \
+ keystore \
+ lmkd \
+ logcat \
+ logd \
+ lowi-server \
+ media.codec \
+ mediadrmserver \
+ media.extractor \
+ mediaserver \
+ mm-qcamera-daemon \
+ mpdecision \
+ netmgrd \
+ perfd \
+ perfprofd \
+ qmuxd \
+ qseecomd \
+ rild \
+ sdcard \
+ servicemanager \
+ slim_daemon \
+ surfaceflinger \
+ thermal-engine \
+ time_daemon \
+ update_engine \
+ vold \
+ wpa_supplicant \
+ zip
+endif
+
+ifneq ($(SANITIZE_ASAN_OPTIONS_FOR),)
+ $(foreach binary, $(SANITIZE_ASAN_OPTIONS_FOR), $(eval $(call create-asan-options-module,$(binary))))
+endif
+
endif
#######################################
@@ -47,14 +114,14 @@
EXPORT_GLOBAL_ASAN_OPTIONS :=
ifneq ($(filter address,$(SANITIZE_TARGET)),)
EXPORT_GLOBAL_ASAN_OPTIONS := export ASAN_OPTIONS include=/system/asan.options
- LOCAL_REQUIRED_MODULES := asan.options
+ LOCAL_REQUIRED_MODULES := asan.options $(ASAN_OPTIONS_FILES)
endif
# Put it here instead of in init.rc module definition,
# because init.rc is conditionally included.
#
# create some directories (some are mount points) and symlinks
LOCAL_POST_INSTALL_CMD := mkdir -p $(addprefix $(TARGET_ROOT_OUT)/, \
- sbin dev proc sys system data oem acct cache config storage mnt root $(BOARD_ROOT_EXTRA_FOLDERS)); \
+ sbin dev proc sys system data oem acct config storage mnt root $(BOARD_ROOT_EXTRA_FOLDERS)); \
ln -sf /system/etc $(TARGET_ROOT_OUT)/etc; \
ln -sf /sys/kernel/debug $(TARGET_ROOT_OUT)/d; \
ln -sf /storage/self/primary $(TARGET_ROOT_OUT)/sdcard
@@ -63,6 +130,11 @@
else
LOCAL_POST_INSTALL_CMD += ; ln -sf /system/vendor $(TARGET_ROOT_OUT)/vendor
endif
+ifdef BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
+ LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/cache
+else
+ LOCAL_POST_INSTALL_CMD += ; ln -sf /data/cache $(TARGET_ROOT_OUT)/cache
+endif
ifdef BOARD_ROOT_EXTRA_SYMLINKS
# BOARD_ROOT_EXTRA_SYMLINKS is a list of <target>:<link_name>.
LOCAL_POST_INSTALL_CMD += $(foreach s, $(BOARD_ROOT_EXTRA_SYMLINKS),\
diff --git a/rootdir/asan.options b/rootdir/asan.options
index 43896a1..70e0eca 100644
--- a/rootdir/asan.options
+++ b/rootdir/asan.options
@@ -3,3 +3,4 @@
alloc_dealloc_mismatch=0
allocator_may_return_null=1
detect_container_overflow=0
+include_if_exists=/system/asan.options.%b
diff --git a/rootdir/asan.options.off.template b/rootdir/asan.options.off.template
new file mode 100644
index 0000000..59a1249
--- /dev/null
+++ b/rootdir/asan.options.off.template
@@ -0,0 +1,7 @@
+quarantine_size_mb=0
+max_redzone=16
+poison_heap=false
+poison_partial=false
+poison_array_cookie=false
+alloc_dealloc_mismatch=false
+new_delete_type_mismatch=false
diff --git a/rootdir/init.rc b/rootdir/init.rc
index a68cb78..f276b55 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -50,12 +50,20 @@
mkdir /dev/stune
mount cgroup none /dev/stune schedtune
mkdir /dev/stune/foreground
+ mkdir /dev/stune/background
+ mkdir /dev/stune/top-app
chown system system /dev/stune
chown system system /dev/stune/foreground
+ chown system system /dev/stune/background
+ chown system system /dev/stune/top-app
chown system system /dev/stune/tasks
chown system system /dev/stune/foreground/tasks
+ chown system system /dev/stune/background/tasks
+ chown system system /dev/stune/top-app/tasks
chmod 0664 /dev/stune/tasks
chmod 0664 /dev/stune/foreground/tasks
+ chmod 0664 /dev/stune/background/tasks
+ chmod 0664 /dev/stune/top-app/tasks
# Mount staging areas for devices managed by vold
# See storage config details at http://source.android.com/tech/storage/
@@ -134,16 +142,17 @@
chown system system /dev/cpuctl
chown system system /dev/cpuctl/tasks
chmod 0666 /dev/cpuctl/tasks
- write /dev/cpuctl/cpu.rt_runtime_us 800000
write /dev/cpuctl/cpu.rt_period_us 1000000
+ write /dev/cpuctl/cpu.rt_runtime_us 950000
mkdir /dev/cpuctl/bg_non_interactive
chown system system /dev/cpuctl/bg_non_interactive/tasks
chmod 0666 /dev/cpuctl/bg_non_interactive/tasks
# 5.0 %
write /dev/cpuctl/bg_non_interactive/cpu.shares 52
- write /dev/cpuctl/bg_non_interactive/cpu.rt_runtime_us 700000
write /dev/cpuctl/bg_non_interactive/cpu.rt_period_us 1000000
+ # active FIFO threads will never be in BG
+ write /dev/cpuctl/bg_non_interactive/cpu.rt_runtime_us 10000
# sets up initial cpusets for ActivityManager
mkdir /dev/cpuset
@@ -225,6 +234,8 @@
# expecting it to point to /proc/self/fd
symlink /proc/self/fd /dev/fd
+ export DOWNLOAD_CACHE /data/cache
+
# Healthd can trigger a full boot from charger mode by signaling this
# property when the power button is held.
on property:sys.boot_from_charger_mode=1
@@ -394,6 +405,10 @@
# create the A/B OTA directory, so as to enforce our permissions
mkdir /data/ota 0771 root root
+ # create the OTA package directory. It will be accessed by GmsCore (cache
+ # group), update_engine and update_verifier.
+ mkdir /data/ota_package 0770 system cache
+
# create resource-cache and double-check the perms
mkdir /data/resource-cache 0771 system system
chown system system /data/resource-cache
@@ -438,6 +453,11 @@
mkdir /data/media 0770 media_rw media_rw
mkdir /data/media/obb 0770 media_rw media_rw
+ mkdir /data/cache 0770 system cache
+ mkdir /data/cache/recovery 0770 system cache
+ mkdir /data/cache/backup_stage 0700 system system
+ mkdir /data/cache/backup 0700 system system
+
init_user0
# Set SELinux security contexts on upgrade or policy update.
@@ -546,7 +566,7 @@
on nonencrypted
# A/B update verifier that marks a successful boot.
- exec - root -- /system/bin/update_verifier nonencrypted
+ exec - root cache -- /system/bin/update_verifier nonencrypted
class_start main
class_start late_start
@@ -569,12 +589,12 @@
on property:vold.decrypt=trigger_restart_min_framework
# A/B update verifier that marks a successful boot.
- exec - root -- /system/bin/update_verifier trigger_restart_min_framework
+ exec - root cache -- /system/bin/update_verifier trigger_restart_min_framework
class_start main
on property:vold.decrypt=trigger_restart_framework
# A/B update verifier that marks a successful boot.
- exec - root -- /system/bin/update_verifier trigger_restart_framework
+ exec - root cache -- /system/bin/update_verifier trigger_restart_framework
class_start main
class_start late_start
diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc
index 807f9bc..2d7d5c2 100644
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -8,4 +8,4 @@
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
- writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
+ writepid /dev/cpuset/foreground/tasks
diff --git a/rootdir/init.zygote32_64.rc b/rootdir/init.zygote32_64.rc
index 10fa915..a5e32c2 100644
--- a/rootdir/init.zygote32_64.rc
+++ b/rootdir/init.zygote32_64.rc
@@ -8,11 +8,11 @@
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
- writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks
+ writepid /dev/cpuset/foreground/tasks
service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
class main
priority -20
socket zygote_secondary stream 660 root system
onrestart restart zygote
- writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
+ writepid /dev/cpuset/foreground/tasks
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
index 13ffd7e..8584cbb 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -8,4 +8,4 @@
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
- writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
+ writepid /dev/cpuset/foreground/tasks
diff --git a/rootdir/init.zygote64_32.rc b/rootdir/init.zygote64_32.rc
index 1164ac5..4a32097 100644
--- a/rootdir/init.zygote64_32.rc
+++ b/rootdir/init.zygote64_32.rc
@@ -8,11 +8,11 @@
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
- writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks
+ writepid /dev/cpuset/foreground/tasks
service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
class main
priority -20
socket zygote_secondary stream 660 root system
onrestart restart zygote
- writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
+ writepid /dev/cpuset/foreground/tasks