當前位置:首頁 » 安卓系統 » androidhardware

androidhardware

發布時間: 2023-01-20 17:24:51

⑴ Android圖形系統系統篇之HWC

HWC (hwcomposer)是Android中進行窗口( Layer )合成和顯示的HAL層模塊,其實現是特定於設備的,而且通常由顯示設備製造商 (OEM)完成,為 SurfaceFlinger 服務提供硬體支持。

SurfaceFlinger 可以使用 OpenGL ES 合成 Layer ,這需要佔用並消耗GPU資源。大多數GPU都沒有針對圖層合成進行優化,當 SurfaceFlinger 通過GPU合成圖層時,應用程序無法使用GPU進行自己的渲染。而 HWC 通過硬體設備進行圖層合成,可以減輕GPU的合成壓力。

顯示設備的能力千差萬別,很難直接用API表示硬體設備支持合成的 Layer 數量, Layer 是否可以進行旋轉和混合模式操作,以及對圖層定位和硬體合成的限制等。因此HWC描述上述信息的流程是這樣的:

雖然每個顯示設備的能力不同,但是官方要求每個 HWC 硬體模塊都應該支持以下能力:

但是並非所有情況下 HWC 都比GPU更高效,例如:當屏幕上沒有任何變化時,尤其是疊加層有透明像素並且需要進行圖層透明像素混合時。在這種情況下, HWC 可以要求部分或者全部疊加層都進行GPU合成,然後 HWC 持有合成的結果Buffer,如果 SurfaceFlinger 要求合成相同的疊加圖層列表, HWC 可以直接顯示之前合成的結果Buffer,這有助於提高待機設備的電池壽命。

HWC 也提供了 VSync 事件,用於管理渲染和圖層合成時機,後續文章會進行介紹。

Android7.0提供了HWC和HWC2兩個版本,默認使用HWC,但是手機廠商也可以選擇HWC2,如下所示:

SurfaceFlinger 通過 HWComposer 使用 HWC 硬體能力, HWComposer 構造函數通過 loadHwcMole 方法載入HWC模塊,並封裝成 HWC2::Device 結構,如下所示:

上述通過 hw_get_mole 方法(hardware\libhardware\hardware.c)載入 hwcomposer 模塊,此模塊由硬體廠商提供實現,例如:hardware\libhardware\moles\hwcomposer\hwcomposer.cpp是 hwcomposer 模塊基於HWC1的default實現,對應的共享庫是 hwcomposer.default.so ;hardware\qcom\display\msm8994\libhwcomposer\hwc.cpp是高通MSM8994基於HWC1的實現,對應的共享庫是 hwcomposer.msm8994.so 。
如果是基於HWC2協議實現,則需要實現hwcomposer2.h中定義的 hwc2_device_t 介面,例如: class VendorComposer : public hwc2_device_t 。Android7.0的 hwcomposer 模塊默認都是基於HWC1協議實現的。
每個HAL層模塊實現都要定義一個 HAL_MODULE_INFO_SYM 數據結構,並且該結構的第一個欄位必須是 hw_mole_t ,下面是高通MSM8994 hwcomposer 模塊的定義:

frameworks\native\services\surfaceflinger\DisplayHardware\HWC2.h主要定義了以下三個結構體:

它們是對 HWC 硬體模塊的進一步封裝,方便進行調用。 HWC2::Device 持有一個 hwc2_device_t ,用於連接硬體設備,它包含了很多HWC2_PFN開頭的函數指針變數,這些函數指針定義在 hwcomposer2.h 。
在 HWC2::Device 的構造函數中,會通過 Device::loadFunctionPointers -> loadFunctionPointer(FunctionDescriptor desc, PFN& outPFN) -> hwc2_device_t::getFunction 的調用鏈從硬體設備中獲取具體的函數指針實現。關鍵模板函數如下所示:

這些函數指針主要分為三類:

通過上述函數指針可以與 hwc2_device_t 表示的硬體合成模塊進行交互。三類指針分別選取了一個示例:

可以通過類圖,直觀感受下引用關系。

HWC2::Device 構造函數除了完成獲取函數指針實現以外,還會通過 Device::registerCallbacks 向硬體設備注冊三個 Display 的回調:熱插拔,刷新和VSync信號,如下所示:

