深刻淺出 - Android系統移植與平臺開發(十一)- Android系統的定製【轉】

本文轉載自:java

4.3定製Android平臺系統

一般產品廠商在拿到Android源碼後會在android源碼基礎上進行定製修改,以匹配適應本身的產品,從本節開始,咱們從最原始的Android源碼系統裏一步一步定製出本身的Android系統。本節主要內容包含:根據Android源碼,添加新產品編譯項,定製系統啓動界面和文字,定製系統啓動動畫和聲音,定製系統桌面。linux

4.3.1 添加新產品編譯項

Android系統的源代碼是一個邏輯結構很是獨立工程,在一套Android源碼中能夠編譯出多個產品映像,在須要編譯某一個產品系統時,只要經過lunch命令選擇產品編譯項便可。本節咱們介紹如何在Android源碼中建立新產品編譯項並定製編譯出該產品系統。android

在建立新產品編譯項時,要先了解下面幾個概念:vim

Ø 目標產品:具體指某個最終用戶買到的Android設備,如:iPhone5,樂PhoneS2,小米手機等。架構

Ø 產品系列:開發手機的團隊一般由同一團隊打造,在研發出一款產品後,每每要繼續在其基礎上研發出新產品,新產品每每是在老產品的硬件或軟件基礎上作一些升級,這些產品們就是一個產品系列。好比:聯想的樂Phone系列手機包含:樂PhoneS1和樂PhoneS2,他們同屬於一個系列。框架

Ø 目標設備:目標設備能夠理解爲手機主板,它是指手機設備硬件配置信息的集合體,每一個手機產品都有設備硬件配置,一個設備硬件配置可能被不一樣產品使用,同一手機有高配置版本和低配置版本,如樂PhoneS2有512M RAM、8G Flash容量版本和1G RAM 、16G Flash容量版本。ide

在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系統只能使用一種啓動動畫方式,先判斷是否使用了逐幀動畫,若是沒有使用逐幀動畫時,才使用默認的蒙板動畫。

相關文章
相關標籤/搜索