歷時四年,給Google提交的Android Framework Bug終于被Fixed了

歷時四年,Google終于修復了一個我發現的Android Framework Bug

2014年在做一個Android終端設備開發過程中,發現了一個Android Framework層的Bug,給Google提交了issue和解決方案,和外界傳言一致Google一般不太在意個人開發者提交的issue,直到2017年12月,再次提交了issue,在幾輪溝通無果下,忍不住噴了Google幾句后,終于該issue被轉交給了Android development team處理,又經過快三個月的時間收到了下面的答復:

這里寫圖片描述
google issues:https://issuetracker.google.com/issues/70016687

issue背景:

在對我們自己研發的一款Android終端設備進行Camera拍照壓力測試時,發現當拍照張數達到數萬張時,出現OOM,導致系統崩潰。

issue分析解決過程:

該項目為開發一款Android工業終端設備,采用TI芯片方案,由于芯片方案商支持不夠完善(主要TI被高通打的放棄了移動端芯片市場),Camera的HAL層需要我們自己移植適配。

分析思路:

首先看下Android系統架構圖中中Camera功能模塊的分布情況,從App層->Framework->HAL->Kernel一路下來:

這里寫圖片描述

(圖片取自https://blog.csdn.net/asd1031/article/details/53699867)

  • 首先懷疑測試app自身存在內存問題。
  • Android application Framework,libraries層和jni相關模塊是經過Google大量驗證的模塊,出現問題的概率比較小,暫時排除。
  • 懷疑HAL層移植問題。
懷疑1:測試app問題

壓力測試app由測試同學開發提供的,該app每隔3s觸發一次拍照操作,并對拍攝的照片進行清理,以達到拍攝10萬張照片的測試目的。基于以上分析,為了排除測試app問題,采用Android原生Camera app進行壓力測試,編寫monkey測試腳本,觸發原生Camera app拍照,進行壓力測試。(此處遇到的問題是:如何實現對照片的清理工作,直接觸發shell環境下rm操作,并不會清除Android內部文件緩存索引,拍攝幾千張照片后仍然會導致存儲空間用盡,解決此問題也耗費了點時間,不過不是本文的重點,此處不做展開)

結果:通過原生Camera app進行測試后,仍然出現內存泄漏,此處基本排除測試app的問題。

懷疑2:HAl層

基于之前的分析,我們把懷疑對象聚集在我們自己集成的Android HAL層,在分析之前,簡單描述下Android Camera拍照的流程:Linux Kernel提供標準的v4l2接口,供上層(此處即為HAL)獲取圖像原始數據,HAL層拿到圖像數據進行編碼(一般為jpeg),回調給Camera service。其中Linux Kernel下Camera驅動和HAL適配層一般由芯片廠商提供,其余部分由Linux Kernel和Android系統官方維護,開發。

這樣對HAL的測試分為三步:

  • 驗證芯片廠商的Camera驅動是否存在問題。
  • 驗證HAL層圖像數據捕獲流程是否存在問題。
  • 驗證圖像編碼流程是否存在問題。
Camera驅動

Android系統是基于Linux Kernel開發,支持標準的v4l2接口,只需要編寫一個簡單的基于v4l2的視頻捕獲程序就可以驗證camera驅動的問題,此處測試驗證沒有內存泄漏,排查驅動問題。

HAL層視頻捕獲流程

測試思路非常明確,難點在于要把芯片提供商的HAL層源碼中進行視頻捕獲功能的模塊剝離出來,單獨進行壓力測試。(由于原廠提供的HAL層代碼,耦合比較嚴重,在不影響內部流程,結構的情況下,要找到適合的切面mock一些數據接口,才好進行有效的測試。)

經過以上的工作,進行了壓力測試,系統未出現內存泄漏,基本排除HAL層捕獲流程。

HAL層圖像編碼流程

繼續對圖像編碼部分剝離,進行壓力測試,發現內存泄漏,基本定位大概的泄漏位置,不過由于Android整個編碼過程也進行層層的封裝,泄漏位置還需要繼續細致的定位,這樣經過層層的細化,像剝洋蔥一樣一層層mock輸入數據,最終定位在Android系統層的jpeg編碼處理中:(frameworks/base/core/jni/android/graphics/YuvToJpegEncoder.cpp)

關于Android的jpeg編碼:Android系統jpeg編碼支持硬編碼和軟編碼,如果芯片集成了jpeg硬件編碼模塊,會優先選擇硬編碼,而如果沒有該模塊,會采用軟件的jpeg編碼進行處理。

Android采用的軟件編碼庫是業內知名的libjpeg庫,而正是對這個庫的使用出了問題:

bool YuvToJpegEncoder::encode(SkWStream* stream, void* inYuv, int width,int height, int* offsets, int jpegQuality) {jpeg_compress_struct    cinfo;skjpeg_error_mgr        sk_err;skjpeg_destination_mgr  sk_wstream(stream);cinfo.err = jpeg_std_error(&sk_err);sk_err.error_exit = skjpeg_error_exit;if (setjmp(sk_err.fJmpBuf)) {return false;}jpeg_create_compress(&cinfo);cinfo.dest = &sk_wstream;setJpegCompressStruct(&cinfo, width, height, jpegQuality);jpeg_start_compress(&cinfo, TRUE);compress(&cinfo, (uint8_t*) inYuv, offsets);jpeg_finish_compress(&cinfo);return true;
}

坑就在上面這個接口函數中:

熟悉libjpeg的同學可能會注意到,上面的接口在調用完jpeg_finish_compress()后,沒有調用jpeg_destroy_compress(),這個接口是釋放壓縮工作過程中所申請的資源,就是代碼中的cinfo結構,該結構只占十幾個字節的內存, 這樣就導致了每拍攝一張照片,就泄漏一個cinfo的內存,當拍照數量達到萬級時,才會有所察覺。

對這種數據流的控制,pipeline方式是比較好的方案,因為可以明確輸入輸出,這樣非常方便通過偽造輸入數據對各個模塊進行單獨的壓力測試,最難控制的就是“洋蔥”式的包裹調用,要像“剝洋蔥”一樣一層層的剝離,找準切面十分麻煩。

這個bug是否影響到你的Android手機

七成的概率下你的手機應該不會有這個問題,即時有這個問題你也很難發現這個問題,因為上面講到android系統有兩種編碼方式選擇,優先使用硬件編碼模塊,如果沒有硬件編碼模塊,才會使用軟編碼的方式,而目前大部分中高端的芯片方案都集成了硬件模塊,只有在少數低端芯片上才會使用軟編碼的方式,并且即使你的手機沒有硬編碼模塊,用的軟編碼,也很難遇見這個問題,因為對于普通用戶,持續拍攝上萬張照片是不太可能的,第一受限于手機的存儲空間(一萬張照片,至少要30G的空間),第二即使能拍攝上萬張照片,但要保持手機一直工作不重啟也還是比較苦難的(總會死個機啥的)。

哈哈,這么一說發現這個bug其實是一個不會發生的bug了!!!不過我們之前的產品,定位于工業級別,對圖像采集有比較高的要求,所以制定了10萬張照片的測試標準,也就讓我發現了這個不會影響到大部分人的bug。

最后再吐槽下Google

改bug我在2014年就已經提交了issue,不過沒持續關注,過了幾個月被莫名其妙的關閉了,當時沒有在意,不過當Android 6.0,7.0版本出來時,我都看了下這個bug,一直存在,所以在去年(2017年)12月份又提了一個issue,Google方面的處理人仍然各種推諉扯皮,最后我沒忍住噴了幾句,這次Google方面回復會轉給開發團隊處理,終于在今年(2018年)給出了fixed的結論。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/449907.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/449907.shtml
英文地址,請注明出處:http://en.pswp.cn/news/449907.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux ping命令、Linux kill命令、Linux logname命令、 Linux logout命令

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 Linux ping命令用于檢測主機。 執行ping指令會使用ICMP傳輸協議,發出要求回應的信息,若遠端主機的網絡功能沒有…

前端布局神器display:flex

2009年,W3C提出了一種新的方案--Flex布局,可以簡便、完整、響應式地實現各種頁面布局。目前已得到所有現在瀏覽器的支持。 flex瀏覽器支持一、Flex布局是什么? Flex是Flexible Box的縮寫,翻譯成中文就是“彈性盒子”,用…

bind簡單轉發實驗

2019獨角獸企業重金招聘Python工程師標準>>> *主配置文件內容// [rootlocalhost /]# cat /etc/named.conf // // named.conf // // Provided by Red Hat bind package to configure the ISC BIND named(8) DNS // server as a caching only nameserver (as a local…

數據結構:塊狀鏈表

一、概述 有時候我們需要設計這樣一種數據結構:它能快速在要求位置插入或者刪除一段數據。先考慮兩種簡單的數據結構:數組和鏈表。數組的優點是能夠在O(1)的時間內找到所要執行操作的位置,但其缺點是無論是插入或刪除都要移動之后的所有數據&…

記賬本開發小計(四)

今天處理的是記賬本小軟件中的查詢功能,由于賬目的要求就是準確性,所以對于記賬本程序來說,模糊查詢并不適用,所以在這里只能是按照指定的條件來進行查詢所以我做的事按照時間進行查詢,為了方便進行處理,這…

Linux ps命令、Linux top命令

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 Linux ps命令用于顯示當前進程 (process) 的狀態。 語法 ps [options] [--help][options] [--help] 參數: ps 的參數非常…

Prime Distance POJ - 2689 線性篩

一個數 $n$ 必有一個不超過 $\sqrt n$ 的質因子。 打表處理出 $1$ 到 $\sqrt n$ 的質因子后去篩掉屬于 $L$ 到 $R$ 區間的素數即可。 Code: #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const…

給定a和n,計算a+aa+aaa+a...a(n個a)的和(大數據處理)

題目描述&#xff1a;給定a和n&#xff0c;計算aaaaaaa...a(n個a)的和。 輸入&#xff1a;測試數據有多組&#xff0c;輸入a&#xff0c;n&#xff08;1<a<9,1<n<100&#xff09;。 輸出&#xff1a;對于每組輸入,請輸出結果。 樣例輸入&#xff1a;1 10 樣例輸出&…

ssh和rsh的區別、Linux rsh命令

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 ssh 和 rsh的區別主要有: 1 安全級別不同, 主要是ssh的密碼等都是加密傳輸,而且還有密鑰認證的機制, rsh明文傳輸. 而且沒有密鑰的機制.…

Java并發編程(多線程)中的相關概念

眾所周知&#xff0c;在Java的知識體系中&#xff0c;并發編程是非常重要的一環&#xff0c;也是面試中必問的題&#xff0c;一個好的Java程序員是必須對并發編程這塊有所了解的。 并發必須知道的概念 在深入學習并發編程之前&#xff0c;我們需要了解幾個基本的概念。 同步和異…

4、容器虛擬化網絡概述

Docker 網絡 Docker 的網絡實現其實就是利用了 Linux 上的網絡名稱空間和虛擬網絡設備&#xff08;特別是 veth pair&#xff09;。 Linux 網絡命名空間&#xff1a;https://www.jianshu.com/p/369e50201bce Linux虛擬網絡設備之veth&#xff1a; https://segmentfault.com/a/1…

Linux whoami命令、Linux su命令、Linux w命令

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Linux whoami命令用于顯示自身用戶名稱。 顯示自身的用戶名稱&#xff0c;本指令相當于執行"id -un"指令。 語法 whoami […

Weekly 10

Algorithm 1.Remove Element What 移除數組中的指定元素,返回處理后的長度sum,并且數組前sum長度的元素為處理后的元素,不用額外數組&#xff0c;O(1)。How 用快慢指針,快指針遍歷,遇到不等于指定元素的替換掉慢指針,然后慢指針前進一位即可。Key Codesclass Solution {public …

大數據計算:如何僅用1.5KB內存為十億對象計數

摘要&#xff1a;AddThis的數據分析副總監Matt Abrams在High Scalability上發表了一篇文章&#xff0c;介紹了他們公司如何應對大數據。Matt Abrams表示&#xff0c;AddThis僅僅用了1.5KB內存的內存就計算了十億個不同的對象&#xff0c;這與他們所使用的計算方法分不開的。 A…

C#關鍵字的個人理解與注釋

C#關鍵字注釋&#xff1a;abstract&#xff1a;抽象as&#xff1a;類型轉換&#xff08;返回轉換結果&#xff09;base&#xff1a;基類bool&#xff1a;布爾類型break&#xff1a;條件中斷語句byte&#xff1a;字節case&#xff1a;條件語句catch&#xff1a;異常捕獲后執行ch…

Linux declare命令、Linux tail 命令

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Linux declare命令用于聲明 shell 變量。 declare為shell指令&#xff0c;在第一種語法中可用來聲明變量并設置變量的屬性([rix]即為變…

詳解Nagios配置文件的邏輯關系

1.主配置文件/usr/local/nagios/etc/nagios.cfg a.定義了用戶和組 b.定義了某些具體參數 c.定義了配置文件和可以存放配置文件的文件夾 d.通過開頭的#號去注釋選項以達到關閉配置的效果 e.更改配置后&#xff0c;可以通過命令 /usr/local/nagios/bin/nagios –v /usr/local/na…

10 步讓你成為更優秀的程序員

這篇文章要介紹的&#xff0c;是我作為專業程序員這些年來學到的能真正提高我的代碼質量和整體工作效率的10件事情。 1. 永遠不要復制代碼 不惜任何代價避免重復的代碼。如果一個常用的代碼片段出現在了程序中的幾個不同地方&#xff0c;重構它&#xff0c;把它放到一個自己的函…

《流浪地球》 電影全集

《流浪地球》 電影全集 《流浪地球》是由郭帆導演&#xff0c;吳京特別出演&#xff0c;屈楚蕭、李光潔、吳孟達等人主演的科幻片《流浪地球》宣布定檔2019大年初一。同時&#xff0c;影片發布了一款定檔預告片&#xff0c;預告片開頭傳來一段廣播聲音&#xff1a;“太陽急速老…

kotlin之plus、copyOf、reverse、forEach、filter、map、reduce、fold等函數解釋和使用

kotlin之::函數調用、plus&#xff08;增加元素&#xff09;、copyOf&#xff08;復制數組&#xff09;、reverse&#xff08;翻轉數組&#xff09;、forEach&#xff08;遍歷數組&#xff09;、filter&#xff08;過濾數組&#xff09;、map函數操作及擴展、reduce函數、fold函…