總結一下, HWC2::Device 構造函數向硬體設備注冊三個 Display 回調:熱插拔,刷新和VSync信號。當 HWC2::Device 收到這些回調時,會通過監聽器向外回調到對應的HWComposer函數: HWComposer::hotplug / HWComposer::invalidate / HWComposer::vsync 。HWComposer再通過這些信息驅動對應工作,後續文章進行介紹。

上文提到 HWC2::Device 中的函數指針是hardware\libhardware\include\hardware\hwcomposer2.h中定義的,除此之外,該頭文件還定義了一些重要的結構體,這里介紹兩個比較重要的:

DisplayType 表示顯示屏類型,上面注釋已經介紹,重點看下Layer合成類型:

那麼一個 Layer 的合成方式是怎麼確定的那?大致流程如下所示:

本篇文章只是簡單介紹了HWC模塊的相關類: HWComposer 、 HWC2::Device 、 HWC2::Display 和 HWC2::Layer ,以及它們的關系。此外,還著重介紹了Layer的合成方式和合成流程。後續文章會更加全面的介紹 SurfaceFlinger 是如何通過HWC模塊完成Layer合成和上屏的(虛擬屏幕是到離屏緩沖區)。

⑵ HAL 硬體抽象層

綁定式 HAL 。以 HAL 介面定義語言 (HIDL) 或 Android 介面定義語言 (AIDL) 表示的 HAL。這些 HAL 取代了早期 Android 版本中使用的傳統 HAL 和舊版 HAL。在綁定式 HAL 中,Android 框架和 HAL 之間通過 Binder 進程間通信 (IPC) 調用進行通信。所有在推出時即搭載了 Android 8.0 或後續版本的設備都必須只支持綁定式 HAL。

直通式 HAL 。以 HIDL 封裝的傳統 HAL 或 舊版 HAL 。這些 HAL 封裝了現有的 HAL,可在綁定模式和 Same-Process(直通)模式下使用。升級到 Android 8.0 的設備可以使用直通式 HAL。

Android 要求所有 Android 設備(無論是搭載 Android O 的設備還是升級到 Android O 的設備)上的下列 HAL 均為綁定式:

[email protected]。取代 Android 8.0 中已不存在的 fingerprintd。

[email protected]。Android 8.0 中的新 HAL。

[email protected]。此 HAL 提供的原始介面可能無法繼續使用,並且已更改。因此,mpstate_board 必須在指定的設備上重新實現(這是一個可選的 HAL)。

[email protected]。在 Android 8.0 中,此 HAL 必須為綁定式,因此無需在可信進程和不可信進程之間分享文件描述符。

[email protected]。取代由存活於自身進程中的 rild 提供的介面。

[email protected]。Android 8.0 中的新 HAL。

[email protected]。Android 8.0 中的新 HAL,可取代此前載入到 system_server 中的舊版 WLAN HAL 庫。

[email protected]。在現有 wpa_supplicant 進程之上的 HIDL 介面。

注意 :Android 提供的以下 HIDL 介面將一律在綁定模式下使用:android.frameworks.*、android.system.* 和 android.hidl.*(不包括下文所述的 [email protected])。

Android 要求所有 Android 設備(無論是搭載 Android O 的設備還是升級到 Android O 的設備)上的下列 HAL 均在直通模式下使用:

[email protected]。將內存映射到其所屬的進程中。

[email protected]。在同一進程中傳遞項(等同於 openGL)。

上方未列出的所有 HAL 在搭載 Android O 的設備上都必須為綁定式。

⑶ Android P 系統穩定性問題分析方法總結

Android系統最開始是為手機設計的,在機頂盒,電視,帶屏音箱等大屏上運行後,晶元廠家做些適配,產品廠家也會做系統客制化,有時候還要適配第三方應用..等待
這種適配容易引人系統的穩定性問題,系統穩定性對於用戶體驗至關重要,很多問題也都比較類似,android系統對系統性能,穩定性分析工具也比較多,下面根據工作中遇到的問題做個總結。

從表現來看有: 死機重啟, 自動關機, 無法開機,凍屏,黑屏以及閃退, 無響應等情況;

