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 #include "raw_address.h"
26 
27 #include "lru.h"
28 
29 namespace bluetooth {
30 
31 namespace common {
32 
33 class MetricIdAllocator {
34  public:
35   using Callback = std::function<bool(const RawAddress& address, const int id)>;
36 
37   static const size_t kMaxNumUnpairedDevicesInMemory;
38   static const size_t kMaxNumPairedDevicesInMemory;
39 
40   static const int kMinId;
41   static const int kMaxId;
42 
43   ~MetricIdAllocator();
44 
45   /**
46    * Get the instance of singleton
47    *
48    * @return MetricIdAllocator&
49    */
50   static MetricIdAllocator& GetInstance();
51 
52   /**
53    * Initialize the allocator
54    *
55    * @param paired_device_map map from mac_address to id already saved
56    * in the disk before init
57    * @param save_id_callback a callback that will be called after successfully
58    * saving id for a paired device
59    * @param forget_device_callback a callback that will be called after
60    * successful id deletion for forgotten device,
61    * @return true if successfully initialized
62    */
63   bool Init(const std::unordered_map<RawAddress, int>& paired_device_map,
64             Callback save_id_callback, Callback forget_device_callback);
65 
66   /**
67    * Close the allocator. should be called when Bluetooth process is killed
68    *
69    * @return true if successfully close
70    */
71   bool Close();
72 
73   /**
74    * Check if no id saved in memory
75    *
76    * @return true if no id is saved
77    */
78   bool IsEmpty() const;
79 
80   /**
81    * Allocate an id for a scanned device, or return the id if there is already
82    * one
83    *
84    * @param mac_address mac address of Bluetooth device
85    * @return the id of device
86    */
87   int AllocateId(const RawAddress& mac_address);
88 
89   /**
90    * Save the id for a paired device
91    *
92    * @param mac_address mac address of Bluetooth device
93    * @return true if save successfully
94    */
95   bool SaveDevice(const RawAddress& mac_address);
96 
97   /**
98    * Delete the id for a device to be forgotten
99    *
100    * @param mac_address mac address of Bluetooth device
101    */
102   void ForgetDevice(const RawAddress& mac_address);
103 
104   /**
105    * Check if an id is valid.
106    * The id should be less than or equal to kMaxId and bigger than or equal to
107    * kMinId
108    *
109    * @param mac_address mac address of Bluetooth device
110    * @return true if delete successfully
111    */
112   static bool IsValidId(const int id);
113 
114  protected:
115   // Singleton
116   MetricIdAllocator();
117 
118  private:
119   static const std::string LOGGING_TAG;
120   mutable std::mutex id_allocator_mutex_;
121 
122   LruCache<RawAddress, int> paired_device_cache_;
123   LruCache<RawAddress, 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 RawAddress& mac_address, const int id);
132 
133   // delete copy constructor for singleton
134   MetricIdAllocator(MetricIdAllocator const&) = delete;
135   MetricIdAllocator& operator=(MetricIdAllocator const&) = delete;
136 };
137 
138 }  // namespace common
139 }  // namespace bluetooth
140