C++程序  |  168行  |  6.34 KB

/*
 * 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