因爲安卓系統比較複雜,開發中會發中會遇見各類小問題,在此作一些記錄,只要以爲有必要就會添加進來。html
開發android4.3高通400平臺時,用atmel_max 640T做爲觸屏,很奇怪的問題,調好驅動後,系統運行的效果,竟然跟鼠標同樣,相對運動,網上查詢資料幾乎沒有,你們都很懶啊!查到一個相關的文章,不過轉載的多,已不知道到底誰寫的了。java
http://blog.sina.com.cn/s/blog_6a16c0ae0101asot.htmlnode
其實只要在你的/system/usr/idc目錄下放一個文件爲 $(tp_dev_name).idc文件便可,比個人修改記錄以下linux
文件名爲:atmel_mxt_ts.idcandroid
內容爲:touch.deviceType = touchScreen
touch.orientationAware = 1git
便可由鼠標模式變爲觸屏模式,若是還有X,Y方向問題,能夠由廠商固件調試。算法
如idc命名及路徑:shell
/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
ubuntu
知道查找優先級順序,用戶軟件能夠訪問/data,就能夠作成任意按鍵映射。通常都在在system/usr相應的目錄下,keylayout文件夾放按鍵映射(linux to Android),idc文件夾放輸入模式設置。app
在源碼的frameworks\base\libs\androidfw\InputDevice.cpp的getInputDeviceConfigurationFilePathByName()函數中。
在運行的android設備的shell中執行dumpsys input會顯示出全部input設備使用的idc及kl等信息,以下
一些硬件有時候要升級固件,固件放在哪,怎麼命名,怎麼升級?
若是你去看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(固然這種狀況名字事先定好了)。
有時候在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到系統中。
有時候但願系統編譯的時候,將一個地方的文件自動的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))
通常會出現文件系統是隻讀系統的警告,這個時候若是你是eng鏡像(開發者模式),你能夠在adb下直接adb remount系統就變爲可寫的了,這個時候你就能用adb push,adb pull推送文件或者導出文件了;可是若是系統是usr鏡像(通常買的手機等Android設備都是usr的),adb remount命令系統都不理你,沒辦法了?好吧,你就ROOT吧,而後用RE管理器吧!
一開機就是小企鵝,可是給客戶的機器是有定製開機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目錄都不能改的。至於關機動畫和開關機聲音,具體修改見上面參考的文章。
因爲開發須要,我在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=傳入的值,想怎樣就怎樣了。
在開發一個平板項目,測試人員反饋,按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同樣能深度休眠喚醒的功能,還得在底層「註冊」這個能硬件喚醒的中斷。
傳感器(電子羅盤,加速度計),這些都是有座標系方向的,即便是一樣的芯片,在PCB上的方向佈局不一樣,輸出的數據確定會不一樣,那麼這個方向的設定在哪裏呢,開始我也不知道,後來不經意的在電子羅盤akm09911調試的時候翻了akm公司提交的git代碼,akm有個後臺算法程序,這個程序中的layout有1到8共8個值,表明8種佈局方式,爲何是8種?正面反面加上每一個面的pin_1有四種方向共8種,這個值通常在kernel的DTS中傳到驅動來。8種值佈局描述以下圖:
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
而後重啓系統就變成法文了。
其中 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
有時候由於硬件問題或者編譯出的系統有問題,安卓系統就會崩潰而後黑屏,這個時候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就是內核的打印
高通平臺升級可經過無線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。
通常當你的應用使用到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的一環
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是各個鏡像分區的起始地址及佔的大小的指定,燒寫的時候就是根據這個指示來燒寫的,好比片斷以下
生成persist.img的腳原本自於msm8x12\device\qcom\common\generate_extra_images.mk,實際上就是對msm8x12\out\target\product\msm8610\persist文件夾打包(若是要放置用戶文件,在你的makefile中將文件拷貝到這個目錄就好了),它還生成device tree還有如oem.img等其餘鏡像。
msm8x12\device\qcom\msm8610\init.target.rc在fs或者early-fs中進行分區的掛載。
在msm8x12\device\qcom\common\rootdir\etc\init.qcom.rc中進行待掛載點建立和權限修改。
這樣你就能夠在內核和android中適當的去使用你的想法了
gpio在kernel中再常見不過了,但它的使用也不是想怎麼用就怎麼用的。好多進去,不request直接就是set_gpio,那麼多個地方都這樣get/set不就亂了麼,也不要在驅動中直接去ioremap而後直接去操做寄存器(三星的2440教程中好多就這麼教的),這樣也會形成混亂,大多狀況在machine中都設置好了gpio_chip,咱們要作的就是翻看數據手冊要使用的GPIO_pin號以及要配置成的功能,而後使用標準GPIO的API去使用便可。使用也有套路,先request再使用(set/irq等),再也不使用了就free掉。使用request加上請求標籤有利於調試,好比在個人msm8x12的內核中使用以下代碼:
那麼在內核輸入cat /sys/kernel/debug/gpio獲得的信息以下
由上圖的紅色框可見,正如代碼設置同樣,標籤爲"akm09911_rest",輸出高。
GPIO相關的經常使用API以下: