1 // Copyright 2017 The Android Open Source Project 2 // 3 // This software is licensed under the terms of the GNU General Public 4 // License version 2, as published by the Free Software Foundation, and 5 // may be copied, distributed, and modified under those terms. 6 // 7 // This program is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 // GNU General Public License for more details. 11 12 #pragma once 13 14 #include "base/SmallVector.h" 15 #include "base/export.h" 16 #include "base/StdioStream.h" 17 #include "base/Lock.h" 18 #include "base/System.h" 19 #include "base/Thread.h" 20 #include "snapshot/common.h" 21 22 #include <functional> 23 #include <memory> 24 #include <unordered_map> 25 26 namespace android { 27 namespace snapshot { 28 29 class ITextureLoader { 30 DISALLOW_COPY_AND_ASSIGN(ITextureLoader); 31 32 protected: 33 ~ITextureLoader() = default; 34 35 public: 36 ITextureLoader() = default; 37 38 using LoaderThreadPtr = std::shared_ptr<android::base::InterruptibleThread>; 39 using loader_t = std::function<void(android::base::Stream*)>; 40 41 virtual bool start() = 0; 42 // Move file position to texId and trigger loader 43 virtual void loadTexture(uint32_t texId, const loader_t& loader) = 0; 44 virtual void acquireLoaderThread(LoaderThreadPtr thread) = 0; 45 virtual bool hasError() const = 0; 46 virtual uint64_t diskSize() const = 0; 47 virtual bool compressed() const = 0; 48 virtual void join() = 0; 49 virtual void interrupt() = 0; 50 }; 51 52 class TextureLoader final : public ITextureLoader { 53 public: 54 AEMU_EXPORT TextureLoader(android::base::StdioStream&& stream); 55 56 AEMU_EXPORT bool start() override; 57 AEMU_EXPORT void loadTexture(uint32_t texId, const loader_t& loader) override; hasError()58 AEMU_EXPORT bool hasError() const override { return mHasError; } diskSize()59 AEMU_EXPORT uint64_t diskSize() const override { return mDiskSize; } compressed()60 AEMU_EXPORT bool compressed() const override { return mVersion > 1; } 61 acquireLoaderThread(LoaderThreadPtr thread)62 AEMU_EXPORT void acquireLoaderThread(LoaderThreadPtr thread) override { 63 mLoaderThread = std::move(thread); 64 } 65 join()66 AEMU_EXPORT void join() override { 67 if (mLoaderThread) { 68 mLoaderThread->wait(); 69 mLoaderThread.reset(); 70 } 71 mStream.close(); 72 mEndTime = base::getHighResTimeUs(); 73 } 74 interrupt()75 AEMU_EXPORT void interrupt() override { 76 if (mLoaderThread) { 77 mLoaderThread->interrupt(); 78 mLoaderThread->wait(); 79 mLoaderThread.reset(); 80 } 81 mStream.close(); 82 mEndTime = base::getHighResTimeUs(); 83 } 84 85 // getDuration(): 86 // Returns true if there was save with measurable time 87 // (and writes it to |duration| if |duration| is not null), 88 // otherwise returns false. getDuration(uint64_t * duration)89 AEMU_EXPORT bool getDuration(uint64_t* duration) { 90 if (mEndTime < mStartTime) { 91 return false; 92 } 93 94 if (duration) { 95 *duration = mEndTime - mStartTime; 96 } 97 return true; 98 } 99 100 private: 101 bool readIndex(); 102 103 android::base::StdioStream mStream; 104 std::unordered_map<uint32_t, int64_t> mIndex; 105 android::base::Lock mLock; 106 bool mStarted = false; 107 bool mHasError = false; 108 int mVersion = 0; 109 uint64_t mDiskSize = 0; 110 LoaderThreadPtr mLoaderThread; 111 112 uint64_t mStartTime = 0; 113 uint64_t mEndTime = 0; 114 }; 115 116 } // namespace snapshot 117 } // namespace android 118