1 // Copyright (C) 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <android/hardware/automotive/evs/1.1/IEvsEnumerator.h>
16 #include <android/hardware/automotive/evs/1.1/IEvsDisplay.h>
17 
18 #include <android-base/logging.h>
19 #include "EvsDisplayManager.h"
20 
21 #include "PixelFormatUtils.h"
22 #include "RenderDirectView.h"
23 
24 namespace android {
25 namespace automotive {
26 namespace computepipe {
27 namespace runner {
28 namespace debug_display_manager {
29 namespace {
30 
31 constexpr char kServiceName[] = "default";
32 
33 using android::hardware::automotive::evs::V1_1::IEvsEnumerator;
34 using android::hardware::automotive::evs::V1_1::IEvsDisplay;
35 using android::hardware::automotive::evs::V1_0::EvsResult;
36 using android::hardware::automotive::evs::V1_0::DisplayState;
37 using android::hardware::automotive::evs::V1_0::BufferDesc;
38 
39 using android::automotive::evs::support::RenderDirectView;
40 
getBufferDesc(const std::shared_ptr<MemHandle> & frame)41 BufferDesc getBufferDesc(const std::shared_ptr<MemHandle>& frame) {
42     AHardwareBuffer_Desc hwDesc;
43     AHardwareBuffer_describe(frame->getHardwareBuffer(), &hwDesc);
44 
45     BufferDesc buffer;
46     buffer.width = hwDesc.width;
47     buffer.height = hwDesc.height;
48     buffer.stride = hwDesc.stride;
49     buffer.pixelSize = numBytesPerPixel(static_cast<AHardwareBuffer_Format>(hwDesc.format));
50     buffer.format = hwDesc.format;
51     buffer.usage = hwDesc.usage;
52     buffer.memHandle = AHardwareBuffer_getNativeHandle(frame->getHardwareBuffer());
53     return buffer;
54 }
55 
56 }  // namespace
57 
~EvsDisplayManager()58 EvsDisplayManager::~EvsDisplayManager() {
59     stopThread();
60 }
61 
setArgs(std::string displayManagerArgs)62 Status EvsDisplayManager::setArgs(std::string displayManagerArgs) {
63     auto pos = displayManagerArgs.find(kDisplayId);
64     if (pos == std::string::npos) {
65         return Status::SUCCESS;
66     }
67     mDisplayId = std::stoi(displayManagerArgs.substr(pos + strlen(kDisplayId)));
68     mOverrideDisplayId = true;
69     return Status::SUCCESS;
70 }
71 
stopThread()72 void EvsDisplayManager::stopThread() {
73     {
74         std::lock_guard<std::mutex> lk(mLock);
75         mStopThread = true;
76         mWait.notify_one();
77     }
78     if (mThread.joinable()) {
79         mThread.join();
80     }
81 }
82 
threadFn()83 void EvsDisplayManager::threadFn() {
84     sp<IEvsEnumerator> evsEnumerator = IEvsEnumerator::getService(std::string() + kServiceName);
85 
86     if (!mOverrideDisplayId) {
87         evsEnumerator->getDisplayIdList([this] (auto ids) {
88                 this->mDisplayId = ids[ids.size() - 1];
89         });
90     }
91 
92     android::sp <IEvsDisplay> evsDisplay = evsEnumerator->openDisplay_1_1(mDisplayId);
93 
94     if (evsDisplay != nullptr) {
95         LOG(INFO) << "Computepipe runner opened debug display.";
96     } else {
97         mStopThread = true;
98         LOG(ERROR) << "EVS Display unavailable.  Exiting thread.";
99         return;
100     }
101 
102     RenderDirectView evsRenderer;
103     EvsResult result = evsDisplay->setDisplayState(DisplayState::VISIBLE_ON_NEXT_FRAME);
104     if (result != EvsResult::OK) {
105         mStopThread = true;
106         LOG(ERROR) <<  "Set display state returned error - " << static_cast<int>(result);
107         evsEnumerator->closeDisplay(evsDisplay);
108         return;
109     }
110 
111     if (!evsRenderer.activate()) {
112         mStopThread = true;
113         LOG(ERROR) <<  "Unable to activate evs renderer.";
114         evsEnumerator->closeDisplay(evsDisplay);
115         return;
116     }
117 
118     std::unique_lock<std::mutex> lk(mLock);
119     while (true) {
120         mWait.wait(lk, [this]() { return mNextFrame != nullptr || mStopThread; });
121 
122         if (mStopThread) {
123             // Free unused frame.
124             if (mFreePacketCallback && mNextFrame) {
125                 mFreePacketCallback(mNextFrame->getBufferId());
126             }
127             break;
128         }
129 
130         BufferDesc tgtBuffer = {};
131         evsDisplay->getTargetBuffer([&tgtBuffer](const BufferDesc& buff) {
132                 tgtBuffer = buff;
133                 }
134             );
135 
136         BufferDesc srcBuffer = getBufferDesc(mNextFrame);
137         if (!evsRenderer.drawFrame(tgtBuffer, srcBuffer)) {
138             LOG(ERROR) << "Error in rendering a frame.";
139             mStopThread = true;
140         }
141 
142         evsDisplay->returnTargetBufferForDisplay(tgtBuffer);
143         if (mFreePacketCallback) {
144             mFreePacketCallback(mNextFrame->getBufferId());
145         }
146         mNextFrame = nullptr;
147     }
148 
149     LOG(INFO) << "Computepipe runner closing debug display.";
150     evsRenderer.deactivate();
151     (void)evsDisplay->setDisplayState(DisplayState::NOT_VISIBLE);
152     evsEnumerator->closeDisplay(evsDisplay);
153 }
154 
setFreePacketCallback(std::function<Status (int bufferId)> freePacketCallback)155 void EvsDisplayManager::setFreePacketCallback(
156             std::function<Status(int bufferId)> freePacketCallback) {
157     std::lock_guard<std::mutex> lk(mLock);
158     mFreePacketCallback = freePacketCallback;
159 }
160 
displayFrame(const std::shared_ptr<MemHandle> & dataHandle)161 Status EvsDisplayManager::displayFrame(const std::shared_ptr<MemHandle>& dataHandle) {
162     std::lock_guard<std::mutex> lk(mLock);
163     Status status = Status::SUCCESS;
164     if (mStopThread) {
165         return Status::ILLEGAL_STATE;
166     }
167     if (mNextFrame != nullptr && mFreePacketCallback) {
168         status = mFreePacketCallback(mNextFrame->getBufferId());
169     }
170     mNextFrame = dataHandle;
171     mWait.notify_one();
172     return status;
173 }
174 
handleExecutionPhase(const RunnerEvent & e)175 Status EvsDisplayManager::handleExecutionPhase(const RunnerEvent& e) {
176     if (e.isPhaseEntry()) {
177         std::lock_guard<std::mutex> lk(mLock);
178         mStopThread = false;
179         mThread = std::thread(&EvsDisplayManager::threadFn, this);
180     } else if (e.isAborted()) {
181         stopThread();
182     }
183     return Status::SUCCESS;
184 }
185 
handleStopWithFlushPhase(const RunnerEvent &)186 Status EvsDisplayManager::handleStopWithFlushPhase(const RunnerEvent& /* e */) {
187     stopThread();
188     return Status::SUCCESS;
189 }
190 
handleStopImmediatePhase(const RunnerEvent &)191 Status EvsDisplayManager::handleStopImmediatePhase(const RunnerEvent& /* e */) {
192     stopThread();
193     return Status::SUCCESS;
194 }
195 
handleResetPhase(const RunnerEvent &)196 Status EvsDisplayManager::handleResetPhase(const RunnerEvent& /* e */) {
197     stopThread();
198     return Status::SUCCESS;
199 }
200 
201 }  // namespace debug_display_manager
202 }  // namespace runner
203 }  // namespace computepipe
204 }  // namespace automotive
205 }  // namespace android
206