// // Copyright (C) 2015 Google, Inc. // // 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. // #include "service/common/bluetooth/binder/IBluetoothLowEnergy.h" #include <base/logging.h> #include <binder/Parcel.h> #include "service/common/bluetooth/binder/parcel_helpers.h" using android::IBinder; using android::interface_cast; using android::Parcel; using android::sp; using android::status_t; using bluetooth::AdvertiseData; using bluetooth::AdvertiseSettings; namespace ipc { namespace binder { // static const char IBluetoothLowEnergy::kServiceName[] = "bluetooth-low-energy-service"; // BnBluetoothLowEnergy (server) implementation // ======================================================== status_t BnBluetoothLowEnergy::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { VLOG(2) << "IBluetoothLowEnergy: " << code; if (!data.checkInterface(this)) return android::PERMISSION_DENIED; switch (code) { case REGISTER_CLIENT_TRANSACTION: { sp<IBinder> callback = data.readStrongBinder(); bool result = RegisterClient( interface_cast<IBluetoothLowEnergyCallback>(callback)); reply->writeInt32(result); return android::NO_ERROR; } case UNREGISTER_CLIENT_TRANSACTION: { int client_id = data.readInt32(); UnregisterClient(client_id); return android::NO_ERROR; } case UNREGISTER_ALL_TRANSACTION: { UnregisterAll(); return android::NO_ERROR; } case CONNECT_TRANSACTION: { int client_id = data.readInt32(); const char* address = data.readCString(); bool is_direct = data.readBool(); bool result = Connect(client_id, address, is_direct); reply->writeInt32(result); return android::NO_ERROR; } case DISCONNECT_TRANSACTION: { int client_id = data.readInt32(); const char* address = data.readCString(); bool result = Disconnect(client_id, address); reply->writeInt32(result); return android::NO_ERROR; } case SET_MTU_TRANSACTION: { int client_id = data.readInt32(); const char* address = data.readCString(); int mtu = data.readInt32(); bool result = SetMtu(client_id, address, mtu); reply->writeInt32(result); return android::NO_ERROR; } case START_SCAN_TRANSACTION: { int client_id = data.readInt32(); auto settings = CreateScanSettingsFromParcel(data); CHECK(settings); std::vector<bluetooth::ScanFilter> filters; int list_meta_data = data.readInt32(); CHECK(list_meta_data == kParcelValList); int filter_count = data.readInt32(); if (filter_count >= 0) { // Make sure |filter_count| isn't negative. for (int i = 0; i < filter_count; i++) { auto filter = CreateScanFilterFromParcel(data); CHECK(filter); filters.push_back(*filter); } } bool result = StartScan(client_id, *settings, filters); reply->writeInt32(result); return android::NO_ERROR; } case STOP_SCAN_TRANSACTION: { int client_id = data.readInt32(); bool result = StopScan(client_id); reply->writeInt32(result); return android::NO_ERROR; } case START_MULTI_ADVERTISING_TRANSACTION: { int client_id = data.readInt32(); std::unique_ptr<AdvertiseData> adv_data = CreateAdvertiseDataFromParcel(data); std::unique_ptr<AdvertiseData> scan_rsp = CreateAdvertiseDataFromParcel(data); std::unique_ptr<AdvertiseSettings> adv_settings = CreateAdvertiseSettingsFromParcel(data); bool result = StartMultiAdvertising( client_id, *adv_data, *scan_rsp, *adv_settings); reply->writeInt32(result); return android::NO_ERROR; } case STOP_MULTI_ADVERTISING_TRANSACTION: { int client_id = data.readInt32(); bool result = StopMultiAdvertising(client_id); reply->writeInt32(result); return android::NO_ERROR; } default: return BBinder::onTransact(code, data, reply, flags); } } // BpBluetoothLowEnergy (client) implementation // ======================================================== BpBluetoothLowEnergy::BpBluetoothLowEnergy(const sp<IBinder>& impl) : BpInterface<IBluetoothLowEnergy>(impl) { } bool BpBluetoothLowEnergy::RegisterClient( const sp<IBluetoothLowEnergyCallback>& callback) { Parcel data, reply; data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); data.writeStrongBinder(IInterface::asBinder(callback.get())); remote()->transact(IBluetoothLowEnergy::REGISTER_CLIENT_TRANSACTION, data, &reply); return reply.readInt32(); } void BpBluetoothLowEnergy::UnregisterClient(int client_id) { Parcel data, reply; data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); data.writeInt32(client_id); remote()->transact(IBluetoothLowEnergy::UNREGISTER_CLIENT_TRANSACTION, data, &reply); } void BpBluetoothLowEnergy::UnregisterAll() { Parcel data, reply; data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); remote()->transact(IBluetoothLowEnergy::UNREGISTER_ALL_TRANSACTION, data, &reply); } bool BpBluetoothLowEnergy::Connect(int client_id, const char* address, bool is_direct) { Parcel data, reply; data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); data.writeInt32(client_id); data.writeCString(address); data.writeBool(is_direct); remote()->transact(IBluetoothLowEnergy::CONNECT_TRANSACTION, data, &reply); return reply.readInt32(); } bool BpBluetoothLowEnergy::Disconnect(int client_id, const char* address) { Parcel data, reply; data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); data.writeInt32(client_id); data.writeCString(address); remote()->transact(IBluetoothLowEnergy::DISCONNECT_TRANSACTION, data, &reply); return reply.readInt32(); } bool BpBluetoothLowEnergy::SetMtu(int client_id, const char* address, int mtu) { Parcel data, reply; data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); data.writeInt32(client_id); data.writeCString(address); data.writeInt32(mtu); remote()->transact(IBluetoothLowEnergy::SET_MTU_TRANSACTION, data, &reply); return reply.readInt32(); } bool BpBluetoothLowEnergy::StartScan( int client_id, const bluetooth::ScanSettings& settings, const std::vector<bluetooth::ScanFilter>& filters) { Parcel data, reply; data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); data.writeInt32(client_id); WriteScanSettingsToParcel(settings, &data); // The Java equivalent of |filters| is a List<ScanFilter>. Parcel.java inserts // a metadata value of VAL_LIST (11) for this so I'm doing it here for // compatibility. data.writeInt32(kParcelValList); data.writeInt32(filters.size()); for (const auto& filter : filters) WriteScanFilterToParcel(filter, &data); remote()->transact(IBluetoothLowEnergy::START_SCAN_TRANSACTION, data, &reply); return reply.readInt32(); } bool BpBluetoothLowEnergy::StopScan(int client_id) { Parcel data, reply; data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); data.writeInt32(client_id); remote()->transact(IBluetoothLowEnergy::STOP_SCAN_TRANSACTION, data, &reply); return reply.readInt32(); } bool BpBluetoothLowEnergy::StartMultiAdvertising( int client_id, const AdvertiseData& advertise_data, const AdvertiseData& scan_response, const AdvertiseSettings& settings) { Parcel data, reply; data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); data.writeInt32(client_id); WriteAdvertiseDataToParcel(advertise_data, &data); WriteAdvertiseDataToParcel(scan_response, &data); WriteAdvertiseSettingsToParcel(settings, &data); remote()->transact(IBluetoothLowEnergy::START_MULTI_ADVERTISING_TRANSACTION, data, &reply); return reply.readInt32(); } bool BpBluetoothLowEnergy::StopMultiAdvertising(int client_id) { Parcel data, reply; data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); data.writeInt32(client_id); remote()->transact(IBluetoothLowEnergy::STOP_MULTI_ADVERTISING_TRANSACTION, data, &reply); return reply.readInt32(); } IMPLEMENT_META_INTERFACE(BluetoothLowEnergy, IBluetoothLowEnergy::kServiceName); } // namespace binder } // namespace ipc