Home | History | Annotate | Download | only in binder
      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/ipc/binder/bluetooth_low_energy_binder_server.h"
     18 
     19 #include <base/logging.h>
     20 
     21 #include "service/adapter.h"
     22 
     23 namespace ipc {
     24 namespace binder {
     25 
     26 namespace {
     27 const int kInvalidInstanceId = -1;
     28 }  // namespace
     29 
     30 BluetoothLowEnergyBinderServer::BluetoothLowEnergyBinderServer(
     31     bluetooth::Adapter* adapter) : adapter_(adapter) {
     32   CHECK(adapter_);
     33 }
     34 
     35 BluetoothLowEnergyBinderServer::~BluetoothLowEnergyBinderServer() {
     36 }
     37 
     38 bool BluetoothLowEnergyBinderServer::RegisterClient(
     39     const android::sp<IBluetoothLowEnergyCallback>& callback) {
     40   VLOG(2) << __func__;
     41   bluetooth::LowEnergyClientFactory* ble_factory =
     42       adapter_->GetLowEnergyClientFactory();
     43 
     44   return RegisterInstanceBase(callback, ble_factory);
     45 }
     46 
     47 void BluetoothLowEnergyBinderServer::UnregisterClient(int client_id) {
     48   VLOG(2) << __func__;
     49   UnregisterInstanceBase(client_id);
     50 }
     51 
     52 void BluetoothLowEnergyBinderServer::UnregisterAll() {
     53   VLOG(2) << __func__;
     54   UnregisterAllBase();
     55 }
     56 
     57 bool BluetoothLowEnergyBinderServer::Connect(int client_id,
     58                                              const char* address,
     59                                              bool is_direct) {
     60   VLOG(2) << __func__ << " client_id: " << client_id
     61           << " address: " << address
     62           << " is_direct: " << is_direct;
     63   std::lock_guard<std::mutex> lock(*maps_lock());
     64 
     65   auto client = GetLEClient(client_id);
     66   if (!client) {
     67     LOG(ERROR) << "Unknown client_id: " << client_id;
     68     return false;
     69   }
     70 
     71   return client->Connect(std::string(address), is_direct);
     72 }
     73 
     74 bool BluetoothLowEnergyBinderServer::Disconnect(int client_id,
     75                                                 const char* address) {
     76   VLOG(2) << __func__ << " client_id: " << client_id
     77           << " address: " << address;
     78   std::lock_guard<std::mutex> lock(*maps_lock());
     79 
     80   auto client = GetLEClient(client_id);
     81   if (!client) {
     82     LOG(ERROR) << "Unknown client_id: " << client_id;
     83     return false;
     84   }
     85 
     86   return client->Disconnect(std::string(address));
     87 }
     88 
     89 bool BluetoothLowEnergyBinderServer::SetMtu(int client_id,
     90                                             const char* address,
     91                                             int mtu) {
     92   VLOG(2) << __func__ << " client_id: " << client_id
     93           << " address: " << address
     94           << " mtu: " << mtu;
     95   std::lock_guard<std::mutex> lock(*maps_lock());
     96 
     97   auto client = GetLEClient(client_id);
     98   if (!client) {
     99     LOG(ERROR) << "Unknown client_id: " << client_id;
    100     return false;
    101   }
    102 
    103   return client->SetMtu(address, mtu);
    104 }
    105 
    106 bool BluetoothLowEnergyBinderServer::StartScan(
    107     int client_id,
    108     const bluetooth::ScanSettings& settings,
    109     const std::vector<bluetooth::ScanFilter>& filters) {
    110   VLOG(2) << __func__ << " client_id: " << client_id;
    111   std::lock_guard<std::mutex> lock(*maps_lock());
    112 
    113   auto client = GetLEClient(client_id);
    114   if (!client) {
    115     LOG(ERROR) << "Unknown client_id: " << client_id;
    116     return false;
    117   }
    118 
    119   return client->StartScan(settings, filters);
    120 }
    121 
    122 bool BluetoothLowEnergyBinderServer::StopScan(int client_id) {
    123   VLOG(2) << __func__ << " client_id: " << client_id;
    124   std::lock_guard<std::mutex> lock(*maps_lock());
    125 
    126   auto client = GetLEClient(client_id);
    127   if (!client) {
    128     LOG(ERROR) << "Unknown client_id: " << client_id;
    129     return false;
    130   }
    131 
    132   return client->StopScan();
    133 }
    134 
    135 bool BluetoothLowEnergyBinderServer::StartMultiAdvertising(
    136     int client_id,
    137     const bluetooth::AdvertiseData& advertise_data,
    138     const bluetooth::AdvertiseData& scan_response,
    139     const bluetooth::AdvertiseSettings& settings) {
    140   VLOG(2) << __func__ << " client_id: " << client_id;
    141   std::lock_guard<std::mutex> lock(*maps_lock());
    142 
    143   auto client = GetLEClient(client_id);
    144   if (!client) {
    145     LOG(ERROR) << "Unknown client_id: " << client_id;
    146     return false;
    147   }
    148 
    149   // Create a weak pointer and pass that to the callback to prevent a potential
    150   // use after free.
    151   android::wp<BluetoothLowEnergyBinderServer> weak_ptr_to_this(this);
    152   auto settings_copy = settings;
    153   auto callback = [=](bluetooth::BLEStatus status) {
    154     auto sp_to_this = weak_ptr_to_this.promote();
    155     if (!sp_to_this.get()) {
    156       VLOG(2) << "BluetoothLowEnergyBinderServer was deleted";
    157       return;
    158     }
    159 
    160     std::lock_guard<std::mutex> lock(*maps_lock());
    161 
    162     auto cb = GetLECallback(client_id);
    163     if (!cb.get()) {
    164       VLOG(1) << "Client was removed before callback: " << client_id;
    165       return;
    166     }
    167 
    168     cb->OnMultiAdvertiseCallback(status, true /* is_start */, settings_copy);
    169   };
    170 
    171   if (!client->StartAdvertising(
    172       settings, advertise_data, scan_response, callback)) {
    173     LOG(ERROR) << "Failed to initiate call to start advertising";
    174     return false;
    175   }
    176 
    177   return true;
    178 }
    179 
    180 bool BluetoothLowEnergyBinderServer::StopMultiAdvertising(int client_id) {
    181   VLOG(2) << __func__;
    182   std::lock_guard<std::mutex> lock(*maps_lock());
    183 
    184   auto client = GetLEClient(client_id);
    185   if (!client) {
    186     LOG(ERROR) << "Unknown client_id: " << client_id;
    187     return false;
    188   }
    189 
    190   // Create a weak pointer and pass that to the callback to prevent a potential
    191   // use after free.
    192   android::wp<BluetoothLowEnergyBinderServer> weak_ptr_to_this(this);
    193   auto settings_copy = client->advertise_settings();
    194   auto callback = [=](bluetooth::BLEStatus status) {
    195     auto sp_to_this = weak_ptr_to_this.promote();
    196     if (!sp_to_this.get()) {
    197       VLOG(2) << "BluetoothLowEnergyBinderServer was deleted";
    198       return;
    199     }
    200 
    201     auto cb = GetLECallback(client_id);
    202     if (!cb.get()) {
    203       VLOG(2) << "Client was unregistered - client_id: " << client_id;
    204       return;
    205     }
    206 
    207     std::lock_guard<std::mutex> lock(*maps_lock());
    208 
    209     cb->OnMultiAdvertiseCallback(status, false /* is_start */, settings_copy);
    210   };
    211 
    212   if (!client->StopAdvertising(callback)) {
    213     LOG(ERROR) << "Failed to initiate call to start advertising";
    214     return false;
    215   }
    216 
    217   return true;
    218 }
    219 
    220 void BluetoothLowEnergyBinderServer::OnConnectionState(
    221       bluetooth::LowEnergyClient* client, int status,
    222       const char* address, bool connected) {
    223   VLOG(2) << __func__ << " address: " << address << " connected: " << connected;
    224 
    225   int client_id = client->GetInstanceId();
    226   auto cb = GetLECallback(client->GetInstanceId());
    227   if (!cb.get()) {
    228     VLOG(2) << "Client was unregistered - client_id: " << client_id;
    229     return;
    230   }
    231 
    232   cb->OnConnectionState(status, client_id, address, connected);
    233 }
    234 
    235 void BluetoothLowEnergyBinderServer::OnMtuChanged(
    236       bluetooth::LowEnergyClient* client, int status, const char* address, int mtu) {
    237   VLOG(2) << __func__ << " address: " << address
    238           << " status: " << status
    239           << " mtu: " << mtu;
    240 
    241   int client_id = client->GetInstanceId();
    242   auto cb = GetLECallback(client_id);
    243   if (!cb.get()) {
    244     VLOG(2) << "Client was unregistered - client_id: " << client_id;
    245     return;
    246   }
    247 
    248   cb->OnMtuChanged(status, address, mtu);
    249 }
    250 
    251 void BluetoothLowEnergyBinderServer::OnScanResult(
    252     bluetooth::LowEnergyClient* client,
    253     const bluetooth::ScanResult& result) {
    254   VLOG(2) << __func__;
    255   std::lock_guard<std::mutex> lock(*maps_lock());
    256 
    257   int client_id = client->GetInstanceId();
    258   auto cb = GetLECallback(client->GetInstanceId());
    259   if (!cb.get()) {
    260     VLOG(2) << "Client was unregistered - client_id: " << client_id;
    261     return;
    262   }
    263 
    264   cb->OnScanResult(result);
    265 }
    266 
    267 android::sp<IBluetoothLowEnergyCallback>
    268 BluetoothLowEnergyBinderServer::GetLECallback(int client_id) {
    269   auto cb = GetCallback(client_id);
    270   return android::sp<IBluetoothLowEnergyCallback>(
    271       static_cast<IBluetoothLowEnergyCallback*>(cb.get()));
    272 }
    273 
    274 std::shared_ptr<bluetooth::LowEnergyClient>
    275 BluetoothLowEnergyBinderServer::GetLEClient(int client_id) {
    276   return std::static_pointer_cast<bluetooth::LowEnergyClient>(
    277       GetInstance(client_id));
    278 }
    279 
    280 void BluetoothLowEnergyBinderServer::OnRegisterInstanceImpl(
    281     bluetooth::BLEStatus status,
    282     android::sp<IInterface> callback,
    283     bluetooth::BluetoothInstance* instance) {
    284   VLOG(1) << __func__ << " status: " << status;
    285   bluetooth::LowEnergyClient* le_client =
    286       static_cast<bluetooth::LowEnergyClient*>(instance);
    287   le_client->SetDelegate(this);
    288 
    289   android::sp<IBluetoothLowEnergyCallback> cb(
    290       static_cast<IBluetoothLowEnergyCallback*>(callback.get()));
    291   cb->OnClientRegistered(
    292       status,
    293       (status == bluetooth::BLE_STATUS_SUCCESS) ?
    294           instance->GetInstanceId() : kInvalidInstanceId);
    295 }
    296 
    297 }  // namespace binder
    298 }  // namespace ipc
    299