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