從技術層面來劃分無外乎兩大類: 長時間無法執行完成(Timeout) 以及異常崩潰(crash). 主要分類如下:

ANR(Application Not responding),是指普通app進程超過一定時間沒有執行完,系統會彈出應用無響應對話框. 如果
該進程運行在system進程, 更准確的來說,應該是(System Not Responding, SNR)

ANR產生的原因可能是各種各樣的,但常見的原因可以分為:

1.logcat日誌
2.trace文件(保存在/data/anr/traces.txt)
從logcat里可以看到死鎖的列印
從traces.txt可以看到線程的函數調用棧

10-16 00:50:10 820 907 E ActivityManager: ANR in com.android.systemui, time=130090695
10-16 00:50:10 820 907 E ActivityManager: Reason: Broadcast of Intent { act=android.intent.action.TIME_TICK flg=0x50000114 (has extras) }
10-16 00:50:10 820 907 E ActivityManager: Load: 30.4 / 22.34 / 19.94
10-16 00:50:10 820 907 E ActivityManager: Android time :[2015-10-16 00:50:05.76] [130191,266]
10-16 00:50:10 820 907 E ActivityManager: CPU usage from 6753ms to -4ms ago:
10-16 00:50:10 820 907 E ActivityManager: 47% 320/netd: 3.1% user + 44% kernel / faults: 14886 minor 3 major
10-16 00:50:10 820 907 E ActivityManager: 15% 10007/com.sohu.sohuvideo: 2.8% user + 12% kernel / faults: 1144 minor
10-16 00:50:10 820 907 E ActivityManager: 13% 10654/hif_thread: 0% user + 13% kernel
10-16 00:50:10 820 907 E ActivityManager: 11% 175/mmcqd/0: 0% user + 11% kernel
10-16 00:50:10 820 907 E ActivityManager: 5.1% 12165/app_process: 1.6% user + 3.5% kernel / faults: 9703 minor 540 major
10-16 00:50:10 820 907 E ActivityManager: 3.3% 29533/com.android.systemui: 2.6% user + 0.7% kernel / faults: 8402 minor 343 major
......
10-16 00:50:10 820 907 E ActivityManager: +0% 12832/cat: 0% user + 0% kernel
10-16 00:50:10 820 907 E ActivityManager: +0% 13211/zygote64: 0% user + 0% kernel
10-16 00:50:10 820 907 E ActivityManager: 87% TOTAL: 3% user + 18% kernel + 64% iowait + 0.5% softirq

發生ANR的時間 00:50:10 ,可以從這個時間點之前的日誌中,還原ANR出現時系統的運行狀態
發生ANR的進程 com.android.system.ui
發生ANR的原因 Reason關鍵字表明了ANR的原因是處理TIME_TICK廣播消息超時
CPU負載 Load關鍵字表明了最近1分鍾、5分鍾、15分鍾內的CPU負載分別是30.4、22.3、19.94.CPU最近1分鍾的負載最具參考價值,因為ANR的超時限制基本都是1分鍾以內, 這可以近似的理解為CPU最近1分鍾平均有30.4個任務要處理,這個負載值是比較高的
CPU使用統計時間段 CPU usage from XX to XX ago關鍵字表明了這是在ANR發生之前一段時間內的CPU統計,類似的還有CPU usage from XX to XX after關鍵字,表明是ANR發生之後一段時間內的CPU統計
各進程的CPU使用率
以com.android.systemui進程的CPU使用率為例,它包含以下信息:
總的CPU使用率: 3.3%,其中systemui進程在用戶態的CPU使用率是2.6%,在內核態的使用率是0.7%
缺頁次數fault:8402 minor表示高速緩存中的缺頁次數,343 major表示內存的缺頁次數。minor可以理解為進程在做內存訪問,major可以理解為進程在做IO操作。 當前minor和major值都是比較高的,從側面反映了發生ANR之前,systemui進程有有較多的內存訪問操作,引發的IO次數也會較多
CPU使用匯總 TOTAL關鍵字表明了CPU使用的匯總,87%是總的CPU使用率,其中有一項iowait表明CPU在等待IO的時間,佔到64%,說明發生ANR以前,有大量的IO操作。app_process、 system_server, com.android.systemui這幾個進程的major值都比較大,說明這些進程的IO操作較為頻繁,從而拉升了整個iowait的時間

