1+x安卓应用开发(中级)课程-项目7 安卓底层原理认知_第1页
1+x安卓应用开发(中级)课程-项目7 安卓底层原理认知_第2页
1+x安卓应用开发(中级)课程-项目7 安卓底层原理认知_第3页
1+x安卓应用开发(中级)课程-项目7 安卓底层原理认知_第4页
1+x安卓应用开发(中级)课程-项目7 安卓底层原理认知_第5页
已阅读5页,还剩17页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

《腾讯1+x安卓应用开发(中级)》教案

一、教案设计课题项目7任务1认识安卓系统服务的启动和工作原理课型理论课理论课时2课时实践课时0课时教学目标知识目标能力(技能)目标能够掌握安卓系统服务的启动原理和工作原理。熟悉安卓系统服务的启动流程。教学重点安卓系统服务的启动流程。教学难点源码阅读能力的培养。教学内容1.ServiceManager启动所有的系统服务都是需要在ServiceManager中进行注册的,而ServiceManager是通过init.rc来启动的。(1)由bootloader载入linux内核后,内核开始初始化,并载入built-in的驱动程序,内核完成系统设置后,启动init进程,切换至user-space(用户空间)后,结束内核的循序过程。(2)由init进程开始,解析init.rc,启动Native服务,并启动重要的外部程序,例如servicemanager、zygote。(3)Zygote进程预加载和初始化一些核心类库,并创建一个服务端socket,等待AMS发起socket请求。同时,启动系统服务进程SystemService,SystemServer进程会启动各项系统服务。(4)servicemanager是系统中的关键服务,其入口函数在service_manager.c中。//frameworks/native/libs/binder/ndk/service_manager.cintmain(intargc,char**argv){structbinder_state*bs;//结构体,用来存储binder的信息unionselinux_callbackcb;char*driver;if(argc>1){driver=argv[1];}else{driver="/dev/binder";}bs=binder_open(driver,128*1024);//1if(!bs){#ifdefVENDORSERVICEMANAGERALOGW("failedtoopenbinderdriver%s\n",driver);while(true){sleep(UINT_MAX);}#elseALOGE("failedtoopenbinderdriver%s\n",driver);#endifreturn-1;}if(binder_become_context_manager(bs)){//2ALOGE(“cannotbecomecontextmanager(%s)\n”,strerror(errno));return-1;}cb.func_audit=audit_callback;selinux_set_callback(SELINUX_CB_AUDIT,cb);cb.func_log=selinux_log_callback;selinux_set_callback(SELINUX_CB_LOG,cb);#ifdefVENDORSERVICEMANAGERsehandle=selinux_android_vendor_service_context_handle();#elsesehandle=selinux_android_service_context_handle();#endifselinux_status_open(true);if(sehandle==NULL){ALOGE(“SELinux:Failedtoacquiresehandle.Aborting.\n”);abort();}if(getcon(&service_manager_context)!=0){ALOGE(“SELinux:Failedtoacquireservice_managercontext.Aborting.\n”);abort();}Binder_loop(bs,svcmgr_handler);//3return0;}在注释1处,打开binder驱动,申请128k字节的内存空间,将文件进行了mmap映射,并将对应的地址空间保存到了结构体中。在注释2处,注册为Binder机制的管理者。在注释3处,启动循环,等待binder驱动发来的消息,即client端发来的请求。2.系统服务注册与查询当有service请求时,servicemanager进程会从睡眠等待中被唤醒,并调用svcmgr_handler()方法,简化后的关键代码如下。//frameworks/native/cmds/servicemanager/service_manager.cintsvcmgr_handler(structbinder_state*bs,structbinder_transaction_data*txn,structbinder_io*msg,structbinder_io*reply){……switch(txn->code){caseSVC_MGR_GET_SERVICE:caseSVC_MGR_CHECK_SERVICE://1……handle=do_find_service(s,len,txn->sender_euid,txn->sender_pid);……return0;caseSVC_MGR_ADD_SERVICE://2……if(do_add_service(bs,s,len,handle,txn->sender_euid,allow_isolated,dumpsys_priority,txn->sender_pid))return-1;break;caseSVC_MGR_LIST_SERVICES:{//3……si=svclist;while(si){if(si->dumpsys_priority&req_dumpsys_priority){if(n==0)break;n--;}si=si->next;}……return-1;}default:ALOGE("unknowncode%d\n",txn->code);return-1;}bio_put_uint32(reply,0);return0;}在注释1处,根据name(参数s)查询ServerHandle。在注释2处,注册服务,将服务插入到svclist链表上,记录服务的name(参数s)与handle的关系。在注释3处,查询所有服务,返回存储所有服务的链表svclist。教学准备教材,PPT、教纲、教案参考资料韩超、梁泉,《Android系统原理及开发要点详解》教学过程方法与手段教学备注【课堂导入】Android系统启动与后续将要介绍的进程启动、四大组件原理等内容都有关联,是本章首先要学习的知识点。【教学实施】10.1.1ServiceManager启动10.1.1.1由bootloader载入linux内核后,内核开始初始化,并载入built-in的驱动程序,内核完成系统设置后,启动init进程,切换至user-space(用户空间)后,结束内核的循序过程。10.1.1.2由init进程开始,解析init.rc,启动Native服务,并启动重要的外部程序,例如servicemanager、zygote。10.1.1.3Zygote进程预加载和初始化一些核心类库,并创建一个服务端socket,等待AMS发起socket请求。同时,启动系统服务进程SystemService,SystemServer进程会启动各项系统服务。10.1.1.4servicemanager是系统中的关键服务,其入口函数在service_manager.c中。对service_manager.c的源码进行分析。10.1.2系统服务注册与查询10.1.2.1当有service请求时,servicemanager进程会从睡眠等待中被唤醒,并调用svcmgr_handler()方法。10.1.2.2对service_manager.c的源码进行分析。【知识(技能)巩固练习】简述ServiceManager启动的过程。【教学小结】讲授、演示课后作业与训练完成项目7课后练习对应的习题。教学反思

