閱讀156 返回首頁    go 阿裏雲 go 技術社區[雲棲]


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

  上一篇:go android的&lt;uses-feature&gt;詳解
  下一篇:go 李一男離開華為時給屬下的忠告!