Android sensor 系統框架 (二)

来源:http://www.cnblogs.com/hackfun/archive/2017/08/10/7341106.html
-Advertisement-
Play Games

連載上一篇http://www.cnblogs.com/hackfun/p/7327320.html (D) 如何載入訪問.so庫 在前一篇博客http://www.cnblogs.com/hackfun/p/7327320.html中,知道如何生成了一個HAL的.so庫,在這裡將分析如何載入這個H ...


連載上一篇http://www.cnblogs.com/hackfun/p/7327320.html

(D) 如何載入訪問.so庫

    在前一篇博客http://www.cnblogs.com/hackfun/p/7327320.html中,知道如何生成了
一個HAL的.so庫,在這裡將分析如何載入這個HAL,如何再次封裝以適合多客戶端訪問的情況。
    實際上,系統是通過SENSORS_HARDWARE_MODULE_ID找到對應的.so庫的。因為該庫中的
struct sensors_module_t結構體包含了一個唯一的ID就是SENSORS_HARDWARE_MODULE_ID,
最終的目的也是要獲得這個結構體。通過查找這個ID得知是在以下文件中載入設個so的。
文件路徑是:

frameworks/native/services/sensorservice/SensorDevice.cpp

先看代碼註釋,最後再總結。

SensorDevice.cpp

  1 SensorDevice::SensorDevice()                                                                                   
  2     :  mSensorDevice(0),                                                                                       
  3        mSensorModule(0)  
  4 {
  5     /* 獲取SENSORS_HARDWARE_MODULE_ID對應的模塊(.so庫) */
  6     status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,                                                   
  7              (hw_module_t const**)&mSensorModule);     
  8     ......
  9     /* 打開模塊 */
 10     err = sensors_open_1(&mSensorModule->common, &mSensorDevice);
 11     ......
 12     /* 這個模塊列表中有多少個sensor */
 13     ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
 14     ......
 15     /* 設置容器大小 */
 16     mActivationCount.setCapacity(count);
 17     ......
 18     /* 激活/使能模塊中所有sensors */
 19     for (size_t i=0 ; i<size_t(count) ; i++) {
 20         /* 添加sensor到容器 */
 21         mActivationCount.add(list[i].handle, model);
 22         /* 激活/使能sensors */
 23         mSensorDevice->activate(
 24                     reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
 25                     list[i].handle, 0);
 26     } 
 27 }
 28 
 29 ......
 30 
 31 ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
 32     ......
 33     do {
 34         /* 輪詢接收所有sensors上報的事件,填入sensors_event_t的buffer */
 35         c = mSensorDevice->poll(reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice),
 36                                 buffer, count);
 37     } while (c == -EINTR);
 38     return c;
 39  }
 40 
 41 status_t SensorDevice::activate(void* ident, int handle, int enabled)                                          
 42 {
 43     ......
 44     /* 初始化handle(sensor類型, 如ID_A)對應的info */
 45     status_t SensorDevice::activate(void* ident, int handle, int enabled);
 46     ......
 47     if (enabled) {
 48         /* 如果ident客戶端不存在 */
 49         if (isClientDisabledLocked(ident)) {                                                                   
 50             return INVALID_OPERATION;                                                                          
 51         }                                                                                                      
 52         
 53         /* 該客戶端存在 */                                                                                                   
 54         if (info.batchParams.indexOfKey(ident) >= 0) {
 55             /* 只有一個客戶端,第一個連接的 */                                                         
 56             if (info.numActiveClients() == 1) {                                                                  
 57                 // This is the first connection, we need to activate the underlying h/w sensor.                  
 58                 actuateHardware = true; 
 59             }                                                                         
 60         } 
 61     } else {
 62         /* ident移除成功(disable) */
 63         if (info.removeBatchParamsForIdent(ident) >= 0) {
 64             /* 如果這是最後一個移除(disable)的客戶端 */
 65             if (info.numActiveClients() == 0) {
 66                 // This is the last connection, we need to de-activate the underlying h/w sensor.
 67                 actuateHardware = true;
 68             } else {
 69                 
 70             }
 71         }
 72         /* 如果被disable,則直接返回 */
 73         if (isClientDisabledLocked(ident)) {
 74             return NO_ERROR;
 75         }
 76     }
 77     
 78     /* 如果是第一次激活(enable)或最後一個禁止(disable)sensor的
 79      * 在這種情況下就根據handle(sensor類型)和enabled值,調用activate
 80      * 來enable/disable對應的sensor
 81      */
 82     if (actuateHardware) {
 83         err = mSensorDevice->activate(
 84               reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice), handle, enabled); 
 85     }
 86 }
 87 
 88 status_t SensorDevice::batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
 89                              int64_t maxBatchReportLatencyNs) {
 90     ......
 91     /* 初始化handle(sensor類型, 如ID_A)對應的info */
 92     Info& info(mActivationCount.editValueFor(handle));
 93     
 94     /* 如果這個ident(key)不存在 */
 95     if (info.batchParams.indexOfKey(ident) < 0) {
 96         BatchParams params(flags, samplingPeriodNs, maxBatchReportLatencyNs);
 97         /* 則添加添加這個(ident, params) (key-value)對 */
 98         info.batchParams.add(ident, params);
 99     } else {
100         /* 如果存在,則更新這個ident */
101         // A batch has already been called with this ident. Update the batch parameters.
102         info.setBatchParamsForIdent(ident, flags, samplingPeriodNs, maxBatchReportLatencyNs);
103     }
104     
105     BatchParams prevBestBatchParams = info.bestBatchParams;
106     /* 為這個sensor找到所有最小的採樣頻率和事件上報最大延遲 */
107     // Find the minimum of all timeouts and batch_rates for this sensor.
108     info.selectBatchParams();
109     
110     /* 如果最小的採樣頻率和事件上報最大延遲相對於上一次發生了變化 */
111     // If the min period or min timeout has changed since the last batch call, call batch.
112     if (prevBestBatchParams != info.bestBatchParams) {
113         ......
114         err = mSensorDevice->batch(mSensorDevice, handle, info.bestBatchParams.flags,
115                                    info.bestBatchParams.batchDelay,
116                                    info.bestBatchParams.batchTimeout);
117     
118 119     ......
120 }
121 
122 /*
123     關於mSensorDevice->batch(SensorDevice::batch()基於它封裝一層,相當於他的實例)的作用,
124     相關的說明是:
125 
126     Sets a sensor’s parameters, including sampling frequency and maximum
127     report latency. This function can be called while the sensor is
128     activated, in which case it must not cause any sensor measurements to
129     be lost: transitioning from one sampling rate to the other cannot cause
130     lost events, nor can transitioning from a high maximum report latency to
131     a low maximum report latency.
132     See the Batching sensor results page for details:
133     http://source.android.com/devices/sensors/batching.html
134     
135     意思是這是一個設置每個sensor的一些參數,包括採樣頻率,最大事件上報延遲,這個
136     函數可以在sensor被激活/使能時被調用,在這種情況下不能造成任何的sensor的測量
137     據丟失,如從一個採樣率轉換到另一個採樣率的時候不能造成事件丟失,或從一個最大
138     上報延遲轉換到另一個較低的最大上報延遲都不能造成事件丟失。
139     
140     也就是說每個感測器都應該有一個batch,這個batch是負責調整採樣頻率和最大上報事
141     件延遲的參數,例如,在sensor激活的時候,可以調整一次這些參數。   
142 */    
143 
144 status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs)
145 {
146     ......
147     Info& info( mActivationCount.editValueFor(handle));
148     
149     /* 如果存在的sensor不是工作在continuous模式,那麼setDelay()應該返回一個錯誤
150      * 在batch模式下調用setDelay()是沒用的
151      */
152     // If the underlying sensor is NOT in continuous mode, setDelay() should return an error.
153     // Calling setDelay() in batch mode is an invalid operation.
154     if (info.bestBatchParams.batchTimeout != 0) {
155         return INVALID_OPERATION;
156     }
157     
158     /* 到了這裡,說明sensor工作的continuous模式 */ 
159     /* 獲得這個客戶端對應的index */
160     ssize_t index = info.batchParams.indexOfKey(ident);
161     /* 根據這個index找到對應的batchParams值 */
162     BatchParams& params = info.batchParams.editValueAt(index);
163     /* 設置這個batchParams對應的batchDelay採樣頻率 */
164     params.batchDelay = samplingPeriodNs;
165     /* 保存batchParams到bestBatchParams */
166     info.selectBatchParams();
167     /* 實際上是調用了sensors_poll_context_t::setDelay */
168     return mSensorDevice->setDelay(reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
169                                    handle, info.bestBatchParams.batchDelay);
170 }
171 
172 
173 status_t SensorDevice::flush(void* ident, int handle) {
174     ......
175     /* 刷數據 */
176     return mSensorDevice->flush(mSensorDevice, handle);
177 }
178 
179 
180 bool SensorDevice::isClientDisabled(void* ident) {
181     /* 上鎖 */
182     Mutex::Autolock _l(mLock);
183     /* 返回客戶端狀態 */
184     return isClientDisabledLocked(ident);
185 }   
186 
187 
188 bool SensorDevice::isClientDisabledLocked(void* ident) {
189     /* 獲取ident (key-value對)對應的索引,索引存在(>=0),返回true,
190      * 否則,返回false。即用於判斷該客戶端是否disable
191      */
192     return mDisabledClients.indexOf(ident) >= 0;
193 }
194 
195 
196 void SensorDevice::enableAllSensors() {
197     for (size_t i = 0; i< mActivationCount.size(); ++i) {
198         Info& info = mActivationCount.editValueAt(i);
199         ......
200         const int sensor_handle = mActivationCount.keyAt(i);
201         ......
202         /* 激活sensor_handle sensor */
203         err = mSensorDevice->activate(
204                 reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
205                 sensor_handle, 1);
206         /* 設置相應的採樣頻率 */
207         err = mSensorDevice->setDelay(
208                 reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
209                 sensor_handle, info.bestBatchParams.batchDelay);        
210     }
211 }
212 
213 
214 void SensorDevice::disableAllSensors() {
215    ......
216    /* 逐個sensor disable */
217    for (size_t i = 0; i< mActivationCount.size(); ++i) {
218         /* 獲得一個sensor對應的info */
219         const Info& info = mActivationCount.valueAt(i);
220         // Check if this sensor has been activated previously and disable it.
221         if (info.batchParams.size() > 0) {
222            /* 獲得sensor類型 */
223            const int sensor_handle = mActivationCount.keyAt(i);
224            ......
225            /* 禁止該sensor */
226            mSensorDevice->activate(
227                    reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice),
228                    sensor_handle, 0); 
229            // Add all the connections that were registered for this sensor to the disabled
230            // clients list.
231            /* 禁止所有註冊了這個sensor的client */
232            for (size_t j = 0; j < info.batchParams.size(); ++j) {
233                mDisabledClients.add(info.batchParams.keyAt(j));
234            }   
235         }   
236     }   
237 }
238 
239 
240 status_t SensorDevice::injectSensorData(const sensors_event_t *injected_sensor_event) {
241     ......
242     /* 增加一個sensor到mSensorDevice */
243     return mSensorDevice->inject_sensor_data(mSensorDevice, injected_sensor_event);
244 }
245 
246 
247 status_t SensorDevice::setMode(uint32_t mode) {
248     ......
249     /* 操作模式設置 */
250     return mSensorModule->set_operation_mode(mode);
251 }
252 
253 int SensorDevice::Info::numActiveClients() {
254     SensorDevice& device(SensorDevice::getInstance());
255     
256     /* 檢查batchParams容器中所有ident是否被disable
257      * 返回未被disable(即active/enable)的個數
258      */
259     for (size_t i = 0; i < batchParams.size(); ++i) {
260         /* 該ident未被disable */
261         if (!device.isClientDisabledLocked(batchParams.keyAt(i))) {
262             ++num;
263         }
264     }
265     
266     return num;
267 }
268 
269 
270 status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int flags,                                    
271                                                     int64_t samplingPeriodNs,                                  
272                                                     int64_t maxBatchReportLatencyNs) {  
273 {
274     /* 從容器中找到indent(key)對應的index */
275     ssize_t index = batchParams.indexOfKey(ident); 
276     ......
277     /* 從容器中找到index索引對應的BatchParams
278      * 修改該BatchParams的採樣頻率和事件上報
279      * 最大延遲
280      */
281     BatchParams& params = batchParams.editValueAt(index);                                                      
282     params.flags = flags; 
283     /* 設置採樣頻率 */                                                                                     
284     params.batchDelay = samplingPeriodNs; 
285     /* 事件上報最大延遲 */                                                                     
286     params.batchTimeout = maxBatchReportLatencyNs;  
287     ......
288 }
289 
290 
291 void SensorDevice::Info::selectBatchParams() {
292     BatchParams bestParams(0, -1, -1);
293     SensorDevice& device(SensorDevice::getInstance());
294     /* 設置容器中所有未被disable(active/enable)的元素(ident)的值 */
295     for (size_t i = 0; i < batchParams.size(); ++i) {
296         /* 如果該元素(ident)被disable,則繼續查找下一個元素(ident) */
297         if (device.isClientDisabledLocked(batchParams.keyAt(i))) continue;
298         /* 獲得該索引對應的元素的value (batchParams)值 */
299         BatchParams params = batchParams.valueAt(i);
300         if (bestParams.batchDelay == -1 || params.batchDelay < bestParams.batchDelay) {
301             /* 如果最新設置採樣頻率的值小於上一次的,採用最新的值 */
302             bestParams.batchDelay = params.batchDelay;
303         }
304         if (bestParams.batchTimeout == -1 || params.batchTimeout < bestParams.batchTimeout) {
305             /* 如果最新事件上報最大延遲的值小於上一次的,採用最新的值 */ 
306             bestParams.batchTimeout = params.batchTimeout;
307         }
308     }
309     
310     /*
311      * 這些參數只能往小調
312      */
313      
314     /* 保存到bestBatchParams */
315     bestBatchParams = bestParams;
316 }

    到這裡,基本代碼已經分析完了,簡單總結一下這個文件主要做了什麼工作:
1. 載入.so庫,sensors_module_t結構體中獲得相關參數
2. 在.so庫的基礎上,再一次封裝activate,setDelay,pollEvents等方法,
    目的是為了支持更多的客戶端(client)訪問。如:struct Info結構體,
    每一個sensor都對應有這樣一個結構體,該結構體中有兩比較重要的成員
    是BatchParams bestBatchParams 和
    KeyedVector<void*, BatchParams> batchParams。每一個client對應著
    一個batchParams,每個client對應的都會傳入一個參數到void *,與
    BatchParams關聯,從BatchParams中選擇合適的參數保存到bestBatchParams
   中。

3. 這個模塊中在.so庫的基礎上增加了一些方法,但這裡是連載前一篇博客
    http://www.cnblogs.com/hackfun/p/7327320.html, 在前一篇博客中沒
    有實現一些flush,batch,inject_sensor_data的方法,因為
    struct sensors_poll_device_t結構體重沒有提供這些方法,而
    struct sensors_poll_device_1結構體才提供這些方法,因此在下一篇
    關於sensor service的博客中暫且忽略這些方法是使用


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 蘋果手機的尺寸:5s及以下都是320px 6是375px寬度 6plus是414px寬度 常用的安卓尺寸:320、360、480、540、640、720... 在真實項目中,設計師給我們的設計稿一般都是:640*960 / 640*1136 / 750*1334 響應式佈局的解決方案: 1)、流式布 ...
  • 第一次寫博客,寫的不好勿怪!!!此博客是通過d3 v4 實現一個餅狀圖,並添加了折線標註;代碼如下let self = this;var tooltip = d3.select("body").append("div").attr("class", "toolTip");let ele = docu ...
  • 1.什麼是SVG? SVG 指可伸縮矢量圖形 (Scalable Vector Graphics) SVG 用來定義用於網路的基於矢量的圖形 SVG 使用 XML 格式定義圖形 SVG 圖像在放大或改變尺寸的情況下其圖形質量不會有所損失 2.簡單的 SVG 實例 一個簡單的SVG圖形例子: 這裡是S ...
  • 初級前端一枚 下麵代碼是在圖片上創建圖像映射 自己整理了下 做個筆記 希望也可以幫助後來學習的朋友!<map name="planetmap"> <area shape="rect" coords="0,0,82,126" alt="Sun" href="sun.htm"> <area shape= ...
  • JavaScript 純粹對象 1、定義: 通過 "{}" 或者 "new Object" 創建的對象,像new Date(),new String()都不是純粹對象 2、檢測 示例代碼(使用jQuery) ...
  • 現在的項目中都在用VUE 以及react 等MVC, MVVM 框架。 丟棄了原始的JQ 。不可能為了個$.ajax();而把JQ引進來吧。 在vue1的開發中 提供了 vueResouce, vue2 出來後明確提出了不在更新vueResouce 而提供axios 的方法。 在react 的開發中 ...
  • 昨天總結的JavaScript中的數組Array方法 數組的迭代方法 ES5中為數組定義了5個迭代方法。每個方法都要接收兩個參數:要在每一項上面運行的函數和(可選的)運行該函數的作用域對象 影響this的值。 傳入方法中的函數會介紹三個參數:1.數組項的值 2. 該項在數組的中位值 3. 數組對象本 ...
  • 最近使用AndroidStudio的最新ndk編譯方式cMake來編譯底層cpp文件,由於之前沒有接觸過cMake語法,先附上官方學習文檔地址:https://developer.android.com/ndk/guides/cmake.html,以及友情中文翻譯網址:https://www.zyb ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...