1 // Copyright (C) 2016 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 #include "ChannelStream.h"
15
16 #include "render-utils/RenderChannel.h"
17
18 #define EMUGL_DEBUG_LEVEL 0
19 #include "host-common/debug.h"
20 #include "host-common/dma_device.h"
21 #include "host-common/GfxstreamFatalError.h"
22
23 #include <assert.h>
24 #include <memory.h>
25
26 namespace gfxstream {
27
28 using IoResult = RenderChannel::IoResult;
29 using emugl::ABORT_REASON_OTHER;
30 using emugl::FatalError;
31
ChannelStream(RenderChannelImpl * channel,size_t bufSize)32 ChannelStream::ChannelStream(RenderChannelImpl* channel, size_t bufSize)
33 : IOStream(bufSize), mChannel(channel) {
34 mWriteBuffer.resize_noinit(bufSize);
35 }
36
allocBuffer(size_t minSize)37 void* ChannelStream::allocBuffer(size_t minSize) {
38 if (mWriteBuffer.size() < minSize) {
39 mWriteBuffer.resize_noinit(minSize);
40 }
41 return mWriteBuffer.data();
42 }
43
commitBuffer(size_t size)44 int ChannelStream::commitBuffer(size_t size) {
45 assert(size <= mWriteBuffer.size());
46 if (mWriteBuffer.isAllocated()) {
47 mWriteBuffer.resize(size);
48 mChannel->writeToGuest(std::move(mWriteBuffer));
49 } else {
50 mChannel->writeToGuest(
51 RenderChannel::Buffer(mWriteBuffer.data(), mWriteBuffer.data() + size));
52 }
53 return size;
54 }
55
readRaw(void * buf,size_t * inout_len)56 const unsigned char* ChannelStream::readRaw(void* buf, size_t* inout_len) {
57 size_t wanted = *inout_len;
58 size_t count = 0U;
59 auto dst = static_cast<uint8_t*>(buf);
60 D("wanted %d bytes", (int)wanted);
61 while (count < wanted) {
62 if (mReadBufferLeft > 0) {
63 size_t avail = std::min<size_t>(wanted - count, mReadBufferLeft);
64 memcpy(dst + count,
65 mReadBuffer.data() + (mReadBuffer.size() - mReadBufferLeft),
66 avail);
67 count += avail;
68 mReadBufferLeft -= avail;
69 continue;
70 }
71 bool blocking = (count == 0);
72 auto result = mChannel->readFromGuest(&mReadBuffer, blocking);
73 D("readFromGuest() returned %d, size %d", (int)result, (int)mReadBuffer.size());
74 if (result == IoResult::Ok) {
75 mReadBufferLeft = mReadBuffer.size();
76 continue;
77 }
78 if (count > 0) { // There is some data to return.
79 break;
80 }
81 // Result can only be IoResult::Error if |count| == 0
82 // since |blocking| was true, it cannot be IoResult::TryAgain.
83 assert(result == IoResult::Error);
84 D("error while trying to read");
85 return nullptr;
86 }
87 *inout_len = count;
88 D("read %d bytes", (int)count);
89 return (const unsigned char*)buf;
90 }
91
getDmaForReading(uint64_t guest_paddr)92 void* ChannelStream::getDmaForReading(uint64_t guest_paddr) {
93 return emugl::g_emugl_dma_get_host_addr(guest_paddr);
94 }
95
unlockDma(uint64_t guest_paddr)96 void ChannelStream::unlockDma(uint64_t guest_paddr) { emugl::g_emugl_dma_unlock(guest_paddr); }
97
forceStop()98 void ChannelStream::forceStop() {
99 mChannel->stopFromHost();
100 }
101
writeFully(const void * buf,size_t len)102 int ChannelStream::writeFully(const void* buf, size_t len) {
103 void* dstBuf = alloc(len);
104 memcpy(dstBuf, buf, len);
105 flush();
106 return 0;
107 }
108
readFully(void * buf,size_t len)109 const unsigned char *ChannelStream::readFully( void *buf, size_t len) {
110 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
111 << "not intended for use with ChannelStream";
112 }
113
onSave(android::base::Stream * stream)114 void ChannelStream::onSave(android::base::Stream* stream) {
115 // Write only the data that's left in read buffer, but in the same format
116 // as saveBuffer() does.
117 stream->putBe32(mReadBufferLeft);
118 stream->write(mReadBuffer.data() + mReadBuffer.size() - mReadBufferLeft,
119 mReadBufferLeft);
120 android::base::saveBuffer(stream, mWriteBuffer);
121 }
122
onLoad(android::base::Stream * stream)123 unsigned char* ChannelStream::onLoad(android::base::Stream* stream) {
124 android::base::loadBuffer(stream, &mReadBuffer);
125 mReadBufferLeft = mReadBuffer.size();
126 android::base::loadBuffer(stream, &mWriteBuffer);
127 return reinterpret_cast<unsigned char*>(mWriteBuffer.data());
128 }
129
130 } // namespace gfxstream
131