android系统按键从linux到java流程
- 格式:docx
- 大小:663.56 KB
- 文档页数:20
在linux下搭建android开发环境,和windows下的搭建有很大的区别,其搭建的顺序分别是java JDK安装---路径设置---eclipse下载---安装ADT插件---下载androidSDK,具体步骤可以总结如下:安装条件需要Linux操作系统,我用的是虚拟机加Ubuntu 11.10版本。
1、JDK下载安装。
(1)进入如下网址:/technetwork/java/javase/downloads/jdk-7u1-download-513651.html(2)下载.tar.gz文件(两个都可以),也可以下载其他版本,但是都必须是linux版本才可以,我下载的是java7.0版本,解压到/username/download目录下,解压命令为tar –zxvf 包名。
如下图(示例)(3)在/usr/local 目录下创建一个jdk7 的目录cd /usr/local && sudo mkdir jdk7将jdk7(上面解压的文件夹)目录复制到jdk7 目录下(注意:来源路径只是例子,应按实际输入)cd jdk7sudo cp –r /home/username/download/jdk1.6.0_23/* .命令解释:-r表示复制整个文件夹,*后面有个空格加“.”号,没有好像都不行,这个我在网上查了也没有详细解释,实验得出的。
(4)完成后,设置环境变量。
使用gedit 编辑profile文件,profile文件是为用户配置的配置文件,保存了一个用户的环境变量等,每个用户都有一个单独的该文件,包括root 用户。
sudo gedit ~/.profile在文件末尾增加以下内容:export JA VA_HOME=/usr/software/jdk7export CLASSPA TH=$CLASSPATH:$JA V A_HOME/lib:$JA V A_HOME/jre/libexport PATH=$PATH:$JA V A_HOME/bin:$JA V A_HOME/jre/bin(5)使用echo命令打印路径信息,并执行source ~/.profileecho $JA V A_HOMEecho $CLASSPATHecho $PATHsource ~/.profile (用于刷新配置文件)注:在后续操作中,特别是在eclipse中安装ADT插件的时候,需要用户级别为root,所以,为了安全起见,同样在root用户模式下重新操作(4)和(5)。
1.处理的内容和流程按键处理的过程,从驱动程序到Android 的Java 层受到的信息,键表示方式经过了两次转化,如下图所示。
键扫描码Scancode 是由Linux 的Input 驱动框架定义的整数类型。
键扫描码Scancode 经过一次转化后,形成按键的标签KeycodeLabel ,是一个字符串的表示形式。
按键的标签KeycodeLabel 经过转换后,再次形成整数型的按键码keycode 。
在Android 应用程序层,主要使用按键码keycode 来区分。
在本地框架层F:\XPcode\lib_Hi3716C_V100R002C00SPC010\froyo\frameworks\base\include\ui 的文件夹中KeycodeLabels.h ,按键码为整数值的格式,其定义KeyCode (枚举值)如下所示:1. typedefenumKeyCode {2. kKeyCodeUnknown = 0,3. kKeyCodeSoftLeft = 1,4. kKeyCodeSoftRight = 2,5. kKeyCodeHome = 3,6. kKeyCodeBack = 4,7. // ...... 省略中间按键码8. } KeyCode;进而在定义了KeycodeLabels.h 中定义了从字符串到整数的映射关系,数组KEYCODES ,定义如下所示:1. static constKeycodeLabel KEYCODES[] = {// {字符串,整数} 2. { "SOFT_LEFT", 1 },3. { "SOFT_RIGHT", 2 },4. { "HOME", 3 },5. { "BACK", 4 },6. { "CALL", 5 },7. { "ENDCALL", 6 },8. { "0", 7 }, // ...... 数字按键ScanCode(整签Keycodelabels(字符按键码keycode (整数型)9. { "1", 8 },10. { "2", 9 },11. { "3", 10 },12. { "4", 11 },13. { "5", 12 },14. { "6", 13 },15. { "7", 14 },16. { "8", 15 },17. { "9", 16 },18. { "STAR", 17 },19. // ...... 省略中间按键映射20. { "MENU", 82 },21. // ...... 省略中间按键映射22. { NULL, 0 }23. };数组KEYCODES表示的映射关系,左列的内容即表示按键标签KeyCodeLabel,右列的内容为按键码KeyCode(与KeyCode的数值对应)。
androidstartup原理Android是由Google开发的一套开放源代码的操作系统,主要用于移动设备和嵌入式系统。
它被广泛应用于智能手机、平板电脑、智能电视等移动设备中。
Android系统的启动过程是一个复杂的过程,涉及到很多不同的模块和组件。
下面将详细介绍Android系统的启动原理。
Android系统的启动过程主要包括五个阶段:引导加载程序、Linux内核初始化、系统服务初始化、应用程序启动和进程初始化。
首先是引导加载程序阶段。
当设备开机时,引导加载程序会被加载并执行。
引导加载程序主要负责初始化硬件设备,并加载第二阶段的引导加载程序。
在这个阶段,设备会进行一些硬件自检和初始化操作,确保设备能够正常运行。
接着是Linux内核初始化阶段。
在这个阶段,Linux内核会被加载并执行。
Linux内核是Android系统的核心部分,它负责管理系统的各种硬件资源和提供系统服务,同时也是Android系统与硬件之间的桥梁。
在这个阶段,Linux内核会初始化一些重要的子系统,如内存管理、文件系统、网络协议栈等。
然后是系统服务初始化阶段。
在这个阶段,系统服务会被加载并启动。
系统服务是Android系统中的一些核心组件,它们负责提供各种系统功能和服务,如Activity管理、通知管理、电源管理、输入管理等。
在这个阶段,系统服务会被初始化,并通过Binder机制提供接口供应用程序调用。
接下来是应用程序启动阶段。
在这个阶段,一些重要的应用程序会被加载并启动。
Android系统中有一些应用程序是系统级别的,它们在系统启动过程中会被优先加载和启动,如Launcher、Settings等。
在这个阶段,应用程序会被启动,并进入到运行状态。
最后是进程初始化阶段。
在这个阶段,Android系统会创建并初始化一些重要的进程。
Android系统采用了一种轻量级的进程模型,每个应用程序对应一个独立的进程,各个进程之间通过IPC机制进行通信。
Android 上层界面到内核代码的完整的流程分析,以alarm为例子很久之前写的一个流程文档,从上层界面一直调用到内核的过程,最近同事跟我要,我看了下又在整理了下,纯属个人分析(不过都运行验证过),不对的请大牛指出。
Alarm调用流程,alarm的流程实现了从上层应用一直到下面driver的调用流程,下面简单阐述:涉及代码;./packages/apps/DeskClock/src/com/android/deskclock/Alarms.java ./frameworks/base/core/java/android/app/AlarmManager.java./frameworks/base/services/java/com/android/server/AlarmManage rService.java./frameworks/base/services/jni/com_android_server_AlarmManagerS ervice.cpp./kernel/kernel/drivers/rtc/alarm-dev.c./kernel/kernel/include/linux/android_alarm.h./kernel/kernel/drivers/rtc/alarm.c./kernel/kernel/drivers/rtc/interface.c./kernel/kernel/drivers/rtc/rtc-pcf8563.c/packages/apps/DeskClock/src/com/android/deskclock/AlarmRecei ver.java./kernel/arch/arm/configs/mmp2_android_defconfig./kernel/kernel/kernel/.config点击Clock应用程序,然后设置新闹钟,会调到Alarms.java里面的publicstaticlongsetAlarm(Contextcontext,Alarmalarm){....setNextAlert(context);....}然后这里面也会调用到publicstaticvoid setNextAlert(finalContextcontext){if(!enableSnoozeAlert(context)){Alarmalarm=calculateNextAlert(context);//new一个新的alarmif(alarm!=null){enableAlert(context,alarm,alarm.time);}else{disableAlert(context);}}}然后继续调用到privatestaticvoid enableAlert(Contextcontext,finalAlarmalarm,finallo ngatTimeInMillis){.......am.set(AlarmManager.RTC_WAKEUP,atTimeInMillis,sender);//这里是RTC_WAKEUP,这就保证了即使系统睡眠了,都能唤醒,闹钟工作(android平台关机闹钟好像不行).....}然后就调用到了AlarmManager.java里面方法publicvoid set(inttype,longtriggerAtTime,PendingIntentoperation){ try{mService.set(type,triggerAtTime,operation);}catch(RemoteExceptionex){}}然后就调用到了AlarmManagerService.java里面方法publicvoid set(inttype,longtriggerAtTime,PendingIntentoperation){ setRepeating(type,triggerAtTime,0,operation);}然后继续调用publicvoid setRepeating(inttype,longtriggerAtTime,longinterval, PendingIntentoperation){.....synchronized(mLock){Alarmalarm=newAlarm();alarm.type=type;alarm.when=triggerAtTime;alarm.repeatInterval=interval;alarm.operation=operation;//Removethisalarmifalreadyscheduled.removeLocked(operation);if(localLOGV)Slog.v(TAG,"set:"+alarm);intindex=addAlarmLocked(alarm);if(index==0){setLocked(alarm);}}}然后就调用到privatevoid setLocked(Alarmalarm){......//mDescriptor这里的文件是/dev/alarmset(mDescriptor,alarm.type,alarmSeconds,alarmNanoseconds);.....}这里就调用到jni了privatenativevoid set(intfd,inttype,longseconds,longnanosecon ds);这就调用到了com_android_server_AlarmManagerService.cpp里面static JNINativeMethodsMethods[]={/*name,signature,funcPtr*/{"init","()I",(void*)android_server_AlarmManagerService_init},{"close","(I)V",(void*)android_server_AlarmManagerService_close}, {"set","(IIJJ)V",(void*)android_server_AlarmManagerService_set}, {"waitForAlarm","(I)I",(void*)android_server_AlarmManagerService _waitForAlarm},{"setKernelTimezone","(II)I",(void*)android_server_AlarmManager Service_setKernelTimezone},};set对应的是android_server_AlarmManagerService_set,具体是staticvoid android_server_AlarmManagerService_set(JNIEnv*env, jobjectobj,jintfd,jinttype,jlongseconds,jlongnanoseconds){#ifHAVE_ANDROID_OSstructtimespects;_sec=seconds;_nsec=nanoseconds;intresult=ioctl(fd,ANDROID_ALARM_SET(type),&ts);if(result<0){LOGE("Unabletosetalarmto%lld.%09lld:%s\n",seconds,nanosecon ds,strerror(errno));}#endif}然后ioctl就调用到了alarm-dev.cstaticlong alarm_ioctl(structfile*file,unsignedintcmd,unsignedlong arg){....caseANDROID_ALARM_SET(0):if(copy_from_user(&new_alarm_time,(void__user*)arg,sizeof(new_ alarm_time))){rv=-EFAULT;gotoerr1;}from_old_alarm_set:spin_lock_irqsave(&alarm_slock,flags);pr_alarm(IO,"alarm%dset%ld.%09ld\n",alarm_type,new_alarm__sec,new_alarm__nsec);alarm_enabled|=alarm_type_mask;alarm_start_range(&alarms[alarm_type],timespec_to_ktime(new_alarm_time),timespec_to_ktime(new_alarm_time));spin_unlock_irqrestore(&alarm_slock,flags);if(ANDROID_ALARM_BASE_CMD(cmd)!=ANDROID_ALARM_SET_ AND_WAIT(0)&&cmd!=ANDROID_ALARM_SET_AND_WAIT_OLD) break;/*fallthough*/....caseANDROID_ALARM_SET_RTC:if(copy_from_user(&new_rtc_time,(void__user*)arg,sizeof(new_rtc_time))){rv=-EFAULT;gotoerr1;}rv=alarm_set_rtc(new_rtc_time);spin_lock_irqsave(&alarm_slock,flags);alarm_pending|=ANDROID_ALARM_TIME_CHANGE_MASK;wake_up(&alarm_wait_queue);spin_unlock_irqrestore(&alarm_slock,flags);if(rv<0)gotoerr1;break;....}然后这边就调用到了alarm_start_range设置闹钟,alarm_set_rtc设置RTC这两个函数在android_alarm.h声明,在alarm.c里实现。
Android按键事件处理流程--KeyEvent 刚接触Android开发的时候,对touch、key事件的处理总是⼀知半解,⼀会是Activity⾥的⽅法,⼀会是各种View中的,⾃⼰始终不清楚到底哪个在先哪个在后,总之对整个处理流程没能很好的把握。
每次写这部分代码的时候都有些⼼虚,因为我不是很清楚什么时候、以什么样的顺序被调⽤,⼤都是打下log看看,没问题就算ok了。
但随着时间流逝,这种感觉⼀直折磨着我。
期间也在⽹上搜索了相关资料,但总感觉不是那么令⼈满意。
⾃打开始研究Android源码起,这部分内容的分析早就被列在我的TODO list上了。
因为弄懂这部分处理逻辑对明明⽩⽩地写android程序实在是太重要了,所以今天我就带领⼤家看看这部分的处理逻辑。
touch事件的处理我将放在另⼀篇博客中介绍(相⽐KeyEvent,⼤体都⼀样,只是稍微复杂些)。
为了突出本⽂的重点,我们直接从事件被派发到View层次结构的根节点DecorView开始分析,这⾥我们先来看看DecorView# dispatchKeyEvent⽅法,代码如下:@Overridepublic boolean dispatchKeyEvent(KeyEvent event) {final int keyCode = event.getKeyCode();final int action = event.getAction();final boolean isDown = action == KeyEvent.ACTION_DOWN;/// 1. 第⼀次down事件的时候,处理panel的快捷键if (isDown && (event.getRepeatCount() == 0)) {// First handle chording of panel key: if a panel key is held// but not released, try to execute a shortcut in it.if ((mPanelChordingKey > 0) && (mPanelChordingKey != keyCode)) {boolean handled = dispatchKeyShortcutEvent(event);if (handled) {return true;}}// If a panel is open, perform a shortcut on it without the// chorded panel keyif ((mPreparedPanel != null) && mPreparedPanel.isOpen) {if (performPanelShortcut(mPreparedPanel, keyCode, event, 0)) {return true;}}}/// 2. 这⾥是我们本⽂的重点,当window没destroy且其Callback⾮空的话,交给其Callback处理if (!isDestroyed()) { // Activity、Dialog都是Callback接⼝的实现final Callback cb = getCallback(); // mFeatureId < 0 表⽰是application的DecorView,⽐如Activity、Dialogfinal boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event) // 派发给callback的⽅法: super.dispatchKeyEvent(event); // 否则直接派发到ViewGroup#dispatchKeyEvent(View层次结构)if (handled) {return true; // 如果被上⾯的步骤处理了则直接返回true,不再往下传递}}/// 3. 这是key事件的最后⼀步,如果到这⼀步还没处理掉,则派发到PhoneWindow对应的onKeyDown, onKeyUp⽅法return isDown ? PhoneWindow.this.onKeyDown(mFeatureId, event.getKeyCode(), event): PhoneWindow.this.onKeyUp(mFeatureId, event.getKeyCode(), event);} 接下来我们按照这个派发顺序依次来看看相关⽅法的实现,这⾥先看看Activity(Callback)的dispatchKeyEvent实现:/*** Called to process key events. You can override this to intercept all* key events before they are dispatched to the window. Be sure to call* this implementation for key events that should be handled normally.** @param event The key event.** @return boolean Return true if this event was consumed.*/@Overridepublic boolean dispatchKeyEvent(KeyEvent event) {/// 2.1. 回调接⼝,实际开发中⽤处不⼤,你感兴趣可以参看其⽅法doconUserInteraction();Window win = getWindow();/// 2.2. 从这⾥事件的处理交给了与之相关的window对象,实质是派发到了view层次结构if (win.superDispatchKeyEvent(event)) {return true; // 被view层次结构处理掉了则直接返回true}View decor = mDecor;if (decor == null) decor = win.getDecorView();/// 2.3. 到这⾥如果view层次结构没处理则交给KeyEvent本⾝的dispatch⽅法,Activity的各种回调⽅法会被触发return event.dispatch(this, decor != nulldecor.getKeyDispatcherState() : null, this);}紧接着我们看看,Window#superDispatchKeyEvent⽅法,相关代码如下:<!-- Window.java -->/*** Used by custom windows, such as Dialog, to pass the key press event* further down the view hierarchy. Application developers should* not need to implement or call this.**/public abstract boolean superDispatchKeyEvent(KeyEvent event);<!-- PhoneWindow.java -->@Overridepublic boolean superDispatchKeyEvent(KeyEvent event) {return mDecor.superDispatchKeyEvent(event);}<!-- DecorView.superDispatchKeyEvent --> public boolean superDispatchKeyEvent(KeyEvent event) {/// 2.2.1. 进⼊view层次结构了,即调⽤ViewGroup的对应实现了。
apt-get 设置好后,按照下面的步骤安装相关组件Required Packages (Ubuntu 8.04)$ sudo apt-get install python2.5$ sudo apt-get install sun-java6-jdk sun-java6-bin sun-java6-jreAdd/Edit /etc/bash.bashrcexport JA V A_HOME=/usr/lib/jvm/java-6-sun-1.6.0.07$ sudo apt-get install flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev zlib1g-dev zip curl valgrind libncurses5-dev build-essential$ sudo apt-get install x-dev$ sudo apt-get install libx11-dev编译Android source code$ cd ~/mydroid$ export ANDROID_JAVA_HOME=$JAVA_HOME$ cd ~/mydroid$ make编译Android KernelBuilding zImageGo into kernel directory$ cd ~/mydroid/kernel$ make msm_defconfig ARCH=arm$ make ARCH=arm CROSS_COMPILE=../prebuilt/linux-x86/toolchain/arm- eabi-4.2.1/bin/arm-eabi-可以在 kernel/arch/arm/boot/目录下看到build好的zImage原文地址:/archiver/tid-2413.html由于论坛改版,很多有用的资源都不见了,所以这里把自己对cupcake下载和编译方法进行详细说明,以后还会陆续发完善的开发板移植说明、内核编译说明、一些模块级的分析等,希望对刚开始做android的朋友有所帮助,同时欢迎高手指正。
存盘 Ctrl+s(肯定知道)注释代码 Ctrl+/取消注释 Ctrl+\(Eclipse3已经都合并到Ctrl+/了)代码辅助 Alt+/快速修复 Ctrl+1代码格式化 Ctrl+Shift+f整理导入 Ctrl+Shift+o切换窗口 Ctrl+f6<可改为ctrl+tab方便>ctrl+shift+M 导入未引用的包ctrl+w 关闭单个窗口F3 跳转到类、变量的声明F11 运行上次程序Ctrl + F11 调试上次程序Alt + 回下一个编辑点ctrl+shift+T 查找工程中的类最经典的快捷键Ctrl+1 快速修复(最经典的快捷键,就不用多说了)Ctrl+D: 删除当前行Ctrl+Alt+↓复制当前行到下一行(复制增加)Ctrl+Alt+↑复制当前行到上一行(复制增加)Alt+↓当前行和下面一行交互位置(特别实用,可以省去先剪切,再粘贴了)Alt+↑当前行和上面一行交互位置(同上)Alt+←前一个编辑的页面Alt+→下一个编辑的页面(当然是针对上面那条来说了)Alt+Enter 显示当前选择资源(工程,or 文件 or文件)的属性Shift+Enter 在当前行的下一行插入空行(这时鼠标可以在当前行的任一位置,不一定是最后)Shift+Ctrl+Enter 在当前行插入空行(原理同上条)Ctrl+Q 定位到最后编辑的地方Ctrl+L 定位在某行 (对于程序超过100的人就有福音了)Ctrl+M 最大化当前的Edit或View (再按则反之)Ctrl+/ 注释当前行,再按则取消注释Ctrl+O 快速显示 OutLineCtrl+T 快速显示当前类的继承结构Ctrl+W 关闭当前EditerCtrl+K 参照选中的Word快速定位到下一个Ctrl+E 快速显示当前Editer的下拉列表(如果当前页面没有显示的用黑体表示)Ctrl+/(小键盘) 折叠当前类中的所有代码Ctrl+×(小键盘) 展开当前类中的所有代码Ctrl+Space 代码助手完成一些代码的插入(但一般和输入法有冲突,可以修改输入法的热键,也可以暂用Alt+/来代替)Ctrl+Shift+E 显示管理当前打开的所有的View的管理器(可以选择关闭,激活等操作)Ctrl+J 正向增量查找(按下Ctrl+J后,你所输入的每个字母编辑器都提供快速匹配定位到某个单词,如果没有,则在stutes line中显示没有找到了,查一个单词时,特别实用,这个功能Idea两年前就有了)Ctrl+Shift+J 反向增量查找(和上条相同,只不过是从后往前查)Ctrl+Shift+F4 关闭所有打开的EditerCtrl+Shift+X 把当前选中的文本全部变为大写Ctrl+Shift+Y 把当前选中的文本全部变为小写Ctrl+Shift+F 格式化当前代码Ctrl+Shift+P 定位到对于的匹配符(譬如{}) (从前面定位后面时,光标要在匹配符里面,后面到前面,则反之)下面的快捷键是重构里面常用的,本人就自己喜欢且常用的整理一下(注:一般重构的快捷键都是Alt+Shift开头的了)Alt+Shift+R 重命名 (是我自己最爱用的一个了,尤其是变量和类的Rename,比手工方法能节省很多劳动力)Alt+Shift+M 抽取方法 (这是重构里面最常用的方法之一了,尤其是对一大堆泥团代码有用)Alt+Shift+C 修改函数结构(比较实用,有N个函数调用了这个方法,修改一次搞定)Alt+Shift+L 抽取本地变量( 可以直接把一些魔法数字和字符串抽取成一个变量,尤其是多处调用的时候)Alt+Shift+F 把Class中的local变量变为field变量 (比较实用的功能)Alt+Shift+I 合并变量(可能这样说有点不妥Inline)Alt+Shift+V 移动函数和变量(不怎么常用)Alt+Shift+Z 重构的后悔药(Undo)Alt+左箭头,右箭头以在编辑窗口切换标签Alt+上下箭头, 以自动选择鼠标所在行,并将其上下移动Ctrl+f6 可以弹出菜单,上面列出可以切换的编辑窗口,这样不用鼠标也可切换Ctrl+f7 可以在视图之间切换 ,如编辑视图,输出视图,工程视图Ctrl+f8 可以在不同的观察视图中切换,就是在java视图,调试视图,等之间切换Ctrl+m 可以在最大化当前窗口和还原当前窗口之间切换Ctrl+e 弹出输入窗口,可以输入你想要编辑的代码窗口,和Ctrl+f6的功能相同,只不过一个是选择的方式,一个是输入的方式,切换窗口Ctrl+T 可以直接显示光标所在内容的类图,可以直接输入,并跳到输入内容部分按住Ctrl键,然后鼠标指向变量名,方法名,类名在源代码中快速跳转Ctrl + F11 快速执行程序Ctrl+Shift+F 程序代码自动排版Ctrl+Shift+O 自动加入引用。
手机linux系统操作方法手机Linux 系统是指基于Linux 内核的操作系统,可以安装在手机上。
它具有高度可定制性和开放性,因此受到了多个技术爱好者的青睐。
手机Linux 系统的功能和界面可以根据个人需求进行自由定制和修改。
要操作手机Linux 系统,需要了解一些基本知识。
本文将从以下几个方面对手机Linux 系统进行介绍和操作方法。
1. 安装手机Linux 系统首先,我们需要安装一个手机Linux 系统,目前比较成熟和流行的手机Linux 系统有Ubuntu T ouch、Arch Linux、LineageOS 等。
可以在官网下载对应的ROM 文件,然后通过刷机工具进行刷机安装。
2. 连接手机Linux 系统连接手机Linux 系统需要使用一些特殊的工具,如Android Debug Bridge (ADB)。
可以通过USB 线将手机连接到电脑上,然后使用ADB 工具连接到手机Linux 系统。
输入命令adb shell 即可进入Linux 终端。
3. 熟悉Linux 终端Linux 终端是类似于CMD 和PowerShell 的命令行工具,用户可以通过在终端输入命令来操作系统。
在Linux 终端中,用户可以使用诸如cd、ls、mkdir、rm、vim 等命令来管理文件、目录和编辑文本等。
用户可以使用man 命令来查询终端命令的用法和参数。
4. 安装和使用软件在手机Linux 系统中,用户可以通过终端来安装和使用软件,通常使用Linux 软件包管理器来进行管理。
在Ubuntu Touch 中使用apt,Arch Linux 使用pacman,LineageOS 使用yum。
使用对应的命令即可安装和卸载软件。
5. 修改手机Linux 系统用户可以根据自己的需求对手机Linux 系统进行修改和优化。
用户可以修改系统的启动界面、桌面背景、主题和字体等。
在终端中,用户可以通过修改配置文件来改变系统设置和功能,如修改/etc/rc.local 文件来设置系统启动项。
1Android系统的启动过程1.1启动过程Android系统完整的启动过程,可分为Linux系统层、Android系统服务层、Zygote进程模型三个阶段,从开机到启动Home Launcher完成具体的任务细节可分为七个步骤。
1.启动BootLoader2.加载系统内核3.启动Init和其它重要守护进程4.启动Zygote进程5.启动Runtime进程,初始化Service Manager。
Service Manager用于binder通讯,负责绑定服务的注册与查找。
6.启动SystemService7.启动Home Laucher8.启动其它应用程序1.1.1BootLoaderAndroid 系统是基于Linux操作系统的,所以它最初的启动过程和Linux一样。
当设备通电后首先执行BootLoader引导装载器,BootLoader是在操作系统内核运行之前运行的一段小程序。
通过这段小程序初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境引导进入合适的状态,以便为最终调用操作系统内核准备好正确的运行环境。
1.1.2启动Init和守护进程当系统内核加载完成之后,会首先启动Init守护进程,它是内核启动的第一个用户级进程,进程号永远是1。
当Init进程启动后,如(图1-1)它还负责启动其他的一些重要守护进程,主要包括:Usbd进程(USB Daemon):USB连接后台进程,负责管理USB连接。
adbd 进程(Android Debug Bridge Daemon):ADB连接后台进程,负责管理ADB连接。
debuggerd 进程(Debugger Daemon) :调试器后台进程,负责管理调试请求及调试过程。
rild进程(Radio Interface Layer Daemon):无线接口层后台进程,负责管理无线通信服务。
图1-1 Init和其它重要守护进程的启动,图片来源:http://www-igm.univ-mlv.fr/~dr/XPOSE2008/android/fonct.html1.1.3启动Zygote进程如(图1-2)所示,当Init进程和一些重要的守护进程启动完成之后,将启动Zygote 进程。
主要介绍linux 内核启动过程以及挂载android 根文件系统的过程,以及介绍android 源代码中文件系统部分的浅析。
主要源代码目录介绍Makefile (全局的Makefile)bionic (Bionic 含义为仿生,这里面是一些基础的库的源代码)bootable (引导加载器)build (build 目录中的内容不是目标所用的代码,而是编译和配置所需要的脚本和工具)dalvik (JAVA 虚拟机)development (程序开发所需要的模板和工具) external (目标机器使用的一些库)frameworks (应用程序的框架层)hardware (与硬件相关的库)packages (Android 的各种应用程序)prebuilt (Android 在各种平台下编译的预置脚本)recovery (与目标的恢复功能相关)system (Android 的底层的一些库)out (编译完成后产生的目录,也就是我们移植文件系统需要的目录)host 目录的结构如下所示:out/host/|-- common| `-- obj (JAVA 库)`-- linux-x86|-- bin (二进制程序)|-- framework (JAVA 库,*.jar 文件)|-- lib (共享库*.so)`-- obj (中间生成的目标文件)host 目录是一些在主机上用的工具,有一些是二进制程序,有一些是JAVA 的程序。
target 目录的结构如下所示:out/target/|-- common| |-- R (资源文件)| |-- docs| `-- obj (目标文件)`-- product`-- generic其中common 目录表示通用的内容,product 中则是针对产品的内容。
在common 目录的obj 中,包含两个重要的目录:APPS 中包含了JAVA 应用程序生成的目标,每个应用程序对应其中一个子目录,将结合每个应用程序的原始文件生成Android 应用程序的APK包。
android系统提供的处理物理按键事件的回调方法-回复Android系统提供了多种处理物理按键事件的回调方法,这些方法可以让开发者轻松地实现用户与设备的交互。
在本文中,我们将一步一步地回答关于这些回调方法的问题,并详细介绍它们的使用场景和功能。
1. 什么是物理按键事件回调方法?物理按键事件回调方法是指在Android系统中,用于接收和处理物理按键事件的一组方法。
这些方法定义在View类及其子类中,可以通过重写这些方法来实现自定义的按键事件处理逻辑。
2. Android系统提供了哪些物理按键事件回调方法?Android系统提供了以下几个常用的物理按键事件回调方法:- onKeyDown(int keyCode, KeyEvent event):表示有按键按下的触发事件。
- onKeyUp(int keyCode, KeyEvent event):表示有按键松开的触发事件。
- onKeyLongPress(int keyCode, KeyEvent event):表示有按键长按的触发事件。
- onKeyMultiple(int keyCode, int repeatCount, KeyEvent event):表示有按键连续按下的触发事件。
3. 如何重写物理按键事件回调方法?要重写物理按键事件回调方法,首先需要在自定义的View类中添加相应的方法签名,如onKeyDown、onKeyUp等。
然后,将所需的按键事件处理逻辑代码写在这些方法内部。
例如,在一个自定义的View类中,我们可以重写onKeyDown方法来处理按键按下事件:java@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) { 根据按键的keyCode判断按下的是哪个物理按键if (keyCode == KeyEvent.KEYCODE_BACK) {在这里添加处理返回按键的逻辑return true; 消费事件,防止事件继续传递}return super.onKeyDown(keyCode, event);}4. 物理按键事件回调方法的使用场景有哪些?物理按键事件回调方法在Android开发中具有广泛的使用场景,下面列举了几个常见的应用场景:- 实现返回键的功能:通过重写onKeyDown方法,可以在用户按下返回键时执行相应的操作,例如返回上一个页面或退出应用程序。
android java教程Android Java是一种非常流行的编程语言,用于开发Android 应用程序。
这种编程语言是基于Java语言的,并添加了一些与Android系统交互的特殊功能和库。
Android Java教程旨在帮助初学者了解Android应用程序开发的基础知识。
以下是一个简要的教程,介绍了Android Java的主要概念和用法。
首先,我们需要了解Android应用程序的基本结构。
每个Android应用程序都由一个或多个Activity组成,Activity是应用程序的主要界面。
通过Activity,我们可以创建用户界面、处理用户输入和与其他组件进行交互。
在Android Java中,我们可以使用XML文件来定义Activity 的用户界面。
XML文件是一种标记语言,用于描述应用程序的布局和样式。
我们可以定义文本框、按钮、图像视图等各种UI组件,并将它们放置在Activity的布局中。
一旦我们定义了用户界面,我们需要在Java代码中处理它。
我们可以使用Java代码来添加逻辑和交互行为,例如为按钮添加点击事件处理程序,或将文本框中的文本发送到服务器。
除了Activity之外,Android应用程序还可以包含其他组件,例如服务、广播接收器和内容提供者。
服务用于在后台执行长时间运行的任务,广播接收器用于接收系统广播消息,内容提供者用于共享数据。
Android还提供了许多API和库,用于简化开发过程并增加应用程序的功能。
例如,我们可以使用相机API来访问设备的摄像头,使用位置API来获取设备的地理位置信息,使用网络API来与服务器通信等。
在Android Java教程中,我们还将介绍一些常用的开发工具和技术。
例如,我们可以使用Android Studio作为开发环境,使用Gradle构建系统来管理项目依赖关系,使用Git版本控制系统来跟踪代码的变化。
最后,我们将介绍一些Android应用程序的最佳实践和性能优化技巧。
1. Boot系统初始化,具体过程参见(system\core\init\Init.c)中的main函数,这时候,手机或者模拟器出现的画面是一个console,显示“ANDROID”msg。
2. 初始化成功后,就开始mounting系统,具体参见(system\core\mountd\Mountd.c) 中的main 函数。
3.接下来运行ndroidRuntime,并开始启动java虚拟机dalvikvm。
4. Java虚拟机启动成功后,开始系统初始化。
系统初始的第一步是用JNI方式实现的,对应java代码为(frameworks\base\services\java\com\android\server\SystemServer.java) init1(Native)函数,对应的JNI C++代码为(frameworks\base\core\jni\server\com_android_server_SystemServer.cpp),而实现的C++代码为(frameworks\base\cmds\system_server\library\ System_init.cpp) 中的system_init()函数。
5. system_init调用SurfaceFlinger,SurfaceFlinger的readyToRun()函数用BootAnimation来实现开机动画,这时候手机或者模拟器显示是一副背景图加一个动态的小机器人。
6. 系统初始化的第二步,将启动ServerThread进程,参见SystemServer.init2()。
ServerThread 将启动各种系统服务,如Power Manager、Activity Manager等等,具体参见ServerThread的run函数,ServerThread同在SystemServer.java中。
7.这之后的事,应该就是进入系统了。
android是一个开放的系统,这个系统体积非常庞大,不同的开发者在开发过程中并不需要掌握整个android系统,只要进行其中某一个部分的开发android 的开发分四个层次1. Linux操作系统及驱动,该层由C语言实现2. 本地代码框架,该层次由C,C++实现3. java框架,该层主要由java实现4. java应用程序,该层主要由java实现应用程序层:所有的应用程序都是使用java语言编写的,通过调用应用程序框架层(Application Framework)所提供的API来完成。
应用程序框架层:为开发人员提供了可以完全访问核心应用程序所使用的API框架。
•活动管理器:管理应用程序生命周期并提供常用的导航回退功能。
比如:开启应用程序需要的资源和退出应用程序时需要的释放资源。
•窗口管理器:管理所有开启的窗口程序。
•内容提供器:使应用程序可以访问另一个应用程序的数据(如联系人数据库),或者共享它们的数据。
•视图系统:可以用来构建应用程序,它包括列表list、网格grid、文本框text box、按钮button、图形绘制等,以及可嵌入的web浏览器•通知管理器:使应用程序可以再状态栏中显示自定义的提示信息。
•包管理器:管理所有安装在Android系统中的应用程序。
比如:信息查看和卸载程序等。
•资源管理器:提供各种资源供应程序使用。
比如:字符资源、图像资源、音频资源。
•硬件服务:电话拨打和接听等相关功能、管理地图服务的相关功能、有关蓝牙服务的相关功能、WIFI服务相关功能、USB服务相关功能、传感器服务相关功能。
系统运行时库:系统运行库层包括程序库和Android运行库两部分1)程序库:Android包含一些C/C++库,这些库能被Android系统中的不同组件使用,它们通过应用程序框架为开发者提供服务,核心库的功能介绍:Surface Manager:对显示子系统进行管理,并且为多个应用程序提供2D和3D 图层的无缝融合。
android 系统编译流程原理Android系统编译流程及原理Android系统是目前全球最流行的移动操作系统之一,而其编译过程是实现系统构建的关键步骤。
本文将介绍Android系统的编译流程及其原理,以帮助读者更好地理解Android系统的工作原理。
一、概述Android系统的编译过程主要包括源代码的获取、构建环境的配置、编译源代码、生成系统镜像等几个主要步骤。
整个编译过程通常需要一台性能较好的计算机来完成。
二、源代码的获取要编译Android系统,首先需要从官方网站或其他渠道获取到Android源代码。
Android源代码以Git的形式进行管理,可以通过Git命令来获取最新的源代码。
三、构建环境的配置在开始编译前,需要配置好编译环境。
首先需要安装Java Development Kit(JDK),并设置好相应的环境变量。
然后需要安装Android SDK,以及Android Build Tools等编译工具。
四、编译源代码编译源代码是整个编译过程的核心步骤。
Android系统的源代码使用Makefile进行管理和编译。
Makefile是一种构建工具,用于描述源代码的依赖关系和编译规则。
在编译过程中,Makefile会根据源代码的依赖关系,自动判断哪些文件需要重新编译。
这样可以避免重复编译和提高编译效率。
编译源代码的过程通常包括以下几个步骤:1. 初始化:Makefile会进行一些初始化操作,例如设置编译参数、创建输出目录等。
2. 依赖检查:Makefile会检查源代码的依赖关系,判断哪些文件需要重新编译。
3. 编译源文件:Makefile会根据源代码的编译规则,将源文件编译成目标文件。
4. 链接目标文件:Makefile会将编译得到的目标文件链接成可执行文件或库文件。
5. 生成系统镜像:最后,Makefile会将编译得到的可执行文件、库文件等打包成系统镜像,以供安装到设备上运行。
五、生成系统镜像在编译完成后,就可以生成Android系统的系统镜像了。
linux内核启动+Android系统启动过程详解第一部分:汇编部分Linux启动之linux-rk3288-tchip/kernel/arch/arm/boot/compressed/head.S分析这段代码是linux boot后执行的第一个程序,完成的主要工作是解压内核,然后跳转到相关执行地址。
这部分代码在做驱动开发时不需要改动,但分析其执行流程对是理解android的第一步开头有一段宏定义这是gnu arm汇编的宏定义。
关于GUN 的汇编和其他编译器,在指令语法上有很大差别,具体可查询相关GUN汇编语法了解另外此段代码必须不能包括重定位部分。
因为这时一开始必须要立即运行的。
所谓重定位,比如当编译时某个文件用到外部符号是用动态链接库的方式,那么该文件生成的目标文件将包含重定位信息,在加载时需要重定位该符号,否则执行时将因找不到地址而出错#ifdef DEBUG//开始是调试用,主要是一些打印输出函数,不用关心#if defined(CONFIG_DEBUG_ICEDCC)……具体代码略#endif宏定义结束之后定义了一个段,.section ".start", #alloc, #execinstr这个段的段名是 .start,#alloc表示Section contains allocated data, #execinstr表示Sectioncontains executable instructions.生成最终映像时,这段代码会放在最开头.alignstart:.type start,#function /*.type指定start这个符号是函数类型*/.rept 8mov r0, r0 //将此命令重复8次,相当于nop,这里是为中断向量保存空间.endrb 1f.word 0x016f2818 @ Magic numbers to help the loader.word start @ absolute load/run zImage//此处保存了内核加载和运行的地址,实质上也是本函数的运行地址address.word _edata@ 内核结束地址//注意这些地址在顶层vmlixu.lds(具体在/kernel文件夹里)里进行了定义,是链接的地址,加载内核后可能会进行重定位1: mov r7, r1 @ 保存architecture ID,这里是从bootload传递进来的mov r8, r2 @ 保存参数列表atags指针r1和r2中分别存放着由bootloader传递过来的architecture ID和指向标记列表的指针。
android系统按键从linux到java流程概述:android系统的键值转换,从linux到java共经历3个层次,分别是:1 linux系统层,原始ir键值读取,转变为linux层键值2 framework层,linux层键值转换为android键值3 framework层,android键值上报java层关系图:剩余疑问:dev/vinput和dev/input之间到底怎么关联的目前没查到这二者是怎么关联的,但是从用户组可以看出,vinput应该是input的输入。
猜测:这二者之间类似一个软连接处理,避免键值读写都在同一个文件,在不同进程之间造成数据异常;二者由系统负责同步。
后续查到相关资料再补充.1 原始ir键值读取,转变为linux层键值核心输入:系统启动android_ir_user后台进程核心输出: 虚拟设备dev/vinput,写入linux键值1.1 流程图1.2转换流程详细说明:1.2.1/device/hisilicon/bigfish/system/ir_user/key_pars/key.xml:该文件编译后输出到/etc目录下。
定义原始硬件码值和对应linux层通用键名:< key value="0x639c4db2" name="KEY_MUTE"/>1.2.2/device/hisilicon/bigfish/system/ir_user/key_pars/linux_key.h:定义linux层通用键名和linux层键值的对应关系:{"KEY_MUTE", 113 },结构linux_keycode_ary类型的数组Linux_KeyCode_Ary[512].1.2.3/device/hisilicon/bigfish/system/ir_user/key_pars/ key_pars.c:提供接口get_keycode解析xml建立原始码值和linux层键值的映射数组get_keycode(_key_arry *keyarry, int keyarry_num)解析:a:调用readXml读取/etc/ key.xml,返回xml根节点:key.xml中<hisi-key>和<other-key>分别各一个节点,我们的遥控器原始键值配置在<other-key>中。
b:调用Pars_Key解析每个节点下的所有按键:解析节点下的所有children节点,通过value属性获取xml定义的原始键值,通过name属性获取xml定义的键名字符串,再调用find_linux_key_code查询这个字符串对应的linux层键值。
把这个映射关系存储到:keyarry->hi_keycode[keynum].ir_keycode = ir_keycode;keyarry->hi_keycode[keynum].linux_keycode = linux_keycode;c: find_linux_key_code函数遍历在linux_key.h定义的Linux_KeyCode_Ary数组,找到参数str(即键名字符串)对应的linux层键值。
1.2.4/device/hisilicon/bigfish/system/ir_user/ir_user.cpp:1)编译为后台进程android_ir_user独立运行;2)进程启动,执行main入口函数,调用get_keycode完成key.xml存储原始码值和linux 层键值的映射关系到数组keyarry;3)建立ir_sample_thread线程读取原始码值,根据keyarry转换为linux层键值,通过ReportKeyEvent写入dev/vinput设备,其他进程可以读取键值1.3总结出差拷机,如果不想其他厂家操作我们的盒子,只需要离开的时候删除/system/bin下面的android_ir_user这个bin文件即可。
2 linux层键值转换为android键值核心输入:/dev/input, 输入linux键值核心输出: 1)getEvents(),输出RawEvent* buffer,存储linux层键值;2)mapKey(),将linux层键值转换为android键值2.1流程图2.2详细说明2.2.1 /device/hisilicon/bigfish/prebuilts/Vendor_0001_Product_0001.kl:定义linux键值和对应的键名字符串key 113 MUTE2.2.2 /frameworks/native/include/input/KeycodeLabels.h定义键名字符串和android的java层键值对应关系结构数组KEYCODES:{ "MUTE", 91 }2.2.3\frameworks\native\libs\input\Keyboard.cpp提供函数loadKeyLayout和getPath,定位linux到android键第一转换映射文件为Vendor_0001_Product_0001.kl:提供函数getKeyCodeByLabel,从KeycodeLabels.h的KEYCODES数组中,查询返回android的java键值。
2.2.4\frameworks\native\libs\input\KeyLayoutMap.cpp提供函数load和parse等解析Vendor_0001_Product_0001.kl,并调用Keyboard.cpp的getKeyCodeByLabel,通过“linux键值---键名字符串---android的java 层键值”的直接建立“linux键值--- android的java层键值”map集合;提供函数mapKey基于此集合供上层转换linux键值为android的java键值2.2.5 \frameworks\base\services\input\EventHub.cpp1 提供getEvents,完成两个事:1):建立linux键值--- android的java层键值”map集合。
2):扫描linux键值,存储到参数RawEvent* buffer。
2 提供mapKey,调用KeyLayoutMap.cpp的mapKey函数,完成转换linux 键值为android的java键值。
2.2.6关于建立linux键值--- android的java层键值”map集合,代码流程:1)\frameworks\base\services\input\EventHub.cppa)getEvents()->scanDevicesLocked():b)scanDevicesLocked-> scanDirLocked():static const char *DEVICE_PATH = "/dev/input";c)scanDirLocked()->openDeviceLocked()d) openDeviceLocked()->loadKeyMapLocked()e) loadKeyMapLocked调用Keyboard.cpp下load()函数:2)\frameworks\native\libs\input\Keyboard.cppf) load()->probeKeyMap():g) probeKeyMap ()->loadKeyLayout():h) loadKeyLayout()->getPath():这里才确定path为:./system/usr/keylayout/Vendor_0001_Product_0001.kl 再继续调用KeyLayoutMap::load加载并解析3)\frameworks\native\libs\input\KeyLayoutMap.cppi)load()->parse()j)parse ()->parseKey()解析Vendor_0001_Product_0001.kl得到linux层code,再调用getKeyCodeByLabel查询code对应的android层键值keyCode将两个键值存入map集合到此完成linux层键值到android的java层键值的转换并存储为map集合;后面真正扫描到linux键值后,调用mapKey根据存储的map集成转换为android键值进行上报。
2.3总结:这个部分可以看出,其完全是个中间过程,如果我们要修改某个键在android的表现,完全不用改这其中相关的任何文件,只需要在java层(后面会讲到,keyevent.java)对收到的android键进行再转换即可。
3 Android键值上报java层核心输入: eventhub.cpp的getEvents()和mapkey()核心输出:PhoneWindowManager.java的interceptKeyBeforeQueueing和interceptKeyBeforeDispatching3.1流程图太多,省略....3.2详细说明3.2.1\frameworks\base\services\input\InputReader.cpp该文件主要负责:linux按键的读取;转换为android键值;通过listener启动按键上报,注意这里仅仅是启动按键上报。
1)InputReader 类构造函数InputReader两个极其重要的参数:eventHub和listener,前者用来读取linux键值,后者用来分发上报按键。
说明:参数eventHub,赋值给变量mEventHub;listener作为参数创建了mQueuedListener。
2) loopOnce函数及其调用的一连串函数调用mEventHub->getEvents读取linux按键到RawEvent 类型的mEventBuffer成员变量;调用processEventsLocked分发上报。
3)重点阐述processEventsLocked是如何分发上报按键的:a)processEventsLocked调用processEventsForDeviceLockedb) processEventsForDeviceLocked从InputReader 的(InputDevice类型)变量mDevices变量中找出当前对应的device,调用其processc) process调用InputDevice的变量(InputMapper类型)mMappers的process函数d)这里的mapper是KeyboardInputMapper类这里process开始调用eventhub类的mapKey()启动参数rawEvent中的linux键值scanCode的转换,变为android键值keyCode,继续调用processKey上传.e) processKey调用getListener()->notifyKey(&args);完成键值上报到其他模块注意这里的getListener就是取得inputreader类初始化时用参数“constsp<InputListenerInterface>& listener”初始化的mQueuedListener。