// Copyright (C) 2023 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #if __ANDROID__ #include #include namespace dittosuite { // Client BpDittoBinder::BpDittoBinder(const sp& impl) : BpInterface(impl) { LOGD("BpDittoBinder::BpDittoBinder()"); } void BpDittoBinder::async() { Parcel data, reply; data.writeInterfaceToken(IDittoBinder::getInterfaceDescriptor()); data.writeString16(String16("")); remote()->transact(ASYNC, data, &reply, IBinder::FLAG_ONEWAY); // asynchronous call LOGD("BpDittoBinder::async()"); } int8_t BpDittoBinder::sync(int8_t c) { Parcel data, reply; data.writeInterfaceToken(IDittoBinder::getInterfaceDescriptor()); data.writeByte(c); LOGD("BpDittoBinder::sync parcel to be sent:"); remote()->transact(SYNC, data, &reply); LOGD("BpDittoBinder::sync transact reply"); int8_t res; reply.readByte(&res); LOGD("BpDittoBinder::sync()"); return res; } void BpDittoBinder::start() { Parcel data, reply; data.writeInterfaceToken(IDittoBinder::getInterfaceDescriptor()); data.writeString16(String16("")); remote()->transact(START, data, &reply, IBinder::FLAG_ONEWAY); // asynchronous call LOGD("BpDittoBinder::start()"); } void BpDittoBinder::end() { Parcel data, reply; data.writeInterfaceToken(IDittoBinder::getInterfaceDescriptor()); data.writeString16(String16("")); remote()->transact(END, data, &reply, IBinder::FLAG_ONEWAY); // asynchronous call LOGD("BpDittoBinder::end()"); } // IMPLEMENT_META_INTERFACE(DittoBinder, "DittoBinder"); // Macro above expands to code below. Doing it by hand so we can log ctor and destructor calls. const String16 IDittoBinder::descriptor("DittoBinder"); const String16& IDittoBinder::getInterfaceDescriptor() const { return IDittoBinder::descriptor; } sp IDittoBinder::asInterface(const sp& obj) { sp intr; if (obj != nullptr) { intr = static_cast(obj->queryLocalInterface(IDittoBinder::descriptor).get()); if (intr == nullptr) { intr = new BpDittoBinder(obj); } } return intr; } IDittoBinder::IDittoBinder() { LOGD("IDittoBinder::IDittoBinder()"); } IDittoBinder::~IDittoBinder() { LOGD("IDittoBinder::~IDittoBinder()"); } // Server status_t BnDittoBinder::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { LOGD("BnDittoBinder::onTransact(), code: " + std::to_string(code)); data.checkInterface(this); switch (code) { case START: { start(); LOGD("BnDittoBinder::onTransact START, refcount: " + std::to_string(client_cnt_)); return NO_ERROR; } break; case END: { end(); LOGD("BnDittoBinder::onTransact END, refcount: " + std::to_string(client_cnt_)); if (client_cnt_ <= 0) { LOGD("BnDittoBinder::onTransact END, unblocking thread pool"); pthread_cond_signal(thread_condition_); } return NO_ERROR; } break; case ASYNC: { async(); return NO_ERROR; } break; case SYNC: { LOGD("BnDittoBinder::onTransact SYNC"); int8_t c = data.readByte(); int8_t res = sync(c); if (!reply) { LOGF("No reply"); } reply->writeByte(res); return NO_ERROR; } break; default: LOGD("BnDittoBinder::onTransact OTHER"); return BBinder::onTransact(code, data, reply, flags); } } void DittoBinder::start() { LOGD("DittoBinder::start()"); client_cnt_++; } void DittoBinder::end() { LOGD("DittoBinder::end()"); client_cnt_--; } void DittoBinder::async() { LOGD("DittoBinder::async()"); } int8_t DittoBinder::sync(int8_t c) { LOGD("DittoBinder::sync()"); return ~c; } } // namespace dittosuite #endif