#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
-#include <hardware_legacy/power.h>
#include <private/android_filesystem_config.h>
+#include <wakelock/wakelock.h>
#include <thread>
#include <dirent.h>
#include <sys/wait.h>
-#define CONSTRAIN(amount, low, high) ((amount) < (low) ? (low) : ((amount) > (high) ? (high) : (amount)))
+#define CONSTRAIN(amount, low, high) \
+ ((amount) < (low) ? (low) : ((amount) > (high) ? (high) : (amount)))
static const char* kPropBlockingExec = "persist.sys.blocking_exec";
static const char* kWakeLock = "MoveTask";
static void notifyProgress(int progress,
- const android::sp<android::os::IVoldTaskListener>& listener) {
+ const android::sp<android::os::IVoldTaskListener>& listener) {
if (listener) {
android::os::PersistableBundle extras;
listener->onStatus(progress, extras);
}
}
-static status_t pushBackContents(const std::string& path, std::vector<std::string>& cmd,
- bool addWildcard) {
- DIR* dir = opendir(path.c_str());
- if (dir == NULL) {
- return -1;
+static bool pushBackContents(const std::string& path, std::vector<std::string>& cmd,
+ int searchLevels) {
+ if (searchLevels == 0) {
+ cmd.emplace_back(path);
+ return true;
+ }
+ auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(path.c_str()), closedir);
+ if (!dirp) {
+ PLOG(ERROR) << "Unable to open directory: " << path;
+ return false;
}
bool found = false;
struct dirent* ent;
- while ((ent = readdir(dir)) != NULL) {
- if ((!strcmp(ent->d_name, ".")) || (!strcmp(ent->d_name, ".."))) {
- continue;
- }
- if (addWildcard) {
- cmd.push_back(StringPrintf("%s/%s/*", path.c_str(), ent->d_name));
- } else {
- cmd.push_back(StringPrintf("%s/%s", path.c_str(), ent->d_name));
- }
- found = true;
+ while ((ent = readdir(dirp.get())) != NULL) {
+ if (IsDotOrDotDot(*ent)) continue;
+ auto subdir = path + "/" + ent->d_name;
+ found |= pushBackContents(subdir, cmd, searchLevels - 1);
}
- closedir(dir);
- return found ? OK : -1;
+ return found;
}
static status_t execRm(const std::string& path, int startProgress, int stepProgress,
- const android::sp<android::os::IVoldTaskListener>& listener) {
+ const android::sp<android::os::IVoldTaskListener>& listener) {
notifyProgress(startProgress, listener);
uint64_t expectedBytes = GetTreeBytes(path);
cmd.push_back(kRmPath);
cmd.push_back("-f"); /* force: remove without confirmation, no error if it doesn't exist */
cmd.push_back("-R"); /* recursive: remove directory contents */
- if (pushBackContents(path, cmd, true) != OK) {
+ if (!pushBackContents(path, cmd, 2)) {
LOG(WARNING) << "No contents in " << path;
return OK;
}
sleep(1);
uint64_t deltaFreeBytes = GetFreeBytes(path) - startFreeBytes;
- notifyProgress(startProgress + CONSTRAIN((int)
- ((deltaFreeBytes * stepProgress) / expectedBytes), 0, stepProgress), listener);
+ notifyProgress(
+ startProgress +
+ CONSTRAIN((int)((deltaFreeBytes * stepProgress) / expectedBytes), 0, stepProgress),
+ listener);
}
return -1;
}
static status_t execCp(const std::string& fromPath, const std::string& toPath, int startProgress,
- int stepProgress, const android::sp<android::os::IVoldTaskListener>& listener) {
+ int stepProgress,
+ const android::sp<android::os::IVoldTaskListener>& listener) {
notifyProgress(startProgress, listener);
uint64_t expectedBytes = GetTreeBytes(fromPath);
if (expectedBytes > startFreeBytes) {
LOG(ERROR) << "Data size " << expectedBytes << " is too large to fit in free space "
- << startFreeBytes;
+ << startFreeBytes;
return -1;
}
cmd.push_back("-R"); /* recurse into subdirectories (DEST must be a directory) */
cmd.push_back("-P"); /* Do not follow symlinks [default] */
cmd.push_back("-d"); /* don't dereference symlinks */
- if (pushBackContents(fromPath, cmd, false) != OK) {
+ if (!pushBackContents(fromPath, cmd, 1)) {
LOG(WARNING) << "No contents in " << fromPath;
return OK;
}
sleep(1);
uint64_t deltaFreeBytes = startFreeBytes - GetFreeBytes(toPath);
- notifyProgress(startProgress + CONSTRAIN((int)
- ((deltaFreeBytes * stepProgress) / expectedBytes), 0, stepProgress), listener);
+ notifyProgress(
+ startProgress +
+ CONSTRAIN((int)((deltaFreeBytes * stepProgress) / expectedBytes), 0, stepProgress),
+ listener);
}
return -1;
}
}
static status_t moveStorageInternal(const std::shared_ptr<VolumeBase>& from,
- const std::shared_ptr<VolumeBase>& to,
- const android::sp<android::os::IVoldTaskListener>& listener) {
+ const std::shared_ptr<VolumeBase>& to,
+ const android::sp<android::os::IVoldTaskListener>& listener) {
std::string fromPath;
std::string toPath;
// useful anyway.
execRm(toPath, 80, 1, listener);
fail:
+ // clang-format off
{
std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getLock());
bringOnline(from);
bringOnline(to);
}
+ // clang-format on
notifyProgress(kMoveFailedInternalError, listener);
return -1;
}
void MoveStorage(const std::shared_ptr<VolumeBase>& from, const std::shared_ptr<VolumeBase>& to,
- const android::sp<android::os::IVoldTaskListener>& listener) {
- acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock);
+ const android::sp<android::os::IVoldTaskListener>& listener) {
+ auto wl = android::wakelock::WakeLock::tryGet(kWakeLock);
+ if (!wl.has_value()) {
+ return;
+ }
android::os::PersistableBundle extras;
status_t res = moveStorageInternal(from, to, listener);
if (listener) {
listener->onFinished(res, extras);
}
-
- release_wake_lock(kWakeLock);
}
} // namespace vold