重学WMS层级结构单手OneHanded Feature作用-源码分析
2、单手设置本质就是对上面所有FEATURE_ONE_HANDED的WindowContainer进行位置Y方向的偏移。1、收集所有的Feature为FEATURE_ONE_HANDED的WindowContainer,进行保存到集合。这里OneHandedTransitionAnimator又是由ofYOffset方法导致的构造。那么这里的mDisplayAreaTokenMap又是哪里设置的呢
背景:
aosp自带的单手模式一般如下:单手模式本身在层级结构树中是有单独的一个Feature:
结构树构建时候代码配置如下:
详细的原理及结合Winscope分析之前已经有分享过
重学WMS核心层级结构树之Feature作用-实战案例讲解
不过没有拿出具体源码分析,本文就来补充这块单手模式的源码分析,看看源码中这个Feature到底是如何影响单手模式的偏移的。
OneHanded位置偏移设置
位置Y方向偏移堆栈情况如下:
setPosition (tx=3358664428444 sc=OneHanded:32:32) x=0.0 y=1183.4318
java.lang.Throwable
at android.view.SurfaceControlRegistry.checkCallStackDebugging(SurfaceControlRegistry.java:330)
at android.view.SurfaceControl$Transaction.setPosition(SurfaceControl.java:3041)
at com.android.wm.shell.onehanded.OneHandedSurfaceTransactionHelper.translate(OneHandedSurfaceTransactionHelper.java:56)
at com.android.wm.shell.onehanded.OneHandedAnimationController$OneHandedTransitionAnimator$1.applySurfaceControlTransaction(OneHandedAnimationController.java:284)
at com.android.wm.shell.onehanded.OneHandedAnimationController$OneHandedTransitionAnimator.onAnimationUpdate(OneHandedAnimationController.java:188)
at android.animation.Animator$AnimatorCaller.lambda$static$4(Animator.java:855)
at android.animation.Animator$AnimatorCaller$$ExternalSyntheticLambda6.call(D8$$SyntheticClass:0)
at android.animation.Animator.callOnList(Animator.java:666)
at android.animation.ValueAnimator.animateValue(ValueAnimator.java:1645)
at android.animation.ValueAnimator.animateBasedOnTime(ValueAnimator.java:1405)
at android.animation.ValueAnimator.doAnimationFrame(ValueAnimator.java:1563)
at android.animation.AnimationHandler.doAnimationFrame(AnimationHandler.java:344)
at android.animation.AnimationHandler.-$$Nest$mdoAnimationFrame(Unknown Source:0)
at android.animation.AnimationHandler$1.doFrame(AnimationHandler.java:87)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1404)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1415)
at android.view.Choreographer.doCallbacks(Choreographer.java:1015)
at android.view.Choreographer.doFrame(Choreographer.java:941)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1389)
at android.os.Handler.handleCallback(Handler.java:959)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loopOnce(Looper.java:232)
at android.os.Looper.loop(Looper.java:317)
at android.os.HandlerThread.run(HandlerThread.java:85)
代码剖析
frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationController.java
那么看看这里的leash是哪里传递过来的
frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationController.java
@Override
public void onAnimationUpdate(ValueAnimator animation) {
final SurfaceControl.Transaction tx = newSurfaceControlTransaction();
mOneHandedAnimationCallbacks.forEach(
(callback) -> callback.onAnimationUpdate(tx, 0f, mCurrentValue)
);
applySurfaceControlTransaction(mLeash, tx, animation.getAnimatedFraction());
}
那么这里的mLeash又是哪来的呢?
这里OneHandedTransitionAnimator又是由ofYOffset方法导致的构造
而ofYOffset又是通过getAnimator方法获取的
frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
private void animateWindows(WindowContainerToken token, SurfaceControl leash, float fromPos,
float toPos, @OneHandedAnimationController.TransitionDirection int direction,
int durationMs) {
final OneHandedAnimationController.OneHandedTransitionAnimator animator =
mAnimationController.getAnimator(token, leash, fromPos, toPos,
mLastVisualDisplayBounds);
//省略
}
再看看animateWindows方法
frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
/**
* Offset the windows by a given offset on Y-axis, triggered also from screen rotation.
* Directly perform manipulation/offset on the leash.
*/
public void scheduleOffset(int xOffset, int yOffset) {
final float fromPos = mLastVisualOffset;
//省略
//这里会调用的mDisplayAreaTokenMap这个集合来遍历获取leash
mDisplayAreaTokenMap.forEach(
(token, leash) -> {
animateWindows(token, leash, fromPos, yOffset, direction,
mEnterExitAnimationDurationMs);
});
mLastVisualOffset = yOffset;
}
那么这里的mDisplayAreaTokenMap又是哪里设置的呢?
frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
@Override
public void onDisplayAreaAppeared(@NonNull DisplayAreaInfo displayAreaInfo,
@NonNull SurfaceControl leash) {
leash.setUnreleasedWarningCallSite(
"OneHandedSiaplyAreaOrganizer.onDisplayAreaAppeared");
mDisplayAreaTokenMap.put(displayAreaInfo.token, leash);
}
onDisplayAreaAppeared调用地方呢?可以看看如下registerOrganizer
@Override
public List<DisplayAreaAppearedInfo> registerOrganizer(int displayAreaFeature) {
final List<DisplayAreaAppearedInfo> displayAreaInfos =
super.registerOrganizer(displayAreaFeature);
for (int i = 0; i < displayAreaInfos.size(); i++) {
final DisplayAreaAppearedInfo info = displayAreaInfos.get(i);
onDisplayAreaAppeared(info.getDisplayAreaInfo(), info.getLeash());
}
mIsReady = true;
updateDisplayBounds();
return displayAreaInfos;
}
这里的调用是
frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
private void updateOneHandedEnabled() {
//省略
if (mDisplayAreaOrganizer.getDisplayAreaTokenMap().isEmpty()) {
mDisplayAreaOrganizer.registerOrganizer(
OneHandedDisplayAreaOrganizer.FEATURE_ONE_HANDED);
}
}
注意在这里时候registerOrganizer时候有传递FEATURE_ONE_HANDED这个参数
获取OneHanded对应的WindowContainer
frameworks/base/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
@Override
public ParceledListSlice<DisplayAreaAppearedInfo> registerOrganizer(
IDisplayAreaOrganizer organizer, int feature) {
enforceTaskPermission("registerOrganizer()");
try {
synchronized (mGlobalLock) {
if (mOrganizersByFeatureIds.get(feature) != null) {
mOrganizersByFeatureIds.remove(feature).destroy();
}
final DisplayAreaOrganizerState state = new DisplayAreaOrganizerState(organizer,
feature);
final List<DisplayAreaAppearedInfo> displayAreaInfos = new ArrayList<>();
mService.mRootWindowContainer.forAllDisplays(dc -> {
dc.forAllDisplayAreas((da) -> {
//遍历出所有为FEATURE_ONE_HANDED的da
if (da.mFeatureId != feature) return;
displayAreaInfos.add(organizeDisplayArea(organizer, da,
"DisplayAreaOrganizerController.registerOrganizer"));
});
});
mOrganizersByFeatureIds.put(feature, state);
return new ParceledListSlice<>(displayAreaInfos);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
到此就OneHanded相关Feature剖析讲解完成。
主要流程分为如下两个:
1、收集所有的Feature为FEATURE_ONE_HANDED的WindowContainer,进行保存到集合
2、单手设置本质就是对上面所有FEATURE_ONE_HANDED的WindowContainer进行位置Y方向的偏移
更多推荐
所有评论(0)