blob: 35cdf5dd415a9ef34037c6dd7a4b2b96f113d920 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "base/SmallVector.h"
#include "base/export.h"
#include "base/StdioStream.h"
#include "base/Lock.h"
#include "base/System.h"
#include "base/Thread.h"
#include "snapshot/common.h"
#include <functional>
#include <memory>
#include <unordered_map>
namespace android {
namespace snapshot {
class ITextureLoader {
DISALLOW_COPY_AND_ASSIGN(ITextureLoader);
protected:
~ITextureLoader() = default;
public:
ITextureLoader() = default;
using LoaderThreadPtr = std::shared_ptr<android::base::InterruptibleThread>;
using loader_t = std::function<void(android::base::Stream*)>;
virtual bool start() = 0;
// Move file position to texId and trigger loader
virtual void loadTexture(uint32_t texId, const loader_t& loader) = 0;
virtual void acquireLoaderThread(LoaderThreadPtr thread) = 0;
virtual bool hasError() const = 0;
virtual uint64_t diskSize() const = 0;
virtual bool compressed() const = 0;
virtual void join() = 0;
virtual void interrupt() = 0;
};
class TextureLoader final : public ITextureLoader {
public:
AEMU_EXPORT TextureLoader(android::base::StdioStream&& stream);
AEMU_EXPORT bool start() override;
AEMU_EXPORT void loadTexture(uint32_t texId, const loader_t& loader) override;
AEMU_EXPORT bool hasError() const override { return mHasError; }
AEMU_EXPORT uint64_t diskSize() const override { return mDiskSize; }
AEMU_EXPORT bool compressed() const override { return mVersion > 1; }
AEMU_EXPORT void acquireLoaderThread(LoaderThreadPtr thread) override {
mLoaderThread = std::move(thread);
}
AEMU_EXPORT void join() override {
if (mLoaderThread) {
mLoaderThread->wait();
mLoaderThread.reset();
}
mStream.close();
mEndTime = base::getHighResTimeUs();
}
AEMU_EXPORT void interrupt() override {
if (mLoaderThread) {
mLoaderThread->interrupt();
mLoaderThread->wait();
mLoaderThread.reset();
}
mStream.close();
mEndTime = base::getHighResTimeUs();
}
// getDuration():
// Returns true if there was save with measurable time
// (and writes it to |duration| if |duration| is not null),
// otherwise returns false.
AEMU_EXPORT bool getDuration(uint64_t* duration) {
if (mEndTime < mStartTime) {
return false;
}
if (duration) {
*duration = mEndTime - mStartTime;
}
return true;
}
private:
bool readIndex();
android::base::StdioStream mStream;
std::unordered_map<uint32_t, int64_t> mIndex;
android::base::Lock mLock;
bool mStarted = false;
bool mHasError = false;
int mVersion = 0;
uint64_t mDiskSize = 0;
LoaderThreadPtr mLoaderThread;
uint64_t mStartTime = 0;
uint64_t mEndTime = 0;
};
} // namespace snapshot
} // namespace android