车模卡片是 SurfaceView,当问题出现后滑动 Launcher activity 时 SurfaceView 不跟随移动,如下所示。
Activity 和 SurfaceView 在 SurfaceFlinger 中都是一个 Layer,SurfaceView 的父是 ViewRootImpl.mBoundsLayer,它的父是 ViewRootImpl。当左右滑动 Launcher 的时候,会把新的位置通过 Transaction 设置给 SurfaceView 对应的 Layer 来改变 SurfaceView 的位置。
直接原因是一次 Transaction 最后会调用 Layer::doTransaction()
函数,当 mLayerDetached
是 true
时,无法执行任何 Transaction,当然也无法改变位置。
uint32_t Layer::doTransaction(uint32_t flags) {
if (mLayerDetached) {
...
return flags;
}
...
State c = getCurrentState();
...
// Commit the transaction
commitTransaction(c);
...
return flags;
}
mLayerDetached
是在 Layer::detachChildren()
中设置的。
bool Layer::detachChildren() {
for (const sp<Layer>& child : mCurrentChildren) {
sp<Client> parentClient = mClientRef.promote();
sp<Client> client(child->mClientRef.promote());
if (client != nullptr && parentClient != client) {
child->mLayerDetached = true;
child->detachChildren();
child->removeRemoteSyncPoints();
}
}
return true;
}
// Detaches all child surfaces (and their children recursively)
// from their SurfaceControl.
// The child SurfaceControls will not throw exceptions or return errors,
// but transactions will have no effect.
// The child surfaces will continue to follow their parent surfaces,
// and remain eligible for rendering, but their relative state will be
// frozen. We use this in the WindowManager, in app shutdown/relaunch
// scenarios, where the app would otherwise clean up its child Surfaces.
// Sometimes the WindowManager needs to extend their lifetime slightly
// in order to perform an exit animation or prevent flicker.
Transaction& detachChildren(const sp<SurfaceControl>& sc);
注释说明,detachChildren()
之后可以继续绘制,但是关联关系(relative state)被冻结了,这里就包含与父的位置关系。在应用关闭或重启时,应用会清理子 Surface,这时 WindowManager 需要延长它们的生命周期来执行退出动画或避免闪烁。
基于注释猜测 detachChildren()
是为了在应用退出时暂时延长 Surface 生命周期,但最终是要销毁的。如果销毁了,下一次显示时会重新创建新 Surface,同时与父建立联系,这样就没有问题了。