traces.txt 如下
----- pid 29533 at 2015-10-16 00:48:29 -----
Cmd line: com.android.systemui
DALVIK THREADS (54):
"main" prio=5 tid=1 Blocked
| group="main" sCount=1 dsCount=0 obj=0x75bd5818 self=0x7f8549a000
| sysTid=29533 nice=0 cgrp=bg_non_interactive sched=0/0 handle=0x7f894bbe58
| state=S schedstat=( 289080040422 93461978317 904874 ) utm=20599 stm=8309 core=0 HZ=100
| stack=0x7fdffda000-0x7fdffdc000 stackSize=8MB
| held mutexes=
at com.mediatek.anrappmanager.MessageLogger.println(SourceFile:77)

Android系統中,有硬體WatchDog用於定時檢測關鍵硬體是否正常工作,類似地,在framework層有一個軟體WatchDog用於定期檢測關鍵系統服務是否發生死鎖事件。
watchdog 每過30s 檢測一次, 如果要監控的線程30s 後沒有響應,系統會mp出此進程堆棧,如果超過60s 沒有相應,會觸發watchdog,並重啟系統
10:57:23.718 579 1308 W Watchdog: *** WATCHDOG KILLING SYSTEM PROCESS: Blocked in monitor com.android.server.am.ActivityManagerService on foreground thread (android.fg), Blocked in handler on main thread (main), Blocked in handler on ActivityManager (ActivityManager)
10:57:23.725 579 1308 W Watchdog: android.fg annotated stack trace:
10:57:23.726 579 1308 W Watchdog: at com.android.server.am.ActivityManagerService.monitor(ActivityManagerService.java:26271)
10:57:23.727 579 1308 W Watchdog: - waiting to lock <0x0bb47e39> (a com.android.server.am.ActivityManagerService)
10:57:23.727 579 1308 W Watchdog: at com.android.server.Watchdog DeliveryTracker.alarmTimedOut(AlarmManagerService.java:4151)
10:57:23.733 579 1308 W Watchdog: - waiting to lock <0x00aaee38> (a java.lang.Object)
......
10:57:23.736 579 1308 W Watchdog: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:838)
10:57:23.739 579 1308 W Watchdog: ActivityManager annotated stack trace:
10:57:23.740 579 1308 W Watchdog: at com.android.server.am.ActivityStack$ActivityStackHandler.handleMessage(ActivityStack.java:405)
10:57:23.740 579 1308 W Watchdog: - waiting to lock <0x0bb47e39> (a com.android.server.am.ActivityManagerService)
10:57:23.740 579 1308 W Watchdog: at android.os.Handler.dispatchMessage(Handler.java:106)
10:57:23.741 579 1308 W Watchdog: *** GOODBYE!
分析:
提示 ActivityManagerService的android.fg,main,ActivityManager 線程Block了,但logcat里只能看到
android.fg等待0x0bb47e39 鎖,main 等待0x00aaee38鎖,ActivityManager等待0x0bb47e39鎖,無法進一步分析,需要看traces.txt
Cmd line: system_server
......
"main" prio=5 tid=1 Blocked

當出現應用閃退,可以從兩個方面查看:
1、是否應用崩潰:
可以通過logcat –s AndroidRuntime DEBUG過濾日誌,查看應用奔潰的具體堆棧信息。
其中AndroidRuntime的TAG列印java層信息,DEBUG的TAG列印native層的信息。
2、是否被lowmemorykiller殺掉:
可以通過 logcat –s lowmemorykiller 過濾日誌,注意adj 0是代表前台進程。例如:
03-08 04:16:58.084 310 310 I lowmemorykiller: Killing'com.google.android.tvlauncher' (2520), uid 10007, adj 0
發生這種情況,需要mpsys meminfo 查看當前內存狀態,是否有進程內存泄漏,導致系統內存不夠,出現前台進程被殺,造成閃退。

