PipMenuView click on the Expand button
Corresponding to the free video tutorial explanation of station b:
https://www.bilibili.com/video/BV1wj411o7A9/
hideMenu:431, PipMenuView (com.android.wm.shell.pip.phone)
expandPip:558, PipMenuView (com.android.wm.shell.pip.phone)
lambda$new$2:198, PipMenuView (com.android.wm.shell.pip.phone)
$r8$lambda$TVGiqqzKEZGnpVVCecTNWyek8VQ:-1, PipMenuView (com.android.wm.shell.pip.phone)
onClick:-1, PipMenuView$$ExternalSyntheticLambda3 (com.android.wm.shell.pip.phone)
performClick:7506, View (android.view)
performClickInternal:7483, View (android.view)
-$$Nest$mperformClickInternal:-1, View (android.view)
run:29335, View$PerformClick (android.view)
handleCallback:942, Handler (android.os)
dispatchMessage:99, Handler (android.os)
loopOnce:201, Looper (android.os)
loop:288, Looper (android.os)
main:7897, ActivityThread (android.app)
invoke:-1, Method (java.lang.reflect)
run:548, RuntimeInit$MethodAndArgsCaller (com.android.internal.os)
main:937, ZygoteInit (com.android.internal.os)
It is relatively simple to find here, the function is to respond to onClick, and then start hideMenu, which will start an animation to hide the
core code as follows:
frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView .java
void hideMenu(final Runnable animationFinishedRunnable, boolean notifyMenuVisibility,
boolean resize, @AnimationType int animationType) {
if (mMenuState != MENU_STATE_NONE) {
cancelDelayedHide();
if (notifyMenuVisibility) {
notifyMenuStateChangeStart(MENU_STATE_NONE, resize, null);
}
mMenuContainerAnimator = new AnimatorSet();
ObjectAnimator menuAnim = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
mMenuContainer.getAlpha(), 0f);
menuAnim.addUpdateListener(mMenuBgUpdateListener);
ObjectAnimator settingsAnim = ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA,
mSettingsButton.getAlpha(), 0f);
ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA,
mDismissButton.getAlpha(), 0f);
ObjectAnimator enterSplitAnim = ObjectAnimator.ofFloat(mEnterSplitButton, View.ALPHA,
mEnterSplitButton.getAlpha(), 0f);
mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim,
enterSplitAnim);
mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_OUT);
mMenuContainerAnimator.setDuration(getFadeOutDuration(animationType));
mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
setVisibility(GONE);
if (notifyMenuVisibility) {
notifyMenuStateChangeFinish(MENU_STATE_NONE);
}
if (animationFinishedRunnable != null) {
animationFinishedRunnable.run();
}
}
});
mMenuContainerAnimator.start();
}
}
After the PipMenuView animation ends, set the corresponding WindowMode and bounds, and perform an animation zoom-in action on the task of the small window
05-25 17:10:34.142 744 744 I test22 : WindowContainerTransaction setBounds bounds = Rect(0, 0 - 1440, 2960)
05-25 17:10:34.143 744 744 I test22 : applySyncTransaction
05-25 17:10:34.143 744 744 I test22 : java.lang.Exception
05-25 17:10:34.143 744 744 I test22 : at android.window.WindowOrganizer.applySyncTransaction(WindowOrganizer.java:81)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.common.SyncTransactionQueue$SyncCallback.send(SyncTransactionQueue.java:197)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.common.SyncTransactionQueue.queue(SyncTransactionQueue.java:80)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.pip.PipTaskOrganizer.exitPip(PipTaskOrganizer.java:471)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.pip.phone.PipMotionHelper.expandLeavePip(PipMotionHelper.java:364)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.pip.phone.PipMotionHelper.expandLeavePip(PipMotionHelper.java:342)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.pip.phone.PipTouchHandler$PipMenuListener.onPipExpand(PipTouchHandler.java:144)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.pip.phone.PhonePipMenuController$$ExternalSyntheticLambda4.accept(Unknown Source:2)
05-25 17:10:34.143 744 744 I test22 : at java.util.ArrayList.forEach(ArrayList.java:1262)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.pip.phone.PhonePipMenuController.onPipExpand(PhonePipMenuController.java:472)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.pip.phone.PipMenuView$$ExternalSyntheticLambda10.run(Unknown Source:2)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.pip.phone.PipMenuView$4.onAnimationEnd(PipMenuView.java:427)
05-25 17:10:34.143 744 744 I test22 : at android.animation.Animator$AnimatorListener.onAnimationEnd(Animator.java:600)
05-25 17:10:34.143 744 744 I test22 : at android.animation.AnimatorSet.endAnimation(AnimatorSet.java:1301)
05-25 17:10:34.143 744 744 I test22 : at android.animation.AnimatorSet.doAnimationFrame(AnimatorSet.java:1086)
05-25 17:10:34.143 744 744 I test22 : at android.animation.AnimationHandler.doAnimationFrame(AnimationHandler.java:307)
05-25 17:10:34.143 744 744 I test22 : at android.animation.AnimationHandler.-$$Nest$mdoAnimationFrame(Unknown Source:0)
05-25 17:10:34.143 744 744 I test22 : at android.animation.AnimationHandler$1.doFrame(AnimationHandler.java:86)
05-25 17:10:34.143 744 744 I test22 : at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1229)
05-25 17:10:34.143 744 744 I test22 : at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1239)
05-25 17:10:34.143 744 744 I test22 : at android.view.Choreographer.doCallbacks(Choreographer.java:899)
05-25 17:10:34.143 744 744 I test22 : at android.view.Choreographer.doFrame(Choreographer.java:827)
05-25 17:10:34.143 744 744 I test22 : at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1214)
05-25 17:10:34.143 744 744 I test22 : at android.os.Handler.handleCallback(Handler.java:942)
05-25 17:10:34.143 744 744 I test22 : at android.os.Handler.dispatchMessage(Handler.java:99)
05-25 17:10:34.143 744 744 I test22 : at android.os.Looper.loopOnce(Looper.java:201)
05-25 17:10:34.143 744 744 I test22 : at android.os.Looper.loop(Looper.java:288)
05-25 17:10:34.143 744 744 I test22 : at android.app.ActivityThread.main(ActivityThread.java:7897)
05-25 17:10:34.143 744 744 I test22 : at java.lang.reflect.Method.invoke(Native Method)
05-25 17:10:34.143 744 744 I test22 : at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
05-25 17:10:34.143 744 744 I test22 : at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:937)
The core code is as follows:
public void exitPip(int animationDurationMs, boolean requestEnterSplit) {
//省略
final Rect destinationBounds = getExitDestinationBounds();//获取目标大小,这里推出pip应该到全屏,所以destinationBounds为全屏
final int direction = syncWithSplitScreenBounds(destinationBounds, requestEnterSplit)
? TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN
: TRANSITION_DIRECTION_LEAVE_PIP;
if (Transitions.ENABLE_SHELL_TRANSITIONS && direction ==
//省略
} else {
final SurfaceControl.Transaction tx =
mSurfaceControlTransactionFactory.getTransaction();
mSurfaceTransactionHelper.scale(tx, mLeash, destinationBounds,
mPipBoundsState.getBounds());
tx.setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height());
// We set to fullscreen here for now, but later it will be set to UNDEFINED for
// the proper windowing mode to take place. See #applyWindowingModeChangeOnExit.
wct.setActivityWindowingMode(mToken, WINDOWING_MODE_FULLSCREEN); //设置windowmode为full
wct.setBounds(mToken, destinationBounds);//设置目标大小为全屏了
wct.setBoundsChangeTransaction(mToken, tx);
}
mPipTransitionState.setTransitionState(PipTransitionState.EXITING_PIP);
mSyncTransactionQueue.queue(wct);
mSyncTransactionQueue.runInSync(t -> {
final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect(
mPictureInPictureParams, destinationBounds);
//进行对应的pip到全屏的task窗口动画开启
final PipAnimationController.PipTransitionAnimator<?> animator =
animateResizePip(mPipBoundsState.getBounds(), destinationBounds, sourceHintRect,direction, animationDurationMs, 0 /* startingAngle */);
});
}