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
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,
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
UnregisterInstanceBase(int instance_id)75 void 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
UnregisterAllBase()83 void 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
GetCallback(int instance_id)91 android::sp<IInterface> InterfaceWithInstancesBase::GetCallback(
92 int instance_id) {
93 return id_to_cb_.Get(instance_id);
94 }
95
96 std::shared_ptr<bluetooth::BluetoothInstance>
GetInstance(int instance_id)97 InterfaceWithInstancesBase::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
OnRegisterInstance(bluetooth::BLEStatus status,const bluetooth::UUID & uuid,std::unique_ptr<bluetooth::BluetoothInstance> instance)104 void 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
OnRemoteCallbackRemoved(const int & key)147 void 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