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(const std::unordered_map<hci::Address, int>& paired_device_map,
63             Callback save_id_callback, Callback forget_device_callback);
64 
65   /**
66    * Close the allocator. should be called when Bluetooth process is killed
67    *
68    * @return true if successfully close
69    */
70   bool Close();
71 
72   /**
73    * Check if no id saved in memory
74    *
75    * @return true if no id is saved
76    */
77   bool IsEmpty() const;
78 
79   /**
80    * Allocate an id for a scanned device, or return the id if there is already
81    * one
82    *
83    * @param mac_address mac address of Bluetooth device
84    * @return the id of device
85    */
86   int AllocateId(const hci::Address& mac_address);
87 
88   /**
89    * Save the id for a paired device
90    *
91    * @param mac_address mac address of Bluetooth device
92    * @return true if save successfully
93    */
94   bool SaveDevice(const hci::Address& mac_address);
95 
96   /**
97    * Delete the id for a device to be forgotten
98    *
99    * @param mac_address mac address of Bluetooth device
100    */
101   void ForgetDevice(const hci::Address& mac_address);
102 
103   /**
104    * Check if an id is valid.
105    * The id should be less than or equal to kMaxId and bigger than or equal to
106    * kMinId
107    *
108    * @param mac_address mac address of Bluetooth device
109    * @return true if delete successfully
110    */
111   static bool IsValidId(const int id);
112 
113 protected:
114   // Singleton
115   MetricIdManager();
116 
117 private:
118   mutable std::mutex id_allocator_mutex_;
119 
120   LruCache<hci::Address, int> paired_device_cache_;
121   LruCache<hci::Address, int> temporary_device_cache_;
122   std::unordered_set<int> id_set_;
123 
124   int next_id_{kMinId};
125   bool initialized_{false};
126   Callback save_id_callback_;
127   Callback forget_device_callback_;
128 
129   void ForgetDevicePostprocess(const hci::Address& mac_address, const int id);
130 
131   // delete copy constructor for singleton
132   MetricIdManager(MetricIdManager const&) = delete;
133   MetricIdManager& operator=(MetricIdManager const&) = delete;
134 };
135 
136 }  // namespace common
137 }  // namespace bluetooth
138