Android框架介绍

目录

Android发展历史

Android大事件

Android框架整体介绍

Android兼容性测试

CTS Verify

GTS

VTS

代码下载

代码编译

AndroidNN

Android发展历史

Android里程碑

Android Inc.于2003年10月由安迪·鲁宾、利奇·米纳尔、尼克·席尔斯、克里斯·怀特在加州帕罗奥图创建。Android最初由安迪·鲁宾等人开发制作,最初开发这个系统的早期方向是创建一个数字相机的先进操作系统,但是后来发现相机市场规模不够大,加上智能手机发展趋势快速成长,于是Android成为一款面向智能手机的操作系统。于2005年7月11日Android Inc.被美国科技企业Google收购

2007年11月,Google与84家硬件制造商、软件开发商及电信营运商成立开放手持设备联盟来共同研发Android,随后,Google以Apache免费开放源代码许可证的授权方式,发布了Android的源代码,开放源代码加速了Android普及,让生产商推出搭载Android的智能手机,Android后来更逐渐拓展到平板电脑及其他领域上

Android最初的版本是于2007年11月5日发行的Android 0.5,它作为一个面向开发者的软件开发包SDK进行发行

Alpha、Beta

初期还未完成的版本以里程碑(Milestone)的M来作编号(如m3, m5)后面接rc号码(如m3-rc37a),再细分为每星期的结果WB或测试序号TC。至2009年团队认为这些编号太难分辨和记忆,所以改成CRA29,而这也某程度上决定了后来使用英文本母排序的方式来命名代号。在这其中无数的里程碑中,曾经打算过使用虚构作品中的机器人(Android)作为代号,例如Astro Boy“铁臂阿童木”和Bender“班德·班亭·罗德里盖兹”

Android 1.0

(2008年9月23日 Android 1.0 API 1)2008年9月23日,发布Android操作系统中的第一个正式版本:Android 1.0,当时并未有特别名称。全球第一台Android设备HTC Dream(G1)就是搭载Android 1.0操作系统

Android 的 Logo. 一直使用到 Android 4.3 (Jelly Bean)

Android Petit Four

(花色小蛋糕, 2009年2月9日,Android 1.1 API 2)正式以甜点为代号,该版本只被预装在T-Mobile G1上,支持对邮件附件的保存和预览功能;增加了长按任意界面弹出多选框的功能;用户搜索企业和其他服务时,下方会显示出其他用户搜索时对该搜索信息的评价和留言

Android Cupcake

(纸杯蛋糕,2009年4月27日,Android 1.5 API 3)增加了对虚拟键盘的支持度,此版系统可以像iPhone那样直接在屏幕上的虚拟键盘中输入。这也是为没有内建QWERTY键盘的Android手机作出的重大改进,增加了影像录制功能,同时也将拍照时的启动速度做了优化,还可以将拍摄的内容发布到Youtube;支持Widget功能;增加了Voice Search的语音识别功能;支持A2DP蓝牙立体声;内置的重力加速感应器增加了自动探测方向的功能;中文显示和中文输入的支持;支持来电照片显示

Android 1.5 界面

Android Donut

(甜甜圈,2009年9月15日 ,Android 1.6 API 4)正式决定以英文本母作代号排序,手势操控支持,
支持CDMA网路,文本转语音系统(Text-to-Speech),快速搜索框,全新的拍照界面,支持虚拟私人网络(VPN),可查看应用程序耗电量,支持OpenCore2媒体引擎,新增对视觉及听觉困难人士的服务

Android Eclair

(松饼,2009年10月26日, Android 2.0, API 5;2009年12月3日 Android 2.0.1 API 6;
2010年1月12日,Android 2.1, API 7) 支持更高的屏幕分辨率,改良的用户界面,新的浏览器的用户界面,并支持HTML5,新的联络人名单,支持Microsoft Exchange,支持内置相机闪光灯,支持数位变焦,支持蓝牙2.1,支持动态桌面。

Android 2.0 界面

Android Froyo

(霜冻优格,2010年5月20日, Adnroid 2.2 API 8)支持将软件安装至记忆卡,支持Adobe Flash 10.1,支持快速启动功能至电话和浏览器,支持浏览器上传文件,集成Chrome的V8 JavaScript引擎

Android 2.2 界面

Android Gingerbread

(姜饼,2010年12月7日 ,Android 2.3 API 9;2011年2月9 Android 2.3.3,API 10), Gingerbread引入了对近场通信(NFC)和对话启动协定(SIP)的支持

Android 2.3 界面

Android Gingerbread的彩蛋

Android Honeycomb

(蜂巢,2011年2月22日,Android 3.0 API 11;2011年5月10日,Android 3.1 API 12;2011年7月15日,Android 3.2 API 13) Honeycomb引入了一个被称为“holographic”的用户界面主题和一个基于Android主要功能(例如多任务,通知和小部件)的交互模型,是第一个Android平板操作系统

Android 3.0 界面

Android Honeycomb的彩蛋

Android Ice Cream Sandwich

(冰淇淋三明治,2011年10月18日, Android 4.0 API 14,2012年3月29日,Android 4.0.4发布, API 15)Android 4.0专注于引入新的简化的、现代化的人机界面交互体验。作为这些努力的一部分,它引入了代号为“Holo”的新视觉外观,该界面引入了更简洁设计,以及一个名为Roboto的新默认字体。它还引入了许多其他新功能,包括更新的主屏幕,近场通信(NFC)支持以及使用该技术将内容“发送”给其他用户的能力(Android Beam),全新的Web浏览器,新的社交网络联系人管理器,从锁定屏幕启动相机和控制音乐播放的能力,可视语音邮件的支持,设备的面部识别解锁功能,监控和限制移动数据使用,以及其他内部改进

Android冰淇淋三明治(Ice Cream Sandwich)标志

Android Ice Cream Sandwich的彩蛋

Android 4.0 界面

Android Jelly Bean

(果冻豆,2012年7月9日,Android 4.1 API 16;2013年2月11日,Android 4.2 API 17;2013年10月5日. Android 4.3 API 18),Google开展了黄油计划(Project Butter),为了让Android系统摆脱UI交互上的严重滞后感,希望能像“黄油”一样顺滑。 核心原理是系统框架中的渲染和动画统一采用垂直同步技术(VSYNC),以及三重缓冲技术(Triple Buffer),让滑动、翻页等操作更加一致与顺滑。

Android 4.1 界面

Android Jelly Bean的彩蛋

Android KitKat

(奇巧巧克力,2013年10月31日,Android 4.4 API 19;2014年6月20日 Google发布Android 4.4.4,API 20),Google开展了瘦身计划(Project Svelte),力求降低安卓系统的内存使用,解决低端机型升级难的问题,让Android 4.4可正常运行在所有Android手机,从而减少安卓系统继续碎片化。UI设计上,支持新的“沉浸式模式”,用户界面由过去的黑色与蓝色为主的色调转向带有透明度的浅色系,视觉语言变得更加明亮与现代化。

