blob: 9079f40983ffd78557eb54fa9b50bca9d6acfb0a [file] [log] [blame]
// Copyright 2018 The Android Open Source Project
//
// This software is licensed under the terms of the GNU General Public
// License version 2, as published by the Free Software Foundation, and
// may be copied, distributed, and modified under those terms.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
#include "android/multi-instance.h"
#include "android/base/files/FileShareOpen.h"
#include "android/base/memory/LazyInstance.h"
#include "android/base/system/System.h"
#include "android/base/threads/Thread.h"
#include "android/globals.h"
#include "android/utils/debug.h"
namespace {
struct MultiInstanceState {
android::base::FileShare shareMode = android::base::FileShare::Write;
FILE* sharedFile = nullptr;
android::multiinstance::UpdateDriveShareModeFunc updateDriveShareModeFunc =
nullptr;
};
static android::base::LazyInstance<MultiInstanceState> sMultiInstanceState =
LAZY_INSTANCE_INIT;
} // namespace
bool android::multiinstance::initInstanceShareMode(
android::base::FileShare shareMode) {
if (sMultiInstanceState.hasInstance()) {
return sMultiInstanceState->shareMode == shareMode;
}
AvdInfo* avd = android_avdInfo;
const char* multiInstanceLock = avdInfo_getMultiInstanceLockFilePath(avd);
if (!android::base::System::get()->pathIsFile(multiInstanceLock)) {
android::base::createFileForShare(multiInstanceLock);
}
const char* mode =
shareMode == android::base::FileShare::Read
? "rb"
: "wb";
for (int i = 0; i < 3; ++ i) {
sMultiInstanceState->sharedFile =
android::base::fsopen(multiInstanceLock, mode, shareMode);
if (!sMultiInstanceState->sharedFile) {
dwarning("Another emualtor is still running, wait for a sec...");
base::Thread::sleepMs(1 * 1000);
} else {
break;
}
}
if (!sMultiInstanceState->sharedFile) {
derror("Another emulator instance is running. Please close it or "
"run all emulators with -read-only flag.\n");
return false;
}
sMultiInstanceState->shareMode = shareMode;
return true;
}
bool android::multiinstance::updateInstanceShareMode(
const char* snapshotName,
base::FileShare shareMode) {
assert(sMultiInstanceState.hasInstance());
if (sMultiInstanceState->shareMode == shareMode) {
return true;
}
if (android::base::updateFileShare(sMultiInstanceState->sharedFile,
shareMode)) {
assert(sMultiInstanceState->updateDriveShareModeFunc);
if (sMultiInstanceState->updateDriveShareModeFunc) {
if (!sMultiInstanceState->updateDriveShareModeFunc(snapshotName,
shareMode)) {
return false;
}
}
sMultiInstanceState->shareMode = shareMode;
return true;
} else {
return false;
}
}
void android::multiinstance::setUpdateDriveShareModeFunc(
UpdateDriveShareModeFunc updateDriveShareModeFunc) {
sMultiInstanceState->updateDriveShareModeFunc = updateDriveShareModeFunc;
}
android::base::FileShare android::multiinstance::getInstanceShareMode() {
assert(sMultiInstanceState.hasInstance());
return sMultiInstanceState->shareMode;
}