Add a default implementation and tests of IBootControl 1.1.

Bug: 138861550
Test: VtsHalBootV1_0TargetTest
      VtsHalBootV1_1TargetTest

Change-Id: I53ea2465612b03435c37c3b4edeaff72c368373b
diff --git a/boot/1.1/default/Android.bp b/boot/1.1/default/Android.bp
new file mode 100644
index 0000000..dca5c26
--- /dev/null
+++ b/boot/1.1/default/Android.bp
@@ -0,0 +1,43 @@
+cc_library_shared {
+    name: "[email protected]",
+    defaults: [
+        "hidl_defaults",
+        "libboot_control_defaults",
+    ],
+    relative_install_path: "hw",
+    vendor: true,
+    recovery_available: true,
+    srcs: ["BootControl.cpp"],
+
+    shared_libs: [
+        "liblog",
+        "libhidlbase",
+        "libhardware",
+        "libutils",
+        "[email protected]",
+        "[email protected]",
+    ],
+    static_libs: [
+        "libboot_control",
+        "libfstab",
+    ],
+}
+
+cc_binary {
+    name: "[email protected]",
+    defaults: ["hidl_defaults"],
+    relative_install_path: "hw",
+    vendor: true,
+    init_rc: ["[email protected]"],
+    srcs: ["service.cpp"],
+
+    shared_libs: [
+        "liblog",
+        "libhardware",
+        "libhidlbase",
+        "libutils",
+        "[email protected]",
+        "[email protected]",
+    ],
+
+}
diff --git a/boot/1.1/default/BootControl.cpp b/boot/1.1/default/BootControl.cpp
new file mode 100644
index 0000000..c9c62a4
--- /dev/null
+++ b/boot/1.1/default/BootControl.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "[email protected]"
+
+#include <memory>
+
+#include <log/log.h>
+
+#include "BootControl.h"
+
+namespace android {
+namespace hardware {
+namespace boot {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::boot::V1_0::CommandResult;
+
+bool BootControl::Init() {
+    return impl_.Init();
+}
+
+// Methods from ::android::hardware::boot::V1_0::IBootControl follow.
+Return<uint32_t> BootControl::getNumberSlots() {
+    return impl_.GetNumberSlots();
+}
+
+Return<uint32_t> BootControl::getCurrentSlot() {
+    return impl_.GetCurrentSlot();
+}
+
+Return<void> BootControl::markBootSuccessful(markBootSuccessful_cb _hidl_cb) {
+    struct CommandResult cr;
+    if (impl_.MarkBootSuccessful()) {
+        cr.success = true;
+        cr.errMsg = "Success";
+    } else {
+        cr.success = false;
+        cr.errMsg = "Operation failed";
+    }
+    _hidl_cb(cr);
+    return Void();
+}
+
+Return<void> BootControl::setActiveBootSlot(uint32_t slot, setActiveBootSlot_cb _hidl_cb) {
+    struct CommandResult cr;
+    if (impl_.SetActiveBootSlot(slot)) {
+        cr.success = true;
+        cr.errMsg = "Success";
+    } else {
+        cr.success = false;
+        cr.errMsg = "Operation failed";
+    }
+    _hidl_cb(cr);
+    return Void();
+}
+
+Return<void> BootControl::setSlotAsUnbootable(uint32_t slot, setSlotAsUnbootable_cb _hidl_cb) {
+    struct CommandResult cr;
+    if (impl_.SetSlotAsUnbootable(slot)) {
+        cr.success = true;
+        cr.errMsg = "Success";
+    } else {
+        cr.success = false;
+        cr.errMsg = "Operation failed";
+    }
+    _hidl_cb(cr);
+    return Void();
+}
+
+Return<BoolResult> BootControl::isSlotBootable(uint32_t slot) {
+    if (!impl_.IsValidSlot(slot)) {
+        return BoolResult::INVALID_SLOT;
+    }
+    return impl_.IsSlotBootable(slot) ? BoolResult::TRUE : BoolResult::FALSE;
+}
+
+Return<BoolResult> BootControl::isSlotMarkedSuccessful(uint32_t slot) {
+    if (!impl_.IsValidSlot(slot)) {
+        return BoolResult::INVALID_SLOT;
+    }
+    return impl_.IsSlotMarkedSuccessful(slot) ? BoolResult::TRUE : BoolResult::FALSE;
+}
+
+Return<void> BootControl::getSuffix(uint32_t slot, getSuffix_cb _hidl_cb) {
+    hidl_string ans;
+    const char* suffix = impl_.GetSuffix(slot);
+    if (suffix) {
+        ans = suffix;
+    }
+    _hidl_cb(ans);
+    return Void();
+}
+
+Return<bool> BootControl::setSnapshotMergeStatus(MergeStatus status) {
+    return impl_.SetSnapshotMergeStatus(status);
+}
+
+Return<MergeStatus> BootControl::getSnapshotMergeStatus() {
+    return impl_.GetSnapshotMergeStatus();
+}
+
+IBootControl* HIDL_FETCH_IBootControl(const char* /* hal */) {
+    auto module = std::make_unique<BootControl>();
+    if (!module->Init()) {
+        ALOGE("Could not initialize BootControl module");
+        return nullptr;
+    }
+    return module.release();
+}
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace boot
+}  // namespace hardware
+}  // namespace android
diff --git a/boot/1.1/default/BootControl.h b/boot/1.1/default/BootControl.h
new file mode 100644
index 0000000..75511b6
--- /dev/null
+++ b/boot/1.1/default/BootControl.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <android/hardware/boot/1.1/IBootControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <libboot_control/libboot_control.h>
+
+namespace android {
+namespace hardware {
+namespace boot {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::boot::V1_0::BoolResult;
+using ::android::hardware::boot::V1_1::IBootControl;
+using ::android::hardware::boot::V1_1::MergeStatus;
+
+class BootControl : public IBootControl {
+  public:
+    bool Init();
+
+    // Methods from ::android::hardware::boot::V1_0::IBootControl follow.
+    Return<uint32_t> getNumberSlots() override;
+    Return<uint32_t> getCurrentSlot() override;
+    Return<void> markBootSuccessful(markBootSuccessful_cb _hidl_cb) override;
+    Return<void> setActiveBootSlot(uint32_t slot, setActiveBootSlot_cb _hidl_cb) override;
+    Return<void> setSlotAsUnbootable(uint32_t slot, setSlotAsUnbootable_cb _hidl_cb) override;
+    Return<BoolResult> isSlotBootable(uint32_t slot) override;
+    Return<BoolResult> isSlotMarkedSuccessful(uint32_t slot) override;
+    Return<void> getSuffix(uint32_t slot, getSuffix_cb _hidl_cb) override;
+
+    // Methods from ::android::hardware::boot::V1_1::IBootControl follow.
+    Return<bool> setSnapshotMergeStatus(MergeStatus status) override;
+    Return<MergeStatus> getSnapshotMergeStatus() override;
+
+  private:
+    android::bootable::BootControl impl_;
+};
+
+extern "C" IBootControl* HIDL_FETCH_IBootControl(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace boot
+}  // namespace hardware
+}  // namespace android
diff --git a/boot/1.1/default/[email protected] b/boot/1.1/default/[email protected]
new file mode 100644
index 0000000..83fa9d0
--- /dev/null
+++ b/boot/1.1/default/[email protected]
@@ -0,0 +1,6 @@
+service vendor.boot-hal-1-1 /vendor/bin/hw/[email protected]
+    interface [email protected]::IBootControl default
+    interface [email protected]::IBootControl default
+    class early_hal
+    user root
+    group root
diff --git a/boot/1.1/default/service.cpp b/boot/1.1/default/service.cpp
new file mode 100644
index 0000000..b24b464
--- /dev/null
+++ b/boot/1.1/default/service.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "[email protected]"
+
+#include <android/hardware/boot/1.1/IBootControl.h>
+#include <hidl/LegacySupport.h>
+
+using android::hardware::defaultPassthroughServiceImplementation;
+using ::android::hardware::boot::V1_1::IBootControl;
+
+int main(int /* argc */, char* /* argv */[]) {
+    return defaultPassthroughServiceImplementation<IBootControl>();
+}
diff --git a/boot/1.1/vts/functional/Android.bp b/boot/1.1/vts/functional/Android.bp
new file mode 100644
index 0000000..49ea09a
--- /dev/null
+++ b/boot/1.1/vts/functional/Android.bp
@@ -0,0 +1,28 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalBootV1_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalBootV1_1TargetTest.cpp"],
+    static_libs: [
+        "[email protected]",
+        "[email protected]",
+        "libgmock",
+    ],
+    test_suites: ["device-tests"],
+}
+
diff --git a/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp b/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp
new file mode 100644
index 0000000..fba9a5e
--- /dev/null
+++ b/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "boot_hidl_hal_test"
+
+#include <vector>
+
+#include <android-base/logging.h>
+#include <android/hardware/boot/1.1/IBootControl.h>
+#include <android/hardware/boot/1.1/types.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include <unistd.h>
+
+using ::android::sp;
+using ::android::hardware::hidl_enum_range;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::boot::V1_1::IBootControl;
+using ::android::hardware::boot::V1_1::MergeStatus;
+using ::testing::Contains;
+
+class BootHidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        boot = IBootControl::getService(GetParam());
+        ASSERT_NE(boot, nullptr);
+
+        LOG(INFO) << "Test is remote " << boot->isRemote();
+    }
+
+    sp<IBootControl> boot;
+};
+
+static std::vector<MergeStatus> ValidMergeStatusValues() {
+    std::vector<MergeStatus> values;
+    for (const auto value : hidl_enum_range<MergeStatus>()) {
+        if (value == MergeStatus::UNKNOWN) {
+            continue;
+        }
+        values.push_back(value);
+    }
+    return values;
+}
+
+/**
+ * Ensure merge status can be retrieved.
+ */
+TEST_P(BootHidlTest, GetSnapshotMergeStatus) {
+    auto values = ValidMergeStatusValues();
+    auto status = (MergeStatus)boot->getSnapshotMergeStatus();
+    EXPECT_THAT(values, Contains(status));
+}
+
+/**
+ * Ensure merge status can be set to arbitrary value.
+ */
+TEST_P(BootHidlTest, SetSnapshotMergeStatus) {
+    for (const auto value : ValidMergeStatusValues()) {
+        EXPECT_TRUE(boot->setSnapshotMergeStatus(value).withDefault(false));
+        auto status = boot->getSnapshotMergeStatus();
+        EXPECT_EQ(status, value);
+    }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        , BootHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IBootControl::descriptor)),
+        android::hardware::PrintInstanceNameToString);