• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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