diff options
5 files changed, 132 insertions, 7 deletions
diff --git a/libs/WindowManager/Shell/res/layout/tv_pip_menu_background.xml b/libs/WindowManager/Shell/res/layout/tv_pip_menu_background.xml index 5af40200d240..bd48ad2cef44 100644 --- a/libs/WindowManager/Shell/res/layout/tv_pip_menu_background.xml +++ b/libs/WindowManager/Shell/res/layout/tv_pip_menu_background.xml @@ -19,10 +19,11 @@ android:layout_width="match_parent" android:layout_height="match_parent"> <View + android:id="@+id/background_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="@dimen/pip_menu_outer_space_frame" android:background="@drawable/tv_pip_menu_background" - android:elevation="@dimen/pip_menu_elevation"/> + android:elevation="@dimen/pip_menu_elevation_no_menu"/> </FrameLayout> diff --git a/libs/WindowManager/Shell/res/values-tvdpi/dimen.xml b/libs/WindowManager/Shell/res/values-tvdpi/dimen.xml index 0b61d7a85d9e..adbf65648dd1 100644 --- a/libs/WindowManager/Shell/res/values-tvdpi/dimen.xml +++ b/libs/WindowManager/Shell/res/values-tvdpi/dimen.xml @@ -36,7 +36,9 @@ <dimen name="pip_menu_arrow_size">24dp</dimen> <dimen name="pip_menu_arrow_elevation">5dp</dimen> - <dimen name="pip_menu_elevation">1dp</dimen> + <dimen name="pip_menu_elevation_no_menu">1dp</dimen> + <dimen name="pip_menu_elevation_move_menu">7dp</dimen> + <dimen name="pip_menu_elevation_all_actions_menu">4dp</dimen> <dimen name="pip_menu_edu_text_view_height">24dp</dimen> <dimen name="pip_menu_edu_text_home_icon">9sp</dimen> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBackgroundView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBackgroundView.java new file mode 100644 index 000000000000..0221db836dda --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBackgroundView.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.pip.tv; + +import static com.android.wm.shell.pip.tv.TvPipMenuController.MODE_ALL_ACTIONS_MENU; +import static com.android.wm.shell.pip.tv.TvPipMenuController.MODE_MOVE_MENU; +import static com.android.wm.shell.pip.tv.TvPipMenuController.MODE_NO_MENU; + +import android.content.Context; +import android.content.res.Resources; +import android.view.View; +import android.view.animation.Interpolator; +import android.widget.FrameLayout; + +import androidx.annotation.NonNull; + +import com.android.internal.protolog.common.ProtoLog; +import com.android.wm.shell.R; +import com.android.wm.shell.protolog.ShellProtoLogGroup; + +/** + * This view is part of the Tv PiP menu. It is drawn behind the PiP surface and serves as a + * background behind the PiP content. If the PiP content is translucent, this view is visible + * behind it. + * It is also used to draw the shadow behind the Tv PiP menu. The shadow intensity is determined + * by the menu mode that the Tv PiP menu is in. See {@link TvPipMenuController.TvPipMenuMode}. + */ +class TvPipBackgroundView extends FrameLayout { + private static final String TAG = "TvPipBackgroundView"; + + private final View mBackgroundView; + private final int mElevationNoMenu; + private final int mElevationMoveMenu; + private final int mElevationAllActionsMenu; + private final int mPipMenuFadeAnimationDuration; + + private @TvPipMenuController.TvPipMenuMode int mCurrentMenuMode = MODE_NO_MENU; + + TvPipBackgroundView(@NonNull Context context) { + super(context, null, 0, 0); + inflate(context, R.layout.tv_pip_menu_background, this); + + mBackgroundView = findViewById(R.id.background_view); + + final Resources res = mContext.getResources(); + mElevationNoMenu = res.getDimensionPixelSize(R.dimen.pip_menu_elevation_no_menu); + mElevationMoveMenu = res.getDimensionPixelSize(R.dimen.pip_menu_elevation_move_menu); + mElevationAllActionsMenu = + res.getDimensionPixelSize(R.dimen.pip_menu_elevation_all_actions_menu); + mPipMenuFadeAnimationDuration = + res.getInteger(R.integer.tv_window_menu_fade_animation_duration); + } + + void transitionToMenuMode(@TvPipMenuController.TvPipMenuMode int pipMenuMode) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: transitionToMenuMode(), old menu mode = %s, new menu mode = %s", + TAG, TvPipMenuController.getMenuModeString(mCurrentMenuMode), + TvPipMenuController.getMenuModeString(pipMenuMode)); + + if (mCurrentMenuMode == pipMenuMode) return; + + int elevation = mElevationNoMenu; + Interpolator interpolator = TvPipInterpolators.ENTER; + switch(pipMenuMode) { + case MODE_NO_MENU: + elevation = mElevationNoMenu; + interpolator = TvPipInterpolators.EXIT; + break; + case MODE_MOVE_MENU: + elevation = mElevationMoveMenu; + break; + case MODE_ALL_ACTIONS_MENU: + elevation = mElevationAllActionsMenu; + if (mCurrentMenuMode == MODE_MOVE_MENU) { + interpolator = TvPipInterpolators.EXIT; + } + break; + default: + throw new IllegalArgumentException( + "Unknown TV PiP menu mode: " + pipMenuMode); + } + + mBackgroundView.animate() + .translationZ(elevation) + .setInterpolator(interpolator) + .setDuration(mPipMenuFadeAnimationDuration) + .start(); + + mCurrentMenuMode = pipMenuMode; + } + +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java index 2c6ca1af62a6..be1f800b9d2e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java @@ -27,7 +27,6 @@ import android.content.IntentFilter; import android.graphics.Insets; import android.graphics.Rect; import android.os.Handler; -import android.view.LayoutInflater; import android.view.SurfaceControl; import android.view.View; import android.view.ViewRootImpl; @@ -61,7 +60,7 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis private Delegate mDelegate; private SurfaceControl mLeash; private TvPipMenuView mPipMenuView; - private View mPipBackgroundView; + private TvPipBackgroundView mPipBackgroundView; private boolean mMenuIsFocused; @TvPipMenuMode @@ -178,12 +177,16 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis } private void attachPipBackgroundView() { - mPipBackgroundView = LayoutInflater.from(mContext) - .inflate(R.layout.tv_pip_menu_background, null); + mPipBackgroundView = createTvPipBackgroundView(); setUpViewSurfaceZOrder(mPipBackgroundView, -1); addPipMenuViewToSystemWindows(mPipBackgroundView, BACKGROUND_WINDOW_TITLE); } + @VisibleForTesting + TvPipBackgroundView createTvPipBackgroundView() { + return new TvPipBackgroundView(mContext); + } + private void setUpViewSurfaceZOrder(View v, int zOrderRelativeToPip) { v.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { @Override @@ -415,10 +418,11 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis } private void updateUiOnNewMenuModeRequest(boolean resetMenu) { - if (mPipMenuView == null) return; + if (mPipMenuView == null || mPipBackgroundView == null) return; mPipMenuView.setPipGravity(mTvPipBoundsState.getTvPipGravity()); mPipMenuView.transitionToMenuMode(mCurrentMenuMode, resetMenu); + mPipBackgroundView.transitionToMenuMode(mCurrentMenuMode); grantPipMenuFocus(mCurrentMenuMode != MODE_NO_MENU); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/TvPipMenuControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/TvPipMenuControllerTest.java index 7c6037c96360..3a08d32bc430 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/TvPipMenuControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/TvPipMenuControllerTest.java @@ -57,6 +57,8 @@ public class TvPipMenuControllerTest extends ShellTestCase { private TvPipActionsProvider mMockActionsProvider; @Mock private TvPipMenuView mMockTvPipMenuView; + @Mock + private TvPipBackgroundView mMockTvPipBackgroundView; private TvPipMenuController mTvPipMenuController; @@ -173,6 +175,7 @@ public class TvPipMenuControllerTest extends ShellTestCase { assertMenuIsInAllActionsMode(); verify(mMockDelegate, times(2)).onInMoveModeChanged(); verify(mMockTvPipMenuView).transitionToMenuMode(eq(MODE_ALL_ACTIONS_MENU), eq(false)); + verify(mMockTvPipBackgroundView, times(2)).transitionToMenuMode(eq(MODE_ALL_ACTIONS_MENU)); } @Test @@ -215,6 +218,7 @@ public class TvPipMenuControllerTest extends ShellTestCase { assertMenuIsInAllActionsMode(); verify(mMockDelegate, times(2)).onInMoveModeChanged(); verify(mMockTvPipMenuView).transitionToMenuMode(eq(MODE_ALL_ACTIONS_MENU), eq(false)); + verify(mMockTvPipBackgroundView, times(2)).transitionToMenuMode(eq(MODE_ALL_ACTIONS_MENU)); pressBackAndAssertMenuClosed(); } @@ -262,12 +266,14 @@ public class TvPipMenuControllerTest extends ShellTestCase { assertMenuIsInMoveMode(); verify(mMockDelegate).onInMoveModeChanged(); verify(mMockTvPipMenuView).transitionToMenuMode(eq(MODE_MOVE_MENU), eq(false)); + verify(mMockTvPipBackgroundView).transitionToMenuMode(eq(MODE_MOVE_MENU)); } private void showAndAssertAllActionsMenu() { mTvPipMenuController.showMenu(); assertMenuIsInAllActionsMode(); verify(mMockTvPipMenuView).transitionToMenuMode(eq(MODE_ALL_ACTIONS_MENU), eq(true)); + verify(mMockTvPipBackgroundView).transitionToMenuMode(eq(MODE_ALL_ACTIONS_MENU)); } private void closeMenuAndAssertMenuClosed() { @@ -284,6 +290,7 @@ public class TvPipMenuControllerTest extends ShellTestCase { assertMenuIsOpen(false); verify(mMockDelegate).onMenuClosed(); verify(mMockTvPipMenuView).transitionToMenuMode(eq(MODE_NO_MENU), eq(false)); + verify(mMockTvPipBackgroundView).transitionToMenuMode(eq(MODE_NO_MENU)); } private void assertMenuIsOpen(boolean open) { @@ -320,5 +327,10 @@ public class TvPipMenuControllerTest extends ShellTestCase { TvPipMenuView createTvPipMenuView() { return mMockTvPipMenuView; } + + @Override + TvPipBackgroundView createTvPipBackgroundView() { + return mMockTvPipBackgroundView; + } } } |