课题项目7任务2认识安卓系统进程启动过程的相关原理课型理论课理论课时2课时实践课时0课时教学目标知识目标能力(技能)目标能够掌握安卓系统进程启动过程中的一些重要机制的初始化原理。熟悉安卓系统进程启动过程。教学重点安卓系统进程启动过程。教学难点培养学生阅读源码的能力。教学内容1.应用程序进程概述要想启动一个应用程序,首先要保证这个应用程序所需要的应用程序进程已经启动。在Android应用程序框架层中,由AMS(ActivityManagerService)组件负责为Android应用程序创建新的进程,它本身也是运行在一个独立的进程之中,这个进程是在系统启动的过程中创建的。AMS在启动应用程序时会检查这个应用程序需要的应用程序进程是否存在,不存在就会向Zygote进程发送一个创建应用程序进程的请求。2.应用程序进程创建过程应用程序进程创建过程的步骤分为两个部分,一部分是AMS请求Zygote创建应用程序进程,另一部分是Zygote接收请求并创建应用程序进程。(1)AMS请求Zygote创建应用程序进程每当ActivityManagerService需要创建一个新的应用程序进程来启动一个应用程序组件时,它就会调用ActivityManagerService类的成员函数startProcessLocked向Zygote进程发送一个创建应用程序进程的请求。(2)Zygote接收请求并创建应用程序进程Zygote进程收到创建新的应用进程的请求后,会调用processOneCommand()方法,使用fork在当前进程中创建子进程。子进程中使用handleChildProc()方法调用ZygoteInit对子进程环境做初始化处理。zygoteInit()方法执行时,会跳转到AMS指定的类ActivityThread的main函数执行。整个过程经历了5个java文件,分别是ZygoteInit.java、ZygoteServer.java、ZygoteConnection.java、RuntimeInit.java和RuntimeInit.java。3.Binder线程池启动过程以及开启消息循环机制应用程序进程创建后,会做两个工作,一是创建Binder线程池,二是去调用ActivityThread的main()方法。(1)Binder线程池的启动过程。整个过程经历了4个文件,分别是ZygoteInit.java、app_main.cpp、ProcessState.cpp、ProcessState.cpp。查看分析这些文件。(2)开启消息循环机制调用ActivityThread的main()方法的过程已经在10.2.2做出分析,现在主要分析main()方法主要做了哪些工作。//frameworks/base/core/java/android/app/ActivityThread.javapublicstaticvoidmain(String[]args){Looper.prepareMainLooper();//1ActivityThreadthread=newActivityThread();//2thread.attach(false);if(sMainThreadHandler==null){ sMainThreadHandler=thread.getHandler();//3}if(false){ Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG,"ActivityThread"));}Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);Looper.loop();//4thrownewRuntimeException("Mainthreadloopunexpectedlyexited");}ActivityThread就是我们常说的主线程或UI线程,ActivityThread的main方法是一个APP的真正入口。在注释1处,创建主线程轮询器looper。在注释2处,创建ActivityThread,用于管理当前应用程序进程的主线程。在注释3处,获取ActivityThread内部类H类赋值给sMainThreadHandler,H继承自Handler,用于处理主线程的消息循环。在注释4处,调用Looper的loop()方法开始工作。教学准备教材,PPT、教纲、教案参考资料韩超、梁泉,《Android系统原理及开发要点详解》教学过程方法与手段教学备注【课堂导入】上一个任务我们学习了Android系统的启动流程,系统启动后,就到了启动应用程序的环节,而在启动一个应用程序之前,需要先保证该应用程序的进程已经被启动,本任务我们就来学习应用程序进程的启动。【教学实施】10.2.1应用程序进程概述10.2.2应用程序进程创建过程10.2.2.1AMS请求Zygote创建应用程序进程10.2.2.2Zygote接收请求并创建应用程序进程10.2.3Binder线程池启动过程以及开启消息循环机制10.2.3.1Binder线程池的启动过程10.2.3.2开启消息循环机制【知识(技能)巩固练习】简述应用程序进程创建的过程。【教学小结】讲授、演示课后作业与训练完成项目7课后练习对应的习题。教学反思

