Merge "TV PiP: prevent unnecessary notification updates" into udc-dev
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipActionsProvider.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipActionsProvider.java
index fa62a73..3b44f10 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipActionsProvider.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipActionsProvider.java
@@ -186,16 +186,17 @@
     }
 
     @VisibleForTesting(visibility = PACKAGE)
-    public void onPipExpansionToggled(boolean expanded) {
+    public void updatePipExpansionState(boolean expanded) {
         ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                 "%s: onPipExpansionToggled, expanded: %b", TAG, expanded);
 
-        mExpandCollapseAction.update(
+        boolean changed = mExpandCollapseAction.update(
                 expanded ? R.string.pip_collapse : R.string.pip_expand,
                 expanded ? R.drawable.pip_ic_collapse : R.drawable.pip_ic_expand);
-
-        notifyActionsChanged(/* added= */ 0, /* updated= */ 1,
-                mActionsList.indexOf(mExpandCollapseAction));
+        if (changed) {
+            notifyActionsChanged(/* added= */ 0, /* updated= */ 1,
+                    mActionsList.indexOf(mExpandCollapseAction));
+        }
     }
 
     List<TvPipAction> getActionsList() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
index 2f74fb6..02eeb2a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
@@ -502,7 +502,7 @@
                 "%s: onPipTransition_Canceled(), state=%s", TAG, stateToName(mState));
         mTvPipMenuController.onPipTransitionFinished(
                 PipAnimationController.isInPipDirection(direction));
-        mTvPipActionsProvider.onPipExpansionToggled(mTvPipBoundsState.isTvPipExpanded());
+        mTvPipActionsProvider.updatePipExpansionState(mTvPipBoundsState.isTvPipExpanded());
     }
 
     @Override
@@ -515,7 +515,7 @@
                 "%s: onPipTransition_Finished(), state=%s, direction=%d",
                 TAG, stateToName(mState), direction);
         mTvPipMenuController.onPipTransitionFinished(enterPipTransition);
-        mTvPipActionsProvider.onPipExpansionToggled(mTvPipBoundsState.isTvPipExpanded());
+        mTvPipActionsProvider.updatePipExpansionState(mTvPipBoundsState.isTvPipExpanded());
     }
 
     private void updateExpansionState() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipSystemAction.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipSystemAction.java
index 4b82e4b..f6dabb7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipSystemAction.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipSystemAction.java
@@ -52,9 +52,14 @@
                 broadcastAction);
     }
 
-    void update(@StringRes int title, @DrawableRes int icon) {
+    /**
+     * @return true if the title and/or icon were changed.
+     */
+    boolean update(@StringRes int title, @DrawableRes int icon) {
+        boolean changed = title != mTitleResource || icon != mIconResource;
         mTitleResource = title;
         mIconResource = icon;
+        return changed;
     }
 
     void populateButton(@NonNull TvWindowMenuActionButton button, Handler mainHandler) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/TvPipActionProviderTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/TvPipActionProviderTest.java
index e5b61ed..02e6b8c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/TvPipActionProviderTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/TvPipActionProviderTest.java
@@ -158,19 +158,73 @@
                 new int[]{ACTION_FULLSCREEN, ACTION_CLOSE, ACTION_MOVE, ACTION_EXPAND_COLLAPSE}));
     }
 
-    @Test
-    public void expandedPip_toggleExpansion() {
-        assumeTelevision();
-        // PiP has expanded PiP enabled, but is in a collapsed state
+    private void check_expandedPip_updateExpansionState(
+            boolean startExpansion, boolean endExpansion, boolean updateExpected) {
+
         mActionsProvider.updateExpansionEnabled(true);
-        mActionsProvider.onPipExpansionToggled(/* expanded= */ false);
+        mActionsProvider.updatePipExpansionState(startExpansion);
 
         mActionsProvider.addListener(mMockListener);
-        mActionsProvider.onPipExpansionToggled(/* expanded= */ true);
+        mActionsProvider.updatePipExpansionState(endExpansion);
 
         assertTrue(checkActionsMatch(mActionsProvider.getActionsList(),
                 new int[]{ACTION_FULLSCREEN, ACTION_CLOSE, ACTION_MOVE, ACTION_EXPAND_COLLAPSE}));
-        verify(mMockListener).onActionsChanged(0, 1, 3);
+
+        if (updateExpected) {
+            verify(mMockListener).onActionsChanged(0, 1, 3);
+        } else {
+            verify(mMockListener, times(0))
+                    .onActionsChanged(anyInt(), anyInt(), anyInt());
+        }
+    }
+
+    @Test
+    public void expandedPip_toggleExpansion_collapse() {
+        assumeTelevision();
+        check_expandedPip_updateExpansionState(
+                /* startExpansion= */ true,
+                /* endExpansion= */ false,
+                /* updateExpected= */ true);
+    }
+
+    @Test
+    public void expandedPip_toggleExpansion_expand() {
+        assumeTelevision();
+        check_expandedPip_updateExpansionState(
+                /* startExpansion= */ false,
+                /* endExpansion= */ true,
+                /* updateExpected= */ true);
+    }
+
+    @Test
+    public void expandedPiP_updateExpansionState_alreadyExpanded() {
+        assumeTelevision();
+        check_expandedPip_updateExpansionState(
+                /* startExpansion= */ true,
+                /* endExpansion= */ true,
+                /* updateExpected= */ false);
+    }
+
+    @Test
+    public void expandedPiP_updateExpansionState_alreadyCollapsed() {
+        assumeTelevision();
+        check_expandedPip_updateExpansionState(
+                /* startExpansion= */ false,
+                /* endExpansion= */ false,
+                /* updateExpected= */ false);
+    }
+
+    @Test
+    public void regularPiP_updateExpansionState_setCollapsed() {
+        assumeTelevision();
+        mActionsProvider.updateExpansionEnabled(false);
+        mActionsProvider.updatePipExpansionState(/* expanded= */ false);
+
+        mActionsProvider.addListener(mMockListener);
+        mActionsProvider.updatePipExpansionState(/* expanded= */ false);
+
+        verify(mMockListener, times(0))
+                .onActionsChanged(anyInt(), anyInt(), anyInt());
     }
 
     @Test