全新Android Logo

Android 4.4.2 界面

Android KitKat的彩蛋

Android Lollipop

(棒棒糖,2014年11月12日,Android 5.0 API 21;2015年4月22日Google发布Android 5.1.1,API 22),Google开展了伏特计划(Project Volta),力求提升续航能力,这方面Google落后于业界厂商,厂商直面用户对续航尤为迫切,往往系统资源管控更为严格。另外,系统采用全新的ART,抛弃Dalvik虚拟机,大幅提升运行效率。UI设计上,使用全新的扁平化Material Design设计风格,更加清新与质感的设计,统一Android设备的外观和使用体验。

平面化的Android Logo. 沿用至Android 9

Android 5.0 界面

Android Lollipop的彩蛋

Android 5.0 界面

Android Marshmallow

(棉花糖,2015年10月5日,Android 6.0 API 23),Google引入新的运行时权限,让用户能够更好地了解和控制权限;引入了Doze模式,进一步提升电池续航能力。UI设计上,新增夜间模式,大幅改进通知栏,让通知更简洁。

Android 6.0 界面

Android Marshmallow的彩蛋

Android Nougat

(牛轧糖,2016年8月22日,Android 7.0 API 24;Android7.1.2 于2017年4月发布,API 25),引入新的JIT编译器,对AOT编译器的补充,可节省存储空间和加快更新速度;进一步优化Doze唤醒机制;UI设计上,支持分屏功能;

Nougat Logo

Android 7.0 界面

Android Nougat的彩蛋

Android Oreo

(奥利奥,2017年8月21日,Android 8.0 API 26;2017年12月5日,谷歌正式发行Android 8.1,API 27),Google开展了计划(Project Treble),重新架构Android,将安卓系统框架与Vendor层解耦,力求彻底解决安卓碎片化这一老大难的问题,这是安卓系统架构最大的变化。系统层面加强对后台服务、广播、位置的管控限制。UI设计上,改进通知栏,智能文本选择和自动填充功能。Android 8.1,引入神经网络API

Oreo Logo

Android 8.1 界面

Android Oreo的彩蛋

Android Pie

(2018年8月6日,Android 9.0 API 28) 采用机器学习的思路来预测用户使用习惯来做省电优化,继续强化Treble计划;文件系统(sdcardf/F2FS)持续提升;私有API的限制进一步规范化Android生态,强化隐私和安全,硬件安全性模块以及统一生物识别身份验证界面。 UI设计上,新的手势导航,加强支持刘海屏,UI搜索界面使用到机器学习,AI正在逐步强化Android系统。

Android P 标志

Android P界面

Android Pie的彩蛋

Android 10

(2019年9月3日 API 29),Google开展了主线计划(Project Mainline),相关模块(Modules)不允许厂商直接修改,只能由Google应用商店来更新升级,强化用户隐私、系统安全与兼容性。支持脸部生物识别。此版本Android是各Android版本中,首次不用甜品来命名

重新设计过的Android Logo

Android 10界面

Android Q的彩蛋

Android 11

(Android R ,2020年9月8日 API 30),着力强调三大主题:人、控制与隐私。

Android 11界面

Android 12

(Android S ,? API 31),Google将引入一种全新的设计语言,称为Material You,采用全新设计语言 引入个性化体验.

Android大事件

⻩油计划(Project Butter)

Google 在 2012 年的 I/O 大会上宣布了 Project Butter 黄油计划,那个曾经严重影响 Android 口碑的 UI 流程性问题,首先在这得到有效的控制,

并且在 Android 4.1 中正式开启了这个机制。

Project Butter

Project Butter 对 Android Display 系统进行了重构,引入了三个核心元素,即 VSYNC、Triple Buffer 和 Choreographer。

其中 VSYNC 是理解 Project Butter 的核心。接下来,我们就围绕 VSYNC 开始介绍 Project Butter 对 Android Display 系统做了哪些优化。

VSYNC
  1. 背景概念
    VSYNC 是一种图形技术,它可以同步 GPU 的帧速率和显示器的刷新频率,所以在理解 VSYNC 产生的原因及其作用之前,我们有必要先来了解下这两个概念。

刷新频率(Refresh Rate)

表示屏幕在一秒内刷新画面的次数, 刷新频率取决于硬件的固定参数,单位 Hz(赫兹)。例如常见的 60 Hz、144 Hz,即每秒钟刷新 60 次或 144 次。

逐行扫描

显示器并不是一次性将画面显示到屏幕上,而是从左到右边,从上到下逐行扫描显示,不过这一过程快到人眼无法察觉到变化。以 60 Hz 刷新率的屏幕为例,即 1000 / 60 ≈ 16.67ms。

帧速率 (Frame Rate)

表示 GPU 在一秒内绘制操作的帧数,单位 fps。例如在电影界采用 24 帧的速度足够使画面运行的非常流畅。而 Android 系统则采用更加流程的 60 fps,即每秒钟绘制 60 帧画面

  1. 屏幕撕裂

现在,刷新频率和帧率需要一起合作,才能使图形内容呈现在屏幕上,GPU 会获取图形数据进行绘制, 然后硬件负责把图像内容呈现到屏幕上,这一过程在应用

程序的生命周期内一遍又一遍的发生。

如上图,CPU / GPU 生成图像的 Buffer 数据,屏幕从 Buffer 中读取数据刷新后显示。理想情况下帧率和刷新频率保持一致,即每绘制完成一帧,显示器显示一帧。不幸的是,刷新频率和帧率并不总是能够保持相对同步,如果帧速率实际比刷新率快,例如帧速率是 120 fps,显示器的刷新频率为 60 Hz。此时将会发生一些视觉上的问题。

当 GPU 利用一块内存区域写入一帧数据时,从顶部开始新一帧覆盖前一帧,并立刻输出一行内容。当屏幕刷新时,此时它并不知道图像缓冲区的状态,因此从缓冲区抓取的帧并不是完整的一帧画面(绘制和屏幕读取使用同一个缓冲区)。此时屏幕显示的图像会出现上半部分和下半部分明显偏差的现象,这种情况被称之为 “tearing”(屏幕撕裂)。

发生 “tearing” 现象的根源是由于帧速率与刷新频率不一致导致。

Double Buffer(双重缓存)

那如何防止 “tearing” 现象的发生呢?由于图像绘制和读取使用的是同一个缓冲区,所以屏幕刷新时可能读取到的是不完整的一帧画面。解决方案是采用 Double Buffer。