课题项目7任务3认识安卓组件的相关原理课型理论课理论课时2课时实践课时0课时教学目标知识目标能力(技能)目标能够理解安卓组件启动原理,绑定原理,注册和收发原理和数据传输原理等。熟悉安卓组件的启动过程。教学重点安卓组件的启动过程。教学难点培训学生阅读源码的能力。教学内容1.根Activity的启动过程(1)Launcher向AMS发起startActivity的请求Launcher收到用户点击事件后,向AMS(ActivityManagerService)发起startActivity的请求,通知AMS将要启动新的Activity了。具体过程如下图所示。(2)启动Activity的应用程序进程的启动过程AMS收到请求,记录下将要启动的Activity的信息,将任务栈栈顶的Activity暂停,并把将要启动的Activity放到栈顶。然后检查activity所在进程是否存在,如果存在,就通知这个进程,并在该进程中启动Activity;如果不存在,则创建一个新进程。期间用到的类和方法如下图所示。ActivityStackSupervisor主要判断activity的状态(是否处于栈顶或处于停止状态等),ActivityStack主要处理activity在栈中的状态,之后又回到ActivityStackSupervisor,判断即将启动的activity所在的进程是否已经创建。(3)ActivityThread启动Activity的过程ApplicationThread接收到服务端的事务后,把事务直接转交给ActivityThread处理。ActivityThread通过Instrumentation利用类加载器创建Activity实例,同时利用Instrumentation回调activity的生命周期方法。主要流程如下图所示。2.广播的注册、发送和接收流程在Android系统中,广播是一种运用在组件之间传递消息的机制,广播接收者是Android四大组件之一,本节将从注册、发送和接收三个方面介绍广播的工作过程。(1)广播的注册流程注册的目的是过滤出那些广播接收者感兴趣的广播,注册分为静态注册和动态注册两种方式。由于官方对耗电量的优化,避免APP滥用广播,Android8.0之后,除了少部分的广播仍支持静态注册(如开机广播),其余的都会出现失效的情况。因此,本书仅讨论动态注册的过程。此过程主要经历了3个文件,分别是ContextWrapper.java、ContextImpl.java、ActivityManagerService.java。查看分析这些文件。(2)广播的发送和接收过程流程Android系统中提供了两种广播,分别是有序广播和无序广播。本书以无序广播为例介绍广播的发送和接收流程。广播的发送涉及3个进程。一是Activity所在的进程,二是AMS进程,三是广播接收器所在进程。Activity把广播发送到AMS中,AMS会检查广播是否合法,然后根据过滤规则IntentFilter,把符合条件的广播接收者BroadcastReceiver存放到队列中,对广播接收者进行权限检查,通过检查后,判断广播接收者所在的应用程序进程是否存在并且正在运行,如果是,则用广播接收者所在的应用程序进程来接收广播。将广播的intent等信息封装为Args对象,以Args对象为参数调用mActivityThread的post方法。这样,在执行BroadcastReceiver类型的receiver对象的onReceive()方法时,注册的广播接收者就收到了广播并得到了intent。用到的源码文件如表10-1所示,具体代码不再列出。表10-1广播发送和接收涉及的主要源码文件列表/frameworks/base/core/java/android/content/ContextWrapper.java/frameworks/base/core/java/android/app/ContextImpl.java/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java发送广播到AMS/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java验证广播是否合法根据过滤规则IntentFilter,把符合条件的广播接收者BroadcastReceiver存放到队列中/frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java对广播接收者进行权限检查判断广播接收者所在的应用程序进程是否存在并且正在运行/frameworks/base/core/java/android/app/ActivityThread.java/frameworks/base/core/java/android/app/LoadedApk.java将广播的intent等信息封装为Args对象执行BroadcastReceiver类型的receiver对象的onReceive方法3.Service组件的启动Service启动方式有两种,一种是通过Context的startService启动Service,另一种是通过Context的bindService绑定Service。本节先介绍Service的启动,下一节将介绍Service的绑定。Service的启动经历了从ContextWrapper到AMS的调用过程和ActivityThread启动Service的过程。(1)向AMS发出startService的请求请求过程如下图所示。(2)通过ActivityThread启动Service过程如下图所示。4.Service的绑定Service的绑定经历了从ContextWrapper到AMS的调用过程和Service的绑定过程。(1)向AMS发送bindService的请求请求过程如下图所示:(2)Service的绑定过程绑定过程如下图所示。5.ContentProvider的启动过程(1)Application的启动过程ContentProvider的启动是在Application的onCreate()之前完成的。所以,我们先来看一下Application的启动过程。ActivityThread中的main()方法可以看做是整个app的入口,在main()方法中创建了ActivityThread对象,并调用了它的attach()方法。在attach()方法中远程调用AMS的attachApplication()方法。attachApplication()中调用了attachApplicationLocked(),该方法远程调用PMS的queryContentProviders()方法获取应用注册的ContentProvider信息,然后调用ApplicationThread的bindApplication()方法将信息传递过去。之后,经过一系列的调用,最后会回调到ActivityThread这个类中的handleBindApplication()方法。在handleBindApplication()方法中创建了app的Application,ContentProvider的启动也是在这个方法中完成的。过程参看下图。(2)ContentProvider的启动过程整个过程主要经历了4个方法,分别是ActivityThread.java的handleBindApplication()方法、ActivityThread.java的installContentProviders()方法、ActivityThread.java的installProvider()方法、ContentProvider.java的attachInfo()方法。对这些方法进行源码分析。教学准备教材,PPT、教纲、教案参考资料韩超、梁泉,《Android系统原理及开发要点详解》教学过程方法与手段教学备注【课堂导入】前两个任务我们学习了系统的启动过程和应用程序进程的启动过程,应用程序进程启动后,就可以启动应用程序了,即启动根Activity。Activity是安卓四大组件之一,另外三大组件是BroadcastReceiver、Service和ContentProvider。本任务主要学习四大组件的相关原理和启动过程。【教学实施】10.3.1根Activity的启动过程10.3.1.1Launcher向AMS发起startActivity的请求10.3.1.2启动Activity的应用程序进程的启动过程10.3.1.3ActivityThread启动Activity的过程10.3.2广播的注册、发送和接收流程10.3.2.1广播的注册流程10.3.2.2广播的发送和接收流程10.3.3Service组件的启动10.3.3.1向AMS发出startService的请求10.3.3.2通过ActivityThread启动Service10.3.4Service的绑定10.3.4.1向AMS发送bindService的请求10.3.4.2Service的绑定过程10.3.5ContentProvider的启动过程10.3.5.1Application的启动过程10.3.5.2ContentProvider的启动过程【知识(技能)巩固练习】简述Service组件的启动过程。【教学小结】讲授、演示课后作业与训练完成项目7课后练习对应的习题。教学反思

