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