Double Buffer(双缓冲)背后的思想是让绘制和显示器拥有各自的图像缓冲区。GPU 始终将完成的一帧图像数据写入到 Back Buffer,而显示器使用 Frame Buffer,当屏幕刷新时,Frame Buffer 并不会发生变化,Back Buffer 根据屏幕的刷新将图形数据 copy 到 Frame Buffer,这便是 VSYNC 的用武之地。

注意,VSYNC 信号负责调度从 Back Buffer 到 Frame Buffer 的交换操作,这里并不是真正的数据 copy,实际是交换各自的内存地址,可以认为该操作是瞬间完成。

在 Android 4.1 之前,Android 便使用的双缓冲机制。怎么理解呢?一般来说,在同一个 View Hierarchy 内的不同 View 共用一个 Window,也就是共用同一个 Surface。

每个 Surface 都会有一个 BufferQueue 缓存队列,但是这个队列会由 SurfaceFlinger 管理,通过匿名共享内存机制与 App 应用层交互。

整个流程如下:

每个 Surface 对应的 BufferQueue 内部都有两个 Graphic Buffer,一个用于绘制一个用于显示。系统会把内容先绘制到离屏缓冲区(OffScreen Buffer),在需要显示时,才把离屏缓冲区的内容通过 Swap Buffer 复制到 Front Graphic Buffer 中。

这样 SurfaceFlinge 就拿到了某个 Surface 最终要显示的内容,但是同一时间我们可能会有多个 Surface。这里面可能是不同应用的 Surface,也可能是同一个应用里面类似 SurfaceView 和 TextureView,它们都会有自己独立的 Surface。

这个时候 SurfaceFlinger 把所有 Surface 要显示的内容统一交给 Hardware Composer,它会根据位置、Z-Order 顺序等信息合成为最终屏幕需要显示的内容,而这个内容会交给系统的帧缓冲区 Frame Buffer 来显示(Frame Buffer 是非常底层的,可以理解为屏幕显示的抽象)。

双重缓存存在问题

但是 UI 绘制任务可能会因为 CPU 在忙别的事情,导致没来得及处理。所以从 Android 4.1 开始, VSYNC 则更进一步,现在 VSYNC 脉冲信号开始用于下一帧的所有处理。

Project Butter 首先对 Android Display 系统的 SurfaceFlinger 进行了改造,目标是提供 VSYNC 中断。每收到 VSYNC 中断后,CPU 会立即准备 Buffer 数据,由于大部分显示设备刷新频率都是 60 Hz(一秒刷新 60 次),也就是说一帧数据的准备工作都要在 16ms 内完成。

这样应用总是在 VSYNC 边界上开始绘制,而 SurfaceFlinger 总是在 VSYNC 边界上进行合成。这样可以消除卡顿,并提升图形的视觉表现。

Triple Buffer(三重缓存)

如果理解了双缓冲机制的原理,那就非常容易理解什么是三缓冲区了。如果只有两个 Graphic Buffer 缓冲区 A 和 B,如果 CPU / GPU 绘制过程较长,超过一个 VSYNC 信号周期。

由上图可知:

在第二个 16 ms 时间段内,Display 本应该显示 B 帧,但却因为 GPU 还在处理 B 帧,导致 A 帧被重复显示。

同理,在第二个 16 ms 时间段内,CPU 无所事事,因为 A Buffer 被 Display 在使用。 B Buffer 被 GPU 在使用。注意,一旦过了 VSYNC 时间点,CPU 就不能被触发处理绘制工作了。

为什么 CPU 不能在第二个 16ms 处理绘制工作呢?原因是只有两个 Buffer,缓冲区 B 中的数据还没有准备完成,所以只能继续展示 A 缓冲区的内容,这样缓冲区 A 和 B 都分别被显示设备和 GPU 占用,CPU 则无法准备下一帧的数据。如果再提供一个缓冲区,CPU、GPU 和显示设备都能使用各自的缓冲区工作,互不影响。

简单来说,三重缓冲机制就是在双缓冲机制基础上增加了一个 Graphic Buffer 缓冲区,这样可以最大限度的利用空闲时间,带来的坏处是多使用的一个 Graphic Buffer 所占用的内存

由上图可知:

在第二个 16ms 时间段,CPU 使用 C Buffer 完成绘图工作,虽然还是会多显示一次 A 帧,但后续显示就比较顺畅了,有效避免 Jank 的进一步加剧。

注意:是不是 Buffer 越多越好呢?这个是否定的,Buffer 正常还是两个,当出现 Jank 后三个足以。

Choreographer

Choreographer 也是 Project Butter 计划新增的机制,用于配合系统的 VSYNC 中断信号。它本质是一个 Java 类,如果直译的话为舞蹈指导,这是一个极富诗意的表达,看到这个词不得不赞叹设计者除了 Coding 之外的广泛视野。舞蹈是有节奏的,节奏使舞蹈的每个动作更加协调和连贯;视图刷新也是如此。

Choreographer 可以接收系统的 VSYNC 信号,统一管理应用的输入、动画和绘制等任务的执行时机。Android 的 UI 绘制任务将在它的统一指挥下,井然有序的完成。业界一般通过它来监控应用的帧率。

Choreographer 是线程单例的,而且必须要和一个 Looper 绑定,因为其内部有一个 Handler 需要和当前绘制线程的 Looper 绑定。

DisplayEventReceiver 是一个 abstract class,在其构造方法内会通过 JNI 创建一个 IDisplayEventConnection 的 VSYNC 的监听者。

另外 DisplayEventReceiver 中包含两个非常重要的方法:一个用于需要绘制任务时,申请 VSYNC 信号的 scheduleVsync 方法,另一个用于接收 VSYNC 信号的 onVsync 方法。FrameDisplayEventReceiver 是 DisplayEventReceiver 的唯一实现类,并重写 onVsync 方法用于通知 Choreographer。

Choreographer 的主要功能是,当收到 VSYNC 信号时,去调用通过 postCallback 设置的回调方法。目前一共定义了四种类型的回调,它们分别是:

  1. CALLBACK_INPUT:优先级最高,和输入事件处理有关;

  2. CALLBACK_ANIMATION:优先级其次,和 Animation 的处理有关;

  3. CALLBACK_TRAVERSAL:优先级最低,和 UI 等空间绘制有关;

  4. CALLBACK_COMMIT:最后执行,和提交任务有关(在 API Level 23 添加)。

优先级的高低和处理顺序有关。当收到 VSYNC 信号时,Choreographer 将首先处理 INPUT 类型的回调,然后 ANIMATION 类型,最后才是 TRAVERSAL 类型。

另外,Android 在 4.1 还对 Handler 机制进行了略微改造,使之支持 Asynchronous Message(异步消息) 和 Synchronization Barrier(同步屏障)。一般情况下同步消息和异步消息的处理方式并没有什么区别,只有在设置了同步屏障时才会出现差异。同步屏障为 Handler 消息机制增加了一种简单的优先级关系,异步消息的优先级要高于同步消息。简单点说,设置了同步屏障之后,Handler 只会处理异步消息。