课题项目7任务4认识安卓跨进程通信的相关原理课型理论课理论课时2课时实践课时0课时教学目标知识目标能力(技能)目标能够理解安卓跨进程通信,对象传递等进程通信原理。熟悉安卓跨进程通信的过程。教学重点安卓跨进程通信的过程。教学难点源码阅读能力的培养。教学内容1.基本概念(1)进程隔离在操作系统中,进程之间的内存和数据都是不共享的,一个进程不能直接操作或者访问另一个进程。这样做的目的,是为了避免进程A的数据写入进程B这种进程间相互干扰的现象发生,从而保证其安全性。为了实现进程隔离,采用了虚拟地址空间,两个进程各自的虚拟地址不同,从而防止进程A将数据信息写入进程B。(2)跨进程通信为了使不同的进程之间能互相访问资源并进行协调工作,就需要进行跨进程通信(IPC,Inter-ProcessCommunication),也可以称之为进程间通信。(3)BinderBinder英文单词的中文含义是“粘合剂”,意味着能把各个组件粘合在一起,起到桥梁的作用。在Android中,它是一种高效的跨进程通信机制,采用C/S架构模式,基于内存映射(mmap()),在内核空间将Client端和Service端两个用户空间的进程联系在一起。2.进程空间划分操作系统从逻辑上将虚拟空间划分为用户空间(UserSpace)和内核空间(KernelSpace)。内核空间是系统内核运行的空间,用户空间是用户程序运行的空间。为了保证安全性,它们之间是隔离的。如下图所示。3.Binder跨进程通信机制1.内存映射BinderIPC机制中涉及到的内存映射通过mmap()来实现,mmap()是操作系统中一种内存映射的方法。它能将用户空间的一块内存区域映射到内核空间。如上图所示,映射关系建立后,用户对这块内存区域的修改可以直接反应到内核空间;同理,内核空间对这段区域的修改也能直接反应到用户空间。2.Binder跨进程通信实现原理Binder跨进程通信是基于内存映射(mmap)来实现的,如图10-14所示。首先创建缓存区。这个工作由Binder驱动完成,它在内核空间创建一个用于接收数据的缓存区,接着,开辟一块内核缓存区。然后建立两个映射关系。一是内核缓存区与内核中数据接收缓存区的映射关系,二是内核中数据接收缓存区与接收进程中用户空间地址的映射关系。保证内核缓存区和接收进程用户空间地址映射到同一个缓存区中。这时如果发送进程需要将数据发送给接收进程,会首先通过系统调用copy_from_user()将数据复制到内核缓存区,由于内核缓存区和接收进程的用户空间存在内存映射,因此也就相当于把数据发送到了接收进程的用户空间,这样便完成了跨进程通信。3.Binder跨进程通信模型了解完Binder跨进程通信原理后,我们再来看看实现层面的设计。Binder跨进程通信模型有4个角色:Client、Server、BinderDriver(Binder驱动)、ServiceManager。其中Client、Server、ServiceManager运行在用户空间,Binder驱动运行在内核空间。Binder驱动和ServiceManager属于Android基础架构,已经由系统实现好了,Client和Server则属于Android应用层,需要开发者自行实现。下面对模型做一个简单描述。首先,注册服务端。Server进程向Binder驱动发起服务注册的请求,向Binder驱动的全局链表binder_procs中插入服务端的信息,Binder驱动将请求转发给ServiceManager进程,向ServiceManager的svcinfo列表中缓存需要注册的服务。然后,获取服务,拿到服务的代理。Client进程向Binder驱动发起获取服务的请求,Binder驱动将该请求转发给ServiceManager进程,ServiceManager进程在svcinfo列表中查找该服务是否已经注册,若已注册,通过Binder驱动将服务的代理返回给Client进程。最后,使用服务。Binder驱动使用mmap实现内存映射,Client进程将请求参数发送给Server进程,Server进程根据Client进程的要求,调用目标方法,并将目标方法的结果返回给Client进程。教学准备教材,PPT、教纲、教案参考资料韩超、梁泉,《Android系统原理及开发要点详解》教学过程方法与手段教学备注【课堂导入】进程间通信简称IPC,英文为InterProcessCommunication,在操作系统中,进程是操作系统调度的基本单元。在Android中一个进程一般指一个应用程序。【教学实施】10.4.1基本概念10.4.1.1进程隔离10.4.1.2跨进程通信10.4.1.3Binder10.4.2进程空间划分10.4.3Binder跨进程通信机制10.4.3.1内存映射10.4.3.2Binder跨进程通信实现原理10.4.3.3Binder跨进程通信模型【知识(技能)巩固练习】简述Binder跨进程通信机制。【教学小结】讲授、演示课后作业与训练完成项目7课后练习对应的习题。教学反思

课题项目7任务5认识安卓线程间通信的相关原理课型理论课理论课时1课时实践课时1课时教学目标知识目标能力(技能)目标能够理解安卓线程间消息传递机制,消息循环机制及其相关原理。熟悉安卓线程间消息传递的流程。教学重点安卓线程间消息传递的流程。教学难点源码阅读能力的培养。教学内容1.基本概念(1)线程的分类Android中可以将线程分为主线程MainThread和工作线程WorkerThread两大类。2.为什么要进行线程间的通信主线程又称为UI线程,跟UI相关的操作都运行在主线程中,而工作线程不操作UI组件。另外,在主线程中执行耗时操作(超过5秒),会造成ANR(applicationnotresponding)。所以,需要启动一个工作线程(子线程)执行耗时操作,耗时操作完成后,需要通知主线程更新UI。2.Android线程间消息处

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论