11d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey/*
21d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey * Copyright (C) 2015 The Android Open Source Project
31d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey *
41d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
51d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey * you may not use this file except in compliance with the License.
61d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey * You may obtain a copy of the License at
71d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey *
81d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
91d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey *
101d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
111d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
121d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey * See the License for the specific language governing permissions and
141d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey * limitations under the License.
151d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey */
161d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
171d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey#include "MoveTask.h"
181d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey#include "Utils.h"
191d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey#include "VolumeManager.h"
201d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey#include "ResponseCode.h"
211d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
227e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/stringprintf.h>
237e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/logging.h>
241d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey#include <private/android_filesystem_config.h>
25c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#include <hardware_legacy/power.h>
261d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
271d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey#include <dirent.h>
281d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey#include <sys/wait.h>
291d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
30cc5d58085850e6643c82b9124477e19bd092b9a9Chih-Hung Hsieh#define CONSTRAIN(amount, low, high) ((amount) < (low) ? (low) : ((amount) > (high) ? (high) : (amount)))
311d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
32fce701b5f164fa0f135b008aafd84c5bf0ce7173Jeff Sharkey#define EXEC_BLOCKING 0
33fce701b5f164fa0f135b008aafd84c5bf0ce7173Jeff Sharkey
341d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeyusing android::base::StringPrintf;
351d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
361d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeynamespace android {
371d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeynamespace vold {
381d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
391d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey// TODO: keep in sync with PackageManager
401d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeystatic const int kMoveSucceeded = -100;
411d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeystatic const int kMoveFailedInternalError = -6;
421d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
431d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeystatic const char* kCpPath = "/system/bin/cp";
441d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeystatic const char* kRmPath = "/system/bin/rm";
451d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
46c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkeystatic const char* kWakeLock = "MoveTask";
47c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey
481d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff SharkeyMoveTask::MoveTask(const std::shared_ptr<VolumeBase>& from,
491d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        const std::shared_ptr<VolumeBase>& to) :
501d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        mFrom(from), mTo(to) {
511d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey}
521d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
531d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff SharkeyMoveTask::~MoveTask() {
541d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey}
551d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
561d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeyvoid MoveTask::start() {
571d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    mThread = std::thread(&MoveTask::run, this);
581d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey}
591d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
601d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeystatic void notifyProgress(int progress) {
611d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(ResponseCode::MoveStatus,
621d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey            StringPrintf("%d", progress).c_str(), false);
631d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey}
641d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
651d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeystatic status_t pushBackContents(const std::string& path, std::vector<std::string>& cmd) {
661d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    DIR* dir = opendir(path.c_str());
671d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (dir == NULL) {
681d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        return -1;
691d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
701d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    bool found = false;
711d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    struct dirent* ent;
721d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    while ((ent = readdir(dir)) != NULL) {
731d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        if ((!strcmp(ent->d_name, ".")) || (!strcmp(ent->d_name, ".."))) {
741d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey            continue;
751d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        }
761d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        cmd.push_back(StringPrintf("%s/%s", path.c_str(), ent->d_name));
771d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        found = true;
781d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
791d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    closedir(dir);
801d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    return found ? OK : -1;
811d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey}
821d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
831d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeystatic status_t execRm(const std::string& path, int startProgress, int stepProgress) {
841d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    notifyProgress(startProgress);
851d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
861d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    uint64_t expectedBytes = GetTreeBytes(path);
871d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    uint64_t startFreeBytes = GetFreeBytes(path);
881d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
891d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    std::vector<std::string> cmd;
901d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    cmd.push_back(kRmPath);
911d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    cmd.push_back("-f"); /* force: remove without confirmation, no error if it doesn't exist */
921d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    cmd.push_back("-R"); /* recursive: remove directory contents */
931d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (pushBackContents(path, cmd) != OK) {
941d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        LOG(WARNING) << "No contents in " << path;
951d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        return OK;
961d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
971d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
98fce701b5f164fa0f135b008aafd84c5bf0ce7173Jeff Sharkey#if EXEC_BLOCKING
99fce701b5f164fa0f135b008aafd84c5bf0ce7173Jeff Sharkey    return ForkExecvp(cmd);
100fce701b5f164fa0f135b008aafd84c5bf0ce7173Jeff Sharkey#else
1011d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    pid_t pid = ForkExecvpAsync(cmd);
1021d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (pid == -1) return -1;
1031d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
1041d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    int status;
1051d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    while (true) {
1061d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        if (waitpid(pid, &status, WNOHANG) == pid) {
1071d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey            if (WIFEXITED(status)) {
1081d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey                LOG(DEBUG) << "Finished rm with status " << WEXITSTATUS(status);
1091d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey                return (WEXITSTATUS(status) == 0) ? OK : -1;
1101d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey            } else {
1111d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey                break;
1121d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey            }
1131d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        }
1141d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
1151d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        sleep(1);
1161d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        uint64_t deltaFreeBytes = GetFreeBytes(path) - startFreeBytes;
1171d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        notifyProgress(startProgress + CONSTRAIN((int)
1181d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey                ((deltaFreeBytes * stepProgress) / expectedBytes), 0, stepProgress));
1191d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
1201d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    return -1;
121fce701b5f164fa0f135b008aafd84c5bf0ce7173Jeff Sharkey#endif
1221d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey}
1231d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
1241d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeystatic status_t execCp(const std::string& fromPath, const std::string& toPath,
1251d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        int startProgress, int stepProgress) {
1261d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    notifyProgress(startProgress);
1271d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
1281d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    uint64_t expectedBytes = GetTreeBytes(fromPath);
1291d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    uint64_t startFreeBytes = GetFreeBytes(toPath);
1301d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
131a0220a5bd410d4b342ee1ca84e8381d6bc5f468eJeff Sharkey    if (expectedBytes > startFreeBytes) {
132a0220a5bd410d4b342ee1ca84e8381d6bc5f468eJeff Sharkey        LOG(ERROR) << "Data size " << expectedBytes << " is too large to fit in free space "
133a0220a5bd410d4b342ee1ca84e8381d6bc5f468eJeff Sharkey                << startFreeBytes;
134a0220a5bd410d4b342ee1ca84e8381d6bc5f468eJeff Sharkey        return -1;
135a0220a5bd410d4b342ee1ca84e8381d6bc5f468eJeff Sharkey    }
136a0220a5bd410d4b342ee1ca84e8381d6bc5f468eJeff Sharkey
1371d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    std::vector<std::string> cmd;
1381d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    cmd.push_back(kCpPath);
1391d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    cmd.push_back("-p"); /* preserve timestamps, ownership, and permissions */
1401d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    cmd.push_back("-R"); /* recurse into subdirectories (DEST must be a directory) */
1411d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    cmd.push_back("-P"); /* Do not follow symlinks [default] */
1421d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    cmd.push_back("-d"); /* don't dereference symlinks */
1431d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (pushBackContents(fromPath, cmd) != OK) {
1441d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        LOG(WARNING) << "No contents in " << fromPath;
1451d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        return OK;
1461d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
1471d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    cmd.push_back(toPath.c_str());
1481d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
149fce701b5f164fa0f135b008aafd84c5bf0ce7173Jeff Sharkey#if EXEC_BLOCKING
150fce701b5f164fa0f135b008aafd84c5bf0ce7173Jeff Sharkey    return ForkExecvp(cmd);
151fce701b5f164fa0f135b008aafd84c5bf0ce7173Jeff Sharkey#else
1521d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    pid_t pid = ForkExecvpAsync(cmd);
1531d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (pid == -1) return -1;
1541d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
1551d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    int status;
1561d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    while (true) {
1571d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        if (waitpid(pid, &status, WNOHANG) == pid) {
1581d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey            if (WIFEXITED(status)) {
1591d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey                LOG(DEBUG) << "Finished cp with status " << WEXITSTATUS(status);
1601d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey                return (WEXITSTATUS(status) == 0) ? OK : -1;
1611d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey            } else {
1621d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey                break;
1631d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey            }
1641d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        }
1651d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
1661d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        sleep(1);
1671d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        uint64_t deltaFreeBytes = startFreeBytes - GetFreeBytes(toPath);
1681d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        notifyProgress(startProgress + CONSTRAIN((int)
1691d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey                ((deltaFreeBytes * stepProgress) / expectedBytes), 0, stepProgress));
1701d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
1711d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    return -1;
172fce701b5f164fa0f135b008aafd84c5bf0ce7173Jeff Sharkey#endif
1731d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey}
1741d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
1751d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeystatic void bringOffline(const std::shared_ptr<VolumeBase>& vol) {
1761d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    vol->destroy();
1771d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    vol->setSilent(true);
1781d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    vol->create();
1791d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    vol->setMountFlags(0);
1801d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    vol->mount();
1811d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey}
1821d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
1831d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeystatic void bringOnline(const std::shared_ptr<VolumeBase>& vol) {
1841d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    vol->destroy();
1851d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    vol->setSilent(false);
1861d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    vol->create();
1871d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey}
1881d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
1891d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeyvoid MoveTask::run() {
190c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey    acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock);
191c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey
1921d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    std::string fromPath;
1931d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    std::string toPath;
1941d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
1951d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    // TODO: add support for public volumes
1961d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (mFrom->getType() != VolumeBase::Type::kEmulated) goto fail;
1971d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (mTo->getType() != VolumeBase::Type::kEmulated) goto fail;
1981d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
1991d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    // Step 1: tear down volumes and mount silently without making
2001d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    // visible to userspace apps
2017f52bca4850ca7dd1c1c3424283575c778424c97Henrik Baard    {
2027f52bca4850ca7dd1c1c3424283575c778424c97Henrik Baard        std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getLock());
2037f52bca4850ca7dd1c1c3424283575c778424c97Henrik Baard        bringOffline(mFrom);
2047f52bca4850ca7dd1c1c3424283575c778424c97Henrik Baard        bringOffline(mTo);
2057f52bca4850ca7dd1c1c3424283575c778424c97Henrik Baard    }
2061d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
2071d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    fromPath = mFrom->getInternalPath();
2081d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    toPath = mTo->getInternalPath();
2091d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
2101d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    // Step 2: clean up any stale data
2111d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (execRm(toPath, 10, 10) != OK) {
2121d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        goto fail;
2131d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
2141d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
2151d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    // Step 3: perform actual copy
2161d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (execCp(fromPath, toPath, 20, 60) != OK) {
21777f156d9f0e683d4d1cf5e1e4327c39d73c9247cHenrik Baard        goto copy_fail;
2181d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
2191d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
2201d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    // NOTE: MountService watches for this magic value to know
2211d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    // that move was successful
2221d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    notifyProgress(82);
2237f52bca4850ca7dd1c1c3424283575c778424c97Henrik Baard    {
2247f52bca4850ca7dd1c1c3424283575c778424c97Henrik Baard        std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getLock());
2257f52bca4850ca7dd1c1c3424283575c778424c97Henrik Baard        bringOnline(mFrom);
2267f52bca4850ca7dd1c1c3424283575c778424c97Henrik Baard        bringOnline(mTo);
2277f52bca4850ca7dd1c1c3424283575c778424c97Henrik Baard    }
2281d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
2291d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    // Step 4: clean up old data
2301d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (execRm(fromPath, 85, 15) != OK) {
2311d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        goto fail;
2321d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
2331d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
2341d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    notifyProgress(kMoveSucceeded);
235c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey    release_wake_lock(kWakeLock);
2361d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    return;
23777f156d9f0e683d4d1cf5e1e4327c39d73c9247cHenrik Baard
23877f156d9f0e683d4d1cf5e1e4327c39d73c9247cHenrik Baardcopy_fail:
23977f156d9f0e683d4d1cf5e1e4327c39d73c9247cHenrik Baard    // if we failed to copy the data we should not leave it laying around
24077f156d9f0e683d4d1cf5e1e4327c39d73c9247cHenrik Baard    // in target location. Do not check return value, we can not do any
24177f156d9f0e683d4d1cf5e1e4327c39d73c9247cHenrik Baard    // useful anyway.
24277f156d9f0e683d4d1cf5e1e4327c39d73c9247cHenrik Baard    execRm(toPath, 80, 1);
2431d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeyfail:
2447f52bca4850ca7dd1c1c3424283575c778424c97Henrik Baard    {
2457f52bca4850ca7dd1c1c3424283575c778424c97Henrik Baard        std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getLock());
2467f52bca4850ca7dd1c1c3424283575c778424c97Henrik Baard        bringOnline(mFrom);
2477f52bca4850ca7dd1c1c3424283575c778424c97Henrik Baard        bringOnline(mTo);
2487f52bca4850ca7dd1c1c3424283575c778424c97Henrik Baard    }
2491d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    notifyProgress(kMoveFailedInternalError);
250c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey    release_wake_lock(kWakeLock);
2511d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    return;
2521d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey}
2531d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
2541d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey}  // namespace vold
2551d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey}  // namespace android
256