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 #pragma once 18 19 #include <unordered_map> 20 #include <unordered_set> 21 22 #include "hci/acl_manager.h" 23 #include "l2cap/cid.h" 24 #include "l2cap/classic/security_policy.h" 25 #include "l2cap/internal/ilink.h" 26 #include "l2cap/psm.h" 27 #include "os/handler.h" 28 #include "os/log.h" 29 30 namespace bluetooth { 31 namespace l2cap { 32 namespace internal { 33 34 class DynamicChannelImpl; 35 36 // Helper class for keeping channels in a Link. It allocates and frees Channel object, and supports querying whether a 37 // channel is in use 38 class DynamicChannelAllocator { 39 public: DynamicChannelAllocator(l2cap::internal::ILink * link,os::Handler * l2cap_handler)40 DynamicChannelAllocator(l2cap::internal::ILink* link, os::Handler* l2cap_handler) 41 : link_(link), l2cap_handler_(l2cap_handler) { 42 ASSERT(link_ != nullptr); 43 ASSERT(l2cap_handler_ != nullptr); 44 } 45 46 // Allocates a channel. If psm is used, OR the remote cid already exists, return nullptr. 47 // NOTE: The returned DynamicChannelImpl object is still owned by the channel allocator, NOT the client. 48 std::shared_ptr<DynamicChannelImpl> AllocateChannel(Psm psm, Cid remote_cid); 49 50 std::shared_ptr<DynamicChannelImpl> AllocateReservedChannel(Cid reserved_cid, Psm psm, Cid remote_cid); 51 52 // Gives an unused Cid to be used for opening a channel. If a channel is used, call AllocateReservedChannel. If no 53 // longer needed, use FreeChannel. 54 Cid ReserveChannel(); 55 56 // Frees a channel (existing or reserved) 57 void FreeChannel(Cid cid); 58 59 bool IsPsmUsed(Psm psm) const; 60 61 std::shared_ptr<DynamicChannelImpl> FindChannelByCid(Cid cid); 62 std::shared_ptr<DynamicChannelImpl> FindChannelByRemoteCid(Cid cid); 63 64 // Returns number of open, but not reserved channels 65 size_t NumberOfChannels() const; 66 67 void OnAclDisconnected(hci::ErrorCode hci_status); 68 69 private: 70 l2cap::internal::ILink* link_; 71 os::Handler* l2cap_handler_; 72 std::unordered_set<Cid> used_cid_; 73 std::unordered_map<Cid, std::shared_ptr<DynamicChannelImpl>> channels_; 74 std::unordered_set<Cid> used_remote_cid_; 75 }; 76 77 } // namespace internal 78 } // namespace l2cap 79 } // namespace bluetooth 80