/* * 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 #include #include #include #include #include #include #include #include #include #include #include "libgsi/libgsi.h" namespace android { namespace gsi { class GsiService : public BinderService, 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& 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 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 CreateMetadata(); std::unique_ptr 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 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 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 system_writer_; // This is used to track which GSI partitions have been created. std::map partitions_; std::unique_ptr metadata_; }; } // namespace gsi } // namespace android