Android平台开发指导(Android Porting Guide)(一)


Android平台开发指导(Android Porting Guide)(一)
2011年02月24日
  没有比这 http://www.netmite.com/android/mydroid/development /pdk/docs/index.html 更官方的android开发指导材料了,闲着无事就翻译了。
   本文为 Android 平台开发人员和 Android 设备制造商提供了底层开发指导。如果你对 Android 的上层应用开发很感兴趣,请访问 Android Developers Site
   关于这份指导书
   这份指导书按照逻辑划分为几个部分(见目录)。在一个持续的开发过程中, Android 是一个复杂的工程项目,随着版本和 API 的改变,这份指导书将会不断更新。
   至使用者
   对于精通嵌入式 Linux 的工程师而言,这本书非常有价值。但是,它的重点并不在普通的嵌入式 Linux 开发,而是更多提供 Android 平台的特色。
   初学 Android
   对于初识 Android 的人而言,建议阅读以下文档:
   Android Develop site :这个网页提供了高版本的 SDK 文档;
   Android Open Source Project site :这个网页指导你如何获取源代码,建立开发环境和从事简单的工程开发。
   如果你准备在你的目标系统上定制和移植 Android 系统,请阅读系统编译概述。 Android 用一个定制的编译系统产生一系列工具,编译文件和文档。这一小节概述了 Android 编译系统和如何建立一个简单的编译环境。
   Android 的编译系统是以 GNU Make 为基础,并且要求最新的版本(注意: Android 所使用的最新的 GNU Make 规则可能并不会出现在 GNU Make 的网页上)。在开始之前,首先通过" make  -v"检查下你的编译环境的版本。如果你不是 3.80 或者更高版本的话,你需要升级你的 GNU Make 版本。
   理解 makefile
   makefile 文件定义了如何去建立一个系统的编译规则。典型的 makefile 包含以下一些元素: 1. 名称:为你的编译目标取一个名称(LOCAL_MODULE := ) ;
   2. 局部变量:用 CLEAR_VARS清除 局部变量 ( include $ (CLESR_VARS));
   3. 所需要编译的文件:注明你的目标需要链接哪些源文件(LOCAL_SRC_FILES := main.c);
   4. 标记:编译选项(LOCAL_MODULE_TAGS := eng development) ;
   5. 库:定义你的目标所需要链接的库文件(LOCAL_SHARED_LIBRARIES := cutils);
   6. 模板文件:所包含的这些模板文件定义了生成目标的类型,同时包含了生成此种目标的编译工具(include $(BUILD_EXECUTABLE))。
   下面一段代码举例说明一个典型的 makefile LOCAL_PATH := $(my-dir) include $(CLEAR_VARS) LOCAL_MODULE :=  LOCAL_SRC_FILES := main.c LOCAL_MODULE_TAGS := eng development LOCAL_SHARED_LIBRARIES := cutils include $(BUILD_EXECUTABLE) (HOST_)EXECUTABLE,(HOST_)JAVA_LIBRARY,(HOST_)PREBU ILT, (HOST_)SHARED_LIBRARY,(HOST_)STATIC_LIBRARY,PACKAG E,JAVADOC, RAW_EXECUTABLE, RAW_STATIC_LIBRARY,COPY_HEADERS, KEY_CHAR_MAP 
   为了提高代码的可读性,上面这段代码中包含了一些的书写风格。
   Layers
   下表描述了编译系统所包含的抽象层。
   每一个抽象层都是以一对多的关系和上面一层相关。例如,一种处理器架构可以运行在很多种目标板上,而每一个目标板又有很多设备。你可以在给定的抽象层上定义一个元素作为同一层元素的一个特例,这样就避免了复制和简化了维护。 Layer Example Description Product myProduct, myProduct_eu, myProduct_eu_fr, j2, sdk 产品层定义了一个产品的详细说明,包括编译的模块和配置。你可以基于一种特定的应用提供一种设备上的几种不同版本。例如,基于摄像技术。 Device myDevice, myDevice_eu, myDevice_eu_lite 设备层代表了构建在设备上的物理层。例如,南美的可能包含 QWERTY 键盘而法国的可能包含 AZERTY 键盘。连接到设备层的典型外设。 Board sardine, trout, goldfish 开发板层代表了一个产品的缩减版。当然你可以连接一些外设上去。 Arch arm (arm5te) (arm6), x86, 68k 架构层描述了你目标系统的处理器架构 编译 Android 系统
   这部分说明如何编译缺省的 Android 版本。一旦你熟悉了普通的编译过程,你就可以尝试着编译一个能运行在你自己的设备上的 Android 系统。
   设备编码
   为了做一个普通 Android 编译过程,源码中 build/envsetup.sh 中包含了一些环境变量和函数定义。例如: 为了一个工程调试编译,你也可以用 eng 取代 user
   这些编译变量随着调试选项和安装包的不同而不同。
     清除编译结果
   通过执行"m  clean"来清除你刚编译产生的目标文件。也可以通过"m clobber"来删除所有目标编译的输出文件,也就相当于将整个 /out 目录删除。
     加速重新编译
   每一个目标系统的编译输出文件都放在 /out 目录下,每一次编译都会快速的选择目标而不需要重新编译所有源码。
   但是如果编译系统没有将改动告诉环境变量或 makefile ,我们就有必要清除以往的编译结果。如果这种情况经常发生,你就需要定义一个环境变量:
   %make  j4 PRODUCT-generic-eng
     这样做是为了迫使编译系统使用 ccache 编译器,它能减少源码的重复编译。
   ccache 编译器源码已经提供( /prebuilt ),不需要再次安装。
     问题定位
   下面的错误很可能是由于 JAVA 版本过低所导致的: % export USE_CCACHE=1 device Dex: core UNEXPECTED TOP-LEVEL ERROR: java.lang.NoSuchMethodError: method java.util.Arrays.hashCode with signature ([Ljava.lang.Object;)I was not found. at com.google.util.FixedSizeList.hashCode(FixedSizeLi st.java:66) at com.google.rop.code.Rop.hashCode(Rop.java:245) at java.util.HashMap.hash(libgcj.so.7)  Dx 是一个 Java 工具,首次出现在 java1.5 版本中。通过 "java -version'检查你的 java 版本。 如果你有 java1.5 或者更高版本,你还会遇到这样的错误,检查你的 PATH 变量。
     编译 Android 的内核
   这部分介绍如何编译 Android 缺省的内核。一旦你熟悉了普通的 Android 内核编译,你就可以尝试着去配置你自己的 Android 驱动。
   为了编译内核,选择设备目录( /home/joe/android/device ),建立环境变量并且运行: % . envsetup.sh % partner_setup generic  然后选择内核目录 /home/joe/android/kernel.
     下载分支
   缺省的代码分支是 Android 。为了下载不同的分支代码,执行:
   % git checkout --track -b android-mydevice origin/android-mydevice //Branch android-mydevice set up to track remote branch % refs/remotes/origin/android-mydevice. //Switched to a new branch "android-mydevice"
   为了简化代码的管理,让你的分支名字和它的主干名字相同。通过执行"git checkout "来选择下载的代码分支。
   分支鉴定
   要找出哪一个代码分支存在和哪一个代码分支是可用(标有 asterisk ),执行: % git branch -a android * android-mydevice origin/HEAD origin/android origin/android-mydevice origin/android-mychipset 编译内核
   执行:
   % make  j4  
     编译选项
   当我们需要针对目标系统编译时,我们希望在最终版本中如果有几种不同编译选项的镜像。下面有几个编译选项: eng This is the default flavor. A plain make is the same as make eng.  Installs modules tagged with: eng, debug, user, and/or development.  Installs non-APK modules that have no tags specified.  Installs APKs according to the product definition files, in addition to tagged APKs.  ro.secure=0  ro.debuggable=1  ro.kernel.android.checkjni=1  adb is enabled by default user make user  This is the flavor intended to be the final release bits.  Installs modules tagged with user.  Installs non-APK modules that have no tags specified.  Installs APKs according to the product definition files; tags are ignored for APK modules.  ro.secure=1  ro.debuggable=0  adb is disabled by default.  userdebug make userdebug  The same as user, except:  Also installs modules tagged with debug.  ro.debuggable=1  adb is enabled by default.  创建 makefile 如何为你的 Android 移动设备创建一个 makefile ?步骤如下: 1. 在 //vendor/ 下,以产品的公司名字创建一个目录
   2. 在公司名字目录下再创建一个产品的目录
   3. 创建一个产品的 makefile 文件,至少包含以下代码
   4. 将产品特性的变量添加到产品定义文件中
   5. 在 /products/ 目录下,创建一个 AndroidProducts.mk 文件,用于链接个别产品的 makefile 文件 mkdir vendor/ mkdir vendor//products/ $(call inherit-product, $(SRC_TARGET_DIR)/product/generic.mk) # # Overrides PRODUCT_NAME :=  PRODUCT_DEVICE :=   6. 在公司目录下在创建一个目标板的目录,这个目录下的 makefile 文件可以被运行在目标板的任何一个产品访问到:
   7. 在目标板目录下创建一个 BoardConfig.mk 文件: # This file should set PRODUCT_MAKEFILES to a list of product makefiles # to expose to the build system. LOCAL_DIR will already be set to # the directory containing this file. # # This file may not rely on the value of any variable other than # LOCAL_DIR; do not use any conditionals, and do not look up the # value of any variable that isn't set in this file or in a file that # it includes. PRODUCT_MAKEFILES := \ $(LOCAL_DIR)/first_product_name.mk \   8. 如果你想改进系统属性,在 [/b][b]目录下创建一个 system.prop 文件:
   9. 在 products/AndroidProducts.mk 中声明 .mk
   10. 一个 Anroid.mk 文件( /vendor// )必须包含以下代码 : 11. 对于同一个目标板的第二个产品,创建第二个 makefile 文件 vendor /companyname/product/.mk PRODUCT_MAKEFILES := \ $(LOCAL_DIR)/first_product_name.mk \ $(LOCAL_DIR)/second_product_name.mk # make file for new hardware from LOCAL_PATH := $(call my-dir) # this is here to use the pre-built kernel ifeq ($(TARGET_PREBUILT_KERNEL),) TARGET_PREBUILT_KERNEL := $(LOCAL_PATH)/kernel endif file := $(INSTALLED_KERNEL_TARGET) ALL_PREBUILT += $(file) $(file): $(TARGET_PREBUILT_KERNEL) | $(ACP) $(transform-prebuilt-to-target) # no boot loader, so we don't need any of that stuff.. LOCAL_PATH := vendor// include $(CLEAR_VARS) # include more board specific stuff here? Such as Audio parameters.   现在,你就有了两个产品, and 。为了验证一个新的产品是否被成功配置,执行:
     编译后,你就会发现产生了一个新的目录 /out/target/product/
   新产品的文件结构树
   在完成了上述步骤之后,在你的系统上你会看到如下目录:
   ||-- |-- Android.mk poduct_config.mk system.prop |-- AndroidProducts.mk .mk .mk  
     产品变量定义文件
   产品的属性变量就定义在产品变量定义文件中。一个产品的变量定义文件可以从其他产品继承,这样就可以减少不必要的复制和易于代码维护。 Parameter Description Example PRODUCT_NAME End-user-visible name for the overall product. Appears in the "About the phone" info PRODUCT_MODEL End-user-visible name for the end product PRODUCT_LOCALS A space-separated list of two-letter language code, two-letter country code pairs that describe several settings for the user, such as the UI language and time, date and currency formatting. The first locale listed in PRODUCT_LOCALES is is used if the locale has never been set before. en_GB de_DE es_ES fr_CA PRODUCT_PACKAGES Lists the APKs to install. Calendar Contacts PRODUCT_DEVICE Name of the industrial design dream PRODUCT_MANUFACTUER Name of the manufacturer acme PRODUCT_BRAND The brand (e.g., carrier) the software is customized for, if any PRODUCT_PROPERTY_OVERRIDES List of property assignments in the format "key=value" PRODUCT_COPY_FILES List of words like source_path:destination_path . The file at the source path should be copied to the destination path when building this product. The rules for the copy steps are defined in config/Makefile PRODUCT_OTA_PUBLIC_KEYS List of OTA public keys for the product PRODUCT_POLICY Indicate which policy this product should use PRODUCT_PACKAGE_OVERLAYS Indicate whether to use default resources or add any product specific overlays vendor/acme/overlay PRODUCT_CONTRIBUTORS_FILE HTML file containing the contributors to the project. PRODUCT_TAGS list of space-separated words for a given productb 下面举例说明一个典型的产品变量定义文件:
   Android 编译手册提供简单的实例代码帮助你很快的建立一些普通的编译任务。
   编译一个简单的 APK 文件
   编译一个依赖 .jar 库的 APK 文件
   $(call inherit-product, build/target/product/generic.mk) #Overrides PRODUCT_NAME := MyDevice PRODUCT_MANUFACTURER := acme PRODUCT_BRAND := acme_us PRODUCT_LOCALES := en_GB es_ES fr_FR PRODUCT_PACKAGE_OVERLAYS := vendor/acme/overlay
   编译一个需要平台密钥文件签名的 APK 文件 编译一个需要定制代码密钥文件签名的 APK 文件
   LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) # List of static libraries to include in the package LOCAL_STATIC_JAVA_LIBRARIES := static-library # Build all java files in the java subdirectory LOCAL_SRC_FILES := $(call all-subdir-java-files) # Name of the APK to build LOCAL_PACKAGE_NAME := LocalPackage # Tell it to build an APK include $(BUILD_PACKAGE)  
   增加一个预编译的 APK 文件 增加一个静态的 JAVA Android.mk 变量 下面是一些 Android.mk 文件中常见的变量,按字母顺序罗列。首先,注意变量的命名 :
   LOCAL_- 这些变量被设置为单独的每个模块。以 "include $(CLEAR_VARS)"为界限,可以通过它清空其他 LOCAL_ 的声明。大多数模块中的变量都是 LOCAL_ 变量;
   PRIVATE_- 这些变量用来编译特定目标代码。即他们仅用在模块的命令当中。也意味着它不可能作用于定义在当前模块后面的模块;
   HOST_ TARGET_- :这些变量包含对 HOST TARGET 的说明和定义。在你的 makefile 文件中不要使用 HOST_ TARGET_
   BUILD_ CLEAR_VARS- 这些变量包含了模板 makefile 的名字。
   其它的名字你都可以任意使用在你自己的 makefile 文件中。但是,记住这是一个非递归的编译系统,很可能你的变量会被其它的 Android.mk 修改,导致你使用的时候它变得不同了。
   (表格见 http://source.android.com/porting/build_cookbook.h tml 介绍 Android 平台要求每个应用程序有密钥文件签名以获取系统权限,这样应用程序就可以获得共享的用户 ID 或者运行在系统进程当中。 Android 平台使用四种密钥文件来维护系统的安全性:
   .Platform :关于 package 的平台密钥文件;
   .Shard :能分享 /home/contacts 进程的密钥文件;
   .Media :关于 media/download 中包的密钥文件;
   .Releasekey :除上面之外的缺省的密钥文件。
   这些密钥文件为发行的 Image 文件中的应用获取数字签名,他们并不是编译所需要的。编译系统使用测试密钥文件( build/target/product/security/ )进行数字签名。这个测试密钥文件是标准的 Android 平台的一部分,所以不会被其他平台产品和设备所使用。相应的,设备制造商们会提供他们设备的产品密钥文件。
   创建一个密钥文件
   设备制造商的产品密钥文件应该放在 /vendor//security/ 下面。为了创建一个简单的密钥文件,复制这个目录下的 mkkey.sh 的脚本。为了定制你自己的密钥文件,修改 AUTH 这一行,更正你公司的信息: mkkey.sh 是一个产生密钥文件的脚本。注意:你输入的密码在你的终端上是可见的。另外,这些密码是用于数字签名的。
   为了产生四种密钥文件,需要运行 mkkey.sh 四次:
   LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) # Build all java files in the java subdirectory LOCAL_SRC_FILES := $(call all-subdir-java-files) # Any libraries that this library depends on LOCAL_JAVA_LIBRARIES := android.test.runner # The name of the jar file to create LOCAL_MODULE := sample # Build a static jar file. include $(BUILD_STATIC_JAVA_LIBRARY)
   这样你就有了自己的产品密钥文件。
   数字签名
   数字签名包含两个步骤: 1. 为需要编译的每个部分进行数字签名;
   2. 签名好后放回 Image 文件中。 应用程序数字签名
   build/tools/releasetools/sign_target_files_apks target_file 进行数字签名。缺省情况下 target_files 不会编译的,所以当你编译是需要明确 "dist":
   这条命令在 out/dist 目录下创建一个文件 -target_files.zip 。这就是脚本 sign_target_files_apks 所需要的文件。
   如果在编译过程中,有些 apk 你不想重新签名,你就要在你的命令行中为增加 "-e Foo.apk="。
   Sign_target_files_apks 有许多其他的命令选项,可以 -h 查看。
   创建 Image 文件
   一旦你有了 signed-target-files.zip, 就可以通过下面命令放到 image 中:
   Sign-img.zip 包含了所有的 image 文件。
   启动画面定制
   在设备启动过程中, Android 会显示一幅图片。如果你希望更改默认的图片: #!/bin/sh AUTH='/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress= [email protected]' if [ "$1" == "" ]; then echo "Create a test certificate key." echo "Usage: $0 NAME" echo "Will generate NAME.pk8 and NAME.x509.pem" echo " $AUTH" exit fi openssl genrsa -3 -out $1.pem 2048 openssl req -new -x509 -key $1.pem -out $1.x509.pem -days 10000 \ -subj "$AUTH" echo "Please enter the password for this key:" openssl pkcs8 -in $1.pem -topk8 -outform DER -out $1.pk8 -passout stdin 网络定制平台
     网络配置
   Android 的网络配置信息作为一种资源被编译到目标文件中。它的 xml 文件在 //android/framework/base/core/res/res/xml/apns.xml 。这个文件中不包括 APNS 配置。一般不需要修改,但是在编译的过程中你需要配置 APNs
   编译时 APN 的配置
   为一个产品配置 APN ,你需要增加一个 apns-conf.xml (不需要修改系统缺省的 APNs )。这样就可以让不同的产品拥有不同的 APNs 配置。
   为了在产品层次上配置 APNs ,在 vendor//products/ myphone-us.mk:
   系统运行时 APN 配置
   系统运行时, Android system/etc/apns-conf.xml 中读取配置。
   Android 提供下面几种运行时的网络配置:
   自动配置:系统启动时, Android SIM 卡的 MCC MNC 中获取的网络配置信心并且自动完成所有配置。
   手动配置: Android 平台也支持运行时用户手动配置。
   WAP/SMS 配置 : 网络配置是标准的 Android 资源。你可以通过安装一个新的系统资源 APK 包来更新网络配置。也可以通过添加一项服务,这项服务可以为 SMS (包含网络配置信息)监听 SMS 端口。  
   定制预加载的应用程序
   为产品定制应用程序开发包(包括 application inputmethods providers services 等),需要在产品配置( product configuration )中设置 PRODUCT_PACKAGES
   sh mkkey.sh platform # enter password sh mkkey.sh media # enter password sh mkkey.sh shared # enter password sh mkkey.sh release # enter password
   程序包名应该和 Android.mk LOCAL_PACKAGE_NAME 名字对应。
     例如:某个 Android.mk 文件: 注意:主屏幕( Launcher.apk )仅仅是一个 Android 的应用程序,可以通过修改源代码的方式定制自己的 HomeScreen
   定制浏览器书签
   浏览器书签存储在 Brower 应用程序的 string 资源当中: //android/packages/ apps/Brower/res/values/strings.xml 。书签被定义为一个简单的字符串数组( bookmarks ),第一部分代表他的书签名,第二部分代表他的 URL Android 在平台配置的基础上交替下载 Like 和应用程序资源。为了给一个特定的移动网络配置书签,请将你的 strings.xml 放在 Mobile Network Code 的资源文件夹下面。例如, Brower/res/values-mccXXX-mncYYY/strings.xml, 其中 XXX YYY 就代表 MCC MNC 的值。
   EmailProvider 定制
   缺省的 email Provider 设置存储在 //android/packages/apps/Email/res/xml/ providers.xml: Android 会在平台配置的基础上交替加载所有的应用程序资源。给一个特定的移动网络配置 email Provider ,你需要见 provider.xml 放在 Mobile Network Code 的资源文件下。例如, Email/res/xml-mccXXX-mnxYYY/providers.xml
   平台主题
   平台主题和风格在 //android/framework/base/core/res/res/values/style s.xml 中。
   动画
   Android 提供了一些窗口和视图变换的动画。系统的动画放在:
   //android/framework/base/core/res/res/anim 中。

猜你喜欢

转载自lix63lix.iteye.com/blog/1361857