108f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray// 208f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray// Copyright (C) 2015 Google, Inc. 308f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray// 408f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray// Licensed under the Apache License, Version 2.0 (the "License"); 508f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray// you may not use this file except in compliance with the License. 608f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray// You may obtain a copy of the License at: 708f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray// 808f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray// http://www.apache.org/licenses/LICENSE-2.0 908f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray// 1008f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray// Unless required by applicable law or agreed to in writing, software 1108f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray// distributed under the License is distributed on an "AS IS" BASIS, 1208f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1308f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray// See the License for the specific language governing permissions and 1408f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray// limitations under the License. 1508f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray// 1608f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 17bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray#include "service/ipc/binder/interface_with_instances_base.h" 1808f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 1908f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray#include <base/logging.h> 2008f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 2108f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguraynamespace ipc { 2208f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguraynamespace binder { 2308f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 24bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguraybool InterfaceWithInstancesBase::RegisterInstanceBase( 2508f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray const android::sp<IInterface>& callback, 26bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray bluetooth::BluetoothInstanceFactory* factory) { 2708f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray VLOG(2) << __func__; 2808f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray CHECK(factory); 2908f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 3008f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray if (!callback.get()) { 3108f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray LOG(ERROR) << "Cannot register a NULL callback"; 3208f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray return false; 3308f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray } 3408f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 3508f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray // Store the callback in the pending list. It will get removed later when the 3608f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray // stack notifies us asynchronously. 3708f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray bluetooth::UUID app_uuid = bluetooth::UUID::GetRandom(); 3808f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray if (!pending_callbacks_.Register(app_uuid, callback)) { 3908f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray LOG(ERROR) << "Failed to store |callback| to map"; 4008f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray return false; 4108f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray } 4208f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 4308f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray // Create a weak pointer and pass that to the callback to prevent an invalid 4408f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray // access later. Since this object is managed using Android's StrongPointer 4508f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray // (sp) we are using a wp here rather than std::weak_ptr. 46bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray android::wp<InterfaceWithInstancesBase> weak_ptr_to_this(this); 4708f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 48bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray bluetooth::BluetoothInstanceFactory::RegisterCallback cb = 4908f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray [weak_ptr_to_this]( 5008f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray bluetooth::BLEStatus status, 5108f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray const bluetooth::UUID& in_uuid, 52bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray std::unique_ptr<bluetooth::BluetoothInstance> instance) { 5308f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray // If the weak pointer was invalidated then there is nothing we can do. 54bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray android::sp<InterfaceWithInstancesBase> strong_ptr_to_this = 5508f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray weak_ptr_to_this.promote(); 5608f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray if (!strong_ptr_to_this.get()) { 57bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray VLOG(2) << "InterfaceWithInstancesBase was deleted while instance was" 58bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray << " being registered"; 5908f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray return; 6008f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray } 6108f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 62bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray strong_ptr_to_this->OnRegisterInstance( 63bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray status, in_uuid, std::move(instance)); 6408f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray }; 6508f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 66bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray if (factory->RegisterInstance(app_uuid, cb)) 6708f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray return true; 6808f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 69bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray LOG(ERROR) << "Failed to register instance"; 7008f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray pending_callbacks_.Remove(app_uuid); 7108f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 7208f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray return false; 7308f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray} 7408f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 75bb18c41ffa0370d4eb0c4a15904b114355606466Arman Ugurayvoid InterfaceWithInstancesBase::UnregisterInstanceBase(int instance_id) { 7608f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray VLOG(2) << __func__; 7708f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray std::lock_guard<std::mutex> lock(maps_lock_); 7808f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 79bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray id_to_cb_.Remove(instance_id); 80bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray id_to_instance_.erase(instance_id); 8108f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray} 8208f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 83bb18c41ffa0370d4eb0c4a15904b114355606466Arman Ugurayvoid InterfaceWithInstancesBase::UnregisterAllBase() { 8408f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray VLOG(2) << __func__; 8508f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray std::lock_guard<std::mutex> lock(maps_lock_); 8608f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 87bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray id_to_cb_.Clear(); 88bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray id_to_instance_.clear(); 8908f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray} 9008f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 91bb18c41ffa0370d4eb0c4a15904b114355606466Arman Ugurayandroid::sp<IInterface> InterfaceWithInstancesBase::GetCallback( 92bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray int instance_id) { 93bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray return id_to_cb_.Get(instance_id); 9408f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray} 9508f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 96bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguraystd::shared_ptr<bluetooth::BluetoothInstance> 97bb18c41ffa0370d4eb0c4a15904b114355606466Arman UgurayInterfaceWithInstancesBase::GetInstance(int instance_id) { 98bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray auto iter = id_to_instance_.find(instance_id); 99bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray if (iter == id_to_instance_.end()) 100bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray return std::shared_ptr<bluetooth::BluetoothInstance>(); 10108f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray return iter->second; 10208f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray} 10308f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 104bb18c41ffa0370d4eb0c4a15904b114355606466Arman Ugurayvoid InterfaceWithInstancesBase::OnRegisterInstance( 10508f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray bluetooth::BLEStatus status, 10608f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray const bluetooth::UUID& uuid, 107bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray std::unique_ptr<bluetooth::BluetoothInstance> instance) { 10808f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray VLOG(2) << __func__ << " - status: " << status; 10908f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 11008f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray // Simply remove the callback from |pending_callbacks_| as it no longer 11108f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray // belongs in there. 11208f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray sp<IInterface> callback = pending_callbacks_.Remove(uuid); 11308f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 11408f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray // |callback| might be NULL if it was removed from the pending list, e.g. the 11508f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray // remote process that owns the callback died. 11608f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray if (!callback.get()) { 117bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray VLOG(1) << "Callback was removed before the call to \"RegisterInstance\" " 118bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray << "returned; unregistering instance"; 11908f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray return; 12008f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray } 12108f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 12208f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray if (status != bluetooth::BLE_STATUS_SUCCESS) { 12308f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray // The call wasn't successful. Notify the implementation and return. 124bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray LOG(ERROR) << "Failed to register instance: " << status; 125bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray OnRegisterInstanceImpl(status, callback, nullptr); 12608f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray return; 12708f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray } 12808f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 12908f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray std::lock_guard<std::mutex> lock(maps_lock_); 130bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray int instance_id = instance->GetInstanceId(); 131bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray CHECK(instance_id); 132bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray if (!id_to_cb_.Register(instance_id, callback, this)) { 13308f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray LOG(ERROR) << "Failed to store callback"; 134bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray OnRegisterInstanceImpl(bluetooth::BLE_STATUS_FAILURE, callback, nullptr); 13508f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray return; 13608f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray } 13708f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 138bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray VLOG(1) << "Registered BluetoothInstance - ID: " << instance_id; 13908f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 140bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray auto shared_instance = 141bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray std::shared_ptr<bluetooth::BluetoothInstance>(instance.release()); 142bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray id_to_instance_[instance_id] = shared_instance; 14308f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 144bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray OnRegisterInstanceImpl(status, callback, shared_instance.get()); 14508f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray} 14608f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 147bb18c41ffa0370d4eb0c4a15904b114355606466Arman Ugurayvoid InterfaceWithInstancesBase::OnRemoteCallbackRemoved(const int& key) { 148bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray VLOG(2) << __func__ << " instance_id: " << key; 14908f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray std::lock_guard<std::mutex> lock(maps_lock_); 15008f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 15108f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray // No need to remove from the callback map as the entry should be already 15208f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray // removed when this callback gets called. 153bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray id_to_instance_.erase(key); 15408f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray} 15508f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray 15608f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray} // namespace binder 15708f80ebd5c714364cb76cc4e4a93454b42ed5669Arman Uguray} // namespace ipc 158