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