总结

在从根本解决 Android UI 不流畅的问题上,Project Butter 黄油计划率先迈出了最重要一步,Android 的渲染性能也确实有了很大改善。

不过优化是无止境的,Google 在后续版本中又引入了一些比较大的改变,例如 Android 5.0 的 RenderThread,Android 将所有的绘制任务都放到了该线程,这样即便主线程有耗时的操作也可以保证动画流畅性。

瘦身计划(Project Svelte)

谷歌继推出了“Project Svelte”(瘦身计划)。开发者的目标是在保持Android运行流畅的基础上,不断减少系统运行时所占据的闪存空间。

尽管丰富强大的功能似乎与更小的运行RAM运行空间是一对矛盾,但谷歌仍在Android 4.4推出之际,完成了上述具有革新意义的“壮举”。

“瘦身计划”的具体要求是让Android系统可以运行在512 MB RAM的智能设备上。减重后的系统无疑会迎来数量庞大的低端入门Android设备

的青睐。谷歌此举更富有深意的一层在于,这将在很大程度上缓解系统碎片化问题——此前受到硬件配置要求而不得不使用Android 2.3(及以下)

系统的智能手机,也将有机会使用上Android最新的系统。

开发者是如何让Android 4.4可以运行在512MB RAM的设备上的呢?这还要从Nexus 4说起。

波尔克说道:“瘦身计划的最终目的是减少系统运行所需空间。为了达到这一要求,我们首先用一台Nexus 4进行了实验。通过不断尝试,我们成功地

将Nexus 4中的内存占用空间控制在512MB。”

在此之后,Android的工程师还对系统运行所需的最低屏幕分辨率进行了降低。为了让更多的入门级Android设备可以使用最新的系统,开发者让

Android系统可以运行在960×540的屏幕上。不仅如此,他们还调低了对CPU核数的要求,以便Android 4.4可以运行在两核的处理器中。完成所有这

一切之前,Android工程师们都在一款Nexus 4上进行了实验。

为了给系统瘦身,Android团队制订了四个发展计划:

第一、减少系统运行占用空间;

第二、减少Google Experience上的应用运行时所占的空间;

第三、保证在运行空间不足等“恶劣条件下”,应用的运行稳定与流畅;

第四、为开发者提供更好的检测工具(ProcStats),以便他们可以了解应用占用的运存情况。

前两个计划已经通过在特殊配置的Nexus 4实验中达成了。系统所占的运存空间随着Android 4.4的发布已控制在了512MB之内。应用运行空间也通过谷

歌应用商店的“分流”而降低。比如,位置应用已经作为一个单独的应用(而不是系统应用)出现在Google Play之中。

后两个计划也通过良好的系统(应用)监控机制而得到了实现。比如,如果Android发现某款应用长时间占据了太多的运存空间,那么系统就会自动关闭这

一应用。在开发者版本的Android 4.4系统中,有一个名为“ProcStats”的进程监控工具。它可以24小时为开发者提供应用运行情况,提供应用占据多少

运行空间等数据。

尽管普通使用者无法发现Android 4.4在以上等方面的重大变化,可谷歌却在“无声无息”之中让Android系统变得更加轻盈。更难的是,上述那些都是

在毫不损失用户体验的情况下完成的。 而这一点正是Android开发过程中最巧妙、最伟大之处。

伏特计化(Project Volta)

Android L,伴随而来的是针对续航改进的“Project Volta”。Google 表示,真正优化之后省电模式至少可以让 Nexus 5 增加 90 分钟的续航时间。

Project Volta 究竟让 Android 续航提升了多少?Ars Technica 使用两台 Nexus 5 进行了一次续航对比测试,测试尽可能保证了实验条件的精准:一台搭载 Android 4.4 KitKat,另一台搭载 Android L 预览版,亮度同时保持 200nit,保持屏幕常亮、同时更新应用,在 Wi-Fi 环境下每 15 秒刷新一次网页,直至电量耗尽为止。

实验结果显示,搭载 Android 4.4 的续航时间为 345 分钟,而Android L 预览版的续航时间则高达 471 分钟,续航能力提升 36%,多了两小时的使用时间。

需要提到的是,Android L 还提供了一个**“电池保护”**的功能,当设备电量低于 15% 时系统会自动降低设备性能、切断后台数据、调低屏幕亮度。尽管可以更进一步提升续航能力,不过测试并没有应用该功能。

“Project Volta” 对 Android 续航能力的提升源于多项措施。首先,“Project Volta”可以通过分析来发现系统资源的最大消耗者,并在节能模式下控制这些进程,从而达到节电的目的。

Google 测试发现,用户每点亮一次屏幕大约消耗 2 分钟的待机,这不仅仅源于屏幕消耗,一些应用程序或网络模块执行后台数据刷新的操作也会消耗电量。Android L 引入了新的“**JobScheduler” **API,使得Android 可以分批处理数据清理和日志上传等不重要的应用请求。

另外,增强的** Battery Historian **电量消耗统计跟踪器增加了大量电量追踪功能,为开发者带来了数据可视化的图标,开发者可以通过有针对性的调整来延长电池续航时间。

当然,ART 替代 Dalvik 成为 Android 的默认虚拟机也是重要原因之一,ART 可以一次性将 Android 应用编译成本地代码,减少了即时编译对计算性能的浪费,从而提高了运行效率。

Project Treble

Android 8.0 重新设计了 Android 操作系统框架(在一个名为“Treble”的项目中),以便让制造商能够以更低的成本更轻松、更快速地将设备更新到新版 Android 系统。在这种新架构中,HAL 接口定义语言(HIDL,发音为“hide-l”)指定了 HAL 和其用户之间的接口,让用户无需重新构建 HAL,就能替换 Android 框架。

利用新的供应商接口,HIDL 将供应商实现(由芯片制造商编写的设备专属底层软件)与 Android 操作系统框架分离开来。供应商或 SOC 制造商构建一次 HAL,并将其放置在设备的 /vendor 分区中;框架可以在自己的分区中通过无线下载 (OTA) 更新进行替换,而无需重新编译 HAL。

关于 Android 更新

利用新的供应商接口,Project Treble 将供应商实现(由芯片制造商编写的设备专属底层软件)与 Android 操作系统框架分离开来。

Android 7.x 及更早版本中没有正式的供应商接口,因此设备制造商必须更新大量 Android 代码才能将设备更新到新版 Android 系统:

图 1. Treble 推出前的 Android 更新环境

Treble 提供了一个稳定的新供应商接口,供设备制造商访问 Android 代码中特定于硬件的部分,这样一来,设备制造商只需更新 Android 操作系统框架,即可跳过芯片制造商直接提供新的 Android 版本:

