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