| /* |
| * 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 <map> |
| #include <memory> |
| #include <mutex> |
| #include <sstream> |
| #include <string> |
| #include <vector> |
| |
| #include <android-base/unique_fd.h> |
| #include <android/gsi/BnGsiService.h> |
| #include <binder/BinderService.h> |
| #include <libfiemap_writer/split_fiemap_writer.h> |
| #include <liblp/builder.h> |
| #include "libgsi/libgsi.h" |
| |
| namespace android { |
| namespace gsi { |
| |
| class GsiService : public BinderService<GsiService>, public BnGsiService { |
| public: |
| static void Register(); |
| |
| GsiService(); |
| ~GsiService() override; |
| |
| binder::Status startGsiInstall(int64_t gsiSize, int64_t userdataSize, bool wipeUserdata, |
| int* _aidl_return) override; |
| binder::Status beginGsiInstall(const GsiInstallParams& params, int* _aidl_return) override; |
| binder::Status commitGsiChunkFromStream(const ::android::os::ParcelFileDescriptor& stream, |
| int64_t bytes, bool* _aidl_return) override; |
| binder::Status getInstallProgress(::android::gsi::GsiProgress* _aidl_return) override; |
| binder::Status commitGsiChunkFromMemory(const ::std::vector<uint8_t>& bytes, |
| bool* _aidl_return) override; |
| binder::Status cancelGsiInstall(bool* _aidl_return) override; |
| binder::Status setGsiBootable(bool oneShot, int* _aidl_return) override; |
| binder::Status isGsiEnabled(bool* _aidl_return) override; |
| binder::Status removeGsiInstall(bool* _aidl_return) override; |
| binder::Status disableGsiInstall(bool* _aidl_return) override; |
| binder::Status isGsiRunning(bool* _aidl_return) override; |
| binder::Status isGsiInstalled(bool* _aidl_return) override; |
| binder::Status isGsiInstallInProgress(bool* _aidl_return) override; |
| binder::Status getUserdataImageSize(int64_t* _aidl_return) override; |
| binder::Status getGsiBootStatus(int* _aidl_return) override; |
| binder::Status getInstalledGsiImageDir(std::string* _aidl_return) override; |
| binder::Status wipeGsiUserdata(int* _aidl_return) override; |
| |
| static char const* getServiceName() { return kGsiServiceName; } |
| |
| static void RunStartupTasks(); |
| |
| // This helper class will redirect writes to either a SplitFiemap or |
| // device-mapper. |
| class WriteHelper { |
| public: |
| virtual ~WriteHelper() {}; |
| virtual bool Write(const void* data, uint64_t bytes) = 0; |
| virtual bool Flush() = 0; |
| virtual uint64_t Size() = 0; |
| |
| WriteHelper() = default; |
| WriteHelper(const WriteHelper&) = delete; |
| WriteHelper& operator=(const WriteHelper&) = delete; |
| WriteHelper& operator=(WriteHelper&&) = delete; |
| WriteHelper(WriteHelper&&) = delete; |
| }; |
| |
| private: |
| using LpMetadata = android::fs_mgr::LpMetadata; |
| using MetadataBuilder = android::fs_mgr::MetadataBuilder; |
| using SplitFiemap = android::fiemap_writer::SplitFiemap; |
| |
| struct Image { |
| std::unique_ptr<SplitFiemap> writer; |
| uint64_t actual_size; |
| }; |
| |
| int ValidateInstallParams(GsiInstallParams* params); |
| int StartInstall(const GsiInstallParams& params); |
| int PerformSanityChecks(); |
| int PreallocateFiles(); |
| int PreallocateUserdata(); |
| int PreallocateSystem(); |
| int DetermineReadWriteMethod(); |
| bool FormatUserdata(); |
| bool CommitGsiChunk(int stream_fd, int64_t bytes); |
| bool CommitGsiChunk(const void* data, size_t bytes); |
| int SetGsiBootable(bool one_shot); |
| int ReenableGsi(bool one_shot); |
| int WipeUserdata(); |
| bool DisableGsiInstall(); |
| bool AddPartitionFiemap(android::fs_mgr::MetadataBuilder* builder, |
| android::fs_mgr::Partition* partition, const Image& image, |
| const std::string& block_device); |
| std::unique_ptr<LpMetadata> CreateMetadata(); |
| std::unique_ptr<SplitFiemap> CreateFiemapWriter(const std::string& path, uint64_t size, |
| int* error); |
| bool CreateInstallStatusFile(); |
| bool CreateMetadataFile(); |
| bool SetBootMode(bool one_shot); |
| void PostInstallCleanup(); |
| |
| void StartAsyncOperation(const std::string& step, int64_t total_bytes); |
| void UpdateProgress(int status, int64_t bytes_processed); |
| int GetExistingImage(const LpMetadata& metadata, const std::string& name, Image* image); |
| std::unique_ptr<WriteHelper> OpenPartition(const std::string& name); |
| |
| enum class AccessLevel { |
| System, |
| SystemOrShell |
| }; |
| binder::Status CheckUid(AccessLevel level = AccessLevel::System); |
| |
| static bool RemoveGsiFiles(const std::string& install_dir, bool wipeUserdata); |
| static std::string GetImagePath(const std::string& image_dir, const std::string& name); |
| static std::string GetInstalledImagePath(const std::string& name); |
| static std::string GetInstalledImageDir(); |
| |
| std::mutex main_lock_; |
| |
| // Set before installation starts, to determine whether or not to delete |
| // the userdata image if installation fails. |
| bool wipe_userdata_on_failure_; |
| |
| // These are initialized or set in StartInstall(). |
| bool installing_ = false; |
| std::atomic<bool> should_abort_ = false; |
| std::string install_dir_; |
| std::string userdata_gsi_path_; |
| std::string system_gsi_path_; |
| uint64_t userdata_block_size_; |
| uint64_t system_block_size_; |
| uint64_t gsi_size_; |
| uint64_t userdata_size_; |
| bool can_use_devicemapper_; |
| bool wipe_userdata_; |
| // Remaining data we're waiting to receive for the GSI image. |
| uint64_t gsi_bytes_written_; |
| |
| // Progress bar state. |
| std::mutex progress_lock_; |
| GsiProgress progress_; |
| |
| std::unique_ptr<WriteHelper> system_writer_; |
| |
| // This is used to track which GSI partitions have been created. |
| std::map<std::string, Image> partitions_; |
| std::unique_ptr<LpMetadata> metadata_; |
| }; |
| |
| } // namespace gsi |
| } // namespace android |