图 2. Treble 推出后的 Android 更新环境
对 Treble 进行测试

所有搭载 Android 8.0 及更高版本的新设备都可以利用这种新架构。为了确保供应商实现的向前兼容性,供应商接口会由供应商测试套 (VTS) 进行验证,该套件类似于兼容性测试套件 (CTS)。您可以使用 VTS 在旧版 Android 架构和当前 Android 架构中自动执行 HAL 和操作系统内核测试。

Treble 资源

要详细了解新的 Treble 架构,请参阅以下部分:

HAL 类型:提供了关于绑定式 HAL、直通 HAL、Same-Process (SP) HAL 和旧版 HAL 的说明。

HIDL(一般信息):包含关于 HAL 接口定义语言(简称 HIDL,发音为“hide-l”)的一般信息;HIDL 是用于指定 HAL 和其用户之间接口的接口描述语言 (IDL)。

HIDL (C++):包含关于为 HIDL 接口创建 C++ 实现的详情。

HIDL (Java):包含关于 HIDL 接口的 Java 前端的详情。

ConfigStore HAL:提供了关于 ConfigStore HAL 的说明;该 HAL 提供了一组 API,可供访问用于配置 Android 框架的只读配置项。

设备树叠加层:提供了关于在 Android 中使用设备树叠加层 (DTO) 的详情。

供应商原生开发套件 (VNDK):提供了关于 VNDK(专门用来让供应商实现其 HAL 的一组库)的说明。

供应商接口对象 (VINTF):VINTF 对象整合了关于设备的相关信息,并让这类信息可通过可查询 API 提供。

SELinux for Android 8.0:提供了关于 SELinux 变更和自定义的详情。

Project Mainline

模块化系统组件

Android 10 或更高版本采用模块化方式来处理一些 Android 系统组件,使其能够在 Android 的常规发布周期外的时间进行更新。最终用户设备可以从 Google Play 商店基础架构或通过合作伙伴提供的无线下载 (OTA) 机制接收这些模块化系统组件的更新。

关于模块化系统组件

模块化系统组件使 Google 和 Android 合作伙伴能够以非侵入性的方式广泛、快速且无缝地向最终用户设备分发更新。例如,媒体编解码器碎片化和严重错误的结合会显着降低应用采用率和用户参与度。对媒体相关模块的频繁更新可以减少编解码器碎片,使不同 Android 设备上的媒体应用行为更加一致,并修复关键错误以建立用户信任。

架构

Android 10 或更高版本会将选定的系统组件转换为模块,其中一些模块采用 APEX 容器格式(在 Android 10 中引入),另一些则采用 APK 格式。借助模块化架构,系统组件能够根据需要以修复严重问题以及做出其他改进的方式进行更新,而不会影响较低级别的供应商实现或较高级别的应用和服务。

图 1. 模块化系统组件

模块更新不会引入新的 API。它们仅使用由兼容性测试套件 (CTS) 保证的 SDK 和系统 API,并且只会彼此之间进行通信,且只使用稳定的 C API 或稳定的 AIDL 接口。

您可以将更新后的模块化系统组件打包在一起,并通过 Google(使用 Google Play 商店基础架构)或 Android 合作伙伴(使用合作伙伴提供的 OTA 机制)将其推送到最终用户设备。模块软件包会以原子方式安装(和回滚),这意味着所有需要更新的模块都会进行更新,或者所有模块都不会进行更新。例如,如果某个需要更新的模块出于某种原因无法更新,设备不会安装软件包中的任何模块。

可用模块
模块名称 软件包名称 类型 推出的版本
adbd com.google.android.adbd APEX Android 11
Runtime com.android.runtime.release.apex APEX Android 10
Captive Portal Login com.android.captiveportallogin APK Android 10
CellBroadcast com.google.android.cellbroadcast APEX Android 11
Conscrypt com.android.conscrypt APEX Android 10
DNS Resolver com.android.resolv APEX Android 10
DocumentsUI com.android.documentsui APK Android 10
ExtServices com.android.ext.services APK (Android 10) APEX (Android 11) Android 10
IPsec/IKEv2 Library com.google.android.ipsec APEX Android 11
Media Codecs com.android.media.swcodec APEX Android 10
Media com.android.media APEX Android 10 (extractors, MediaSession API) Android 11 (MediaParser API)
MediaProvider com.google.android.mediaprovider APEX Android 11
ModuleMetadata com.android.modulemetadata APK Android 10
Network Stack Permission Configuration com.android.networkstack.permissionconfig APK Android 10
Network Components com.android.networkstack APK Android 10
NNAPI Runtime com.google.android.neuralnetworks APEX Android 11
PermissionController com.android.permissioncontroller APK Android 10
SDK Extensions com.android.sdkext APEX Android 11
Statsd com.google.android.os.statsd APEX Android 11
Telemetry Train Version Package com.google.mainline.telemetry APEX Android 11
Tethering com.google.android.tethering APK Android 11
Time Zone Data com.android.tzdata APEX Android 10
Wi-Fi com.google.android.wifi.apex APEX Android 11

Android框架整体介绍

Android是一种基于Linux的开放源代码软件栈,为各类设备和机型而创建。下图所示为Android平台的主要组件。

Android 软件堆栈(old version)

Android 软件堆栈(new version)

Linux 内核

Android平台的基础是Linux内核。例如,Android Runtime (ART) 依靠Linux内核来执行底层功能,例如线程和低层内存管理。

使用Linux内核可让Android利用主要安全功能,并且允许设备制造商针对内核开发硬件驱动程序。

硬件抽象层 (HAL,Hardware Abstraction Layer)

硬件抽象层(HAL) 提供标准接口,向更高级别的Java API 框架暴露设备硬件功能。HAL包含多个库模块,其中每个模块都为特定类型的硬件组件实现一个接口,例如相机或蓝牙模块。当框架 API 要求访问设备硬件时,Android 系统将为该硬件组件加载库模块。

Android Runtime

对于运行 Android 5.0(API 级别 21)或更高版本的设备,每个应用都在其自己的进程中运行,并且有其自己的 Android Runtime (ART) 实例。ART可以通过执行DEX文件
在低内存设备上运行多个虚拟机,DEX文件是一种专为Android设计的字节码格式,经过优化,使用的内存很少。编译工具链(例如 d8)将 Java 源代码编译为 DEX 字节码,使其可在 Android 平台上运行。

ART的部分主要功能包括:

预先预编译 (AOT,Ahead-of-time) 和即时 (JIT,just-in-time) 编译

优化的垃圾回收 (GC,garbage collection)

在 Android 9(API 级别 28)及更高版本的系统中,支持将应用软件包中的 Dalvik Executable 格式 (DEX) 文件转换为更紧凑的机器代码。

