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