| // |
| // 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/IBluetooth.h" |
| |
| #include <base/logging.h> |
| #include <binder/IServiceManager.h> |
| #include <binder/Parcel.h> |
| |
| using android::defaultServiceManager; |
| using android::IBinder; |
| using android::interface_cast; |
| using android::IServiceManager; |
| using android::Parcel; |
| using android::PERMISSION_DENIED; |
| using android::sp; |
| using android::status_t; |
| using android::String16; |
| |
| namespace ipc { |
| namespace binder { |
| |
| // static |
| const char IBluetooth::kServiceName[] = "bluetooth-service"; |
| |
| // static |
| sp<IBluetooth> IBluetooth::getClientInterface() { |
| sp<IServiceManager> sm = defaultServiceManager(); |
| if (!sm.get()) { |
| LOG(ERROR) << "Failed to obtain a handle to the default Service Manager"; |
| return nullptr; |
| } |
| |
| sp<IBinder> binder = sm->getService(String16(kServiceName)); |
| if (!binder.get()) { |
| LOG(ERROR) << "Failed to obtain a handle to the Bluetooth service"; |
| return nullptr; |
| } |
| |
| sp<IBluetooth> bt_iface = interface_cast<IBluetooth>(binder); |
| if (!bt_iface.get()) { |
| LOG(ERROR) << "Obtained invalid IBinder handle"; |
| return nullptr; |
| } |
| |
| return bt_iface; |
| } |
| |
| // BnBluetooth (server) implementation |
| // ======================================================== |
| |
| status_t BnBluetooth::onTransact( |
| uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { |
| VLOG(2) << "IBluetooth transaction: " << code; |
| |
| switch (code) { |
| case IS_ENABLED_TRANSACTION: { |
| CHECK_INTERFACE(IBluetooth, data, reply); |
| bool is_enabled = IsEnabled(); |
| reply->writeInt32(is_enabled); |
| return android::NO_ERROR; |
| } |
| case GET_STATE_TRANSACTION: { |
| CHECK_INTERFACE(IBluetooth, data, reply); |
| int state = GetState(); |
| reply->writeInt32(state); |
| return android::NO_ERROR; |
| } |
| case ENABLE_TRANSACTION: { |
| CHECK_INTERFACE(IBluetooth, data, reply); |
| bool start_restricted = data.readBool(); |
| bool result = Enable(start_restricted); |
| reply->writeInt32(result); |
| return android::NO_ERROR; |
| } |
| case DISABLE_TRANSACTION: { |
| CHECK_INTERFACE(IBluetooth, data, reply); |
| bool result = Disable(); |
| reply->writeInt32(result); |
| return android::NO_ERROR; |
| } |
| case GET_ADDRESS_TRANSACTION: { |
| CHECK_INTERFACE(IBluetooth, data, reply); |
| std::string address = GetAddress(); |
| reply->writeCString(address.c_str()); |
| return android::NO_ERROR; |
| } |
| case GET_UUIDS_TRANSACTION: |
| CHECK_INTERFACE(IBluetooth, data, reply); |
| // TODO(armansito): Figure out how to handle a Java "ParcelUuid" natively. |
| // (see http://b/23316698). |
| return android::INVALID_OPERATION; |
| |
| case SET_NAME_TRANSACTION: { |
| CHECK_INTERFACE(IBluetooth, data, reply); |
| std::string name(data.readCString()); |
| bool result = SetName(name); |
| reply->writeInt32(result); |
| return android::NO_ERROR; |
| } |
| case GET_NAME_TRANSACTION: { |
| CHECK_INTERFACE(IBluetooth, data, reply); |
| std::string name = GetName(); |
| reply->writeCString(name.c_str()); |
| return android::NO_ERROR; |
| } |
| case REGISTER_CALLBACK_TRANSACTION: { |
| CHECK_INTERFACE(IBluetooth, data, reply); |
| sp<IBinder> callback = data.readStrongBinder(); |
| RegisterCallback(interface_cast<IBluetoothCallback>(callback)); |
| return android::NO_ERROR; |
| } |
| case UNREGISTER_CALLBACK_TRANSACTION: { |
| CHECK_INTERFACE(IBluetooth, data, reply); |
| sp<IBinder> callback = data.readStrongBinder(); |
| UnregisterCallback(interface_cast<IBluetoothCallback>(callback)); |
| return android::NO_ERROR; |
| } |
| case IS_MULTI_ADVERTISEMENT_SUPPORTED_TRANSACTION: { |
| CHECK_INTERFACE(IBluetooth, data, reply); |
| bool result = IsMultiAdvertisementSupported(); |
| reply->writeInt32(result); |
| return android::NO_ERROR; |
| } |
| case GET_LOW_ENERGY_INTERFACE_TRANSACTION: { |
| CHECK_INTERFACE(IBluetooth, data, reply); |
| sp<IBluetoothLowEnergy> ble_iface = GetLowEnergyInterface(); |
| reply->writeStrongBinder(IInterface::asBinder(ble_iface.get())); |
| return android::NO_ERROR; |
| } |
| case GET_GATT_CLIENT_INTERFACE_TRANSACTION: { |
| CHECK_INTERFACE(IBluetooth, data, reply); |
| sp<IBluetoothGattClient> gatt_client_iface = GetGattClientInterface(); |
| reply->writeStrongBinder(IInterface::asBinder(gatt_client_iface.get())); |
| return android::NO_ERROR; |
| } |
| case GET_GATT_SERVER_INTERFACE_TRANSACTION: { |
| CHECK_INTERFACE(IBluetooth, data, reply); |
| sp<IBluetoothGattServer> gatt_server_iface = GetGattServerInterface(); |
| reply->writeStrongBinder(IInterface::asBinder(gatt_server_iface.get())); |
| return android::NO_ERROR; |
| } |
| default: |
| return BBinder::onTransact(code, data, reply, flags); |
| } |
| } |
| |
| // BpBluetooth (client) implementation |
| // ======================================================== |
| |
| BpBluetooth::BpBluetooth(const sp<IBinder>& impl) |
| : BpInterface<IBluetooth>(impl) { |
| } |
| |
| bool BpBluetooth::IsEnabled() { |
| Parcel data, reply; |
| |
| data.writeInterfaceToken(IBluetooth::getInterfaceDescriptor()); |
| remote()->transact(IBluetooth::IS_ENABLED_TRANSACTION, data, &reply); |
| |
| return reply.readInt32(); |
| } |
| |
| int BpBluetooth::GetState() { |
| Parcel data, reply; |
| |
| data.writeInterfaceToken(IBluetooth::getInterfaceDescriptor()); |
| remote()->transact(IBluetooth::GET_STATE_TRANSACTION, data, &reply); |
| |
| return reply.readInt32(); |
| } |
| |
| bool BpBluetooth::Enable(bool start_restricted) { |
| Parcel data, reply; |
| |
| data.writeInterfaceToken(IBluetooth::getInterfaceDescriptor()); |
| data.writeBool(start_restricted); |
| remote()->transact(IBluetooth::ENABLE_TRANSACTION, data, &reply); |
| |
| return reply.readInt32(); |
| } |
| |
| bool BpBluetooth::EnableNoAutoConnect() { |
| Parcel data, reply; |
| |
| data.writeInterfaceToken(IBluetooth::getInterfaceDescriptor()); |
| remote()->transact(IBluetooth::ENABLE_NO_AUTO_CONNECT_TRANSACTION, |
| data, &reply); |
| |
| return reply.readInt32(); |
| } |
| |
| bool BpBluetooth::Disable() { |
| Parcel data, reply; |
| |
| data.writeInterfaceToken(IBluetooth::getInterfaceDescriptor()); |
| remote()->transact(IBluetooth::DISABLE_TRANSACTION, data, &reply); |
| |
| return reply.readInt32(); |
| } |
| |
| std::string BpBluetooth::GetAddress() { |
| Parcel data, reply; |
| |
| data.writeInterfaceToken(IBluetooth::getInterfaceDescriptor()); |
| remote()->transact(IBluetooth::GET_ADDRESS_TRANSACTION, data, &reply); |
| |
| return reply.readCString(); |
| } |
| |
| std::vector<bluetooth::UUID> BpBluetooth::GetUUIDs() { |
| // TODO(armansito): need to deserialize a parceled java.util.ParcelUUID[] to |
| // std::vector<bluetooth::UUID> here (see http://b/23316698). |
| return std::vector<bluetooth::UUID>(); |
| } |
| |
| bool BpBluetooth::SetName(const std::string& name) { |
| Parcel data, reply; |
| |
| data.writeInterfaceToken(IBluetooth::getInterfaceDescriptor()); |
| data.writeCString(name.c_str()); |
| remote()->transact(IBluetooth::SET_NAME_TRANSACTION, data, &reply); |
| |
| return reply.readInt32(); |
| } |
| |
| std::string BpBluetooth::GetName() { |
| Parcel data, reply; |
| |
| data.writeInterfaceToken(IBluetooth::getInterfaceDescriptor()); |
| remote()->transact(IBluetooth::GET_NAME_TRANSACTION, data, &reply); |
| |
| return reply.readCString(); |
| } |
| |
| void BpBluetooth::RegisterCallback(const sp<IBluetoothCallback>& callback) { |
| Parcel data, reply; |
| |
| data.writeInterfaceToken(IBluetooth::getInterfaceDescriptor()); |
| data.writeStrongBinder(IInterface::asBinder(callback.get())); |
| |
| remote()->transact(IBluetooth::REGISTER_CALLBACK_TRANSACTION, data, &reply); |
| } |
| |
| void BpBluetooth::UnregisterCallback(const sp<IBluetoothCallback>& callback) { |
| Parcel data, reply; |
| |
| data.writeInterfaceToken(IBluetooth::getInterfaceDescriptor()); |
| data.writeStrongBinder(IInterface::asBinder(callback.get())); |
| |
| remote()->transact(IBluetooth::UNREGISTER_CALLBACK_TRANSACTION, data, &reply); |
| } |
| |
| bool BpBluetooth::IsMultiAdvertisementSupported() { |
| Parcel data, reply; |
| |
| data.writeInterfaceToken(IBluetooth::getInterfaceDescriptor()); |
| |
| remote()->transact(IBluetooth::IS_MULTI_ADVERTISEMENT_SUPPORTED_TRANSACTION, |
| data, &reply); |
| |
| return reply.readInt32(); |
| } |
| |
| sp<IBluetoothLowEnergy> BpBluetooth::GetLowEnergyInterface() { |
| Parcel data, reply; |
| |
| data.writeInterfaceToken(IBluetooth::getInterfaceDescriptor()); |
| |
| remote()->transact(IBluetooth::GET_LOW_ENERGY_INTERFACE_TRANSACTION, |
| data, &reply); |
| |
| return interface_cast<IBluetoothLowEnergy>(reply.readStrongBinder()); |
| } |
| |
| sp<IBluetoothGattClient> BpBluetooth::GetGattClientInterface() { |
| Parcel data, reply; |
| |
| data.writeInterfaceToken(IBluetooth::getInterfaceDescriptor()); |
| |
| remote()->transact(IBluetooth::GET_GATT_CLIENT_INTERFACE_TRANSACTION, |
| data, &reply); |
| |
| return interface_cast<IBluetoothGattClient>(reply.readStrongBinder()); |
| } |
| |
| sp<IBluetoothGattServer> BpBluetooth::GetGattServerInterface() { |
| Parcel data, reply; |
| |
| data.writeInterfaceToken(IBluetooth::getInterfaceDescriptor()); |
| |
| remote()->transact(IBluetooth::GET_GATT_SERVER_INTERFACE_TRANSACTION, |
| data, &reply); |
| |
| return interface_cast<IBluetoothGattServer>(reply.readStrongBinder()); |
| } |
| |
| IMPLEMENT_META_INTERFACE(Bluetooth, IBluetooth::kServiceName); |
| |
| } // namespace binder |
| } // namespace ipc |