diff options
-rw-r--r-- | Android.bp | 1 | ||||
-rw-r--r-- | daemon.cpp | 12 | ||||
-rw-r--r-- | file_paths.h | 7 | ||||
-rw-r--r-- | gsi_service.cpp | 54 | ||||
-rw-r--r-- | gsi_service.h | 4 | ||||
-rw-r--r-- | gsid.rc | 3 | ||||
-rw-r--r-- | include/libgsi/libgsi.h | 2 | ||||
-rw-r--r-- | libgsi.cpp | 45 | ||||
-rw-r--r-- | libgsi_private.h | 31 |
9 files changed, 143 insertions, 16 deletions
@@ -69,6 +69,7 @@ cc_binary { "libbinder", "libgsi", "libfs_mgr", + "libgsi", "liblog", "liblp", "libutils", @@ -16,16 +16,26 @@ #include "gsi_service.h" +#include <getopt.h> + +#include <string> + #include <android-base/logging.h> #include <binder/IPCThreadState.h> #include <binder/ProcessState.h> using android::ProcessState; using android::sp; +using namespace std::literals; -int main(int /* argc */, char** argv) { +int main(int argc, char** argv) { android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM)); + if (argc > 1 && argv[1] == "run-startup-tasks"s) { + android::gsi::GsiService::RunStartupTasks(); + exit(0); + } + android::gsi::GsiService::Register(); { sp<ProcessState> ps(ProcessState::self()); diff --git a/file_paths.h b/file_paths.h index 078540f..b305db3 100644 --- a/file_paths.h +++ b/file_paths.h @@ -26,8 +26,13 @@ static constexpr char kSystemFile[] = "/data/unencrypted/gsi/system_gsi.img"; static constexpr char kGsiMetadataFolder[] = "/metadata/gsi"; static constexpr char kGsiLpMetadataFile[] = "/metadata/gsi/lp_metadata"; -static constexpr char kGsiBootableFile[] = "/metadata/gsi/bootable"; static constexpr char kGsiMetadata[] = "/metadata/gsi/lp_metadata"; +// This file can contain the following values: +// [int] - boot attempt counter, starting from 0 +// "ok" - boot was marked successful +// "disabled" - boot into GSI no longer allowed +static constexpr char kGsiInstallStatusFile[] = "/metadata/gsi/install_status"; + } // namespace gsi } // namespace android diff --git a/gsi_service.cpp b/gsi_service.cpp index d30ba07..95d5255 100644 --- a/gsi_service.cpp +++ b/gsi_service.cpp @@ -33,7 +33,9 @@ #include <fs_mgr_dm_linear.h> #include <libfiemap_writer/fiemap_writer.h> #include <logwrap/logwrap.h> + #include "file_paths.h" +#include "libgsi_private.h" namespace android { namespace gsi { @@ -317,7 +319,7 @@ bool GsiService::SetGsiBootable() { return false; } - if (!CreateMetadataFile() || !CreateBootableFile()) { + if (!CreateMetadataFile() || !CreateInstallStatusFile()) { return false; } @@ -325,11 +327,11 @@ bool GsiService::SetGsiBootable() { return true; } -bool GsiService::RemoveGsiInstall() { +static bool RemoveGsiFiles() { const std::vector<std::string> files{ kUserdataFile, kSystemFile, - kGsiBootableFile, + kGsiInstallStatusFile, kGsiLpMetadataFile, }; bool ok = true; @@ -340,6 +342,17 @@ bool GsiService::RemoveGsiInstall() { ok = false; } } + return ok; +} + +bool GsiService::RemoveGsiInstall() { + bool ok = false; + if (IsGsiRunning()) { + // Can't remove gsi files while running. + ok = UninstallGsi(); + } else { + ok = RemoveGsiFiles(); + } installing_ = false; return ok; } @@ -414,11 +427,9 @@ bool GsiService::AddPartitionFiemap(MetadataBuilder* builder, Partition* partiti return true; } -bool GsiService::CreateBootableFile() { - android::base::unique_fd fd( - open(kGsiBootableFile, O_WRONLY | O_CLOEXEC | O_NOFOLLOW | O_CREAT, 0755)); - if (fd < 0) { - LOG(ERROR) << "open: " << strerror(errno) << ": " << kGsiBootableFile; +bool GsiService::CreateInstallStatusFile() { + if (!android::base::WriteStringToFile("0", kGsiInstallStatusFile)) { + PLOG(ERROR) << "write " << kGsiInstallStatusFile; return false; } return true; @@ -433,5 +444,32 @@ bool GsiService::EnsureFolderExists(const std::string& path) { return false; } +void GsiService::RunStartupTasks() { + if (!IsGsiInstalled()) { + return; + } + + std::string boot_key; + if (!GetInstallStatus(&boot_key)) { + PLOG(ERROR) << "read " << kGsiInstallStatusFile; + return; + } + + if (!IsGsiRunning()) { + // Check if a wipe was requested from fastboot or adb-in-gsi. + if (boot_key == kInstallStatusWipe) { + RemoveGsiFiles(); + } + } else { + int ignore; + if (GetBootAttempts(boot_key, &ignore)) { + // Mark the GSI as having successfully booted. + if (!android::base::WriteStringToFile(kInstallStatusOk, kGsiInstallStatusFile)) { + PLOG(ERROR) << "write " << kGsiInstallStatusFile; + } + } + } +} + } // namespace gsi } // namespace android diff --git a/gsi_service.h b/gsi_service.h index 1b20fd6..7f5d49b 100644 --- a/gsi_service.h +++ b/gsi_service.h @@ -48,6 +48,8 @@ class GsiService : public BinderService<GsiService>, public BnGsiService { static char const* getServiceName() { return kGsiServiceName; } + static void RunStartupTasks(); + private: using LpMetadata = android::fs_mgr::LpMetadata; using MetadataBuilder = android::fs_mgr::MetadataBuilder; @@ -66,7 +68,7 @@ class GsiService : public BinderService<GsiService>, public BnGsiService { android::fiemap_writer::FiemapWriter* writer); std::unique_ptr<MetadataBuilder> CreateMetadataBuilder(); fiemap_writer::FiemapUniquePtr CreateFiemapWriter(const std::string& path, uint64_t size); - bool CreateBootableFile(); + bool CreateInstallStatusFile(); bool CreateMetadataFile(); void PostInstallCleanup(); @@ -3,3 +3,6 @@ service gsid /system/bin/gsid disabled user root group root + +on boot + exec - gsid gsid -- /system/bin/gsid run-startup-tasks diff --git a/include/libgsi/libgsi.h b/include/libgsi/libgsi.h index 705636c..ba5dd71 100644 --- a/include/libgsi/libgsi.h +++ b/include/libgsi/libgsi.h @@ -25,6 +25,8 @@ static constexpr char kGsiServiceName[] = "gsiservice"; static constexpr char kGsiBootedIndicatorFile[] = "/metadata/gsi/booted"; +static constexpr int kMaxBootAttempts = 3; + // Returns true if the currently running system image is a live GSI. bool IsGsiRunning(); @@ -16,21 +16,28 @@ #include "libgsi/libgsi.h" +#include <string.h> #include <unistd.h> +#include <string> + #include <android-base/file.h> +#include <android-base/parseint.h> #include "file_paths.h" +#include "libgsi_private.h" namespace android { namespace gsi { +using namespace std::literals; + bool IsGsiRunning() { return !access(kGsiBootedIndicatorFile, F_OK); } bool IsGsiInstalled() { - return !access(kGsiBootableFile, F_OK); + return !access(kGsiInstallStatusFile, F_OK); } static bool CanBootIntoGsi(std::string* error) { @@ -38,8 +45,29 @@ static bool CanBootIntoGsi(std::string* error) { *error = "not detected"; return false; } - // :TODO: boot attempts - return true; + + std::string boot_key; + if (!GetInstallStatus(&boot_key)) { + *error = "error ("s + strerror(errno) + ")"; + return false; + } + + // Give up if we've failed to boot kMaxBootAttempts times. + int attempts; + if (GetBootAttempts(boot_key, &attempts)) { + if (attempts + 1 >= kMaxBootAttempts) { + *error = "exceeded max boot attempts"; + return false; + } + std::string new_key = std::to_string(attempts + 1); + if (!android::base::WriteStringToFile(new_key, kGsiInstallStatusFile)) { + *error = "error ("s + strerror(errno) + ")"; + return false; + } + return true; + } + + return boot_key == kInstallStatusOk; } bool CanBootIntoGsi(std::string* metadata_file, std::string* error) { @@ -49,7 +77,6 @@ bool CanBootIntoGsi(std::string* metadata_file, std::string* error) { android::base::RemoveFileIfExists(kGsiBootedIndicatorFile); if (!CanBootIntoGsi(error)) { - android::base::RemoveFileIfExists(kGsiBootableFile); return false; } @@ -58,7 +85,7 @@ bool CanBootIntoGsi(std::string* metadata_file, std::string* error) { } bool UninstallGsi() { - if (!android::base::RemoveFileIfExists(kGsiBootableFile)) { + if (!android::base::WriteStringToFile(kInstallStatusWipe, kGsiInstallStatusFile)) { return false; } return true; @@ -68,5 +95,13 @@ bool MarkSystemAsGsi() { return android::base::WriteStringToFile("1", kGsiBootedIndicatorFile); } +bool GetInstallStatus(std::string* status) { + return android::base::ReadFileToString(kGsiInstallStatusFile, status); +} + +bool GetBootAttempts(const std::string& boot_key, int* attempts) { + return android::base::ParseInt(boot_key, attempts); +} + } // namespace gsi } // namespace android diff --git a/libgsi_private.h b/libgsi_private.h new file mode 100644 index 0000000..54e4ab2 --- /dev/null +++ b/libgsi_private.h @@ -0,0 +1,31 @@ +/* + * 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 <string> + +namespace android { +namespace gsi { + +bool GetInstallStatus(std::string* status); +bool GetBootAttempts(const std::string& boot_key, int* attempts); + +static constexpr char kInstallStatusOk[] = "ok"; +static constexpr char kInstallStatusWipe[] = "wipe"; + +} // namespace gsi +} // namespace android |