Android开发小问题集
由于安卓系統比較復雜,開發中會發中會碰見各種小問題,在此做一些記錄,只要覺得有必要就會添加進來。
1、觸屏鼠標模式和觸屏模式
開發android4.3高通400平臺時,用atmel_max 640T作為觸屏,很奇怪的問題,調好驅動后,系統運行的效果,居然跟鼠標一樣,相對運動,網上查詢資料幾乎沒有,大家都很懶啊!查到一個相關的文章,不過轉載的多,已不知道到底誰寫的了。
android4.0與2.3版本的觸摸屏驅動調試注意
? ?http://blog.sina.com.cn/s/blog_6a16c0ae0101asot.html
其實只要在你的/system/usr/idc目錄下放一個文件為 $(tp_dev_name).idc文件即可,比我的修改記錄如下
文件名為:atmel_mxt_ts.idc
內容為:touch.deviceType = touchScreen
touch.orientationAware = 1
即可由鼠標模式變為觸屏模式,如果還有X,Y方向問題,可以由廠商固件調試。
2、布局文件idc和kl命名及放在哪
如idc命名及路徑:
/system/usr/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl
/system/usr/keylayout/Vendor_XXXX_Product_XXXX.kl
/system/usr/keylayout/DEVICE_NAME.kl
/data/system/devices/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl
/data/system/devices/keylayout/Vendor_XXXX_Product_XXXX.kl
/data/system/devices/keylayout/DEVICE_NAME.kl
/system/usr/keylayout/Generic.kl
/data/system/devices/keylayout/Generic.kl
知道查找優先級順序,用戶軟件可以訪問/data,就可以做成任意按鍵映射。一般都在在system/usr相應的目錄下,keylayout文件夾放按鍵映射(linux to?Android),idc文件夾放輸入模式設置。
在源碼的frameworks\base\libs\androidfw\InputDevice.cpp的getInputDeviceConfigurationFilePathByName()函數中。
在運行的android設備的shell中執行dumpsys input會顯示出所有input設備使用的idc及kl等信息,如下
3、固件升級
一些硬件有時候要升級固件,固件放在哪,怎么命名,怎么升級?
如果你去看Android第一個init程序源碼,你會發現放在哪?
在Android源碼的system/core/init下的devices.c文件中有放在哪的定義
#define FIRMWARE_DIR1 ? "/etc/firmware"//實際上是安卓系統的system/etc的link
#define FIRMWARE_DIR2 ? "/vendor/firmware" //實際上是安卓系統的system/vendor的link
#define FIRMWARE_DIR3 ? "/firmware/image"
至于如何命名一般都是由驅動決定的,
request_firmware(const struct firmware **firmware_p, const char *name,struct device *device)就是加載用戶空間的固件到數據到內核空間,一般固件有2種:完整固件和配置。該函數的name就是文件名,可以是驅動代碼寫死的固件名,也可以是由用戶在驅動屬性節點下動態echo進去的,firmware_p是個存放固件原始數據的結構體。這個函數只是加載用戶空間到內核空間,沒有任何處理,相當于copy,至于怎么校驗,怎么升級都是由芯片廠家的協議決定的。那么何時升級?可以內核一啟動就升級,也可以在系統起來時動態升級,根據需求加載不同的固件版本,一般在系統都預留了升級節點,比如echo fw_name > update_fw或者echo cfg_name > update_cfg,也可能是echo 1 > update_fw(當然這種情況名字事先定好了)。
4、自定義編譯模塊
有時候在Android源碼加入自己的底層HAL或者apk,但是如何讓它編譯進系統。此處不得不提Android.mk中的LOCAL_MODULE_TAGS這個參數值一般有3個:eng usr optional,前2個分別代表工程模式,用戶模式鏡像才會編譯進去,而optional就比較特殊了,故名思議它需要在其他地方確認,其他地方是哪?一般就是不同的board類型,比如高通處理器msm8610,msm8974都有可能,在對應board類型的makefile中加入,那么這個類型的板子就會編譯該模塊。
舉例:比如我集成一個叫SysSetting的apk源碼到安卓系統中,其中Android.mk就用了optional,如果就這樣是永遠編譯不到系統的,還要在device\qcom\msm8610\msm8610.mk中加入PRODUCT_PACKAGES +=?SysSetting,那么在編譯msm8610的時候就會編譯SysSetting.apk到系統中。
5、自定義文件的拷貝
有時候希望系統編譯的時候,將一個地方的文件自動的copy到另一個地方(另一個地方一般都是Android系統鏡像所在目錄),比如編譯的時候將某個固件或者配置文件copy到Android系統的system某個目錄。
舉例:比如在Android源碼的device\qcom\msm8610下的msm8610.mk中加入
PRODUCT_COPY_FILES += \
? ??device/qcom/msm8610/atmel_mxt_ts.idc:system/usr/idc/atmel_mxt_ts.idc
冒號前表示待拷貝文件原路徑,冒號后面表示要被拷貝到的路徑(默認前綴是out\target\product\$(board))
6、不能傳送文件進系統
一般會出現文件系統是只讀系統的警告,這個時候如果你是eng鏡像(開發者模式),你可以在adb下直接adb remount系統就變為可寫的了,這個時候你就能用adb push,adb pull推送文件或者導出文件了;但是如果系統是usr鏡像(一般買的手機等Android設備都是usr的),adb remount命令系統都不理你,沒辦法了?好吧,你就ROOT吧,然后用RE管理器吧!
7、制作開機畫面(splash.img)
一開機就是小企鵝,但是給客戶的機器是有定制開機logo的,開始從網上找到什么第一屏制作工作,根本就不行,后來才知道在android源碼中就有制作工具。我的是高通的源碼,在msm8x12/device/qcom/common/display/logo下有個logo_gen.py,這就是工具,在這個目錄下直接運行Python?./logo_gen.py xxx.png就會在當前目錄下生成xxx.img。
參考文章 :Android——開機卡通,http://www.csdn123.com/html/exception/654/654636_654641_654638.htm
android關機動畫,http://blog.csdn.net/zeng622peng/article/details/7334018?author:zeng622peng
android定制化開關機動畫、鈴音,?http://blog.csdn.net/zeng622peng/article/details/7334016
圖片動畫階段包括
1.bootloader圖片
這個其實就是splash.img,在U-BOOT階段使用,開機圖片,開機第一屏,第一次拿到的一般都是小企鵝。
2.內核圖片
參考文章:修改Linux內核啟動圖片 http://www.linuxde.net/2013/06/13936.html
這個一般android手機不用,原理就是直接刷framebuffer,如果要用的話要開啟一些編譯選項,還要替換圖片資源,在linux源碼的drivers/video/logo下,具體見參考文章。
3.init進程啟動動畫
播放的資源在系統的目錄/initlogo.rle,
4.android系統服務啟動動畫
默認動畫就是滾動的“android”字符串,其資源在frameworks/base/core/res/assets/images;當然用戶可以自定義,一個bootanimation.zip其中打包了一個圖片文件夾part0和一個描述動畫動作屬性的文件desc.txt,把這個動畫壓縮包放在/data/local/bootanimation.zip或者/system/media/bootanimation.zip,與上面2段布局文件路徑類似,前者優先級高,可通過apk修改動畫文件,一般system目錄都不能改的。至于關機動畫和開關機聲音,具體修改見上面參考的文章。
8、內核啟動預先處理自定義cmdline字段
由于開發需要,我在LK中增加了一個camera_type字段,值為c200或者c201,便于內核啟動時加載處理不同的攝像頭驅動,那么加載驅動之前,你就得知道攝像頭型號,解決辦法就是用__setup(str,fn);這個宏函數是內核提供的,你要看其定義就知道鏈接時str放在init.data段的,fn放在init.set段,fu的類型為static int __init fn(char *str)。這樣一來實際是使.init.setup段變成一張表,Kernel在處理每一個啟動參數時,都會來查找這張表,與每一個數據項中的成員str進行比較,如果完全相同,就會調用該數據項的函數指針成員setup_func所指向的函數(該函數是在使用__setup宏定義該變量時傳入的函數參數),并將啟動參數如root=后面的內容傳給該處理函數。比如我用到的__setup("devfunc=", devfunc_setup);而在cmdline中devfunc=S1W1G4,這樣的話devfunc_setup函數得到的輸入參數為S1W1G4,這樣你的驅動就能根據devfunc=傳入的值,想怎樣就怎樣了。
9、實體MENU鍵能解開鎖屏界面及按鍵喚醒
在開發一個平板項目,測試人員反饋,按POWER鍵喚醒后,再按以下MENU鍵,鎖屏界面直接就解鎖了。然后我就在安卓代碼里grep KEY_MENU字段。在frameworks/base/core/res/res/values/config.xml中,有這么一行<bool name="config_disableMenuKeyInLockScreen">false</bool>,這個值為false時,MENU就能解鎖屏,true時禁用解鎖。另外按鍵喚醒是如何設定的呢?!在/system/usr/layout下是不是有XXX.kl,如果不是自定義的話,就用默認的Generatic.kl。仔細看key 115?? VOLUME_UP ?WAKE_DROPPED,key 114 VOLUME_DOWN WAKE_DROPPED,key 102 HOME WAKE,其中的WAKE代表這個鍵值將喚醒屏幕并且上報給應用,WAKE_DROPPED代表這個鍵將喚醒屏幕并且不上報給應用。這里有個疑問的地方,經測試如果機器進入深度休眠的話帶有WAKE*的鍵并不能喚醒,如果是淺度休眠(比如充電,播放音樂時,只要CPU沒完全停就行)時可以的,我的理解,如果某個鍵能實現像電源鍵POWER一樣能深度休眠喚醒的功能,還得在底層“注冊”這個能硬件喚醒的中斷。
10、傳感器放置布局layout
傳感器(電子羅盤,加速度計),這些都是有坐標系方向的,即使是同樣的芯片,在PCB上的方向布局不同,輸出的數據肯定會不同,那么這個方向的設定在哪里呢,開始我也不知道,后來不經意的在電子羅盤akm09911調試的時候翻了akm公司提交的git代碼,akm有個后臺算法程序,這個程序中的layout有1到8共8個值,代表8種布局方式,為什么是8種?正面反面加上每個面的pin_1有四種方向共8種,這個值一般在kernel的DTS中傳到驅動來。8種值布局描述如下圖:
11、多語言及默認啟動語言
build/target/product/full_base.mk下會繼承locales_full.mk,locales_full.mk會繼承languages_full.mk或者languages_small.mk,其中的PRODUCT_LOCALES代表的就是支持的多語言。
frameworks/base/core/jni/AndroidRuntime.cpp(其中的readLocale()函數)是Android系統運行時真正執行默認語言的代碼。該代碼優先讀取persist.sys.language和persist.sys.country(在build/target/product/core.mk中的PRODUCT_PROPERTY_OVERRIDES中設置),若沒有(property_get()為0),就讀取ro.product.locale.language和ro.product.locale.region,這2個屬性再沒有就取默認值en和US。
恢復出廠系統默認使用的是/build.prop中的ro.product.locale.language和ro.product.locale.region分表代碼語言和國家。當你設置中修改語言后,會在/data/property/下生成persist.sys.language和persist.sys.country。系統語言和區域生效策略為:優先使用persist屬性,沒有就使用ro屬性,再沒有就是en_US。
你如果有root權限,當你默認系統是zh_CN,你進行如下操作后
echo fr >?persist.sys.language
echo FR > persist.sys.country
然后重啟系統就變成法文了。
12、android.mk集成第三方java包
[plain]?view plaincopy其中 LOCAL_STATIC_JAVA_LIBRARIES :=zxing??ScannerAPI android-support-v4 android-support-v13中,依賴的包zxing只是個模塊名字,真正的包在
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES :=zxing:libs/zxing-1.6-core.jar
13、高通平臺Android崩潰抓dump并解析內核信息
有時候因為硬件問題或者編譯出的系統有問題,安卓系統就會崩潰然后黑屏,這個時候log肯定也打不出來了,無法知道哪出了問題,那么使用高通工具QPST抓dump就很方便了。
當機器黑屏崩潰后,USB鏈接插入電腦,打開QPST的eMMC Software Download軟件,中間顯示的框子中會看到一個Qualcomm USB storage dev相關的設備,等待直到安卓設備重啟,這時dump就抓取完成,dump文件抓取完一般放在電腦的
C:\Documents and Settings\All Users\Application Data\Qualcomm\QPST\Sahara\$(USB端口號)\DDRCS0.BIN
其中$(USB端口號)需要在設備管理器中查看,然后在ubuntu環境下執行命令,
"strings DDRCS0.BIN | grep -REns "<.>
.+ " > kdump.txt"這樣kdump.txt就是內核的打印
14、高通平臺差分升級/完整升級
高通平臺升級可通過無線OTA升級,也可以用sdcard升級,升級包都是一樣的,支持完整升級包(包含完整Android系統進行)和差分升級包(必須從A版本升級才能到B版本,差分包就是A版本到B版本的差異補丁包)。
OTA無線升級一般人都知道的,sdcard升級:將待升級包拷貝到sdcard,插到設備上,開機進入recovery模式,選擇到“apply update from sdcard”,按power鍵確認,進入后再選擇要升級的包,按power鍵進行升級,截圖如下:
如果有源代碼,那么完整升級包在哪,差分升級包怎么做?
高通平臺編譯后在msm8x12\out\target\product\msm8610\msm8610-ota-eng.zip就是完整升級包,大小200M左右。
差分升級包制作需要2個版本的msm8610-target_files-eng.zip,其在源碼路徑如下,
msm8x12\out\target\product\msm8610\obj\PACKAGING\target_files_intermediates\msm8610-target_files-eng.zip
制作命令:
ota_from_target_files -p ~/otatool/bin -k ~/otatool/releasekey ?-i $(pwd)/A.zip $(pwd)/B.zip $(pwd)/A_TO_B.zip
其中A和B就是上面說的2個版本的msm8610-target_files-eng.zip改名而來,當前目錄下的A_TO_B.zip就是差分升級包,大小幾M或幾十M。
15、簽名
一般當你的應用使用到system權限時,就需要簽名了,不然你連apk安裝都裝不上。
應用中manifest使用? ? android:sharedUserId="android.uid.system"
簽名時使用命令java -jar signapk.jar platform.x509.pem platform.pk8 old_name.apk new_name.apk
signapk.jar在msm8x12\out\host\linux-x86\framework目錄下
至于platform.x509.pem和platform.pk8他們存在于msm8x12\build\target\product\security目錄下
一般總共有四種簽名:
testkey普通apk簽名使用;在源碼中Android.mk中有一個LOCAL_CERTIFICATE字段未指明,默認也是testkey簽名
platform該簽名的apk使用到了系統核心功能,該進程的UID為system
shared該簽名的apk與home、contact共享數據
media該簽名的apk是media、download的一環
16、persist目錄的使用
persist目錄在我們的設備上,是persist分區,然后掛載到/persist目錄上,只有system有讀寫權限,其大小指定來自于device/qcom/msm8610/BoardConfig.mk(一般與vendor下某個地方copy出來的)指定,BOARD_PERSISTIMAGE_PARTITION_SIZE := 5242880,其他的相關分區大小及一些基地址這也有指定。大小如何定呢?msm8x12/vendor/qcom/proprietary/tools/ext4_sparse/rawprogram0.xml是各個鏡像分區的起始地址及占的大小的指定,燒寫的時候就是根據這個指示來燒寫的,比如片段如下
[plain]?view plaincopy生成persist.img的腳本來自于msm8x12\device\qcom\common\generate_extra_images.mk,實際上就是對msm8x12\out\target\product\msm8610\persist文件夾打包(如果要放置用戶文件,在你的makefile中將文件拷貝到這個目錄就行了),它還生成device tree還有如oem.img等其他鏡像。
[plain]?view plaincopy?
msm8x12\device\qcom\msm8610\init.target.rc在fs或者early-fs中進行分區的掛載。
[plain]?view plaincopy?
在msm8x12\device\qcom\common\rootdir\etc\init.qcom.rc中進行待掛載點創建和權限修改。
[plain]?view plaincopy
?
這樣你就可以在內核和android中適當的去使用你的想法了
?
17、調試gpio
gpio在kernel中再常見不過了,但它的使用也不是想怎么用就怎么用的。好多進去,不request直接就是set_gpio,那么多個地方都這樣get/set不就亂了么,也不要在驅動中直接去ioremap然后直接去操作寄存器(三星的2440教程中好多就這么教的),這樣也會造成混亂,大多情況在machine中都設置好了gpio_chip,我們要做的就是翻看數據手冊要使用的GPIO_pin號以及要配置成的功能,然后使用標準GPIO的API去使用即可。使用也有套路,先request再使用(set/irq等),不再使用了就free掉。使用request加上請求標簽有利于調試,比如在我的msm8x12的內核中使用如下代碼:
[cpp]?view plaincopy那么在內核輸入cat? /sys/kernel/debug/gpio得到的信息如下
由上圖的紅色框可見,正如代碼設置一樣,標簽為"akm09911_rest",輸出高。
GPIO相關的常用API如下:
[cpp]?view plaincopy18、快速獲取linux/android的config
adb pull /proc/config.gz f:\ 用adb工具將內核配置文件放到WINDOWS的F盤,然后加壓就能看見config了。
總結
以上是生活随笔為你收集整理的Android开发小问题集的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: USB有时adb shell连不上设备
- 下一篇: 高通8x12平台开机画面制作工具