1 // Copyright (C) 2023 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 #if __ANDROID__
16 
17 #include <ditto/binder.h>
18 
19 #include <ditto/logger.h>
20 
21 namespace dittosuite {
22 
23 // Client
BpDittoBinder(const sp<IBinder> & impl)24 BpDittoBinder::BpDittoBinder(const sp<IBinder>& impl) : BpInterface<IDittoBinder>(impl) {
25   LOGD("BpDittoBinder::BpDittoBinder()");
26 }
27 
async()28 void BpDittoBinder::async() {
29   Parcel data, reply;
30   data.writeInterfaceToken(IDittoBinder::getInterfaceDescriptor());
31   data.writeString16(String16(""));
32   remote()->transact(ASYNC, data, &reply, IBinder::FLAG_ONEWAY);  // asynchronous call
33   LOGD("BpDittoBinder::async()");
34 }
35 
sync(int8_t c)36 int8_t BpDittoBinder::sync(int8_t c) {
37   Parcel data, reply;
38   data.writeInterfaceToken(IDittoBinder::getInterfaceDescriptor());
39   data.writeByte(c);
40   LOGD("BpDittoBinder::sync parcel to be sent:");
41   remote()->transact(SYNC, data, &reply);
42   LOGD("BpDittoBinder::sync transact reply");
43 
44   int8_t res;
45   reply.readByte(&res);
46   LOGD("BpDittoBinder::sync()");
47   return res;
48 }
49 
start()50 void BpDittoBinder::start() {
51   Parcel data, reply;
52   data.writeInterfaceToken(IDittoBinder::getInterfaceDescriptor());
53   data.writeString16(String16(""));
54   remote()->transact(START, data, &reply, IBinder::FLAG_ONEWAY);  // asynchronous call
55   LOGD("BpDittoBinder::start()");
56 }
57 
end()58 void BpDittoBinder::end() {
59   Parcel data, reply;
60   data.writeInterfaceToken(IDittoBinder::getInterfaceDescriptor());
61   data.writeString16(String16(""));
62   remote()->transact(END, data, &reply, IBinder::FLAG_ONEWAY);  // asynchronous call
63   LOGD("BpDittoBinder::end()");
64 }
65 
66 // IMPLEMENT_META_INTERFACE(DittoBinder, "DittoBinder");
67 //  Macro above expands to code below. Doing it by hand so we can log ctor and destructor calls.
68 const String16 IDittoBinder::descriptor("DittoBinder");
getInterfaceDescriptor() const69 const String16& IDittoBinder::getInterfaceDescriptor() const {
70   return IDittoBinder::descriptor;
71 }
72 
asInterface(const sp<IBinder> & obj)73 sp<IDittoBinder> IDittoBinder::asInterface(const sp<IBinder>& obj) {
74   sp<IDittoBinder> intr;
75   if (obj != nullptr) {
76     intr = static_cast<IDittoBinder*>(obj->queryLocalInterface(IDittoBinder::descriptor).get());
77     if (intr == nullptr) {
78       intr = new BpDittoBinder(obj);
79     }
80   }
81   return intr;
82 }
IDittoBinder()83 IDittoBinder::IDittoBinder() {
84   LOGD("IDittoBinder::IDittoBinder()");
85 }
~IDittoBinder()86 IDittoBinder::~IDittoBinder() {
87   LOGD("IDittoBinder::~IDittoBinder()");
88 }
89 
90 // Server
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)91 status_t BnDittoBinder::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
92   LOGD("BnDittoBinder::onTransact(), code: " + std::to_string(code));
93   data.checkInterface(this);
94 
95   switch (code) {
96     case START: {
97       start();
98       LOGD("BnDittoBinder::onTransact START, refcount: " + std::to_string(client_cnt_));
99       return NO_ERROR;
100     } break;
101     case END: {
102       end();
103       LOGD("BnDittoBinder::onTransact END, refcount: " + std::to_string(client_cnt_));
104       if (client_cnt_ <= 0) {
105         LOGD("BnDittoBinder::onTransact END, unblocking thread pool");
106         pthread_cond_signal(thread_condition_);
107       }
108       return NO_ERROR;
109     } break;
110     case ASYNC: {
111       async();
112       return NO_ERROR;
113     } break;
114     case SYNC: {
115       LOGD("BnDittoBinder::onTransact SYNC");
116       int8_t c = data.readByte();
117       int8_t res = sync(c);
118       if (!reply) {
119         LOGF("No reply");
120       }
121       reply->writeByte(res);
122       return NO_ERROR;
123     } break;
124     default:
125       LOGD("BnDittoBinder::onTransact OTHER");
126       return BBinder::onTransact(code, data, reply, flags);
127   }
128 }
129 
start()130 void DittoBinder::start() {
131   LOGD("DittoBinder::start()");
132   client_cnt_++;
133 }
end()134 void DittoBinder::end() {
135   LOGD("DittoBinder::end()");
136   client_cnt_--;
137 }
138 
async()139 void DittoBinder::async() {
140   LOGD("DittoBinder::async()");
141 }
142 
sync(int8_t c)143 int8_t DittoBinder::sync(int8_t c) {
144   LOGD("DittoBinder::sync()");
145   return ~c;
146 }
147 
148 }  // namespace dittosuite
149 
150 #endif
151