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_le_advertiser_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
34BluetoothLeAdvertiserBinderServer::BluetoothLeAdvertiserBinderServer(
35    bluetooth::Adapter* adapter)
36    : adapter_(adapter) {
37  CHECK(adapter_);
38}
39
40BluetoothLeAdvertiserBinderServer::~BluetoothLeAdvertiserBinderServer() {}
41
42Status BluetoothLeAdvertiserBinderServer::RegisterAdvertiser(
43    const android::sp<IBluetoothLeAdvertiserCallback>& callback,
44    bool* _aidl_return) {
45  VLOG(2) << __func__;
46  bluetooth::LowEnergyAdvertiserFactory* adv_factory =
47      adapter_->GetLeAdvertiserFactory();
48
49  *_aidl_return = RegisterInstanceBase(callback, adv_factory);
50  return Status::ok();
51}
52
53Status BluetoothLeAdvertiserBinderServer::UnregisterAdvertiser(
54    int advertiser_id) {
55  VLOG(2) << __func__;
56  UnregisterInstanceBase(advertiser_id);
57  return Status::ok();
58}
59
60Status BluetoothLeAdvertiserBinderServer::UnregisterAll() {
61  VLOG(2) << __func__;
62  UnregisterAllBase();
63  return Status::ok();
64}
65
66Status BluetoothLeAdvertiserBinderServer::StartMultiAdvertising(
67    int advertiser_id, const android::bluetooth::AdvertiseData& advertise_data,
68    const android::bluetooth::AdvertiseData& scan_response,
69    const android::bluetooth::AdvertiseSettings& settings, bool* _aidl_return) {
70  VLOG(2) << __func__ << " advertiser_id: " << advertiser_id;
71  std::lock_guard<std::mutex> lock(*maps_lock());
72
73  auto advertiser = GetLEAdvertiser(advertiser_id);
74  if (!advertiser) {
75    LOG(ERROR) << "Unknown advertiser_id: " << advertiser_id;
76    *_aidl_return = false;
77    return Status::ok();
78  }
79
80  // Create a weak pointer and pass that to the callback to prevent a potential
81  // use after free.
82  android::wp<BluetoothLeAdvertiserBinderServer> weak_ptr_to_this(this);
83  auto settings_copy = settings;
84  auto callback = [=](bluetooth::BLEStatus status) {
85    auto sp_to_this = weak_ptr_to_this.promote();
86    if (!sp_to_this.get()) {
87      VLOG(2) << "BluetoothLeAdvertiserBinderServer was deleted";
88      return;
89    }
90
91    std::lock_guard<std::mutex> lock(*maps_lock());
92
93    auto cb = GetLECallback(advertiser_id);
94    if (!cb.get()) {
95      VLOG(1) << "Advertiser was removed before callback: " << advertiser_id;
96      return;
97    }
98
99    cb->OnMultiAdvertiseCallback(status, true /* is_start */, settings_copy);
100  };
101
102  if (!advertiser->StartAdvertising(settings, advertise_data, scan_response,
103                                    callback)) {
104    LOG(ERROR) << "Failed to initiate call to start advertising";
105    *_aidl_return = false;
106    return Status::ok();
107  }
108
109  *_aidl_return = true;
110  return Status::ok();
111}
112
113Status BluetoothLeAdvertiserBinderServer::StopMultiAdvertising(
114    int advertiser_id, bool* _aidl_return) {
115  VLOG(2) << __func__;
116  std::lock_guard<std::mutex> lock(*maps_lock());
117
118  auto advertiser = GetLEAdvertiser(advertiser_id);
119  if (!advertiser) {
120    LOG(ERROR) << "Unknown advertiser_id: " << advertiser_id;
121    *_aidl_return = false;
122    return Status::ok();
123  }
124
125  // Create a weak pointer and pass that to the callback to prevent a potential
126  // use after free.
127  android::wp<BluetoothLeAdvertiserBinderServer> weak_ptr_to_this(this);
128  auto settings_copy = advertiser->advertise_settings();
129  auto callback = [=](bluetooth::BLEStatus status) {
130    auto sp_to_this = weak_ptr_to_this.promote();
131    if (!sp_to_this.get()) {
132      VLOG(2) << "BluetoothLeAdvertiserBinderServer was deleted";
133      return;
134    }
135
136    auto cb = GetLECallback(advertiser_id);
137    if (!cb.get()) {
138      VLOG(2) << "Advertiser was unregistered - advertiser_id: "
139              << advertiser_id;
140      return;
141    }
142
143    std::lock_guard<std::mutex> lock(*maps_lock());
144
145    cb->OnMultiAdvertiseCallback(status, false /* is_start */, settings_copy);
146  };
147
148  if (!advertiser->StopAdvertising(callback)) {
149    LOG(ERROR) << "Failed to initiate call to start advertising";
150    *_aidl_return = false;
151    return Status::ok();
152  }
153
154  *_aidl_return = true;
155  return Status::ok();
156}
157
158android::sp<IBluetoothLeAdvertiserCallback>
159BluetoothLeAdvertiserBinderServer::GetLECallback(int advertiser_id) {
160  auto cb = GetCallback(advertiser_id);
161  return android::sp<IBluetoothLeAdvertiserCallback>(
162      static_cast<IBluetoothLeAdvertiserCallback*>(cb.get()));
163}
164
165std::shared_ptr<bluetooth::LowEnergyAdvertiser>
166BluetoothLeAdvertiserBinderServer::GetLEAdvertiser(int advertiser_id) {
167  return std::static_pointer_cast<bluetooth::LowEnergyAdvertiser>(
168      GetInstance(advertiser_id));
169}
170
171void BluetoothLeAdvertiserBinderServer::OnRegisterInstanceImpl(
172    bluetooth::BLEStatus status, android::sp<IInterface> callback,
173    bluetooth::BluetoothInstance* instance) {
174  VLOG(1) << __func__ << " status: " << status;
175
176  android::sp<IBluetoothLeAdvertiserCallback> cb(
177      static_cast<IBluetoothLeAdvertiserCallback*>(callback.get()));
178  cb->OnAdvertiserRegistered(status, (status == bluetooth::BLE_STATUS_SUCCESS)
179                                         ? instance->GetInstanceId()
180                                         : kInvalidInstanceId);
181}
182
183}  // namespace binder
184}  // namespace ipc
185