1 // 2 // Copyright (C) 2015 Google, Inc. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at: 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include "service/common/bluetooth/binder/IBluetoothLowEnergy.h" 18 19 #include <base/logging.h> 20 #include <binder/Parcel.h> 21 22 #include "service/common/bluetooth/binder/parcel_helpers.h" 23 24 using android::IBinder; 25 using android::interface_cast; 26 using android::Parcel; 27 using android::sp; 28 using android::status_t; 29 30 using bluetooth::AdvertiseData; 31 using bluetooth::AdvertiseSettings; 32 33 namespace ipc { 34 namespace binder { 35 36 // static 37 const char IBluetoothLowEnergy::kServiceName[] = 38 "bluetooth-low-energy-service"; 39 40 // BnBluetoothLowEnergy (server) implementation 41 // ======================================================== 42 43 status_t BnBluetoothLowEnergy::onTransact( 44 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { 45 VLOG(2) << "IBluetoothLowEnergy: " << code; 46 if (!data.checkInterface(this)) 47 return android::PERMISSION_DENIED; 48 49 switch (code) { 50 case REGISTER_CLIENT_TRANSACTION: { 51 sp<IBinder> callback = data.readStrongBinder(); 52 bool result = RegisterClient( 53 interface_cast<IBluetoothLowEnergyCallback>(callback)); 54 55 reply->writeInt32(result); 56 57 return android::NO_ERROR; 58 } 59 case UNREGISTER_CLIENT_TRANSACTION: { 60 int client_id = data.readInt32(); 61 UnregisterClient(client_id); 62 return android::NO_ERROR; 63 } 64 case UNREGISTER_ALL_TRANSACTION: { 65 UnregisterAll(); 66 return android::NO_ERROR; 67 } 68 case CONNECT_TRANSACTION: { 69 int client_id = data.readInt32(); 70 const char* address = data.readCString(); 71 bool is_direct = data.readBool(); 72 73 bool result = Connect(client_id, address, is_direct); 74 reply->writeInt32(result); 75 76 return android::NO_ERROR; 77 } 78 case DISCONNECT_TRANSACTION: { 79 int client_id = data.readInt32(); 80 const char* address = data.readCString(); 81 82 bool result = Disconnect(client_id, address); 83 reply->writeInt32(result); 84 85 return android::NO_ERROR; 86 } 87 case SET_MTU_TRANSACTION: { 88 int client_id = data.readInt32(); 89 const char* address = data.readCString(); 90 int mtu = data.readInt32(); 91 92 bool result = SetMtu(client_id, address, mtu); 93 reply->writeInt32(result); 94 95 return android::NO_ERROR; 96 } 97 case START_SCAN_TRANSACTION: { 98 int client_id = data.readInt32(); 99 auto settings = CreateScanSettingsFromParcel(data); 100 CHECK(settings); 101 std::vector<bluetooth::ScanFilter> filters; 102 103 int list_meta_data = data.readInt32(); 104 CHECK(list_meta_data == kParcelValList); 105 106 int filter_count = data.readInt32(); 107 if (filter_count >= 0) { // Make sure |filter_count| isn't negative. 108 for (int i = 0; i < filter_count; i++) { 109 auto filter = CreateScanFilterFromParcel(data); 110 CHECK(filter); 111 filters.push_back(*filter); 112 } 113 } 114 115 bool result = StartScan(client_id, *settings, filters); 116 reply->writeInt32(result); 117 118 return android::NO_ERROR; 119 } 120 case STOP_SCAN_TRANSACTION: { 121 int client_id = data.readInt32(); 122 bool result = StopScan(client_id); 123 reply->writeInt32(result); 124 return android::NO_ERROR; 125 } 126 case START_MULTI_ADVERTISING_TRANSACTION: { 127 int client_id = data.readInt32(); 128 std::unique_ptr<AdvertiseData> adv_data = 129 CreateAdvertiseDataFromParcel(data); 130 std::unique_ptr<AdvertiseData> scan_rsp = 131 CreateAdvertiseDataFromParcel(data); 132 std::unique_ptr<AdvertiseSettings> adv_settings = 133 CreateAdvertiseSettingsFromParcel(data); 134 135 bool result = StartMultiAdvertising( 136 client_id, *adv_data, *scan_rsp, *adv_settings); 137 138 reply->writeInt32(result); 139 140 return android::NO_ERROR; 141 } 142 case STOP_MULTI_ADVERTISING_TRANSACTION: { 143 int client_id = data.readInt32(); 144 bool result = StopMultiAdvertising(client_id); 145 146 reply->writeInt32(result); 147 148 return android::NO_ERROR; 149 } 150 default: 151 return BBinder::onTransact(code, data, reply, flags); 152 } 153 } 154 155 // BpBluetoothLowEnergy (client) implementation 156 // ======================================================== 157 158 BpBluetoothLowEnergy::BpBluetoothLowEnergy(const sp<IBinder>& impl) 159 : BpInterface<IBluetoothLowEnergy>(impl) { 160 } 161 162 bool BpBluetoothLowEnergy::RegisterClient( 163 const sp<IBluetoothLowEnergyCallback>& callback) { 164 Parcel data, reply; 165 166 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); 167 data.writeStrongBinder(IInterface::asBinder(callback.get())); 168 169 remote()->transact(IBluetoothLowEnergy::REGISTER_CLIENT_TRANSACTION, 170 data, &reply); 171 172 return reply.readInt32(); 173 } 174 175 void BpBluetoothLowEnergy::UnregisterClient(int client_id) { 176 Parcel data, reply; 177 178 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); 179 data.writeInt32(client_id); 180 181 remote()->transact(IBluetoothLowEnergy::UNREGISTER_CLIENT_TRANSACTION, 182 data, &reply); 183 } 184 185 void BpBluetoothLowEnergy::UnregisterAll() { 186 Parcel data, reply; 187 188 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); 189 190 remote()->transact(IBluetoothLowEnergy::UNREGISTER_ALL_TRANSACTION, 191 data, &reply); 192 } 193 194 bool BpBluetoothLowEnergy::Connect(int client_id, const char* address, 195 bool is_direct) { 196 Parcel data, reply; 197 198 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); 199 data.writeInt32(client_id); 200 data.writeCString(address); 201 data.writeBool(is_direct); 202 203 remote()->transact(IBluetoothLowEnergy::CONNECT_TRANSACTION, 204 data, &reply); 205 206 return reply.readInt32(); 207 } 208 209 bool BpBluetoothLowEnergy::Disconnect(int client_id, const char* address) { 210 Parcel data, reply; 211 212 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); 213 data.writeInt32(client_id); 214 data.writeCString(address); 215 216 remote()->transact(IBluetoothLowEnergy::DISCONNECT_TRANSACTION, 217 data, &reply); 218 219 return reply.readInt32(); 220 } 221 222 bool BpBluetoothLowEnergy::SetMtu(int client_id, const char* address, int mtu) { 223 Parcel data, reply; 224 225 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); 226 data.writeInt32(client_id); 227 data.writeCString(address); 228 data.writeInt32(mtu); 229 230 remote()->transact(IBluetoothLowEnergy::SET_MTU_TRANSACTION, data, &reply); 231 return reply.readInt32(); 232 } 233 234 bool BpBluetoothLowEnergy::StartScan( 235 int client_id, 236 const bluetooth::ScanSettings& settings, 237 const std::vector<bluetooth::ScanFilter>& filters) { 238 Parcel data, reply; 239 240 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); 241 data.writeInt32(client_id); 242 WriteScanSettingsToParcel(settings, &data); 243 244 // The Java equivalent of |filters| is a List<ScanFilter>. Parcel.java inserts 245 // a metadata value of VAL_LIST (11) for this so I'm doing it here for 246 // compatibility. 247 data.writeInt32(kParcelValList); 248 data.writeInt32(filters.size()); 249 for (const auto& filter : filters) 250 WriteScanFilterToParcel(filter, &data); 251 252 remote()->transact(IBluetoothLowEnergy::START_SCAN_TRANSACTION, 253 data, &reply); 254 255 return reply.readInt32(); 256 } 257 258 bool BpBluetoothLowEnergy::StopScan(int client_id) { 259 Parcel data, reply; 260 261 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); 262 data.writeInt32(client_id); 263 264 remote()->transact(IBluetoothLowEnergy::STOP_SCAN_TRANSACTION, 265 data, &reply); 266 267 return reply.readInt32(); 268 } 269 270 bool BpBluetoothLowEnergy::StartMultiAdvertising( 271 int client_id, 272 const AdvertiseData& advertise_data, 273 const AdvertiseData& scan_response, 274 const AdvertiseSettings& settings) { 275 Parcel data, reply; 276 277 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); 278 data.writeInt32(client_id); 279 WriteAdvertiseDataToParcel(advertise_data, &data); 280 WriteAdvertiseDataToParcel(scan_response, &data); 281 WriteAdvertiseSettingsToParcel(settings, &data); 282 283 remote()->transact(IBluetoothLowEnergy::START_MULTI_ADVERTISING_TRANSACTION, 284 data, &reply); 285 286 return reply.readInt32(); 287 } 288 289 bool BpBluetoothLowEnergy::StopMultiAdvertising(int client_id) { 290 Parcel data, reply; 291 292 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); 293 data.writeInt32(client_id); 294 295 remote()->transact(IBluetoothLowEnergy::STOP_MULTI_ADVERTISING_TRANSACTION, 296 data, &reply); 297 298 return reply.readInt32(); 299 } 300 301 IMPLEMENT_META_INTERFACE(BluetoothLowEnergy, IBluetoothLowEnergy::kServiceName); 302 303 } // namespace binder 304 } // namespace ipc 305