App Version:6.3.7,Model:vivo x209,AndroidVer6.0.1,SubVersion:6.3.7.2795.2016-08-24.r224866.vivo

汗水凝结成时光胶囊,独自在这命运里拓荒
AndroidStudio配置与使用SVN
svn安装: 需注意,需安装 command line功能。
svn注意点:
3.1. 需要重启电脑,右键才会出现svn的各种菜单。
3.2. 若是直接打开TotoseSVN客户端,会出现以下提示:
tortoisesvn is a shell extension
that means it is integrated into the windows explorer.
to use tortoisesvn please open the explorer and right-click on
any folder you like to bring up the context menu where you will find all tortoisesvn commands.
因此,svn不直接以客户端运行,需对文件进行操作。
AndroidStudio 上SVN的使用
1. AndroidStudio配置 svn:
步骤:打开Android Studio–&File–&Setting–&Version Control–&Subversion
配置svn路径:在上图中的Use Command Line Client中添加svn.exe, svn默认路径C:\Program Files\TortoiseSVN\bin\svn.exe。
若是不存在svn.exe,则安装TotoseSVN未安装command line功能,需重新安装。
2. Android Studio添加忽略文件以及上传项目到svn:
上传项目到svn前需添加忽略文件
步骤:打开Android Studio–&File–&Setting–&Version Control–&Ignored Files –添加忽略的文件
androidStudio提供了三种选择忽略规则:
Ignore specified file:忽略指定文件
Ignore all files under:忽略文件夹下所有文件
Ignore all files mathching: 忽略符合匹配规则的文件。
SVN中文件忽略规则:
.ide文件 、 .gradle文件 、 所有的build文件(包含module中build) 、 所有的.iml文件 、local.properties 文件。
依次添加完忽略文件,如下图所示:
除此之外,还有一种通过.ignore插件方式添加忽略文件。
步骤:File→Settings→Plugins→Browse repositories-& 搜索.ignore–&安装后,重启AS–&手写忽略文件规则。
最终项目(Project)中出现.gitignore文件如下图所示:
android studio上传项目到svn进行关联:
步骤: VCS-&Import into Version Control-&Import into Subversion(这里androidStudio 2.1.1 没有Share Project(Subversion))–&Import into Subversion弹窗中,点击+ –&创建一个新的仓库,填写svn服务器路径,选择上传的项目(Project而不是单个Moudle),一路next。
Import into Subversion过程说明:
先将本地代码导入SVN服务器上。但是SVN没有关联到本地的代码。因此,需要将svn服务器上的代码更新下来,即下面AndroidStudio从步骤中从svn中check out项目的步骤。这样才能完成本地项目和SVN服务器建立关联,才能正常开发。
3. AndroidStudio从SVN服务器上Check out 项目:
第一种方式:file–&project from verson controll–&subvsersion –&从Repostory(仓库中)选择要check out的项目的路径或者新增要check out的项目路径–&check out–&Destionation Directory弹窗中,选择项目存放路径–&OK,接下来Android Studio会自动加载项目。
从SVN服务器check ou项目到本地路径中,成功建立关联后如下图所示:
第二种方式:CVS–&Check from Verson Controll–&subversion–&选择仓库路径–&import:
点击yes打开,导入项目后会问你两次*iml要不要加到版本控制,选择no即可 。
点击yes后,可能遇到导入其他工程会弹出Import project form Gradle弹窗,需要选择UseLocal gradle distribution–&在Gradle Home中选择安装androidstudio中gradle插件的路径。这里是E:\AndroidStudio\studio\plugins\gradle
接着却提示:
the project is using an unsupported version of gradle. please point to a supported Gradle version in the project's Gradle.
The project is using an unsupported version of Gradle.
Please point to a supported Gradle version in the project's Gradle settings or in the project's Gradle wrapper (if applicable.)
com.intellij.openapi.externalSystem.model.ExternalSystemException: The project is using an unsupported version of Gradle.
Please point to a supported Gradle version in the project's Gradle settings or in the project's Gradle wrapper (if applicable.)
原因:Gradle版本太新了
解决方式:
AS去自行下载所支持的Gradle版本。
先拷贝下来项目,然后通过AS导入项目(曲线救国方式)。
引入其他的Gradle:
C:\Users\xxxx.gradle\wrapper\dists\gradle-1.12-all\2apkk7d25miauqf1pdjp1bm0uo\gradle-1.12
接下来却报:Plugin with id ‘com.android.application’ not found.
4. AndroidStudio svn代码冲突的解决方式:
当代码冲突时候,会弹出Files Merged with Conflicts弹窗。弹窗左边是是冲突的列表,右边有合并方式,Accept Yours(以自己的代码为合并后的代码),Accept Theirs(接受svn服务器上的代码),Merge(两者合并)。
最佳方案:选择Merge(合并)–&合并对照窗口。
合并弹窗说明:有三个子视图部分,最左边视图的是本地代码,即自己的代码。中间视图是合并后代码显示的视图。最右边的是svn上的代码视图。
合并做法:点击箭头将两边冲突的代码添加到中间的合并区域中去,点击叉号则辨识放弃那一段代码,待所有冲突处理完成后merge就成功了。
5. AndroidStudio浏览SVN服务器上的项目文件夹:
步骤:Vcs–&Browse VS Repository–&Browse Subversion Repository.
SVN Repository窗口会显示项目列表:
6. SVN关联后项目中颜色说明:
红色文件:未添加svn中文件,可以右键–&subversion-add to svn
绿色文件:关联上了svn,但是进行了修改,未提交。可以右键–&subversion-commit file
蓝色文件: 多人修改,需要下载后mergc后再上传。也可以先锁上(subversion-lock),修改完后cmomit提交上去,会自动解锁。
7. SVN创建分支
步骤:对着项目(Project)右键–&SubVersion–&Branch or Tag
–&弹出Create Branch or Tag弹窗–&Base URL选分支路径(同行中最右边的选择路径弹窗中选择)–&Comment注释–&OK.
比较项目的操作:对着项目右键–&SubVersion-&Compare With branch…比较合并.
8. SVN恢复资源库文件
当文件修改了之后,发现修改的无效,需要恢复资源库最后一个版本的内容,在所选文件单击右键,选择 Subversion ,再选择Reset ,即回到了资源库中的版本。
9. 一些svn操作术语:
Auto-update after commit :自动升级后提交
keep files locked :把文件锁上,我想这应该就只能你修改其他开发人不能修改不了的功能,在你提交之前:before commit
Reformat code:重新格式化代码
Rearrange code:重新整理代码
Optimize imports:优化导入
Perform code analysis:执行代码分析[ 默认选择]
Check TODO(show all):检测需要修改的代码[显示所有默认选择]
clean up: 清除所有
Update copyright:更新版权
PS:本篇文章,通过知乎,度娘,谷歌等多种方式搜索以及参考多篇优秀教程,资源如下。
资源参考:
博客教程:
知乎上教程:
AndroidStudio上SVN教程(英文):
Gradle Problem:
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!vivo X9s配置曝光:处理器升级 或2798元起售
购OPPOA33.A37手机,送多功能折叠烧烤炉+碎屏险一年+联通50兆宽带2年,
购VIVO Y55.Y66手机,送电饭煲+碎屏险一年+小电风扇+联通50兆宽带2年,
购OPPOA57.A59s,VIVOY67.X9手机,送挂烫机(或)电饭煲+多功能折叠烧烤炉+碎屏险一年+联通50兆宽带2年,
购OPPOR9s.R9splus.手机,送电压力锅(或)吸尘器+多功能折叠烧烤炉+碎屏险一年+电风扇+联通50兆宽带2年。
购VIVOX9plus.xplay6手机,送电压力锅(或)+电饭锅+多功能折叠烧烤炉+碎屏险一年+联通50兆宽带2年。
活动期间本店购机均可参加分期付款,0首付 0利息,不用花一分钱手机带回家。
本周四,vivo将在北京发布新机X9s,从vivo昨天的预售信息看,X9s系列依然包含X9s Plus,手机外形与X9系列基本保持一致,主要卖点仍是前置2000万像素柔光双摄自拍。
今天网上曝光了X9s的一些详细信息,配置方面,X9s搭载5.5英寸1080p屏幕,处理器升级至骁龙652,而X9s Plus搭载6英寸1080p屏幕,仍然是骁龙653处理器,运行Android 7.1.1系统。另外提升的还有电池容量,X9s电池升级至3220mAh,而vivo X9s Plus则是4015mAh容量电池。
拍照方面,两款新机前置均为 2000万像素+500万像素的组合,至于背面的主摄像头则仍是1600万像素。但新增了vivo前不久公布的全新DSP拍照技术,从官方之前的介绍看,这颗256M RAM的独立DSP芯片,进行RAW格式的多帧合成,以增强手机暗光及复杂光线环境下的成像素质,相当让人期待。
售价方面,有消息称X9s将会2798元起起售,有黑色,金色和粉色等三种色彩款式可选,至于X9s Plus价格预计跟X9 Plus上市时保持一致。
责任编辑:
声明:该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。
今日搜狐热点Android studio如何使用SVN进行版本控制? - 知乎有问题,上知乎。知乎作为中文互联网最大的知识分享平台,以「知识连接一切」为愿景,致力于构建一个人人都可以便捷接入的知识分享网络,让人们便捷地与世界分享知识、经验和见解,发现更大的世界。364被浏览<strong class="NumberBoard-itemValue" title="4,577分享邀请回答19371 条评论分享收藏感谢收起211 条评论分享收藏感谢收起Android系统移植技术详解
Android系统开发编译环境配置
主机系统:Ubuntu9.04
(1)安装如下软件包
sudo apt-get install git-core
sudo apt-get install gnupg
sudo apt-get install sun-java5-jdk
sudo apt-get install flex
sudo apt-get install bison
sudo apt-get install gperf
sudo apt-get install libsdl-dev
sudo apt-get install libesd0-dev
sudo apt-get install build-essential
sudo apt-get install zip
sudo apt-get install curl
sudo apt-get install libncurses5-dev
sudo apt-get install zlib1g-dev
android编译对java的需求只支持jdk5.0低版本,jdk5.0 update 12版本和java 6不支持。
(2)下载repo工具
&/bin/repo
chmod a&#43;x /bin/repo
(3)创建源代码下载目录:
mkdir /work/android-froyo-r2
(4)用repo工具初始化一个版本(以android2.2r2为例)
cd /work/android-froyo-r2
repo init -u git://android.git.kernel.org/platform/manifest.git -b froyo
初始化过程中会显示相关的版本的TAG信息,同时会提示你输入用户名和邮箱地址,以上面的方式初始化的是android2.2 froyo的最新版本,
android2.2本身也会有很多个版本,这可以从TAG信息中看出来,当前froyo的所有版本如下:
&* [new tag]&&&&&&&& android-2.2.1_r1 -& android-2.2.1_r1
&* [new tag]&&&&&&&& android-2.2_r1 -& android-2.2_r1
&* [new tag]&&&&&&&& android-2.2_r1.1 -& android-2.2_r1.1
&* [new tag]&&&&&&&& android-2.2_r1.2 -& android-2.2_r1.2
&* [new tag]&&&&&&&& android-2.2_r1.3 -& android-2.2_r1.3
&* [new tag]&&&&&&&& android-cts-2.2_r1 -& android-cts-2.2_r1
&* [new tag]&&&&&&&& android-cts-2.2_r2 -& android-cts-2.2_r2
&* [new tag]&&&&&&&& android-cts-2.2_r3 -& android-cts-2.2_r3
这样每次下载的都是最新的版本,当然我们也可以根据TAG信息下载某一特定的版本如下:
repo init -u git://android.git.kernel.org/platform/manifest.git -b android-cts-2.2_r3
(5)下载代码
froyo版本的代码大小超过2G,漫长的下载过程。
(6)编译代码
cd /work/android-froyo-r2
Ubuntu下使用Simba服务实现局域网内文件共享
Ubuntu下安装Simba服务器将linux电脑上的内容共享,同一局域网内的另外一台Windows PC即可访问其共享内容,
从而实现Windows电脑向访问本地文件一样访问Linux文件系统的内容。
(1)安装Simaba服务器
sudo apt-get install samba
(2)安装samba图形化配置软件
sudo apt-get install system-config-samba
(3)创建一个Simba专用用户
从“系统”—“系统管理”—“用户和组”,来创建。如图,先点击“解锁”,然后“添加新用户”
然后输入新用户名字(如Simba)和密码(如111111),然后在“高级”里面,选择“主组”为sambashare后点击&确定&即可
一句话来概括,就是创建一个主组为sambashare的用户
(4)配置samba共享
从“系统”—“系统管理—”samba“,运行配置界面
然后”首选项“—”服务器设置“。点击:安全性,在最后的”来宾帐号“里面,
选择我们新建立的那个用户simba后点击确定
(5)修改samba配置文件
打开/etc/samba/smb.conf,修改valid users = XXXX为valid users = simba
(6)重启samba服务
sudo /etc/init.d/samba restart
(7)添加共享文件
从“系统”—“系统管理—”samba“,运行配置界面
点击&添加&来添加共享文件夹,点击&浏览&来选择需要共享的文件夹,选择&可擦写&和&显示&,点击&访问&可以设置访问权限,最好设置成&允许所有用户访问&
本文来自CSDN博客,转载请标明出处:
Ubuntu下tftp服务器的创建
实验平台:Ubuntu9.04
(1)安装tftp服务
sudo apt-get install tftp tftpd openbsd-inetd
(2)在根目录下创建文件夹 tftpboot文件夹并修改权限
sudo mkdir tftpboot
sudo chmod 777 tftpboot
(3)修改/etc/inetd.conf文件如下:
tftp dgram udp wait nobody /usr/sbin/tcpd /usr/sbin/in.tftpd /tftpboot
(4)开启tftp服务
sudo /etc/init.d/openbsd-inetd reload
sudo in.tftpd -l /tftpboot
(5)重启电脑,然后将测试文件放入/tftpboot目录下即可开始测试,出现问题可能一般都是权限问题
/tftpboot目录下的文件访问权限改成0777
本文来自CSDN博客,转载请标明出处:
创建一个新的Android产品项目
从google网站上下载的android源代码编译时默认是编译google设定的产品,如果要开发自己的产品,
则需要重新定义一个产品项目,过程如下:
首先我们定义产品的规&#26684;,举例如下:
公司名称 ardent
产品名称 MTP
主板名称 merlin
然后安装下面的步骤新建产品项目:
(1)在源代码目录下创建一个用户目录
mkdir vendor
(2)在用户目录下创建一个公司目录
mkdir vendor/merlin
(3)在公司目录下创建一个products目录
mkdir vendor/merlin/products
(4)在上面创建的products下创建一个产品makefile文件MTP.mk,内容如下:
PRODUCT_PACKAGES := \
AlarmClock \
Fallback \
Launcher2 \
Settings \
LatinIME \
SoundRecorder \
Bluetooth \
CertInstaller \
$(call inherit-product, $(SRC_TARGET_DIR)/product/core.mk)
# Overrides
PRODUCT_MANUFACTURER := ardent
PRODUCT_BRAND := ardent
PRODUCT_NAME := MTP
PRODUCT_MODEL := MultiMedia Touch Phone
PRODUCT_DEVICE := merlin
PRODUCT_LOCALES := zh_CN
产品makefile文件的编写有一套规则,详细情况见此文后面的补充内容。
(5)在vendor/merlin/products目录下创建一个AndroidProducts.mk文件,定义Android产品配置文件的路径,具体如下:
PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/MTP.mk
(6)在公司目录下创建一个主板目录
mkdir vendor/ardent/merlin
(7)在主板目录下新建一个主板配置文件BoardConfig.mk,内容如下:
TARGET_NO_BOOTLOADER := true
TARGET_NO_KERNEL := true
TARGET_CPU_ABI := armeabi
BOARD_USES_GENERIC_AUDIO := true
USE_CAMERA_STUB := true
(8)如果你希望修改系统属性,则可以在主板目录下新建一个system.prop文件,该文件中可以修改系统属性,举例如下:
# system.prop for
# This overrides settings in the products/generic/system.prop file
# rild.libpath=/system/lib/libreference-ril.so
# rild.libargs=-d /dev/ttyS0
(9)在主板目录下建议一个Android的主板配置文件AndroidBoard.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
file := $(INSTALLED_KERNEL_TARGET)
ALL_PREBUILT &#43;= $(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/ardent/merlin
include $(CLEAR_VARS)
# include more board specific stuff here? Such as Audio parameters.
(10)编译新的项目
. build/envsetup.sh
make PRODUCT-MTP-user
补充内容:
(1)上面的新建的几个文件的编写可以参考build/target/board/generic目录下的AndroidBoard.mk,BoardConfig.mk和system.prop
(2)产品makefile的编写规则,变量定义解释如下:
PRODUCT_NAME 终端用户可见的产品名称,对应到“Settings“中的“About the phone”信息
PRODUCT_MODEL End-user-visible name for the end product
PRODUCT_LOCALES 1个以空&#26684;分隔开的两个字母的语言码加上2字节的国家码的列表,影响到&Settings&中的语言,时间,日期和货币&#26684;式设置,
举例:en_GB de_DE es_ES fr_CA
PRODUCT_PACKAGES 需要安装的APK应用程序列表
PRODUCT_DEVICE 工作设计名称,即主板名称
PRODUCT_MANUFACTURER 生产厂家
PRODUCT_BRAND 软件设计针对的客户品牌
PRODUCT_PROPERTY_OVERRIDES 以&key=value&为&#26684;式的属性列表
PRODUCT_COPY_FILES 文件复制列表,&#26684;式为“原文件路径:目的文件路径”,编译过程中会按照此规则复制文件
PRODUCT_OTA_PUBLIC_KEYS 产品的OTA公共密匙列表
PRODUCT_POLICY 声明此产品使用的政策
PRODUCT_PACKAGE_OVERLAYS 指示是否使用默认资源或添加任何产品特定的资源,例如:vendor/acme/overlay
PRODUCT_CONTRIBUTORS_FILE HTML文件中包含项目的贡献者
PRODUCT_TAGS 以空&#26684;分隔开的指定产品关键词列表
本文来自CSDN博客,转载请标明出处:ttp://blog.csdn.net/jiajie961/archive//5993126.aspx
制作ubifs文件系统
1,安装相关的软件包
apt-get install liblzo2-dev
2,获取相关的工具mkfs.ubifs和ubinize
这两个工具是制作ubifs文件系统的时候用到,它们是mtd-utils工具包中的内容,mtd-utils工具包你可以从下面的网站下载和编译出来:
官方网站:
资源下载网站:
3,创建一个create-ubifs.sh脚本,主要是调用mkfs.ubifs和ubinize工具和相关参数来制作ubifs文件系统,内容如下:
#!/bin/bash
##########################################################
# Script to generate ubifs filesystem image. #
##########################################################
##### ubinize configuration file
config_file=rootfs_ubinize.cfg
##### Function to check result of the command
check_result() {
if [ $? -ne 0 ]
echo &FAILED&
echo &SUCCESSFUL&
###### Function to check whether an application exists
check_program() {
for cmd in &$@&
which ${cmd} & /dev/null 2&&1
if [ $? -ne 0 ]
echo &Cannot find command \&${cmd}\&&
if [ $# -ne 5 ]
echo 'Usage: create-ubifs.sh [page_size_in_bytes] [pages_per_block] [partition_size_in_bytes] [blocks_per_device] [path_to_rootfs]'
page_size_in_bytes=$1
echo &Page size [$page_size_in_bytes]bytes.&
pages_per_block=$2
echo &Pages per block [$pages_per_block]&
partition_size_in_bytes=$3
echo &File-system partition size [$partition_size_in_bytes]bytes.&
blocks_per_device=$4
echo &Blocks per device [$blocks_per_device]&
path_to_rootfs=$5
# wear_level_reserved_blocks is 1% of total blcoks per device
wear_level_reserved_blocks=`expr $blocks_per_device / 100`
echo &Reserved blocks for wear level [$wear_level_reserved_blocks]&
#logical_erase_block_size is physical erase block size minus 2 pages for UBI
logical_pages_per_block=`expr $pages_per_block - 2`
logical_erase_block_size=`expr $page_size_in_bytes \* $logical_pages_per_block`
echo &Logical erase block size [$logical_erase_block_size]bytes.&
#Block size = page_size * pages_per_block
block_size=`expr $page_size_in_bytes \* $pages_per_block`
echo &Block size [$block_size]bytes.&
#physical blocks on a partition = partition size / block size
partition_physical_blocks=`expr $partition_size_in_bytes / $block_size`
echo &Physical blocks in a partition [$partition_physical_blocks]&
#Logical blocks on a partition = physical blocks on a partitiion - reserved for wear level
patition_logical_blocks=`expr $partition_physical_blocks - $wear_level_reserved_blocks`
echo &Logical blocks in a partition [$patition_logical_blocks]&
#File-system volume = Logical blocks in a partition * Logical erase block size
fs_vol_size=`expr $patition_logical_blocks \* $logical_erase_block_size`
echo &File-system volume [$fs_vol_size]bytes.&
echo &Generating configuration file...&
echo &[rootfs-volume]& & $config_file
echo &mode=ubi& && $config_file
echo &image=rootfs_ubifs.img& && $config_file
echo &vol_id=0& && $config_file
echo &vol_size=$fs_vol_size& && $config_file
echo &vol_type=dynamic& && $config_file
echo &vol_name=system& && $config_file
# Note: Check necessary program for installation
#echo -n &Checking necessary program for installation......&
#check_program mkfs.ubifs ubinize
#echo &Done&
#Generate ubifs image
echo -n &Generating ubifs...&
./mkfs.ubifs -x lzo -m $page_size_in_bytes -e $logical_erase_block_size -c $patition_logical_blocks -o rootfs_ubifs.img -d $path_to_rootfs
check_result
echo -n &Generating ubi image out of the ubifs...&
./ubinize -o ubi.img -m $page_size_in_bytes -p $block_size -s $page_size_in_bytes $config_file -v
check_result
rm -f rootfs_ubifs.img
rm -f $config_file
(4)将mkfs.ubifs和ubinize以及create-ubifs.sh放置在同一目录下,然后调用create-ubifs.sh即可创建ubifs文件系统,create-ubifs.sh用法如下:
create-ubifs.sh page_size_in_bytes(页大小) pages_per_block(每个扇区的页数量) partition_size_in_bytes(分区大小) blocks_per_device(扇区数量) path_to_rootfs(文件系统路径)
举例如下:
./create-ubifs.sh
上面命令的意思是调用create-ubifs.sh将当前目录下的rootfs文件夹的内容制作成ubifs文件系统,nand flash的页大小为2k,每个扇区有64页,
总共有4096个扇区,要制作的文件系统的大小为字节。
本文来自CSDN博客,转载请标明出处:
android编译系统makefile(Android.mk)写法
android编译系统的makefile文件Android.mk写法如下
(1)Android.mk文件首先需要指定LOCAL_PATH变量,用于查找源文件。由于一般情况下
Android.mk和需要编译的源文件在同一目录下,所以定义成如下形式:
LOCAL_PATH:=$(call my-dir)
上面的语句的意思是将LOCAL_PATH变量定义成本文件所在目录路径。
(2)Android.mk中可以定义多个编译模块,每个编译模块都是以include $(CLEAR_VARS)开始
以include $(BUILD_XXX)结束。
include $(CLEAR_VARS)
CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE为你清除除LOCAL_PATH以外的所有LOCAL_XXX变量,
如LOCAL_MODULE,LOCAL_SRC_FILES,LOCAL_SHARED_LIBRARIES,LOCAL_STATIC_LIBRARIES等。
include $(BUILD_STATIC_LIBRARY)表示编译成静态库
include $(BUILD_SHARED_LIBRARY)表示编译成动态库。
include $(BUILD_EXECUTABLE)表示编译成可执行程序
(3)举例如下(frameworks/base/libs/audioflinger/Android.mk):
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS) 模块一
ifeq ($(AUDIO_POLICY_TEST),true)
ENABLE_AUDIO_DUMP := true
LOCAL_SRC_FILES:= \
AudioHardwareGeneric.cpp \
AudioHardwareStub.cpp \
AudioHardwareInterface.cpp
ifeq ($(ENABLE_AUDIO_DUMP),true)
LOCAL_SRC_FILES &#43;= AudioDumpInterface.cpp
LOCAL_CFLAGS &#43;= -DENABLE_AUDIO_DUMP
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libbinder \
libmedia \
libhardware_legacy
ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
LOCAL_CFLAGS &#43;= -DGENERIC_AUDIO
LOCAL_MODULE:= libaudiointerface
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
LOCAL_SRC_FILES &#43;= A2dpAudioInterface.cpp
LOCAL_SHARED_LIBRARIES &#43;= liba2dp
LOCAL_CFLAGS &#43;= -DWITH_BLUETOOTH -DWITH_A2DP
LOCAL_C_INCLUDES &#43;= $(call include-path-for, bluez)
include $(BUILD_STATIC_LIBRARY) 模块一编译成静态库
include $(CLEAR_VARS) 模块二
LOCAL_SRC_FILES:= \
AudioPolicyManagerBase.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_LDLIBS &#43;= -ldl
LOCAL_SHARED_LIBRARIES &#43;= libdl
LOCAL_MODULE:= libaudiopolicybase
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
LOCAL_CFLAGS &#43;= -DWITH_A2DP
ifeq ($(AUDIO_POLICY_TEST),true)
LOCAL_CFLAGS &#43;= -DAUDIO_POLICY_TEST
include $(BUILD_STATIC_LIBRARY) 模块二编译成静态库
include $(CLEAR_VARS) 模块三
LOCAL_SRC_FILES:= \
AudioFlinger.cpp \
AudioMixer.cpp.arm \
AudioResampler.cpp.arm \
AudioResamplerSinc.cpp.arm \
AudioResamplerCubic.cpp.arm \
AudioPolicyService.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libbinder \
libmedia \
libhardware_legacy
ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
LOCAL_STATIC_LIBRARIES &#43;= libaudiointerface libaudiopolicybase
LOCAL_CFLAGS &#43;= -DGENERIC_AUDIO
LOCAL_SHARED_LIBRARIES &#43;= libaudio libaudiopolicy
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_LDLIBS &#43;= -ldl
LOCAL_SHARED_LIBRARIES &#43;= libdl
LOCAL_MODULE:= libaudioflinger
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
LOCAL_CFLAGS &#43;= -DWITH_BLUETOOTH -DWITH_A2DP
LOCAL_SHARED_LIBRARIES &#43;= liba2dp
ifeq ($(AUDIO_POLICY_TEST),true)
LOCAL_CFLAGS &#43;= -DAUDIO_POLICY_TEST
ifeq ($(TARGET_SIMULATOR),true)
ifeq ($(HOST_OS),linux)
LOCAL_LDLIBS &#43;= -lrt -lpthread
ifeq ($(BOARD_USE_LVMX),true)
LOCAL_CFLAGS &#43;= -DLVMX
LOCAL_C_INCLUDES &#43;= vendor/nxp
LOCAL_STATIC_LIBRARIES &#43;= liblifevibes
LOCAL_SHARED_LIBRARIES &#43;= liblvmxservice
# LOCAL_SHARED_LIBRARIES &#43;= liblvmxipc
include $(BUILD_SHARED_LIBRARY) 模块三编译成动态库
(4)编译一个应用程序(APK)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# 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)
(5)编译一个依赖于静态Java库(static.jar)的应用程序
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)
(6)编译一个需要用平台的key签名的应用程序
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# 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
LOCAL_CERTIFICATE := platform
# Tell it to build an APK
include $(BUILD_PACKAGE)
(7)编译一个需要用特定key前面的应用程序
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# 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
LOCAL_CERTIFICATE := vendor/example/certs/app
# Tell it to build an APK
include $(BUILD_PACKAGE)
(8)添加一个预编译应用程序
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Module name should match apk name to be installed.
LOCAL_MODULE := LocalModuleName
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
include $(BUILD_PREBUILT)
(9)添加一个静态JAVA库
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)
(10)Android.mk的编译模块中间可以定义相关的编译内容,也就是指定相关的变量如下:
LOCAL_AAPT_FLAGS
LOCAL_ACP_UNAVAILABLE
LOCAL_ADDITIONAL_JAVA_DIR
LOCAL_AIDL_INCLUDES
LOCAL_ALLOW_UNDEFINED_SYMBOLS
LOCAL_ARM_MODE
LOCAL_ASFLAGS
LOCAL_ASSET_DIR
LOCAL_ASSET_FILES 在Android.mk文件中编译应用程序(BUILD_PACKAGE)时设置此变量,表示资源文件,
通常会定义成LOCAL_ASSET_FILES &#43;= $(call find-subdir-assets)
LOCAL_BUILT_MODULE_STEM
LOCAL_C_INCLUDES 额外的C/C&#43;&#43;编译头文件路径,用LOCAL_PATH表示本文件所在目录
举例如下:
LOCAL_C_INCLUDES &#43;= extlibs/zlib-1.2.3
LOCAL_C_INCLUDES &#43;= $(LOCAL_PATH)/src
LOCAL_CC 指定C编译器
LOCAL_CERTIFICATE 签名认证
LOCAL_CFLAGS 为C/C&#43;&#43;编译器定义额外的标志(如宏定义),举例:LOCAL_CFLAGS &#43;= -DLIBUTILS_NATIVE=1
LOCAL_CLASSPATH
LOCAL_COMPRESS_MODULE_SYMBOLS
LOCAL_COPY_HEADERS install应用程序时需要复制的头文件,必须同时定义LOCAL_COPY_HEADERS_TO
LOCAL_COPY_HEADERS_TO install应用程序时复制头文件的目的路径
LOCAL_CPP_EXTENSION 如果你的C&#43;&#43;文件不是以cpp为文件后缀,你可以通过LOCAL_CPP_EXTENSION指定C&#43;&#43;文件后缀名
如:LOCAL_CPP_EXTENSION := .cc
注意统一模块中C&#43;&#43;文件后缀必须保持一致。
LOCAL_CPPFLAGS 传递额外的标志给C&#43;&#43;编译器,如:LOCAL_CPPFLAGS &#43;= -ffriend-injection
LOCAL_CXX 指定C&#43;&#43;编译器
LOCAL_DX_FLAGS
LOCAL_EXPORT_PACKAGE_RESOURCES
LOCAL_FORCE_STATIC_EXECUTABLE 如果编译的可执行程序要进行静态链接(执行时不依赖于任何动态库),则设置LOCAL_FORCE_STATIC_EXECUTABLE:=true
目前只有libc有静态库形式,这个只有文件系统中/sbin目录下的应用程序会用到,这个目录下的应用程序在运行时通常
文件系统的其它部分还没有加载,所以必须进行静态链接。
LOCAL_GENERATED_SOURCES
LOCAL_INSTRUMENTATION_FOR
LOCAL_INSTRUMENTATION_FOR_PACKAGE_NAME
LOCAL_INTERMEDIATE_SOURCES
LOCAL_INTERMEDIATE_TARGETS
LOCAL_IS_HOST_MODULE
LOCAL_JAR_MANIFEST
LOCAL_JARJAR_RULES
LOCAL_JAVA_LIBRARIES 编译java应用程序和库的时候指定包含的java类库,目前有core和framework两种
多数情况下定义成:LOCAL_JAVA_LIBRARIES := core framework
注意LOCAL_JAVA_LIBRARIES不是必须的,而且编译APK时不允许定义(系统会自动添加)
LOCAL_JAVA_RESOURCE_DIRS
LOCAL_JAVA_RESOURCE_FILES
LOCAL_JNI_SHARED_LIBRARIES
LOCAL_LDFLAGS 传递额外的参数给连接器(务必注意参数的顺序)
LOCAL_LDLIBS 为可执行程序或者库的编译指定额外的库,指定库以&-lxxx&&#26684;式,举例:
LOCAL_LDLIBS &#43;= -lcurses -lpthread
LOCAL_LDLIBS &#43;= -Wl,-z,origin
LOCAL_MODULE 生成的模块的名称(注意应用程序名称用LOCAL_PACKAGE_NAME而不是LOCAL_MODULE)
LOCAL_MODULE_PATH 生成模块的路径
LOCAL_MODULE_STEM
LOCAL_MODULE_TAGS 生成模块的标记
LOCAL_NO_DEFAULT_COMPILER_FLAGS
LOCAL_NO_EMMA_COMPILE
LOCAL_NO_EMMA_INSTRUMENT
LOCAL_NO_STANDARD_LIBRARIES
LOCAL_OVERRIDES_PACKAGES
LOCAL_PACKAGE_NAME APK应用程序的名称
LOCAL_POST_PROCESS_COMMAND
LOCAL_PREBUILT_EXECUTABLES 预编译including $(BUILD_PREBUILT)或者$(BUILD_HOST_PREBUILT)时所用,指定需要复制的可执行文件
LOCAL_PREBUILT_JAVA_LIBRARIES
LOCAL_PREBUILT_LIBS 预编译including $(BUILD_PREBUILT)或者$(BUILD_HOST_PREBUILT)时所用, 指定需要复制的库.
LOCAL_PREBUILT_OBJ_FILES
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES
LOCAL_PRELINK_MODULE 是否需要预连接处理(默认需要,用来做动态库优化)
LOCAL_REQUIRED_MODULES 指定模块运行所依赖的模块(模块安装时将会同步安装它所依赖的模块)
LOCAL_RESOURCE_DIR
LOCAL_SDK_VERSION
LOCAL_SHARED_LIBRARIES 可链接动态库
LOCAL_SRC_FILES 编译源文件
LOCAL_STATIC_JAVA_LIBRARIES
LOCAL_STATIC_LIBRARIES 可链接静态库
LOCAL_UNINSTALLABLE_MODULE
LOCAL_UNSTRIPPED_PATH
LOCAL_WHOLE_STATIC_LIBRARIES 指定模块所需要载入的完整静态库(这些精通库在链接是不允许链接器删除其中无用的代码)
LOCAL_YACCFLAGS
OVERRIDE_BUILT_MODULE_PATH
本文来自CSDN博客,转载请标明出处:
Android系统移植(一)-让android系统在目标平台上运行起来
Android系统由于用的是linux内核,因此内核移植和嵌入式linux内核移植差异不大,过程如下:
(1)移植boot-loader和linux2.6内核到目标平台上,让linux内核可以启动起来,基本的驱动允许正常。
此过程完全是嵌入式linux的开发,这里直接跳过。需要注意的是,由于android已经被linux官方开除,因此从
网站上(如)下载的最新linux内核源代码已经不包含android的专有驱动,因此建议
从google网上下下载Linux内核,android源代码浏览网站如下:
从该网站上发现内核相关的包如下:
kernel/common.git 通用android内核项目
kernel/experimental.git 实验性内核项目
kernel/linux-2.6.git 这个是标准的Linux内核,没有android的驱动
kernel/lk.git 微内核项目
kernel/msm.git 这个是高通msm7xxx系列芯片所用内核
kernel/omap.git
kernel/tegra.git NVIDIA Tegra系列芯片所用内核
下载内核代码的方法如下:
git clone git://android.git.kernel.org/kernel/common.git
下载完后用git branch -a查看所有git分支,结果如下:
& android-2.6.27
& origin/HEAD
& origin/android-2.6.25
& origin/android-2.6.27
& origin/android-2.6.29
& origin/android-2.6.32
& origin/android-2.6.35
& origin/android-2.6.36
& origin/android-goldfish-2.6.27
& origin/android-goldfish-2.6.29
然后切换到最新分支git checkout origin/android-2.6.36
(2)修改内核配置文件,打开Android必须的驱动(日志和BINDER)如下:
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ANDROID_LOGGER=y
此部分的代码在内核drivers/staging/android目录下。
(3)为了提高启动速度,采用ramdisk,将android文件系统的部分内容压缩到内核中。
首先打开内核驱动:
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=&root&
CONFIG_INITRAMFS_ROOT_UID=0
CONFIG_INITRAMFS_ROOT_GID=0
然后在android源代码编译出来的out/target/product/merlin/root目录复制到内核目录下。
(4)根据android文件系统的要求对nand flash进行重新分区,举例如下:
将nand flash分区以下8个分区
Mass Storage
(5)根据分区表修改内核启动参数如下:
CONFIG_CMDLINE=&ubi.mtd=4 ubi.mtd=5 ubi.mtd=6 root=ubi0_0 rootfstype=ubifs console=ttyS1,115200 uart_dma init=/init&
参数的意思是:载入的文件系统部分有3个分区,分别为nand flash的第4,5,6分区(从0编号),文件系统采用ubifs&#26684;式,控制台设备为ttyS1,波特率为115200
启动的第一个应用程序是/init
(6)确保控制台的设置和硬件保持一致,如:硬件上串口用的是UART1,则内核启动参数中设置有console=ttyS1,而且android的启动过程中设要设置正确,修改
部分位于android源代码system/core/init/init.c文件中,将
static char *console_name = &/dev/console&;
static char *console_name = &/dev/ttyS1&;
(7)修改android源代码system/core/rootdir目录下的init.rc文件,作如下修改(android默认yaffs2文件系统):
首先将android文件系统修改成可读写,将
&&& mount rootfs rootfs / ro remount
&&& mount rootfs rootfs / rw remount
然后修改挂载system和userdata部分的代码,将
&&& # Mount /system rw first to give the filesystem a chance to save a checkpoint
&&& mount yaffs2
&&& mount yaffs2
/system ro remount
&&& # We chown/chmod /data again so because mount is run as root &#43; defaults
&&& mount yaffs2
/data nosuid nodev
&&& chown system system /data
&&& chmod 0771 /data
&&& # Mount /system rw first to give the filesystem a chance to save a checkpoint
&&& mount ubifs ubi0_0 /system ro
&&& # We chown/chmod /data again so because mount is run as root &#43; defaults
&&& mount ubifs ubi1_0 /data nosuid nodev
&&& chown system system /data
&&& chmod 0771 /data
(8)完成后编译内核,可以启动文件系统,控制台可用,但是没有显示启动log,而且不停的重启。
(9)系统不停的重启,因此控制台已经可用了,自然而然的想到看到logcat日志,一看,发现logcat设备居然没起来,配置文件里面都定义了
居然没起来,查看了下内核drivers/staging/android目录,没有.o文件,证明是没编译到,在看内核目录下的.config文件,发现居然没有了
logcat和binder的宏定义,配置文件里面有定义而.config文件中无定义,肯定是相关Kconfig文件的问题,通过分析drivers/staging目录下的
Kconfig文件发现是因为STAGING_EXCLUDE_BUILD宏默认是y,在配置文件中否定此宏即可,在配置文件中CONFIG_STAGING定义后加上即可,如下:
CONFIG_STAGING=y
# CONFIG_STAGING_EXCLUDE_BUILD is not set
修改后重新编译发现系统完成正常启动,启动过程中启动log也显示正常。
至此,android初步移植工作已经完成,当然,系统还有很多问题,需要下一步继续修改。
总结:android的移植按如下流程:
(1)android linux内核的普通驱动移植,让内核可以在目标平台上运行起来。
(2)正确挂载文件系统,确保内核启动参数和android源代码system/core/rootdir目录下的init.rc中的文件系统挂载正确。
(3)调试控制台,让内核启动参数中的console参数以及android源代码system/core/init/init.c中的console_name设置和硬件保持一致
(4)打开android相关的驱动(logger,binder等),串口输入logcat看logger驱动起来,没有的话调试logger驱动。
说明:ARM的内核配置文件定义在内核arch/arm/configs目录下
Android系统移植(二)-按键移植
这一部分主要是移植android的键盘和按键
(1)Android使用标准的linux输入事件设备(/dev/input目录下)和驱动,按键定义在内核include/linux/input.h文件中,
按键定义形式如下:
#define KEY_ESC&&&&&&&&&&& 1
#define KEY_1&&&&&&&&&&& 2
#define KEY_2&&&&&&&&&&& 3
(2)内核中(我的平台是arch/arm/mach-mmp/merlin.c文件)中按键的定义如下形式:
static struct gpio_keys_button btn_button_table[] = {
&&& [0] = {
&&&&&&& .code&&&&&&&&&&& =&&& KEY_F1,
&&&&&&& .gpio&&&&&&&&&&& =&&& MFP_PIN_GPIO2,
&&&&&&& .active_low&&&&&&& =&&& 1,&&&&&&& /* 0 for down 0, up 1; 1 for down 1, up 0 */
&&&&&&& .desc&&&&&&&&&&& =&&& &H_BTN button&,
&&&&&&& .type&&&&&&&&&&& =&&& EV_KEY,
&&&&&&& /* .wakeup&&&&&&&&&&& = */
&&&&&&& .debounce_interval&&& =&&& 10,&&&&&&& /* 10 msec jitter elimination */
&&& [1] = {
&&&&&&& .code&&&&&&&&&&& =&&& KEY_F2,
&&&&&&& .gpio&&&&&&&&&&& =&&& MFP_PIN_GPIO3,
&&&&&&& .active_low&&&&&&& =&&& 1,&&&&&&& /* 0 for down 0, up 1; 1 for down 1, up 0 */
&&&&&&& .desc&&&&&&&&&&& =&&& &O_BTN button&,
&&&&&&& .type&&&&&&&&&&& =&&& EV_KEY,
&&&&&&& /* .wakeup&&&&&&&&&&& = */
&&&&&&& .debounce_interval&&& =&&& 10,&&&&&&& /* 10 msec jitter elimination */
&&& [2] = {
&&&&&&& .code&&&&&&&&&&& =&&& KEY_F4,
&&&&&&& .gpio&&&&&&&&&&& =&&& MFP_PIN_GPIO1,
&&&&&&& .active_low&&&&&&& =&&& 1,&&&&&&& /* 0 for down 0, up 1; 1 for down 1, up 0 */
&&&&&&& .desc&&&&&&&&&&& =&&& &S_BTN button&,
&&&&&&& .type&&&&&&&&&&& =&&& EV_KEY,
&&&&&&& /* .wakeup&&&&&&&&&&& = */
&&&&&&& .debounce_interval&&& =&&& 10,&&&&&&& /* 10 msec jitter elimination */
static struct gpio_keys_platform_data gpio_keys_data = {
&&& .buttons& = btn_button_table,
&&& .nbuttons = ARRAY_SIZE(btn_button_table),
static struct platform_device gpio_keys = {
&&& .name = &gpio-keys&,
&&& .dev& = {
&&&&&&& .platform_data = &gpio_keys_data,
&&& .id&& = -1,
上面定义是将MFP_PIN_GPIO2这个GPIO口的按键映射到Linux的KEY_F1按键,MPF_PIN_GPIO3映射到KEY_F2,MFP_PIN_GPIO1映射到KEY_F4
(3)上面(2)步实现了从硬件GPIO口到内核标准按键的映射,但是android并没有直接使用映射后的键&#20540;,而且对其再进行了一次映射,从内核标准键&#20540;
到android所用键&#20540;的映射表定义在android文件系统的/system/usr/keylayout目录下。标准的映射文件为qwerty.kl,定义如下:
key 399&& GRAVE
key 2&&&& 1
key 3&&&& 2
key 4&&&& 3
key 5&&&& 4
key 6&&&& 5
key 7&&&& 6
key 8&&&& 7
key 9&&&& 8
key 10&&& 9
key 11&&& 0
key 158&& BACK&&&&&&&&&&&&& WAKE_DROPPED
key 230&& SOFT_RIGHT&&&&&&& WAKE
key 60&&& SOFT_RIGHT&&&&&&& WAKE
key 107&& ENDCALL&&&&&&&&&& WAKE_DROPPED
key 62&&& ENDCALL&&&&&&&&&& WAKE_DROPPED
key 229&& MENU&&&&&&&&&&&&& WAKE_DROPPED
key 139&& MENU&&&&&&&&&&&&& WAKE_DROPPED
key 59&&& MENU&&&&&&&&&&&&& WAKE_DROPPED
key 127&& SEARCH&&&&&&&&&&& WAKE_DROPPED
key 217&& SEARCH&&&&&&&&&&& WAKE_DROPPED
key 228&& POUND
key 227&& STAR
key 231&& CALL&&&&&&&&&&&&& WAKE_DROPPED
key 61&&& CALL&&&&&&&&&&&&& WAKE_DROPPED
key 232&& DPAD_CENTER&&&&&& WAKE_DROPPED
key 108&& DPAD_DOWN&&&&&&&& WAKE_DROPPED
key 103&& DPAD_UP&&&&&&&&&& WAKE_DROPPED
key 102&& HOME&&&&&&&&&&&&& WAKE
key 105&& DPAD_LEFT&&&&&&&& WAKE_DROPPED
key 106&& DPAD_RIGHT&&&&&&& WAKE_DROPPED
key 115&& VOLUME_UP
key 114&& VOLUME_DOWN
key 116&& POWER&&&&&&&&&&&& WAKE
key 212&& CAMERA
key 16&&& Q
key 17&&& W
key 18&&& E
key 19&&& R
key 20&&& T
key 21&&& Y
key 22&&& U
key 23&&& I
key 24&&& O
key 25&&& P
key 26&&& LEFT_BRACKET
key 27&&& RIGHT_BRACKET
key 43&&& BACKSLASH
key 30&&& A
key 31&&& S
key 32&&& D
key 33&&& F
key 34&&& G
key 35&&& H
key 36&&& J
key 37&&& K
key 38&&& L
key 39&&& SEMICOLON
key 40&&& APOSTROPHE
key 14&&& DEL
key 44&&& Z
key 45&&& X
key 46&&& C
key 47&&& V
key 48&&& B
key 49&&& N
key 50&&& M
key 51&&& COMMA
key 52&&& PERIOD
key 53&&& SLASH
key 28&&& ENTER
key 56&&& ALT_LEFT
key 100&& ALT_RIGHT
key 42&&& SHIFT_LEFT
key 54&&& SHIFT_RIGHT
key 15&&& TAB
key 57&&& SPACE
key 150&& EXPLORER
key 155&& ENVELOPE&&&&&&&
key 12&&& MINUS
key 13&&& EQUALS
key 215&& AT
(4)android对底层按键的处理方法
android按键的处理是Window Manager负责,主要的映射转换实现在android源代码frameworks/base/libs/ui/EventHub.cpp
此文件处理来自底层的所有输入事件,并根据来源对事件进行分类处理,对于按键事件,处理过程如下:
(a)记录驱动名称为
(b)获取环境变量ANDROID_ROOT为系统路径(默认是/system,定义在android源代码/system/core/rootdir/init.rc文件中)
(c)查找路径为&系统路径/usr/keylayout/驱动名称.kl&的按键映射文件,如果不存在则默认用路径为&系统路径/usr/keylayout/qwerty.kl&
这个默认的按键映射文件,映射完成后再把经映射得到的android按键码&#20540;发给上层应用程序。
所以我们可以在内核中定义多个按键设备,然后为每个设备设定不同的按键映射文件,不定义则会默认用qwerty.kl
上面(2)步我们在内核中声明了一个名为&gpio-keys&的按键设备,此设备定义在内核drivers/input/keyboard/gpio_keys.c文件中
然后我们在内核启动过程中注册此设备:& platform_device_register(&gpio_keys);
然后我们可以自己定义一个名为gpio-keys.kl的android按键映射文件,此文件的定义可以参考querty.kl的内容,比如说我们想将MPF_PIN_GPIO3
对应的按键作android中的MENU键用,首先我们在内核中将MPF_PIN_GPIO3映射到KEY_F2,在内核include/linux/input.h中查找KEY_F2发现
#define KEY_F2&&&&&&&&&&& 60
参照KEY_F2的&#20540;我们在gpio-keys.kl中加入如下映射即可
key 60&&& MENU&&&&&&&&&&&&& WAKE
其它按键也照此添加,完成后将按键表放置到/system/usr/keylayout目录下即可。
(1)android按键设备的映射关系可以在logcat开机日志中找的到(查找EventHub即可)
(2)android按键设备由Window Manager负责,Window Manager从按键驱动读取内核按键码,然后将内核按键码转换成android按键码,转换完成
后Window Manager会将内核按键码和android按键码一起发给应用程序来使用,这一点一定要注意。
Android系统开发小知识-在android产品开发中添加新的编译模块
Android开发中用户内容定义在vendor目录下,而用户产品的内容都定义在vendor/&company_name&/&board_name&目录下
如果需要添加新的内容,可以在该目录下新建子目录,同时修改AndroidBoard.mk文件即可。比如说要添加一个按键映射文件:
(1)在vendor/&company_name&/&board_name&目录下建立一个keymaps子目录
(2)将我们需要的按键映射文件gpio-keys.kl和power-button.kl复制到keymaps目录下
(3)在keymaps目录下新建一个Mdroid.mk文件,内容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
file := $(TARGET_OUT_KEYLAYOUT)/gpio-keys.kl
ALL_PREBUILT &#43;= $(file)
$(file): $(LOCAL_PATH)/gpio-keys.kl | $(ACP)
&&& $(transform-prebuilt-to-target)
file := $(TARGET_OUT_KEYLAYOUT)/power-button.kl
ALL_PREBUILT &#43;= $(file)
$(file): $(LOCAL_PATH)/power-button.kl | $(ACP)
&&& $(transform-prebuilt-to-target)
(4)在vendor/&company_name&/&board_name&目录下的AndroidBoard.mk添加如下内容:
include $(LOCAL_PATH)/keymaps/Mdroid.mk
Android系统移植(三)-按键字符表
上节讲android的Window Manager将内核按键码通过按键映射表转换成android按键码,
这节讲的是android按键码向android字符的转换,转换也是通过Window Manager来完成的
(1)原始按键字符表,我们知道一个按键是可以显示多个字符的,决定显示字符的是CAPS(大小写),FN,NUNMBER等按键
举例如下:
[type=QWERTY]&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
# keycode&&&&&& display number& base&&& caps&&& fn&&&&& caps_fn
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
A&&&&&&&&&&&&&& 'A'&&&& '2'&&&& 'a'&&&& 'A'&&&& '#'&&&& 0x00
B&&&&&&&&&&&&&& 'B'&&&& '2'&&&& 'b'&&&& 'B'&&&& '&'&&&& 0x00
C&&&&&&&&&&&&&& 'C'&&&& '2'&&&& 'c'&&&& 'C'&&&& '9'&&&& 0x00E7
D&&&&&&&&&&&&&& 'D'&&&& '3'&&&& 'd'&&&& 'D'&&&& '5'&&&& 0x00
E&&&&&&&&&&&&&& 'E'&&&& '3'&&&& 'e'&&&& 'E'&&&& '2'&&&& 0x0301
F&&&&&&&&&&&&&& 'F'&&&& '3'&&&& 'f'&&&& 'F'&&&& '6'&&&& 0x00A5
G&&&&&&&&&&&&&& 'G'&&&& '4'&&&& 'g'&&&& 'G'&&&& '-'&&&& '_'
H&&&&&&&&&&&&&& 'H'&&&& '4'&&&& 'h'&&&& 'H'&&&& '['&&&& '{'
I&&&&&&&&&&&&&& 'I'&&&& '4'&&&& 'i'&&&& 'I'&&&& '$'&&&& 0x0302
J&&&&&&&&&&&&&& 'J'&&&& '5'&&&& 'j'&&&& 'J'&&&& ']'&&&& '}'
K&&&&&&&&&&&&&& 'K'&&&& '5'&&&& 'k'&&&& 'K'&&&& '&'&&&& '~'
L&&&&&&&&&&&&&& 'L'&&&& '5'&&&& 'l'&&&& 'L'&&&& '''&&&& '`'
M&&&&&&&&&&&&&& 'M'&&&& '6'&&&& 'm'&&&& 'M'&&&& '!'&&&& 0x00
N&&&&&&&&&&&&&& 'N'&&&& '6'&&&& 'n'&&&& 'N'&&&& '&'&&&& 0x0303
O&&&&&&&&&&&&&& 'O'&&&& '6'&&&& 'o'&&&& 'O'&&&& '('&&&& 0x00
P&&&&&&&&&&&&&& 'P'&&&& '7'&&&& 'p'&&&& 'P'&&&& ')'&&&& 0x00
Q&&&&&&&&&&&&&& 'Q'&&&& '7'&&&& 'q'&&&& 'Q'&&&& '*'&&&& 0x0300
R&&&&&&&&&&&&&& 'R'&&&& '7'&&&& 'r'&&&& 'R'&&&& '3'&&&& 0x20AC
S&&&&&&&&&&&&&& 'S'&&&& '7'&&&& 's'&&&& 'S'&&&& '4'&&&& 0x00DF
T&&&&&&&&&&&&&& 'T'&&&& '8'&&&& 't'&&&& 'T'&&&& '&#43;'&&&& 0x00A3
U&&&&&&&&&&&&&& 'U'&&&& '8'&&&& 'u'&&&& 'U'&&&& '&'&&&& 0x0308
V&&&&&&&&&&&&&& 'V'&&&& '8'&&&& 'v'&&&& 'V'&&&& '='&&&& '^'
W&&&&&&&&&&&&&& 'W'&&&& '9'&&&& 'w'&&&& 'W'&&&& '1'&&&& 0x00
X&&&&&&&&&&&&&& 'X'&&&& '9'&&&& 'x'&&&& 'X'&&&& '8'&&&& 0xEF00
Y&&&&&&&&&&&&&& 'Y'&&&& '9'&&&& 'y'&&&& 'Y'&&&& '%'&&&& 0x00A1
Z&&&&&&&&&&&&&& 'Z'&&&& '9'&&&& 'z'&&&& 'Z'&&&& '7'&&&& 0x00
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
# on pc keyboards
COMMA&&&&&&&&&& ','&&&& ','&&&& ','&&&& ';'&&&& ';'&&&& '|'
PERIOD&&&&&&&&& '.'&&&& '.'&&&& '.'&&&& ':'&&&& ':'&&&& 0x2026
AT&&&&&&&&&&&&& &&&& '0'&&&& &&&& '0'&&&& '0'&&&& 0x2022
SLASH&&&&&&&&&& '/'&&&& '/'&&&& '/'&&&& '?'&&&& '?'&&&& '\'
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
SPACE&&&&&&&&&& 0x20&&& 0x20&&& 0x20&&& 0x20&&& 0xEF01& 0xEF01
ENTER&&&&&&&& 0xa&&&& 0xa&&&& 0xa&&&& 0xa&&&& 0xa&&&& 0xa
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
TAB&&&&&&&&&&&& 0x9&&&& 0x9&&&& 0x9&&&& 0x9&&&& 0x9&&&& 0x9
0&&&&&&&&&&&&&& '0'&&&& '0'&&&& '0'&&&& ')'&&&& ')'&&&& ')'
1&&&&&&&&&&&&&& '1'&&&& '1'&&&& '1'&&&& '!'&&&& '!'&&&& '!'
2&&&&&&&&&&&&&& '2'&&&& '2'&&&& '2'&&&& &&&& &&&&
3&&&&&&&&&&&&&& '3'&&&& '3'&&&& '3'&&&& '#'&&&& '#'&&&& '#'
4&&&&&&&&&&&&&& '4'&&&& '4'&&&& '4'&&&& '$'&&&& '$'&&&& '$'
5&&&&&&&&&&&&&& '5'&&&& '5'&&&& '5'&&&& '%'&&&& '%'&&&& '%'
6&&&&&&&&&&&&&& '6'&&&& '6'&&&& '6'&&&& '^'&&&& '^'&&&& '^'
7&&&&&&&&&&&&&& '7'&&&& '7'&&&& '7'&&&& '&'&&&& '&'&&&& '&'
8&&&&&&&&&&&&&& '8'&&&& '8'&&&& '8'&&&& '*'&&&& '*'&&&& '*'
9&&&&&&&&&&&&&& '9'&&&& '9'&&&& '9'&&&& '('&&&& '('&&&& '('
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
GRAVE&&&&&&&&&& '`'&&&& '`'&&&& '`'&&&& '~'&&&& '`'&&&& '~'
MINUS&&&&&&&&&& '-'&&&& '-'&&&& '-'&&&& '_'&&&& '-'&&&& '_'
EQUALS&&&&&&&&& '='&&&& '='&&&& '='&&&& '&#43;'&&&& '='&&&& '&#43;'
LEFT_BRACKET&&& '['&&&& '['&&&& '['&&&& '{'&&&& '['&&&& '{'
RIGHT_BRACKET&& ']'&&&& ']'&&&& ']'&&&& '}'&&&& ']'&&&& '}'
BACKSLASH&&&&&& '\'&&&& '\'&&&& '\'&&&& '|'&&&& '\'&&&& '|'
SEMICOLON&&&&&& ';'&&&& ';'&&&& ';'&&&& ':'&&&& ';'&&&& ':'
APOSTROPHE&&&&& '''&&&& '''&&&& '''&&&& '&'&&&& '''&&&& '&'
STAR&&&&&&&&&&& '*'&&&& '*'&&&& '*'&&&& '*'&&&& '*'&&&& '*'
POUND&&&&&&&&&& '#'&&&& '#'&&&& '#'&&&& '#'&&&& '#'&&&& '#'
PLUS&&&&&&&&&&& '&#43;'&&&& '&#43;'&&&& '&#43;'&&&& '&#43;'&&&& '&#43;'&&&& '&#43;'
(2)android为了减少载入时间,并没有使用原始按键表文件,而是将其转换成二进制文件
转换的工具源代码在android源代码build/tools/kcm目录下,android在编译过程中会
首先编译转换工具,然后利用转换工具将android源代码sdk/emulator/keymaps目录下
的qwerty.kcm和qwerty2.kcm文件分别转换成qwerty.kcm.bin和qwerty2.kcm.bin
转换后的二进制文件复制到out/target/product/&board_name&/system/usr/keychars
目录下,也就是目标平台的/system/usr/keychars目录中。
(3)Window Manager对按键的处理在android源代码frameworks/base/libs/ui/EventHub.cpp文件中
Window Manager从内核接收到一个按键输入事件后会首先调用按键映射表将内核按键码映射成android按键码(这部分上节已讲),然后会
将android按键码转换成字符,具体过程如下:
(a)设置系统系统属性hw.keyboards.设备号.devname的&#20540;为设备名
以上节的gpio-keys设备为例,会设置系统属性hw.keyboards.65539.devname的&#20540;为gpio-keys
(b)载入按键字符表,首先载入/system/usr/keychars目录下的设备名.kcm.bin文件(此例即gpio-keys.kcm.bin文件),如果载入失败
则载入该目录下的querty.kcm.bin.
(c)利用载入的按键字符表将android按键转换成按键字符发给上层应用程序。
(4)一般情况下一个控制按键是不需要作按键字符表的,系统会调用默认的去处理,但是如果要开发一个全功能键盘(包含了字母和数字),那可能就需要
自己作一个专用的按键字符表了。
android系统开发小问题-启动过程中android字符没有显示出来
android目标平台可以正常启动,但是启动过程中的android字符没有显示出来,这个是linux内核配置的问题
打开内核framebuffer控制台即可。
(1)make menuconifg后选择Device Drivers-&Graphics support-&Console display driver support-&Framebuffer Console support
然后打开相关的几个配置选项即可。
(2)直接修改内核配置文件,如下:
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
CONFIG_FONTS=y
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
CONFIG_FONT_6x11=y
# CONFIG_FONT_7x14 is not set
# CONFIG_FONT_PEARL_8x8 is not set
# CONFIG_FONT_ACORN_8x8 is not set
# CONFIG_FONT_MINI_4x6 is not set
# CONFIG_FONT_SUN8x16 is not set
# CONFIG_FONT_SUN12x22 is not set
# CONFIG_FONT_10x18 is not set
(3)android启动过程中的android字符显示在源代码的system/core/init.c中,如下:
&&& if( load_565rle_image(INIT_IMAGE_FILE) ) {
&&& fd = open(&/dev/tty0&, O_WRONLY);
&&& if (fd &= 0) {
&&&&&&& const char *
&&&&&&&&&&& msg = &\n&
&&&&&&& &\n&
&&&&&&& &\n&
&&&&&&& &\n&
&&&&&&& &\n&
&&&&&&& &\n&
&&&&&&& &\n&& // console is 40 cols x 30 lines
&&&&&&& &\n&
&&&&&&& &\n&
&&&&&&& &\n&
&&&&&&& &\n&
&&&&&&& &\n&
&&&&&&& &\n&
&&&&&&& &\n&
&&&&&&& &&&&&&&&&&&&& A N D R O I D &;
&&&&&&& write(fd, msg, strlen(msg));
&&&&&&& close(fd);
android启动过程配置文件的解析与语法
(1)android启动文件系统后调用的第一个应用程序是/init,此文件的很重要的内容是解析了init.rc和init.xxx.rc
两个配置文件,然后执行解析出来的任务。相关代码在android源代码/system/core/init/init.c文件中,如下:
&&& parse_config_file(&/init.rc&);
&&& /* pull the kernel commandline and ramdisk properties file in */
&&& qemu_init();
&&& import_kernel_cmdline(0);
&&& get_hardware_name();
&&& snprintf(tmp, sizeof(tmp), &/init.%s.rc&, hardware);
&&& parse_config_file(tmp);
(2)从上面代码可以看到,第一个配置文件名称固定为init.rc,而第二个配置文件&#26684;式为init.xxx.rc,其中xxx部分的内容
是从内核读取的,具体是读取文件/proc/cpuinfo中的Hardware部分,然后截取其部分内容。Hardware部分是定义在内核的
主板定义文件中,我的平台是定义在内核arch/arm/mach-mmp/merlin.c中,我的平台定义如下:
MACHINE_START(ARDENT_MERLIN, &PXA168-based Merlin Platform&)
&&& .phys_io = APB_PHYS_BASE,
&&& .boot_params = 0x,
&&& .io_pg_offst = (APB_VIRT_BASE && 18) & 0xfffc,
&&& .map_io = pxa_map_io,
&&& .init_irq = pxa168_init_irq,
&&& .timer = &pxa168_timer,
&&& .init_machine = merlin_init,
MACHINE_END
这样截取到的hardware部分的内容就为pxa168-based,也就是说我的平台的第二个配置文件应该命名为init.pxa168-based.rc
(3)从上面看init.xxx.rc中的xxx内容是取决是内核中主板的定义的,如果觉得麻烦,可以将其在代码中写死,例如:
&&& parse_config_file(“init.merlin.rc”);
(4)配置文件的语法如下:
(a)配置文件的内容包含有4种:
&&&& 动作(Action)
&&&& 命令(Commands)
&&&& 服务(Services)
&&&& 选项(Options)
(b)动作和命令一起使用,形式如下:
on &trigger&
& &command&
& &command&
& &command&
其中trigger是触发条件,也就是说在满足触发条件的情况下执行1个或多个相应的命令,举例如下:
on property:persist.service.adb.enable=1
&&& start adbd
(c)服务和选项一起使用,形式如下:
& service &name& &pathname& [ &argument& ]*
& &option&
& &option&
上面内容解释为:
& service 服务名称服务对应的命令的路径 命令的参数
举例如下:
service ril-daemon /system/bin/rild
&&& socket rild stream 660 root radio
&&& socket rild-debug stream 660 radio system
&&& user root
&&& group radio cache inet misc audio
上面的服务对应到/system/bin/rild命令,没有参数,服务名称为ril-daemon,后面的内容都是服务的选项。
(d)选项是影响服务启动和运行的参数,主要的选项如下:
disabled& 禁用服务,此服务开机时不会自动启动,但是可以在应用程序中手动启动它。
socket &type& &name& &perm& [ &user& [ &group& ] ]
套接字&&& 类型&&&&&&& 名称&&&&&&&&&& 权限&&&&&&&&&& 用户&&&&&&&&&& 组
创建一个名为/dev/socket/&name&,然后把它的fd传给启动程序
类型type的&#20540;为dgram或者stream
perm表示该套接字的访问权限,user和group表示改套接字所属的用户和组,这两个参数默认都是0,因此可以不设置。
user &username&
执行服务前切换到用户&username&,此选项默认是root,因此可以不设置。
group &groupname& [ &groupname& ]*
执行服务前切换到组&groupname&,此选项默认是root,因此可以不设置
capability [ &capability& ]&#43;
执行服务前设置linux capability,没什么用。
服务只启动一次,一旦关闭就不能再启动。
class &name&
为服务指定一个类别,默认为&default&,同一类别的服务必须一起启动和停止
(e)动作触发条件&trigger&
boot& 首个触发条件,初始化开始(载入配置文件)的时候触发
&name&=&value&
当名为&name&的属性(property)的&#20540;为&value&的时候触发
device-added-&path&
路径为&path&的设置添加的时候触发
device-removed-&path&
路径为&path&的设置移除的时候触发
service-exited-&name&
名为&name&的服务关闭的时候触发
(f)命令(Command)的形式
exec &path& [ &argument& ]*
复制(fork)和执行路径为&path&的应用程序,&argument&为该应用程序的参数,在该应用程序执行完前,此命令会屏蔽,
export &name& &value&
声明名为&name&的环境变量的&#20540;为&value&,声明的环境变量是系统环境变量,启动后一直有效。
ifup &interface&
启动名为&interface&的网络接口
import &filename&
加入新的位置文件,扩展当前的配置。
hostname &name&
设置主机名
class_start &serviceclass&
启动指定类别的所有服务
class_stop &serviceclass&
停止指定类别的所有服务
domainname &name&
insmod &path&
加载路径为&path&的内核模块
mkdir &path&
创建路径为&path&目录
mount &type& &device& &dir& [ &mountoption& ]*
挂载类型为&type&的设备&device&到目录&dir&,&mountoption&为挂载参数,距离如下:
&&& mount ubifs ubi1_0 /data nosuid nodev
暂时未定义
setprop &name& &value&
设置名为&name&的系统属性的&#20540;为&value&
setrlimit &resource& &cur& &max&
设置资源限制,举例:
# set RLIMIT_NICE to allow priorities from 19 to -20
&&& setrlimit 13 40 40
没看懂是什么意思。
start &service&
启动服务(如果服务未运行)
stop &service&
停止服务(如果服务正在运行)
symlink &target& &path&
创建一个从&path&指向&target&的符号链接,举例:
&&& symlink /system/etc /etc
write &path& &string& [ &string& ]*
打开路径为&path&的文件并将一个多这多个字符串写入到该文件中。
(g)系统属性(Property)
android初始化过程中会修改一些属性,通过getprop命令我们可以看到属性&#20540;,这些属性指示了某些动作或者服务的状态,主要如下:
init.action&&&&& 如果当前某个动作正在执行则init.action属性的&#20540;等于该动作的名称,否则为&&
init.command&&&& 如果当前某个命令正在执行则init.command属性的&#20540;等于该命令的名称,否则为&&
init.svc.&name&& 此属性指示个名为&name&的服务的状态(&stopped&, &running&, 或者 &restarting&).
android系统开发(四)-触摸屏tslib移植(内核)和原理分析
首先了解一下tslib的运行原理,tslib的运行分成两部分
在LCD固定坐标位置依次显示出5个坐标让用户触摸,把LCD坐标和用户触摸时驱动屏驱动底层的坐标总共5组&#20540;保存起来
运行tslib库的算法对其进行运算,得出校准用7个&#20540;
每次触摸屏驱动读取到硬件坐标时应用校准用的7个&#20540;对该坐标进行一次运算,然后将运算后的坐标作为正常坐标即可。
按照上面的原理,
(1)我们先修改内核部分,我的平台用的触摸屏幕驱动是tsc2007,驱动文件为内核/drivers/input/touchscreen
目录下的tsc2007.c和ts_linear.c
其中,ts_linear.c中定义的是校准模块,该模块在proc文件系统中建立了7个文件,用来存放校准用的7个点,7的点的默认&#20540;
为1,0,0,0,1,0,1,对应的目标平台文件系统的位置为/proc/sys/dev/ts_device目录下a0,a1,a2,a3,a4,a5,a6等7个文件
此模块中还定义了一个校准函数ts_linear_scale,此函数的主要内容是读取a0,a1,a2,a3,a4,a5,a6等7个文件中的&#20540;作为7个
校准&#20540;与传入的触摸平坐标&#20540;进行运算,返回运算结果。
ts_linear_scale函数定义如下:
int ts_linear_scale(int *x, int *y, int swap_xy)
&&& int xtemp,
&&& xtemp = *x;
&&& ytemp = *y;
&&& if (cal.a[6] == 0)
&&&&&&& return -EINVAL;
&&& *x = (cal.a[2] &#43; cal.a[0] * xtemp &#43; cal.a[1] * ytemp) / cal.a[6];
&&& *y = (cal.a[5] &#43; cal.a[3] * xtemp &#43; cal.a[4] * ytemp) / cal.a[6];
&&& if (swap_xy) {
&&&&&&& int tmp = *x;
&&&&&&& *x = *y;
&&&&&&& *y =
&&& return 0;
ts2007.c为触摸屏驱,与其他驱动不同的地方是在取得硬件坐标&#20540;发送之前先调用了ts_linear_scale函数对坐标&#20540;进行了校准
&&&&&&&&&&& if (x & 0 && y & 0)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& ts_linear_scale(&x, &y, invert);
&&&&&&&&&&&&&&& input_report_abs(input, ABS_X, x);
&&&&&&&&&&&&&&& input_report_abs(input, ABS_Y, y);
&&&&&&&&&&&&&&& input_report_abs(input, ABS_PRESSURE, 255);
&&&&&&&&&&&&&&& input_report_abs(input, ABS_TOOL_WIDTH, 1);
&&&&&&&&&&&&&&& input_report_key(input, BTN_TOUCH, 1);
&&&&&&&&&&&&&&& input_sync(input);
&&&&&&&&&&& }
(2)在android源代码/system/core/rootdir/init.rc文件中添加tslib相关的宏定义如下:
# touchscreen parameters
&&& export TSLIB_FBDEVICE /dev/graphics/fb0
&&& export TSLIB_CALIBFILE /data/etc/pointercal
&&& export TSLIB_CONFFILE& /system/etc/ts.conf
&&& export TSLIB_TRIGGERDEV /dev/input/event0
&&& export TSLIB_TSDEVICE /dev/input/event1
(2)移植tslib库到android系统,比较麻烦,看下一节的内容。
(3)校验程序完成后会将生成的7个校准&#20540;写入到环境变量TSLIB_CALIBFILE对应的路径/data/etc/pointercal文件中
(4)校验完后将pointercal文件中的7个&#20540;分别写入到/proc/sys/dev/ts_device目录下a0,a1,a2,a3,a4,a5,a6文件即可。
(5)开机启动的时候我们编写一个应用程序,首先判断环境变量TSLIB_CALIBFILE对应的路径/data/etc/pointercal文件是否存在,如果
文件存在而且非空,则将该文件中的7个&#20540;取出来分别写入到/proc/sys/dev/ts_device目录下a0,a1,a2,a3,a4,a5,a6文件
(6)为了确保未校验前触摸屏可用,我们将一次校验后得出的7个坐标&#20540;作为初始&#20540;,修改到内核ts_linear.c文件中。
下面是源代码:
ts_linear.c文件
&*& Touchscreen Linear Scale Adaptor
&*& Copyright (C) 2009 Marvell Corporation
&*& Author: Mark F. Brown &&
&*& Based on tslib 1.0 plugin linear.c by Russel King
&* This library is licensed under GPL.
#include &linux/module.h&
#include &linux/init.h&
#include &linux/kernel.h&
#include &linux/input.h&
#include &linux/interrupt.h&
#include &linux/wait.h&
#include &linux/delay.h&
#include &linux/platform_device.h&
#include &linux/proc_fs.h&
#include &linux/sysctl.h&
#include &asm/system.h&
&* sysctl-tuning infrastructure.
static struct ts_calibration {
/* Linear scaling and offset parameters for x,y (can include rotation) */
&&& int a[7];
static ctl_table ts_proc_calibration_table[] = {
&&&& .ctl_name = CTL_UNNUMBERED,
&&&& .procname = &a0&,
&&&& .data = &cal.a[0],
&&&& .maxlen = sizeof(int),
&&&& .mode = 0666,
&&&& .proc_handler = &proc_dointvec,
&&&& .ctl_name = CTL_UNNUMBERED,
&&&& .procname = &a1&,
&&&& .data = &cal.a[1],
&&&& .maxlen = sizeof(int),
&&&& .mode = 0666,
&&&& .proc_handler = &proc_dointvec,
&&&& .ctl_name = CTL_UNNUMBERED,
&&&& .procname = &a2&,
&&&& .data = &cal.a[2],
&&&& .maxlen = sizeof(int),
&&&& .mode = 0666,
&&&& .proc_handler = &proc_dointvec,
&&&& .ctl_name = CTL_UNNUMBERED,
&&&& .procname = &a3&,
&&&& .data = &cal.a[3],
&&&& .maxlen = sizeof(int),
&&&& .mode = 0666,
&&&& .proc_handler = &proc_dointvec,
&&&& .ctl_name = CTL_UNNUMBERED,
&&&& .procname = &a4&,
&&&& .data = &cal.a[4],
&&&& .maxlen = sizeof(int),
&&&& .mode = 0666,
&&&& .proc_handler = &proc_dointvec,
&&&& .ctl_name = CTL_UNNUMBERED,
&&&& .procname = &a5&,
&&&& .data = &cal.a[5],
&&&& .maxlen = sizeof(int),
&&&& .mode = 0666,
&&&& .proc_handler = &proc_dointvec,
&&&& .ctl_name = CTL_UNNUMBERED,
&&&& .procname = &a6&,
&&&& .data = &cal.a[6],
&&&& .maxlen = sizeof(int),
&&&& .mode = 0666,
&&&& .proc_handler = &proc_dointvec,
&&& {.ctl_name = 0}
static ctl_table ts_proc_root[] = {
&&&& .ctl_name = CTL_UNNUMBERED,
&&&& .procname = &ts_device&,
&&&& .mode = 0555,
&&&& .child = ts_proc_calibration_table,
&&& {.ctl_name = 0}
static ctl_table ts_dev_root[] = {
&&&& .ctl_name = CTL_DEV,
&&&& .procname = &dev&,
&&&& .mode = 0555,
&&&& .child = ts_proc_root,
&&& {.ctl_name = 0}
static struct ctl_table_header *ts_sysctl_
int ts_linear_scale(int *x, int *y, int swap_xy)
&&& int xtemp,
&&& xtemp = *x;
&&& ytemp = *y;
&&& if (cal.a[6] == 0)
&&&&&&& return -EINVAL;
&&& *x = (cal.a[2] &#43; cal.a[0] * xtemp &#43; cal.a[1] * ytemp) / cal.a[6];
&&& *y = (cal.a[5] &#43; cal.a[3] * xtemp &#43; cal.a[4] * ytemp) / cal.a[6];
&&& if (swap_xy) {
&&&&&&& int tmp = *x;
&&&&&&& *x = *y;
&&&&&&& *y =
&&& return 0;
EXPORT_SYMBOL(ts_linear_scale);
static int __init ts_linear_init(void)
&&& ts_sysctl_header = register_sysctl_table(ts_dev_root);
&&& /* Use default values that leave ts numbers unchanged after transform */
&&& cal.a[0] = 1;
&&& cal.a[1] = 0;
&&& cal.a[2] = 0;
&&& cal.a[3] = 0;
&&& cal.a[4] = 1;
&&& cal.a[5] = 0;
&&& cal.a[6] = 1;
&&& return 0;
static void __exit ts_linear_cleanup(void)
&&& unregister_sysctl_table(ts_sysctl_header);
module_init(ts_linear_init);
module_exit(ts_linear_cleanup);
MODULE_DESCRIPTION(&touch screen linear scaling driver&);
MODULE_LICENSE(&GPL&);
ts2007.c文件
&*& linux/drivers/input/touchscreen/tsc2007.c
&*& touch screen driver for tsc2007
&*& Copyright (C) 2006, Marvell Corporation
&*& This prog you can redistribute it and/or modify
&*& it under the terms of the GNU General Public License version 2 as
&*& published by the Free Software Foundation.
#include &linux/module.h&
#include &linux/init.h&
#include &linux/kernel.h&
#include &linux/input.h&
#include &linux/interrupt.h&
#include &linux/wait.h&
#include &linux/delay.h&
#include &linux/platform_device.h&
#include &linux/freezer.h&
#include &linux/proc_fs.h&
#include &linux/clk.h&
#include &linux/i2c.h&
#include &mach/gpio.h&
#include &linux/sysctl.h&
#include &asm/system.h&
extern int ts_linear_scale(int *x, int *y, int swap_xy);
/* Use MAV filter */
#define TSC_CMD_SETUP 0xb0
/* Use 12-bit */
#define TSC_CMD_X 0xc0
#define TSC_CMD_PLATEX 0x80
#define TSC_CMD_Y 0xd0
#define TSC_CMD_PLATEY 0x90
#define TSC_X_MAX 4096
#define TSC_Y_MAX 4096
#define TSC_X_MIN 0
#define TSC_Y_MIN 0
/* delay time for compute x, y, computed as us */
#define DEBUG
#ifdef DEBUG
#define TS_DEBUG(fmt,args...) printk(KERN_DEBUG fmt, ##args )
#define TS_DEBUG(fmt,args...)
static int x_min=TSC_X_MIN;
static int y_min=TSC_Y_MIN;
static int x_max=TSC_X_MAX;
static int y_max=TSC_Y_MAX;
static int invert = 0;
static int debounce_time& = 150;
static int init_debounce =
static int delay_time = 1;
enum tsc2007_status {
&&& PEN_UP,
&&& PEN_DOWN,
struct _tsc2007 {
&&& struct input_dev *
&&&&&&&&&& /* X sample values */
&&&&&&&&&& /* Y sample values */
&&& struct work_struct irq_
&&& struct i2c_client *
&&& unsigned long last_
struct _tsc2007 *g_tsc2007;
/* update abs params when min and max coordinate values are set */
int tsc2007_proc_minmax(struct ctl_table *table, int write, struct file *filp,
&&&&&&&&&&&&&&&&&&&& void __user *buffer, size_t *lenp, loff_t *ppos)
&&& struct _tsc2007 *tsc2007= g_tsc2007;
&&& struct input_dev *input = tsc2007-&
&&& /* update value */
&&& int ret = proc_dointvec(table, write, filp, buffer, lenp, ppos);
&&& /* updated abs params */
&&& if (input) {
&&&&&&& TS_DEBUG(KERN_DEBUG &update x_min %d x_max %d&
&&&&&&&&&&& & y_min %d y_max %d\n&, x_min, x_max,
&&&&&&&&&&& y_min, y_max);
&&&&&&& input_set_abs_params(input, ABS_X, x_min, x_max, 0, 0);
&&&&&&& input_set_abs_params(input, ABS_Y, y_min, y_max, 0, 0);
static ctl_table tsc2007_proc_table[] = {
&&&&&&& .ctl_name&&& = CTL_UNNUMBERED,
&&&&&&& .procname&&& = &x-max&,
&&&&&&& .data&&&&&&& = &x_max,
&&&&&&& .maxlen&&&&&&& = sizeof(int),
&&&&&&& .mode&&&&&&& = 0666,
&&&&&&& .proc_handler&&& = &tsc2007_proc_minmax,
&&&&&&& .ctl_name&&& = CTL_UNNUMBERED,
&&&&&&& .procname&&& = &y-max&,
&&&&&&& .data&&&&&&& = &y_max,
&&&&&&& .maxlen&&&&&&& = sizeof(int),
&&&&&&& .mode&&&&&&& = 0666,
&&&&&&& .proc_handler&&& = &tsc2007_proc_minmax,
&&&&&&& .ctl_name&&& = CTL_UNNUMBERED,
&&&&&&& .procname&&& = &x-min&,
&&&&&&& .data&&&&&&& = &x_min,
&&&&&&& .maxlen&&&&&&& = sizeof(int),
&&&&&&& .mode&&&&&&& = 0666,
&&&&&&& .proc_handler&&& = &tsc2007_proc_minmax,
&&&&&&& .ctl_name&&& = CTL_UNNUMBERED,
&&&&&&& .procname&&& = &y-min&,
&&&&&&& .data&&&&&&& = &y_min,
&&&&&&& .maxlen&&&&&&& = sizeof(int),
&&&&&&& .mode&&&&&&& = 0666,
&&&&&&& .proc_handler&&& = &tsc2007_proc_minmax,
&&&&&&& .ctl_name&&& = CTL_UNNUMBERED,
&&&&&&& .procname&&& = &invert_xy&,
&&&&&&& .data&&&&&&& = &invert,
&&&&&&& .maxlen&&&&&&& = sizeof(int),
&&&&&&& .mode&&&&&&& = 0666,
&&&&&&& .proc_handler&&& = &proc_dointvec,
&&&&&&& .ctl_name&&& = CTL_UNNUMBERED,
&&&&&&& .procname&&& = &debounce_time&,
&&&&&&& .data&&&&&&& = &debounce_time,
&&&&&&& .maxlen&&&&&&& = sizeof(int),
&&&&&&& .mode&&&&&&& = 0666,
&&&&&&& .proc_handler&&& = &proc_dointvec,
&&&&&&& .ctl_name&&& = CTL_UNNUMBERED,
&&&&&&& .procname&&& = &delay_time&,
&&&&&&& .data&&&&&&& = &delay_time,
&&&&&&& .maxlen&&&&&&& = sizeof(int),
&&&&&&& .mode&&&&&&& = 0666,
&&&&&&& .proc_handler&&& = &proc_dointvec,
&&& { .ctl_name = 0 }
static ctl_table tsc2007_proc_root[] = {
&&&&&&& .ctl_name&&& = CTL_UNNUMBERED,
&&&&&&& .procname&&& = &ts_device&,
&&&&&&& .mode&&&&&&& = 0555,
&&&&&&& .child&&&&&&& = tsc2007_proc_table,
&&& { .ctl_name = 0 }
static ctl_table tsc2007_proc_dev_root[] = {
&&&&&&& .ctl_name&&& = CTL_DEV,
&&&&&&& .procname&&& = &dev&,
&&&&&&& .mode&&&&&&& = 0555,
&&&&&&& .child&&&&&&& = tsc2007_proc_root,
&&& { .ctl_name = 0 }
static struct ctl_table_header *sysctl_
static int __init init_sysctl(void)
&&& sysctl_header = register_sysctl_table(tsc2007_proc_dev_root);
&&& return 0;
static void __exit cleanup_sysctl(void)
&&& unregister_sysctl_table(sysctl_header);
static int tsc2007_measure(struct i2c_client *client, int *x, int * y)
&&& u8 x_buf[2] = {0, 0};
&&& u8 y_buf[2] = {0, 0};
&&& i2c_smbus_write_byte(client, TSC_CMD_PLATEX);
&&& msleep_interruptible(delay_time);
&&& i2c_smbus_write_byte(client, TSC_CMD_X);
&&& i2c_master_recv(client, x_buf, 2);
&&& *x = (x_buf[0]&&4) | (x_buf[1] &&4);
&&& i2c_smbus_write_byte(client, TSC_CMD_PLATEY);
&&& msleep_interruptible(delay_time);
&&& i2c_smbus_write_byte(client, TSC_CMD_Y);
&&& i2c_master_recv(client, y_buf, 2);
&&& *y = (y_buf[0]&&4) | (y_buf[1] &&4);
&&& *y = 4096 - *y; //added by allen
&&& printk(&\ntouchscreen x = 0x%x, y = 0x%x\n&,*x,*y);
&&& return 0;
static void tsc2007_irq_work(struct work_struct *work)
&&& struct _tsc2007 *tsc2007= g_tsc2007;
&&& struct i2c_client *client = tsc2007-&
&&& struct input_dev *input = tsc2007-&
&&& int x = -1, y = -1, is_valid = 0;
&&& int tmp_x = 0, tmp_y = 0;
&&& int gpio = irq_to_gpio(client-&irq);
&&& /* Ignore if PEN_DOWN */
&&& if(PEN_UP == tsc2007-&status){
&&&&&&& if (gpio_request(gpio, &tsc2007 touch detect&)) {
&&&&&&&&&&& printk(KERN_ERR &Request GPIO failed, gpio: %X\n&, gpio);
&&&&&&&&&&&
&&&&&&& gpio_direction_input(gpio);&&&
&&&&&&& while(0 == gpio_get_value(gpio)){
&&&&&&&&&&&&&&&&&&&&&&& if ((jiffies_to_msecs(
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ((long)jiffies - (long)tsc2007-&last_touch)) &
&&&&&&&&&&&&&&&& debounce_time &&
&&&&&&&&&&&&&&& tsc2007-&status == PEN_DOWN) ||
&&&&&&&&&&&&&&& init_debounce)
&&&&&&&&&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&& init_debounce =
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& tsc2007_measure(client, &tmp_x, &tmp_y);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& TS_DEBUG(KERN_DEBUG
&&&&&&&&&&&&&&& &dropping pen touch %lu %lu (%u)\n&,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& jiffies, tsc2007-&last_touch,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& jiffies_to_msecs(
&&&&&&&&&&&&&&& (long)jiffies - (long)tsc2007-&last_touch));
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& schedule();
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&& /* continue report x, y */
&&&&&&&&&&& if (x & 0 && y & 0)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& ts_linear_scale(&x, &y, invert);
&&&&&&&&&&&&&&& input_report_abs(input, ABS_X, x);
&&&&&&&&&&&&&&& input_report_abs(input, ABS_Y, y);
&&&&&&&&&&&&&&& input_report_abs(input, ABS_PRESSURE, 255);
&&&&&&&&&&&&&&& input_report_abs(input, ABS_TOOL_WIDTH, 1);
&&&&&&&&&&&&&&& input_report_key(input, BTN_TOUCH, 1);
&&&&&&&&&&&&&&& input_sync(input);
&&&&&&&&&&& }
&&&&&&&&&&& tsc2007-&status = PEN_DOWN;
&&&&&&&&&&& tsc2007_measure(client, &x, &y);
&&&&&&&&&&& TS_DEBUG(KERN_DEBUG &pen down x=%d y=%d!\n&, x, y);
&&&&&&&&&&& is_valid = 1;
&&&&&&&&&&& schedule();
&&&&&&& if (is_valid)
&&&&&&&&&&& /*consider PEN_UP */
&&&&&&&&&&& tsc2007-&status = PEN_UP;
&&&&&&&&&&& input_report_abs(input, ABS_PRESSURE, 0);
&&&&&&&&&&& input_report_abs(input, ABS_TOOL_WIDTH, 1);
&&&&&&&&&&& input_report_key(input, BTN_TOUCH, 0);
&&&&&&&&&&& input_sync(input);
&&&&&&&&&&& tsc2007-&last_touch =
&&&&&&&&&&& TS_DEBUG(KERN_DEBUG &pen up!\n&);
&&&&&&& gpio_free(gpio);&&&
static irqreturn_t tsc2007_interrupt(int irq, void *dev_id)
&&& schedule_work(&g_tsc2007-&irq_work);
&&& return IRQ_HANDLED;
static int __devinit tsc2007_probe(struct i2c_client *client,
&&&&&&&&&&&&&&& const struct i2c_device_id *id)
&&& struct _tsc2007 *tsc2007;
&&& struct input_dev *input_
&&& tsc2007 = kzalloc(sizeof(struct _tsc2007), GFP_KERNEL);
&&& input_dev = input_allocate_device();
&&& g_tsc2007 = tsc2007;
&&& if (!tsc2007 || !input_dev) {
&&&&&&& ret = -ENOMEM;
&&&&&&& goto fail1;
&&& i2c_set_clientdata(client, tsc2007);
&&& tsc2007-&dev = input_
&&& input_dev-&name = &tsc2007&;
&&& input_dev-&phys = &tsc2007/input0&;
&&& //input_dev-&id.bustype = BUS_HOST;
&&& input_dev-&dev.parent = &client-&
&&& __set_bit(EV_KEY, input_dev-&evbit);
&&& __set_bit(BTN_TOUCH, input_dev-&keybit);
&&& __set_bit(EV_ABS, input_dev-&evbit);
&&& __set_bit(ABS_PRESSURE, input_dev-&evbit);
&&& __set_bit(ABS_X, input_dev-&evbit);
&&& __set_bit(ABS_Y, input_dev-&evbit);
&&& input_set_abs_params(input_dev, ABS_X, x_min, x_max, 0, 0);
&&& input_set_abs_params(input_dev, ABS_Y, y_min, y_max, 0, 0);
&&& input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0);
&&& ret = request_irq(client-&irq, tsc2007_interrupt,
&&&&&&& IRQF_DISABLED | IRQF_TRIGGER_FALLING,
&&&&&&&& &tsc2007 irq&, NULL);
&&& if (ret){
&&&&&&& printk(KERN_ERR &tsc2007 request irq failed\n&);
&&&&&&& goto fail2;
&&& ret = input_register_device(tsc2007-&dev);
&&& if (ret){
&&&&&&& printk(KERN_ERR &tsc2007 register device fail\n&);
&&&&&&& goto fail2;
&&& /*init */
&&& tsc2007-&status = PEN_UP;
&&& tsc2007-&client =
&&& tsc2007-&last_touch =
&&& INIT_WORK(&tsc2007-&irq_work, tsc2007_irq_work);
&&& /* init tsc2007 */
&&& i2c_smbus_write_byte(client, TSC_CMD_SETUP);
&&& return 0;
&&& free_irq(client-&irq, client);
&&& i2c_set_clientdata(client, NULL);
&&& input_free_device(input_dev);
&&& kfree(tsc2007);
static int __devexit tsc2007_remove(struct i2c_client *client)
&&& struct _tsc2007 *tsc2007 = i2c_get_clientdata(client);
&&& if(client-&irq)
&&&&&&& }

我要回帖

更多关于 vivo 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信