測試過程中,經常遇到屏幕閃爍的現象,需要排除是OSD層閃爍,還是video層閃爍。
1、先通過android原生方法:screencap截圖, screenrecord 錄制視頻,這里都是截取的OSD層,查看是否有閃屏現象。
2、OSD沒有問題,就需要從更底層的顯示模塊分析,一般需要晶元廠家提供debug手段,不同晶元廠家方案不一樣。
3, 有時候輸出不穩定,hdmi/mipi信號干擾,輸出頻率異常等也會導致閃屏,這種情況需要硬體協助分析。
如果OSD層也閃爍,則需從系統和應用層面分析。如曾遇到在開機向導界面,有個應用不斷被喚起,導致走開機向導時出現連續閃灰屏的現象。

黑屏分UI黑屏,視頻播放黑屏但UI正常等,2種場景

1、screencap截屏,排查OSD層圖形是否正常,
2、如果OSD圖形正常,需要排查顯示輸出模塊是否異常。
3、電視機裡面屏顯是單獨控制,如果屏參配置錯誤會導致整改黑屏。
OSD異常,需要排查頂層activity是否黑屏,window是否有異常等.

1,排查視頻圖層或者window是否創建成功。
2,排查解碼是否有異常,不同的應用youtube,netflix,iptv解碼方式不一樣,需要具體問題具體分析。

如下,ActivityManager因為空對象引用而掛掉,導致system_server重啟
*** [FATAL EXCEPTION IN SYSTEM PROCESS: ActivityHanager [
^ava.lang.NullPointerException: Attempt to invoke virtual method 'void co®.android.internal.os.KernelSingleUidTimeReader.iBarkDataAsStale(boolean)' on a null object reference
at com.android.internal.os.BatteryStatsIiaplSConstants.(BatteryStatslnpl.java:13355)
at com.android.internal.os.BatteryStatsInplSConstants.upddteConstants(BatteryStatsImpl.java:13330)
at com.android.internal-o-batteryStatslMpl$Constants-onChange(BatteryStatsInpl-java:13316)
at android.database.Contentobserver.onChange(ContentObserver.java:145)
解決方法:修復空指針

DEBUG : pid: 296, tid: 1721, name: Binder:296_4 >>> /system/bin/surfaceflinger <<<
DEBUG : signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr ------
DEBUG : Abort message: 'status.cpp:149] Failed HIDL return status not checked: Status(EXTRANSACTIONFAILED):
DEBUG : r0 00000000 rl 000006b9
DEBUG : C4 00000128 r5 000006b9
r2 00000006 r3 a5c5d620
r6 a235d60c r7 0000010c
DEAD_OB3ECT:
DEBUG : r8 00000019 r9 0000015d
DEBUG : ip a6ablbec sp a235d5f8
rlO a568f090 rll a620dce9
Ir a5be901d pc a5be0da2
/system/lib/libc.so (abort+62)
/system/lib/libbase.so (android::base::DefaultAborter(char const )+6)
backtrace:
/system/lib/libsurfaceflinger.so
/system/lib/libsurfaceflinger.so
/system/lib/libsurfaceflinger.so
/system/lib/libsurfaceflinger.so
/system/lib/libbase.so (android::base::LogMessage::~LogMessage()+502)
/system/lib/libhidlbase.so (android::hardware::details::return_status::~return_status()+184)
(android::Hwc2::impl::Composer::getActiveConfig(unsigned long long, unsigned int
)+56)
(HWC2::Display::getActiveConfig(std::_1::shared_ptr<HWC2::Display::Config const>*) const+38)
(android::HWComposer::getActiveConfig(int) const+64)
(android::SurfaceFlinger::resyncToHardwareVsync(bool)+64)
可以根據backtrace來進行定位異常崩潰的地方。Android P上, backtrace使用Java上下文來顯示,省去使用addr2line來轉換的一個過程,方便調試分析問題。但是實際場景中,
有些native進程崩潰只有pc地址,而無函數信息,或者需要定位到具體的某個文件某個函數,則可藉助堆棧分析工具addr2line。
addr2line:根據堆棧定位具體函數和文件
addr2line -e libsurfaceflinger.so -f 00071a09
addr2line -e libsurfaceflinger.so -f 00071a09
_
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:1229
需注意兩點:
1、需用帶debug信息的LINK目錄裡面的so庫,機頂盒上的so庫是無法定位的:
out/target/proct/xx/obj/SHARED_LIBRARIES/libsurfaceflinger_intermediates/LINKED/libsurfaceflinger.so
或者:out/target/proct/xx/symbols/system/lib/libsurfaceflinger.so
2、定位的文件,必現和機器上出現問題的版本一致,否則定位不準確
debuggerd:列印當前進程實時堆棧:debuggerd –b pid

主要可以分為以下3類
1)Data abort
Unable to handle kernel NULL pointer dereference at virtual address...
Unable to handle kernel paging request at virtual address...
Unhandled fault...at...
Unhandled prefetch abort...at...
2)BUG/BUG_ON
Oops - BUG...
例如:
Out of memory and no killable processes...
rbus timeout...
...
PS:WARN_ON只mp stacks,kernel還是正常
3)bad mode
Oops - bad mode...
日誌列印:
〃錯誤類型原因
[214.962667] 08:14:19.315 (2)-0488 Unable to handle kernel paging request at virtual address 6b6b6cl7
[214.973889] 08:14:19.326 (2)-0488 addr:6b6b6c17 pgd = d0824000
[214.980132] [6b6b6c17J •pgd=O000eO0e
〃Oopsttl誤碼序號
[214.983865] 08:14:19.336 (2)-0488 Internal error: Oops: 805 [#1] PREEMPT SMP ARM
[214.9914S3] Moles linked in: 8192eu ufsd(PO) jnl(O) fusion(O)
〃發生也錯誤的CPU序號
(215.001878] 08:14:19.354 (2)-0488 CPU: 2 PID: 488 Comm: system_server Tainted: P 4.4.3+ #113
(2)-0488 Hardware name: rtd284x
[215.011865] 08:14:19.364
〃當前PC指針 98:14:19.377 (2)-0488 PC is at mutex_unlo<k+0xc/0x38
(21S.024846] 08:14:19.383 (2)-0488 LR is at storage_pm_event+0xb4/0xe8
(21S.031026]
//Registers 08:14:19.390 (2)-0488 :[<ceb78ffc>] Ir : [<C0542034>] psr: 200f0013
I 215.037644] sp : ccf79e38 ip : eceoeeee fp : 9b34648c
I 215.037644]
08:14:19.404 (2)-0488 rlO: 00000080 r9 :Cl8b3864 r8 : oeeeeeoe
215.051370]
215.058692] 08:14:19.411 (2)-0488 P7 : C1293a98 P6 :C1293940 r5 : C1293940 r4 :C1293a80
21S.067345]
[ 215.076014] 08:14:19.420 (2)-0488 r3 : 00000033 r2 :00000000 ri : 000^000 re :6b6b6c07
[ 215.085307]
08:14:19.428 (2)-0488 Flags: nzCv IRQs on FIQs on Mode SVC 32 ISA ARM Segment user
08:14:19.438 (2)-0488 Control: 10c5383d Table: 1082406a DAC: 00000055
//Process.不 ,定是該process的錯誤,只是發生錯誤時,剛好在運行該process
[215.093168]
//Stacks 08:14:19.446 (2)-0488 Process syste«i_server (pid: 488, stack limit = 0xccf78218)

