Android係統的定製---定製係統開機動畫
4.3定製Android平台係統
通常產品廠商在拿到Android源碼後會在Android源碼基礎上進行定製修改,以匹配適應自己的產品,從本節開始,我們從最原始的Android源碼係統裏一步一步定製出自己的Android係統。本節主要內容包含:根據Android源碼,添加新產品編譯項,定製係統啟動界麵和文字,定製係統啟動動畫和聲音,定製係統桌麵。
4.3.1 添加新產品編譯項
Android係統的源代碼是一個邏輯結構非常獨立工程,在一套Android源碼中可以編譯出多個產品映像,在需要編譯某一個產品係統時,隻要通過lunch命令選擇產品編譯項即可。本節我們介紹如何在Android源碼中創建新產品編譯項並定製編譯出該產品係統。
在創建新產品編譯項時,要先了解下麵幾個概念:
Ø 目標產品:具體指某個最終用戶買到的Android設備,如:iPhone5,樂PhoneS2,小米手機等。
Ø 產品係列:開發手機的團隊通常由同一團隊打造,在研發出一款產品後,往往要繼續在其基礎上研發出新產品,新產品往往是在老產品的硬件或軟件基礎上做一些升級,這些產品們就是一個產品係列。比如:聯想的樂Phone係列手機包含:樂PhoneS1和樂PhoneS2,他們同屬於一個係列。
Ø 目標設備:目標設備可以理解為手機主板,它是指手機設備硬件配置信息的集合體,每個手機產品都有設備硬件配置,一個設備硬件配置可能被不同產品使用,同一手機有高配置版本和低配置版本,如樂PhoneS2有512M RAM、8G Flash容量版本和1G RAM 、16G Flash容量版本。
在Android編譯係統中,每個編譯項編譯出一個產品係統,每個目標產品都對應一個目標設備,一個產品係列包含多個不同的產品,一個目標設備可能被多個產品配置使用。
由前麵描述可知,同一係列的新老產品之間可以存在“繼承關係”,新產品是老產品的“子產品”,老產品是新產品的“父產品”,子產品可以複用父產品的特性,還可以重寫、擴展父產品。如:老產品不支持NFC近距離通信技術,新產品支持NFC技術。同樣,設備主板間也存在“繼承關係”。
圖x-x 產品、設備與編譯項關係圖
如圖x-x所示,某一產品係列包含3個產品,2個目標設備,其中產品2繼承了產品1,產品2 使用了設備2,它是基於產品1所使用的設備1的升級。產品3使用了和產品2一樣的設備2,他們硬件配置一樣,但是卻不是同一產品,3個不同產品都對應一個產品編譯項。
在Android編譯係統中,產品編譯項相關配置文件都在device/<廠商名>/目錄下。廠商的產品列表由AndroidProducts.mk文件定義,目標產品信息由<產品名>.mk定義,目標設備信息由BoardConfig.mk和AndroidBoard.mk定義。創建新產品的編譯項就是創建上述幾個mk文件的過程。
1. 創建廠商目錄
不同的手機廠商對應device/下不同目錄,在廠商目錄下放置該廠商的產品相關信息,我們廠商名定義為mycompany。
$ cd ~/android/android_source
$ mkdir device/mycompany
2. 在廠商目錄下創建設備目錄
定義設備名為myphone。
$ mkdir device/mycompany/myphone
3. 添加新產品編譯項配置文件,該配置文件在執行source build/envsetup.sh時,被加載執行
$ vim device/mycompany/myphone/vendorsetup.sh
在vendorsetup.sh文件時添加下麵一條命令,用於向編譯係統添加編譯項,新添加的產品名為:myproduct,編譯類型為eng。
add_lunch_combo myproduct-eng
注:add_lunch_combo命令是build/envsetup.sh腳本中定義的函數,表示將一個新產品編譯項添加到lunch菜單裏。
4. 創建產品列表配置文件AndroidProducts.mk
AndroidProducts.mk文件用於定義當前廠商所擁有的所有產品列表,每個產品都對應一個配置文件:
$ vimdevice/mycompany/myphone/AndroidProducts.mk
在產品列表配置文件中添加如下內容:
PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/full_product.mk
注:PRODUCT_MAKEFILES變量用於保存所有產品配置信息列表,$(LOCAL_DIR)表示當前目錄,full_product.mk表示某一款產品的配置文件。
5. 配置full_product.mk文件,定義產品的配置信息,添加如下內容:
include build/target/product/languages_full.mk
include build/target/product/full.mk
# Discard inherited values and use our owninstead.
PRODUCT_NAME := myproduct
PRODUCT_DEVICE := myphone
產品配置也可以和Java中的類一樣被繼承,通過inclulde命令可以將指定的文件包含進來,然後在後麵可以對裏麵的內容進行重寫。一般而言不同的產品產品名和設備名都不一樣,在full_product.mk中對繼承的full.mk中的產品名和設備名進行重寫:PRODUCT_NAME為myproduct,PRODUCT_DEVICE為myphone。
在full_product.mk文件中繼承的languages_full.mk內容如下:
@build/target/product/languages_full.mk
PRODUCT_LOCALES := en_US fr_FR it_IT es_ES de_DEnl_NL cs_CZ pl_PL ja_JP zh_TW zh_CN ru_RU ko_KR nb_NO es_US da_DK el_GR tr_TRpt_PT pt_BR rm_CH sv_SE bg_BG ca_ES en_GB fi_FI hr_HR hu_HU in_ID iw_IL lt_LTlv_LV ro_RO sk_SK sl_SI sr_RS uk_UA vi_VN tl_PH
該配置文件裏表示的是當前產品係統裏默認支持的本地語言,由上述配置信息可知,它基本包含了Android所支持的所有語言包。
@build/target/product/full.mk
PRODUCT_PACKAGES := \
OpenWnn \
PinyinIME \
VoiceDialer\
libWnnEngDic \
libWnnJpnDic \
libwnndict
# Additional settings used in all AOSP builds
PRODUCT_PROPERTY_OVERRIDES := \
keyguard.no_require_sim=true \
ro.com.android.dateformat=MM-dd-yyyy \
ro.com.android.dataroaming=true \
ro.ril.hsxpa=1 \
ro.ril.gprsclass=10
PRODUCT_COPY_FILES := \
development/data/etc/apns-conf.xml:system/etc/apns-conf.xml \
development/data/etc/vold.conf:system/etc/vold.conf
# Pick up some sounds - stick with the shortlist to save space
# on smaller devices.
$(call inherit-product,frameworks/base/data/sounds/OriginalAudio.mk)
# Get the TTS language packs
$(call inherit-product-if-exists,external/svox/pico/lang/all_pico_languages.mk)
# Get a list of languages. We use the small listto save space
# on smaller devices.
$(call inherit-product,build/target/product/languages_small.mk)
$(call inherit-product,build/target/product/generic.mk)
# Overrides
PRODUCT_NAME := full
PRODUCT_BRAND := generic
PRODUCT_DEVICE := generic
PRODUCT_MODEL := Full Android
繼承的full.mk文件內容比較多,我們將主要的一些變量列出如表x-x所示。
變量名 |
作用 |
使用方式 |
PRODUCT_PACKAGES |
係統預置的模塊列表,不僅僅隻是Android應用程序,還可以包含庫,可執行程序等 |
直接將係統中要安裝的模塊名以空格隔開列出 |
PRODUCT_PROPERTY_OVERRIDES |
係統設置的屬性值 |
將所有預設的屬性以空格隔開列出,屬性格式為:key-value |
PRODUCT_COPY_FILES |
要拷貝的文件 |
將文件列表拷貝到文件係統中,文件格式為:源文件:目標文件 |
PRODUCT_NAME |
產品名 |
該產品名要和編譯項中產品名一致 |
PRODUCT_BRAND |
產品品牌 |
|
PRODUCT_DEVICE |
產品對應的設備名 |
該名字要和產品設備主板配置文件(BoardConfig.mk)所在目錄名一致 |
PRODUCT_MODEL |
|
|
總結:我們自己定義的full_product產品繼承了build/target/product/目錄下的full.mk和languages_full.mk,full.mk文件是Android係統定義的一個“通用產品”,languages_full.mk文件是全部語言包配置文件,這樣,自己的產品full_product就具有了通用產品的特點並且支持全部語言包。
6. 定義目標產品對應的設備配置文件AndroidBoard.mk和BoardConfig.mk
同樣的道理,我們可以繼承使用通用設備配置文件:build/target/board/generic/目錄下的AndroidBoard.mk和BoardConfig.mk文件。
Ø 創建AndroidBoard.mk和BoardConfig.mk文件
$ touch AndroidBoard.mk BoardConfig.mk
Ø 添加AndoridBoard.mk的內容如下:
@ device/mycompany/myphone/AndroidBoard.mk
include build/target/board/generic/AndroidBoard.mk
“繼承”的父AndroidBoard.mk,其內容:
@build/target/board/generic/AndroidBoard.mk
LOCAL_PATH := $(call my-dir)
file := $(TARGET_OUT_KEYLAYOUT)/tuttle2.kl # Linux內核按鍵碼布局文件
ALL_PREBUILT += $(file)
$(file) : $(LOCAL_PATH)/tuttle2.kl | $(ACP)
$(transform-prebuilt-to-target)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := tuttle2.kcm # Android按鍵碼映射文件
include $(BUILD_KEY_CHAR_MAP)
其實build/target/board/generic/AndroidBoard.mk文件裏隻是拷貝了按鍵映射文件和默認係統屬性文件,我們可以將其內容直接拷貝到device/mycompany/myphone/AndroidBoard.mk中。
Ø 添加BoardConfig.mk的內容如下:
@ device/mycompany/myphone/BoardConfig.mk
includebuild/target/board/generic/BoardConfig.mk
“繼承”的父BoardConfig.mk內容:
@build/target/board/generic/BoardConfig.mk
# config.mk
#
# Product-specific compile-time definitions.
#
# The generic product target doesn't have anyhardware-specific pieces.
TARGET_NO_BOOTLOADER := true # 當前設備是否沒有Bootloader
TARGET_NO_KERNEL := true # 當前設備是否沒有Linux內核
TARGET_CPU_ABI := armeabi # 當前設備支持的目標架構
HAVE_HTC_AUDIO_DRIVER := true # 是否使用HTC的音頻驅動
BOARD_USES_GENERIC_AUDIO := true # 是否使用通用音頻技術
# no hardware camera
USE_CAMERA_STUB := true # 是否使用攝像頭Stub
通過BoardConfig.mk的信息可知,其實該文件就是定義了一些設備硬件相關的一些變量,這些變量用來裁剪係統的功能,決定Android係統可運行的體係構架。
7. 根據需要定義產品默認屬性和鍵值信息
Android係統的屬性服務類似於Windows的注冊表,記錄著係統的一些設置信息,我們可以在新產品中預定義一些屬性值來設置自己產品。在Android編譯係統中,屬性都保存在xxx.prop文件中,在build/target/board/generic/system.prop中定義了默認的屬性,我們可以在它基礎上進行修改。
複製屬性文件:
$ cp build/target/board/generic/system.prop device/mycompany/myphone/
在Android係統中,底層使用Linux內核來接收來自按鍵硬件上報的鍵值信息,上層處理用戶按鍵的是Android的框架,二者之間通過兩個鍵值布局文件來進行鍵值的映射。
Ø Keylayout文件:按鍵布局文件,以kl後綴命名,該文件用來定義按鍵驅動裏上報的鍵值號(數字)和Linux內核中通過event事件上報的鍵值(字符)之間的映射關係。kl文件要放在/system/usr/keylayout/目錄下或/data/usr/keylayout/目錄下。
Ø KeyCharMap文件:鍵值字符映射文件,以kcm後綴命名,它用來將Linux內核上報來的鍵值(字符)進行轉換,轉換成Android係統裏可以識別的鍵盤碼或組合按鍵。kcm文件要放在/system/usr/keychars/目錄下或/data/usr/keychars/目錄下。
上述兩個按鍵映射文件使用按鍵驅動名作為其文件名,如果沒有驅動名對應的布局文件,則使用/system/usr/keylayout/qwerty.kl和/system/usr/keychars/qwerty.kcm作為默認的按鍵映射文件。這兩個文件名都通過AndroidBoard.mk文件負責拷貝和安裝。
如果我們要使用模擬器作為目標設備,隻需要將源碼build/target/board/generic/目錄裏的tuttole2.kl和tuttle2.kcm拷貝到AndroidBoard.mk所在的目錄中即可。
$ cp build/target/board/generic/tuttle2.kl device/mycompany/myphone/tuttle2.kl
$ cp build/target/board/generic/tuttle2.kcm device/mycompany/myphone/tuttle2.kcm
如果想要自定義係統的物理按鍵與Android係統的按鍵映射關係,則需要在tuttle2.kl和tuttle2.kcm的基礎上進行修改,然後再修改AndroidBoard.mk的內容:
$ cp build/target/board/generic/tuttle2.kl device/mycompany/myphone/<按鍵驅動名>.kl
$ cp build/target/board/generic/tuttle2.kcm device/mycompany/myphone/<按鍵驅動名>.kcm
修改device/mycompany/myphone/AndroidBoard.mk文件:
LOCAL_PATH := $(call my-dir)
file := $(TARGET_OUT_KEYLAYOUT)/<按鍵驅動名>.kl # Linux內核按鍵碼布局文件
ALL_PREBUILT += $(file)
$(file) : $(LOCAL_PATH)/<按鍵驅動名>.kl | $(ACP)
$(transform-prebuilt-to-target)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := <按鍵驅動名>.kcm # Android按鍵碼映射文件
include $(BUILD_KEY_CHAR_MAP)
注:kcm文件最終被編譯係統的key_char_map.mk編譯成xxx.kcm.bin的二進製形式,這是因為每個Android應用程序都要加載該按鍵映射文件,為了加快讀取速度刻意而為之的。
創建新產品編譯項時創建的目錄與文件結構如下:
device/mycompany/ # 廠商目錄
└── vendorsetup.sh # 添加編譯項命令文件
└── myphone/ # 設備名目錄
├── AndroidBoard.mk # 設備屬性和鍵值映射配置文件
├── AndroidProducts.mk # 產品列表文件
├── BoardConfig.mk # 設備硬件配置及目標架構配置文件
├── full_product.mk # 目標產品配置文件
├── system.prop # 係統默認屬性配置文件
├── tuttle2.kcm # Android係統鍵值映射文件
├── tuttle2.kl # Linux內核按鍵布局文件
確認上述目錄和文件創建沒有問題了,執行Android編譯步驟:sourcebuild/envsetup.sh,lunch選擇myproduct-eng編譯項。
如果看到如下信息,說明我們已經添加新產品成功。
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=2.3.6
TARGET_PRODUCT=myproduct
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=false
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=GRK39F
============================================
8. 常見問題
Ø 問題1: lunch菜單裏沒有出現myproduct編譯項
原因及解決方法:在執行lunch之前,要執行source build/envsetup.sh命令,確認vendorsetup.sh文件存在及其內容正確無誤。
Ø 問題2:選擇完lunch菜單裏的編譯項後,出錯:
*** No matches for product"myproduct". Stop.
** Don't have a product spec for:'myproduct'
** Do you have the right repo manifest?
原因及解決方法:編譯係統找不到用戶選擇的編譯項裏的myproduct產品,確認AndroidProducts.mk文件裏列出了myproduct產品的配置文件full_product.mk,並且full_product.mk文件中PRODUCT_NAME變量的值為產品名:myproduct
Ø 問題3:選擇完lunch菜單裏的編譯項後,出錯:
*** No config file found for TARGET_DEVICEmyphone. Stop.
** Don't have a product spec for:'myproduct'
** Do you have the right repo manifest?
原因及解決方法:編譯係統找不到myproduct產品對應的設備myphone,確認myproduct產品的配置文件full_product.mk中PRODUCT_DEVICE變量的值為產品名:myphone,並且在device/mycompany/目錄下創建了myphone的設備目錄,在該目錄下存在BoardConfig.mk文件。
4.3.2 定製產品的意義及定製要點
Android係統是一個完全開源的係統,我們可以通過修改Linux內核代碼和Android源碼,定製具有獨特創意的產品係統,對於產品同質化非常嚴重的移動市場, Android係統的細節個性化定製也可以讓用戶眼前一亮。另外,一些產品明確要求要修改或增加一些個性化,如:默認的Android係統開機界麵是一個黃嘴的小企鵝,在Android係統啟動過程中是一個ANDROID字樣的動畫效果,廠商一般都要求自己產品開機界麵是廠商Logo,開機動畫是一個能動態、鮮明表現公司活力的動畫效果,我們從本節開始介紹定製產品係統的實現技術。
在整個開機過程中,屏幕上會出現三次內容,如圖x-x 所示:
Ø Linux啟動時畫麵,通常是個黃嘴的小企鵝
Ø Android係統init進程啟動階段畫麵,是“ANDROID”文字字樣
Ø Android係統啟動階段動畫,是滾動的ANDROID動畫
圖 x-x 開機界麵與Android動畫
定製係統開機動畫
【實驗背景知識】
Android的開機動畫是由Linux本地守護程序bootanimation專門控製實現的,其代碼在:frameworks/base/cmds/bootanimation/目錄下,修改Android開機動畫有兩種方式:
Ø 蒙板圖片替換:
替換frameworks/base/core/res/assets/images/目錄下的兩個圖片文件:android-logo-mask.png和android-logo-shine.png。android-logo-mask.png是鏤空蒙板圖片,android-logo-shine.png是鏤空蒙板後麵的閃光png圖片。兩個圖片通過疊加移動來達到動畫效果。
Ø 逐幀動畫替換:
在/data/local/或/system/media/目錄創建bootanimation.zip文件,該壓縮包文件裏存放有逐幀動畫及控製腳本。
【實驗組成】
本實驗分為兩部分:蒙板圖片替換實驗和逐幀動畫替換實驗。
【實驗內容】
分析Android係統的兩種開機動畫實現方式,製作並替換開機動畫,最終在Android模擬器中運行定製開機動畫的係統。
【實驗目的】
通過實驗,了解Android係統的兩種開機動畫實現方式,掌握如何定製產品的開機動畫,並在Android模擬器中,運行定製開機動畫的Android係統。
【實驗平台】
擁有Android源碼編譯環境的Ubuntu操作係統(可以在Windows係統中虛擬Ubuntu係統)。
【蒙板圖片替換實驗步驟】
1. 使用PhotoShop等圖像處理軟件製作一張背景為黑色,中間鏤空的png格式的圖片,命名為:android-logo-mask.png,如圖x-x所示。
圖x-x 製作鏤空動畫
2. 將android-logo-mask.png拷貝到frameworks/base/core/res/assets/images/目錄下替換Android默認的圖片,為了防止源碼不編譯圖片資源,將圖片時間戳更新一下。
$ cp android-logo-mask.png ~/android/android_source/frameworks/base/core/res/assets/images/
$ touch ~/android/android_source/frameworks/base/core/res/assets/images/android-logo-mask.png
3. 重新編譯Android的係統資源包framework-res.apk
$ source build/envsetup.sh
$ lunch generic-eng
$ mmm frameworks/base/core/res/
4. 生成新的system.img
$ make snod
5. 啟動Android模擬器,實驗效果如圖x-x所示。
$ ./run_emulator.sh
圖x-x 定製開機動畫效果
【逐幀動畫替換實驗步驟】
1. 在/data/local/或/system/media/目錄創建bootanimation.zip文件
如果放在/data/local目錄下,不需要編譯Android源碼,直接通過adb命令或文件管理軟件拷貝到目錄下即可,如果集成進Android係統中,則需要放在/system/media/目錄下,這時要重新編譯生成system.img映像。
bootanimation.zip文件是直接由幾個文件打包生成的,打包的格式是ZIP,打包時的壓縮方式選擇為存儲。
圖x-x 壓縮文件方式
bootanimation.zip文件打包前的結構為:
表x-x bootanimation.zip壓縮包文件結構
文件 |
說明 |
desc.txt |
動畫屬性描述文件 |
part0/ |
第一階段動畫圖片的目錄 |
part1/ |
第二階段動畫圖片的目錄 |
其中part0和part1中的動畫圖片類似於電影膠片,兩張圖片之間變化較小,他們以固定的速度顯示,從而產生動畫效果,圖片的大小和圖片顯示的時間控製由desc.txt文件說明。
desc.txt文件內容為:
480 250 15
p 1 0 part0
p 0 10 part1
desc.txt文件的格式為:
|
數據及說明 |
|||
圖片屬性 |
320(圖片寬) |
320(圖片高) |
15(每秒顯示幀數) |
無 |
第一階段動畫屬性 |
P(默寫標誌符) |
1(循環次數為1 ) |
0(進入該階段的間隔時間) |
part0(該階段圖片存放目錄) |
第二階段動畫屬性 |
p(默寫標誌符) |
0(無限循環) |
10(進入該階段的間隔時間) |
part1(該階段圖片存放目錄) |
注:
標識符:p 是必須的。
循環次數:指該目錄中圖片循環顯示的次數,0表示本階段無限循環。
每秒顯示幀數:就是每秒顯示的圖片數量,決定每張圖片顯示的時間。
階段切換間隔時間:指的是該階段結束後間隔多長時間顯示下一階段的圖片,其單位是每張圖片顯示的時間。
對應圖片目錄:就是該階段動畫的係列圖片,以圖片文件目錄的順序顯示動畫,而且圖片的格式必須要為PNG。
由於逐幀動畫不太方便製做,我們直接使用光盤中:章節實驗/第四章定製係統開機動畫/bootanimation.zip文件作為演示。
2. 如果bootanimation.zip放到/system/media/目錄下,則重新編譯生成system.img
$ source build/envsetup.sh
$ lunch generic-eng
$ make snod
3. 啟動Android模擬器,查看動畫效果,如圖x-x和x-x所示。
$ ./run_emulator.sh
圖x-x 第一階段開機動畫
圖x-x 第二階段開機動畫
結論:通過實驗看出,當我們使用逐幀動畫時,蒙板動畫就不播放了,這是因為Android係統隻能使用一種啟動動畫方式,先判斷是否使用了逐幀動畫,如果沒有使用逐幀動畫時,才使用默認的蒙板動畫。
原文:https://blog.csdn.net/mr_raptor/article/details/30113417
最後更新:2017-04-03 07:57:10