更好的调试支持,包括专用采样分析器(profiler)、详细的诊断异常和崩溃报告(bugreport),并且能够设置观察点以监控特定字段(Trace)

在 Android 版本 5.0(API 级别 21)之前,Dalvik 是 Android Runtime。如果您的应用在 ART 上运行效果很好,那么它应该也可在 Dalvik 上运行,但反过来不一定。

Android 还包含一套核心运行时库,可提供 Java API 框架所使用的 Java 编程语言中的大部分功能,包括一些 Java 8 语言特性。

原生C/C++库

许多核心Android系统组件和服务(例如ART和HAL构建自原生代码,需要以C和C++编写的原生库。Android平台提供 Java 框架 API 以向应用显示其中部分原生库的功能。例如,您可以通过 Android 框架的 Java OpenGL API 访问 OpenGL ES,以支持在应用中绘制和操作 2D 和 3D 图形。

如果开发的是需要 C 或 C++ 代码的应用,可以使用 Android NDK 直接从原生代码访问某些原生平台库。

Java API 框架

您可通过以 Java 语言编写的 API 使用 Android OS 的整个功能集。这些 API 形成创建 Android 应用所需的构建块,它们可简化核心模块化系统组件和服务的重复使用,包括以下组件和服务:

丰富、可扩展的视图系统,可用以构建应用的 UI,包括列表、网格、文本框、按钮甚至可嵌入的网络浏览器

资源管理器(Resource Manager),用于访问非代码资源,例如本地化的字符串、图形和布局文件

通知管理器(Notification Manager ),可让所有应用在状态栏中显示自定义提醒

Activity管理器( Activity Manager),用于管理应用的生命周期,提供常见的导航返回栈

内容提供程序(Content Providers ),可让应用访问其他应用(例如“联系人”应用)中的数据或者共享其自己的数据

开发者可以完全访问 Android 系统应用使用的框架 API。

系统应用

Android 系统集成了一套用于电子邮件、短信、日历、互联网浏览和联系人等的核心应用。平台集成的应用与用户可以选择安装的应用一样,没有特殊状态。因此第三方应用可成为用户的默认网络浏览器、短信 Messenger 甚至默认键盘(有一些例外,例如系统的“设置”应用)。

系统应用可用作用户的应用,以及提供开发者可从其自己的应用访问的主要功能。例如,如果您的应用要发短信,您无需自己构建该功能,可以改为调用已安装的短信应用向您指定的接收者发送消息。

Android兼容性测试

Android 的目的是构建一个开放平台,供开发者打造创新应用。

Android 兼容性计划定义了 Android 平台的技术细节,并为原始设备制造商 (OEM) 提供了各种工具,以确保开发者应用可以在各种设备上顺利运行。

Android SDK 为开发者提供了内置工具,方便他们清楚地说明其应用所需的设备功能。

Google Play 只会将应用显示给可以正常运行这些应用的设备。

计划组成部分

Android 兼容性计划由三个关键部分组成:

Android 开源项目的源代码

兼容性定义文档 (CDD),介绍兼容性的“政策”方面

兼容性测试套件 (CTS),介绍兼容性的“机制”

Android 兼容性计划是免费的,而且申请步骤很简单

按以下三个步骤操作即可打造与 Android 兼容的移动设备:

  1. 获取 Android 软件源代码。这是要移植到您的硬件的 Android 平台源代码。
  1. 遵循 Android 兼容性定义文档 (CDD)(PDF 版、HTML 版)。CDD 列出了兼容的 Android 设备应遵循的软件和硬件要求。
  1. 通过兼容性测试套件 (CTS,Compatibility Test Suite) 测试。在开发过程中可随时借助 CTS 评估兼容性。

在符合 CDD 要求且通过 CTS 测试后,您的设备即是与 Android 兼容的设备,这意味着生态系统中的 Android 应用在您的设备上运行时可提供一致的体验。

就像每个版本的 Android 平台存在于源代码树的单独分支中一样,每个版本也具有单独的 CTS 和 CDD。CDD、CTS 和源代码,再加上您的硬件和软件自定义内容,便是打造兼容设备所需的一切。

申请 Google 移动服务 (GMS) 许可

打造与 Android 兼容的设备后,请考虑申请在 Android 上运行的 Google 移动服务(简称 GMS,指 Google 拥有的一系列应用,包括 Google Play、YouTube、Google 地图、Gmail 等)的使用许可。GMS 不是 Android 开源项目的一部分,您只有在获得 Google 许可后才能使用这些服务

CTS Verify

Android 兼容性测试套件验证程序 (CTS 验证程序) 补充了兼容性测试套件 (CTS)。CTS 检查可以自动化的 API 和功能,而 CTS Verifier 提供了在没有手动输入的情况下无法在固定设备上测试的 API 和功能的测试,例如音频质量、触摸屏、加速度计和相机。

GTS

GTS的全称是Google Mobile Services Test Suite,所谓的Google Mobile Services即谷歌移动服务,是谷歌开发并推动Android的动力,也是Android系统的灵魂所在。GMS目前提供有Search、Search by Voice、Gmail、Contact Sync、Calendar Sync、Talk、Maps、Street View、YouTube、Android Market (ICS 上更改为Play store)服务。当用户使用谷歌的时候,谷歌可以把广告嵌入各种谷歌的服务中。

依据GMS,谷歌对android手机给予不同程度的授权,把搭载Android系统的手机厂商分为三个级别

1. 免费使用Android操作系统,但不内嵌GMS。

2. 内嵌部分GMS,但手机不能打上谷歌的商标。

3. 内嵌所有的GMS服务,也可以使用谷歌商标。如果在android手机中内置有谷歌GMS服务的话,是等同被谷歌官方认证过的产品。

VTS (Vendor Test Suite (VTS) & Infrastructure)

Project Treble 中引入 Vendor Interface 的目的是将 Android Framework 与 HAL 分开,并通过 VTS 测试来对这些 Vendor Interface 进行测试以确保 HAL 的向前兼容

我们知道 APP 层与 Framework 层在设计上是分开的, 但通过 CTS 测试,确保了 APP 与 Android Framework 之间有一致的调用接口(API),这使得 APP 开发者编写的同一款程序可以运行在不同系统版本(向前兼容)、不同硬件平台、不同厂商制造的不同设备上。 VTS 类似 CTS,通过对 Vendor Interface 进行测试,确保同一个版本的 Android Framework 可以运行在不同 HAL 上,或不同 Android Framework 可以运行在 同一个 HAL 上。 通过这样的 Framework / HAL 分离设计和接口一致性保证,也使得 8.0 版本之后的 Android 系统在进行升级时,可以直接对 Framework 进行升级而不用考虑 HAL 层的改动,从而缩短了用户手上设备得到系统升级 OTA 推送的时间。

代码下载

源代码控制工具

如需使用 Android 代码,您需要使用 Git(一种开源版本控制系统)和 Repo(一种对 Git 构成补充的 Google 代码库管理工具)。如需查看您可以执行的常规操作(例如上传更改以供审核)的摘要,请参阅源代码控制工作流程页面。

Git

Git 可以处理分布在多个代码库上的大型项目。Android 使用 Git 执行本地操作,例如建立本地分支、提交、对比差异、修改。打造 Android 项目所面临的挑战之一就是确定如何最好地支持外部社区 - 从业余爱好者社区到生产大众消费类设备的大型 OEM。Google 希望组件可以替换,并希望有趣的组件能够在 Android 之外自行发展。Google 最初决定使用一种分布式修订版本控制系统,经过筛选,最后选中了 Git。

Repo

Repo 可以在必要时整合多个 Git 代码库,将相关内容上传到 Gerrit 修订版本控制系统,并自动执行 Android 开发工作流程的部分环节。

Repo 启动器会提供一个 Python 脚本,该脚本可以初始化检出,并可以下载第二部分,即完整的 Repo 工具。完整的 Repo 工具包含在 Android 源代码检出中。该工具默认位于 $SRCDIR/.repo/repo/… 中,它可以从下载的 Repo 启动器接收转发的命令。

Repo 不会取代 Git,只是为了让您在 Android 环境中更轻松地使用 Git。Repo 使用清单文件将 Git 项目汇总到 Android 超级项目中。您可以将 repo 命令(这是一个可执行的 Python 脚本)放在路径中的任何位置。使用 Android 源代码文件时,您可以使用 Repo 执行跨网络操作,例如使用一个 Repo 工作目录。

在大多数情况下,您可以仅使用 Git(不必使用 Repo),或结合使用 Repo 和 Git 命令以组成复杂的命令。不过,使用 Repo 执行基本的跨网络操作可大大简化您的工作。如需详细了解 Repo,请参阅 Repo 命令参考资料、Repo README、可在 Repo 中启用的预上传钩子(测试)以及 AOSP 中的通用文档。

Gerrit

Gerrit 是一个基于网页的代码审核系统,适用于使用 Git 的项目。Gerrit 允许所有授权用户提交更改(如果这些更改通过代码审核,便会自动纳入到项目中),以此鼓励他们更集中地使用 Git。此外,Gerrit 会在浏览器中并排显示更改,并支持代码内注释,从而使审核工作变得非常轻松。

代码下载流程

安装 Repo

  1. 确保您的主目录中有一个 bin/ 目录,并且它包含在您的路径中:
mkdir ~/bin
PATH=~/bin:$PATH

1.下载 Repo 启动器,并确保它可执行:

curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo

下载源代码

  1. 创建一个空目录来存放您的工作文件。为其指定一个您喜欢的任意名称:
mkdir WORKING_DIRECTORY
cd WORKING_DIRECTORY
  1. 使用您的真实姓名和电子邮件地址配置 Git
git config --global user.name Your Name
git config --global user.email [email protected]
  1. 运行 repo init 获取最新版本的 Repo 及其最新的 bug 修复
repo init -u https://android.googlesource.com/platform/manifest

  1. 下载 Android 源代码树
repo sync 

or 

repo sync -c -j<threadcount >

代码编译

设置环境

使用 envsetup.sh 脚本初始化环境

source build/envsetup.sh

选择目标

lunch

lunch product_name-build_variant

lunch aosp_arm-eng

构建代码

m 可以使用 -jN 参数处理并行任务

m -j8

AndroidNN

Android Neural Networks API (NNAPI) 是一个 Android C API,专为在 Android 设备上运行计算密集型运算从而实现机器学习而设计。NNAPI 旨在为更高层级的机器学习框架(如 TensorFlow Lite 和 Caffe2)提供一个基本功能层,用来建立和训练神经网络。搭载 Android 8.1(API 级别 27)或更高版本的所有 Android 设备上都提供该 API。

NNAPI 支持通过将 Android 设备中的数据应用到先前训练的开发者定义的模型来进行推断。推断的示例包括为图像分类、预测用户行为以及选择针对搜索查询的适当响应。

Neural Networks API 运行时

NNAPI 应由机器学习库、框架和工具调用,这样可让开发者在设备外训练他们的模型,并将其部署在 Android 设备上。应用一般不会直接使用 NNAPI,而会使用更高层级的机器学习框架。这些框架进而又可以使用 NNAPI 在受支持的设备上执行硬件加速的推断运算。

根据应用的要求和 Android 设备的硬件功能,Android 的神经网络运行时可以在可用的设备上处理器(包括专用的神经网络硬件、图形处理单元 (GPU) 和数字信号处理器 (DSP))之间高效地分配计算工作负载。

对于缺少专用供应商驱动程序的 Android 设备,NNAPI 运行时将在 CPU 上执行请求。

图 所示为 NNAPI 的简要系统架构

Neural Networks API 编程模型

若要使用 NNAPI 执行计算,您需要先构造一张有向图来定义要执行的计算。此计算图与您的输入数据(例如,从机器学习框架传递过来的权重和偏差)相结合,构成 NNAPI 运行时求值的模型。

NNAPI 使用四个主要抽象概念:

模型:由数学运算和通过训练过程学习到的常量值构成的计算图。这些运算特定于神经网络。它们包括二维 (2D) 卷积、逻辑 (sigmoid) 激活函数、修正线性 (ReLU) 激活函数等。创建模型是一项同步操作。成功创建后,便可在线程和编译之间重用模型。在 NNAPI 中,模型表示为 ANeuralNetworksModel 实例。

编译:表示用于将 NNAPI 模型编译到更低级别代码中的配置。创建编译是一项同步操作。成功创建后,便可在线程和执行之间重用编译。在 NNAPI 中,每个编译都表示为一个 ANeuralNetworksCompilation 实例。

内存:表示共享内存、内存映射文件和类似内存缓冲区。使用内存缓冲区可让 NNAPI 运行时更高效地将数据传输到驱动程序。应用一般会创建一个共享内存缓冲区,其中包含定义模型所需的每个张量。您还可以使用内存缓冲区来存储执行实例的输入和输出。在 NNAPI 中,每个内存缓冲区均表示为一个 ANeuralNetworksMemory 实例。

执行:用于将 NNAPI 模型应用到一组输入并收集结果的接口。执行可以同步执行,也可以异步执行。

对于异步执行,多个线程可以等待同一执行。此执行完成后,所有线程都被释放。

在 NNAPI 中,每次执行均表示为一个 ANeuralNetworksExecution 实例。

" >

Android Neural Networks API 的编程流程

Neural Networks代码仓库

Android Neural Networks 代码仓库

Neural Networks Driver

神经网络 HAL

神经网络 (NN) HAL 定义了产品(例如手机或平板电脑)中各种设备的抽象概念,例如图形处理单元 (GPU) 和数字信号处理器 (DSP)。这些设备的驱动程序必须符合 NN HAL。接口在 hardware/interfaces/neuralnetworks 下的 HAL 定义文件中指定。

下图显示了框架和驱动程序之间的接口遵循的一般流程。

神经网络流程
初始化

在进行初始化时,框架使用 IDevice::getCapabilities_1_3 向驱动程序查询其功能。@1.3::Capabilities 结构包括所有数据类型,并使用向量表示非放宽(no-relaxed,freed from or lacking in precision or stringency)的性能。

为了确定如何将计算分配给可用设备,框架根据这些功能了解每个驱动程序的执行速度和执行能效。为了提供这些信息,驱动程序必须根据参考工作负载的执行情况提供标准化的性能值。

如需确定驱动程序响应 IDevice::getCapabilities_1_3 而返回的值,请使用 NNAPI 基准应用衡量处理相应数据类型时的性能。建议使用 MobileNet v1 和 v2 asr_float 和 tts_float 模型衡量处理 32 位浮点值时的性能,并建议使用 MobileNet v1 和 v2 量化模型衡量处理 8 位量化值时的性能。如需了解详情,请参阅 Android 机器学习测试套件

在 Android 9 及更低版本中,Capabilities 结构仅包含浮点和量化张量的驱动程序性能信息,不包含标量数据类型的驱动程序性能信息。

在初始化过程中,框架可能会使用 IDevice::getType、IDevice::getVersionString、IDevice:getSupportedExtensions 和 IDevice::getNumberOfCacheFilesNeeded 查询更多信息。

在产品重新启动之间,框架希望本部分中描述的所有查询始终针对指定驱动程序报告相同的值。否则,使用该驱动程序的应用可能会出现性能下降或行为不当的情况。

编译

在收到应用的请求时,框架会确定要使用的设备。在 Android 10 中,应用可以发现并指定设备,让框架从中进行选择。如需了解详情,请参阅设备发现和分配

在模型编译过程中,框架通过调用 IDevice::getSupportedOperations_1_3 将模型发送到每个候选驱动程序。每个驱动程序都会返回一个布尔值数组,以指出支持模型的哪些运算。驱动程序可以根据多种原因确定无法支持指定的运算。例如:

驱动程序不支持相应数据类型。

驱动程序仅支持具有特定输入参数的运算。例如,驱动程序可能支持 3x3 和 5x5 卷积运算,但不支持 7x7 卷积运算。

驱动程序具有内存限制,导致无法处理大型图表或输入

在编译期间,模型的输入、输出和内部运算数(如 OperandLifeTime 中所述)可能具有未知的维度或秩。如需了解详情,请参阅输出形状

框架通过调用 IDevice::prepareModel_1_3 指示每个选定驱动程序准备好执行一部分模型。然后,每个驱动程序会编译自己负责的那一部分模型。例如,驱动程序可能会生成代码或创建重新排序的权重副本。由于编译模型和执行请求之间可能间隔很长时间,因此不应在编译期间分配诸如大块设备内存等资源。

编译成功后,驱动程序会返回 @1.3::IPreparedModel 句柄。如果驱动程序在准备自己的那一部分模型时返回失败代码,框架会在 CPU 上运行整个模型。

为了减少应用启动时编译所用的时间,驱动程序可以缓存编译工件。如需了解详情,请参阅编译缓存

执行

当应用要求框架执行请求时,框架会默认调用 IPreparedModel::executeSynchronously_1_3 HAL 方法,以在准备好的模型上同步执行请求。也可以使用 execute_1_3 方法、executeFenced 方法(请参阅围栏执行) 异步执行请求,或者使用爆发执行方法执行请求。

与异步调用相比,同步执行调用可提高性能并减少线程开销,因为只有在执行完成后才将控制权返还给应用进程。这意味着驱动程序不需要单独的机制来通知应用进程执行已完成。

如果使用异步 execute_1_3 方法,控制权在执行开始后便返还给应用进程,并且驱动程序必须在执行完成时使用 @1.3::IExecutionCallback 通知框架。

传递给 execute 方法的 Request 参数列出了用于执行的输入和输出运算数。存储运算数数据的内存必须使用行主序,第一维度的迭代速度最慢,并且在任何行的末尾都没有填充。如需详细了解运算数类型,请参阅运算数

对于使用 NN HAL 1.2 或更高版本的驱动程序,当请求完成时,错误状态、输出形状和时间信息会返回到框架。在执行期间,模型的输出或内部运算数可具有一个或多个未知维度或未知秩。当至少一个输出运算数具有未知维度或秩时,驱动程序必须返回大小动态变化的输出信息。

对于使用 NN HAL 1.1 或更低版本的驱动程序,在请求完成时仅返回错误状态。必须完全指定输入和输出运算数的维度,才能成功完成执行。内部运算数可具有一个或多个未知维度,但它们必须具有指定的秩。

对于涉及多个驱动程序的用户请求,框架负责预留中间内存,并按顺序执行对每个驱动程序的调用。

可以在同一个 @1.3::IPreparedModel 上并行发起多个请求。驱动程序可以并行执行这些请求,也可以按顺序执行。

框架可以要求驱动程序保留多个准备好的模型。例如,准备模型 m1,准备 m2,在 m1 上执行请求 r1,在 m2 上执行 r2,在 m1 上执行 r3,在 m2 上执行 r4,释放(如清理中所述)m1,以及释放 m2。

为了避免首次执行速度缓慢(这可能会导致糟糕的用户体验,比如第一帧卡顿),驱动程序应在编译阶段执行大部分初始化工作。首次执行时的初始化应仅限于过早执行会对系统运行状况产生负面影响的操作,例如预留较大的临时缓冲区或提高设备的时钟频率。只能准备有限数量的并发模型的驱动程序可能必须在首次执行时进行初始化。

在 Android 10 或更高版本中,如果快速连续地执行针对准备好的同一个模型的多个执行请求,客户端可以选择使用执行爆发对象在应用和驱动程序进程之间进行通信。如需了解详情,请参阅爆发执行和快速消息队列。

为了提高多次快速连续执行的性能,驱动程序可以保留临时缓冲区或提高时钟频率。建议创建一个监控线程,在经过固定的一段时间后未创建任何新请求时释放资源。

参考链接:

Project Treble

Project Svelte

Project Volta

Project Butter

Treble 现已推出:Android 的模块化基础

借助 Treble 项目更快速地采用新系统

Project Treble

Modular System Components

Android 兼容性计划概览

Compatibility Test Suite

Using CTS Verifier

Android 平台测试

Android下载

编译 Android

Neural Networks API 驱动程序

Neural Networks API

猜你喜欢

转载自blog.csdn.net/lincolnjunior_lj/article/details/131223767
今日推荐