(21S.101827] 08:14:19.454 (2)-0488 Stack: 0xccf79e38 (Oxccf79d7。 to 0xccf7a08Q) - par(0xcf796d4)

---[ end trace 45d55384id6a0974 ]--- Kernel panic not syncing: Fatal exception
[217.359794] 08:14:21.712 (0)-0488
解決方案: kernel異常一般找晶元原廠協助分析。

系統卡頓時,一般先分三步走:
1、查看當前系統的CPU,IO等參數,輸入top、iotop命令: (如:iotop -s io -m 9)
如果有異常飆高的進程,kill掉後會發現系統恢復正常。
之前項目上遇到過某些U盤IO性能比較差,媒體中心又在後台掃描媒體問題,導致系統各種卡頓,io wait時間比較長。
2、系統進程卡住,觸發Watchdog:ps –A |grep system_server,一般而言,system_server正常的進程號是200多,如果發現進程號變成幾千,則可能出現重啟,結合tombstone和 /data/anr下的trace文件分析重啟原因
3、當前應用出現卡頓,造成ANR。輸入logcat | grep ANR,如果有ANR列印,再去/data/anr下面查看相應進程的traces文件
有時在應用裡面操作卡頓,按鍵響應延遲,但是卻沒有生成ANR,此時如果退出該應用(如果無法退出,在抓取足夠信息的情況下,可以串口直接kill掉卡頓的應用),則一切正常,可能是應用自身實現問題,或者調用了其它介面導致(例如曾遇到應用調用了中間件、mediaplayer某些介面導致操作嚴重卡頓,按鍵響應延遲),這種情況則需應用和相應介面的實現者去排查。

