一、背景
智能座舱在播放音乐的时候,有歌曲名称的media widget,当歌曲名称比较长的情况下,会有走马灯Marquee的效果,然后在桌面待机状态下,测试发现cpu loading过高,总体cpu负载120%左右,针对这种场景,需要优化这一特定场景的cpu 负载。
二、问题分析以及修改方案
通过抓systrace分析可知,launcher3 的app刷新率是60fps,通过结合代码分析,是media widget跑马灯功能固定的60fps,导致cpu loading过高,要想办法将60fps降低到30fps。
通过代码跟踪,最后找到是TextView的tick()函数会根据屏幕刷新率申请app vsync实现60fps的帧率效果。
void tick() {
if (mStatus != MARQUEE_RUNNING) {
return;
}
mChoreographer.removeFrameCallback(mTickCallback);
final TextView textView = mView.get();
if (textView != null && textView.isAggregatedVisible()
&& (textView.isFocused() || textView.isSelected())) {
long currentMs = mChoreographer.getFrameTime();
long deltaMs = currentMs - mLastAnimationMs;
mLastAnimationMs = currentMs;
float deltaPx = deltaMs * mPixelsPerMs;
mScroll += deltaPx;
if (mScroll > mMaxScroll) {
mScroll = mMaxScroll;
mChoreographer.postFrameCallbackDelayed(mRestartCallback, MARQUEE_DELAY);
} else {
mChoreographer.postFrameCallback(mTickCallback);
}
textView.invalidate();
}
}
修改方案:postFrameCallbackDelayed 错开16.6ms的vsync,就能实现32ms的vsync。
long delayTimeMs = 1000 / 60 + 2;
mChoreographer.postFrameCallbackDelayed(mTickCallback, delayTimeMs);
void tick() {
if (mStatus != MARQUEE_RUNNING) {
return;
}
mChoreographer.removeFrameCallback(mTickCallback);
final TextView textView = mView.get();
if (textView != null && textView.isAggregatedVisible()
&& (textView.isFocused() || textView.isSelected())) {
long currentMs = mChoreographer.getFrameTime();
long deltaMs = currentMs - mLastAnimationMs;
mLastAnimationMs = currentMs;
float deltaPx = deltaMs * mPixelsPerMs;
mScroll += deltaPx;
if (mScroll > mMaxScroll) {
mScroll = mMaxScroll;
mChoreographer.postFrameCallbackDelayed(mRestartCallback, MARQUEE_DELAY);
} else {
long delayTimeMs = 1000 / 60 + 2;
mChoreographer.postFrameCallbackDelayed(mTickCallback, delayTimeMs);
}
textView.invalidate();
}
}
修改之后的systace:
三、实验对比数据
通过实验对比数据可以看到,30fps能够降低cpu loading 30%以上,还是比较可观的。