android_编译系统/Framework简介



  Android中,manager的含义是经纪人,所管理的对象是服务本身,因为每个具体的服务都会提供多个API接口。
  Android中,设备商要扩充framework:增加一些额外的类文件,这些类文件一般以独立的jar包存在;修改已有文件,可以使用import,但为了保持和原生Framework的兼容性/对原生framework最少化修改,可以使用类装载器动态装载自定义jar包。
  dex文件是将所需的Class文件重新打包,打包的规则不是简单的压缩,而是完全对Class文件内部的各种函数表/变量表等进行优化,并产生一个dex文件。加载它需要特殊的类装载器,DexClassLoader。
  HostApk调用PluginApk中的类的方法1:通过PackageManager的queryIntentActivities方法,获取ResolvInfo和ActivityInfo;new出一个DexClassLoader,加载PluginApk中的类,利用newInstance方式获取类对象;利用反射机制获取类方法;
  HostApk调用PluginApk中的类的方法2:面向接口编程,不用反射的方式。(Plugin项目必须通过一个外部jar,并且该jar包必须是以Library方式被添加到Plugin项目的build path中,不能以“外部Jar”的方式添加。原因:外部jar会作为程序的一部分被打包到最终的程序文件中,从而使得Plugin和Host项目中存在包名相同但验证码不同的类文件。)  
  插件架构设计过的两种应用:系统主题架构和App Store架构。
  Android中的theme概念并不是真正的系统主题,所有的系统图标可以通过一种主题文件进行切换,比如状态栏上的系统图标/各种UI控件的图标/桌面等。思路是把每一个主题文件作为一个插件,在系统设置中可以使用不同的插件作为当前系统的主题,然后修改Framework中都去Resources资源的相关代码。
  App Stroe架构,设计一个通用的电子商店客户端,并定义标准的和电子商店服务器通讯的机制,把这种通信机制定义为一个或多个interface文件,不同商店厂只要实现interface即可。然后,把实现后的程序作为一个插件安装到手机中,从而使得用户可以选择不同的插件,而不再需要安装那么多个客户端。

  JNI存在原因:调用驱动(java不具备操作驱动的能力);大数据处理模块(C的效率高);某些功能模块C已经实现。
  当调用native函数时,java会自动产生一个对应的C中的函数名称。其关系为,包名+名称,并且中间以下画线分割(这个并不是java编译器内含的,是一种编程规范);native引擎中AndroidRuntime类提供了一个registerNativeMethods函数,可以定义映射关系。
  在产生的C函数中,包含两个参数,JNIEnv对象是Java虚拟机所运行的环境,相当于JVM的管家,通过它可以访问JVM内部的各种对象;jobject是调用该函数的对象。Java代码中不能直接访问C中的变量,C中的变量对于java是私有的,让C提供get和set方法。
  C访问java,类似于反射机制调用类中的方法。
  在C中使用持久对象:private int mObject,使用的时候强制转换成本地对象。
  异步消息处理线程原因:任务需要常驻,比如用于处理用户交互的任务;任务需要根据外部传递的消息做不同的操作。
  实现异步线程要解决的问题包括:消息队列;无限循环体;消息队列锁。
  线程局部存储TLS,thread local strorage。
  不同作用域的变量类型:函数成员变量;类成员变量;线程局部存储TLS变量;静态变量;跨进程通讯IPC变量。
  为什么一个线程中只能有一个Looper对象:一个线程只能有一个消息队列,不是ThreadLocal惹的祸。
  让一个线程变成异步消息处理线程:run方法前先调用Looper.prepare为该线程创建MessageQueue对象,然后调用Looper.loop函数,使当前线程进入消息处理循环。
  调用MessageQueue对象的next函数取出消息队列中的消息,如果当前消息为空,则当前线程会被挂起;在Looper中,每处理完消息后,调用msg.recycle回收该Message所占用的系统资源。
  一个线程中,可以包含多个Handler对象,在Looper.loop函数中,不同的Message对应不同的Handler对象,从而回调不同的handleMessage函数。
  android分为四层:应用程序层(Applications)、应用程序框架层(Application Framework)、系统运行库层(Libraries和Android Runtime)和Linux内核层(Linux Kernel)。
  Framework框架包含三个主要部分:客户端,服务端,Linux驱动。服务端主要包含两个重要类:WindowManagerService(WmS)和ActivityManagerService;还包含两个重要的消息处理类(KeyQ类,读取用户UI操作消息,比如按键/触摸屏/trackball/鼠标等;InputDispatcher类,从QueueEvent中读取用户消息,并进行过滤,过滤后将消息发送给当前活动的客户端)。
  APK程序中有至少含有三个线程:两个binder对象对应两个线程(ViewRoot.W对象和Application对象,都继承与binder,扶着接受linux Binder驱动发送的IPC调用),主线程。
  UI线程是从ActivityThread运行的,在该类的main方法中。
  传递消息一般指多个线程之间,而Activity本身不是线程。ActivityThread才是线程。
  普通类的实例化都是程序员显示完成的,而Activity的实例化却是由framework完成的,程序员只能使用startActivity方法告诉framework去运行哪个Activity,程序员得不到Activity对象的引用。可借助Activity.getApplication函数,获取Application对象,程序中唯一,该对象的名称可以在AndroidMenifest中指定。还可以通过Intent,SharePreference/文件/数据库。
  窗口:程序员所看到的屏幕上的某个独立的界面,比如Activity界面,一个对话框,一个Menu菜单。从WmS角度讲,窗口是接收用户消息的最小单元;给WmS添加一个窗口调用WindowManager类的addView方法,即添加一个View对象。
  ViewRoot类:客户端申请创建窗口时需要一个客户端代理,用以和WmS进行交互。WmS所管理的每一个窗口都会对应一个ViewRoot类。
  W类:ViewRoot的内部类,继承于Binder,用于向WmS提供一个IPC接口,从而让WmS控制窗口客户端的行为。
  一个Activity就是一个场景(Context),一个Service也对应一个场景。Context.getResources方法回去的是同一个全局对象。
  Context个数=Service个数+Activity个数+1;
  Context类本身是一个纯abstract类;ContextWrapper一个包装而已,构造函数中必须包含一个真正的Context引用。ContextThemeWrapper包含了与主题Theme相关的接口,主题指的是AndroidManifest中通过android:theme为Applicaiton的元素或者Activity的元素指定的主题。

  android编译系统被调用的三种形式:编译整个android系统;编译某个子工程(apk/java运行时的jar库/linux的静态库/动态库/可执行程序);编译sdk;
  整个编译系统的三个组成部分:编译中枢(各种.mk文件,便管理所有的子项目,并生成所有的target);子项目;输入路径(host对应PC上所需要的各种工具/target最终的输出目标);
  .PHONY定义默认的编译名称;多数target并不属于某个子项目,而是整个android源码可以生成的目标(files,生成编译过程中所需的各种临时文件,包含各种中间所需的目标文件;bootimage,生成boot image文件;boottarball,生成boot.img的压缩文件;systemtarball,生成system.img的压缩文件);
  只有指定的tag值才会有真正意义,否则该子项目在编译后不会被添加到任何的product中:user,设备厂商的私有项目,一般依赖于不同的硬件平台;optional,该项目被每一个product包含;debug/eng/tests,对应用户调用make的命令参数值;
  各种目标类型最终都会引用到base_rules.mk;而在base_rules.mk中,ALL_MODULES+=$(LOCAL_MODULE),这就把子项目的定义添加到了ALL_MODULES变量中,从而使编译中枢获知了子项目的目标;
  config.mk定义个各种宏;比如BUILD_PACKAGE,它的功能:取出项目环境变量(各个目录下的Android.mk;除在当前目录中asset/res外,还从PRODUCT_PACKAGE_OVERLAYS/DEVICE_PACAGE_OVERLAYS,不改变源码,扩展原有项目);包含特定的基础脚本文件(eg,java.mk,java.mk中调用了definations.mk);增加额外的目标条件(增加R文件/增加JNI的目标条件/增加签名文件/增加对aapt及zipalign的条件依赖);
  Android.mk中,LOCAL_PATH:= $(call my-dir),在开发树中查找源文件;my-dir为宏函数,由编译系统提供,用于返回当前路径(即包含Android.mk文件的目录)。
  envsetup.sh中:$(gettop),返回源码的顶层目录。
  Android.mk中,include $(CLEAR_VARS),在build/core/config.mk:54:CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk,它用于清空变量。
  Android.mk中,include $(BUILD_PACKAGE),在build/core/config.mk:70:BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk,它用于*** 。
  config.mk中,定义了BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk。
  package.mk中,include $(BUILD_SYSTEM)/java.mk,BUILD_SYSTEM的定义在/core/main.mk:62:BUILD_SYSTEM := $(TOPDIR)build/core。
  Android.mk中,LOCAL_SDK_VERSION会使应用程序不能访问hide的api,current代表了当前Android源码的版本。eg,访问com.android.internal.R.attr.listViewStyle系统资源。新加的API为了不影响SDK接口,一般故意hide。
  Android.mk中,LOCAL_PATH:= $(call my-dir),my-dir函数是Android编译时build/envsetup.sh命令生成的,能够获取当前目录的路径。


  $M=/yajun/Calendar/Android.mk  $T=/yajun  $RES=`echo $M|sed 's:'$T'/::'`   #结果为 Calendar/Android.mk
  $make -C /home/liulijun/repo all_modules ONE_SHOT_MAKEFILE=packages/apps/calendar/AllInOneActivity/Android.mk  #在AllInOneActivity目录下运行,就编译了Calendar.apk。
  $ONE_SHOT_MAKEFILE=packages/apps/calendar/AllInOneActivity/Android.mk make -C /home/liulijun/repo all_modules   #在AllInOneActivity目录下运行,就编译了Calendar.apk。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值