• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #ifndef CHRE_CORE_BLE_REQUEST_MANAGER_H_
18 #define CHRE_CORE_BLE_REQUEST_MANAGER_H_
19 
20 #include "chre/core/ble_request.h"
21 #include "chre/core/ble_request_multiplexer.h"
22 #include "chre/core/nanoapp.h"
23 #include "chre/core/settings.h"
24 #include "chre/platform/platform_ble.h"
25 #include "chre/util/non_copyable.h"
26 #include "chre/util/system/debug_dump.h"
27 #include "chre/util/time.h"
28 
29 namespace chre {
30 
31 /**
32  * Manages requests for ble resources from nanoapps and multiplexes these
33  * requests into the platform-specific implementation of the ble subsystem.
34  */
35 class BleRequestManager : public NonCopyable {
36  public:
37   /**
38    * Initializes the underlying platform-specific BLE module. Must be called
39    * prior to invoking any other methods in this class.
40    */
41   void init();
42 
43   /**
44    * @return the BLE capabilities exposed by this platform.
45    */
46   uint32_t getCapabilities();
47 
48   /**
49    * @return the BLE filter capabilities exposed by this platform.
50    */
51   uint32_t getFilterCapabilities();
52 
53   /**
54    * Begins a BLE scan asynchronously. The result is delivered through a
55    * CHRE_EVENT_BLE_ASYNC_RESULT event.
56    *
57    * @param nanoapp The nanoapp starting the request.
58    * @param mode Scanning mode selected among enum chreBleScanMode
59    * @param reportDelayMs Maximum requested batching delay in ms. 0 indicates no
60    *                      batching. Note that the system may deliver results
61    *                      before the maximum specified delay is reached.
62    * @param filter Pointer to the requested best-effort filter configuration as
63    *               defined by struct chreBleScanFilter. The ownership of filter
64    *               and its nested elements remains with the caller, and the
65    *               caller may release it as soon as chreBleStartScanAsync()
66    *               returns.
67    * @return true if scan was successfully enabled.
68    */
69   bool startScanAsync(Nanoapp *nanoapp, chreBleScanMode mode,
70                       uint32_t reportDelayMs,
71                       const struct chreBleScanFilter *filter);
72 
73   /**
74    * End a BLE scan asynchronously. The result is delivered through a
75    * CHRE_EVENT_BLE_ASYNC_RESULT event.
76    *
77    * @param nanoapp The nanoapp stopping the request.
78    * @return whether the scan was successfully ended.
79    */
80   bool stopScanAsync(Nanoapp *nanoapp);
81 
82   /**
83    * Disables active scan for a nanoapp (no-op if no active scan).
84    *
85    * @param nanoapp A non-null pointer to the nanoapp.
86    * @return the number of scans cancelled (1 or 0).
87    */
88   uint32_t disableActiveScan(const Nanoapp *nanoapp);
89 
90   /**
91    * Frees an advertising event that was previously provided to the BLE
92    * manager.
93    *
94    * @param event the event to release.
95    */
96   void handleFreeAdvertisingEvent(struct chreBleAdvertisementEvent *event);
97 
98   /**
99    * Releases BLE Advertising Event after nanoapps have processed it.
100    *
101    * @param eventType the type of event being freed.
102    * @param eventData a pointer to the scan event to release.
103    */
104   static void freeAdvertisingEventCallback(uint16_t eventType, void *eventData);
105 
106   /**
107    * Handles a CHRE BLE advertisement event.
108    *
109    * @param event The BLE advertisement event containing BLE advertising
110    *              reports. This memory is guaranteed not to be modified until it
111    *              has been explicitly released through the PlatformBle instance.
112    */
113   void handleAdvertisementEvent(struct chreBleAdvertisementEvent *event);
114 
115   /**
116    * Handles the result of a request to the PlatformBle to enable or end a scan.
117    *
118    * @param enable true if the scan is being enabled, false if not.
119    * @param errorCode an error code that is used to indicate success or what
120    *                  type of error has occurred. See chreError enum in the CHRE
121    *                  API for additional details.
122    */
123   void handlePlatformChange(bool enable, uint8_t errorCode);
124 
125   /**
126    * Invoked as a result of a requestStateResync() callback from the BLE PAL.
127    * Runs asynchronously in the context of the callback immediately.
128    */
129   void handleRequestStateResyncCallback();
130 
131   /**
132    * Invoked when the host notifies CHRE that ble access has been
133    * disabled via the user settings.
134    *
135    * @param setting The setting that changed.
136    * @param enabled Whether setting is enabled or not.
137    */
138   void onSettingChanged(Setting setting, bool enabled);
139 
140   /**
141    * Prints state in a string buffer. Must only be called from the context of
142    * the main CHRE thread.
143    *
144    * @param debugDump The debug dump wrapper where a string can be printed
145    *     into one of the buffers.
146    */
147   void logStateToBuffer(DebugDumpWrapper &debugDump) const;
148 
149  private:
150   // Multiplexer used to keep track of BLE requests from nanoapps.
151   BleRequestMultiplexer mRequests;
152 
153   // The platform BLE interface.
154   PlatformBle mPlatformBle;
155 
156   // Expected platform state after completion of async platform request.
157   BleRequest mPendingPlatformRequest;
158 
159   // Current state of the platform.
160   BleRequest mActivePlatformRequest;
161 
162   // True if a request from the PAL is currently pending.
163   bool mInternalRequestPending;
164 
165   // True if a state resync request is pending to be processed.
166   bool mResyncPending;
167 
168   // True if a setting change request is pending to be processed.
169   bool mSettingChangePending;
170 
171   // Struct to hold ble request data for logging
172   struct BleRequestLog {
BleRequestLogBleRequestLog173     BleRequestLog(Nanoseconds timestamp, uint32_t instanceId, bool enable,
174                   bool compliesWithBleSetting)
175         : timestamp(timestamp),
176           instanceId(instanceId),
177           enable(enable),
178           compliesWithBleSetting(compliesWithBleSetting) {}
populateRequestDataBleRequestLog179     void populateRequestData(const BleRequest &req) {
180       mode = req.getMode();
181       reportDelayMs = req.getReportDelayMs();
182       rssiThreshold = req.getRssiThreshold();
183       scanFilterCount = static_cast<uint8_t>(req.getGenericFilters().size());
184     }
185     Nanoseconds timestamp;
186     uint32_t instanceId;
187     bool enable;
188     bool compliesWithBleSetting;
189     chreBleScanMode mode;
190     uint32_t reportDelayMs;
191     int8_t rssiThreshold;
192     uint8_t scanFilterCount;
193   };
194 
195   // List of most recent ble request logs
196   static constexpr size_t kNumBleRequestLogs = 10;
197   ArrayQueue<BleRequestLog, kNumBleRequestLogs> mBleRequestLogs;
198 
199   /**
200    * Configures BLE platform based on the current maximal BleRequest.
201    */
202   bool controlPlatform();
203 
204   /**
205    * Processes nanoapp requests to start and stop a scan and updates BLE
206    * platform if necessary.
207    *
208    * @param request BLE request to start or stop scan.
209    * @return true if request was successfully processed.
210    */
211   bool configure(BleRequest &&request);
212 
213   /**
214    * Handle sending an async response if a nanoapp attempts to override an
215    * existing request.
216    *
217    * @param instanceId Instance id of nanoapp that made the request.
218    * @param hasExistingRequest Indicates whether a request exists corresponding
219    * to the nanoapp instance id of the new request.
220    * @param requestIndex If hasExistingRequest is true, requestIndex
221    * corresponds to the index of that request.
222    */
223   void handleExistingRequest(uint16_t instanceId, bool *hasExistingRequest,
224                              size_t *requestIndex);
225 
226   /**
227    * Check whether a request is attempting to enable the BLE platform while the
228    * BLE setting is disabled.
229    *
230    * @param instanceId Instance id of nanoapp that made the request.
231    * @param enabled Whether the request should start or stop a scan.
232    * @param hasExistingRequest Indicates whether a request exists corresponding
233    * to the nanoapp instance id of the new request.
234    * @param requestIndex If hasExistingRequest is true, requestIndex
235    * corresponds to the index of that request.
236    * @return true if the request does not attempt to enable the platform while
237    * the BLE setting is disabled.
238    */
239   bool compliesWithBleSetting(uint16_t instanceId, bool enabled,
240                               bool hasExistingRequest, size_t requestIndex);
241 
242   /**
243    * Add a log to list of BLE request logs possibly pushing out the oldest log.
244    *
245    * @param instanceId Instance id of nanoapp that made the request.
246    * @param enabled Whether the request should start or stop a scan.
247    * @param requestIndex Index of request in multiplexer. Must check whether it
248    * is valid range before using.
249    * @param compliesWithBleSetting true if the request does not attempt to
250    * enable the platform while the BLE setting is disabled.
251    */
252   void addBleRequestLog(uint32_t instanceId, bool enabled, size_t requestIndex,
253                         bool compliesWithBleSetting);
254 
255   /**
256    * Update active BLE scan requests upon successful starting or ending a scan
257    * and register or unregister nanoapp for BLE broadcast events.
258    *
259    * @param request Scan requested by nanoapp, only valid if nanoappEnabled is
260    *                true.
261    * @param requestChanged Indicates when the new request resulted in a change
262    *                       to the underlying maximal request
263    * @param hasExistingRequest Indicates whether a request exists for the
264    * corresponding nanoapp instance Id of the new request.
265    * @param requestIndex If equal to mRequests.size(), indicates the request
266    *                     wasn't added (perhaps due to removing a non-existent
267    *                     request). Otherwise, indicates the correct index for
268    *                     the request.
269    * @return true if requests were successfully updated.
270    */
271   bool updateRequests(BleRequest &&request, bool hasExistingRequest,
272                       bool *requestChanged, size_t *requestIndex);
273 
274   /**
275    * Handles the result of a request to the PlatformBle to enable or end a scan.
276    * This method is intended to be invoked on the CHRE event loop thread. The
277    * handlePlatformChange method which may be called from any thread. For
278    * parameter details,
279    * @see handleAdvertisementEvent
280    */
281   void handlePlatformChangeSync(bool enable, uint8_t errorCode);
282 
283   /**
284    * Dispatches pending BLE requests from nanoapps.
285    */
286   void dispatchPendingRequests();
287 
288   /**
289    * Handles registering/unregistering a nanoapp to the appropriate broadcast
290    * event.
291    *
292    * @param instanceId Nanoapp instance to send result to.
293    * @param enabled Whether nanoapp was enabled or disabled for BLE events.
294    * @param success Whether the request was processed by the PAL successfully.
295    * @param forceUnregister Whether the nanoapp should be force unregistered
296    *                        from BLE broadcast events.
297    */
298   void handleNanoappEventRegistration(uint16_t instanceId, bool enabled,
299                                       bool success, bool forceUnregister);
300 
301   /**
302    * Handles an async result, sending the result to the requesting nanoapp and
303    * registering/unregistering it from the appropriate broadcast
304    *
305    * @param instanceId Nanoapp instance to send result to.
306    * @param enabled Whether nanoapp was enabled or disabled for BLE events.
307    * @param success Whether the request was processed by the PAL successfully
308    * @param errorCode Error code resulting from the request
309    * @param forceUnregister Whether the nanoapp should be force unregistered
310    *                        from BLE broadcast events.
311    */
312   void handleAsyncResult(uint16_t instanceId, bool enabled, bool success,
313                          uint8_t errorCode, bool forceUnregister = false);
314 
315   /**
316    * Invoked as a result of a requestStateResync() callback from the BLE PAL.
317    * Runs in the context of the CHRE thread.
318    */
319   void handleRequestStateResyncCallbackSync();
320 
321   /**
322    * Updates the platform BLE request according to the current state. It should
323    * be used to synchronize the BLE to the desired state, e.g. for setting
324    * changes or handling a state resync request.
325    *
326    * @param forceUpdate if true force the platform BLE request to be made.
327    */
328   void updatePlatformRequest(bool forceUpdate = false);
329 
330   /**
331    * @return true if an async response is pending from BLE. This method should
332    * be used to check if a BLE platform request is in progress.
333    */
334   bool asyncResponsePending() const;
335 
336   /**
337    * Validates the parameters given to ensure that they can be issued to the
338    * PAL.
339    *
340    * @param request BleRequest sent by a nanoapp.
341    */
342   static bool validateParams(const BleRequest &request);
343 
344   /**
345    * Posts the result of a BLE start/stop scan request.
346    *
347    * @param instanceId The nanoapp instance ID that made the request.
348    * @param requestType The type of BLE request the nanoapp issued.
349    * @param success true if the operation was successful.
350    * @param errorCode the error code as a result of this operation.
351    */
352   static void postAsyncResultEventFatal(uint16_t instanceId,
353                                         uint8_t requestType, bool success,
354                                         uint8_t errorCode);
355 
356   /**
357    * @return True if the given advertisement type is valid
358    */
359   static bool isValidAdType(uint8_t adType);
360 
361   /**
362    * @return true if BLE setting is enabled.
363    */
364   bool bleSettingEnabled();
365 };
366 
367 }  // namespace chre
368 
369 #endif  // CHRE_CORE_BLE_REQUEST_MANAGER_H_
370