// Copyright 2017 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. #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 #include #include namespace android { namespace snapshot { class ITextureLoader { DISALLOW_COPY_AND_ASSIGN(ITextureLoader); protected: ~ITextureLoader() = default; public: ITextureLoader() = default; using LoaderThreadPtr = std::shared_ptr; using loader_t = std::function; 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 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