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
23using android::String8;
24using android::String16;
25using android::binder::Status;
26
27namespace ipc {
28namespace binder {
29
30namespace {
31const int kInvalidInstanceId = -1;
32}  // namespace
33
34BluetoothLowEnergyBinderServer::BluetoothLowEnergyBinderServer(
35    bluetooth::Adapter* adapter)
36    : adapter_(adapter) {
37  CHECK(adapter_);
38}
39
40BluetoothLowEnergyBinderServer::~BluetoothLowEnergyBinderServer() {}
41
42Status BluetoothLowEnergyBinderServer::RegisterClient(
43    const android::sp<IBluetoothLowEnergyCallback>& callback,
44    bool* _aidl_return) {
45  VLOG(2) << __func__;
46  bluetooth::LowEnergyClientFactory* ble_factory =
47      adapter_->GetLowEnergyClientFactory();
48
49  *_aidl_return = RegisterInstanceBase(callback, ble_factory);
50  return Status::ok();
51}
52
53Status BluetoothLowEnergyBinderServer::UnregisterClient(int client_id) {
54  VLOG(2) << __func__;
55  UnregisterInstanceBase(client_id);
56  return Status::ok();
57}
58
59Status BluetoothLowEnergyBinderServer::UnregisterAll() {
60  VLOG(2) << __func__;
61  UnregisterAllBase();
62  return Status::ok();
63}
64
65Status BluetoothLowEnergyBinderServer::Connect(int client_id,
66                                               const String16& address,
67                                               bool is_direct,
68                                               bool* _aidl_return) {
69  VLOG(2) << __func__ << " client_id: " << client_id << " address: " << address
70          << " is_direct: " << is_direct;
71  std::lock_guard<std::mutex> lock(*maps_lock());
72
73  auto client = GetLEClient(client_id);
74  if (!client) {
75    LOG(ERROR) << "Unknown client_id: " << client_id;
76    *_aidl_return = false;
77    return Status::ok();
78  }
79
80  *_aidl_return =
81      client->Connect(std::string(String8(address).string()), is_direct);
82  return Status::ok();
83}
84
85Status BluetoothLowEnergyBinderServer::Disconnect(int client_id,
86                                                  const String16& address,
87                                                  bool* _aidl_return) {
88  VLOG(2) << __func__ << " client_id: " << client_id << " address: " << address;
89  std::lock_guard<std::mutex> lock(*maps_lock());
90
91  auto client = GetLEClient(client_id);
92  if (!client) {
93    LOG(ERROR) << "Unknown client_id: " << client_id;
94    *_aidl_return = false;
95    return Status::ok();
96  }
97
98  *_aidl_return = client->Disconnect(std::string(String8(address).string()));
99  return Status::ok();
100}
101
102Status BluetoothLowEnergyBinderServer::SetMtu(int client_id,
103                                              const String16& address, int mtu,
104                                              bool* _aidl_return) {
105  VLOG(2) << __func__ << " client_id: " << client_id << " address: " << address
106          << " mtu: " << mtu;
107  std::lock_guard<std::mutex> lock(*maps_lock());
108
109  auto client = GetLEClient(client_id);
110  if (!client) {
111    LOG(ERROR) << "Unknown client_id: " << client_id;
112    *_aidl_return = false;
113    return Status::ok();
114  }
115
116  *_aidl_return = client->SetMtu(std::string(String8(address).string()), mtu);
117  return Status::ok();
118}
119
120void BluetoothLowEnergyBinderServer::OnConnectionState(
121    bluetooth::LowEnergyClient* client, int status, const char* address,
122    bool connected) {
123  VLOG(2) << __func__ << " address: " << address << " connected: " << connected;
124
125  int client_id = client->GetInstanceId();
126  auto cb = GetLECallback(client->GetInstanceId());
127  if (!cb.get()) {
128    VLOG(2) << "Client was unregistered - client_id: " << client_id;
129    return;
130  }
131
132  cb->OnConnectionState(status, client_id,
133                        String16(address, std::strlen(address)), connected);
134}
135
136void BluetoothLowEnergyBinderServer::OnMtuChanged(
137    bluetooth::LowEnergyClient* client, int status, const char* address,
138    int mtu) {
139  VLOG(2) << __func__ << " address: " << address << " status: " << status
140          << " mtu: " << mtu;
141
142  int client_id = client->GetInstanceId();
143  auto cb = GetLECallback(client_id);
144  if (!cb.get()) {
145    VLOG(2) << "Client was unregistered - client_id: " << client_id;
146    return;
147  }
148
149  cb->OnMtuChanged(status, String16(address, std::strlen(address)), mtu);
150}
151
152android::sp<IBluetoothLowEnergyCallback>
153BluetoothLowEnergyBinderServer::GetLECallback(int client_id) {
154  auto cb = GetCallback(client_id);
155  return android::sp<IBluetoothLowEnergyCallback>(
156      static_cast<IBluetoothLowEnergyCallback*>(cb.get()));
157}
158
159std::shared_ptr<bluetooth::LowEnergyClient>
160BluetoothLowEnergyBinderServer::GetLEClient(int client_id) {
161  return std::static_pointer_cast<bluetooth::LowEnergyClient>(
162      GetInstance(client_id));
163}
164
165void BluetoothLowEnergyBinderServer::OnRegisterInstanceImpl(
166    bluetooth::BLEStatus status, android::sp<IInterface> callback,
167    bluetooth::BluetoothInstance* instance) {
168  VLOG(1) << __func__ << " status: " << status;
169  bluetooth::LowEnergyClient* le_client =
170      static_cast<bluetooth::LowEnergyClient*>(instance);
171  le_client->SetDelegate(this);
172
173  android::sp<IBluetoothLowEnergyCallback> cb(
174      static_cast<IBluetoothLowEnergyCallback*>(callback.get()));
175  cb->OnClientRegistered(status, (status == bluetooth::BLE_STATUS_SUCCESS)
176                                     ? instance->GetInstanceId()
177                                     : kInvalidInstanceId);
178}
179
180}  // namespace binder
181}  // namespace ipc
182