系統完全卡死,一般分三種情況
1,串口無響應,大概率kernel panic,
2,串口日誌狂輸出,把系統堵塞, 優化日誌輸出,關注關閉後壓測。
3,Input系統完全堵塞,導致任何輸入都無響應。

⑷ Android進階——你所知道的Camera2和你所不知道的Camera2完全解析

一切源於在項目過程中的一個Bug:我的需求是在MainActivity 實現自動預覽,也可以點擊跳到簽到SignedActivity去實現拍照簽到,第一次進入界面的時候都是正常的,但是有時候返回來的時候預覽失敗,即從MainActivity跳轉到SignedActivity偶爾預覽失敗和從SignedActivity返回MainActivity偶爾失敗,都是報(CAMERA_IN_USE)ERRO=1的錯誤,奇怪的是的的確確做了完全釋放操作,加上以前用的更多的是Camera api 對於Camer2 的機制沒有完整去研究過,一下子懵了,於是乎先去找了Stack Overflow,查到一個解決方案是:"我棄用了新API,換回舊API",ORZ,找了其他的也沒有答案,可是我不服呀,我就把官方的文檔全部啃了一遍,於是乎便有了以下的理解,我想如果你不懂得怎麼使用Camera2的話,這篇絕對值得你去閱讀,你會發現Camera2 並非像大多數說得那樣使用起來很復雜。

全新的android.hardware.Camera2 。Android 5.0對拍照API進行了全新的設計,新增了全新設計的Camera 2 API,這些API不僅大幅提高了Android系統拍照的功能,還能支持RAW照片輸出,甚至允許程序調整相機的對焦模式、曝光模式、快門等。

在Camera2 架構在核心參與類角色有: CameraManager CameraDevice CameraCharacteristics CameraRequest與CameraRequest.Builder CameraCaptureSession 以及 CaptureResult

位於android.hardware.camera2.CameraManager下,也是Android 21(5.0)添加的,和其他系統服務一樣通過 Context.getSystemService(CameraManager.class ) 或者 Context.getSystemService(Context.CAMERA_SERVICE) 來完成初始化,主要用於管理系統攝像頭:

CameraDevice是Camera2中抽象出來的一個對象,直接與系統硬體攝像頭相聯系。因為不可能所有的攝像頭都會支持高級功能(即攝像頭功能可被分為limit 和full 兩個級別),當攝像頭處於limited 級別時候,此時Camera2和早期的Camera功能差不多,除此之外在Camera2架構中,CameraDevice還承擔其他兩項重要任務:

正如前面所說, 系統向攝像頭發送 Capture 請求,而攝像頭會返回 CameraMetadata,這一切都是在由對應的CameraDevice創建的CameraCaptureSession 會話完成 ,當程序需要預覽、拍照、再次預覽時,都需要先通過會話。(A configured capture session for a CameraDevice , used for capturing images from the camera or reprocessing images captured from the camera in the same session previously.A CameraCaptureSession is created by providing a set of target output surfaces to createCaptureSession , or by providing an InputConfiguration and a set of target output surfaces to for a reprocessable capture session . Once created, the session is active until a new session is created by the camera device, or the camera device is closed.)CameraCaptureSession一旦被創建,直到對應的CameraDevice關閉才會死掉。雖然CameraCaptureSession會話用於從攝像頭中捕獲圖像,但是只有同一個會話才能再次從同一攝像頭中捕獲圖像。另外, 創建會話是一項耗時的非同步操作,可能需要幾百毫秒 ,因為它需要配置相機設備的內部管道並分配內存緩沖區以將圖像發送到所需的目標,因而createCaptureSession和會將隨時可用的CameraCaptureSession發送到提供的監聽器的onConfigured回調中。如果 無法完成配置,則觸發onConfigureFailed回調 ,並且會話將不會變為活動狀態。最後需要注意的是,如果 攝像頭設備創建了一個新的會話,那麼上一個會話是被關閉的,並且會回調與其關聯的onClosed ,如果不處理好,當會話關閉之後再次調用會話的對應方法那麼所有方法將會跑出IllegalStateException異常。關閉的會話清除任何重復的請求(和調用了stopRepeating()方法類似),但是在新創建的會話接管並重新配置攝像機設備之前,關閉的會話仍然會正常完成所有正在進行的捕獲請求。簡而言之,在Camera2中CameraCaptureSession承擔很重要的角色:

