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