1 /******************************************************************************
2  *
3  *  Copyright 2020 Google, Inc.
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 #pragma once
20 
21 #include <mutex>
22 #include <string>
23 #include <thread>
24 #include <unordered_set>
25 
26 #include "common/lru_cache.h"
27 #include "hci/address.h"
28 
29 namespace bluetooth {
30 namespace common {
31 
32 class MetricIdManager {
33  public:
34   using Callback = std::function<bool(const hci::Address& address, const int id)>;
35 
36   static const size_t kMaxNumUnpairedDevicesInMemory;
37   static const size_t kMaxNumPairedDevicesInMemory;
38 
39   static const int kMinId;
40   static const int kMaxId;
41 
42   ~MetricIdManager();
43 
44   /**
45    * Get the instance of singleton
46    *
47    * @return MetricIdManager&
48    */
49   static MetricIdManager& GetInstance();
50 
51   /**
52    * Initialize the allocator
53    *
54    * @param paired_device_map map from mac_address to id already saved
55    * in the disk before init
56    * @param save_id_callback a callback that will be called after successfully
57    * saving id for a paired device
58    * @param forget_device_callback a callback that will be called after
59    * successful id deletion for forgotten device,
60    * @return true if successfully initialized
61    */
62   bool Init(
63       const std::unordered_map<hci::Address, int>& paired_device_map,
64       Callback save_id_callback,
65       Callback forget_device_callback);
66 
67   /**
68    * Close the allocator. should be called when Bluetooth process is killed
69    *
70    * @return true if successfully close
71    */
72   bool Close();
73 
74   /**
75    * Check if no id saved in memory
76    *
77    * @return true if no id is saved
78    */
79   bool IsEmpty() const;
80 
81   /**
82    * Allocate an id for a scanned device, or return the id if there is already
83    * one
84    *
85    * @param mac_address mac address of Bluetooth device
86    * @return the id of device
87    */
88   int AllocateId(const hci::Address& mac_address);
89 
90   /**
91    * Save the id for a paired device
92    *
93    * @param mac_address mac address of Bluetooth device
94    * @return true if save successfully
95    */
96   bool SaveDevice(const hci::Address& mac_address);
97 
98   /**
99    * Delete the id for a device to be forgotten
100    *
101    * @param mac_address mac address of Bluetooth device
102    */
103   void ForgetDevice(const hci::Address& mac_address);
104 
105   /**
106    * Check if an id is valid.
107    * The id should be less than or equal to kMaxId and bigger than or equal to
108    * kMinId
109    *
110    * @param mac_address mac address of Bluetooth device
111    * @return true if delete successfully
112    */
113   static bool IsValidId(const int id);
114 
115  protected:
116   // Singleton
117   MetricIdManager();
118 
119  private:
120   mutable std::mutex id_allocator_mutex_;
121 
122   LruCache<hci::Address, int> paired_device_cache_;
123   LruCache<hci::Address, int> temporary_device_cache_;
124   std::unordered_set<int> id_set_;
125 
126   int next_id_{kMinId};
127   bool initialized_{false};
128   Callback save_id_callback_;
129   Callback forget_device_callback_;
130 
131   void ForgetDevicePostprocess(const hci::Address& mac_address,
132       const int id);
133 
134   // delete copy constructor for singleton
135   MetricIdManager(MetricIdManager const&) = delete;
136   MetricIdManager& operator=(MetricIdManager const&) = delete;
137 };
138 
139 }  // namespace common
140 }  // namespace bluetooth
141