summaryrefslogtreecommitdiff
path: root/gsi_service.h
blob: 7a30d88b317ef37aa3269bc32b7ea3d70d110286 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/*
 * 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;

    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;

        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);
    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