Merge "DO NOT MERGE - Merge qt-dev-plus-aosp-without-vendor (5699924) into stage-aosp-master" into stage-aosp-master
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 39abc4a..c436be3 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -389,6 +389,8 @@
             " set_active SLOT            Set the active slot.\n"
             " oem [COMMAND...]           Execute OEM-specific command.\n"
             " gsi wipe|disable           Wipe or disable a GSI installation (fastbootd only).\n"
+            " wipe-super [SUPER_EMPTY]   Wipe the super partition. This will reset it to\n"
+            "                            contain an empty set of default dynamic partitions.\n"
             "\n"
             "boot image:\n"
             " boot KERNEL [RAMDISK [SECOND]]\n"
@@ -1582,6 +1584,76 @@
     return false;
 }
 
+static bool wipe_super(const android::fs_mgr::LpMetadata& metadata, const std::string& slot,
+                       std::string* message) {
+    auto super_device = GetMetadataSuperBlockDevice(metadata);
+    auto block_size = metadata.geometry.logical_block_size;
+    auto super_bdev_name = android::fs_mgr::GetBlockDevicePartitionName(*super_device);
+
+    if (super_bdev_name != "super") {
+        // retrofit devices do not allow flashing to the retrofit partitions,
+        // so enable it if we can.
+        fb->RawCommand("oem allow-flash-super");
+    }
+
+    // Note: do not use die() in here, since we want TemporaryDir's destructor
+    // to be called.
+    TemporaryDir temp_dir;
+
+    bool ok;
+    if (metadata.block_devices.size() > 1) {
+        ok = WriteSplitImageFiles(temp_dir.path, metadata, block_size, {}, true);
+    } else {
+        auto image_path = temp_dir.path + "/"s + super_bdev_name + ".img";
+        ok = WriteToImageFile(image_path, metadata, block_size, {}, true);
+    }
+    if (!ok) {
+        *message = "Could not generate a flashable super image file";
+        return false;
+    }
+
+    for (const auto& block_device : metadata.block_devices) {
+        auto partition = android::fs_mgr::GetBlockDevicePartitionName(block_device);
+        bool force_slot = !!(block_device.flags & LP_BLOCK_DEVICE_SLOT_SUFFIXED);
+
+        std::string image_name;
+        if (metadata.block_devices.size() > 1) {
+            image_name = "super_" + partition + ".img";
+        } else {
+            image_name = partition + ".img";
+        }
+
+        auto image_path = temp_dir.path + "/"s + image_name;
+        auto flash = [&](const std::string& partition_name) {
+            do_flash(partition_name.c_str(), image_path.c_str());
+        };
+        do_for_partitions(partition, slot, flash, force_slot);
+
+        unlink(image_path.c_str());
+    }
+    return true;
+}
+
+static void do_wipe_super(const std::string& image, const std::string& slot_override) {
+    if (access(image.c_str(), R_OK) != 0) {
+        die("Could not read image: %s", image.c_str());
+    }
+    auto metadata = android::fs_mgr::ReadFromImageFile(image);
+    if (!metadata) {
+        die("Could not parse image: %s", image.c_str());
+    }
+
+    auto slot = slot_override;
+    if (slot.empty()) {
+        slot = get_current_slot();
+    }
+
+    std::string message;
+    if (!wipe_super(*metadata.get(), slot, &message)) {
+        die(message);
+    }
+}
+
 int FastBootTool::Main(int argc, char* argv[]) {
     bool wants_wipe = false;
     bool wants_reboot = false;
@@ -1958,6 +2030,14 @@
             } else {
                 syntax_error("expected 'wipe' or 'disable'");
             }
+        } else if (command == "wipe-super") {
+            std::string image;
+            if (args.empty()) {
+                image = find_item_given_name("super_empty.img");
+            } else {
+                image = next_arg(&args);
+            }
+            do_wipe_super(image, slot_override);
         } else {
             syntax_error("unknown command %s", command.c_str());
         }
diff --git a/fastboot/util.cpp b/fastboot/util.cpp
index d02b37f..900d6ea 100644
--- a/fastboot/util.cpp
+++ b/fastboot/util.cpp
@@ -53,6 +53,10 @@
     exit(EXIT_FAILURE);
 }
 
