1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include "aemu/base/containers/SmallVector.h" 20 #include "aemu/base/export.h" 21 #include "aemu/base/files/StdioStream.h" 22 #include "aemu/base/synchronization/Lock.h" 23 #include "aemu/base/system/System.h" 24 #include "aemu/base/threads/Thread.h" 25 #include "snapshot/common.h" 26 27 #include <functional> 28 #include <memory> 29 #include <unordered_map> 30 31 namespace android { 32 namespace snapshot { 33 34 class ITextureLoader { 35 DISALLOW_COPY_AND_ASSIGN(ITextureLoader); 36 37 protected: 38 ~ITextureLoader() = default; 39 40 public: 41 ITextureLoader() = default; 42 43 using LoaderThreadPtr = std::shared_ptr<android::base::InterruptibleThread>; 44 using loader_t = std::function<void(android::base::Stream*)>; 45 46 virtual bool start() = 0; 47 // Move file position to texId and trigger loader 48 virtual void loadTexture(uint32_t texId, const loader_t& loader) = 0; 49 virtual void acquireLoaderThread(LoaderThreadPtr thread) = 0; 50 virtual bool hasError() const = 0; 51 virtual uint64_t diskSize() const = 0; 52 virtual bool compressed() const = 0; 53 virtual void join() = 0; 54 virtual void interrupt() = 0; 55 }; 56 57 class TextureLoader final : public ITextureLoader { 58 public: 59 AEMU_EXPORT TextureLoader(android::base::StdioStream&& stream); 60 61 AEMU_EXPORT bool start() override; 62 AEMU_EXPORT void loadTexture(uint32_t texId, const loader_t& loader) override; hasError()63 AEMU_EXPORT bool hasError() const override { return mHasError; } diskSize()64 AEMU_EXPORT uint64_t diskSize() const override { return mDiskSize; } compressed()65 AEMU_EXPORT bool compressed() const override { return mVersion > 1; } 66 acquireLoaderThread(LoaderThreadPtr thread)67 AEMU_EXPORT void acquireLoaderThread(LoaderThreadPtr thread) override { 68 mLoaderThread = std::move(thread); 69 } 70 join()71 AEMU_EXPORT void join() override { 72 if (mLoaderThread) { 73 mLoaderThread->wait(); 74 mLoaderThread.reset(); 75 } 76 mStream.close(); 77 mEndTime = base::getHighResTimeUs(); 78 } 79 interrupt()80 AEMU_EXPORT void interrupt() override { 81 if (mLoaderThread) { 82 mLoaderThread->interrupt(); 83 mLoaderThread->wait(); 84 mLoaderThread.reset(); 85 } 86 mStream.close(); 87 mEndTime = base::getHighResTimeUs(); 88 } 89 90 // getDuration(): 91 // Returns true if there was save with measurable time 92 // (and writes it to |duration| if |duration| is not null), 93 // otherwise returns false. getDuration(uint64_t * duration)94 AEMU_EXPORT bool getDuration(uint64_t* duration) { 95 if (mEndTime < mStartTime) { 96 return false; 97 } 98 99 if (duration) { 100 *duration = mEndTime - mStartTime; 101 } 102 return true; 103 } 104 105 private: 106 bool readIndex(); 107 108 android::base::StdioStream mStream; 109 std::unordered_map<uint32_t, int64_t> mIndex; 110 android::base::Lock mLock; 111 bool mStarted = false; 112 bool mHasError = false; 113 int mVersion = 0; 114 uint64_t mDiskSize = 0; 115 LoaderThreadPtr mLoaderThread; 116 117 uint64_t mStartTime = 0; 118 uint64_t mEndTime = 0; 119 }; 120 121 } // namespace snapshot 122 } // namespace android 123