描述Cameradevice屬性的對象,可以使用CameraManager通過getCameraCharacteristics(String cameraId)進行查詢。

CameraRequest代表了一次捕獲請求, 而CameraRequest.Builder用於描述捕獲圖片的各種參數設置,包含捕獲硬體(感測器,鏡頭,快閃記憶體),對焦模式、曝光模式,處理流水線,控制演算法和輸出緩沖區的配置。 ,然後傳遞到對應的會話中進行設置, CameraRequest.Builder則負責生成CameraRequest對象 。當程序調用setRepeatingRequest()方法進行預覽時,或調用capture()方法進行拍照時,都需要傳入CameraRequest參數。CameraRequest可以通過CameraRequest.Builder來進行初始化,通過調用createCaptureRequest來獲得。

CaptureRequest描述是從圖像感測器捕獲單個圖像的結果的子集的對象。(CaptureResults are proced by a CameraDevice after processing a CaptureRequest)當CaptureRequest被處理之後由CameraDevice生成。

CameraManager 處於頂層管理位置負責 檢測獲取所有攝像頭及其特性 傳入指定的CameraDevice.StateCallback回調打開指定攝像頭 CameraDevice 是負責管理抽象對象,包括 監聽Camera 的狀態回調CameraDevice.StateCallback 創建CameraCaptureSession和CameraRequest CameraCaptureSession 用於描述一次圖像捕獲操作,主要負責 監聽自己會話的狀態回調CameraCaptureSession.StateCallback CameraCaptureSession.CaptureCallback捕獲回調 ,還有 發送處理CameraRequest CameraRequest 則可以看成是一個"JavaBean"的作用用於描述希望什麼樣的配置來處理這次請求;最後三個回調用於監聽對應的狀態。

CameraManager 處於頂層管理位置負責檢測 檢測獲取所有攝像頭並設置輸出參數,傳入指定的CameraDevice.StateCallback回調,然後打開指定攝像頭,並觸發CameraDevice.StateCallback中的onOpened方法,並在onOpened方法里開始通過調用創建預覽會話, ,CameraDevice負責創建請求 CameraCharacteristics CameraRequest與CameraRequest.Builder CameraCaptureSession 以及 CaptureResult 則可以看成是一個JavaBean的作用用於描述以什麼樣的配置來處理這次請求。

Camera2Helper類只是簡單的封裝了下,為了讓Camera2的初始化和Activity 高度分離,這個類只是Demo 階段部分有待優化,另外結合我具體的業務,對於圖片大小有限制,所以我都是默認採用采樣壓縮率方式對圖片進行壓縮

熱點內容
汽車配置物品怎麼處理 發布:2025-05-20 07:47:23 瀏覽:225
怎麼修改華為wifi密碼 發布:2025-05-20 07:45:12 瀏覽:41
php函數遞歸 發布:2025-05-20 07:39:36 瀏覽:780
登陸認證失敗請檢查伺服器地址 發布:2025-05-20 07:06:55 瀏覽:831
無限分類實現php 發布:2025-05-20 06:57:40 瀏覽:681
數據結構c語言版嚴蔚敏李冬梅 發布:2025-05-20 06:55:05 瀏覽:449
iphone快捷訪問 發布:2025-05-20 06:55:05 瀏覽:929
如何加密硬碟分區 發布:2025-05-20 06:52:29 瀏覽:363
反編譯gd 發布:2025-05-20 06:52:23 瀏覽:838
java源碼知乎 發布:2025-05-20 06:47:59 瀏覽:483