blob: f8518fd58679072d798dbedfffb99641cf894924 [file] [log] [blame]
Songchun Fan3c82a302019-11-29 14:23:45 -08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
19#include <android-base/strings.h>
20#include <android-base/unique_fd.h>
Songchun Fan3c82a302019-11-29 14:23:45 -080021#include <android/content/pm/DataLoaderParamsParcel.h>
Songchun Fan103ba1d2020-02-03 17:32:32 -080022#include <android/os/incremental/IIncrementalManager.h>
Songchun Fan3c82a302019-11-29 14:23:45 -080023#include <binder/IServiceManager.h>
24#include <utils/String16.h>
25#include <utils/StrongPointer.h>
26#include <utils/Vector.h>
27
28#include <atomic>
29#include <chrono>
30#include <future>
31#include <limits>
32#include <map>
33#include <mutex>
34#include <string>
35#include <string_view>
36#include <unordered_map>
37#include <utility>
38#include <vector>
39
40#include "ServiceWrappers.h"
41#include "android/content/pm/BnDataLoaderStatusListener.h"
42#include "incfs.h"
43#include "path.h"
44
45using namespace android::os::incremental;
46
47namespace android::os {
48class IVold;
49}
50
51namespace android::incremental {
52
53using MountId = int;
54using StorageId = int;
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080055using FileId = incfs::FileId;
Songchun Fan3c82a302019-11-29 14:23:45 -080056using BlockIndex = incfs::BlockIndex;
57using RawMetadata = incfs::RawMetadata;
58using Clock = std::chrono::steady_clock;
59using TimePoint = std::chrono::time_point<Clock>;
60using Seconds = std::chrono::seconds;
61
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080062class IncrementalService final {
Songchun Fan3c82a302019-11-29 14:23:45 -080063public:
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080064 explicit IncrementalService(ServiceManagerWrapper&& sm, std::string_view rootDir);
Songchun Fan3c82a302019-11-29 14:23:45 -080065
66#pragma GCC diagnostic push
67#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
68 ~IncrementalService();
69#pragma GCC diagnostic pop
70
71 static constexpr StorageId kInvalidStorageId = -1;
72 static constexpr StorageId kMaxStorageId = std::numeric_limits<int>::max();
73
74 enum CreateOptions {
75 TemporaryBind = 1,
76 PermanentBind = 2,
77 CreateNew = 4,
78 OpenExisting = 8,
79
80 Default = TemporaryBind | CreateNew
81 };
82
83 enum class BindKind {
84 Temporary = 0,
85 Permanent = 1,
86 };
87
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080088 static FileId idFromMetadata(std::span<const uint8_t> metadata);
89 static inline FileId idFromMetadata(std::span<const char> metadata) {
90 return idFromMetadata({(const uint8_t*)metadata.data(), metadata.size()});
91 }
92
Songchun Fan3c82a302019-11-29 14:23:45 -080093 std::optional<std::future<void>> onSystemReady();
94
Songchun Fan103ba1d2020-02-03 17:32:32 -080095 StorageId createStorage(std::string_view mountPoint, DataLoaderParamsParcel&& dataLoaderParams,
Songchun Fan3c82a302019-11-29 14:23:45 -080096 CreateOptions options = CreateOptions::Default);
97 StorageId createLinkedStorage(std::string_view mountPoint, StorageId linkedStorage,
98 CreateOptions options = CreateOptions::Default);
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080099 StorageId openStorage(std::string_view path);
Songchun Fan3c82a302019-11-29 14:23:45 -0800100
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800101 FileId nodeFor(StorageId storage, std::string_view path) const;
102 std::pair<FileId, std::string_view> parentAndNameFor(StorageId storage,
103 std::string_view path) const;
Songchun Fan3c82a302019-11-29 14:23:45 -0800104
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800105 int bind(StorageId storage, std::string_view source, std::string_view target, BindKind kind);
Songchun Fan3c82a302019-11-29 14:23:45 -0800106 int unbind(StorageId storage, std::string_view target);
107 void deleteStorage(StorageId storage);
108
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800109 int makeFile(StorageId storage, std::string_view path, int mode, FileId id,
110 incfs::NewFileParams params);
111 int makeDir(StorageId storage, std::string_view path, int mode = 0555);
112 int makeDirs(StorageId storage, std::string_view path, int mode = 0555);
Songchun Fan3c82a302019-11-29 14:23:45 -0800113
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800114 int link(StorageId sourceStorageId, std::string_view oldPath, StorageId destStorageId,
115 std::string_view newPath);
116 int unlink(StorageId storage, std::string_view path);
Songchun Fan3c82a302019-11-29 14:23:45 -0800117
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800118 bool isRangeLoaded(StorageId storage, FileId file, std::pair<BlockIndex, BlockIndex> range) {
Songchun Fan3c82a302019-11-29 14:23:45 -0800119 return false;
120 }
121
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800122 RawMetadata getMetadata(StorageId storage, FileId node) const;
123 std::string getSignatureData(StorageId storage, FileId node) const;
Songchun Fan3c82a302019-11-29 14:23:45 -0800124
125 std::vector<std::string> listFiles(StorageId storage) const;
126 bool startLoading(StorageId storage) const;
127
128 class IncrementalDataLoaderListener : public android::content::pm::BnDataLoaderStatusListener {
129 public:
130 IncrementalDataLoaderListener(IncrementalService& incrementalService)
131 : incrementalService(incrementalService) {}
132 // Callbacks interface
133 binder::Status onStatusChanged(MountId mount, int newStatus) override;
134
135 private:
136 IncrementalService& incrementalService;
137 };
138
139private:
140 struct IncFsMount {
141 struct Bind {
142 StorageId storage;
143 std::string savedFilename;
144 std::string sourceDir;
145 BindKind kind;
146 };
147
148 struct Storage {
149 std::string name;
Songchun Fan3c82a302019-11-29 14:23:45 -0800150 };
151
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800152 using Control = incfs::UniqueControl;
Songchun Fan3c82a302019-11-29 14:23:45 -0800153
154 using BindMap = std::map<std::string, Bind>;
155 using StorageMap = std::unordered_map<StorageId, Storage>;
156
157 mutable std::mutex lock;
158 const std::string root;
159 Control control;
160 /*const*/ MountId mountId;
161 StorageMap storages;
162 BindMap bindPoints;
163 std::optional<DataLoaderParamsParcel> savedDataLoaderParams;
164 std::atomic<int> nextStorageDirNo{0};
165 std::atomic<int> dataLoaderStatus = -1;
166 std::condition_variable dataLoaderReady;
167 TimePoint connectionLostTime = TimePoint();
168 const IncrementalService& incrementalService;
169
170 IncFsMount(std::string root, MountId mountId, Control control,
171 const IncrementalService& incrementalService)
172 : root(std::move(root)),
173 control(std::move(control)),
174 mountId(mountId),
175 incrementalService(incrementalService) {}
176 IncFsMount(IncFsMount&&) = delete;
177 IncFsMount& operator=(IncFsMount&&) = delete;
178 ~IncFsMount();
179
180 StorageMap::iterator makeStorage(StorageId id);
181
182 static void cleanupFilesystem(std::string_view root);
183 };
184
185 using IfsMountPtr = std::shared_ptr<IncFsMount>;
186 using MountMap = std::unordered_map<MountId, IfsMountPtr>;
187 using BindPathMap = std::map<std::string, IncFsMount::BindMap::iterator, path::PathLess>;
188
189 void mountExistingImages();
190 bool mountExistingImage(std::string_view root, std::string_view key);
191
192 IfsMountPtr getIfs(StorageId storage) const;
193 const IfsMountPtr& getIfsLocked(StorageId storage) const;
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800194 int addBindMount(IncFsMount& ifs, StorageId storage, std::string_view storageRoot,
195 std::string&& source, std::string&& target, BindKind kind,
196 std::unique_lock<std::mutex>& mainLock);
Songchun Fan3c82a302019-11-29 14:23:45 -0800197
198 int addBindMountWithMd(IncFsMount& ifs, StorageId storage, std::string&& metadataName,
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800199 std::string&& source, std::string&& target, BindKind kind,
Songchun Fan3c82a302019-11-29 14:23:45 -0800200 std::unique_lock<std::mutex>& mainLock);
201
202 bool prepareDataLoader(IncFsMount& ifs, DataLoaderParamsParcel* params);
203 BindPathMap::const_iterator findStorageLocked(std::string_view path) const;
204 StorageId findStorageId(std::string_view path) const;
205
206 void deleteStorage(IncFsMount& ifs);
207 void deleteStorageLocked(IncFsMount& ifs, std::unique_lock<std::mutex>&& ifsLock);
208 MountMap::iterator getStorageSlotLocked();
Songchun Fan103ba1d2020-02-03 17:32:32 -0800209 std::string normalizePathToStorage(const IfsMountPtr incfs, StorageId storage,
210 std::string_view path);
Songchun Fan3c82a302019-11-29 14:23:45 -0800211
212 // Member variables
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800213 std::unique_ptr<VoldServiceWrapper> mVold;
214 std::unique_ptr<IncrementalManagerWrapper> mIncrementalManager;
215 std::unique_ptr<IncFsWrapper> mIncFs;
Songchun Fan3c82a302019-11-29 14:23:45 -0800216 const std::string mIncrementalDir;
217
218 mutable std::mutex mLock;
219 mutable std::mutex mMountOperationLock;
220 MountMap mMounts;
221 BindPathMap mBindsByPath;
222
223 std::atomic_bool mSystemReady = false;
224 StorageId mNextId = 0;
225 std::promise<void> mPrepareDataLoaders;
226};
227
228} // namespace android::incremental