• 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 #include "chre/pal/ble.h"
18 
19 #include "chre/util/memory.h"
20 #include "chre/util/unique_ptr.h"
21 
22 #include <future>
23 #include <thread>
24 
25 /**
26  * A simulated implementation of the BLE PAL for the linux platform.
27  */
28 namespace {
29 const struct chrePalSystemApi *gSystemApi = nullptr;
30 const struct chrePalBleCallbacks *gCallbacks = nullptr;
31 
32 std::thread gBleStartScanThread;
33 std::thread gBleStopScanThread;
34 std::promise<void> gStopAdvertisingEvents;
35 
36 bool gBleEnabled = false;
37 
scanModeToInterval(chreBleScanMode mode)38 std::chrono::milliseconds scanModeToInterval(chreBleScanMode mode) {
39   std::chrono::milliseconds interval(1000);
40   switch (mode) {
41     case CHRE_BLE_SCAN_MODE_BACKGROUND:
42       interval = std::chrono::milliseconds(2000);
43       break;
44     case CHRE_BLE_SCAN_MODE_FOREGROUND:
45       interval = std::chrono::milliseconds(1000);
46       break;
47     case CHRE_BLE_SCAN_MODE_AGGRESSIVE:
48       interval = std::chrono::milliseconds(500);
49       break;
50   }
51   return interval;
52 }
53 
startScan(chreBleScanMode mode)54 void startScan(chreBleScanMode mode) {
55   gCallbacks->scanStatusChangeCallback(true, CHRE_ERROR_NONE);
56   std::future<void> signal = gStopAdvertisingEvents.get_future();
57   while (signal.wait_for(scanModeToInterval(mode)) ==
58          std::future_status::timeout) {
59     auto event = chre::MakeUniqueZeroFill<struct chreBleAdvertisementEvent>();
60     auto report = chre::MakeUniqueZeroFill<struct chreBleAdvertisingReport>();
61     uint8_t *data =
62         static_cast<uint8_t *>(chre::memoryAlloc(sizeof(uint8_t) * 2));
63     data[0] = 0x01;
64     data[1] = 0x16;
65     report->data = data;
66     report->dataLength = 2;
67     event->reports = report.release();
68     event->numReports = 1;
69     gCallbacks->advertisingEventCallback(event.release());
70   }
71 }
72 
stopScan()73 void stopScan() {
74   gCallbacks->scanStatusChangeCallback(false, CHRE_ERROR_NONE);
75 }
76 
stopThreads()77 void stopThreads() {
78   if (gBleStartScanThread.joinable()) {
79     gStopAdvertisingEvents.set_value();
80     gBleStartScanThread.join();
81   }
82   if (gBleStopScanThread.joinable()) {
83     gBleStopScanThread.join();
84   }
85 }
86 
chrePalBleGetCapabilities()87 uint32_t chrePalBleGetCapabilities() {
88   return CHRE_BLE_CAPABILITIES_SCAN |
89          CHRE_BLE_CAPABILITIES_SCAN_RESULT_BATCHING |
90          CHRE_BLE_CAPABILITIES_SCAN_FILTER_BEST_EFFORT;
91 }
92 
chrePalBleGetFilterCapabilities()93 uint32_t chrePalBleGetFilterCapabilities() {
94   return CHRE_BLE_FILTER_CAPABILITIES_RSSI |
95          CHRE_BLE_FILTER_CAPABILITIES_SERVICE_DATA;
96 }
97 
chrePalBleStartScan(chreBleScanMode mode,uint32_t,const struct chreBleScanFilter *)98 bool chrePalBleStartScan(chreBleScanMode mode, uint32_t /* reportDelayMs */,
99                          const struct chreBleScanFilter * /* filter */) {
100   stopThreads();
101   gStopAdvertisingEvents = std::promise<void>();
102   gBleStartScanThread = std::thread(startScan, mode);
103   gBleEnabled = true;
104   return true;
105 }
106 
chrePalBleStopScan()107 bool chrePalBleStopScan() {
108   stopThreads();
109   gBleStopScanThread = std::thread(stopScan);
110   gBleEnabled = false;
111   return true;
112 }
113 
chrePalBleReleaseAdvertisingEvent(struct chreBleAdvertisementEvent * event)114 void chrePalBleReleaseAdvertisingEvent(
115     struct chreBleAdvertisementEvent *event) {
116   for (size_t i = 0; i < event->numReports; i++) {
117     chre::memoryFree(
118         const_cast<chreBleAdvertisingReport *>(&(event->reports[i])));
119   }
120   chre::memoryFree(event);
121 }
122 
chrePalBleApiClose()123 void chrePalBleApiClose() {
124   stopThreads();
125 }
126 
chrePalBleApiOpen(const struct chrePalSystemApi * systemApi,const struct chrePalBleCallbacks * callbacks)127 bool chrePalBleApiOpen(const struct chrePalSystemApi *systemApi,
128                        const struct chrePalBleCallbacks *callbacks) {
129   chrePalBleApiClose();
130 
131   bool success = false;
132   if (systemApi != nullptr && callbacks != nullptr) {
133     gSystemApi = systemApi;
134     gCallbacks = callbacks;
135     success = true;
136   }
137 
138   return success;
139 }
140 
141 }  // anonymous namespace
142 
chrePalIsBleEnabled()143 bool chrePalIsBleEnabled() {
144   return gBleEnabled;
145 }
146 
chrePalBleGetApi(uint32_t requestedApiVersion)147 const struct chrePalBleApi *chrePalBleGetApi(uint32_t requestedApiVersion) {
148   static const struct chrePalBleApi kApi = {
149       .moduleVersion = CHRE_PAL_BLE_API_CURRENT_VERSION,
150       .open = chrePalBleApiOpen,
151       .close = chrePalBleApiClose,
152       .getCapabilities = chrePalBleGetCapabilities,
153       .getFilterCapabilities = chrePalBleGetFilterCapabilities,
154       .startScan = chrePalBleStartScan,
155       .stopScan = chrePalBleStopScan,
156       .releaseAdvertisingEvent = chrePalBleReleaseAdvertisingEvent,
157   };
158 
159   if (!CHRE_PAL_VERSIONS_ARE_COMPATIBLE(kApi.moduleVersion,
160                                         requestedApiVersion)) {
161     return nullptr;
162   } else {
163     return &kApi;
164   }
165 }
166