forked from organicmaps/organicmaps
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplatform.hpp
350 lines (281 loc) · 11.8 KB
/
platform.hpp
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
#pragma once
#include "platform/battery_tracker.hpp"
#include "platform/country_defines.hpp"
#include "platform/gui_thread.hpp"
#include "platform/secure_storage.hpp"
#include "coding/reader.hpp"
#include "base/assert.hpp"
#include "base/exception.hpp"
#include "base/task_loop.hpp"
#include "base/thread_pool_delayed.hpp"
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "defines.hpp"
DECLARE_EXCEPTION(FileAbsentException, RootException);
DECLARE_EXCEPTION(FileSystemException, RootException);
namespace platform
{
class LocalCountryFile;
}
class Platform;
extern Platform & GetPlatform();
class Platform
{
public:
friend class ThreadRunner;
// ThreadRunner may be subclassed for testing purposes.
class ThreadRunner
{
public:
ThreadRunner() { GetPlatform().RunThreads(); }
virtual ~ThreadRunner() { GetPlatform().ShutdownThreads(); }
};
enum EError
{
ERR_OK = 0,
ERR_FILE_DOES_NOT_EXIST,
ERR_ACCESS_FAILED,
ERR_DIRECTORY_NOT_EMPTY,
ERR_FILE_ALREADY_EXISTS,
ERR_NAME_TOO_LONG,
ERR_NOT_A_DIRECTORY,
ERR_SYMLINK_LOOP,
ERR_IO_ERROR,
ERR_UNKNOWN
};
enum EFileType
{
Unknown = 0x1,
Regular = 0x2,
Directory = 0x4
};
enum class EConnectionType : uint8_t
{
CONNECTION_NONE,
CONNECTION_WIFI,
CONNECTION_WWAN
};
enum class ChargingStatus : uint8_t
{
Unknown,
Plugged,
Unplugged
};
enum class Thread : uint8_t
{
File,
Network,
Gui,
Background,
};
using TFilesWithType = std::vector<std::pair<std::string, EFileType>>;
protected:
/// Usually read-only directory for application resources
std::string m_resourcesDir;
/// Writable directory to store downloaded map data
/// @note on some systems it can point to external ejectable storage
std::string m_writableDir;
/// Temporary directory, can be cleaned up by the system
std::string m_tmpDir;
/// Writable directory to store persistent application data
std::string m_settingsDir;
/// Used in Android only to get corret GUI elements layout.
bool m_isTablet = false;
/// Returns last system call error as EError.
static EError ErrnoToError();
/// Platform-dependent secure storage.
platform::SecureStorage m_secureStorage;
std::unique_ptr<base::TaskLoop> m_guiThread;
std::unique_ptr<base::DelayedThreadPool> m_networkThread;
std::unique_ptr<base::DelayedThreadPool> m_fileThread;
std::unique_ptr<base::DelayedThreadPool> m_backgroundThread;
platform::BatteryLevelTracker m_batteryTracker;
public:
Platform();
virtual ~Platform() = default;
static bool IsFileExistsByFullPath(std::string const & filePath);
static void DisableBackupForFile(std::string const & filePath);
static bool RemoveFileIfExists(std::string const & filePath);
/// @returns path to current working directory.
/// @note In case of an error returns an empty std::string.
static std::string GetCurrentWorkingDirectory() noexcept;
/// @return always the same writable dir for current user with slash at the end
std::string const & WritableDir() const
{
ASSERT(!m_writableDir.empty(), ());
return m_writableDir;
}
/// Set writable dir — use for testing and linux stuff only
void SetWritableDirForTests(std::string const & path);
/// @return full path to file in user's writable directory
std::string WritablePathForFile(std::string const & file) const;
/// Uses m_writeableDir [w], m_resourcesDir [r], m_settingsDir [s].
std::string ReadPathForFile(std::string const & file,
std::string searchScope = std::string()) const;
/// @return resource dir (on some platforms it's differ from Writable dir)
std::string const & ResourcesDir() const
{
ASSERT(!m_resourcesDir.empty(), ());
return m_resourcesDir;
}
/// @note! This function is used in generator_tool and unit tests.
/// Client app should not replace default resource dir.
void SetResourceDir(std::string const & path);
/// Creates the directory in the filesystem.
[[nodiscard]] static EError MkDir(std::string const & dirName);
/// Creates the directory. Returns true on success.
/// Returns false and logs the reason on failure.
[[nodiscard]] static bool MkDirChecked(std::string const & dirName);
// Creates the directory path dirName.
// The function creates all parent directories necessary to create the directory.
// Returns true if successful; otherwise returns false.
// If the path already exists when this function is called, it returns true.
// If only some intermediate directories were created, the function returns false
// and does not restore the previous state of the file system.
[[nodiscard]] static bool MkDirRecursively(std::string const & dirName);
/// Removes empty directory from the filesystem.
static EError RmDir(std::string const & dirName);
/// Removes directory from the filesystem.
/// @note Directory can be non empty.
/// @note If function fails, directory can be partially removed.
static bool RmDirRecursively(std::string const & dirName);
/// @return path for directory with temporary files with slash at the end
std::string const & TmpDir() const { return m_tmpDir; }
/// @return full path to file in the temporary directory
std::string TmpPathForFile(std::string const & file) const { return TmpDir() + file; }
/// @return full random path to temporary file.
std::string TmpPathForFile() const;
/// @return full partially random path to temporary file.
std::string TmpPathForFile(std::string const & prefix, std::string const & suffix) const;
/// @return full path to the file where data for unit tests is stored.
std::string TestsDataPathForFile(std::string const & file) const { return ReadPathForFile(file); }
/// @return path for directory in the persistent memory, can be the same
/// as WritableDir, but on some platforms it's different
std::string const & SettingsDir() const { return m_settingsDir; }
void SetSettingsDir(std::string const & path);
/// @return full path to file in the settings directory
std::string SettingsPathForFile(std::string const & file) const;
/// @return reader for file decriptor.
/// @throws FileAbsentException
/// @param[in] file name or full path which we want to read
/// @param[in] searchScope looks for file in dirs in given order: \n
/// [w]ritable, [r]esources, [s]ettings, by [f]ull path, [e]xternal resources,
std::unique_ptr<ModelReader> GetReader(std::string const & file,
std::string searchScope = std::string()) const;
/// @name File operations
//@{
using FilesList = std::vector<std::string>;
/// Retrieves files list contained in given directory
/// @param directory directory path with slash at the end
//@{
/// @param ext files extension to find, like ".mwm".
static void GetFilesByExt(std::string const & directory, std::string_view ext,
FilesList & outFiles);
static void GetFilesByRegExp(std::string const & directory, std::string const & regexp,
FilesList & outFiles);
//@}
static void GetFilesByType(std::string const & directory, unsigned typeMask,
TFilesWithType & outFiles);
static void GetFilesRecursively(std::string const & directory, FilesList & filesList);
static bool IsDirectoryEmpty(std::string const & directory);
// Returns true if |path| refers to a directory. Returns false otherwise or on error.
static bool IsDirectory(std::string const & path);
static EError GetFileType(std::string const & path, EFileType & type);
/// @return false if file is not exist
/// @note Check files in Writable dir first, and in ReadDir if not exist in Writable dir
bool GetFileSizeByName(std::string const & fileName, uint64_t & size) const;
/// @return false if file is not exist
/// @note Try do not use in client production code
static bool GetFileSizeByFullPath(std::string const & filePath, uint64_t & size);
//@}
/// @return 0 in case of failure.
static time_t GetFileCreationTime(std::string const & path);
/// @return 0 in case of failure.
static time_t GetFileModificationTime(std::string const & path);
/// Used to check available free storage space for downloading.
enum TStorageStatus
{
STORAGE_OK = 0,
STORAGE_DISCONNECTED,
NOT_ENOUGH_SPACE
};
TStorageStatus GetWritableStorageStatus(uint64_t neededSize) const;
// Please note, that number of active cores can vary at runtime.
// DO NOT assume for the same return value between calls.
static unsigned CpuCores() ;
void GetFontNames(FilesList & res) const;
// TODO: Optimize for each platform/device.
int VideoMemoryLimit() const;
// TODO: Optimize for each platform/device.
int PreCachingDepth() const;
std::string DeviceName() const;
std::string DeviceModel() const;
/// @return string version as displayed to the user.
std::string Version() const;
/// @return integer version in yyMMdd format.
int32_t IntVersion() const;
/// @return url for clients to download maps
std::string MetaServerUrl() const;
/// @return JSON-encoded list of urls if metaserver is unreachable
std::string DefaultUrlsJSON() const;
bool IsTablet() const { return m_isTablet; }
/// @return information about kinds of memory which are relevant for a platform.
/// This method is implemented for iOS and Android only.
/// @TODO remove as its not used anywhere?
std::string GetMemoryInfo() const;
static EConnectionType ConnectionStatus();
static bool IsConnected() { return ConnectionStatus() != EConnectionType::CONNECTION_NONE; }
static ChargingStatus GetChargingStatus();
// Returns current battery level. Possible values are from 0 to 100.
// Returns 100 when actual level is unknown.
static uint8_t GetBatteryLevel();
void SetupMeasurementSystem() const;
platform::SecureStorage & GetSecureStorage() { return m_secureStorage; }
/// \brief Placing an executable object |task| on a queue of |thread|. Then the object will be
/// executed on |thread|.
/// \note |task| cannot be moved in case of |Thread::Gui|. This way unique_ptr cannot be used
/// in |task|. Use shared_ptr instead.
template <typename Task>
base::TaskLoop::PushResult RunTask(Thread thread, Task && task)
{
ASSERT(m_networkThread && m_fileThread && m_backgroundThread, ());
switch (thread)
{
case Thread::File: return m_fileThread->Push(std::forward<Task>(task));
case Thread::Network: return m_networkThread->Push(std::forward<Task>(task));
case Thread::Gui: return m_guiThread->Push(std::forward<Task>(task));
case Thread::Background: return m_backgroundThread->Push(std::forward<Task>(task));
}
UNREACHABLE();
}
template <typename Task>
base::TaskLoop::PushResult RunDelayedTask(
Thread thread, base::DelayedThreadPool::Duration const & delay, Task && task)
{
ASSERT(m_networkThread && m_fileThread && m_backgroundThread, ());
switch (thread)
{
case Thread::File: return m_fileThread->PushDelayed(delay, std::forward<Task>(task));
case Thread::Network: return m_networkThread->PushDelayed(delay, std::forward<Task>(task));
case Thread::Gui:
CHECK(false, ("Delayed tasks for gui thread are not supported yet"));
return {};
case Thread::Background:
return m_backgroundThread->PushDelayed(delay, std::forward<Task>(task));
}
UNREACHABLE();
}
void CancelTask(Thread thread, base::TaskLoop::TaskId id);
// Use this method for testing purposes only.
void SetGuiThread(std::unique_ptr<base::TaskLoop> guiThread);
platform::BatteryLevelTracker & GetBatteryTracker() { return m_batteryTracker; }
private:
void RunThreads();
void ShutdownThreads();
void GetSystemFontNames(FilesList & res) const;
};
std::string DebugPrint(Platform::EError err);
std::string DebugPrint(Platform::ChargingStatus status);