1 //
2 //  Copyright 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 
21 namespace ipc {
22 namespace binder {
23 
RegisterInstanceBase(const android::sp<IInterface> & callback,bluetooth::BluetoothInstanceFactory * factory)24 bool 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, const bluetooth::Uuid& in_uuid,
51           std::unique_ptr<bluetooth::BluetoothInstance> instance) {
52         // If the weak pointer was invalidated then there is nothing we can do.
53         android::sp<InterfaceWithInstancesBase> strong_ptr_to_this =
54             weak_ptr_to_this.promote();
55         if (!strong_ptr_to_this.get()) {
56           VLOG(2) << "InterfaceWithInstancesBase was deleted while instance was"
57                   << " being registered";
58           return;
59         }
60 
61         strong_ptr_to_this->OnRegisterInstance(status, in_uuid,
62                                                std::move(instance));
63       };
64 
65   if (factory->RegisterInstance(app_uuid, cb)) return true;
66 
67   LOG(ERROR) << "Failed to register instance";
68   pending_callbacks_.Remove(app_uuid);
69 
70   return false;
71 }
72 
UnregisterInstanceBase(int instance_id)73 void InterfaceWithInstancesBase::UnregisterInstanceBase(int instance_id) {
74   VLOG(2) << __func__;
75   std::lock_guard<std::mutex> lock(maps_lock_);
76 
77   id_to_cb_.Remove(instance_id);
78   id_to_instance_.erase(instance_id);
79 }
80 
UnregisterAllBase()81 void InterfaceWithInstancesBase::UnregisterAllBase() {
82   VLOG(2) << __func__;
83   std::lock_guard<std::mutex> lock(maps_lock_);
84 
85   id_to_cb_.Clear();
86   id_to_instance_.clear();
87 }
88 
ForEachCallback(const std::function<void (IInterface *)> & func)89 void InterfaceWithInstancesBase::ForEachCallback(
90     const std::function<void(IInterface*)>& func) {
91   VLOG(2) << __func__;
92   std::lock_guard<std::mutex> lock(maps_lock_);
93   for (auto& pair : id_to_instance_) {
94     auto cb = id_to_cb_.Get(pair.first);
95     func(cb.get());
96   }
97 }
98 
GetCallback(int instance_id)99 android::sp<IInterface> InterfaceWithInstancesBase::GetCallback(
100     int instance_id) {
101   return id_to_cb_.Get(instance_id);
102 }
103 
104 std::shared_ptr<bluetooth::BluetoothInstance>
GetInstance(int instance_id)105 InterfaceWithInstancesBase::GetInstance(int instance_id) {
106   auto iter = id_to_instance_.find(instance_id);
107   if (iter == id_to_instance_.end())
108     return std::shared_ptr<bluetooth::BluetoothInstance>();
109   return iter->second;
110 }
111 
OnRegisterInstance(bluetooth::BLEStatus status,const bluetooth::Uuid & uuid,std::unique_ptr<bluetooth::BluetoothInstance> instance)112 void InterfaceWithInstancesBase::OnRegisterInstance(
113     bluetooth::BLEStatus status, const bluetooth::Uuid& uuid,
114     std::unique_ptr<bluetooth::BluetoothInstance> instance) {
115   VLOG(2) << __func__ << " - status: " << status;
116 
117   // Simply remove the callback from |pending_callbacks_| as it no longer
118   // belongs in there.
119   sp<IInterface> callback = pending_callbacks_.Remove(uuid);
120 
121   // |callback| might be NULL if it was removed from the pending list, e.g. the
122   // remote process that owns the callback died.
123   if (!callback.get()) {
124     VLOG(1) << "Callback was removed before the call to \"RegisterInstance\" "
125             << "returned; unregistering instance";
126     return;
127   }
128 
129   if (status != bluetooth::BLE_STATUS_SUCCESS) {
130     // The call wasn't successful. Notify the implementation and return.
131     LOG(ERROR) << "Failed to register instance: " << status;
132     OnRegisterInstanceImpl(status, callback, nullptr);
133     return;
134   }
135 
136   std::lock_guard<std::mutex> lock(maps_lock_);
137   int instance_id = instance->GetInstanceId();
138   if (!id_to_cb_.Register(instance_id, callback, this)) {
139     LOG(ERROR) << "Failed to store callback";
140     OnRegisterInstanceImpl(bluetooth::BLE_STATUS_FAILURE, callback, nullptr);
141     return;
142   }
143 
144   VLOG(1) << "Registered BluetoothInstance - ID: " << instance_id;
145 
146   auto shared_instance =
147       std::shared_ptr<bluetooth::BluetoothInstance>(instance.release());
148   id_to_instance_[instance_id] = shared_instance;
149 
150   OnRegisterInstanceImpl(status, callback, shared_instance.get());
151 }
152 
OnRemoteCallbackRemoved(const int & key)153 void InterfaceWithInstancesBase::OnRemoteCallbackRemoved(const int& key) {
154   VLOG(2) << __func__ << " instance_id: " << key;
155   std::lock_guard<std::mutex> lock(maps_lock_);
156 
157   // No need to remove from the callback map as the entry should be already
158   // removed when this callback gets called.
159   id_to_instance_.erase(key);
160 }
161 
162 }  // namespace binder
163 }  // namespace ipc
164