summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/WindowManager/Shell/proto/wm_shell_transition_trace.proto3
-rw-r--r--libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml2
-rw-r--r--libs/WindowManager/Shell/res/values-et/strings.xml2
-rw-r--r--libs/WindowManager/Shell/res/values-fr/strings.xml4
-rw-r--r--libs/WindowManager/Shell/res/values-hi/strings.xml2
-rw-r--r--libs/WindowManager/Shell/res/values-in/strings.xml2
-rw-r--r--libs/WindowManager/Shell/res/values-sr/strings.xml2
-rw-r--r--libs/WindowManager/Shell/res/values-zh-rHK/strings.xml2
-rw-r--r--libs/WindowManager/Shell/res/values/colors.xml2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java48
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java34
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java25
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BubbleInfo.java17
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java34
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java30
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/LetterboxEduWindowManager.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/ReachabilityEduWindowManager.java14
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java26
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt28
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java93
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/Tracer.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/util/KtProtoLog.kt74
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java41
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java17
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/bubbles/BubbleInfoTest.kt49
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java10
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/ReachabilityEduWindowManagerTest.java67
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/RestartDialogWindowManagerTest.java97
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java4
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java3
-rw-r--r--libs/hwui/renderthread/HintSessionWrapper.cpp41
-rw-r--r--libs/hwui/renderthread/HintSessionWrapper.h3
-rw-r--r--libs/hwui/renderthread/VulkanSurface.cpp12
-rw-r--r--libs/hwui/renderthread/VulkanSurface.h1
-rw-r--r--libs/input/PointerController.cpp5
-rw-r--r--libs/input/PointerController.h4
-rw-r--r--libs/input/tests/PointerController_test.cpp2
46 files changed, 659 insertions, 219 deletions
diff --git a/libs/WindowManager/Shell/proto/wm_shell_transition_trace.proto b/libs/WindowManager/Shell/proto/wm_shell_transition_trace.proto
index 6e0110193a05..c82a70c9a44e 100644
--- a/libs/WindowManager/Shell/proto/wm_shell_transition_trace.proto
+++ b/libs/WindowManager/Shell/proto/wm_shell_transition_trace.proto
@@ -37,6 +37,9 @@ message WmShellTransitionTraceProto {
required fixed64 magic_number = 1;
repeated Transition transitions = 2;
repeated HandlerMapping handlerMappings = 3;
+ /* offset between real-time clock and elapsed time clock in nanoseconds.
+ Calculated as: 1000000 * System.currentTimeMillis() - SystemClock.elapsedRealtimeNanos() */
+ optional fixed64 real_to_elapsed_time_offset_nanos = 4;
}
message Transition {
diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
index 8de9d11def2b..c415c868ac04 100644
--- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
@@ -89,7 +89,7 @@
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Važi"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Proširite za još informacija."</string>
<string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Želite li da restartujete radi boljeg prikaza?"</string>
- <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Možete da restartujete aplikaciju da bi izgledala bolje na ekranu, s tim što možete da izgubite ono što ste uradili ili nesačuvane promene, ako ih ima"</string>
+ <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Možete da restartujete aplikaciju da bi izgledala bolje na ekranu, ali možete da izgubite napredak ili nesačuvane promene"</string>
<string name="letterbox_restart_cancel" msgid="1342209132692537805">"Otkaži"</string>
<string name="letterbox_restart_restart" msgid="8529976234412442973">"Restartuj"</string>
<string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Ne prikazuj ponovo"</string>
diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml
index 90feff32cc2b..fb23d11ef74a 100644
--- a/libs/WindowManager/Shell/res/values-et/strings.xml
+++ b/libs/WindowManager/Shell/res/values-et/strings.xml
@@ -89,7 +89,7 @@
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Selge"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Laiendage lisateabe saamiseks."</string>
<string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Kas taaskäivitada parema vaate saavutamiseks?"</string>
- <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Saate rakenduse taaskäivitada, et see näeks ekraanikuval parem välja, kuid võite kaotada edenemise või salvestamata muudatused"</string>
+ <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Saate rakenduse taaskäivitada, et see näeks ekraanikuval parem välja, kuid võite kaotada edenemise või salvestamata muudatused."</string>
<string name="letterbox_restart_cancel" msgid="1342209132692537805">"Tühista"</string>
<string name="letterbox_restart_restart" msgid="8529976234412442973">"Taaskäivita"</string>
<string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Ära kuva uuesti"</string>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml
index da5b5c9bfeba..5fb91f7b6948 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings.xml
@@ -79,7 +79,7 @@
<string name="notification_bubble_title" msgid="6082910224488253378">"Bulle"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Gérer"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bulle fermée."</string>
- <string name="restart_button_description" msgid="6712141648865547958">"Appuyez pour redémarrer cette appli et avoir une meilleure vue."</string>
+ <string name="restart_button_description" msgid="6712141648865547958">"Pour un meilleur affichage, appuyez pour redémarrer cette appli."</string>
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problèmes d\'appareil photo ?\nAppuyez pour réajuster"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problème non résolu ?\nAppuyez pour rétablir"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Aucun problème d\'appareil photo ? Appuyez pour ignorer."</string>
@@ -89,7 +89,7 @@
<string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Développez pour obtenir plus d\'informations"</string>
<string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Redémarrer pour améliorer l\'affichage ?"</string>
- <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Vous pouvez redémarrer l\'appli pour en améliorer son aspect sur votre écran, mais vous risquez de perdre votre progression ou les modifications non enregistrées"</string>
+ <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Vous pouvez redémarrer l\'appli pour un meilleur rendu sur votre écran, mais il se peut que vous perdiez votre progression ou les modifications non enregistrées"</string>
<string name="letterbox_restart_cancel" msgid="1342209132692537805">"Annuler"</string>
<string name="letterbox_restart_restart" msgid="8529976234412442973">"Redémarrer"</string>
<string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Ne plus afficher"</string>
diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml
index fb5040b36a89..b0b0e9c6f5bc 100644
--- a/libs/WindowManager/Shell/res/values-hi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hi/strings.xml
@@ -89,7 +89,7 @@
<string name="letterbox_education_got_it" msgid="4057634570866051177">"ठीक है"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ज़्यादा जानकारी के लिए बड़ा करें."</string>
<string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"बेहतर व्यू पाने के लिए ऐप्लिकेशन को रीस्टार्ट करना है?"</string>
- <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"स्क्रीन पर ऐप्लिकेशन का बेहतर व्यू पाने के लिए उसे रीस्टार्ट करें. हालांकि, आपने जो बदलाव सेव नहीं किए हैं या अब तक जो काम किए हैं उनका डेटा, ऐप्लिकेशन रीस्टार्ट करने पर मिट सकता है"</string>
+ <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"स्क्रीन पर ऐप्लिकेशन का बेहतर व्यू पाने के लिए उसे रीस्टार्ट करें. हालांकि, इससे अब तक किया गया काम और सेव न किए गए बदलाव मिट सकते हैं"</string>
<string name="letterbox_restart_cancel" msgid="1342209132692537805">"रद्द करें"</string>
<string name="letterbox_restart_restart" msgid="8529976234412442973">"रीस्टार्ट करें"</string>
<string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"फिर से न दिखाएं"</string>
diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml
index 5747deb405ab..3f6d9c551aa6 100644
--- a/libs/WindowManager/Shell/res/values-in/strings.xml
+++ b/libs/WindowManager/Shell/res/values-in/strings.xml
@@ -88,7 +88,7 @@
<string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Ketuk dua kali di luar aplikasi untuk mengubah posisinya"</string>
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Oke"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Luaskan untuk melihat informasi selengkapnya."</string>
- <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Mulai ulang untuk tampilan yang lebih baik?"</string>
+ <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Mulai ulang untuk melihat tampilan yang lebih baik?"</string>
<string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Anda dapat memulai ulang aplikasi agar terlihat lebih baik di layar, tetapi Anda mungkin kehilangan progres atau perubahan yang belum disimpan"</string>
<string name="letterbox_restart_cancel" msgid="1342209132692537805">"Batal"</string>
<string name="letterbox_restart_restart" msgid="8529976234412442973">"Mulai ulang"</string>
diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml
index 307efc9d6a2e..85798cf9f784 100644
--- a/libs/WindowManager/Shell/res/values-sr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sr/strings.xml
@@ -89,7 +89,7 @@
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Важи"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Проширите за још информација."</string>
<string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Желите ли да рестартујете ради бољег приказа?"</string>
- <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Можете да рестартујете апликацију да би изгледала боље на екрану, с тим што можете да изгубите оно што сте урадили или несачуване промене, ако их има"</string>
+ <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Можете да рестартујете апликацију да би изгледала боље на екрану, али можете да изгубите напредак или несачуване промене"</string>
<string name="letterbox_restart_cancel" msgid="1342209132692537805">"Откажи"</string>
<string name="letterbox_restart_restart" msgid="8529976234412442973">"Рестартуј"</string>
<string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Не приказуј поново"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
index 021ec46072f8..3d33ecaccc38 100644
--- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
@@ -88,7 +88,7 @@
<string name="letterbox_education_reposition_text" msgid="4589957299813220661">"在應用程式外輕按兩下即可調整位置"</string>
<string name="letterbox_education_got_it" msgid="4057634570866051177">"知道了"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"展開即可查看詳情。"</string>
- <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"要重新啟動改善檢視畫面嗎?"</string>
+ <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"要重新啟動以改善檢視畫面嗎?"</string>
<string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"你可重新啟動應用程式,讓系統更新檢視畫面;但系統可能不會儲存目前進度及你作出的任何變更"</string>
<string name="letterbox_restart_cancel" msgid="1342209132692537805">"取消"</string>
<string name="letterbox_restart_restart" msgid="8529976234412442973">"重新啟動"</string>
diff --git a/libs/WindowManager/Shell/res/values/colors.xml b/libs/WindowManager/Shell/res/values/colors.xml
index 54a8f33fd679..33861485d6f7 100644
--- a/libs/WindowManager/Shell/res/values/colors.xml
+++ b/libs/WindowManager/Shell/res/values/colors.xml
@@ -67,4 +67,6 @@
<color name="desktop_mode_caption_menu_text_color">#191C1D</color>
<color name="desktop_mode_caption_menu_buttons_color_inactive">#191C1D</color>
<color name="desktop_mode_caption_menu_buttons_color_active">#00677E</color>
+ <color name="desktop_mode_resize_veil_light">#EFF1F2</color>
+ <color name="desktop_mode_resize_veil_dark">#1C1C17</color>
</resources>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java
index 18615f7e353a..39f861de1ba0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java
@@ -19,8 +19,6 @@ package com.android.wm.shell.activityembedding;
import static android.graphics.Matrix.MTRANS_X;
import static android.graphics.Matrix.MTRANS_Y;
-import static com.android.wm.shell.activityembedding.ActivityEmbeddingAnimationRunner.shouldUseSnapshotAnimationForClosingChange;
-
import android.annotation.CallSuper;
import android.graphics.Point;
import android.graphics.Rect;
@@ -62,7 +60,7 @@ class ActivityEmbeddingAnimationAdapter {
private final Rect mContentBounds = new Rect();
/** Offset relative to the window parent surface for {@link #mContentBounds}. */
@NonNull
- private final Point mContentRelOffset = new Point();
+ final Point mContentRelOffset = new Point();
@NonNull
final Transformation mTransformation = new Transformation();
@@ -75,8 +73,8 @@ class ActivityEmbeddingAnimationAdapter {
private int mOverrideLayer = LAYER_NO_OVERRIDE;
ActivityEmbeddingAnimationAdapter(@NonNull Animation animation,
- @NonNull TransitionInfo.Change change) {
- this(animation, change, change.getLeash(), change.getEndAbsBounds());
+ @NonNull TransitionInfo.Change change, @NonNull TransitionInfo.Root root) {
+ this(animation, change, change.getLeash(), change.getEndAbsBounds(), root);
}
/**
@@ -87,32 +85,34 @@ class ActivityEmbeddingAnimationAdapter {
*/
ActivityEmbeddingAnimationAdapter(@NonNull Animation animation,
@NonNull TransitionInfo.Change change, @NonNull SurfaceControl leash,
- @NonNull Rect wholeAnimationBounds) {
+ @NonNull Rect wholeAnimationBounds, @NonNull TransitionInfo.Root root) {
mAnimation = animation;
mChange = change;
mLeash = leash;
mWholeAnimationBounds.set(wholeAnimationBounds);
+
+ final Rect startBounds = change.getStartAbsBounds();
+ final Rect endBounds = change.getEndAbsBounds();
+ if (change.getParent() != null) {
+ mContentRelOffset.set(change.getEndRelOffset());
+ } else {
+ // Change leash has been reparented to the root if its parent is not in the transition.
+ // Because it is reparented to the root, the actual offset should be its relative
+ // position to the root instead. See Transitions#setupAnimHierarchy.
+ final Point rootOffset = root.getOffset();
+ mContentRelOffset.set(endBounds.left - rootOffset.x, endBounds.top - rootOffset.y);
+ }
+
if (TransitionUtil.isClosingType(change.getMode())) {
// When it is closing, we want to show the content at the start position in case the
// window is resizing as well. For example, when the activities is changing from split
// to stack, the bottom TaskFragment will be resized to fullscreen when hiding.
- final Rect startBounds = change.getStartAbsBounds();
- final Rect endBounds = change.getEndAbsBounds();
mContentBounds.set(startBounds);
- // Put the transition to the top left for snapshot animation.
- if (shouldUseSnapshotAnimationForClosingChange(mChange)) {
- // TODO(b/275034335): Fix an issue that black hole when closing the right container
- // in bounds change transition.
- mContentRelOffset.set(0, 0);
- } else {
- mContentRelOffset.set(change.getEndRelOffset());
- mContentRelOffset.offset(
+ mContentRelOffset.offset(
startBounds.left - endBounds.left,
startBounds.top - endBounds.top);
- }
} else {
mContentBounds.set(change.getEndAbsBounds());
- mContentRelOffset.set(change.getEndRelOffset());
}
}
@@ -192,8 +192,8 @@ class ActivityEmbeddingAnimationAdapter {
static class SnapshotAdapter extends ActivityEmbeddingAnimationAdapter {
SnapshotAdapter(@NonNull Animation animation, @NonNull TransitionInfo.Change change,
- @NonNull SurfaceControl snapshotLeash) {
- super(animation, change, snapshotLeash, change.getEndAbsBounds());
+ @NonNull SurfaceControl snapshotLeash, @NonNull TransitionInfo.Root root) {
+ super(animation, change, snapshotLeash, change.getEndAbsBounds(), root);
}
@Override
@@ -219,14 +219,14 @@ class ActivityEmbeddingAnimationAdapter {
*/
static class BoundsChangeAdapter extends ActivityEmbeddingAnimationAdapter {
- BoundsChangeAdapter(@NonNull Animation animation, @NonNull TransitionInfo.Change change) {
- super(animation, change);
+ BoundsChangeAdapter(@NonNull Animation animation, @NonNull TransitionInfo.Change change,
+ @NonNull TransitionInfo.Root root) {
+ super(animation, change, root);
}
@Override
void onAnimationUpdateInner(@NonNull SurfaceControl.Transaction t) {
- final Point offset = mChange.getEndRelOffset();
- mTransformation.getMatrix().postTranslate(offset.x, offset.y);
+ mTransformation.getMatrix().postTranslate(mContentRelOffset.x, mContentRelOffset.y);
t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix);
t.setAlpha(mLeash, mTransformation.getAlpha());
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
index ab7c7d8ae6c8..59f120deeb94 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
@@ -250,7 +250,8 @@ class ActivityEmbeddingAnimationRunner {
SurfaceControl screenshot = getOrCreateScreenshot(change, change, startTransaction);
if (screenshot != null) {
final SnapshotAdapter snapshotAdapter = new SnapshotAdapter(
- createShowSnapshotForClosingAnimation(), change, screenshot);
+ createShowSnapshotForClosingAnimation(), change, screenshot,
+ TransitionUtil.getRootFor(change, info));
if (!isOpening) {
snapshotAdapter.overrideLayer(offsetLayer++);
}
@@ -338,7 +339,7 @@ class ActivityEmbeddingAnimationRunner {
@NonNull AnimationProvider animationProvider, @NonNull Rect wholeAnimationBounds) {
final Animation animation = animationProvider.get(info, change, wholeAnimationBounds);
return new ActivityEmbeddingAnimationAdapter(animation, change, change.getLeash(),
- wholeAnimationBounds);
+ wholeAnimationBounds, TransitionUtil.getRootFor(change, info));
}
@NonNull
@@ -387,6 +388,12 @@ class ActivityEmbeddingAnimationRunner {
// size.
parentBounds.union(boundsAnimationChange.getStartAbsBounds());
parentBounds.union(boundsAnimationChange.getEndAbsBounds());
+ if (boundsAnimationChange != change) {
+ // Union the change starting bounds in case the activity is resized and reparented
+ // to a TaskFragment. In that case, the TaskFragment may not cover the activity's
+ // starting bounds.
+ parentBounds.union(change.getStartAbsBounds());
+ }
// There are two animations in the array. The first one is for the start leash
// (snapshot), and the second one is for the end leash (TaskFragment).
@@ -401,17 +408,18 @@ class ActivityEmbeddingAnimationRunner {
// boundsAnimationChange.
final SurfaceControl screenshotLeash = getOrCreateScreenshot(change,
boundsAnimationChange, startTransaction);
+ final TransitionInfo.Root root = TransitionUtil.getRootFor(change, info);
if (screenshotLeash != null) {
// Adapter for the starting screenshot leash.
// The screenshot leash will be removed in SnapshotAdapter#onAnimationEnd
adapters.add(new ActivityEmbeddingAnimationAdapter.SnapshotAdapter(
- animations[0], change, screenshotLeash));
+ animations[0], change, screenshotLeash, root));
} else {
Log.e(TAG, "Failed to take screenshot for change=" + change);
}
// Adapter for the ending bounds changed leash.
adapters.add(new ActivityEmbeddingAnimationAdapter.BoundsChangeAdapter(
- animations[1], boundsAnimationChange));
+ animations[1], boundsAnimationChange, root));
}
if (parentBounds.isEmpty()) {
@@ -443,7 +451,8 @@ class ActivityEmbeddingAnimationRunner {
animation = mAnimationSpec.createChangeBoundsOpenAnimation(change, parentBounds);
shouldShouldBackgroundColor = false;
}
- adapters.add(new ActivityEmbeddingAnimationAdapter(animation, change));
+ adapters.add(new ActivityEmbeddingAnimationAdapter(animation, change,
+ TransitionUtil.getRootFor(change, info)));
}
if (shouldShouldBackgroundColor && changeAnimation != null) {
@@ -534,8 +543,19 @@ class ActivityEmbeddingAnimationRunner {
@NonNull SurfaceControl.Transaction startTransaction) {
for (TransitionInfo.Change change : info.getChanges()) {
final SurfaceControl leash = change.getLeash();
- startTransaction.setPosition(leash,
- change.getEndRelOffset().x, change.getEndRelOffset().y);
+ if (change.getParent() != null) {
+ startTransaction.setPosition(leash,
+ change.getEndRelOffset().x, change.getEndRelOffset().y);
+ } else {
+ // Change leash has been reparented to the root if its parent is not in the
+ // transition.
+ // Because it is reparented to the root, the actual offset should be its relative
+ // position to the root instead. See Transitions#setupAnimHierarchy.
+ final TransitionInfo.Root root = TransitionUtil.getRootFor(change, info);
+ startTransaction.setPosition(leash,
+ change.getEndAbsBounds().left - root.getOffset().x,
+ change.getEndAbsBounds().top - root.getOffset().y);
+ }
startTransaction.setWindowCrop(leash,
change.getEndAbsBounds().width(), change.getEndAbsBounds().height());
if (change.getMode() == TRANSIT_CLOSE) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index 24fd86b45df4..e396ba13f154 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -300,7 +300,8 @@ public class Bubble implements BubbleViewProvider {
getShortcutId(),
getIcon(),
getUser().getIdentifier(),
- getPackageName());
+ getPackageName(),
+ getTitle());
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index 6c482c831152..adc0c9c4322a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -27,6 +27,7 @@ import static com.android.wm.shell.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_EXPAND
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.wm.shell.bubbles.BubblePositioner.MAX_HEIGHT;
+import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
import android.annotation.NonNull;
import android.annotation.SuppressLint;
@@ -214,9 +215,6 @@ public class BubbleExpandedView extends LinearLayout {
ActivityOptions options = ActivityOptions.makeCustomAnimation(getContext(),
0 /* enterResId */, 0 /* exitResId */);
- Rect launchBounds = new Rect();
- mTaskView.getBoundsOnScreen(launchBounds);
-
// TODO: I notice inconsistencies in lifecycle
// Post to keep the lifecycle normal
post(() -> {
@@ -225,6 +223,9 @@ public class BubbleExpandedView extends LinearLayout {
+ getBubbleKey());
}
try {
+ Rect launchBounds = new Rect();
+ mTaskView.getBoundsOnScreen(launchBounds);
+
options.setTaskAlwaysOnTop(true);
options.setLaunchedFromBubble(true);
options.setPendingIntentBackgroundActivityStartMode(
@@ -478,7 +479,7 @@ public class BubbleExpandedView extends LinearLayout {
void applyThemeAttrs() {
final TypedArray ta = mContext.obtainStyledAttributes(new int[]{
android.R.attr.dialogCornerRadius,
- android.R.attr.colorBackgroundFloating});
+ com.android.internal.R.attr.materialColorSurfaceBright});
boolean supportsRoundedCorners = ScreenDecorationsUtils.supportsRoundedCornersOnWindows(
mContext.getResources());
mCornerRadius = supportsRoundedCorners ? ta.getDimensionPixelSize(0, 0) : 0;
@@ -1057,13 +1058,21 @@ public class BubbleExpandedView extends LinearLayout {
Log.d(TAG, "cleanUpExpandedState: bubble=" + getBubbleKey() + " task=" + mTaskId);
}
if (getTaskId() != INVALID_TASK_ID) {
- try {
- ActivityTaskManager.getService().removeTask(getTaskId());
- } catch (RemoteException e) {
- Log.w(TAG, e.getMessage());
+ // Ensure the task is removed from WM
+ if (ENABLE_SHELL_TRANSITIONS) {
+ if (mTaskView != null) {
+ mTaskView.removeTask();
+ }
+ } else {
+ try {
+ ActivityTaskManager.getService().removeTask(getTaskId());
+ } catch (RemoteException e) {
+ Log.w(TAG, e.getMessage());
+ }
}
}
if (mTaskView != null) {
+ // Release the surface & other task view related things
mTaskView.release();
removeView(mTaskView);
mTaskView = null;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BubbleInfo.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BubbleInfo.java
index d27d05b207a6..baa23e3040c4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BubbleInfo.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BubbleInfo.java
@@ -30,7 +30,6 @@ import java.util.Objects;
*/
public class BubbleInfo implements Parcelable {
- // TODO(b/269672147): needs a title string for a11y & that comes from notification
// TODO(b/269671451): needs whether the bubble is an 'important person' or not
private String mKey; // Same key as the Notification
@@ -46,24 +45,28 @@ public class BubbleInfo implements Parcelable {
*/
@Nullable
private Icon mIcon;
+ @Nullable
+ private String mTitle;
public BubbleInfo(String key, int flags, @Nullable String shortcutId, @Nullable Icon icon,
- int userId, String packageName) {
+ int userId, String packageName, @Nullable String title) {
mKey = key;
mFlags = flags;
mShortcutId = shortcutId;
mIcon = icon;
mUserId = userId;
mPackageName = packageName;
+ mTitle = title;
}
- public BubbleInfo(Parcel source) {
+ private BubbleInfo(Parcel source) {
mKey = source.readString();
mFlags = source.readInt();
mShortcutId = source.readString();
mIcon = source.readTypedObject(Icon.CREATOR);
mUserId = source.readInt();
mPackageName = source.readString();
+ mTitle = source.readString();
}
public String getKey() {
@@ -92,6 +95,11 @@ public class BubbleInfo implements Parcelable {
return mPackageName;
}
+ @Nullable
+ public String getTitle() {
+ return mTitle;
+ }
+
/**
* Whether this bubble is currently being hidden from the stack.
*/
@@ -141,11 +149,12 @@ public class BubbleInfo implements Parcelable {
parcel.writeTypedObject(mIcon, flags);
parcel.writeInt(mUserId);
parcel.writeString(mPackageName);
+ parcel.writeString(mTitle);
}
@NonNull
public static final Creator<BubbleInfo> CREATOR =
- new Creator<BubbleInfo>() {
+ new Creator<>() {
public BubbleInfo createFromParcel(Parcel source) {
return new BubbleInfo(source);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index e7dede757578..2832c553c20c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -412,7 +412,10 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
/** Releases and re-inflates {@link DividerView} on the root surface. */
public void update(SurfaceControl.Transaction t) {
- if (!mInitialized) return;
+ if (!mInitialized) {
+ init();
+ return;
+ }
mSplitWindowManager.release(t);
mImePositionProcessor.reset();
mSplitWindowManager.init(this, mInsetsState);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
index 838e37a905db..2bbd870f024d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
@@ -47,6 +47,8 @@ import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
+import dagger.Lazy;
+
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashSet;
@@ -55,8 +57,6 @@ import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
-import dagger.Lazy;
-
/**
* Controller to show/update compat UI components on Tasks based on whether the foreground
* activities are in compatibility mode.
@@ -284,13 +284,18 @@ public class CompatUIController implements OnDisplaysChangedListener,
ShellTaskOrganizer.TaskListener taskListener) {
CompatUIWindowManager layout = mActiveCompatLayouts.get(taskInfo.taskId);
if (layout != null) {
- // UI already exists, update the UI layout.
- if (!layout.updateCompatInfo(taskInfo, taskListener,
- showOnDisplay(layout.getDisplayId()))) {
- // The layout is no longer eligible to be shown, remove from active layouts.
+ if (layout.needsToBeRecreated(taskInfo, taskListener)) {
mActiveCompatLayouts.remove(taskInfo.taskId);
+ layout.release();
+ } else {
+ // UI already exists, update the UI layout.
+ if (!layout.updateCompatInfo(taskInfo, taskListener,
+ showOnDisplay(layout.getDisplayId()))) {
+ // The layout is no longer eligible to be shown, remove from active layouts.
+ mActiveCompatLayouts.remove(taskInfo.taskId);
+ }
+ return;
}
- return;
}
// Create a new UI layout.
@@ -433,13 +438,18 @@ public class CompatUIController implements OnDisplaysChangedListener,
private void createOrUpdateReachabilityEduLayout(TaskInfo taskInfo,
ShellTaskOrganizer.TaskListener taskListener) {
if (mActiveReachabilityEduLayout != null) {
- // UI already exists, update the UI layout.
- if (!mActiveReachabilityEduLayout.updateCompatInfo(taskInfo, taskListener,
- showOnDisplay(mActiveReachabilityEduLayout.getDisplayId()))) {
- // The layout is no longer eligible to be shown, remove from active layouts.
+ if (mActiveReachabilityEduLayout.needsToBeRecreated(taskInfo, taskListener)) {
+ mActiveReachabilityEduLayout.release();
mActiveReachabilityEduLayout = null;
+ } else {
+ // UI already exists, update the UI layout.
+ if (!mActiveReachabilityEduLayout.updateCompatInfo(taskInfo, taskListener,
+ showOnDisplay(mActiveReachabilityEduLayout.getDisplayId()))) {
+ // The layout is no longer eligible to be shown, remove from active layouts.
+ mActiveReachabilityEduLayout = null;
+ }
+ return;
}
- return;
}
// Create a new UI layout.
final Context context = getOrCreateDisplayContext(taskInfo.displayId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java
index 659229228a57..d4778fa7a58a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java
@@ -22,7 +22,6 @@ import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.TaskInfo;
import android.app.TaskInfo.CameraCompatControlState;
@@ -53,9 +52,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract {
private final Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> mOnRestartButtonClicked;
- @NonNull
- private TaskInfo mTaskInfo;
-
// Remember the last reported states in case visibility changes due to keyguard or IME updates.
@VisibleForTesting
boolean mHasSizeCompat;
@@ -77,7 +73,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract {
CompatUIHintsState compatUIHintsState, CompatUIConfiguration compatUIConfiguration,
Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> onRestartButtonClicked) {
super(context, taskInfo, syncQueue, taskListener, displayLayout);
- mTaskInfo = taskInfo;
mCallback = callback;
mHasSizeCompat = taskInfo.topActivityInSizeCompat;
mCameraCompatControlState = taskInfo.cameraCompatControlState;
@@ -129,7 +124,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract {
@Override
public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener,
boolean canShow) {
- mTaskInfo = taskInfo;
final boolean prevHasSizeCompat = mHasSizeCompat;
final int prevCameraCompatControlState = mCameraCompatControlState;
mHasSizeCompat = taskInfo.topActivityInSizeCompat;
@@ -149,7 +143,7 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract {
/** Called when the restart button is clicked. */
void onRestartButtonClicked() {
- mOnRestartButtonClicked.accept(Pair.create(mTaskInfo, getTaskListener()));
+ mOnRestartButtonClicked.accept(Pair.create(getLastTaskInfo(), getTaskListener()));
}
/** Called when the camera treatment button is clicked. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
index 9c4e79cd631b..180498c50c78 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
@@ -26,6 +26,7 @@ import static com.android.internal.annotations.VisibleForTesting.Visibility.PACK
import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.TaskInfo;
import android.content.Context;
@@ -65,6 +66,9 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
private DisplayLayout mDisplayLayout;
private final Rect mStableBounds;
+ @NonNull
+ private TaskInfo mTaskInfo;
+
/**
* Utility class for adding and releasing a View hierarchy for this {@link
* WindowlessWindowManager} to {@code mLeash}.
@@ -83,6 +87,7 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
SyncTransactionQueue syncQueue, ShellTaskOrganizer.TaskListener taskListener,
DisplayLayout displayLayout) {
super(taskInfo.configuration, null /* rootSurface */, null /* hostInputToken */);
+ mTaskInfo = taskInfo;
mContext = context;
mSyncQueue = syncQueue;
mTaskConfig = taskInfo.configuration;
@@ -95,6 +100,17 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
}
/**
+ * @return {@code true} if the instance of the specific {@link CompatUIWindowManagerAbstract}
+ * for the current task id needs to be recreated loading the related resources. This happens
+ * if the user switches between Light/Dark mode, if the device is docked/undocked or if the
+ * user switches between multi-window mode to fullscreen where the
+ * {@link ShellTaskOrganizer.TaskListener} implementation is different.
+ */
+ boolean needsToBeRecreated(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) {
+ return hasUiModeChanged(mTaskInfo, taskInfo) || hasTaskListenerChanged(taskListener);
+ }
+
+ /**
* Returns the z-order of this window which will be passed to the {@link SurfaceControl} once
* {@link #attachToParentSurface} is called.
*
@@ -195,6 +211,7 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
@VisibleForTesting(visibility = PROTECTED)
public boolean updateCompatInfo(TaskInfo taskInfo,
ShellTaskOrganizer.TaskListener taskListener, boolean canShow) {
+ mTaskInfo = taskInfo;
final Configuration prevTaskConfig = mTaskConfig;
final ShellTaskOrganizer.TaskListener prevTaskListener = mTaskListener;
mTaskConfig = taskInfo.configuration;
@@ -315,6 +332,11 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
updateSurfacePosition();
}
+ @Nullable
+ protected TaskInfo getLastTaskInfo() {
+ return mTaskInfo;
+ }
+
/**
* Called following a change in the task bounds, display layout stable bounds, or the layout
* direction.
@@ -402,4 +424,12 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
protected final String getTag() {
return getClass().getSimpleName();
}
+
+ protected boolean hasTaskListenerChanged(ShellTaskOrganizer.TaskListener newTaskListener) {
+ return !mTaskListener.equals(newTaskListener);
+ }
+
+ protected static boolean hasUiModeChanged(TaskInfo currentTaskInfo, TaskInfo newTaskInfo) {
+ return currentTaskInfo.configuration.uiMode != newTaskInfo.configuration.uiMode;
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/LetterboxEduWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/LetterboxEduWindowManager.java
index 959c50d5c640..9a67258ded2e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/LetterboxEduWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/LetterboxEduWindowManager.java
@@ -19,7 +19,6 @@ package com.android.wm.shell.compatui;
import static android.provider.Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING;
import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.TaskInfo;
import android.content.Context;
@@ -69,9 +68,6 @@ class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract {
@VisibleForTesting
LetterboxEduDialogLayout mLayout;
- @NonNull
- private TaskInfo mTaskInfo;
-
/**
* The vertical margin between the dialog container and the task stable bounds (excluding
* insets).
@@ -99,7 +95,6 @@ class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract {
DialogAnimationController<LetterboxEduDialogLayout> animationController,
DockStateReader dockStateReader, CompatUIConfiguration compatUIConfiguration) {
super(context, taskInfo, syncQueue, taskListener, displayLayout);
- mTaskInfo = taskInfo;
mTransitions = transitions;
mOnDismissCallback = onDismissCallback;
mAnimationController = animationController;
@@ -197,7 +192,7 @@ class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract {
mLayout.setDismissOnClickListener(null);
mAnimationController.startExitAnimation(mLayout, () -> {
release();
- mOnDismissCallback.accept(Pair.create(mTaskInfo, getTaskListener()));
+ mOnDismissCallback.accept(Pair.create(getLastTaskInfo(), getTaskListener()));
});
}
@@ -210,7 +205,6 @@ class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract {
@Override
public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener,
boolean canShow) {
- mTaskInfo = taskInfo;
mEligibleForLetterboxEducation = taskInfo.topActivityEligibleForLetterboxEducation;
return super.updateCompatInfo(taskInfo, taskListener, canShow);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/ReachabilityEduWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/ReachabilityEduWindowManager.java
index a18ab9154e01..95bb1fe1c986 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/ReachabilityEduWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/ReachabilityEduWindowManager.java
@@ -20,7 +20,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.TaskInfo;
import android.content.Context;
@@ -52,9 +51,6 @@ class ReachabilityEduWindowManager extends CompatUIWindowManagerAbstract {
private final ShellExecutor mMainExecutor;
- @NonNull
- private TaskInfo mTaskInfo;
-
private boolean mIsActivityLetterboxed;
private int mLetterboxVerticalPosition;
@@ -86,7 +82,6 @@ class ReachabilityEduWindowManager extends CompatUIWindowManagerAbstract {
ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout,
CompatUIConfiguration compatUIConfiguration, ShellExecutor mainExecutor) {
super(context, taskInfo, syncQueue, taskListener, displayLayout);
- mTaskInfo = taskInfo;
mIsActivityLetterboxed = taskInfo.isLetterboxDoubleTapEnabled;
mLetterboxVerticalPosition = taskInfo.topActivityLetterboxVerticalPosition;
mLetterboxHorizontalPosition = taskInfo.topActivityLetterboxHorizontalPosition;
@@ -136,7 +131,6 @@ class ReachabilityEduWindowManager extends CompatUIWindowManagerAbstract {
@Override
public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener,
boolean canShow) {
- mTaskInfo = taskInfo;
final boolean prevIsActivityLetterboxed = mIsActivityLetterboxed;
final int prevLetterboxVerticalPosition = mLetterboxVerticalPosition;
final int prevLetterboxHorizontalPosition = mLetterboxHorizontalPosition;
@@ -222,14 +216,14 @@ class ReachabilityEduWindowManager extends CompatUIWindowManagerAbstract {
if (mLayout == null) {
return;
}
-
+ final TaskInfo lastTaskInfo = getLastTaskInfo();
final boolean eligibleForDisplayHorizontalEducation = mForceUpdate
- || !mCompatUIConfiguration.hasSeenHorizontalReachabilityEducation(mTaskInfo)
+ || !mCompatUIConfiguration.hasSeenHorizontalReachabilityEducation(lastTaskInfo)
|| (mHasUserDoubleTapped
&& (mLetterboxHorizontalPosition == REACHABILITY_LEFT_OR_UP_POSITION
|| mLetterboxHorizontalPosition == REACHABILITY_RIGHT_OR_BOTTOM_POSITION));
final boolean eligibleForDisplayVerticalEducation = mForceUpdate
- || !mCompatUIConfiguration.hasSeenVerticalReachabilityEducation(mTaskInfo)
+ || !mCompatUIConfiguration.hasSeenVerticalReachabilityEducation(lastTaskInfo)
|| (mHasUserDoubleTapped
&& (mLetterboxVerticalPosition == REACHABILITY_LEFT_OR_UP_POSITION
|| mLetterboxVerticalPosition == REACHABILITY_RIGHT_OR_BOTTOM_POSITION));
@@ -241,7 +235,7 @@ class ReachabilityEduWindowManager extends CompatUIWindowManagerAbstract {
mLayout.handleVisibility(eligibleForDisplayHorizontalEducation,
eligibleForDisplayVerticalEducation,
mLetterboxVerticalPosition, mLetterboxHorizontalPosition, availableWidth,
- availableHeight, mCompatUIConfiguration, mTaskInfo);
+ availableHeight, mCompatUIConfiguration, lastTaskInfo);
if (!mHasLetterboxSizeChanged) {
updateHideTime();
mMainExecutor.executeDelayed(this::hideReachability, DISAPPEAR_DELAY_MS);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
index 51e5141a28af..a770da28fbd1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
@@ -19,7 +19,6 @@ package com.android.wm.shell.compatui;
import static android.provider.Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING;
import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.TaskInfo;
import android.content.Context;
@@ -67,9 +66,6 @@ class RestartDialogWindowManager extends CompatUIWindowManagerAbstract {
*/
private final int mDialogVerticalMargin;
- @NonNull
- private TaskInfo mTaskInfo;
-
@Nullable
@VisibleForTesting
RestartDialogLayout mLayout;
@@ -95,7 +91,6 @@ class RestartDialogWindowManager extends CompatUIWindowManagerAbstract {
DialogAnimationController<RestartDialogLayout> animationController,
CompatUIConfiguration compatUIConfiguration) {
super(context, taskInfo, syncQueue, taskListener, displayLayout);
- mTaskInfo = taskInfo;
mTransitions = transitions;
mOnDismissCallback = onDismissCallback;
mOnRestartCallback = onRestartCallback;
@@ -125,7 +120,7 @@ class RestartDialogWindowManager extends CompatUIWindowManagerAbstract {
protected boolean eligibleToShowLayout() {
// We don't show this dialog if the user has explicitly selected so clicking on a checkbox.
return mRequestRestartDialog && !isTaskbarEduShowing() && (mLayout != null
- || mCompatUIConfiguration.shouldShowRestartDialogAgain(mTaskInfo));
+ || mCompatUIConfiguration.shouldShowRestartDialogAgain(getLastTaskInfo()));
}
@Override
@@ -143,18 +138,6 @@ class RestartDialogWindowManager extends CompatUIWindowManagerAbstract {
mRequestRestartDialog = enabled;
}
- @Override
- public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener,
- boolean canShow) {
- mTaskInfo = taskInfo;
- return super.updateCompatInfo(taskInfo, taskListener, canShow);
- }
-
- boolean needsToBeRecreated(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) {
- return taskInfo.configuration.uiMode != mTaskInfo.configuration.uiMode
- || !getTaskListener().equals(taskListener);
- }
-
private void updateDialogMargins() {
if (mLayout == null) {
return;
@@ -191,6 +174,7 @@ class RestartDialogWindowManager extends CompatUIWindowManagerAbstract {
// Dialog has already been released.
return;
}
+ final TaskInfo lastTaskInfo = getLastTaskInfo();
mLayout.setDismissOnClickListener(this::onDismiss);
mLayout.setRestartOnClickListener(dontShowAgain -> {
if (mLayout != null) {
@@ -200,9 +184,9 @@ class RestartDialogWindowManager extends CompatUIWindowManagerAbstract {
});
}
if (dontShowAgain) {
- mCompatUIConfiguration.setDontShowRestartDialogAgain(mTaskInfo);
+ mCompatUIConfiguration.setDontShowRestartDialogAgain(lastTaskInfo);
}
- mOnRestartCallback.accept(Pair.create(mTaskInfo, getTaskListener()));
+ mOnRestartCallback.accept(Pair.create(lastTaskInfo, getTaskListener()));
});
// Focus on the dialog title for accessibility.
mLayout.getDialogTitle().sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
@@ -216,7 +200,7 @@ class RestartDialogWindowManager extends CompatUIWindowManagerAbstract {
mLayout.setDismissOnClickListener(null);
mAnimationController.startExitAnimation(mLayout, () -> {
release();
- mOnDismissCallback.accept(Pair.create(mTaskInfo, getTaskListener()));
+ mOnDismissCallback.accept(Pair.create(getLastTaskInfo(), getTaskListener()));
});
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index b3109388da2c..9de9855720bc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -39,7 +39,6 @@ import android.window.TransitionRequestInfo
import android.window.WindowContainerToken
import android.window.WindowContainerTransaction
import androidx.annotation.BinderThread
-import com.android.internal.protolog.common.ProtoLog
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.common.DisplayController
@@ -56,6 +55,7 @@ import com.android.wm.shell.sysui.ShellController
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.sysui.ShellSharedConstants
import com.android.wm.shell.transition.Transitions
+import com.android.wm.shell.util.KtProtoLog
import java.util.concurrent.Executor
import java.util.function.Consumer
@@ -91,7 +91,7 @@ class DesktopTasksController(
}
private fun onInit() {
- ProtoLog.d(WM_SHELL_DESKTOP_MODE, "Initialize DesktopTasksController")
+ KtProtoLog.d(WM_SHELL_DESKTOP_MODE, "Initialize DesktopTasksController")
shellController.addExternalInterface(
ShellSharedConstants.KEY_EXTRA_SHELL_DESKTOP_MODE,
{ createExternalInterface() },
@@ -102,7 +102,7 @@ class DesktopTasksController(
/** Show all tasks, that are part of the desktop, on top of launcher */
fun showDesktopApps(displayId: Int) {
- ProtoLog.v(WM_SHELL_DESKTOP_MODE, "showDesktopApps")
+ KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "showDesktopApps")
val wct = WindowContainerTransaction()
// TODO(b/278084491): pass in display id
bringDesktopAppsToFront(displayId, wct)
@@ -130,7 +130,7 @@ class DesktopTasksController(
/** Move a task to desktop */
fun moveToDesktop(task: RunningTaskInfo) {
- ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToDesktop: %d", task.taskId)
+ KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToDesktop: %d", task.taskId)
val wct = WindowContainerTransaction()
// Bring other apps to front first
@@ -190,7 +190,7 @@ class DesktopTasksController(
/** Move a task to fullscreen */
fun moveToFullscreen(task: RunningTaskInfo) {
- ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToFullscreen: %d", task.taskId)
+ KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToFullscreen: %d", task.taskId)
val wct = WindowContainerTransaction()
addMoveToFullscreenChanges(wct, task.token)
@@ -255,10 +255,10 @@ class DesktopTasksController(
fun moveToNextDisplay(taskId: Int) {
val task = shellTaskOrganizer.getRunningTaskInfo(taskId)
if (task == null) {
- ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: taskId=%d not found", taskId)
+ KtProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: taskId=%d not found", taskId)
return
}
- ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: taskId=%d taskDisplayId=%d",
+ KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: taskId=%d taskDisplayId=%d",
taskId, task.displayId)
val displayIds = rootTaskDisplayAreaOrganizer.displayIds.sorted()
@@ -269,7 +269,7 @@ class DesktopTasksController(
newDisplayId = displayIds.firstOrNull { displayId -> displayId < task.displayId }
}
if (newDisplayId == null) {
- ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: next display not found")
+ KtProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: next display not found")
return
}
moveToDisplay(task, newDisplayId)
@@ -281,17 +281,17 @@ class DesktopTasksController(
* No-op if task is already on that display per [RunningTaskInfo.displayId].
*/
private fun moveToDisplay(task: RunningTaskInfo, displayId: Int) {
- ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToDisplay: taskId=%d displayId=%d",
+ KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToDisplay: taskId=%d displayId=%d",
task.taskId, displayId)
if (task.displayId == displayId) {
- ProtoLog.d(WM_SHELL_DESKTOP_MODE, "moveToDisplay: task already on display")
+ KtProtoLog.d(WM_SHELL_DESKTOP_MODE, "moveToDisplay: task already on display")
return
}
val displayAreaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(displayId)
if (displayAreaInfo == null) {
- ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToDisplay: display not found")
+ KtProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToDisplay: display not found")
return
}
@@ -316,7 +316,7 @@ class DesktopTasksController(
}
private fun bringDesktopAppsToFront(displayId: Int, wct: WindowContainerTransaction) {
- ProtoLog.v(WM_SHELL_DESKTOP_MODE, "bringDesktopAppsToFront")
+ KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "bringDesktopAppsToFront")
val activeTasks = desktopModeTaskRepository.getActiveTasks(displayId)
// First move home to front and then other tasks on top of it
@@ -397,7 +397,7 @@ class DesktopTasksController(
if (task.windowingMode == WINDOWING_MODE_FULLSCREEN) {
// If there are any visible desktop tasks, switch the task to freeform
if (activeTasks.any { desktopModeTaskRepository.isVisibleTask(it) }) {
- ProtoLog.d(
+ KtProtoLog.d(
WM_SHELL_DESKTOP_MODE,
"DesktopTasksController#handleRequest: switch fullscreen task to freeform," +
" taskId=%d",
@@ -414,7 +414,7 @@ class DesktopTasksController(
// If no visible desktop tasks, switch this task to freeform as the transition came
// outside of this controller
if (activeTasks.none { desktopModeTaskRepository.isVisibleTask(it) }) {
- ProtoLog.d(
+ KtProtoLog.d(
WM_SHELL_DESKTOP_MODE,
"DesktopTasksController#handleRequest: switch freeform task to fullscreen," +
" taskId=%d",
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index 3e568e9cb996..387d39056ffc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -431,6 +431,11 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
" adding opening taskId=%d", taskInfo.taskId);
mOpeningTasks.add(new TaskState(change, target.leash));
}
+ } else if (TransitionUtil.isDividerBar(change)) {
+ final RemoteAnimationTarget target = TransitionUtil.newTarget(change,
+ info.getChanges().size() - i, info, t, mLeashMap);
+ // Add this as a app and we will separate them on launcher side by window type.
+ apps.add(target);
}
}
t.apply();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index e5ae10c097a5..b8373f3548ca 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -482,8 +482,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
final WindowContainerTransaction wct = new WindowContainerTransaction();
- final WindowContainerTransaction evictWct = new WindowContainerTransaction();
- prepareEvictChildTasks(position, evictWct);
options = resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, null /* wct */);
wct.sendPendingIntent(intent, fillInIntent, options);
@@ -494,12 +492,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
prepareEnterSplitScreen(wct, null /* taskInfo */, position);
mSplitTransitions.startEnterTransition(TRANSIT_TO_FRONT, wct, null, this,
- null /* consumedCallback */,
- (finishWct, finishT) -> {
- if (!evictWct.isEmpty()) {
- finishWct.merge(evictWct, true);
- }
- } /* finishedCallback */, extraTransitType);
+ null /* consumedCallback */, null /* finishedCallback */, extraTransitType);
}
/** Launches an activity into split by legacy transition. */
@@ -1476,6 +1469,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSideStage.removeAllTasks(wct, false /* toTop */);
mMainStage.deactivate(wct, false /* toTop */);
}
+ wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
+ false /* reparentLeafTaskIfRelaunch */);
}
private void prepareEnterSplitScreen(WindowContainerTransaction wct) {
@@ -1509,7 +1504,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
if (taskInfo != null) {
wct.startTask(taskInfo.taskId,
resolveStartStage(STAGE_TYPE_UNDEFINED, startPosition, null, wct));
- targetStage.evictAllChildren(wct);
}
// If running background, we need to reparent current top visible task to another stage
// and evict all tasks current under its.
@@ -1519,7 +1513,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
updateWindowBounds(mSplitLayout, wct);
final StageTaskListener anotherStage = targetStage == mMainStage
? mSideStage : mMainStage;
- anotherStage.evictAllChildren(wct);
anotherStage.reparentTopTask(wct);
wct.reorder(mRootTaskInfo.token, true);
setRootForceTranslucent(false, wct);
@@ -1538,13 +1531,14 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSideStage.addTask(taskInfo, wct);
}
mMainStage.activate(wct, true /* includingTopTask */);
+ mSplitLayout.resetDividerPosition();
updateWindowBounds(mSplitLayout, wct);
wct.reorder(mRootTaskInfo.token, true);
setRootForceTranslucent(false, wct);
}
void finishEnterSplitScreen(SurfaceControl.Transaction t) {
- mSplitLayout.init();
+ mSplitLayout.update(t);
setDividerVisibility(true, t);
// Ensure divider surface are re-parented back into the hierarchy at the end of the
// transition. See Transition#buildFinishTransaction for more detail.
@@ -1776,7 +1770,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
});
}
- void onChildTaskAppeared(StageListenerImpl stageListener, int taskId) {
+ /** Callback when split roots have child task appeared under it, this is a little different from
+ * #onStageHasChildrenChanged because this would be called every time child task appeared.
+ * NOTICE: This only be called on legacy transition. */
+ private void onChildTaskAppeared(StageListenerImpl stageListener, int taskId) {
// Handle entering split screen while there is a split pair running in the background.
if (stageListener == mSideStageListener && !isSplitScreenVisible() && isSplitActive()
&& mSplitRequest == null) {
@@ -1822,6 +1819,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
wct.setForceTranslucent(mRootTaskInfo.token, translucent);
}
+ /** Callback when split roots visiblility changed.
+ * NOTICE: This only be called on legacy transition. */
private void onStageVisibilityChanged(StageListenerImpl stageListener) {
// If split didn't active, just ignore this callback because we should already did these
// on #applyExitSplitScreen.
@@ -1963,6 +1962,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
}
+ /** Callback when split roots have child or haven't under it.
+ * NOTICE: This only be called on legacy transition. */
private void onStageHasChildrenChanged(StageListenerImpl stageListener) {
final boolean hasChildren = stageListener.mHasChildren;
final boolean isSideStage = stageListener == mSideStageListener;
@@ -2327,6 +2328,15 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// the remote handler.
return null;
}
+
+ if ((mMainStage.containsTask(triggerTask.taskId)
+ && mMainStage.getChildCount() == 1)
+ || (mSideStage.containsTask(triggerTask.taskId)
+ && mSideStage.getChildCount() == 1)) {
+ // A splitting task is opening to fullscreen causes one side of the split empty,
+ // so appends operations to exit split.
+ prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, out);
+ }
}
} else {
if (isOpening && getStageOfTask(triggerTask) != null) {
@@ -2409,9 +2419,23 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
if (isOpeningType(change.getMode())) {
// Split is opened by someone so set it as visible.
setSplitsVisible(true);
+ // TODO(b/275664132): Find a way to integrate this with finishWct.
+ // This is setting the flag to a task and not interfering with the
+ // transition.
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
+ false /* reparentLeafTaskIfRelaunch */);
+ mTaskOrganizer.applyTransaction(wct);
} else if (isClosingType(change.getMode())) {
// Split is closed by someone so set it as invisible.
setSplitsVisible(false);
+ // TODO(b/275664132): Find a way to integrate this with finishWct.
+ // This is setting the flag to a task and not interfering with the
+ // transition.
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
+ true /* reparentLeafTaskIfRelaunch */);
+ mTaskOrganizer.applyTransaction(wct);
}
continue;
}
@@ -2530,7 +2554,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
boolean shouldAnimate = true;
if (mSplitTransitions.isPendingEnter(transition)) {
shouldAnimate = startPendingEnterAnimation(
- transition, info, startTransaction, finishTransaction);
+ mSplitTransitions.mPendingEnter, info, startTransaction, finishTransaction);
} else if (mSplitTransitions.isPendingDismiss(transition)) {
shouldAnimate = startPendingDismissAnimation(
mSplitTransitions.mPendingDismiss, info, startTransaction, finishTransaction);
@@ -2566,7 +2590,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
}
- private boolean startPendingEnterAnimation(@NonNull IBinder transition,
+ private boolean startPendingEnterAnimation(
+ @NonNull SplitScreenTransitions.TransitSession enterTransition,
@NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t,
@NonNull SurfaceControl.Transaction finishT) {
// First, verify that we actually have opened apps in both splits.
@@ -2577,9 +2602,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
if (taskInfo == null || !taskInfo.hasParentTask()) continue;
final @StageType int stageType = getStageType(getStageOfTask(taskInfo));
- if (stageType == STAGE_TYPE_MAIN) {
+ if (stageType == STAGE_TYPE_MAIN
+ && (isOpeningType(change.getMode()) || change.getMode() == TRANSIT_CHANGE)) {
+ // Includes TRANSIT_CHANGE to cover reparenting top-most task to split.
mainChild = change;
- } else if (stageType == STAGE_TYPE_SIDE) {
+ } else if (stageType == STAGE_TYPE_SIDE && isOpeningType(change.getMode())) {
sideChild = change;
}
}
@@ -2598,7 +2625,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
final int dismissTop = mainChild != null ? STAGE_TYPE_MAIN :
(sideChild != null ? STAGE_TYPE_SIDE : STAGE_TYPE_UNDEFINED);
mSplitTransitions.mPendingEnter.cancel(
- (cancelWct, cancelT) -> prepareExitSplitScreen(dismissTop, cancelWct));
+ (cancelWct, cancelT) -> {
+ mSideStage.removeAllTasks(cancelWct, dismissTop == STAGE_TYPE_SIDE);
+ mMainStage.deactivate(cancelWct, dismissTop == STAGE_TYPE_MAIN);
+ });
return true;
}
}
@@ -2620,6 +2650,17 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
+ " before startAnimation().");
}
+ final TransitionInfo.Change finalMainChild = mainChild;
+ final TransitionInfo.Change finalSideChild = sideChild;
+ enterTransition.setFinishedCallback((callbackWct, callbackT) -> {
+ if (finalMainChild != null) {
+ mMainStage.evictOtherChildren(callbackWct, finalMainChild.getTaskInfo().taskId);
+ }
+ if (finalSideChild != null) {
+ mSideStage.evictOtherChildren(callbackWct, finalSideChild.getTaskInfo().taskId);
+ }
+ });
+
finishEnterSplitScreen(finishT);
addDividerBarToTransition(info, true /* show */);
return true;
@@ -2788,8 +2829,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
/** Call this when starting the open-recents animation while split-screen is active. */
- public void onRecentsInSplitAnimationStart(@NonNull SurfaceControl.Transaction t) {
- setDividerVisibility(false, t);
+ public void onRecentsInSplitAnimationStart(TransitionInfo info) {
+ addDividerBarToTransition(info, false /* show */);
}
/** Call this when the recents animation during split-screen finishes. */
@@ -2806,21 +2847,15 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|| mSideStage.containsContainer(container))) {
updateSurfaceBounds(mSplitLayout, finishT,
false /* applyResizingOffset */);
+ finishT.reparent(mSplitLayout.getDividerLeash(), mRootTaskLeash);
setDividerVisibility(true, finishT);
return;
}
}
- // TODO(b/275664132): Remove dismissing split screen here to fit in back-to-split support.
- // Dismiss the split screen if it's not returning to split.
- prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, finishWct);
- for (TransitionInfo.Change change : info.getChanges()) {
- if (change.getTaskInfo() != null && TransitionUtil.isClosingType(change.getMode())) {
- finishT.setCrop(change.getLeash(), null).hide(change.getLeash());
- }
- }
setSplitsVisible(false);
- setDividerVisibility(false, finishT);
+ finishWct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
+ true /* reparentLeafTaskIfRelaunch */);
logExit(EXIT_REASON_UNKNOWN);
}
@@ -2892,6 +2927,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
if (!isSplitScreenVisible()) {
// If split running background, exit split first.
+ // TODO(b/280392203) : skip doing this on shell transition once this bug is fixed.
exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RECREATE_SPLIT);
}
mLogger.enterRequestedByDrag(position, dragSessionId);
@@ -2903,6 +2939,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
public void onRequestToSplit(InstanceId sessionId, int enterReason) {
if (!isSplitScreenVisible()) {
// If split running background, exit split first.
+ // TODO(b/280392203) : skip doing this on shell transition once this bug is fixed.
exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RECREATE_SPLIT);
}
mLogger.enterRequested(sessionId, enterReason);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java
index e4d8c32eb5c8..4faa92979733 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java
@@ -177,6 +177,13 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
}
/**
+ * Call to remove the task from window manager. This task will not appear in recents.
+ */
+ public void removeTask() {
+ mTaskViewTaskController.removeTask();
+ }
+
+ /**
* Release this container if it is initialized.
*/
public void release() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
index 2ab4c751d399..94190c74f3e9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
@@ -102,7 +102,7 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
}
/** Until all users are converted, we may have mixed-use (eg. Car). */
- private boolean isUsingShellTransitions() {
+ public boolean isUsingShellTransitions() {
return mTaskViewTransitions != null && mTaskViewTransitions.isEnabled();
}
@@ -401,6 +401,15 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
mSyncQueue.queue(wct);
}
+ /**
+ * Call to remove the task from window manager. This task will not appear in recents.
+ */
+ void removeTask() {
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.removeTask(mTaskToken);
+ mTaskViewTransitions.closeTaskView(wct, this);
+ }
+
/** Should be called when the client surface is destroyed. */
public void surfaceDestroyed() {
mSurfaceCreated = false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
index 2faed3a4b93d..689f9e1a3eda 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
@@ -17,6 +17,7 @@
package com.android.wm.shell.taskview;
import static android.view.WindowManager.TRANSIT_CHANGE;
+import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
@@ -201,6 +202,13 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
startNextTransition();
}
+ void closeTaskView(@NonNull WindowContainerTransaction wct,
+ @NonNull TaskViewTaskController taskView) {
+ updateVisibilityState(taskView, false /* visible */);
+ mPending.add(new PendingTransition(TRANSIT_CLOSE, wct, taskView, null /* cookie */));
+ startNextTransition();
+ }
+
void setTaskViewVisible(TaskViewTaskController taskView, boolean visible) {
if (mTaskViews.get(taskView) == null) return;
if (mTaskViews.get(taskView).mVisible == visible) return;
@@ -297,6 +305,11 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
if (TransitionUtil.isClosingType(chg.getMode())) {
final boolean isHide = chg.getMode() == TRANSIT_TO_BACK;
TaskViewTaskController tv = findTaskView(chg.getTaskInfo());
+ if (tv == null && !isHide) {
+ // TaskView can be null when closing
+ changesHandled++;
+ continue;
+ }
if (tv == null) {
if (pending != null) {
Slog.w(TAG, "Found a non-TaskView task in a TaskView Transition. This "
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
index 49429327572e..6fa1861a23e2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
@@ -150,9 +150,9 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
@Override
public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
@NonNull TransitionRequestInfo request) {
- if (mPipHandler.requestHasPipEnter(request) && mSplitHandler.isSplitScreenVisible()) {
+ if (mPipHandler.requestHasPipEnter(request) && mSplitHandler.isSplitActive()) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a PiP-enter request while "
- + "Split-Screen is foreground, so treat it as Mixed.");
+ + "Split-Screen is active, so treat it as Mixed.");
if (request.getRemoteTransition() != null) {
throw new IllegalStateException("Unexpected remote transition in"
+ "pip-enter-from-split request");
@@ -524,7 +524,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
finishCallback.onTransitionFinished(wct, wctCB);
};
mixed.mInFlightSubAnimations = 1;
- mSplitHandler.onRecentsInSplitAnimationStart(startTransaction);
+ mSplitHandler.onRecentsInSplitAnimationStart(info);
final boolean handled = mixed.mLeftoversHandler.startAnimation(mixed.mTransition, info,
startTransaction, finishTransaction, finishCB);
if (!handled) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Tracer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Tracer.java
index 0cede902f034..e27e4f990407 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Tracer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Tracer.java
@@ -28,7 +28,6 @@ import android.os.Trace;
import android.util.Log;
import com.android.internal.util.TraceBuffer;
-import com.android.wm.shell.nano.HandlerMapping;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.google.protobuf.nano.MessageNano;
@@ -41,6 +40,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
+import java.util.concurrent.TimeUnit;
/**
* Helper class to collect and dump transition traces.
@@ -241,6 +241,10 @@ public class Tracer implements ShellCommandHandler.ShellCommandActionHandler {
new com.android.wm.shell.nano.WmShellTransitionTraceProto();
proto.magicNumber = MAGIC_NUMBER_VALUE;
writeHandlerMappingToProto(proto);
+ long timeOffsetNs =
+ TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis())
+ - SystemClock.elapsedRealtimeNanos();
+ proto.realToElapsedTimeOffsetNanos = timeOffsetNs;
int pid = android.os.Process.myPid();
LogAndPrintln.i(pw, "Writing file to " + file.getAbsolutePath()
+ " from process " + pid);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index a73ab776486b..fda943d7dc02 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -19,8 +19,6 @@ package com.android.wm.shell.transition;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FIRST_CUSTOM;
-import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_SLEEP;
import static android.view.WindowManager.TRANSIT_TO_BACK;
@@ -851,14 +849,13 @@ public class Transitions implements RemoteCallable<Transitions>,
active.mStartT, active.mFinishT, (wct, cb) -> onFinish(active, wct, cb));
if (consumed) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " animated by firstHandler");
+ mTracer.logDispatched(active.mInfo.getDebugId(), active.mHandler);
return;
}
}
// Otherwise give every other handler a chance
active.mHandler = dispatchTransition(active.mToken, active.mInfo, active.mStartT,
active.mFinishT, (wct, cb) -> onFinish(active, wct, cb), active.mHandler);
-
- mTracer.logDispatched(active.mInfo.getDebugId(), active.mHandler);
}
/**
@@ -877,6 +874,7 @@ public class Transitions implements RemoteCallable<Transitions>,
if (consumed) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " animated by %s",
mHandlers.get(i));
+ mTracer.logDispatched(info.getDebugId(), mHandlers.get(i));
return mHandlers.get(i);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/KtProtoLog.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/util/KtProtoLog.kt
new file mode 100644
index 000000000000..9b48a542720c
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/KtProtoLog.kt
@@ -0,0 +1,74 @@
+/*
+ * 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.util
+
+import android.util.Log
+import com.android.internal.protolog.common.IProtoLogGroup
+import com.android.wm.shell.protolog.ShellProtoLogImpl
+
+/**
+ * Log messages using an API similar to [com.android.internal.protolog.common.ProtoLog]. Useful for
+ * logging from Kotlin classes as ProtoLog does not have support for Kotlin.
+ *
+ * All messages are logged to logcat if logging is enabled for that [IProtoLogGroup].
+ */
+// TODO(b/168581922): remove once ProtoLog adds support for Kotlin
+class KtProtoLog {
+ companion object {
+ /** @see [com.android.internal.protolog.common.ProtoLog.d] */
+ fun d(group: IProtoLogGroup, messageString: String, vararg args: Any) {
+ if (ShellProtoLogImpl.isEnabled(group)) {
+ Log.d(group.tag, String.format(messageString, *args))
+ }
+ }
+
+ /** @see [com.android.internal.protolog.common.ProtoLog.v] */
+ fun v(group: IProtoLogGroup, messageString: String, vararg args: Any) {
+ if (ShellProtoLogImpl.isEnabled(group)) {
+ Log.v(group.tag, String.format(messageString, *args))
+ }
+ }
+
+ /** @see [com.android.internal.protolog.common.ProtoLog.i] */
+ fun i(group: IProtoLogGroup, messageString: String, vararg args: Any) {
+ if (ShellProtoLogImpl.isEnabled(group)) {
+ Log.i(group.tag, String.format(messageString, *args))
+ }
+ }
+
+ /** @see [com.android.internal.protolog.common.ProtoLog.w] */
+ fun w(group: IProtoLogGroup, messageString: String, vararg args: Any) {
+ if (ShellProtoLogImpl.isEnabled(group)) {
+ Log.w(group.tag, String.format(messageString, *args))
+ }
+ }
+
+ /** @see [com.android.internal.protolog.common.ProtoLog.e] */
+ fun e(group: IProtoLogGroup, messageString: String, vararg args: Any) {
+ if (ShellProtoLogImpl.isEnabled(group)) {
+ Log.e(group.tag, String.format(messageString, *args))
+ }
+ }
+
+ /** @see [com.android.internal.protolog.common.ProtoLog.wtf] */
+ fun wtf(group: IProtoLogGroup, messageString: String, vararg args: Any) {
+ if (ShellProtoLogImpl.isEnabled(group)) {
+ Log.wtf(group.tag, String.format(messageString, *args))
+ }
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
index c5cd2d91eb39..7d05c0e62e13 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
@@ -110,6 +110,11 @@ public class TransitionUtil {
&& !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
}
+ /** Returns `true` if `change` is the divider. */
+ public static boolean isDividerBar(TransitionInfo.Change change) {
+ return isNonApp(change) && change.hasFlags(FLAG_IS_DIVIDER_BAR);
+ }
+
/** Returns `true` if `change` is only re-ordering. */
public static boolean isOrderOnly(TransitionInfo.Change change) {
return change.getMode() == TRANSIT_CHANGE
@@ -175,6 +180,14 @@ public class TransitionUtil {
t.setPosition(leash, absBounds.left - info.getRoot(rootIdx).getOffset().x,
absBounds.top - info.getRoot(rootIdx).getOffset().y);
+ if (isDividerBar(change)) {
+ if (isOpeningType(mode)) {
+ t.setAlpha(leash, 0.f);
+ }
+ t.setLayer(leash, Integer.MAX_VALUE);
+ return;
+ }
+
// Put all the OPEN/SHOW on top
if (TransitionUtil.isOpeningType(mode)) {
if (isOpening) {
@@ -245,6 +258,10 @@ public class TransitionUtil {
*/
public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
SurfaceControl leash) {
+ if (isDividerBar(change)) {
+ return getDividerTarget(change, leash);
+ }
+
int taskId;
boolean isNotInRecents;
ActivityManager.RunningTaskInfo taskInfo;
@@ -284,8 +301,7 @@ public class TransitionUtil {
new Rect(change.getStartAbsBounds()),
taskInfo,
change.getAllowEnterPip(),
- (change.getFlags() & FLAG_IS_DIVIDER_BAR) != 0
- ? TYPE_DOCK_DIVIDER : INVALID_WINDOW_TYPE
+ INVALID_WINDOW_TYPE
);
target.setWillShowImeOnTarget(
(change.getFlags() & TransitionInfo.FLAG_WILL_IME_SHOWN) != 0);
@@ -293,6 +309,17 @@ public class TransitionUtil {
return target;
}
+ private static RemoteAnimationTarget getDividerTarget(TransitionInfo.Change change,
+ SurfaceControl leash) {
+ return new RemoteAnimationTarget(-1 /* taskId */, -1 /* mode */,
+ leash, false /* isTranslucent */, null /* clipRect */,
+ null /* contentInsets */, Integer.MAX_VALUE /* prefixOrderIndex */,
+ new android.graphics.Point(0, 0) /* position */, change.getStartAbsBounds(),
+ change.getStartAbsBounds(), new WindowConfiguration(), true, null /* startLeash */,
+ null /* startBounds */, null /* taskInfo */, false /* allowEnterPip */,
+ TYPE_DOCK_DIVIDER);
+ }
+
/**
* Finds the "correct" root idx for a change. The change's end display is prioritized, then
* the start display. If there is no display, it will fallback on the 0th root in the
@@ -306,4 +333,14 @@ public class TransitionUtil {
if (rootIdx >= 0) return rootIdx;
return 0;
}
+
+ /**
+ * Gets the {@link TransitionInfo.Root} for the given {@link TransitionInfo.Change}.
+ * @see #rootIndexFor(TransitionInfo.Change, TransitionInfo)
+ */
+ @NonNull
+ public static TransitionInfo.Root getRootFor(@NonNull TransitionInfo.Change change,
+ @NonNull TransitionInfo info) {
+ return info.getRoot(rootIndexFor(change, info));
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java
index fa2d7a87c3cb..4899453ac991 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java
@@ -19,8 +19,10 @@ package com.android.wm.shell.windowdecor;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
+import android.annotation.ColorRes;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -109,6 +111,10 @@ public class ResizeVeil {
t.reparent(mVeilSurface, parentSurface);
mParentSurface = parentSurface;
}
+
+ int backgroundColorId = getBackgroundColorId();
+ mViewHost.getView().setBackgroundColor(mContext.getColor(backgroundColorId));
+
t.show(mVeilSurface)
.apply();
final ValueAnimator animator = new ValueAnimator();
@@ -158,6 +164,17 @@ public class ResizeVeil {
animator.start();
}
+ @ColorRes
+ private int getBackgroundColorId() {
+ Configuration configuration = mContext.getResources().getConfiguration();
+ if ((configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK)
+ == Configuration.UI_MODE_NIGHT_YES) {
+ return R.color.desktop_mode_resize_veil_dark;
+ } else {
+ return R.color.desktop_mode_resize_veil_light;
+ }
+ }
+
/**
* Dispose of veil when it is no longer needed, likely on close of its container decor.
*/
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/bubbles/BubbleInfoTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/bubbles/BubbleInfoTest.kt
new file mode 100644
index 000000000000..8fbac1db8653
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/bubbles/BubbleInfoTest.kt
@@ -0,0 +1,49 @@
+/*
+ * 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.common.bubbles
+
+import android.os.Parcel
+import android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.wm.shell.ShellTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class BubbleInfoTest : ShellTestCase() {
+
+ @Test
+ fun bubbleInfo() {
+ val bubbleInfo = BubbleInfo("key", 0, "shortcut id", null, 6, "com.some.package", "title")
+ val parcel = Parcel.obtain()
+ bubbleInfo.writeToParcel(parcel, PARCELABLE_WRITE_RETURN_VALUE)
+ parcel.setDataPosition(0)
+
+ val bubbleInfoFromParcel = BubbleInfo.CREATOR.createFromParcel(parcel)
+
+ assertThat(bubbleInfo.key).isEqualTo(bubbleInfoFromParcel.key)
+ assertThat(bubbleInfo.flags).isEqualTo(bubbleInfoFromParcel.flags)
+ assertThat(bubbleInfo.shortcutId).isEqualTo(bubbleInfoFromParcel.shortcutId)
+ assertThat(bubbleInfo.icon).isEqualTo(bubbleInfoFromParcel.icon)
+ assertThat(bubbleInfo.userId).isEqualTo(bubbleInfoFromParcel.userId)
+ assertThat(bubbleInfo.packageName).isEqualTo(bubbleInfoFromParcel.packageName)
+ assertThat(bubbleInfo.title).isEqualTo(bubbleInfoFromParcel.title)
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java
index 4de529885565..55781f1b4d6f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java
@@ -37,6 +37,7 @@ import static org.mockito.Mockito.verify;
import android.app.ActivityManager;
import android.app.TaskInfo;
+import android.content.res.Configuration;
import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
import android.util.Pair;
@@ -455,12 +456,21 @@ public class CompatUIWindowManagerTest extends ShellTestCase {
verify(mLayout).setCameraCompatHintVisibility(/* show= */ true);
}
+ @Test
+ public void testWhenDockedStateHasChanged_needsToBeRecreated() {
+ ActivityManager.RunningTaskInfo newTaskInfo = new ActivityManager.RunningTaskInfo();
+ newTaskInfo.configuration.uiMode |= Configuration.UI_MODE_TYPE_DESK;
+
+ Assert.assertTrue(mWindowManager.needsToBeRecreated(newTaskInfo, mTaskListener));
+ }
+
private static TaskInfo createTaskInfo(boolean hasSizeCompat,
@TaskInfo.CameraCompatControlState int cameraCompatControlState) {
ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
taskInfo.taskId = TASK_ID;
taskInfo.topActivityInSizeCompat = hasSizeCompat;
taskInfo.cameraCompatControlState = cameraCompatControlState;
+ taskInfo.configuration.uiMode &= ~Configuration.UI_MODE_TYPE_DESK;
return taskInfo;
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/ReachabilityEduWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/ReachabilityEduWindowManagerTest.java
index 5bcc72e73cb9..973a99c269ea 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/ReachabilityEduWindowManagerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/ReachabilityEduWindowManagerTest.java
@@ -21,6 +21,7 @@ import static org.junit.Assert.assertNull;
import android.app.ActivityManager;
import android.app.TaskInfo;
+import android.content.res.Configuration;
import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest;
@@ -31,6 +32,8 @@ import com.android.wm.shell.TestShellExecutor;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.SyncTransactionQueue;
+import junit.framework.Assert;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -46,63 +49,61 @@ import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@SmallTest
public class ReachabilityEduWindowManagerTest extends ShellTestCase {
-
- private static final int USER_ID = 1;
- private static final int TASK_ID = 1;
-
@Mock
private SyncTransactionQueue mSyncTransactionQueue;
@Mock
private ShellTaskOrganizer.TaskListener mTaskListener;
@Mock
- private CompatUIController.CompatUICallback mCallback;
- @Mock
private CompatUIConfiguration mCompatUIConfiguration;
@Mock
private DisplayLayout mDisplayLayout;
-
private TestShellExecutor mExecutor;
+ private TaskInfo mTaskInfo;
+ private ReachabilityEduWindowManager mWindowManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mExecutor = new TestShellExecutor();
+ mTaskInfo = new ActivityManager.RunningTaskInfo();
+ mTaskInfo.configuration.uiMode =
+ (mTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_NIGHT_MASK)
+ | Configuration.UI_MODE_NIGHT_NO;
+ mTaskInfo.configuration.uiMode =
+ (mTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_TYPE_MASK)
+ | Configuration.UI_MODE_TYPE_NORMAL;
+ mWindowManager = createReachabilityEduWindowManager(mTaskInfo);
}
@Test
public void testCreateLayout_notEligible_doesNotCreateLayout() {
- final ReachabilityEduWindowManager windowManager = createReachabilityEduWindowManager(
- createTaskInfo(/* userId= */ USER_ID, /*isLetterboxDoubleTapEnabled */ false));
-
- assertFalse(windowManager.createLayout(/* canShow= */ true));
+ assertFalse(mWindowManager.createLayout(/* canShow= */ true));
- assertNull(windowManager.mLayout);
+ assertNull(mWindowManager.mLayout);
}
- private ReachabilityEduWindowManager createReachabilityEduWindowManager(TaskInfo taskInfo) {
- return new ReachabilityEduWindowManager(mContext, taskInfo, mSyncTransactionQueue,
- mTaskListener, mDisplayLayout, mCompatUIConfiguration, mExecutor);
+ @Test
+ public void testWhenDockedStateHasChanged_needsToBeRecreated() {
+ ActivityManager.RunningTaskInfo newTaskInfo = new ActivityManager.RunningTaskInfo();
+ newTaskInfo.configuration.uiMode =
+ (newTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_TYPE_MASK)
+ | Configuration.UI_MODE_TYPE_DESK;
+
+ Assert.assertTrue(mWindowManager.needsToBeRecreated(newTaskInfo, mTaskListener));
}
- private static TaskInfo createTaskInfo(int userId, boolean isLetterboxDoubleTapEnabled) {
- return createTaskInfo(userId, /* isLetterboxDoubleTapEnabled */ isLetterboxDoubleTapEnabled,
- /* topActivityLetterboxVerticalPosition */ -1,
- /* topActivityLetterboxHorizontalPosition */ -1,
- /* topActivityLetterboxWidth */ -1,
- /* topActivityLetterboxHeight */ -1);
+ @Test
+ public void testWhenDarkLightThemeHasChanged_needsToBeRecreated() {
+ ActivityManager.RunningTaskInfo newTaskInfo = new ActivityManager.RunningTaskInfo();
+ mTaskInfo.configuration.uiMode =
+ (mTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_NIGHT_MASK)
+ | Configuration.UI_MODE_NIGHT_YES;
+
+ Assert.assertTrue(mWindowManager.needsToBeRecreated(newTaskInfo, mTaskListener));
}
- private static TaskInfo createTaskInfo(int userId, boolean isLetterboxDoubleTapEnabled,
- int topActivityLetterboxVerticalPosition, int topActivityLetterboxHorizontalPosition,
- int topActivityLetterboxWidth, int topActivityLetterboxHeight) {
- ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
- taskInfo.userId = userId;
- taskInfo.taskId = TASK_ID;
- taskInfo.isLetterboxDoubleTapEnabled = isLetterboxDoubleTapEnabled;
- taskInfo.topActivityLetterboxVerticalPosition = topActivityLetterboxVerticalPosition;
- taskInfo.topActivityLetterboxHorizontalPosition = topActivityLetterboxHorizontalPosition;
- taskInfo.topActivityLetterboxWidth = topActivityLetterboxWidth;
- taskInfo.topActivityLetterboxHeight = topActivityLetterboxHeight;
- return taskInfo;
+ private ReachabilityEduWindowManager createReachabilityEduWindowManager(TaskInfo taskInfo) {
+ return new ReachabilityEduWindowManager(mContext, taskInfo, mSyncTransactionQueue,
+ mTaskListener, mDisplayLayout, mCompatUIConfiguration, mExecutor);
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/RestartDialogWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/RestartDialogWindowManagerTest.java
new file mode 100644
index 000000000000..9f109a1d0f50
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/RestartDialogWindowManagerTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.compatui;
+
+import android.app.ActivityManager;
+import android.app.TaskInfo;
+import android.content.res.Configuration;
+import android.testing.AndroidTestingRunner;
+import android.util.Pair;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.common.DisplayLayout;
+import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.transition.Transitions;
+
+import junit.framework.Assert;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.function.Consumer;
+
+/**
+ * Tests for {@link RestartDialogWindowManager}.
+ *
+ * Build/Install/Run:
+ * atest WMShellUnitTests:RestartDialogWindowManagerTest
+ */
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+public class RestartDialogWindowManagerTest extends ShellTestCase {
+
+ @Mock
+ private SyncTransactionQueue mSyncTransactionQueue;
+ @Mock private ShellTaskOrganizer.TaskListener mTaskListener;
+ @Mock private CompatUIConfiguration mCompatUIConfiguration;
+ @Mock private Transitions mTransitions;
+ @Mock private Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> mOnRestartCallback;
+ @Mock private Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> mOnDismissCallback;
+ private RestartDialogWindowManager mWindowManager;
+ private TaskInfo mTaskInfo;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mTaskInfo = new ActivityManager.RunningTaskInfo();
+ mTaskInfo.configuration.uiMode =
+ (mTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_NIGHT_MASK)
+ | Configuration.UI_MODE_NIGHT_NO;
+ mTaskInfo.configuration.uiMode =
+ (mTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_TYPE_MASK)
+ | Configuration.UI_MODE_TYPE_NORMAL;
+ mWindowManager = new RestartDialogWindowManager(mContext, mTaskInfo, mSyncTransactionQueue,
+ mTaskListener, new DisplayLayout(), mTransitions, mOnRestartCallback,
+ mOnDismissCallback, mCompatUIConfiguration);
+ }
+
+ @Test
+ public void testWhenDockedStateHasChanged_needsToBeRecreated() {
+ ActivityManager.RunningTaskInfo newTaskInfo = new ActivityManager.RunningTaskInfo();
+ newTaskInfo.configuration.uiMode =
+ (newTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_TYPE_MASK)
+ | Configuration.UI_MODE_TYPE_DESK;
+
+ Assert.assertTrue(mWindowManager.needsToBeRecreated(newTaskInfo, mTaskListener));
+ }
+
+ @Test
+ public void testWhenDarkLightThemeHasChanged_needsToBeRecreated() {
+ ActivityManager.RunningTaskInfo newTaskInfo = new ActivityManager.RunningTaskInfo();
+ mTaskInfo.configuration.uiMode =
+ (mTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_NIGHT_MASK)
+ | Configuration.UI_MODE_NIGHT_YES;
+
+ Assert.assertTrue(mWindowManager.needsToBeRecreated(newTaskInfo, mTaskListener));
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
index 92cbf7f068b4..b76d2dcc6e1e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
@@ -273,7 +273,7 @@ public class SplitTransitionTests extends ShellTestCase {
// simulate the start of recents transition
mMainStage.onTaskVanished(mMainChild);
mSideStage.onTaskVanished(mSideChild);
- mStageCoordinator.onRecentsInSplitAnimationStart(mock(SurfaceControl.Transaction.class));
+ mStageCoordinator.onRecentsInSplitAnimationStart(mock(TransitionInfo.class));
assertTrue(mStageCoordinator.isSplitScreenVisible());
// Make sure it cleans-up if recents doesn't restore
@@ -307,7 +307,7 @@ public class SplitTransitionTests extends ShellTestCase {
// simulate the start of recents transition
mMainStage.onTaskVanished(mMainChild);
mSideStage.onTaskVanished(mSideChild);
- mStageCoordinator.onRecentsInSplitAnimationStart(mock(SurfaceControl.Transaction.class));
+ mStageCoordinator.onRecentsInSplitAnimationStart(mock(TransitionInfo.class));
assertTrue(mStageCoordinator.isSplitScreenVisible());
// Make sure we remain in split after recents restores.
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index d27064d1b4da..44a0ede82e5c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -158,8 +158,6 @@ public class StageCoordinatorTests extends ShellTestCase {
verify(mStageCoordinator).prepareEnterSplitScreen(eq(wct), eq(task),
eq(SPLIT_POSITION_BOTTOM_OR_RIGHT));
verify(mMainStage).reparentTopTask(eq(wct));
- verify(mMainStage).evictAllChildren(eq(wct));
- verify(mSideStage).evictAllChildren(eq(wct));
verify(mSplitLayout).resetDividerPosition();
assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition());
assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition());
@@ -178,7 +176,6 @@ public class StageCoordinatorTests extends ShellTestCase {
mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct);
verify(mStageCoordinator).prepareEnterSplitScreen(eq(wct), eq(task),
eq(SPLIT_POSITION_BOTTOM_OR_RIGHT));
- verify(mMainStage).evictAllChildren(eq(wct));
assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getMainStagePosition());
assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getSideStagePosition());
}
diff --git a/libs/hwui/renderthread/HintSessionWrapper.cpp b/libs/hwui/renderthread/HintSessionWrapper.cpp
index 8c9f65fac10c..597cbf732d82 100644
--- a/libs/hwui/renderthread/HintSessionWrapper.cpp
+++ b/libs/hwui/renderthread/HintSessionWrapper.cpp
@@ -20,11 +20,14 @@
#include <private/performance_hint_private.h>
#include <utils/Log.h>
+#include <chrono>
#include <vector>
#include "../Properties.h"
#include "thread/CommonPool.h"
+using namespace std::chrono_literals;
+
namespace android {
namespace uirenderer {
namespace renderthread {
@@ -96,10 +99,25 @@ HintSessionWrapper::~HintSessionWrapper() {
}
bool HintSessionWrapper::init() {
- // If it already exists, broke last time we tried this, shouldn't be running, or
+ if (mHintSession != nullptr) return true;
+
+ // If we're waiting for the session
+ if (mHintSessionFuture.valid()) {
+ // If the session is here
+ if (mHintSessionFuture.wait_for(0s) == std::future_status::ready) {
+ mHintSession = mHintSessionFuture.get();
+ if (mHintSession != nullptr) {
+ mSessionValid = true;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // If it broke last time we tried this, shouldn't be running, or
// has bad argument values, don't even bother
- if (mHintSession != nullptr || !mSessionValid || !Properties::useHintManager ||
- !Properties::isDrawingEnabled() || mUiThreadId < 0 || mRenderThreadId < 0) {
+ if (!mSessionValid || !Properties::useHintManager || !Properties::isDrawingEnabled() ||
+ mUiThreadId < 0 || mRenderThreadId < 0) {
return false;
}
@@ -118,15 +136,14 @@ bool HintSessionWrapper::init() {
// Use a placeholder target value to initialize,
// this will always be replaced elsewhere before it gets used
int64_t defaultTargetDurationNanos = 16666667;
- mHintSession =
- gAPH_createSessionFn(manager, tids.data(), tids.size(), defaultTargetDurationNanos);
-
- mSessionValid = !!mHintSession;
- return mSessionValid;
+ mHintSessionFuture = CommonPool::async([=, tids = std::move(tids)] {
+ return gAPH_createSessionFn(manager, tids.data(), tids.size(), defaultTargetDurationNanos);
+ });
+ return false;
}
void HintSessionWrapper::updateTargetWorkDuration(long targetWorkDurationNanos) {
- if (mHintSession == nullptr) return;
+ if (!init()) return;
targetWorkDurationNanos = targetWorkDurationNanos * Properties::targetCpuTimePercentage / 100;
if (targetWorkDurationNanos != mLastTargetWorkDuration &&
targetWorkDurationNanos > kSanityCheckLowerBound &&
@@ -138,7 +155,7 @@ void HintSessionWrapper::updateTargetWorkDuration(long targetWorkDurationNanos)
}
void HintSessionWrapper::reportActualWorkDuration(long actualDurationNanos) {
- if (mHintSession == nullptr) return;
+ if (!init()) return;
if (actualDurationNanos > kSanityCheckLowerBound &&
actualDurationNanos < kSanityCheckUpperBound) {
gAPH_reportActualWorkDurationFn(mHintSession, actualDurationNanos);
@@ -146,7 +163,7 @@ void HintSessionWrapper::reportActualWorkDuration(long actualDurationNanos) {
}
void HintSessionWrapper::sendLoadResetHint() {
- if (mHintSession == nullptr) return;
+ if (!init()) return;
nsecs_t now = systemTime();
if (now - mLastFrameNotification > kResetHintTimeout) {
gAPH_sendHintFn(mHintSession, static_cast<int>(SessionHint::CPU_LOAD_RESET));
@@ -155,7 +172,7 @@ void HintSessionWrapper::sendLoadResetHint() {
}
void HintSessionWrapper::sendLoadIncreaseHint() {
- if (mHintSession == nullptr) return;
+ if (!init()) return;
gAPH_sendHintFn(mHintSession, static_cast<int>(SessionHint::CPU_LOAD_UP));
}
diff --git a/libs/hwui/renderthread/HintSessionWrapper.h b/libs/hwui/renderthread/HintSessionWrapper.h
index f2f1298c1eec..b7a433fb4eae 100644
--- a/libs/hwui/renderthread/HintSessionWrapper.h
+++ b/libs/hwui/renderthread/HintSessionWrapper.h
@@ -18,6 +18,8 @@
#include <android/performance_hint.h>
+#include <future>
+
#include "utils/TimeUtils.h"
namespace android {
@@ -38,6 +40,7 @@ public:
private:
APerformanceHintSession* mHintSession = nullptr;
+ std::future<APerformanceHintSession*> mHintSessionFuture;
nsecs_t mLastFrameNotification = 0;
nsecs_t mLastTargetWorkDuration = 0;
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index 10f456745147..3168cb09291b 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -375,6 +375,14 @@ void VulkanSurface::releaseBuffers() {
}
}
+void VulkanSurface::invalidateBuffers() {
+ for (uint32_t i = 0; i < mWindowInfo.bufferCount; i++) {
+ VulkanSurface::NativeBufferInfo& bufferInfo = mNativeBuffers[i];
+ bufferInfo.hasValidContents = false;
+ bufferInfo.lastPresentedCount = 0;
+ }
+}
+
VulkanSurface::NativeBufferInfo* VulkanSurface::dequeueNativeBuffer() {
// Set the mCurrentBufferInfo to invalid in case of error and only reset it to the correct
// value at the end of the function if everything dequeued correctly.
@@ -407,6 +415,10 @@ VulkanSurface::NativeBufferInfo* VulkanSurface::dequeueNativeBuffer() {
// new NativeBufferInfo storage will be populated lazily as we dequeue each new buffer.
mWindowInfo.actualSize = actualSize;
releaseBuffers();
+ } else {
+ // A change in transform means we need to repaint the entire buffer area as the damage
+ // rects have just moved about.
+ invalidateBuffers();
}
if (transformHint != mWindowInfo.transform) {
diff --git a/libs/hwui/renderthread/VulkanSurface.h b/libs/hwui/renderthread/VulkanSurface.h
index 6f5280105e55..116075c16eba 100644
--- a/libs/hwui/renderthread/VulkanSurface.h
+++ b/libs/hwui/renderthread/VulkanSurface.h
@@ -116,6 +116,7 @@ private:
WindowInfo* outWindowInfo);
static bool UpdateWindow(ANativeWindow* window, const WindowInfo& windowInfo);
void releaseBuffers();
+ void invalidateBuffers();
// TODO: This number comes from ui/BufferQueueDefs. We're not pulling the
// header in so that we don't need to depend on libui, but we should share
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 88e351963148..e21d6fb2fe14 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -45,14 +45,13 @@ const ui::Transform kIdentityTransform;
// --- PointerController::DisplayInfoListener ---
void PointerController::DisplayInfoListener::onWindowInfosChanged(
- const std::vector<android::gui::WindowInfo>&,
- const std::vector<android::gui::DisplayInfo>& displayInfos) {
+ const gui::WindowInfosUpdate& update) {
std::scoped_lock lock(mLock);
if (mPointerController == nullptr) return;
// PointerController uses DisplayInfoListener's lock.
base::ScopedLockAssertion assumeLocked(mPointerController->getLock());
- mPointerController->onDisplayInfosChangedLocked(displayInfos);
+ mPointerController->onDisplayInfosChangedLocked(update.displayInfos);
}
void PointerController::DisplayInfoListener::onPointerControllerDestroyed() {
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index ca14b6e9bfdc..62ee74331302 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -19,6 +19,7 @@
#include <PointerControllerInterface.h>
#include <gui/DisplayEventReceiver.h>
+#include <gui/WindowInfosUpdate.h>
#include <input/DisplayViewport.h>
#include <input/Input.h>
#include <utils/BitSet.h>
@@ -114,8 +115,7 @@ private:
class DisplayInfoListener : public gui::WindowInfosListener {
public:
explicit DisplayInfoListener(PointerController* pc) : mPointerController(pc){};
- void onWindowInfosChanged(const std::vector<android::gui::WindowInfo>&,
- const std::vector<android::gui::DisplayInfo>&) override;
+ void onWindowInfosChanged(const gui::WindowInfosUpdate&) override;
void onPointerControllerDestroyed();
// This lock is also used by PointerController. See PointerController::getLock().
diff --git a/libs/input/tests/PointerController_test.cpp b/libs/input/tests/PointerController_test.cpp
index 2378d42793a1..85747514aa03 100644
--- a/libs/input/tests/PointerController_test.cpp
+++ b/libs/input/tests/PointerController_test.cpp
@@ -343,7 +343,7 @@ TEST_F(PointerControllerWindowInfoListenerTest,
localListenerCopy = registeredListener;
}
EXPECT_EQ(nullptr, registeredListener) << "WindowInfosListener was not unregistered";
- localListenerCopy->onWindowInfosChanged({}, {});
+ localListenerCopy->onWindowInfosChanged({{}, {}, 0, 0});
}
} // namespace android