+void die(const std::string& str) {
+    die("%s", str.c_str());
+}
+
 void set_verbose() {
     g_verbose = true;
 }
diff --git a/fastboot/util.h b/fastboot/util.h
index 2535414..c719df2 100644
--- a/fastboot/util.h
+++ b/fastboot/util.h
@@ -15,4 +15,7 @@
 // use the same attribute for compile-time format string checking.
 void die(const char* fmt, ...) __attribute__((__noreturn__))
 __attribute__((__format__(__printf__, 1, 2)));
+
 void verbose(const char* fmt, ...) __attribute__((__format__(__printf__, 1, 2)));
+
+void die(const std::string& str) __attribute__((__noreturn__));
diff --git a/init/host_init_verifier.cpp b/init/host_init_verifier.cpp
index 9323aa0..8aa3509 100644
--- a/init/host_init_verifier.cpp
+++ b/init/host_init_verifier.cpp
@@ -129,6 +129,23 @@
     return nullptr;
 }
 
+static std::optional<std::set<std::string>> ReadKnownInterfaces(
+        const std::string& known_interfaces_file) {
+    if (known_interfaces_file.empty()) {
+        LOG(WARNING) << "Missing a known interfaces file.";
+        return {};
+    }
+
+    std::string known_interfaces;
+    if (!ReadFileToString(known_interfaces_file, &known_interfaces)) {
+        LOG(ERROR) << "Failed to read known interfaces file '" << known_interfaces_file << "'";
+        return {};
+    }
+
+    auto interfaces = Split(known_interfaces, " ");
+    return std::set<std::string>(interfaces.begin(), interfaces.end());
+}
+
 namespace android {
 namespace init {
 
@@ -139,11 +156,12 @@
 #include "generated_stub_builtin_function_map.h"
 
 void PrintUsage() {
-    std::cout << "usage: host_init_verifier [-p FILE] <init rc file>\n"
+    std::cout << "usage: host_init_verifier [-p FILE] -k FILE <init rc file>\n"
                  "\n"
                  "Tests an init script for correctness\n"
                  "\n"
                  "-p FILE\tSearch this passwd file for users and groups\n"
+                 "-k FILE\tUse this file as a space-separated list of known interfaces\n"
               << std::endl;
 }
 
@@ -151,13 +169,15 @@
     android::base::InitLogging(argv, &android::base::StdioLogger);
     android::base::SetMinimumLogSeverity(android::base::ERROR);
 
+    std::string known_interfaces_file;
+
     while (true) {
         static const struct option long_options[] = {
                 {"help", no_argument, nullptr, 'h'},
                 {nullptr, 0, nullptr, 0},
         };
 
-        int arg = getopt_long(argc, argv, "p:", long_options, nullptr);
+        int arg = getopt_long(argc, argv, "p:k:", long_options, nullptr);
 
         if (arg == -1) {
             break;
@@ -170,6 +190,9 @@
             case 'p':
                 passwd_files.emplace_back(optarg);
                 break;
+            case 'k':
+                known_interfaces_file = optarg;
+                break;
             default:
                 std::cerr << "getprop: getopt returned invalid result: " << arg << std::endl;
                 return EXIT_FAILURE;
@@ -189,7 +212,9 @@
     ActionManager& am = ActionManager::GetInstance();
     ServiceList& sl = ServiceList::GetInstance();
     Parser parser;
-    parser.AddSectionParser("service", std::make_unique<ServiceParser>(&sl, nullptr));
+    parser.AddSectionParser(
+            "service", std::make_unique<ServiceParser>(&sl, nullptr,
+                                                       ReadKnownInterfaces(known_interfaces_file)));
     parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
     parser.AddSectionParser("import", std::make_unique<HostImportParser>());
 
diff --git a/init/init.cpp b/init/init.cpp
index b6911e5..675f3e5 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -113,7 +113,8 @@
 Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {
     Parser parser;
 
-    parser.AddSectionParser("service", std::make_unique<ServiceParser>(&service_list, subcontexts));
+    parser.AddSectionParser(
+            "service", std::make_unique<ServiceParser>(&service_list, subcontexts, std::nullopt));
     parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, subcontexts));
     parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
 
@@ -124,7 +125,8 @@
 Parser CreateServiceOnlyParser(ServiceList& service_list) {
     Parser parser;
 
-    parser.AddSectionParser("service", std::make_unique<ServiceParser>(&service_list, subcontexts));
+    parser.AddSectionParser(
+            "service", std::make_unique<ServiceParser>(&service_list, subcontexts, std::nullopt));
     return parser;
 }
 
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 1bcc5ef..a09db18 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -44,7 +44,8 @@
     Action::set_function_map(&test_function_map);
 
     Parser parser;
-    parser.AddSectionParser("service", std::make_unique<ServiceParser>(service_list, nullptr));
+    parser.AddSectionParser("service",
+                            std::make_unique<ServiceParser>(service_list, nullptr, std::nullopt));
     parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
     parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
 
diff --git a/init/service_parser.cpp b/init/service_parser.cpp
index 33ed050..ba35104 100644
--- a/init/service_parser.cpp
+++ b/init/service_parser.cpp
@@ -152,6 +152,12 @@
         return Error() << "Interface name must not be a value name '" << interface_name << "'";
     }
 
+    if (known_interfaces_ && known_interfaces_->count(interface_name) == 0) {
+        return Error() << "Interface is not in the known set of hidl_interfaces: '"
+                       << interface_name << "'. Please ensure the interface is built "
+                       << "by a hidl_interface target.";
+    }
+
     const std::string fullname = interface_name + "/" + instance_name;
 
     for (const auto& svc : *service_list_) {
diff --git a/init/service_parser.h b/init/service_parser.h
index 0a5b291..5a16768 100644
--- a/init/service_parser.h
+++ b/init/service_parser.h
@@ -28,8 +28,12 @@
 
 class ServiceParser : public SectionParser {
   public:
-    ServiceParser(ServiceList* service_list, std::vector<Subcontext>* subcontexts)
-        : service_list_(service_list), subcontexts_(subcontexts), service_(nullptr) {}
+    ServiceParser(ServiceList* service_list, std::vector<Subcontext>* subcontexts,
+                  const std::optional<std::set<std::string>>& known_interfaces)
+        : service_list_(service_list),
+          subcontexts_(subcontexts),
+          known_interfaces_(known_interfaces),
+          service_(nullptr) {}
     Result<void> ParseSection(std::vector<std::string>&& args, const std::string& filename,
                               int line) override;
     Result<void> ParseLineSection(std::vector<std::string>&& args, int line) override;
@@ -81,6 +85,7 @@
 
     ServiceList* service_list_;
     std::vector<Subcontext>* subcontexts_;
+    std::optional<std::set<std::string>> known_interfaces_;
     std::unique_ptr<Service> service_;
     std::string filename_;
 };
diff --git a/logd/Android.bp b/logd/Android.bp
index 9b86258..b337b7c 100644
--- a/logd/Android.bp
+++ b/logd/Android.bp
@@ -39,7 +39,6 @@
         "FlushCommand.cpp",
         "LogBuffer.cpp",
         "LogBufferElement.cpp",
-        "LogBufferInterface.cpp",
         "LogTimes.cpp",
         "LogStatistics.cpp",
         "LogWhiteBlackList.cpp",
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index 404433f..c2d5b97 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -27,7 +27,6 @@
 #include <sysutils/SocketClient.h>
 
 #include "LogBufferElement.h"
-#include "LogBufferInterface.h"
 #include "LogStatistics.h"
 #include "LogTags.h"
 #include "LogTimes.h"
@@ -75,7 +74,7 @@
 
 typedef std::list<LogBufferElement*> LogBufferElementCollection;
 
-class LogBuffer : public LogBufferInterface {
+class LogBuffer {
     LogBufferElementCollection mLogElements;
     pthread_rwlock_t mLogElementsLock;
 
@@ -108,14 +107,14 @@
     LastLogTimes& mTimes;
 
     explicit LogBuffer(LastLogTimes* times);
-    ~LogBuffer() override;
+    ~LogBuffer();
     void init();
     bool isMonotonic() {
         return monotonic;
     }
 
-    int log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid,
-            const char* msg, uint16_t len) override;
+    int log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid, const char* msg,
+            uint16_t len);
     // lastTid is an optional context to help detect if the last previous
     // valid message was from the same source so we can differentiate chatty
     // filter types (identical or expired)
diff --git a/logd/LogBufferInterface.cpp b/logd/LogBufferInterface.cpp
deleted file mode 100644
index 66b3ab4..0000000
--- a/logd/LogBufferInterface.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2017 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 "LogBufferInterface.h"
-
-LogBufferInterface::LogBufferInterface() {
-}
-LogBufferInterface::~LogBufferInterface() {}
\ No newline at end of file
diff --git a/logd/LogBufferInterface.h b/logd/LogBufferInterface.h
deleted file mode 100644
index 2bb08f9..0000000
--- a/logd/LogBufferInterface.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2012-2014 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 _LOGD_LOG_BUFFER_INTERFACE_H__
-#define _LOGD_LOG_BUFFER_INTERFACE_H__
-
-#include <sys/types.h>
-
-#include <android-base/macros.h>
-#include <log/log_id.h>
-#include <log/log_time.h>
-
-// Abstract interface that handles log when log available.
-class LogBufferInterface {
-   public:
-    LogBufferInterface();
-    virtual ~LogBufferInterface();
-    // Handles a log entry when available in LogListener.
-    // Returns the size of the handled log message.
-    virtual int log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
-                    pid_t tid, const char* msg, uint16_t len) = 0;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(LogBufferInterface);
-};
-
-#endif  // _LOGD_LOG_BUFFER_INTERFACE_H__
diff --git a/logd/LogListener.cpp b/logd/LogListener.cpp
index 7f78e19..443570f 100644
--- a/logd/LogListener.cpp
+++ b/logd/LogListener.cpp
@@ -30,9 +30,8 @@
 #include "LogListener.h"
 #include "LogUtils.h"
 
-LogListener::LogListener(LogBufferInterface* buf, LogReader* reader)
-    : SocketListener(getLogSocket(), false), logbuf(buf), reader(reader) {
-}
+LogListener::LogListener(LogBuffer* buf, LogReader* reader)
+    : SocketListener(getLogSocket(), false), logbuf(buf), reader(reader) {}
 
 bool LogListener::onDataAvailable(SocketClient* cli) {
     static bool name_set;
@@ -107,13 +106,10 @@
     // NB: hdr.msg_flags & MSG_TRUNC is not tested, silently passing a
     // truncated message to the logs.
 
-    if (logbuf != nullptr) {
-        int res = logbuf->log(
-            logId, header->realtime, cred->uid, cred->pid, header->tid, msg,
-            ((size_t)n <= UINT16_MAX) ? (uint16_t)n : UINT16_MAX);
-        if (res > 0 && reader != nullptr) {
-            reader->notifyNewLog(static_cast<log_mask_t>(1 << logId));
-        }
+    int res = logbuf->log(logId, header->realtime, cred->uid, cred->pid, header->tid, msg,
+                          ((size_t)n <= UINT16_MAX) ? (uint16_t)n : UINT16_MAX);
+    if (res > 0) {
+        reader->notifyNewLog(static_cast<log_mask_t>(1 << logId));
     }
 
     return true;
diff --git a/logd/LogListener.h b/logd/LogListener.h
index e16c5fb..8fe3da4 100644
--- a/logd/LogListener.h
+++ b/logd/LogListener.h
@@ -21,11 +21,11 @@
 #include "LogReader.h"
 
 class LogListener : public SocketListener {
-    LogBufferInterface* logbuf;
+    LogBuffer* logbuf;
     LogReader* reader;
 
    public:
-    LogListener(LogBufferInterface* buf, LogReader* reader /* nullable */);
+     LogListener(LogBuffer* buf, LogReader* reader);
 
    protected:
     virtual bool onDataAvailable(SocketClient* cli);