Android 硬件加速流程和源码分析(一)
我们在Android开发过程中多少会听到硬件加速这个名词,但是实际开发中好像基本和我们又没有太多关系,那么到底什么是硬件加速? 加速了啥? 为啥要加速?
硬件加速简单说来就是通过硬件GPU来处理anroid图形界面的渲染,加速页面渲染的速度.在开启硬件加速的情况下,部分原来需要CPU完成的渲染工作丢给了专门处理图形渲染的GPU,也部分解放了CPU的性能用于其他运算,同时由于GPU的架构就是专为图形处理而生,GPU处理同样的渲染工作会比CPU更高速高效.
贴一个GPU和CPU的一个对比的视频连接,只是形象的说明GPU在图形处理上的效率,但这并不是说明GPU就比CPU强,只是各自专注的部分不一样而已.
1. Android硬件加速介绍
从 Android 3.0(API 级别 11)开始,Android 2D 渲染管道支持硬件加速,也就是说,在 View的画布上执行的所有绘制操作都会使用 GPU。启用硬件加速需要更多资源,因此应用会占用更多内存。
如果您的目标 API 级别为 14 及更高级别,则硬件加速默认处于启用状态,但也可以明确启用该功能。如果您的应用仅使用标准视图和 Drawable,则全局启用硬件加速不会造成任何不良绘制效果。不过,并非所有 2D 绘制操作都支持硬件加速,因此启用硬件加速可能会影响您的部分自定义视图或绘制调用。
1.1 硬件加速相关设置
Android中,开发者可以分别在 Application/Activity/window/View级别开启或者关闭硬件加速, 注意不是每个级别都想开就开,想关就关硬件加速,这个还得取决于他的上一个级别的硬件加速开关的设置状态.
- 窗口级别开启硬件加速
window.setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED )
注意:您目前无法在窗口级别停用硬件加速
- 视图级别停用硬件加速
myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
注意:您目前无法在视图级别启用硬件加速
- 为啥不能窗口级别停用硬件加速?
Activity#attach()
final void attach(...
ActivityInfo info,
..
) {
...
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
...
}
Window
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
...
mHardwareAccelerated = hardwareAccelerated;
...
}
void adjustLayoutParamsForSubWindow(WindowManager.LayoutParams wp) {
if (mHardwareAccelerated ||
(mWindowAttributes.flags & FLAG_HARDWARE_ACCELERATED) != 0) {
//
wp.flags |= FLAG_HARDWARE_ACCELERATED;
}
}
以上代码可以看出window是否开启硬件加速取决于Activity清单文件中的设置ActivityInfo info 和WindowManager.LayoutParams标志位的共同判断, ||说明 layoutParams中的标志位只能开,不能关闭
然后在 ViewRootImpl中setView方法会调用enableHardwareAcceleration(WindowManager.LayoutParams attrs) 来开启硬件加速
983 private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
984 mAttachInfo.mHardwareAccelerated = false;
985 mAttachInfo.mHardwareAccelerationRequested = false;
....
991 final boolean hardwareAccelerated =
992 (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
993 //设置了硬件加速标志时开启硬件加速
994 if (hardwareAccelerated) {
...
999 // Persistent processes (including the system) should not do
1000 // accelerated rendering on low-end devices. In that case,
1001 // sRendererDisabled will be set. In addition, the system process
1002 // itself should never do accelerated rendering. In that case, both
1003 // sRendererDisabled and sSystemRendererDisabled are set. When
1004 // sSystemRendererDisabled is set,PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED
1005 // can be used by code on the system process to escape that and enable
1006 // HW accelerated drawing. (This is basically for the lock screen.)
1007 //上面的意思就是说安卓常驻进程在很low的设备上不使用硬件加速,但是嘞在这些不使用硬件加速的进程中又有部分要使用硬件加速的页面,比如锁屏页,forceHwAccelerated 就是为了这种情况
1008 final boolean fakeHwAccelerated = (attrs.privateFlags &
1009 WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED) != 0;
1010 final boolean forceHwAccelerated = (attrs.privateFlags &
1011 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED) != 0;
1012
1013 if (fakeHwAccelerated) {
1014 // This is exclusively for the preview windows the window manager
1015 // shows for launching applications, so they will look more like
1016 // the app being launched.
//fakeHwAccelerated 是给启动一个application的预览窗口设置的
1017 mAttachInfo.mHardwareAccelerationRequested = true;
1018 } else if (!ThreadedRenderer.sRendererDisabled
1019 ...
//创建渲染器
1032 mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(...);
1034 ...
//mAttachInfo的硬件加速标志位设置
1036 mAttachInfo.mHardwareAccelerated = mAttachInfo.mHardwareAccelerationRequested = true;
1038 ...
1039 }
1040 }
1041 }
1042
-
为啥不能在视图级别启用硬件加速?
view中定义的方法isHardwareAccelerated表明了view是否支持硬件加速.
public boolean isHardwareAccelerated() { return mAttachInfo != null && mAttachInfo.mHardwareAccelerated; }但是view是否使用硬件加速由当前 window
mAttachInfo.mHardwareAccelerated和当前view的layerTypelayerType == LAYER_TYPE_SOFTWARE共同决定,mAttachInfo.mHardwareAccelerated 由window的flag决定,视图级别可以设置View的layerType,简单说来就是视图级别可以决定自己不用硬件加速,但是当window级别没有使用硬件加速时,视图级别想用也没得用,所以不能在视图级别启用硬件加速. -
为啥有时自定义控件要禁止硬件加速?
因为Android canvas部分api不支持硬件加速 ,所以只能在自定义控件中调用
setLayerType(View.LAYER_TYPE_SOFTWARE, null)来表明当前控件使用LAYER_TYPE_SOFTWARE类型绘制而不使用硬件加速绘制, View树种其他控件不受影响该咋渲染还咋渲染,至于哪些api不支持硬件加速,请点击这里下拉看官方说明.
1.2 软件绘制和硬件加速的区别
-
基于软件的绘制模型的绘制步骤
-
对层次结构进行无效化处理 invalidate()
-
绘制层次结构
-
-
硬件加速绘制模型的绘制步骤
- 对层次结构进行无效化处理 invalidate()
- 记录并更新显示列表 DisplayList(DisplayList 很重要,下面详解)
- 绘制显示列表