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/interface_with_instances_base.h"
18
19#include <base/logging.h>
20
21namespace ipc {
22namespace binder {
23
24bool InterfaceWithInstancesBase::RegisterInstanceBase(
25    const android::sp<IInterface>& callback,
26    bluetooth::BluetoothInstanceFactory* factory) {
27  VLOG(2) << __func__;
28  CHECK(factory);
29
30  if (!callback.get()) {
31    LOG(ERROR) << "Cannot register a NULL callback";
32    return false;
33  }
34
35  // Store the callback in the pending list. It will get removed later when the
36  // stack notifies us asynchronously.
37  bluetooth::UUID app_uuid = bluetooth::UUID::GetRandom();
38  if (!pending_callbacks_.Register(app_uuid, callback)) {
39    LOG(ERROR) << "Failed to store |callback| to map";
40    return false;
41  }
42
43  // Create a weak pointer and pass that to the callback to prevent an invalid
44  // access later. Since this object is managed using Android's StrongPointer
45  // (sp) we are using a wp here rather than std::weak_ptr.
46  android::wp<InterfaceWithInstancesBase> weak_ptr_to_this(this);
47
48  bluetooth::BluetoothInstanceFactory::RegisterCallback cb =
49      [weak_ptr_to_this](
50          bluetooth::BLEStatus status,
51          const bluetooth::UUID& in_uuid,
52          std::unique_ptr<bluetooth::BluetoothInstance> instance) {
53        // If the weak pointer was invalidated then there is nothing we can do.
54        android::sp<InterfaceWithInstancesBase> strong_ptr_to_this =
55            weak_ptr_to_this.promote();
56        if (!strong_ptr_to_this.get()) {
57          VLOG(2) << "InterfaceWithInstancesBase was deleted while instance was"
58                  << " being registered";
59          return;
60        }
61
62        strong_ptr_to_this->OnRegisterInstance(
63            status, in_uuid, std::move(instance));
64      };
65
66  if (factory->RegisterInstance(app_uuid, cb))
67    return true;
68
69  LOG(ERROR) << "Failed to register instance";
70  pending_callbacks_.Remove(app_uuid);
71
72  return false;
73}
74
75void InterfaceWithInstancesBase::UnregisterInstanceBase(int instance_id) {
76  VLOG(2) << __func__;
77  std::lock_guard<std::mutex> lock(maps_lock_);
78
79  id_to_cb_.Remove(instance_id);
80  id_to_instance_.erase(instance_id);
81}
82
83void InterfaceWithInstancesBase::UnregisterAllBase() {
84  VLOG(2) << __func__;
85  std::lock_guard<std::mutex> lock(maps_lock_);
86
87  id_to_cb_.Clear();
88  id_to_instance_.clear();
89}
90
91android::sp<IInterface> InterfaceWithInstancesBase::GetCallback(
92    int instance_id) {
93  return id_to_cb_.Get(instance_id);
94}
95
96std::shared_ptr<bluetooth::BluetoothInstance>
97InterfaceWithInstancesBase::GetInstance(int instance_id) {
98  auto iter = id_to_instance_.find(instance_id);
99  if (iter == id_to_instance_.end())
100    return std::shared_ptr<bluetooth::BluetoothInstance>();
101  return iter->second;
102}
103
104void InterfaceWithInstancesBase::OnRegisterInstance(
105    bluetooth::BLEStatus status,
106    const bluetooth::UUID& uuid,
107    std::unique_ptr<bluetooth::BluetoothInstance> instance) {
108  VLOG(2) << __func__ << " - status: " << status;
109
110  // Simply remove the callback from |pending_callbacks_| as it no longer
111  // belongs in there.
112  sp<IInterface> callback = pending_callbacks_.Remove(uuid);
113
114  // |callback| might be NULL if it was removed from the pending list, e.g. the
115  // remote process that owns the callback died.
116  if (!callback.get()) {
117    VLOG(1) << "Callback was removed before the call to \"RegisterInstance\" "
118            << "returned; unregistering instance";
119    return;
120  }
121
122  if (status != bluetooth::BLE_STATUS_SUCCESS) {
123    // The call wasn't successful. Notify the implementation and return.
124    LOG(ERROR) << "Failed to register instance: " << status;
125    OnRegisterInstanceImpl(status, callback, nullptr);
126    return;
127  }
128
129  std::lock_guard<std::mutex> lock(maps_lock_);
130  int instance_id = instance->GetInstanceId();
131  CHECK(instance_id);
132  if (!id_to_cb_.Register(instance_id, callback, this)) {
133    LOG(ERROR) << "Failed to store callback";
134    OnRegisterInstanceImpl(bluetooth::BLE_STATUS_FAILURE, callback, nullptr);
135    return;
136  }
137
138  VLOG(1) << "Registered BluetoothInstance - ID: " << instance_id;
139
140  auto shared_instance =
141      std::shared_ptr<bluetooth::BluetoothInstance>(instance.release());
142  id_to_instance_[instance_id] = shared_instance;
143
144  OnRegisterInstanceImpl(status, callback, shared_instance.get());
145}
146
147void InterfaceWithInstancesBase::OnRemoteCallbackRemoved(const int& key) {
148  VLOG(2) << __func__ << " instance_id: " << key;
149  std::lock_guard<std::mutex> lock(maps_lock_);
150
151  // No need to remove from the callback map as the entry should be already
152  // removed when this callback gets called.
153  id_to_instance_.erase(key);
154}
155
156}  // namespace binder
157}  // namespace ipc
158