1 // Copyright 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 "RefcountPipe.h"
16
17 #include "aemu/base/ArraySize.h"
18 #include "refcount-pipe.h"
19
20 #include <string.h>
21
22 using android::base::arraySize;
23
24 namespace android {
25 namespace emulation {
26
27 static OnLastColorBufferRef* sOnLastColorBufferRef = new OnLastColorBufferRef;
28
RefcountPipe(void * hwPipe,Service * svc,base::Stream * loadStream)29 RefcountPipe::RefcountPipe(void* hwPipe, Service* svc, base::Stream* loadStream)
30 : AndroidPipe(hwPipe, svc) {
31 if (loadStream) {
32 mHandle = loadStream->getBe32();
33 } else {
34 mHandle = 0;
35 }
36 }
37
~RefcountPipe()38 RefcountPipe::~RefcountPipe() {
39 OnLastColorBufferRef func = *sOnLastColorBufferRef;
40 if (func != nullptr)
41 func(mHandle);
42 }
43
onGuestClose(PipeCloseReason reason)44 void RefcountPipe::onGuestClose(PipeCloseReason reason) {
45 delete this;
46 }
47
onGuestPoll() const48 unsigned RefcountPipe::onGuestPoll() const {
49 // Guest can always write
50 return PIPE_POLL_OUT;
51 }
52
onGuestRecv(AndroidPipeBuffer * buffers,int numBuffers)53 int RefcountPipe::onGuestRecv(AndroidPipeBuffer* buffers, int numBuffers) {
54 // Guest is not supposed to read
55 return PIPE_ERROR_IO;
56 }
57
onGuestSend(const AndroidPipeBuffer * buffers,int numBuffers,void ** newPipePtr)58 int RefcountPipe::onGuestSend(const AndroidPipeBuffer* buffers,
59 int numBuffers,
60 void** newPipePtr) {
61 int result = 0;
62 char forRecv[4] = {};
63
64 while (numBuffers > 0 && arraySize(forRecv) - result >= buffers->size) {
65 memcpy(forRecv + result, buffers->data, buffers->size);
66 result += static_cast<int>(buffers->size);
67 buffers++;
68 numBuffers--;
69 }
70
71 if (result == arraySize(forRecv)) {
72 memcpy(&mHandle, forRecv, arraySize(forRecv));
73 }
74
75 return result;
76 }
77
onSave(base::Stream * stream)78 void RefcountPipe::onSave(base::Stream* stream) {
79 stream->putBe32(mHandle);
80 }
81
registerRefcountPipeService()82 void registerRefcountPipeService() {
83 AndroidPipe::Service::add(std::make_unique<RefcountPipe::Service>());
84 }
85
86 ////////////////////////////////////////////////////////////////////////////////
87
Service()88 RefcountPipe::Service::Service() : AndroidPipe::Service("refcount") {}
89
create(void * hwPipe,const char * args,enum AndroidPipeFlags flags)90 AndroidPipe* RefcountPipe::Service::create(void* hwPipe, const char* args,
91 enum AndroidPipeFlags flags) {
92 return new RefcountPipe(hwPipe, this);
93 }
94
load(void * hwPipe,const char * args,android::base::Stream * stream)95 AndroidPipe* RefcountPipe::Service::load(void* hwPipe,
96 const char* args,
97 android::base::Stream* stream) {
98 return new RefcountPipe(hwPipe, this, stream);
99 }
100
canLoad() const101 bool RefcountPipe::Service::canLoad() const {
102 return true;
103 }
104
registerOnLastRefCallback(OnLastColorBufferRef func)105 void registerOnLastRefCallback(OnLastColorBufferRef func) {
106 *sOnLastColorBufferRef = func;
107 }
108
109 } // namespace emulation
110 } // namespace android
111
android_init_refcount_pipe(void)112 void android_init_refcount_pipe(void) {
113 android::emulation::registerRefcountPipeService();
114 }
115