1 /*
2  * Copyright 2019 The Android Open Source Project
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 "l2cap/classic/internal/fixed_channel_impl.h"
18 
19 #include <bluetooth/log.h>
20 
21 #include <unordered_map>
22 
23 #include "l2cap/cid.h"
24 #include "l2cap/classic/internal/link.h"
25 #include "os/handler.h"
26 #include "os/log.h"
27 
28 namespace bluetooth {
29 namespace l2cap {
30 namespace classic {
31 namespace internal {
32 
FixedChannelImpl(Cid cid,Link * link,os::Handler * l2cap_handler)33 FixedChannelImpl::FixedChannelImpl(Cid cid, Link* link, os::Handler* l2cap_handler)
34     : cid_(cid), device_(link->GetDevice()), link_(link), l2cap_handler_(l2cap_handler) {
35   log::assert_that(
36       cid_ >= kFirstFixedChannel && cid_ <= kLastFixedChannel, "Invalid cid: {}", cid_);
37   log::assert_that(link_ != nullptr, "assert failed: link_ != nullptr");
38   log::assert_that(l2cap_handler_ != nullptr, "assert failed: l2cap_handler_ != nullptr");
39 }
40 
RegisterOnCloseCallback(os::Handler * user_handler,FixedChannel::OnCloseCallback on_close_callback)41 void FixedChannelImpl::RegisterOnCloseCallback(os::Handler* user_handler,
42                                                FixedChannel::OnCloseCallback on_close_callback) {
43   log::assert_that(user_handler_ == nullptr, "OnCloseCallback can only be registered once");
44   // If channel is already closed, call the callback immediately without saving it
45   if (closed_) {
46     user_handler->Post(common::BindOnce(std::move(on_close_callback), close_reason_));
47     return;
48   }
49   user_handler_ = user_handler;
50   on_close_callback_ = std::move(on_close_callback);
51 }
52 
OnClosed(hci::ErrorCode status)53 void FixedChannelImpl::OnClosed(hci::ErrorCode status) {
54   log::assert_that(
55       !closed_,
56       "Device {} Cid 0x{:x} closed twice, old status 0x{:x}, new status 0x{:x}",
57       ADDRESS_TO_LOGGABLE_CSTR(device_),
58       cid_,
59       static_cast<int>(close_reason_),
60       static_cast<int>(status));
61   closed_ = true;
62   close_reason_ = status;
63   acquired_ = false;
64   link_ = nullptr;
65   l2cap_handler_ = nullptr;
66   if (user_handler_ == nullptr) {
67     return;
68   }
69   // On close callback can only be called once
70   user_handler_->Post(common::BindOnce(std::move(on_close_callback_), status));
71   user_handler_ = nullptr;
72   on_close_callback_.Reset();
73 }
74 
Acquire()75 void FixedChannelImpl::Acquire() {
76   log::assert_that(
77       user_handler_ != nullptr, "Must register OnCloseCallback before calling any methods");
78   if (closed_) {
79     log::warn("{} is already closed", ToLoggableStr(*this));
80     log::assert_that(!acquired_, "assert failed: !acquired_");
81     return;
82   }
83   if (acquired_) {
84     log::info("{} was already acquired", ToLoggableStr(*this));
85     return;
86   }
87   acquired_ = true;
88   link_->RefreshRefCount();
89 }
90 
Release()91 void FixedChannelImpl::Release() {
92   log::assert_that(
93       user_handler_ != nullptr, "Must register OnCloseCallback before calling any methods");
94   if (closed_) {
95     log::warn("{} is already closed", ToLoggableStr(*this));
96     log::assert_that(!acquired_, "assert failed: !acquired_");
97     return;
98   }
99   if (!acquired_) {
100     log::info("{} was already released", ToLoggableStr(*this));
101     return;
102   }
103   acquired_ = false;
104   link_->RefreshRefCount();
105 }
106 
107 }  // namespace internal
108 }  // namespace classic
109 }  // namespace l2cap
110 }  // namespace bluetooth
111