summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/Notification.java1
-rw-r--r--core/java/android/app/admin/DeviceAdminInfo.java5
-rw-r--r--core/java/android/companion/virtual/flags/flags.aconfig8
-rw-r--r--core/java/android/hardware/display/DisplayManagerInternal.java10
-rw-r--r--core/java/android/window/DesktopModeFlags.java1
-rw-r--r--core/java/com/android/internal/widget/ConversationLayout.java1
-rw-r--r--core/java/com/android/internal/widget/MessagingGroup.java13
-rw-r--r--core/java/com/android/internal/widget/MessagingLayout.java1
-rw-r--r--core/java/com/android/internal/widget/PeopleHelper.java2
-rw-r--r--core/tests/coretests/src/android/app/NotificationTest.java10
-rw-r--r--libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml5
-rw-r--r--libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_action_button.xml1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipDesktopState.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java9
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopRepositoryTest.kt8
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt9
-rw-r--r--packages/SettingsLib/aconfig/settingslib.aconfig17
-rw-r--r--packages/SettingsLib/res/drawable/ic_news.xml19
-rw-r--r--packages/SettingsLib/res/drawable/ic_promotions.xml19
-rw-r--r--packages/SettingsLib/res/drawable/ic_recs.xml25
-rw-r--r--packages/SettingsLib/res/drawable/ic_social.xml19
-rw-r--r--packages/SystemUI/aconfig/predictive_back.aconfig7
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/PagerDots.kt (renamed from packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PagerDots.kt)4
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt2
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt4
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockController.kt8
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/clipboardoverlay/ActionIntentCreatorTest.kt150
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/clipboardoverlay/DefaultIntentCreatorTest.java (renamed from packages/SystemUI/multivalentTests/src/com/android/systemui/clipboardoverlay/IntentCreatorTest.java)22
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt36
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/PerDisplayInstanceRepositoryImplTest.kt9
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java3
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt30
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/FakeCondition.java2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt9
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt3
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt3
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockController.kt6
-rw-r--r--packages/SystemUI/pods/com/android/systemui/dagger/qualifiers/DisplaySpecific.kt (renamed from packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/DisplaySpecific.kt)5
-rw-r--r--packages/SystemUI/pods/com/android/systemui/dagger/qualifiers/Main.java (renamed from packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/Main.java)0
-rw-r--r--packages/SystemUI/pods/com/android/systemui/dagger/qualifiers/UiBackground.java (renamed from packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/UiBackground.java)0
-rw-r--r--packages/SystemUI/shared/Android.bp1
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/Tracing.kt20
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/condition/CombinedCondition.kt11
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.java306
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.kt270
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/condition/ConditionExtensions.kt18
-rw-r--r--packages/SystemUI/src/com/android/keyguard/ClockEventController.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesChecker.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt35
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/ActionIntentCreator.kt99
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/DefaultIntentCreator.java102
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/IntentCreator.java78
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/DeviceInactiveCondition.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/display/data/repository/PerDisplayRepository.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/conditions/DreamCondition.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/lowlightclock/DirectBootCondition.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/lowlightclock/ForceLowLightCondition.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightCondition.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/lowlightclock/ScreenSaverEnabledCondition.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/model/SysUIStateDispatcher.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/LauncherProxyService.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt57
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/data/StatusBarDataLayerModule.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarConfigurationStateStore.kt120
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarPerDisplayConfigurationStateRepository.kt69
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerStatusBarViewBinder.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt34
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowImageInflater.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTileGrid.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactoryTest.kt72
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/recents/LauncherProxyServiceTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/condition/CombinedConditionTest.kt50
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowImageInflaterTest.kt51
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/model/SysUiStateKosmos.kt7
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorKosmos.kt3
-rwxr-xr-xravenwood/scripts/list-ravenwood-tests.sh18
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java21
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java17
-rw-r--r--services/core/java/com/android/server/display/DisplayTopologyCoordinator.java5
-rw-r--r--services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java2
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java15
-rw-r--r--services/core/java/com/android/server/wm/BackgroundActivityStartController.java7
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java29
-rw-r--r--services/core/java/com/android/server/wm/DisplayWindowSettings.java5
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java16
-rw-r--r--services/core/java/com/android/server/wm/Task.java2
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java8
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java20
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt22
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java19
-rw-r--r--tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt14
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml27
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_bottom_half_pip.xml1
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_bubble.xml1
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_base_layout.xml1
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml1
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_secondary_activity_layout.xml3
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_ime.xml1
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_launch_new.xml1
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_mail.xml1
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_non_resizeable.xml3
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_pip.xml1
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_simple.xml1
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_splitscreen.xml1
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_splitscreen_secondary.xml1
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_start_media_projection.xml3
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_surfaceview.xml1
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_transparent.xml1
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/activity_transparent_launch.xml1
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/notification_button.xml2
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/layout/task_button.xml1
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/res/values/styles.xml6
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ImeActivity.java5
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ImeEditorPopupDialogActivity.java2
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchNewActivity.java5
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchNewTaskActivity.java5
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/NotificationActivity.java8
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java8
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PortraitOnlyActivity.java5
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SeamlessRotationActivity.java2
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ShowWhenLockedActivity.java5
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SimpleActivity.java5
-rw-r--r--tools/codegen/src/com/android/codegen/Debug.kt2
-rw-r--r--tools/codegen/src/com/android/codegen/FeatureFlag.kt4
-rw-r--r--tools/codegen/src/com/android/codegen/FileInfo.kt8
-rw-r--r--tools/codegen/src/com/android/codegen/Generators.kt4
-rw-r--r--tools/codegen/src/com/android/codegen/Utils.kt2
149 files changed, 1523 insertions, 1031 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index cc72d8f1ad8c..8d4925d8182d 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3266,7 +3266,6 @@ public class Notification implements Parcelable
final Class<? extends Style> notificationStyle = getNotificationStyle();
return notificationStyle == null
- || BigPictureStyle.class.equals(notificationStyle)
|| BigTextStyle.class.equals(notificationStyle)
|| CallStyle.class.equals(notificationStyle)
|| ProgressStyle.class.equals(notificationStyle);
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index cb2b8adae0f9..8a8877f441a9 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -558,6 +558,11 @@ public final class DeviceAdminInfo implements Parcelable {
}
public void dump(Printer pw, String prefix) {
+ pw.println("mVisible: " + mVisible);
+ pw.println("mUsesPolicies: " + mUsesPolicies);
+ pw.println("mSupportsTransferOwnership: " + mSupportsTransferOwnership);
+ pw.println("mHeadlessDeviceOwnerMode: " + mHeadlessDeviceOwnerMode);
+
pw.println(prefix + "Receiver:");
mActivityInfo.dump(pw, prefix + " ");
}
diff --git a/core/java/android/companion/virtual/flags/flags.aconfig b/core/java/android/companion/virtual/flags/flags.aconfig
index 0085e4f42397..4fb3982c3754 100644
--- a/core/java/android/companion/virtual/flags/flags.aconfig
+++ b/core/java/android/companion/virtual/flags/flags.aconfig
@@ -150,3 +150,11 @@ flag {
description: "Settings override for virtual devices"
bug: "371801645"
}
+
+flag {
+ namespace: "virtual_devices"
+ name: "viewconfiguration_apis"
+ description: "APIs for settings ViewConfiguration attributes on virtual devices"
+ bug: "370720522"
+ is_exported: true
+}
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 343e4b5668c0..0c8a9ed56ae8 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -476,6 +476,16 @@ public abstract class DisplayManagerInternal {
public abstract boolean isDisplayReadyForMirroring(int displayId);
/**
+ * Called by {@link com.android.server.wm.WindowManagerService} to notify whether a display
+ * should be in the topology.
+ * @param displayId The logical ID of the display
+ * @param inTopology Whether the display should be in the topology. This being true does not
+ * guarantee that the display will be in the topology - Display Manager might
+ * also check other parameters.
+ */
+ public abstract void onDisplayBelongToTopologyChanged(int displayId, boolean inTopology);
+
+ /**
* Called by {@link com.android.server.display.DisplayBackupHelper} when backup files were
* restored and are ready to be reloaded.
*/
diff --git a/core/java/android/window/DesktopModeFlags.java b/core/java/android/window/DesktopModeFlags.java
index 888d7e7c895d..78769248c013 100644
--- a/core/java/android/window/DesktopModeFlags.java
+++ b/core/java/android/window/DesktopModeFlags.java
@@ -94,6 +94,7 @@ public enum DesktopModeFlags {
ENABLE_DESKTOP_WINDOWING_MULTI_INSTANCE_FEATURES(
Flags::enableDesktopWindowingMultiInstanceFeatures, true),
ENABLE_DESKTOP_WINDOWING_PERSISTENCE(Flags::enableDesktopWindowingPersistence, true),
+ ENABLE_DESKTOP_WINDOWING_PIP(Flags::enableDesktopWindowingPip, false),
ENABLE_DESKTOP_WINDOWING_QUICK_SWITCH(Flags::enableDesktopWindowingQuickSwitch, true),
ENABLE_DESKTOP_WINDOWING_SCVH_CACHE(Flags::enableDesktopWindowingScvhCacheBugFix, true),
ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS(Flags::enableDesktopWindowingSizeConstraints, true),
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java
index 2cca3dbc4f2f..3da19220248b 100644
--- a/core/java/com/android/internal/widget/ConversationLayout.java
+++ b/core/java/com/android/internal/widget/ConversationLayout.java
@@ -1178,6 +1178,7 @@ public class ConversationLayout extends FrameLayout
}
newGroup.setShowingAvatar(!mIsOneToOne && !mIsCollapsed);
newGroup.setSingleLine(mIsCollapsed && TextUtils.isEmpty(mSummarizedContent));
+ newGroup.setIsCollapsed(mIsCollapsed);
newGroup.setSender(sender, nameOverride);
newGroup.setSending(groupIndex == (groups.size() - 1) && showSpinner);
mGroups.add(newGroup);
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index b31a200218ee..21bb7a9468bd 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -103,6 +103,7 @@ public class MessagingGroup extends NotificationOptimizedLinearLayout implements
private boolean mShowingAvatar = true;
private CharSequence mSenderName;
private boolean mSingleLine = false;
+ private boolean mIsCollapsed = false;
private LinearLayout mContentContainer;
private int mRequestedMaxDisplayedLines = Integer.MAX_VALUE;
private int mSenderTextPaddingSingleLine;
@@ -451,7 +452,7 @@ public class MessagingGroup extends NotificationOptimizedLinearLayout implements
private void updateIconVisibility() {
if (Flags.notificationsRedesignTemplates()) {
// We don't show any icon (other than the app or person icon) in the collapsed form.
- mMessagingIconContainer.setVisibility(mSingleLine ? GONE : VISIBLE);
+ mMessagingIconContainer.setVisibility(mIsCollapsed ? GONE : VISIBLE);
}
}
@@ -714,10 +715,18 @@ public class MessagingGroup extends NotificationOptimizedLinearLayout implements
updateMaxDisplayedLines();
updateClipRect();
updateSenderVisibility();
- updateIconVisibility();
}
}
+ /**
+ * Sets whether this is in a collapsed layout or not. Certain elements like icons are not shown
+ * when the notification is collapsed.
+ */
+ public void setIsCollapsed(boolean isCollapsed) {
+ mIsCollapsed = isCollapsed;
+ updateIconVisibility();
+ }
+
public boolean isSingleLine() {
return mSingleLine;
}
diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java
index 9fe2de82adee..4cc4b38f95a5 100644
--- a/core/java/com/android/internal/widget/MessagingLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLayout.java
@@ -551,6 +551,7 @@ public class MessagingLayout extends FrameLayout
}
newGroup.setSingleLine(mIsCollapsed && TextUtils.isEmpty(mSummarizedContent));
newGroup.setShowingAvatar(!mIsCollapsed);
+ newGroup.setIsCollapsed(mIsCollapsed);
newGroup.setSender(sender, nameOverride);
newGroup.setSending(groupIndex == (groups.size() - 1) && showSpinner);
mGroups.add(newGroup);
diff --git a/core/java/com/android/internal/widget/PeopleHelper.java b/core/java/com/android/internal/widget/PeopleHelper.java
index 3f5b4a0d61fe..3aa4c8498747 100644
--- a/core/java/com/android/internal/widget/PeopleHelper.java
+++ b/core/java/com/android/internal/widget/PeopleHelper.java
@@ -110,7 +110,7 @@ public class PeopleHelper {
@NonNull
public Icon createAvatarSymbol(@NonNull CharSequence name, @NonNull String symbol,
@ColorInt int layoutColor) {
- if (symbol.isEmpty() || TextUtils.isDigitsOnly(symbol)
+ if (symbol == null || symbol.isEmpty() || TextUtils.isDigitsOnly(symbol)
|| SPECIAL_CHAR_PATTERN.matcher(symbol).find()) {
Icon avatarIcon = Icon.createWithResource(mContext, R.drawable.messaging_user);
avatarIcon.setTint(findColor(name, layoutColor));
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index f89e4416ce78..157c74abc5de 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -371,22 +371,22 @@ public class NotificationTest {
@Test
@EnableFlags(Flags.FLAG_UI_RICH_ONGOING)
- public void testHasPromotableStyle_bigPicture() {
+ public void testHasPromotableStyle_bigText() {
Notification n = new Notification.Builder(mContext, "test")
.setSmallIcon(android.R.drawable.sym_def_app_icon)
- .setStyle(new Notification.BigPictureStyle())
+ .setStyle(new Notification.BigTextStyle())
.build();
assertThat(n.hasPromotableStyle()).isTrue();
}
@Test
@EnableFlags(Flags.FLAG_UI_RICH_ONGOING)
- public void testHasPromotableStyle_bigText() {
+ public void testHasPromotableStyle_no_bigPictureStyle() {
Notification n = new Notification.Builder(mContext, "test")
.setSmallIcon(android.R.drawable.sym_def_app_icon)
- .setStyle(new Notification.BigTextStyle())
+ .setStyle(new Notification.BigPictureStyle())
.build();
- assertThat(n.hasPromotableStyle()).isTrue();
+ assertThat(n.hasPromotableStyle()).isFalse();
}
@Test
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml
index a75453578f16..16e098b39004 100644
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml
@@ -142,6 +142,7 @@
android:contentDescription="@string/screenshot_text"
android:text="@string/screenshot_text"
android:src="@drawable/desktop_mode_ic_handle_menu_screenshot"
+ android:importantForAccessibility="no"
style="@style/DesktopModeHandleMenuActionButton"/>
<com.android.wm.shell.windowdecor.HandleMenuActionButton
@@ -149,6 +150,7 @@
android:contentDescription="@string/new_window_text"
android:text="@string/new_window_text"
android:src="@drawable/desktop_mode_ic_handle_menu_new_window"
+ android:importantForAccessibility="no"
style="@style/DesktopModeHandleMenuActionButton"/>
<com.android.wm.shell.windowdecor.HandleMenuActionButton
@@ -156,6 +158,7 @@
android:contentDescription="@string/manage_windows_text"
android:text="@string/manage_windows_text"
android:src="@drawable/desktop_mode_ic_handle_menu_manage_windows"
+ android:importantForAccessibility="no"
style="@style/DesktopModeHandleMenuActionButton"/>
<com.android.wm.shell.windowdecor.HandleMenuActionButton
@@ -163,6 +166,7 @@
android:contentDescription="@string/change_aspect_ratio_text"
android:text="@string/change_aspect_ratio_text"
android:src="@drawable/desktop_mode_ic_handle_menu_change_aspect_ratio"
+ android:importantForAccessibility="no"
style="@style/DesktopModeHandleMenuActionButton"/>
</LinearLayout>
@@ -182,6 +186,7 @@
android:text="@string/open_in_browser_text"
android:src="@drawable/desktop_mode_ic_handle_menu_open_in_browser"
style="@style/DesktopModeHandleMenuActionButton"
+ android:importantForAccessibility="no"
android:layout_width="0dp"
android:layout_weight="1"/>
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_action_button.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_action_button.xml
index 0163c018479f..de38e6fc2330 100644
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_action_button.xml
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_action_button.xml
@@ -34,5 +34,6 @@
<com.android.wm.shell.windowdecor.MarqueedTextView
android:id="@+id/label"
+ android:importantForAccessibility="no"
style="@style/DesktopModeHandleMenuActionButtonTextView"/>
</LinearLayout>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index d1c7f7d7dcad..80b65d025399 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -28,6 +28,7 @@ import static android.window.TransitionInfo.FLAG_MOVED_TO_TOP;
import static android.window.TransitionInfo.FLAG_SHOW_WALLPAPER;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_PREDICTIVE_BACK_HOME;
+import static com.android.systemui.Flags.predictiveBackDelayTransition;
import static com.android.window.flags.Flags.unifyBackNavigationTransition;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW;
@@ -431,6 +432,11 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
@VisibleForTesting
public void onThresholdCrossed() {
mThresholdCrossed = true;
+ BackTouchTracker activeTracker = getActiveTracker();
+ if (predictiveBackDelayTransition() && activeTracker != null && mActiveCallback == null
+ && mBackGestureStarted) {
+ startBackNavigation(activeTracker);
+ }
// There was no focus window when calling startBackNavigation, still pilfer pointers so
// the next focus window won't receive motion events.
if (mBackNavigationInfo == null && mReceivedNullNavigationInfo) {
@@ -488,9 +494,14 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
if (swipeEdge == EDGE_NONE) {
// start animation immediately for non-gestural sources (without ACTION_MOVE
// events)
- mThresholdCrossed = true;
+ if (!predictiveBackDelayTransition()) {
+ mThresholdCrossed = true;
+ }
mPointersPilfered = true;
onGestureStarted(touchX, touchY, swipeEdge);
+ if (predictiveBackDelayTransition()) {
+ onThresholdCrossed();
+ }
mShouldStartOnNextMoveEvent = false;
} else {
mShouldStartOnNextMoveEvent = true;
@@ -544,14 +555,17 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
mPostCommitAnimationInProgress = false;
mShellExecutor.removeCallbacks(mAnimationTimeoutRunnable);
startSystemAnimation();
- } else if (touchTracker == mCurrentTracker) {
- // Only start the back navigation if no other gesture is being processed. Otherwise,
- // the back navigation will fall back to legacy back event injection.
- startBackNavigation(mCurrentTracker);
+ } else if (!predictiveBackDelayTransition()) {
+ startBackNavigation(touchTracker);
}
}
private void startBackNavigation(@NonNull BackTouchTracker touchTracker) {
+ if (touchTracker != mCurrentTracker) {
+ // Only start the back navigation if no other gesture is being processed. Otherwise,
+ // the back navigation will fall back to legacy back event injection.
+ return;
+ }
try {
startLatencyTracking();
if (mBackAnimationAdapter != null
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipDesktopState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipDesktopState.java
index 01fd3442f604..453ca167557a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipDesktopState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipDesktopState.java
@@ -20,9 +20,10 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import android.window.DesktopExperienceFlags;
+import android.window.DesktopModeFlags;
import android.window.DisplayAreaInfo;
-import com.android.window.flags.Flags;
+import com.android.wm.shell.Flags;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler;
@@ -48,18 +49,23 @@ public class PipDesktopState {
/**
* Returns whether PiP in Desktop Windowing is enabled by checking the following:
- * - Desktop Windowing in PiP flag is enabled
+ * - PiP in Desktop Windowing flag is enabled
* - DesktopUserRepositories is injected
* - DragToDesktopTransitionHandler is injected
*/
public boolean isDesktopWindowingPipEnabled() {
- return Flags.enableDesktopWindowingPip() && mDesktopUserRepositoriesOptional.isPresent()
+ return DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PIP.isTrue()
+ && mDesktopUserRepositoriesOptional.isPresent()
&& mDragToDesktopTransitionHandlerOptional.isPresent();
}
- /** Returns whether PiP in Connected Displays is enabled by checking the flag. */
+ /**
+ * Returns whether PiP in Connected Displays is enabled by checking the following:
+ * - PiP in Connected Displays flag is enabled
+ * - PiP2 flag is enabled
+ */
public boolean isConnectedDisplaysPipEnabled() {
- return DesktopExperienceFlags.ENABLE_CONNECTED_DISPLAYS_PIP.isTrue();
+ return DesktopExperienceFlags.ENABLE_CONNECTED_DISPLAYS_PIP.isTrue() && Flags.enablePip2();
}
/** Returns whether the display with the PiP task is in freeform windowing mode. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt
index 8c2748742595..bbb300ea42da 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt
@@ -733,7 +733,8 @@ class DesktopRepository(
desktopData.getActiveDesk(displayId)?.topTransparentFullscreenTaskId = null
}
- private fun notifyVisibleTaskListeners(displayId: Int, visibleTasksCount: Int) {
+ @VisibleForTesting
+ public fun notifyVisibleTaskListeners(displayId: Int, visibleTasksCount: Int) {
visibleTasksListeners.forEach { (listener, executor) ->
executor.execute { listener.onTasksVisibilityChanged(displayId, visibleTasksCount) }
}
@@ -915,6 +916,7 @@ class DesktopRepository(
val wasActive = desktopData.getActiveDesk(desk.displayId)?.deskId == desk.deskId
val activeTasks = ArraySet(desk.activeTasks)
desktopData.remove(desk.deskId)
+ notifyVisibleTaskListeners(desk.displayId, getVisibleTaskCount(displayId = desk.displayId))
deskChangeListeners.forEach { (listener, executor) ->
executor.execute {
if (wasActive) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
index 26a5d5b52358..bd9c30e2a495 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
@@ -32,7 +32,6 @@ import android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVI
import android.window.TransitionInfo
import android.window.WindowContainerTransaction
import com.android.internal.protolog.ProtoLog
-import com.android.window.flags.Flags
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.back.BackAnimationController
import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.isExitDesktopModeTransition
@@ -107,7 +106,7 @@ class DesktopTasksTransitionObserver(
info.changes.forEach { change ->
change.taskInfo?.let { taskInfo ->
if (
- Flags.enableDesktopWindowingPip() &&
+ DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PIP.isTrue &&
desktopRepository.isTaskMinimizedPipInDisplay(
taskInfo.displayId,
taskInfo.taskId,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 04f03361258e..0966110d2f41 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -70,6 +70,7 @@ import android.view.Choreographer;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceControl;
+import android.window.DesktopModeFlags;
import android.window.DisplayAreaInfo;
import android.window.TaskOrganizer;
import android.window.TaskSnapshot;
@@ -78,7 +79,6 @@ import android.window.WindowContainerTransaction;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.ProtoLog;
-import com.android.window.flags.Flags;
import com.android.wm.shell.R;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -781,7 +781,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
// TODO(b/377581840): Update this check to include non-minimized cases, e.g. split to PiP etc.
private boolean isPipExitingToDesktopMode() {
DesktopRepository currentRepo = getCurrentRepo();
- return Flags.enableDesktopWindowingPip() && currentRepo != null
+ return DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PIP.isTrue() && currentRepo != null
&& (currentRepo.isAnyDeskActive(mTaskInfo.displayId)
|| isDisplayInFreeform());
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
index 242f7fa5f1b1..5706f19f177a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
@@ -39,11 +39,11 @@ import android.view.InputEventReceiver;
import android.view.InputMonitor;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
+import android.window.DesktopModeFlags;
import androidx.annotation.VisibleForTesting;
import com.android.internal.policy.TaskResizingAlgorithm;
-import com.android.window.flags.Flags;
import com.android.wm.shell.R;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
@@ -183,7 +183,7 @@ public class PipResizeGestureHandler {
private void reloadResources() {
final Resources res = mContext.getResources();
mDelta = res.getDimensionPixelSize(R.dimen.pip_resize_edge_size);
- mEnableDragCornerResize = Flags.enableDesktopWindowingPip();
+ mEnableDragCornerResize = DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PIP.isTrue();
mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
index d36fc1247dad..a9df4bd1860d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
@@ -28,6 +28,7 @@ import static android.view.MotionEvent.ACTION_UP;
import android.annotation.NonNull;
import android.graphics.PointF;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
@@ -43,6 +44,8 @@ import androidx.annotation.Nullable;
* All touch events must be passed through this class to track a drag event.
*/
public class DragDetector {
+ private static final String TAG = "DragDetector";
+
private final MotionEventHandler mEventHandler;
private final PointF mInputDownPoint = new PointF();
@@ -109,8 +112,12 @@ public class DragDetector {
return mResultOfDownAction;
}
final int dragPointerIndex = ev.findPointerIndex(mDragPointerId);
+ // TODO(b/400635953): Separate the app header and its buttons'
+ // touch listeners so they're not handled by the same DragDetector.
if (dragPointerIndex == -1) {
- throw new IllegalStateException("Failed to find primary pointer!");
+ Log.w(TAG, "Invalid pointer index on ACTION_MOVE. Drag"
+ + " pointer id: " + mDragPointerId);
+ return mResultOfDownAction;
}
if (!mIsDragEvent) {
float dx = ev.getRawX(dragPointerIndex) - mInputDownPoint.x;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopRepositoryTest.kt
index 2e74d4391c63..de92d391645a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopRepositoryTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopRepositoryTest.kt
@@ -88,7 +88,7 @@ class DesktopRepositoryTest(flags: FlagsParameterization) : ShellTestCase() {
datastoreScope = CoroutineScope(Dispatchers.Unconfined + SupervisorJob())
shellInit = spy(ShellInit(testExecutor))
- repo = DesktopRepository(persistentRepository, datastoreScope, DEFAULT_USER_ID)
+ repo = spy(DesktopRepository(persistentRepository, datastoreScope, DEFAULT_USER_ID))
whenever(runBlocking { persistentRepository.readDesktop(any(), any()) })
.thenReturn(Desktop.getDefaultInstance())
shellInit.init()
@@ -1171,6 +1171,7 @@ class DesktopRepositoryTest(flags: FlagsParameterization) : ShellTestCase() {
val tasksBeforeRemoval = repo.removeDesk(deskId = DEFAULT_DISPLAY)
+ verify(repo, times(1)).notifyVisibleTaskListeners(DEFAULT_DISPLAY, visibleTasksCount = 0)
assertThat(tasksBeforeRemoval).containsExactly(1, 2, 3).inOrder()
assertThat(repo.getActiveTasks(displayId = DEFAULT_DISPLAY)).isEmpty()
}
@@ -1184,6 +1185,7 @@ class DesktopRepositoryTest(flags: FlagsParameterization) : ShellTestCase() {
repo.removeDesk(deskId = 3)
+ verify(repo, times(1)).notifyVisibleTaskListeners(DEFAULT_DISPLAY, visibleTasksCount = 0)
assertThat(repo.getDeskIds(displayId = DEFAULT_DISPLAY)).doesNotContain(3)
}
@@ -1196,6 +1198,7 @@ class DesktopRepositoryTest(flags: FlagsParameterization) : ShellTestCase() {
repo.removeDesk(deskId = 2)
+ verify(repo, times(1)).notifyVisibleTaskListeners(DEFAULT_DISPLAY, visibleTasksCount = 0)
assertThat(repo.getDeskIds(displayId = DEFAULT_DISPLAY)).doesNotContain(2)
}
@@ -1424,6 +1427,7 @@ class DesktopRepositoryTest(flags: FlagsParameterization) : ShellTestCase() {
repo.removeDesk(deskId = 1)
executor.flushAll()
+ verify(repo, times(1)).notifyVisibleTaskListeners(DEFAULT_DISPLAY, visibleTasksCount = 0)
val lastRemoval = assertNotNull(listener.lastRemoval)
assertThat(lastRemoval.displayId).isEqualTo(0)
assertThat(lastRemoval.deskId).isEqualTo(1)
@@ -1440,6 +1444,7 @@ class DesktopRepositoryTest(flags: FlagsParameterization) : ShellTestCase() {
repo.removeDesk(deskId = 2)
executor.flushAll()
+ verify(repo, times(0)).notifyVisibleTaskListeners(DEFAULT_DISPLAY, visibleTasksCount = 0)
assertThat(listener.lastRemoval).isNull()
}
@@ -1455,6 +1460,7 @@ class DesktopRepositoryTest(flags: FlagsParameterization) : ShellTestCase() {
repo.removeDesk(deskId = 1)
executor.flushAll()
+ verify(repo, times(1)).notifyVisibleTaskListeners(DEFAULT_DISPLAY, visibleTasksCount = 0)
val lastActivationChange = assertNotNull(listener.lastActivationChange)
assertThat(lastActivationChange.displayId).isEqualTo(0)
assertThat(lastActivationChange.oldActive).isEqualTo(1)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt
index 9588a5c73385..0871d38ceb46 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt
@@ -15,7 +15,6 @@ import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
-import android.view.Display.DEFAULT_DISPLAY
import android.view.SurfaceControl
import android.view.WindowManager.TRANSIT_OPEN
import android.window.TransitionInfo
@@ -785,7 +784,7 @@ class DragToDesktopTransitionHandlerTest : ShellTestCase() {
startTransaction: SurfaceControl.Transaction = mock(),
finishTransaction: SurfaceControl.Transaction = mock(),
homeChange: TransitionInfo.Change? = createHomeChange(),
- transitionRootLeash: SurfaceControl? = null,
+ transitionRootLeash: SurfaceControl = mock(),
): IBinder {
whenever(dragAnimator.position).thenReturn(PointF())
// Simulate transition is started and is ready to animate.
@@ -887,7 +886,7 @@ class DragToDesktopTransitionHandlerTest : ShellTestCase() {
type: Int,
draggedTask: RunningTaskInfo,
homeChange: TransitionInfo.Change? = createHomeChange(),
- rootLeash: SurfaceControl? = null,
+ rootLeash: SurfaceControl = mock(),
) =
TransitionInfo(type, /* flags= */ 0).apply {
homeChange?.let { addChange(it) }
@@ -904,9 +903,7 @@ class DragToDesktopTransitionHandlerTest : ShellTestCase() {
flags = flags or FLAG_IS_WALLPAPER
}
)
- if (rootLeash != null) {
- addRootLeash(DEFAULT_DISPLAY, rootLeash, /* offsetLeft= */ 0, /* offsetTop= */ 0)
- }
+ addRootLeash(draggedTask.displayId, rootLeash, /* offsetLeft= */ 0, /* offsetTop= */ 0)
}
private fun createHomeChange() =
diff --git a/packages/SettingsLib/aconfig/settingslib.aconfig b/packages/SettingsLib/aconfig/settingslib.aconfig
index a029f56cf1d7..349d13a29b05 100644
--- a/packages/SettingsLib/aconfig/settingslib.aconfig
+++ b/packages/SettingsLib/aconfig/settingslib.aconfig
@@ -37,13 +37,6 @@ flag {
}
flag {
- name: "enable_hide_exclusively_managed_bluetooth_device"
- namespace: "dck_framework"
- description: "Hide exclusively managed Bluetooth devices in BT settings menu."
- bug: "324475542"
-}
-
-flag {
name: "enable_set_preferred_transport_for_le_audio_device"
namespace: "bluetooth"
description: "Enable setting preferred transport for Le Audio device"
@@ -249,3 +242,13 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "audio_stream_media_service_by_receive_state"
+ namespace: "cross_device_experiences"
+ description: "Start or update audio stream media service by receive state"
+ bug: "398700619"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/packages/SettingsLib/res/drawable/ic_news.xml b/packages/SettingsLib/res/drawable/ic_news.xml
new file mode 100644
index 000000000000..90615ec1b8fd
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_news.xml
@@ -0,0 +1,19 @@
+<!--
+ ~ Copyright (C) 2025 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.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="14.933333dp" android:viewportHeight="14" android:viewportWidth="15" android:width="16dp">
+ <path android:fillColor="#ffffff" android:pathData="M3,10.8H11V9.6H3V10.8ZM3,8.4H5.4V4.8H3V8.4ZM12.2,13.6H1.8C1.467,13.6 1.183,13.483 0.95,13.25C0.717,13.017 0.6,12.733 0.6,12.4V3.6C0.6,3.267 0.717,2.983 0.95,2.75C1.183,2.517 1.467,2.4 1.8,2.4H6.683C6.528,2.711 6.406,3.033 6.317,3.367C6.239,3.7 6.2,4.044 6.2,4.4C6.2,4.933 6.283,5.439 6.45,5.917C6.628,6.383 6.878,6.811 7.2,7.2H6.6V8.4H8.767C9.056,8.522 9.35,8.622 9.65,8.7C9.961,8.767 10.278,8.8 10.6,8.8C11.111,8.8 11.606,8.717 12.083,8.55C12.572,8.372 13.011,8.122 13.4,7.8V12.4C13.4,12.733 13.283,13.017 13.05,13.25C12.817,13.483 12.533,13.6 12.2,13.6ZM10.6,8C10.6,7 10.25,6.15 9.55,5.45C8.85,4.75 8,4.4 7,4.4C8,4.4 8.85,4.05 9.55,3.35C10.25,2.65 10.6,1.8 10.6,0.8C10.6,1.8 10.95,2.65 11.65,3.35C12.35,4.05 13.2,4.4 14.2,4.4C13.2,4.4 12.35,4.75 11.65,5.45C10.95,6.15 10.6,7 10.6,8Z"/>
+</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_promotions.xml b/packages/SettingsLib/res/drawable/ic_promotions.xml
new file mode 100644
index 000000000000..a597ecebd967
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_promotions.xml
@@ -0,0 +1,19 @@
+<!--
+ ~ Copyright (C) 2025 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.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="16dp" android:viewportHeight="15" android:viewportWidth="13" android:width="13.866667dp">
+ <path android:fillColor="#ffffff" android:pathData="M1.4,13.4C1.067,13.4 0.783,13.283 0.55,13.05C0.317,12.817 0.2,12.533 0.2,12.2V4.6C0.2,4.267 0.317,3.983 0.55,3.75C0.783,3.517 1.067,3.4 1.4,3.4H2.6V3.133C2.6,2.467 2.822,1.878 3.267,1.367C3.722,0.856 4.3,0.6 5,0.6C5.667,0.6 6.233,0.833 6.7,1.3C7.167,1.767 7.4,2.333 7.4,3V3.4H8.6C8.933,3.4 9.217,3.517 9.45,3.75C9.683,3.983 9.8,4.267 9.8,4.6V6.367C9.611,6.311 9.417,6.272 9.217,6.25C9.017,6.217 8.811,6.2 8.6,6.2C7.378,6.2 6.339,6.628 5.483,7.483C4.628,8.339 4.2,9.378 4.2,10.6C4.2,11.111 4.283,11.611 4.45,12.1C4.628,12.578 4.878,13.011 5.2,13.4H1.4ZM8.6,14.2C8.6,13.2 8.25,12.35 7.55,11.65C6.85,10.95 6,10.6 5,10.6C6,10.6 6.85,10.25 7.55,9.55C8.25,8.85 8.6,8 8.6,7C8.6,8 8.95,8.85 9.65,9.55C10.35,10.25 11.2,10.6 12.2,10.6C11.2,10.6 10.35,10.95 9.65,11.65C8.95,12.35 8.6,13.2 8.6,14.2ZM3.8,3.4H6.2V3C6.2,2.667 6.083,2.383 5.85,2.15C5.617,1.917 5.333,1.8 5,1.8C4.667,1.8 4.383,1.917 4.15,2.15C3.917,2.383 3.8,2.667 3.8,3V3.4ZM3.2,5.8C3.367,5.8 3.506,5.744 3.617,5.633C3.739,5.511 3.8,5.367 3.8,5.2V4.6H2.6V5.2C2.6,5.367 2.656,5.511 2.767,5.633C2.889,5.744 3.033,5.8 3.2,5.8ZM6.8,5.8C6.967,5.8 7.106,5.744 7.217,5.633C7.339,5.511 7.4,5.367 7.4,5.2V4.6H6.2V5.2C6.2,5.367 6.256,5.511 6.367,5.633C6.489,5.744 6.633,5.8 6.8,5.8Z"/>
+</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_recs.xml b/packages/SettingsLib/res/drawable/ic_recs.xml
new file mode 100644
index 000000000000..034ff9e221b0
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_recs.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ Copyright (C) 2025 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.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="14dp"
+ android:height="16dp"
+ android:viewportWidth="14"
+ android:viewportHeight="16">
+ <path
+ android:pathData="M6,15.2L3.6,12.8H1.6C1.278,12.8 0.994,12.683 0.75,12.45C0.517,12.206 0.4,11.922 0.4,11.6V2.8C0.4,2.478 0.517,2.2 0.75,1.967C0.994,1.722 1.278,1.6 1.6,1.6H6.2C5.878,1.989 5.628,2.428 5.45,2.917C5.283,3.394 5.2,3.889 5.2,4.4C5.2,5.622 5.628,6.661 6.483,7.517C7.339,8.372 8.378,8.8 9.6,8.8C9.956,8.8 10.3,8.761 10.633,8.683C10.967,8.594 11.289,8.472 11.6,8.317V11.6C11.6,11.922 11.483,12.206 11.25,12.45C11.017,12.683 10.733,12.8 10.4,12.8H8.4L6,15.2ZM9.6,8C9.6,7 9.25,6.15 8.55,5.45C7.85,4.75 7,4.4 6,4.4C7,4.4 7.85,4.05 8.55,3.35C9.25,2.65 9.6,1.8 9.6,0.8C9.6,1.8 9.95,2.65 10.65,3.35C11.35,4.05 12.2,4.4 13.2,4.4C12.2,4.4 11.35,4.75 10.65,5.45C9.95,6.15 9.6,7 9.6,8Z"
+ android:fillColor="#ffffff"/>
+</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_social.xml b/packages/SettingsLib/res/drawable/ic_social.xml
new file mode 100644
index 000000000000..01974319b441
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_social.xml
@@ -0,0 +1,19 @@
+<!--
+ ~ Copyright (C) 2025 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.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="16dp" android:viewportHeight="15" android:viewportWidth="15" android:width="16dp">
+ <path android:fillColor="#ffffff" android:pathData="M0.6,14.4V12.733C0.6,12.411 0.678,12.117 0.833,11.85C0.989,11.583 1.211,11.378 1.5,11.233C2.056,10.956 2.628,10.75 3.217,10.617C3.817,10.472 4.428,10.4 5.05,10.4C5.661,10.4 6.256,10.472 6.833,10.617C7.422,10.75 7.989,10.956 8.533,11.233C8.811,11.378 9.028,11.583 9.183,11.85C9.339,12.117 9.417,12.411 9.417,12.733V14.4H0.6ZM10.6,14.4V12.617C10.6,12.183 10.494,11.778 10.283,11.4C10.072,11.022 9.772,10.733 9.383,10.533C9.772,10.6 10.144,10.7 10.5,10.833C10.856,10.956 11.206,11.106 11.55,11.283C11.828,11.439 12.072,11.628 12.283,11.85C12.494,12.061 12.6,12.317 12.6,12.617V14.4H10.6ZM5.2,9.6C4.589,9.6 4.067,9.389 3.633,8.967C3.211,8.533 3,8.011 3,7.4C3,6.789 3.211,6.272 3.633,5.85C4.067,5.417 4.589,5.2 5.2,5.2C5.811,5.2 6.328,5.417 6.75,5.85C7.183,6.272 7.4,6.789 7.4,7.4C7.4,8.011 7.183,8.533 6.75,8.967C6.328,9.389 5.811,9.6 5.2,9.6ZM10.6,7.4C10.6,8.011 10.383,8.533 9.95,8.967C9.528,9.389 9.011,9.6 8.4,9.6C8.311,9.6 8.217,9.594 8.117,9.583C8.017,9.572 7.922,9.55 7.833,9.517C8.089,9.206 8.278,8.872 8.4,8.517C8.533,8.161 8.6,7.789 8.6,7.4C8.6,7.011 8.533,6.639 8.4,6.283C8.278,5.928 8.089,5.594 7.833,5.283C7.922,5.25 8.017,5.228 8.117,5.217C8.217,5.206 8.311,5.2 8.4,5.2C9.011,5.2 9.528,5.417 9.95,5.85C10.383,6.272 10.6,6.789 10.6,7.4ZM11.4,6.4C11.4,5.622 11.128,4.961 10.583,4.417C10.039,3.872 9.378,3.6 8.6,3.6C9.378,3.6 10.039,3.328 10.583,2.783C11.128,2.239 11.4,1.578 11.4,0.8C11.4,1.578 11.672,2.239 12.217,2.783C12.761,3.328 13.422,3.6 14.2,3.6C13.422,3.6 12.761,3.872 12.217,4.417C11.672,4.961 11.4,5.622 11.4,6.4Z"/>
+</vector>
diff --git a/packages/SystemUI/aconfig/predictive_back.aconfig b/packages/SystemUI/aconfig/predictive_back.aconfig
index ee918c275b7b..89a0d895a17c 100644
--- a/packages/SystemUI/aconfig/predictive_back.aconfig
+++ b/packages/SystemUI/aconfig/predictive_back.aconfig
@@ -7,3 +7,10 @@ flag {
description: "Enable Shade Animations"
bug: "327732946"
}
+
+flag {
+ name: "predictive_back_delay_transition"
+ namespace: "systemui"
+ description: "Slightly delays the back transition start"
+ bug: "301195601"
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PagerDots.kt b/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/PagerDots.kt
index 91f1477d5325..172d88af4cc8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PagerDots.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/PagerDots.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.qs.panels.ui.compose
+package com.android.systemui.common.ui.compose
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.Canvas
@@ -43,9 +43,9 @@ import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
+import com.android.app.tracing.coroutines.launchTraced as launch
import kotlin.math.absoluteValue
import kotlinx.coroutines.CoroutineScope
-import com.android.app.tracing.coroutines.launchTraced as launch
import platform.test.motion.compose.values.MotionTestValueKey
import platform.test.motion.compose.values.motionTestValues
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
index 4e1aab58ac24..3150e94908cd 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
@@ -182,7 +182,7 @@ fun CommunalContainer(
viewModel.communalBackground.collectAsStateWithLifecycle(
initialValue = CommunalBackgroundType.ANIMATED
)
- val swipeToHubEnabled by viewModel.swipeToHubEnabled.collectAsStateWithLifecycle()
+ val swipeToHubEnabled by viewModel.swipeToHubEnabled.collectAsStateWithLifecycle(false)
val state: MutableSceneTransitionLayoutState =
rememberMutableSceneTransitionLayoutState(
initialScene = currentSceneKey,
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
index 9bb3bac824e9..365567b17ec0 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
@@ -17,7 +17,6 @@ import android.content.Context
import android.content.res.Resources
import android.graphics.Color
import android.graphics.Rect
-import android.graphics.RectF
import android.icu.text.NumberFormat
import android.util.TypedValue
import android.view.LayoutInflater
@@ -29,6 +28,7 @@ import com.android.systemui.plugins.clocks.AlarmData
import com.android.systemui.plugins.clocks.ClockAnimations
import com.android.systemui.plugins.clocks.ClockConfig
import com.android.systemui.plugins.clocks.ClockController
+import com.android.systemui.plugins.clocks.ClockEventListener
import com.android.systemui.plugins.clocks.ClockEvents
import com.android.systemui.plugins.clocks.ClockFaceConfig
import com.android.systemui.plugins.clocks.ClockFaceController
@@ -102,7 +102,7 @@ class DefaultClockController(
isDarkTheme: Boolean,
dozeFraction: Float,
foldFraction: Float,
- onBoundsChanged: (RectF) -> Unit,
+ clockListener: ClockEventListener?,
) {
largeClock.recomputePadding(null)
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockController.kt
index 6dfd2268005f..5acd4468fe92 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockController.kt
@@ -16,13 +16,13 @@
package com.android.systemui.shared.clocks
-import android.graphics.RectF
import com.android.systemui.animation.GSFAxes
import com.android.systemui.customization.R
import com.android.systemui.plugins.clocks.AlarmData
import com.android.systemui.plugins.clocks.AxisType
import com.android.systemui.plugins.clocks.ClockConfig
import com.android.systemui.plugins.clocks.ClockController
+import com.android.systemui.plugins.clocks.ClockEventListener
import com.android.systemui.plugins.clocks.ClockEvents
import com.android.systemui.plugins.clocks.ClockFontAxis
import com.android.systemui.plugins.clocks.ClockFontAxis.Companion.merge
@@ -107,11 +107,11 @@ class FlexClockController(private val clockCtx: ClockContext) : ClockController
isDarkTheme: Boolean,
dozeFraction: Float,
foldFraction: Float,
- onBoundsChanged: (RectF) -> Unit,
+ clockListener: ClockEventListener?,
) {
events.onFontAxesChanged(clockCtx.settings.axes)
smallClock.run {
- layerController.onViewBoundsChanged = onBoundsChanged
+ layerController.onViewBoundsChanged = { clockListener?.onBoundsChanged(it) }
events.onThemeChanged(theme.copy(isDarkTheme = isDarkTheme))
animations.doze(dozeFraction)
animations.fold(foldFraction)
@@ -119,7 +119,7 @@ class FlexClockController(private val clockCtx: ClockContext) : ClockController
}
largeClock.run {
- layerController.onViewBoundsChanged = onBoundsChanged
+ layerController.onViewBoundsChanged = { clockListener?.onBoundsChanged(it) }
events.onThemeChanged(theme.copy(isDarkTheme = isDarkTheme))
animations.doze(dozeFraction)
animations.fold(foldFraction)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/clipboardoverlay/ActionIntentCreatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/clipboardoverlay/ActionIntentCreatorTest.kt
new file mode 100644
index 000000000000..239e02640908
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/clipboardoverlay/ActionIntentCreatorTest.kt
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2025 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.systemui.clipboardoverlay
+
+import android.content.ClipData
+import android.content.ComponentName
+import android.content.Intent
+import android.net.Uri
+import android.text.SpannableString
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.res.R
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ActionIntentCreatorTest : SysuiTestCase() {
+ val creator = ActionIntentCreator()
+
+ @Test
+ fun test_getTextEditorIntent() {
+ val intent = creator.getTextEditorIntent(context)
+ assertEquals(ComponentName(context, EditTextActivity::class.java), intent.component)
+ assertFlags(intent, Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ }
+
+ @Test
+ fun test_getRemoteCopyIntent() {
+ context.getOrCreateTestableResources().addOverride(R.string.config_remoteCopyPackage, "")
+
+ val clipData = ClipData.newPlainText("Test", "Test Item")
+ var intent = creator.getRemoteCopyIntent(clipData, context)
+
+ assertEquals(null, intent.component)
+ assertFlags(intent, EXTERNAL_INTENT_FLAGS)
+ assertEquals(clipData, intent.clipData)
+
+ // Try again with a remote copy component
+ val fakeComponent =
+ ComponentName("com.android.remotecopy", "com.android.remotecopy.RemoteCopyActivity")
+ context
+ .getOrCreateTestableResources()
+ .addOverride(R.string.config_remoteCopyPackage, fakeComponent.flattenToString())
+
+ intent = creator.getRemoteCopyIntent(clipData, context)
+ assertEquals(fakeComponent, intent.component)
+ }
+
+ @Test
+ fun test_getImageEditIntent() {
+ context.getOrCreateTestableResources().addOverride(R.string.config_screenshotEditor, "")
+ val fakeUri = Uri.parse("content://foo")
+ var intent = creator.getImageEditIntent(fakeUri, context)
+
+ assertEquals(Intent.ACTION_EDIT, intent.action)
+ assertEquals("image/*", intent.type)
+ assertEquals(null, intent.component)
+ assertEquals("clipboard", intent.getStringExtra("edit_source"))
+ assertFlags(intent, EXTERNAL_INTENT_FLAGS)
+
+ // try again with an editor component
+ val fakeComponent =
+ ComponentName("com.android.remotecopy", "com.android.remotecopy.RemoteCopyActivity")
+ context
+ .getOrCreateTestableResources()
+ .addOverride(R.string.config_screenshotEditor, fakeComponent.flattenToString())
+ intent = creator.getImageEditIntent(fakeUri, context)
+ assertEquals(fakeComponent, intent.component)
+ }
+
+ @Test
+ fun test_getShareIntent_plaintext() {
+ val clipData = ClipData.newPlainText("Test", "Test Item")
+ val intent = creator.getShareIntent(clipData, context)
+
+ assertEquals(Intent.ACTION_CHOOSER, intent.action)
+ assertFlags(intent, EXTERNAL_INTENT_FLAGS)
+ val target = intent.getParcelableExtra(Intent.EXTRA_INTENT, Intent::class.java)
+ assertEquals("Test Item", target?.getStringExtra(Intent.EXTRA_TEXT))
+ assertEquals("text/plain", target?.type)
+ }
+
+ @Test
+ fun test_getShareIntent_html() {
+ val clipData = ClipData.newHtmlText("Test", "Some HTML", "<b>Some HTML</b>")
+ val intent = creator.getShareIntent(clipData, getContext())
+
+ assertEquals(Intent.ACTION_CHOOSER, intent.action)
+ assertFlags(intent, EXTERNAL_INTENT_FLAGS)
+ val target = intent.getParcelableExtra(Intent.EXTRA_INTENT, Intent::class.java)
+ assertEquals("Some HTML", target?.getStringExtra(Intent.EXTRA_TEXT))
+ assertEquals("text/plain", target?.type)
+ }
+
+ @Test
+ fun test_getShareIntent_image() {
+ val uri = Uri.parse("content://something")
+ val clipData = ClipData("Test", arrayOf("image/png"), ClipData.Item(uri))
+ val intent = creator.getShareIntent(clipData, context)
+
+ assertEquals(Intent.ACTION_CHOOSER, intent.action)
+ assertFlags(intent, EXTERNAL_INTENT_FLAGS)
+ val target = intent.getParcelableExtra(Intent.EXTRA_INTENT, Intent::class.java)
+ assertEquals(uri, target?.getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java))
+ assertEquals(uri, target?.clipData?.getItemAt(0)?.uri)
+ assertEquals("image/png", target?.type)
+ }
+
+ @Test
+ fun test_getShareIntent_spannableText() {
+ val clipData = ClipData.newPlainText("Test", SpannableString("Test Item"))
+ val intent = creator.getShareIntent(clipData, context)
+
+ assertEquals(Intent.ACTION_CHOOSER, intent.action)
+ assertFlags(intent, EXTERNAL_INTENT_FLAGS)
+ val target = intent.getParcelableExtra(Intent.EXTRA_INTENT, Intent::class.java)
+ assertEquals("Test Item", target?.getStringExtra(Intent.EXTRA_TEXT))
+ assertEquals("text/plain", target?.type)
+ }
+
+ // Assert that the given flags are set
+ private fun assertFlags(intent: Intent, flags: Int) {
+ assertTrue((intent.flags and flags) == flags)
+ }
+
+ companion object {
+ private const val EXTERNAL_INTENT_FLAGS: Int =
+ (Intent.FLAG_ACTIVITY_NEW_TASK or
+ Intent.FLAG_ACTIVITY_CLEAR_TASK or
+ Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/clipboardoverlay/IntentCreatorTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/clipboardoverlay/DefaultIntentCreatorTest.java
index ea6cb3b6d178..126b3fa9e7ca 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/clipboardoverlay/IntentCreatorTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/clipboardoverlay/DefaultIntentCreatorTest.java
@@ -36,13 +36,15 @@ import org.junit.runner.RunWith;
@SmallTest
@RunWith(AndroidJUnit4.class)
-public class IntentCreatorTest extends SysuiTestCase {
+public class DefaultIntentCreatorTest extends SysuiTestCase {
private static final int EXTERNAL_INTENT_FLAGS = Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION;
+ private final DefaultIntentCreator mIntentCreator = new DefaultIntentCreator();
+
@Test
public void test_getTextEditorIntent() {
- Intent intent = IntentCreator.getTextEditorIntent(getContext());
+ Intent intent = mIntentCreator.getTextEditorIntent(getContext());
assertEquals(new ComponentName(getContext(), EditTextActivity.class),
intent.getComponent());
assertFlags(intent, Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
@@ -54,7 +56,7 @@ public class IntentCreatorTest extends SysuiTestCase {
"");
ClipData clipData = ClipData.newPlainText("Test", "Test Item");
- Intent intent = IntentCreator.getRemoteCopyIntent(clipData, getContext());
+ Intent intent = mIntentCreator.getRemoteCopyIntent(clipData, getContext());
assertEquals(null, intent.getComponent());
assertFlags(intent, EXTERNAL_INTENT_FLAGS);
@@ -66,7 +68,7 @@ public class IntentCreatorTest extends SysuiTestCase {
getContext().getOrCreateTestableResources().addOverride(R.string.config_remoteCopyPackage,
fakeComponent.flattenToString());
- intent = IntentCreator.getRemoteCopyIntent(clipData, getContext());
+ intent = mIntentCreator.getRemoteCopyIntent(clipData, getContext());
assertEquals(fakeComponent, intent.getComponent());
}
@@ -75,7 +77,7 @@ public class IntentCreatorTest extends SysuiTestCase {
getContext().getOrCreateTestableResources().addOverride(R.string.config_screenshotEditor,
"");
Uri fakeUri = Uri.parse("content://foo");
- Intent intent = IntentCreator.getImageEditIntent(fakeUri, getContext());
+ Intent intent = mIntentCreator.getImageEditIntent(fakeUri, getContext());
assertEquals(Intent.ACTION_EDIT, intent.getAction());
assertEquals("image/*", intent.getType());
@@ -88,14 +90,14 @@ public class IntentCreatorTest extends SysuiTestCase {
"com.android.remotecopy.RemoteCopyActivity");
getContext().getOrCreateTestableResources().addOverride(R.string.config_screenshotEditor,
fakeComponent.flattenToString());
- intent = IntentCreator.getImageEditIntent(fakeUri, getContext());
+ intent = mIntentCreator.getImageEditIntent(fakeUri, getContext());
assertEquals(fakeComponent, intent.getComponent());
}
@Test
public void test_getShareIntent_plaintext() {
ClipData clipData = ClipData.newPlainText("Test", "Test Item");
- Intent intent = IntentCreator.getShareIntent(clipData, getContext());
+ Intent intent = mIntentCreator.getShareIntent(clipData, getContext());
assertEquals(Intent.ACTION_CHOOSER, intent.getAction());
assertFlags(intent, EXTERNAL_INTENT_FLAGS);
@@ -108,7 +110,7 @@ public class IntentCreatorTest extends SysuiTestCase {
public void test_getShareIntent_html() {
ClipData clipData = ClipData.newHtmlText("Test", "Some HTML",
"<b>Some HTML</b>");
- Intent intent = IntentCreator.getShareIntent(clipData, getContext());
+ Intent intent = mIntentCreator.getShareIntent(clipData, getContext());
assertEquals(Intent.ACTION_CHOOSER, intent.getAction());
assertFlags(intent, EXTERNAL_INTENT_FLAGS);
@@ -122,7 +124,7 @@ public class IntentCreatorTest extends SysuiTestCase {
Uri uri = Uri.parse("content://something");
ClipData clipData = new ClipData("Test", new String[]{"image/png"},
new ClipData.Item(uri));
- Intent intent = IntentCreator.getShareIntent(clipData, getContext());
+ Intent intent = mIntentCreator.getShareIntent(clipData, getContext());
assertEquals(Intent.ACTION_CHOOSER, intent.getAction());
assertFlags(intent, EXTERNAL_INTENT_FLAGS);
@@ -135,7 +137,7 @@ public class IntentCreatorTest extends SysuiTestCase {
@Test
public void test_getShareIntent_spannableText() {
ClipData clipData = ClipData.newPlainText("Test", new SpannableString("Test Item"));
- Intent intent = IntentCreator.getShareIntent(clipData, getContext());
+ Intent intent = mIntentCreator.getShareIntent(clipData, getContext());
assertEquals(Intent.ACTION_CHOOSER, intent.getAction());
assertFlags(intent, EXTERNAL_INTENT_FLAGS);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
index f47aa6b3dc03..8dc7a331dc2d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
@@ -32,6 +32,8 @@ import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_DIRECT_EDIT_MODE
import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
+import com.android.systemui.common.data.repository.batteryRepository
+import com.android.systemui.common.data.repository.fake
import com.android.systemui.communal.data.model.CommunalSmartspaceTimer
import com.android.systemui.communal.data.repository.FakeCommunalMediaRepository
import com.android.systemui.communal.data.repository.FakeCommunalSceneRepository
@@ -48,6 +50,7 @@ import com.android.systemui.communal.domain.interactor.communalInteractor
import com.android.systemui.communal.domain.interactor.communalSceneInteractor
import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
import com.android.systemui.communal.domain.interactor.communalTutorialInteractor
+import com.android.systemui.communal.domain.interactor.setCommunalV2ConfigEnabled
import com.android.systemui.communal.domain.model.CommunalContentModel
import com.android.systemui.communal.shared.log.CommunalMetricsLogger
import com.android.systemui.communal.shared.model.CommunalContentSize
@@ -73,6 +76,8 @@ import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.keyguard.ui.transitions.blurConfig
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
import com.android.systemui.log.logcatLogBuffer
@@ -96,6 +101,7 @@ import com.android.systemui.statusbar.KeyguardIndicationController
import com.android.systemui.testKosmos
import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.user.data.repository.fakeUserRepository
+import com.android.systemui.util.settings.fakeSettings
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.advanceTimeBy
@@ -940,6 +946,36 @@ class CommunalViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
assertThat(isUiBlurred).isFalse()
}
+ @Test
+ @EnableFlags(FLAG_GLANCEABLE_HUB_V2)
+ fun swipeToCommunal() =
+ kosmos.runTest {
+ setCommunalV2ConfigEnabled(true)
+ val mainUser = fakeUserRepository.asMainUser()
+ fakeKeyguardRepository.setKeyguardShowing(true)
+ fakeUserRepository.setUserUnlocked(mainUser.id, true)
+ fakeUserTracker.set(userInfos = listOf(mainUser), selectedUserIndex = 0)
+ fakeSettings.putIntForUser(
+ Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
+ 1,
+ mainUser.id,
+ )
+
+ val viewModel = createViewModel()
+ val swipeToHubEnabled by collectLastValue(viewModel.swipeToHubEnabled)
+ assertThat(swipeToHubEnabled).isFalse()
+
+ batteryRepository.fake.setDevicePluggedIn(true)
+ assertThat(swipeToHubEnabled).isTrue()
+
+ keyguardTransitionRepository.sendTransitionStep(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.AOD,
+ transitionState = TransitionState.STARTED,
+ )
+ assertThat(swipeToHubEnabled).isFalse()
+ }
+
private suspend fun setIsMainUser(isMainUser: Boolean) {
val user = if (isMainUser) MAIN_USER_INFO else SECONDARY_USER_INFO
with(userRepository) {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/PerDisplayInstanceRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/PerDisplayInstanceRepositoryImplTest.kt
index 299105e2dabd..e41d46ce90af 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/PerDisplayInstanceRepositoryImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/PerDisplayInstanceRepositoryImplTest.kt
@@ -20,6 +20,7 @@ import android.view.Display
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.dumpManager
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.testKosmos
@@ -29,6 +30,9 @@ import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.verify
@RunWith(AndroidJUnit4::class)
@SmallTest
@@ -99,6 +103,11 @@ class PerDisplayInstanceRepositoryImplTest : SysuiTestCase() {
assertThat(fakePerDisplayInstanceProviderWithTeardown.destroyed).isEmpty()
}
+ @Test
+ fun start_registersDumpable() {
+ verify(kosmos.dumpManager).registerNormalDumpable(anyString(), eq(underTest))
+ }
+
private fun createDisplay(displayId: Int): Display =
display(type = Display.TYPE_INTERNAL, id = displayId)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
index 2c852c3f6185..94db429c2225 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -598,7 +598,8 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
mKeyguardClockPositionAlgorithm,
mMSDLPlayer,
mBrightnessMirrorShowingRepository,
- new BlurConfig(0f, 0f));
+ new BlurConfig(0f, 0f),
+ () -> mKosmos.getFakeShadeDisplaysRepository());
mNotificationPanelViewController.initDependencies(
mCentralSurfaces,
null,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index f54c36754d31..89263fc42739 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -195,9 +195,7 @@ public class NotificationPanelViewControllerTest extends NotificationPanelViewCo
@EnableFlags(Flags.FLAG_SHADE_WINDOW_GOES_AROUND)
public void updateSystemUiStateFlags_updatesSysuiStateInteractor() {
var DISPLAY_ID = 10;
- var displayMock = display(TYPE_INTERNAL, /* flags= */ 0, /* id= */DISPLAY_ID,
- /* state= */ null);
- when(mView.getDisplay()).thenReturn(displayMock);
+ mKosmos.getFakeShadeDisplaysRepository().setPendingDisplayId(DISPLAY_ID);
mNotificationPanelViewController.updateSystemUiStateFlags();
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
index 4f301031e77c..fad66581682f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
@@ -108,7 +108,7 @@ class DefaultClockProviderTest : SysuiTestCase() {
verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA)
verify(mockLargeClockView).setColors(DOZE_COLOR, Color.MAGENTA)
- clock.initialize(true, 0f, 0f, {})
+ clock.initialize(true, 0f, 0f, null)
val expectedColor = 0
verify(mockSmallClockView).setColors(DOZE_COLOR, expectedColor)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt
index 4bd02e0fab22..17509dc6a80f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt
@@ -19,6 +19,10 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class ConditionExtensionsTest : SysuiTestCase() {
private lateinit var testScope: TestScope
+ private val testCallback =
+ Condition.Callback {
+ // This is a no-op
+ }
@Before
fun setUp() {
@@ -33,7 +37,7 @@ class ConditionExtensionsTest : SysuiTestCase() {
assertThat(condition.isConditionSet).isFalse()
- condition.start()
+ condition.testStart()
assertThat(condition.isConditionSet).isTrue()
assertThat(condition.isConditionMet).isTrue()
}
@@ -46,7 +50,7 @@ class ConditionExtensionsTest : SysuiTestCase() {
assertThat(condition.isConditionSet).isFalse()
- condition.start()
+ condition.testStart()
assertThat(condition.isConditionSet).isTrue()
assertThat(condition.isConditionMet).isFalse()
}
@@ -56,7 +60,7 @@ class ConditionExtensionsTest : SysuiTestCase() {
testScope.runTest {
val flow = emptyFlow<Boolean>()
val condition = flow.toCondition(scope = this, Condition.START_EAGERLY)
- condition.start()
+ condition.testStop()
assertThat(condition.isConditionSet).isFalse()
assertThat(condition.isConditionMet).isFalse()
@@ -72,7 +76,7 @@ class ConditionExtensionsTest : SysuiTestCase() {
strategy = Condition.START_EAGERLY,
initialValue = true,
)
- condition.start()
+ condition.testStart()
assertThat(condition.isConditionSet).isTrue()
assertThat(condition.isConditionMet).isTrue()
@@ -88,7 +92,7 @@ class ConditionExtensionsTest : SysuiTestCase() {
strategy = Condition.START_EAGERLY,
initialValue = false,
)
- condition.start()
+ condition.testStart()
assertThat(condition.isConditionSet).isTrue()
assertThat(condition.isConditionMet).isFalse()
@@ -99,7 +103,7 @@ class ConditionExtensionsTest : SysuiTestCase() {
testScope.runTest {
val flow = MutableStateFlow(false)
val condition = flow.toCondition(scope = this, strategy = Condition.START_EAGERLY)
- condition.start()
+ condition.testStart()
assertThat(condition.isConditionSet).isTrue()
assertThat(condition.isConditionMet).isFalse()
@@ -110,7 +114,7 @@ class ConditionExtensionsTest : SysuiTestCase() {
flow.value = false
assertThat(condition.isConditionMet).isFalse()
- condition.stop()
+ condition.testStop()
}
@Test
@@ -120,10 +124,18 @@ class ConditionExtensionsTest : SysuiTestCase() {
val condition = flow.toCondition(scope = this, strategy = Condition.START_EAGERLY)
assertThat(flow.subscriptionCount.value).isEqualTo(0)
- condition.start()
+ condition.testStart()
assertThat(flow.subscriptionCount.value).isEqualTo(1)
- condition.stop()
+ condition.testStop()
assertThat(flow.subscriptionCount.value).isEqualTo(0)
}
+
+ fun Condition.testStart() {
+ addCallback(testCallback)
+ }
+
+ fun Condition.testStop() {
+ removeCallback(testCallback)
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/FakeCondition.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/FakeCondition.java
index 5416536305fc..da660e2f6009 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/FakeCondition.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/FakeCondition.java
@@ -40,7 +40,7 @@ public class FakeCondition extends Condition {
}
@Override
- protected int getStartStrategy() {
+ public int getStartStrategy() {
return START_EAGERLY;
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt
index 0f1cdac05f7a..fdc6657acd1d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt
@@ -31,6 +31,8 @@ import com.android.systemui.kosmos.testScope
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
+import com.android.systemui.shade.domain.interactor.enableDualShade
+import com.android.systemui.shade.domain.interactor.enableSingleShade
import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds
import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimShape
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationTransitionThresholds.EXPANSION_FOR_DELAYED_STACK_FADE_IN
@@ -69,6 +71,7 @@ class NotificationStackAppearanceIntegrationTest : SysuiTestCase() {
@Test
fun updateBounds() =
testScope.runTest {
+ kosmos.enableSingleShade()
val radius = MutableStateFlow(32)
val leftOffset = MutableStateFlow(0)
val shape by
@@ -106,7 +109,7 @@ class NotificationStackAppearanceIntegrationTest : SysuiTestCase() {
)
)
- // When: QuickSettings shows up full screen
+ // When: QuickSettings shows up full screen on single shade.
fakeKeyguardRepository.setStatusBarState(StatusBarState.SHADE)
val transitionState =
MutableStateFlow<ObservableTransitionState>(
@@ -115,6 +118,10 @@ class NotificationStackAppearanceIntegrationTest : SysuiTestCase() {
sceneInteractor.setTransitionState(transitionState)
// Then: shape is null
assertThat(shape).isNull()
+
+ // Same scenario on Dual Shade, shape should have clipping bounds
+ kosmos.enableDualShade()
+ assertThat(shape).isNotNull()
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt
index 216fd2d54a1e..3116143504eb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt
@@ -57,7 +57,8 @@ class PromotedNotificationContentExtractorImplTest : SysuiTestCase() {
private val underTest = kosmos.promotedNotificationContentExtractor
private val systemClock = kosmos.fakeSystemClock
- private val rowImageInflater = RowImageInflater.newInstance(previousIndex = null)
+ private val rowImageInflater =
+ RowImageInflater.newInstance(previousIndex = null, reinflating = false)
private val imageModelProvider by lazy { rowImageInflater.useForContentModel() }
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt
index ce3aee1d88d2..31413b06e5fd 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt
@@ -41,7 +41,6 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTIO
import com.android.systemui.statusbar.NotificationLockscreenUserManager.RedactionType
import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
import com.android.systemui.statusbar.notification.ConversationNotificationProcessor
-import com.android.systemui.statusbar.notification.collection.EntryAdapter
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.promoted.FakePromotedNotificationContentExtractor
import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUi
@@ -204,7 +203,7 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() {
val result =
NotificationRowContentBinderImpl.InflationProgress(
packageContext = mContext,
- rowImageInflater = RowImageInflater.newInstance(null),
+ rowImageInflater = RowImageInflater.newInstance(null, reinflating = false),
remoteViews = NewRemoteViews(),
contentModel = NotificationContentModel(headsUpStatusBarModel),
promotedContent = null,
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockController.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockController.kt
index 4c1f6450dd78..b52db83d513c 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockController.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockController.kt
@@ -42,9 +42,13 @@ interface ClockController {
isDarkTheme: Boolean,
dozeFraction: Float,
foldFraction: Float,
- onBoundsChanged: (RectF) -> Unit,
+ clockListener: ClockEventListener?,
)
/** Optional method for dumping debug information */
fun dump(pw: PrintWriter)
}
+
+interface ClockEventListener {
+ fun onBoundsChanged(bounds: RectF)
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/DisplaySpecific.kt b/packages/SystemUI/pods/com/android/systemui/dagger/qualifiers/DisplaySpecific.kt
index 3e39ae9a3fe5..0c46e0784a31 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/DisplaySpecific.kt
+++ b/packages/SystemUI/pods/com/android/systemui/dagger/qualifiers/DisplaySpecific.kt
@@ -18,4 +18,7 @@ package com.android.systemui.dagger.qualifiers
import javax.inject.Qualifier
/** Annotates a class that is display specific. */
-@Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class DisplaySpecific
+@Qualifier
+@MustBeDocumented
+@Retention(AnnotationRetention.RUNTIME)
+public annotation class DisplaySpecific
diff --git a/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/Main.java b/packages/SystemUI/pods/com/android/systemui/dagger/qualifiers/Main.java
index 7b097740ff11..7b097740ff11 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/Main.java
+++ b/packages/SystemUI/pods/com/android/systemui/dagger/qualifiers/Main.java
diff --git a/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/UiBackground.java b/packages/SystemUI/pods/com/android/systemui/dagger/qualifiers/UiBackground.java
index 3d37468c322a..3d37468c322a 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/UiBackground.java
+++ b/packages/SystemUI/pods/com/android/systemui/dagger/qualifiers/UiBackground.java
diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp
index ae3a76e2d2ca..8d7cab41ea20 100644
--- a/packages/SystemUI/shared/Android.bp
+++ b/packages/SystemUI/shared/Android.bp
@@ -51,6 +51,7 @@ android_library {
":wm_shell-shared-aidls",
],
static_libs: [
+ "com.android.systemui.dagger-api",
"BiometricsSharedLib",
"PlatformAnimationLib",
"PluginCoreLib",
diff --git a/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/Tracing.kt b/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/Tracing.kt
deleted file mode 100644
index 9b7cd704aa2f..000000000000
--- a/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/Tracing.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.systemui.dagger.qualifiers
-
-import javax.inject.Qualifier
-
-@Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class Tracing
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/CombinedCondition.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/CombinedCondition.kt
index a2b6e2cf9ae3..f276a82baaef 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/CombinedCondition.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/CombinedCondition.kt
@@ -41,7 +41,7 @@ class CombinedCondition
constructor(
private val scope: CoroutineScope,
private val conditions: Collection<Condition>,
- @Evaluator.ConditionOperand private val operand: Int
+ @Evaluator.ConditionOperand private val operand: Int,
) : Condition(scope, null, false) {
private var job: Job? = null
@@ -54,7 +54,7 @@ constructor(
lazilyEvaluate(
conditions = groupedConditions.getOrDefault(true, emptyList()),
- filterUnknown = true
+ filterUnknown = true,
)
.distinctUntilChanged()
.flatMapLatest { overriddenValue ->
@@ -62,7 +62,7 @@ constructor(
if (overriddenValue == null) {
lazilyEvaluate(
conditions = groupedConditions.getOrDefault(false, emptyList()),
- filterUnknown = false
+ filterUnknown = false,
)
} else {
flowOf(overriddenValue)
@@ -188,7 +188,6 @@ constructor(
return startStrategy
}
- override fun getStartStrategy(): Int {
- return _startStrategy
- }
+ override val startStrategy: Int
+ get() = _startStrategy
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.java b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.java
deleted file mode 100644
index 670feeba6e8a..000000000000
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.java
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2022 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.systemui.shared.condition;
-
-import android.util.Log;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleEventObserver;
-import androidx.lifecycle.LifecycleOwner;
-
-import kotlinx.coroutines.CoroutineScope;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Base class for a condition that needs to be fulfilled in order for {@link Monitor} to inform
- * its callbacks.
- */
-public abstract class Condition {
- private final String mTag = getClass().getSimpleName();
-
- private final ArrayList<WeakReference<Callback>> mCallbacks = new ArrayList<>();
- private final boolean mOverriding;
- private final CoroutineScope mScope;
- private Boolean mIsConditionMet;
- private boolean mStarted = false;
-
- /**
- * By default, conditions have an initial value of false and are not overriding.
- */
- public Condition(CoroutineScope scope) {
- this(scope, false, false);
- }
-
- /**
- * Constructor for specifying initial state and overriding condition attribute.
- *
- * @param initialConditionMet Initial state of the condition.
- * @param overriding Whether this condition overrides others.
- */
- protected Condition(CoroutineScope scope, Boolean initialConditionMet, boolean overriding) {
- mIsConditionMet = initialConditionMet;
- mOverriding = overriding;
- mScope = scope;
- }
-
- /**
- * Starts monitoring the condition.
- */
- protected abstract void start();
-
- /**
- * Stops monitoring the condition.
- */
- protected abstract void stop();
-
- /**
- * Condition should be started as soon as there is an active subscription.
- */
- public static final int START_EAGERLY = 0;
- /**
- * Condition should be started lazily only if needed. But once started, it will not be cancelled
- * unless there are no more active subscriptions.
- */
- public static final int START_LAZILY = 1;
- /**
- * Condition should be started lazily only if needed, and can be stopped when not needed. This
- * should be used for conditions which are expensive to keep running.
- */
- public static final int START_WHEN_NEEDED = 2;
-
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({START_EAGERLY, START_LAZILY, START_WHEN_NEEDED})
- @interface StartStrategy {
- }
-
- @StartStrategy
- protected abstract int getStartStrategy();
-
- /**
- * Returns whether the current condition overrides
- */
- public boolean isOverridingCondition() {
- return mOverriding;
- }
-
- /**
- * Registers a callback to receive updates once started. This should be called before
- * {@link #start()}. Also triggers the callback immediately if already started.
- */
- public void addCallback(@NonNull Callback callback) {
- if (shouldLog()) Log.d(mTag, "adding callback");
- mCallbacks.add(new WeakReference<>(callback));
-
- if (mStarted) {
- callback.onConditionChanged(this);
- return;
- }
-
- start();
- mStarted = true;
- }
-
- /**
- * Removes the provided callback from further receiving updates.
- */
- public void removeCallback(@NonNull Callback callback) {
- if (shouldLog()) Log.d(mTag, "removing callback");
- final Iterator<WeakReference<Callback>> iterator = mCallbacks.iterator();
- while (iterator.hasNext()) {
- final Callback cb = iterator.next().get();
- if (cb == null || cb == callback) {
- iterator.remove();
- }
- }
-
- if (!mCallbacks.isEmpty() || !mStarted) {
- return;
- }
-
- stop();
- mStarted = false;
- }
-
- /**
- * Wrapper to {@link #addCallback(Callback)} when a lifecycle is in the resumed state
- * and {@link #removeCallback(Callback)} when not resumed automatically.
- */
- public Callback observe(LifecycleOwner owner, Callback listener) {
- return observe(owner.getLifecycle(), listener);
- }
-
- /**
- * Wrapper to {@link #addCallback(Callback)} when a lifecycle is in the resumed state
- * and {@link #removeCallback(Condition.Callback)} when not resumed automatically.
- */
- public Callback observe(Lifecycle lifecycle, Callback listener) {
- lifecycle.addObserver((LifecycleEventObserver) (lifecycleOwner, event) -> {
- if (event == Lifecycle.Event.ON_RESUME) {
- addCallback(listener);
- } else if (event == Lifecycle.Event.ON_PAUSE) {
- removeCallback(listener);
- }
- });
- return listener;
- }
-
- /**
- * Updates the value for whether the condition has been fulfilled, and sends an update if the
- * value changes and any callback is registered.
- *
- * @param isConditionMet True if the condition has been fulfilled. False otherwise.
- */
- protected void updateCondition(boolean isConditionMet) {
- if (mIsConditionMet != null && mIsConditionMet == isConditionMet) {
- return;
- }
-
- if (shouldLog()) Log.d(mTag, "updating condition to " + isConditionMet);
- mIsConditionMet = isConditionMet;
- sendUpdate();
- }
-
- /**
- * Clears the set condition value. This is purposefully separate from
- * {@link #updateCondition(boolean)} to avoid confusion around {@code null} values.
- */
- protected void clearCondition() {
- if (mIsConditionMet == null) {
- return;
- }
-
- if (shouldLog()) Log.d(mTag, "clearing condition");
-
- mIsConditionMet = null;
- sendUpdate();
- }
-
- private void sendUpdate() {
- final Iterator<WeakReference<Callback>> iterator = mCallbacks.iterator();
- while (iterator.hasNext()) {
- final Callback cb = iterator.next().get();
- if (cb == null) {
- iterator.remove();
- } else {
- cb.onConditionChanged(this);
- }
- }
- }
-
- /**
- * Returns whether the condition is set. This method should be consulted to understand the
- * value of {@link #isConditionMet()}.
- *
- * @return {@code true} if value is present, {@code false} otherwise.
- */
- public boolean isConditionSet() {
- return mIsConditionMet != null;
- }
-
- /**
- * Returns whether the condition has been met. Note that this method will return {@code false}
- * if the condition is not set as well.
- */
- public boolean isConditionMet() {
- return Boolean.TRUE.equals(mIsConditionMet);
- }
-
- protected final boolean shouldLog() {
- return Log.isLoggable(mTag, Log.DEBUG);
- }
-
- protected final String getTag() {
- if (isOverridingCondition()) {
- return mTag + "[OVRD]";
- }
-
- return mTag;
- }
-
- /**
- * Returns the state of the condition.
- * - "Invalid", condition hasn't been set / not monitored
- * - "True", condition has been met
- * - "False", condition has not been met
- */
- protected final String getState() {
- if (!isConditionSet()) {
- return "Invalid";
- }
- return isConditionMet() ? "True" : "False";
- }
-
- /**
- * Creates a new condition which will only be true when both this condition and all the provided
- * conditions are true.
- */
- public Condition and(@NonNull Collection<Condition> others) {
- final List<Condition> conditions = new ArrayList<>();
- conditions.add(this);
- conditions.addAll(others);
- return new CombinedCondition(mScope, conditions, Evaluator.OP_AND);
- }
-
- /**
- * Creates a new condition which will only be true when both this condition and the provided
- * condition is true.
- */
- public Condition and(@NonNull Condition... others) {
- return and(Arrays.asList(others));
- }
-
- /**
- * Creates a new condition which will only be true when either this condition or any of the
- * provided conditions are true.
- */
- public Condition or(@NonNull Collection<Condition> others) {
- final List<Condition> conditions = new ArrayList<>();
- conditions.add(this);
- conditions.addAll(others);
- return new CombinedCondition(mScope, conditions, Evaluator.OP_OR);
- }
-
- /**
- * Creates a new condition which will only be true when either this condition or the provided
- * condition is true.
- */
- public Condition or(@NonNull Condition... others) {
- return or(Arrays.asList(others));
- }
-
- /**
- * Callback that receives updates about whether the condition has been fulfilled.
- */
- public interface Callback {
- /**
- * Called when the fulfillment of the condition changes.
- *
- * @param condition The condition in question.
- */
- void onConditionChanged(Condition condition);
- }
-}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.kt
new file mode 100644
index 000000000000..69236b48ed51
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.kt
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2025 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.systemui.shared.condition
+
+import android.util.Log
+import androidx.annotation.IntDef
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleEventObserver
+import androidx.lifecycle.LifecycleOwner
+import java.lang.ref.WeakReference
+import kotlinx.coroutines.CoroutineScope
+
+/**
+ * Base class for a condition that needs to be fulfilled in order for [Monitor] to inform its
+ * callbacks.
+ */
+abstract class Condition
+/**
+ * Constructor for specifying initial state and overriding condition attribute.
+ *
+ * @param initialConditionMet Initial state of the condition.
+ * @param overriding Whether this condition overrides others.
+ */
+@JvmOverloads
+protected constructor(
+ private val _scope: CoroutineScope,
+ private var _isConditionMet: Boolean? = false,
+ /** Returns whether the current condition overrides */
+ val isOverridingCondition: Boolean = false,
+) {
+ private val mTag: String = javaClass.simpleName
+
+ private val _callbacks = mutableListOf<WeakReference<Callback>>()
+ private var _started = false
+
+ /** Starts monitoring the condition. */
+ protected abstract fun start()
+
+ /** Stops monitoring the condition. */
+ protected abstract fun stop()
+
+ @Retention(AnnotationRetention.SOURCE)
+ @IntDef(START_EAGERLY, START_LAZILY, START_WHEN_NEEDED)
+ annotation class StartStrategy
+
+ @get:StartStrategy abstract val startStrategy: Int
+
+ /**
+ * Registers a callback to receive updates once started. This should be called before [.start].
+ * Also triggers the callback immediately if already started.
+ */
+ fun addCallback(callback: Callback) {
+ if (shouldLog()) Log.d(mTag, "adding callback")
+ _callbacks.add(WeakReference(callback))
+
+ if (_started) {
+ callback.onConditionChanged(this)
+ return
+ }
+
+ start()
+ _started = true
+ }
+
+ /** Removes the provided callback from further receiving updates. */
+ fun removeCallback(callback: Callback) {
+ if (shouldLog()) Log.d(mTag, "removing callback")
+ val iterator = _callbacks.iterator()
+ while (iterator.hasNext()) {
+ val cb = iterator.next().get()
+ if (cb == null || cb === callback) {
+ iterator.remove()
+ }
+ }
+
+ if (_callbacks.isNotEmpty() || !_started) {
+ return
+ }
+
+ stop()
+ _started = false
+ }
+
+ /**
+ * Wrapper to [.addCallback] when a lifecycle is in the resumed state and [.removeCallback] when
+ * not resumed automatically.
+ */
+ fun observe(owner: LifecycleOwner, listener: Callback): Callback {
+ return observe(owner.lifecycle, listener)
+ }
+
+ /**
+ * Wrapper to [.addCallback] when a lifecycle is in the resumed state and [.removeCallback] when
+ * not resumed automatically.
+ */
+ fun observe(lifecycle: Lifecycle, listener: Callback): Callback {
+ lifecycle.addObserver(
+ LifecycleEventObserver { lifecycleOwner: LifecycleOwner?, event: Lifecycle.Event ->
+ if (event == Lifecycle.Event.ON_RESUME) {
+ addCallback(listener)
+ } else if (event == Lifecycle.Event.ON_PAUSE) {
+ removeCallback(listener)
+ }
+ }
+ )
+ return listener
+ }
+
+ /**
+ * Updates the value for whether the condition has been fulfilled, and sends an update if the
+ * value changes and any callback is registered.
+ *
+ * @param isConditionMet True if the condition has been fulfilled. False otherwise.
+ */
+ protected fun updateCondition(isConditionMet: Boolean) {
+ if (_isConditionMet != null && _isConditionMet == isConditionMet) {
+ return
+ }
+
+ if (shouldLog()) Log.d(mTag, "updating condition to $isConditionMet")
+ _isConditionMet = isConditionMet
+ sendUpdate()
+ }
+
+ /**
+ * Clears the set condition value. This is purposefully separate from [.updateCondition] to
+ * avoid confusion around `null` values.
+ */
+ fun clearCondition() {
+ if (_isConditionMet == null) {
+ return
+ }
+
+ if (shouldLog()) Log.d(mTag, "clearing condition")
+
+ _isConditionMet = null
+ sendUpdate()
+ }
+
+ private fun sendUpdate() {
+ val iterator = _callbacks.iterator()
+ while (iterator.hasNext()) {
+ val cb = iterator.next().get()
+ if (cb == null) {
+ iterator.remove()
+ } else {
+ cb.onConditionChanged(this)
+ }
+ }
+ }
+
+ val isConditionSet: Boolean
+ /**
+ * Returns whether the condition is set. This method should be consulted to understand the
+ * value of [.isConditionMet].
+ *
+ * @return `true` if value is present, `false` otherwise.
+ */
+ get() = _isConditionMet != null
+
+ val isConditionMet: Boolean
+ /**
+ * Returns whether the condition has been met. Note that this method will return `false` if
+ * the condition is not set as well.
+ */
+ get() = true == _isConditionMet
+
+ protected fun shouldLog(): Boolean {
+ return Log.isLoggable(mTag, Log.DEBUG)
+ }
+
+ val tag: String
+ get() {
+ if (isOverridingCondition) {
+ return "$mTag[OVRD]"
+ }
+
+ return mTag
+ }
+
+ val state: String
+ /**
+ * Returns the state of the condition.
+ * - "Invalid", condition hasn't been set / not monitored
+ * - "True", condition has been met
+ * - "False", condition has not been met
+ */
+ get() {
+ if (!isConditionSet) {
+ return "Invalid"
+ }
+ return if (isConditionMet) "True" else "False"
+ }
+
+ /**
+ * Creates a new condition which will only be true when both this condition and all the provided
+ * conditions are true.
+ */
+ fun and(others: Collection<Condition>): Condition {
+ val conditions: List<Condition> = listOf(this, *others.toTypedArray())
+ return CombinedCondition(_scope, conditions, Evaluator.OP_AND)
+ }
+
+ /**
+ * Creates a new condition which will only be true when both this condition and the provided
+ * condition is true.
+ */
+ fun and(vararg others: Condition): Condition {
+ return and(listOf(*others))
+ }
+
+ /**
+ * Creates a new condition which will only be true when either this condition or any of the
+ * provided conditions are true.
+ */
+ fun or(others: Collection<Condition>): Condition {
+ val conditions: MutableList<Condition> = ArrayList()
+ conditions.add(this)
+ conditions.addAll(others)
+ return CombinedCondition(_scope, conditions, Evaluator.OP_OR)
+ }
+
+ /**
+ * Creates a new condition which will only be true when either this condition or the provided
+ * condition is true.
+ */
+ fun or(vararg others: Condition): Condition {
+ return or(listOf(*others))
+ }
+
+ /** Callback that receives updates about whether the condition has been fulfilled. */
+ fun interface Callback {
+ /**
+ * Called when the fulfillment of the condition changes.
+ *
+ * @param condition The condition in question.
+ */
+ fun onConditionChanged(condition: Condition)
+ }
+
+ companion object {
+ /** Condition should be started as soon as there is an active subscription. */
+ const val START_EAGERLY: Int = 0
+
+ /**
+ * Condition should be started lazily only if needed. But once started, it will not be
+ * cancelled unless there are no more active subscriptions.
+ */
+ const val START_LAZILY: Int = 1
+
+ /**
+ * Condition should be started lazily only if needed, and can be stopped when not needed.
+ * This should be used for conditions which are expensive to keep running.
+ */
+ const val START_WHEN_NEEDED: Int = 2
+ }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/ConditionExtensions.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/ConditionExtensions.kt
index 84edc3577007..0f535cdfa5cc 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/ConditionExtensions.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/ConditionExtensions.kt
@@ -14,7 +14,7 @@ import kotlinx.coroutines.launch
fun Flow<Boolean>.toCondition(
scope: CoroutineScope,
@StartStrategy strategy: Int,
- initialValue: Boolean? = null
+ initialValue: Boolean? = null,
): Condition {
return object : Condition(scope, initialValue, false) {
var job: Job? = null
@@ -28,7 +28,8 @@ fun Flow<Boolean>.toCondition(
job = null
}
- override fun getStartStrategy() = strategy
+ override val startStrategy: Int
+ get() = strategy
}
}
@@ -36,13 +37,16 @@ fun Flow<Boolean>.toCondition(
fun Condition.toFlow(): Flow<Boolean?> {
return callbackFlow {
val callback =
- Condition.Callback { condition ->
- if (condition.isConditionSet) {
- trySend(condition.isConditionMet)
- } else {
- trySend(null)
+ object : Condition.Callback {
+ override fun onConditionChanged(condition: Condition) {
+ if (condition.isConditionSet) {
+ trySend(condition.isConditionMet)
+ } else {
+ trySend(null)
+ }
}
}
+
addCallback(callback)
callback.onConditionChanged(this@toFlow)
awaitClose { removeCallback(callback) }
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index e827b2d54a19..1549b699eee6 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -56,6 +56,7 @@ import com.android.systemui.log.core.Logger
import com.android.systemui.modes.shared.ModesUi
import com.android.systemui.plugins.clocks.AlarmData
import com.android.systemui.plugins.clocks.ClockController
+import com.android.systemui.plugins.clocks.ClockEventListener
import com.android.systemui.plugins.clocks.ClockFaceController
import com.android.systemui.plugins.clocks.ClockMessageBuffers
import com.android.systemui.plugins.clocks.ClockTickRate
@@ -148,7 +149,7 @@ constructor(
val clockStr = clock.toString()
loggers.forEach { it.d({ "New Clock: $str1" }) { str1 = clockStr } }
- clock.initialize(isDarkTheme(), dozeAmount.value, 0f, { onClockBoundsChanged.value = it })
+ clock.initialize(isDarkTheme(), dozeAmount.value, 0f, clockListener)
if (!regionSamplingEnabled) {
updateColors()
@@ -312,6 +313,13 @@ constructor(
private var zenData: ZenData? = null
private var alarmData: AlarmData? = null
+ private val clockListener =
+ object : ClockEventListener {
+ override fun onBoundsChanged(bounds: RectF) {
+ onClockBoundsChanged.value = bounds
+ }
+ }
+
private val configListener =
object : ConfigurationController.ConfigurationListener {
override fun onThemeChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesChecker.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesChecker.java
index 2d1cd03aea4d..20290f7b5373 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesChecker.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesChecker.java
@@ -99,10 +99,7 @@ public class HearingDevicesChecker {
private boolean isExclusivelyManagedBluetoothDevice(
@NonNull CachedBluetoothDevice cachedDevice) {
- if (com.android.settingslib.flags.Flags.enableHideExclusivelyManagedBluetoothDevice()) {
- return BluetoothUtils.isExclusivelyManagedBluetoothDevice(mContext,
- cachedDevice.getDevice());
- }
- return false;
+ return BluetoothUtils.isExclusivelyManagedBluetoothDevice(mContext,
+ cachedDevice.getDevice());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt
index bfbc27d3a086..858cc00b86b9 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt
@@ -21,7 +21,6 @@ import android.content.Context
import com.android.settingslib.bluetooth.BluetoothUtils
import com.android.settingslib.bluetooth.CachedBluetoothDevice
import com.android.settingslib.bluetooth.LocalBluetoothManager
-import com.android.settingslib.flags.Flags
import com.android.systemui.res.R
private val backgroundOn = R.drawable.settingslib_switch_bar_bg_on
@@ -222,12 +221,8 @@ internal class ConnectedDeviceItemFactory : DeviceItemFactory() {
isOngoingCall: Boolean,
audioSharingAvailable: Boolean,
): Boolean {
- return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) {
- !BluetoothUtils.isExclusivelyManagedBluetoothDevice(context, cachedDevice.device) &&
- BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, isOngoingCall)
- } else {
+ return !BluetoothUtils.isExclusivelyManagedBluetoothDevice(context, cachedDevice.device) &&
BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, isOngoingCall)
- }
}
override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem {
@@ -250,13 +245,9 @@ internal open class SavedDeviceItemFactory : DeviceItemFactory() {
isOngoingCall: Boolean,
audioSharingAvailable: Boolean,
): Boolean {
- return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) {
- !BluetoothUtils.isExclusivelyManagedBluetoothDevice(context, cachedDevice.device) &&
- cachedDevice.bondState == BluetoothDevice.BOND_BONDED &&
- !cachedDevice.isConnected
- } else {
- cachedDevice.bondState == BluetoothDevice.BOND_BONDED && !cachedDevice.isConnected
- }
+ return !BluetoothUtils.isExclusivelyManagedBluetoothDevice(context, cachedDevice.device) &&
+ cachedDevice.bondState == BluetoothDevice.BOND_BONDED &&
+ !cachedDevice.isConnected
}
override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem {
@@ -279,18 +270,12 @@ internal class SavedHearingDeviceItemFactory : SavedDeviceItemFactory() {
isOngoingCall: Boolean,
audioSharingAvailable: Boolean,
): Boolean {
- return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) {
- !BluetoothUtils.isExclusivelyManagedBluetoothDevice(
- context,
- cachedDevice.getDevice(),
- ) &&
- cachedDevice.isHearingAidDevice &&
- cachedDevice.bondState == BluetoothDevice.BOND_BONDED &&
- !cachedDevice.isConnected
- } else {
+ return !BluetoothUtils.isExclusivelyManagedBluetoothDevice(
+ context,
+ cachedDevice.getDevice(),
+ ) &&
cachedDevice.isHearingAidDevice &&
- cachedDevice.bondState == BluetoothDevice.BOND_BONDED &&
- !cachedDevice.isConnected
- }
+ cachedDevice.bondState == BluetoothDevice.BOND_BONDED &&
+ !cachedDevice.isConnected
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ActionIntentCreator.kt b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ActionIntentCreator.kt
new file mode 100644
index 000000000000..df6c1b18e3e9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ActionIntentCreator.kt
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2025 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.systemui.clipboardoverlay
+
+import android.content.ClipData
+import android.content.ClipDescription
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.text.TextUtils
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.res.R
+import javax.inject.Inject
+
+@SysUISingleton
+class ActionIntentCreator @Inject constructor() : IntentCreator {
+ override fun getTextEditorIntent(context: Context?) =
+ Intent(context, EditTextActivity::class.java).apply {
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ }
+
+ override fun getShareIntent(clipData: ClipData, context: Context?): Intent {
+ val shareIntent = Intent(Intent.ACTION_SEND)
+
+ // From the ACTION_SEND docs:
+ // "If using EXTRA_TEXT, the MIME type should be "text/plain"; otherwise it should be the
+ // MIME type of the data in EXTRA_STREAM"
+ val uri = clipData.getItemAt(0).uri
+ shareIntent.apply {
+ if (uri != null) {
+ // We don't use setData here because some apps interpret this as "to:".
+ setType(clipData.description.getMimeType(0))
+ // Include URI in ClipData also, so that grantPermission picks it up.
+ setClipData(
+ ClipData(
+ ClipDescription("content", arrayOf(clipData.description.getMimeType(0))),
+ ClipData.Item(uri),
+ )
+ )
+ putExtra(Intent.EXTRA_STREAM, uri)
+ addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ } else {
+ putExtra(Intent.EXTRA_TEXT, clipData.getItemAt(0).coerceToText(context).toString())
+ setType("text/plain")
+ }
+ }
+
+ return Intent.createChooser(shareIntent, null)
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
+ .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ }
+
+ override fun getImageEditIntent(uri: Uri?, context: Context): Intent {
+ val editorPackage = context.getString(R.string.config_screenshotEditor)
+ return Intent(Intent.ACTION_EDIT).apply {
+ if (!TextUtils.isEmpty(editorPackage)) {
+ setComponent(ComponentName.unflattenFromString(editorPackage))
+ }
+ setDataAndType(uri, "image/*")
+ addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ putExtra(EXTRA_EDIT_SOURCE, EDIT_SOURCE_CLIPBOARD)
+ }
+ }
+
+ override fun getRemoteCopyIntent(clipData: ClipData?, context: Context): Intent {
+ val remoteCopyPackage = context.getString(R.string.config_remoteCopyPackage)
+ return Intent(REMOTE_COPY_ACTION).apply {
+ if (!TextUtils.isEmpty(remoteCopyPackage)) {
+ setComponent(ComponentName.unflattenFromString(remoteCopyPackage))
+ }
+
+ setClipData(clipData)
+ addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ }
+ }
+
+ companion object {
+ private const val EXTRA_EDIT_SOURCE: String = "edit_source"
+ private const val EDIT_SOURCE_CLIPBOARD: String = "clipboard"
+ private const val REMOTE_COPY_ACTION: String = "android.intent.action.REMOTE_COPY"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
index ac747845267c..314b6e7f5a28 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
@@ -65,7 +65,6 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.clipboardoverlay.dagger.ClipboardOverlayModule.OverlayWindowContext;
import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.res.R;
import com.android.systemui.screenshot.TimeoutHandler;
@@ -94,13 +93,13 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
private final ClipboardOverlayWindow mWindow;
private final TimeoutHandler mTimeoutHandler;
private final ClipboardOverlayUtils mClipboardUtils;
- private final FeatureFlags mFeatureFlags;
private final Executor mBgExecutor;
private final ClipboardImageLoader mClipboardImageLoader;
private final ClipboardTransitionExecutor mTransitionExecutor;
private final ClipboardOverlayView mView;
private final ClipboardIndicationProvider mClipboardIndicationProvider;
+ private final IntentCreator mIntentCreator;
private Runnable mOnSessionCompleteListener;
private Runnable mOnRemoteCopyTapped;
@@ -189,13 +188,13 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
BroadcastDispatcher broadcastDispatcher,
BroadcastSender broadcastSender,
TimeoutHandler timeoutHandler,
- FeatureFlags featureFlags,
ClipboardOverlayUtils clipboardUtils,
@Background Executor bgExecutor,
ClipboardImageLoader clipboardImageLoader,
ClipboardTransitionExecutor transitionExecutor,
ClipboardIndicationProvider clipboardIndicationProvider,
- UiEventLogger uiEventLogger) {
+ UiEventLogger uiEventLogger,
+ IntentCreator intentCreator) {
mContext = context;
mBroadcastDispatcher = broadcastDispatcher;
mClipboardImageLoader = clipboardImageLoader;
@@ -203,6 +202,7 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
mClipboardIndicationProvider = clipboardIndicationProvider;
mClipboardLogger = new ClipboardLogger(uiEventLogger);
+ mIntentCreator = intentCreator;
mView = clipboardOverlayView;
mWindow = clipboardOverlayWindow;
@@ -211,7 +211,6 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
hideImmediate();
});
- mFeatureFlags = featureFlags;
mTimeoutHandler = timeoutHandler;
mTimeoutHandler.setDefaultTimeoutMillis(CLIPBOARD_DEFAULT_TIMEOUT_MILLIS);
@@ -508,7 +507,8 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
}
private void maybeShowRemoteCopy(ClipData clipData) {
- Intent remoteCopyIntent = IntentCreator.getRemoteCopyIntent(clipData, mContext);
+ Intent remoteCopyIntent = mIntentCreator.getRemoteCopyIntent(clipData, mContext);
+
// Only show remote copy if it's available.
PackageManager packageManager = mContext.getPackageManager();
if (packageManager.resolveActivity(
@@ -558,19 +558,19 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
private void editImage(Uri uri) {
mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_EDIT_TAPPED);
- mContext.startActivity(IntentCreator.getImageEditIntent(uri, mContext));
+ mContext.startActivity(mIntentCreator.getImageEditIntent(uri, mContext));
animateOut();
}
private void editText() {
mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_EDIT_TAPPED);
- mContext.startActivity(IntentCreator.getTextEditorIntent(mContext));
+ mContext.startActivity(mIntentCreator.getTextEditorIntent(mContext));
animateOut();
}
private void shareContent(ClipData clip) {
mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_SHARE_TAPPED);
- mContext.startActivity(IntentCreator.getShareIntent(clip, mContext));
+ mContext.startActivity(mIntentCreator.getShareIntent(clip, mContext));
animateOut();
}
@@ -717,22 +717,22 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
public void onRemoteCopyButtonTapped() {
if (clipboardSharedTransitions()) {
finish(CLIPBOARD_OVERLAY_REMOTE_COPY_TAPPED,
- IntentCreator.getRemoteCopyIntent(mClipboardModel.getClipData(), mContext));
+ mIntentCreator.getRemoteCopyIntent(mClipboardModel.getClipData(), mContext));
}
}
@Override
public void onShareButtonTapped() {
if (clipboardSharedTransitions()) {
+ Intent shareIntent =
+ mIntentCreator.getShareIntent(mClipboardModel.getClipData(), mContext);
switch (mClipboardModel.getType()) {
case TEXT:
case URI:
- finish(CLIPBOARD_OVERLAY_SHARE_TAPPED,
- IntentCreator.getShareIntent(mClipboardModel.getClipData(), mContext));
+ finish(CLIPBOARD_OVERLAY_SHARE_TAPPED, shareIntent);
break;
case IMAGE:
- finishWithSharedTransition(CLIPBOARD_OVERLAY_SHARE_TAPPED,
- IntentCreator.getShareIntent(mClipboardModel.getClipData(), mContext));
+ finishWithSharedTransition(CLIPBOARD_OVERLAY_SHARE_TAPPED, shareIntent);
break;
}
}
@@ -744,11 +744,11 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
switch (mClipboardModel.getType()) {
case TEXT:
finish(CLIPBOARD_OVERLAY_EDIT_TAPPED,
- IntentCreator.getTextEditorIntent(mContext));
+ mIntentCreator.getTextEditorIntent(mContext));
break;
case IMAGE:
finishWithSharedTransition(CLIPBOARD_OVERLAY_EDIT_TAPPED,
- IntentCreator.getImageEditIntent(mClipboardModel.getUri(), mContext));
+ mIntentCreator.getImageEditIntent(mClipboardModel.getUri(), mContext));
break;
default:
Log.w(TAG, "Got preview tapped callback for non-editable type "
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/DefaultIntentCreator.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/DefaultIntentCreator.java
new file mode 100644
index 000000000000..4b24536ad28f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/DefaultIntentCreator.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2022 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.systemui.clipboardoverlay;
+
+import android.content.ClipData;
+import android.content.ClipDescription;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.text.TextUtils;
+
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.res.R;
+
+import javax.inject.Inject;
+
+@SysUISingleton
+public class DefaultIntentCreator implements IntentCreator {
+ private static final String EXTRA_EDIT_SOURCE = "edit_source";
+ private static final String EDIT_SOURCE_CLIPBOARD = "clipboard";
+ private static final String REMOTE_COPY_ACTION = "android.intent.action.REMOTE_COPY";
+
+ @Inject
+ public DefaultIntentCreator() {}
+
+ public Intent getTextEditorIntent(Context context) {
+ Intent intent = new Intent(context, EditTextActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ return intent;
+ }
+
+ public Intent getShareIntent(ClipData clipData, Context context) {
+ Intent shareIntent = new Intent(Intent.ACTION_SEND);
+
+ // From the ACTION_SEND docs:
+ // "If using EXTRA_TEXT, the MIME type should be "text/plain"; otherwise it should be the
+ // MIME type of the data in EXTRA_STREAM"
+ Uri uri = clipData.getItemAt(0).getUri();
+ if (uri != null) {
+ // We don't use setData here because some apps interpret this as "to:".
+ shareIntent.setType(clipData.getDescription().getMimeType(0));
+ // Include URI in ClipData also, so that grantPermission picks it up.
+ shareIntent.setClipData(new ClipData(
+ new ClipDescription(
+ "content", new String[]{clipData.getDescription().getMimeType(0)}),
+ new ClipData.Item(uri)));
+ shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
+ shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ } else {
+ shareIntent.putExtra(
+ Intent.EXTRA_TEXT, clipData.getItemAt(0).coerceToText(context).toString());
+ shareIntent.setType("text/plain");
+ }
+ Intent chooserIntent = Intent.createChooser(shareIntent, null)
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
+ .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ return chooserIntent;
+ }
+
+ public Intent getImageEditIntent(Uri uri, Context context) {
+ String editorPackage = context.getString(R.string.config_screenshotEditor);
+ Intent editIntent = new Intent(Intent.ACTION_EDIT);
+ if (!TextUtils.isEmpty(editorPackage)) {
+ editIntent.setComponent(ComponentName.unflattenFromString(editorPackage));
+ }
+ editIntent.setDataAndType(uri, "image/*");
+ editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ editIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ editIntent.putExtra(EXTRA_EDIT_SOURCE, EDIT_SOURCE_CLIPBOARD);
+ return editIntent;
+ }
+
+ public Intent getRemoteCopyIntent(ClipData clipData, Context context) {
+ Intent nearbyIntent = new Intent(REMOTE_COPY_ACTION);
+
+ String remoteCopyPackage = context.getString(R.string.config_remoteCopyPackage);
+ if (!TextUtils.isEmpty(remoteCopyPackage)) {
+ nearbyIntent.setComponent(ComponentName.unflattenFromString(remoteCopyPackage));
+ }
+
+ nearbyIntent.setClipData(clipData);
+ nearbyIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ return nearbyIntent;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/IntentCreator.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/IntentCreator.java
index a18b4c84b081..c8a6b05f090b 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/IntentCreator.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/IntentCreator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2025 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.
@@ -17,79 +17,13 @@
package com.android.systemui.clipboardoverlay;
import android.content.ClipData;
-import android.content.ClipDescription;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
-import android.text.TextUtils;
-import com.android.systemui.res.R;
-
-class IntentCreator {
- private static final String EXTRA_EDIT_SOURCE = "edit_source";
- private static final String EDIT_SOURCE_CLIPBOARD = "clipboard";
- private static final String REMOTE_COPY_ACTION = "android.intent.action.REMOTE_COPY";
-
- static Intent getTextEditorIntent(Context context) {
- Intent intent = new Intent(context, EditTextActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- return intent;
- }
-
- static Intent getShareIntent(ClipData clipData, Context context) {
- Intent shareIntent = new Intent(Intent.ACTION_SEND);
-
- // From the ACTION_SEND docs:
- // "If using EXTRA_TEXT, the MIME type should be "text/plain"; otherwise it should be the
- // MIME type of the data in EXTRA_STREAM"
- Uri uri = clipData.getItemAt(0).getUri();
- if (uri != null) {
- // We don't use setData here because some apps interpret this as "to:".
- shareIntent.setType(clipData.getDescription().getMimeType(0));
- // Include URI in ClipData also, so that grantPermission picks it up.
- shareIntent.setClipData(new ClipData(
- new ClipDescription(
- "content", new String[]{clipData.getDescription().getMimeType(0)}),
- new ClipData.Item(uri)));
- shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
- shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- } else {
- shareIntent.putExtra(
- Intent.EXTRA_TEXT, clipData.getItemAt(0).coerceToText(context).toString());
- shareIntent.setType("text/plain");
- }
- Intent chooserIntent = Intent.createChooser(shareIntent, null)
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
- .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- return chooserIntent;
- }
-
- static Intent getImageEditIntent(Uri uri, Context context) {
- String editorPackage = context.getString(R.string.config_screenshotEditor);
- Intent editIntent = new Intent(Intent.ACTION_EDIT);
- if (!TextUtils.isEmpty(editorPackage)) {
- editIntent.setComponent(ComponentName.unflattenFromString(editorPackage));
- }
- editIntent.setDataAndType(uri, "image/*");
- editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- editIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- editIntent.putExtra(EXTRA_EDIT_SOURCE, EDIT_SOURCE_CLIPBOARD);
- return editIntent;
- }
-
- static Intent getRemoteCopyIntent(ClipData clipData, Context context) {
- Intent nearbyIntent = new Intent(REMOTE_COPY_ACTION);
-
- String remoteCopyPackage = context.getString(R.string.config_remoteCopyPackage);
- if (!TextUtils.isEmpty(remoteCopyPackage)) {
- nearbyIntent.setComponent(ComponentName.unflattenFromString(remoteCopyPackage));
- }
-
- nearbyIntent.setClipData(clipData);
- nearbyIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- return nearbyIntent;
- }
+public interface IntentCreator {
+ Intent getTextEditorIntent(Context context);
+ Intent getShareIntent(ClipData clipData, Context context);
+ Intent getImageEditIntent(Uri uri, Context context);
+ Intent getRemoteCopyIntent(ClipData clipData, Context context);
}
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java
index 6c10eea07ffc..c86a84b17efe 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java
@@ -20,6 +20,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
import static com.android.systemui.Flags.clipboardOverlayMultiuser;
import static com.android.systemui.Flags.enableViewCaptureTracing;
+import static com.android.systemui.shared.Flags.usePreferredImageEditor;
import static com.android.systemui.util.ConvenienceExtensionsKt.toKotlinLazy;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@@ -32,7 +33,10 @@ import android.view.WindowManager;
import com.android.app.viewcapture.ViewCapture;
import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
+import com.android.systemui.clipboardoverlay.ActionIntentCreator;
import com.android.systemui.clipboardoverlay.ClipboardOverlayView;
+import com.android.systemui.clipboardoverlay.DefaultIntentCreator;
+import com.android.systemui.clipboardoverlay.IntentCreator;
import com.android.systemui.res.R;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
@@ -102,6 +106,17 @@ public interface ClipboardOverlayModule {
/* isViewCaptureEnabled= */ enableViewCaptureTracing());
}
+ @Provides
+ static IntentCreator provideIntentCreator(
+ Lazy<DefaultIntentCreator> defaultIntentCreator,
+ Lazy<ActionIntentCreator> actionIntentCreator) {
+ if (usePreferredImageEditor()) {
+ return actionIntentCreator.get();
+ } else {
+ return defaultIntentCreator.get();
+ }
+ }
+
@Qualifier
@Documented
@Retention(RUNTIME)
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt b/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt
index ba7e17bdd7a5..07cc136e6bc6 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt
@@ -23,7 +23,6 @@ import androidx.annotation.ColorInt
import androidx.annotation.DimenRes
import androidx.annotation.LayoutRes
import com.android.settingslib.Utils
-import com.android.systemui.statusbar.data.repository.StatusBarConfigurationState
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.onDensityOrFontScaleChanged
import com.android.systemui.statusbar.policy.onThemeChanged
@@ -79,7 +78,7 @@ class ConfigurationStateImpl
constructor(
@Assisted private val configurationController: ConfigurationController,
@Assisted private val context: Context,
-) : ConfigurationState, StatusBarConfigurationState {
+) : ConfigurationState {
private val layoutInflater = LayoutInflater.from(context)
diff --git a/packages/SystemUI/src/com/android/systemui/communal/DeviceInactiveCondition.java b/packages/SystemUI/src/com/android/systemui/communal/DeviceInactiveCondition.java
index e456310febfd..4be9601f4277 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/DeviceInactiveCondition.java
+++ b/packages/SystemUI/src/com/android/systemui/communal/DeviceInactiveCondition.java
@@ -102,7 +102,7 @@ public class DeviceInactiveCondition extends Condition {
}
@Override
- protected int getStartStrategy() {
+ public int getStartStrategy() {
return START_EAGERLY;
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
index d7859c985c7b..140db7b7a0b7 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
@@ -367,12 +367,22 @@ constructor(
/** See [CommunalSettingsInteractor.isV2FlagEnabled] */
fun v2FlagEnabled(): Boolean = communalSettingsInteractor.isV2FlagEnabled()
- val swipeToHubEnabled: StateFlow<Boolean> by lazy {
- if (v2FlagEnabled()) {
- communalInteractor.shouldShowCommunal
- } else {
- MutableStateFlow(swipeToHub)
- }
+ val swipeToHubEnabled: Flow<Boolean> by lazy {
+ val inAllowedDeviceState =
+ if (swipeToHub) {
+ MutableStateFlow(true)
+ } else if (v2FlagEnabled()) {
+ communalInteractor.shouldShowCommunal
+ } else {
+ MutableStateFlow(false)
+ }
+
+ val inAllowedKeyguardState =
+ keyguardTransitionInteractor.startedKeyguardTransitionStep.map {
+ it.to == KeyguardState.LOCKSCREEN || it.to == KeyguardState.GLANCEABLE_HUB
+ }
+
+ allOf(inAllowedDeviceState, inAllowedKeyguardState)
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/display/data/repository/PerDisplayRepository.kt b/packages/SystemUI/src/com/android/systemui/display/data/repository/PerDisplayRepository.kt
index 3458c9549665..d27e33e53dbb 100644
--- a/packages/SystemUI/src/com/android/systemui/display/data/repository/PerDisplayRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/data/repository/PerDisplayRepository.kt
@@ -126,7 +126,7 @@ constructor(
get() = perDisplayInstances.keys
private suspend fun start() {
- dumpManager.registerDumpable(this)
+ dumpManager.registerNormalDumpable("PerDisplayRepository-${debugName}", this)
displayRepository.displayIds.collectLatest { displayIds ->
val toRemove = perDisplayInstances.keys - displayIds
toRemove.forEach { displayId ->
@@ -184,8 +184,13 @@ constructor(
* Provides an instance of a given class **only** for the default display, even if asked for another
* display.
*
- * This is useful in case of flag refactors: it can be provided instead of an instance of
+ * This is useful in case of **flag refactors**: it can be provided instead of an instance of
* [PerDisplayInstanceRepositoryImpl] when a flag related to multi display refactoring is off.
+ *
+ * Note that this still requires all instances to be provided by a [PerDisplayInstanceProvider]. If
+ * you want to provide an existing instance instead for the default display, either implement it in
+ * a custom [PerDisplayInstanceProvider] (e.g. inject it in the constructor and return it if the
+ * displayId is zero), or use [SingleInstanceRepositoryImpl].
*/
class DefaultDisplayOnlyInstanceRepositoryImpl<T>(
override val debugName: String,
@@ -198,3 +203,18 @@ class DefaultDisplayOnlyInstanceRepositoryImpl<T>(
override fun get(displayId: Int): T? = lazyDefaultDisplayInstance
}
+
+/**
+ * Always returns [instance] for any display.
+ *
+ * This can be used to provide a single instance based on a flag value during a refactor. Similar to
+ * [DefaultDisplayOnlyInstanceRepositoryImpl], but also avoids creating the
+ * [PerDisplayInstanceProvider]. This is useful when you want to provide an existing instance only,
+ * without even instantiating a [PerDisplayInstanceProvider].
+ */
+class SingleInstanceRepositoryImpl<T>(override val debugName: String, private val instance: T) :
+ PerDisplayRepository<T> {
+ override val displayIds: Set<Int> = setOf(Display.DEFAULT_DISPLAY)
+
+ override fun get(displayId: Int): T? = instance
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java b/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java
index d81949d08a66..c17094b7456c 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java
@@ -63,7 +63,7 @@ public class AssistantAttentionCondition extends Condition {
}
@Override
- protected int getStartStrategy() {
+ public int getStartStrategy() {
return START_EAGERLY;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/conditions/DreamCondition.java b/packages/SystemUI/src/com/android/systemui/dreams/conditions/DreamCondition.java
index c7fe1e1e754b..fb4ed1419688 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/conditions/DreamCondition.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/conditions/DreamCondition.java
@@ -63,7 +63,7 @@ public class DreamCondition extends Condition {
}
@Override
- protected int getStartStrategy() {
+ public int getStartStrategy() {
return START_EAGERLY;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/DirectBootCondition.kt b/packages/SystemUI/src/com/android/systemui/lowlightclock/DirectBootCondition.kt
index 4c1da0198498..57d709835b2c 100644
--- a/packages/SystemUI/src/com/android/systemui/lowlightclock/DirectBootCondition.kt
+++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/DirectBootCondition.kt
@@ -54,7 +54,6 @@ constructor(
job?.cancel()
}
- override fun getStartStrategy(): Int {
- return START_EAGERLY
- }
+ override val startStrategy: Int
+ get() = START_EAGERLY
}
diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/ForceLowLightCondition.java b/packages/SystemUI/src/com/android/systemui/lowlightclock/ForceLowLightCondition.java
index 7f21d0707f63..5ec81a9a94a1 100644
--- a/packages/SystemUI/src/com/android/systemui/lowlightclock/ForceLowLightCondition.java
+++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/ForceLowLightCondition.java
@@ -131,7 +131,7 @@ public class ForceLowLightCondition extends Condition {
}
@Override
- protected int getStartStrategy() {
+ public int getStartStrategy() {
return START_EAGERLY;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightCondition.java b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightCondition.java
index e91be5028777..c1a24e7e020e 100644
--- a/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightCondition.java
+++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightCondition.java
@@ -54,7 +54,7 @@ public class LowLightCondition extends Condition {
}
@Override
- protected int getStartStrategy() {
+ public int getStartStrategy() {
// As this condition keeps the lowlight sensor active, it should only run when needed.
return START_WHEN_NEEDED;
}
diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/ScreenSaverEnabledCondition.java b/packages/SystemUI/src/com/android/systemui/lowlightclock/ScreenSaverEnabledCondition.java
index fd6ce1762a28..81572554cb86 100644
--- a/packages/SystemUI/src/com/android/systemui/lowlightclock/ScreenSaverEnabledCondition.java
+++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/ScreenSaverEnabledCondition.java
@@ -70,7 +70,7 @@ public class ScreenSaverEnabledCondition extends Condition {
}
@Override
- protected int getStartStrategy() {
+ public int getStartStrategy() {
return START_EAGERLY;
}
diff --git a/packages/SystemUI/src/com/android/systemui/model/SysUIStateDispatcher.kt b/packages/SystemUI/src/com/android/systemui/model/SysUIStateDispatcher.kt
index f95ae2501acb..2bdd9a88ad6c 100644
--- a/packages/SystemUI/src/com/android/systemui/model/SysUIStateDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/model/SysUIStateDispatcher.kt
@@ -55,7 +55,7 @@ class SysUIStateDispatcher @Inject constructor() {
/** Called from each [SysUiState] to propagate new state changes. */
fun dispatchSysUIStateChange(sysUiFlags: Long, displayId: Int) {
- if (displayId != Display.DEFAULT_DISPLAY && !ShadeWindowGoesAround.isEnabled) return;
+ if (displayId != Display.DEFAULT_DISPLAY && !ShadeWindowGoesAround.isEnabled) return
listeners.forEach { listener ->
listener.onSystemUiStateChanged(sysUiFlags = sysUiFlags, displayId = displayId)
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 7af538105cae..237ec7cfce7f 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -1129,6 +1129,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
mGestureBlockingActivityRunning.get(), mIsInPip, mDisplaySize,
mEdgeWidthLeft, mLeftInset, mEdgeWidthRight, mRightInset, mExcludeRegion));
} else if (mAllowGesture || mLogGesture) {
+ boolean mLastFrameThresholdCrossed = mThresholdCrossed;
if (!mThresholdCrossed) {
mEndPoint.x = (int) ev.getX();
mEndPoint.y = (int) ev.getY();
@@ -1181,9 +1182,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
return;
} else if (dx > dy && dx > mTouchSlop) {
if (mAllowGesture) {
- if (mBackAnimation != null) {
- mBackAnimation.onThresholdCrossed();
- } else {
+ if (mBackAnimation == null) {
pilferPointers();
}
mThresholdCrossed = true;
@@ -1198,6 +1197,9 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
// forward touch
mEdgeBackPlugin.onMotionEvent(ev);
dispatchToBackAnimation(ev);
+ if (mBackAnimation != null && mThresholdCrossed && !mLastFrameThresholdCrossed) {
+ mBackAnimation.onThresholdCrossed();
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java b/packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java
index 694b525e7bc1..ea2bf6a44884 100644
--- a/packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java
+++ b/packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java
@@ -48,7 +48,7 @@ public class SystemProcessCondition extends Condition {
}
@Override
- protected int getStartStrategy() {
+ public int getStartStrategy() {
return START_EAGERLY;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt
index feb4d41e49b6..865ae9a37d87 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt
@@ -42,6 +42,7 @@ import androidx.compose.ui.res.integerResource
import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.ContentScope
import com.android.compose.modifiers.padding
+import com.android.systemui.common.ui.compose.PagerDots
import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.development.ui.compose.BuildNumber
import com.android.systemui.development.ui.viewmodel.BuildNumberViewModel
diff --git a/packages/SystemUI/src/com/android/systemui/recents/LauncherProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/LauncherProxyService.java
index 7a6426c741a6..4be35f147c2f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/LauncherProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/LauncherProxyService.java
@@ -830,7 +830,8 @@ public class LauncherProxyService implements CallbackController<LauncherProxyLis
private void notifySystemUiStateFlags(@SystemUiStateFlags long flags, int displayId) {
if (SysUiState.DEBUG) {
Log.d(TAG_OPS, "Notifying sysui state change to launcher service: proxy="
- + mLauncherProxy + " flags=" + flags + " displayId=" + displayId);
+ + mLauncherProxy + " display=" + displayId + " flags="
+ + QuickStepContract.getSystemUiStateString(flags) + " displayId=" + displayId);
}
try {
if (mLauncherProxy != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 17fb50aa6890..24e7976011f4 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -140,6 +140,7 @@ import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.settings.brightness.data.repository.BrightnessMirrorShowingRepository;
import com.android.systemui.settings.brightness.domain.interactor.BrightnessMirrorShowingInteractor;
import com.android.systemui.shade.data.repository.FlingInfo;
+import com.android.systemui.shade.data.repository.ShadeDisplaysRepository;
import com.android.systemui.shade.data.repository.ShadeRepository;
import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor;
import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround;
@@ -204,6 +205,7 @@ import dalvik.annotation.optimization.NeverCompile;
import com.google.android.msdl.data.model.MSDLToken;
import com.google.android.msdl.domain.MSDLPlayer;
+import dagger.Lazy;
import kotlin.Unit;
import kotlinx.coroutines.CoroutineDispatcher;
@@ -394,7 +396,7 @@ public final class NotificationPanelViewController implements
/** Whether the notifications are displayed full width (no margins on the side). */
private boolean mIsFullWidth;
private boolean mBlockingExpansionForCurrentTouch;
- // Following variables maintain state of events when input focus transfer may occur.
+ // Following variables maintain state of events when input focus transfer may occur.
private boolean mExpectingSynthesizedDown;
private boolean mLastEventSynthesizedDown;
@@ -456,6 +458,7 @@ public final class NotificationPanelViewController implements
@Deprecated // Use SysUIStateInteractor instead
private final SysUiState mSysUiState;
private final SysUIStateDisplaysInteractor mSysUIStateDisplaysInteractor;
+ private final Lazy<ShadeDisplaysRepository> mShadeDisplaysRepository;
private final NotificationShadeDepthController mDepthController;
private final NavigationBarController mNavigationBarController;
private final int mDisplayId;
@@ -637,7 +640,8 @@ public final class NotificationPanelViewController implements
KeyguardClockPositionAlgorithm keyguardClockPositionAlgorithm,
MSDLPlayer msdlPlayer,
BrightnessMirrorShowingRepository brightnessMirrorShowingRepository,
- BlurConfig blurConfig) {
+ BlurConfig blurConfig,
+ Lazy<ShadeDisplaysRepository> shadeDisplaysRepository) {
mBlurConfig = blurConfig;
SceneContainerFlag.assertInLegacyMode();
keyguardStateController.addCallback(new KeyguardStateController.Callback() {
@@ -745,6 +749,7 @@ public final class NotificationPanelViewController implements
mTapAgainViewController = tapAgainViewController;
mSysUiState = sysUiState;
mSysUIStateDisplaysInteractor = sysUIStateDisplaysInteractor;
+ mShadeDisplaysRepository = shadeDisplaysRepository;
mKeyguardBypassController = bypassController;
mUpdateMonitor = keyguardUpdateMonitor;
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
@@ -2716,8 +2721,17 @@ public final class NotificationPanelViewController implements
}
private int getShadeDisplayId() {
- if (mView != null && mView.getDisplay() != null) return mView.getDisplay().getDisplayId();
- return Display.DEFAULT_DISPLAY;
+ if (ShadeWindowGoesAround.isEnabled()) {
+ var pendingDisplayId =
+ mShadeDisplaysRepository.get().getPendingDisplayId().getValue();
+ // Use the pendingDisplayId from the repository, *not* the Shade's context.
+ // This ensures correct UI state updates also if this method is called just *before*
+ // the Shade window moves to another display.
+ // The pendingDisplayId is guaranteed to be updated before this method is called.
+ return pendingDisplayId;
+ } else {
+ return Display.DEFAULT_DISPLAY;
+ }
}
private void setPerDisplaySysUIStateFlags() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index 3db004848d22..bdfdb8191356 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -60,6 +60,8 @@ import java.util.Optional
import javax.inject.Inject
import kotlin.math.max
import kotlin.math.sign
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
/**
* Responsible for blurring the notification shade window, and applying a zoom effect to the
@@ -92,6 +94,7 @@ constructor(
private const val MIN_VELOCITY = -MAX_VELOCITY
private const val INTERACTION_BLUR_FRACTION = 0.8f
private const val ANIMATION_BLUR_FRACTION = 1f - INTERACTION_BLUR_FRACTION
+ private const val TRANSITION_THRESHOLD = 0.98f
private const val TAG = "DepthController"
}
@@ -156,6 +159,9 @@ constructor(
/**
* When launching an app from the shade, the animations progress should affect how blurry the
* shade is, overriding the expansion amount.
+ *
+ * TODO(b/399617511): remove this once [Flags.notificationShadeBlur] is launched and the Shade
+ * closing is actually instantaneous.
*/
var blursDisabledForAppLaunch: Boolean = false
set(value) {
@@ -185,8 +191,12 @@ constructor(
return
}
- shadeAnimation.animateTo(0)
- shadeAnimation.finishIfRunning()
+ if (Flags.notificationShadeBlur()) {
+ shadeAnimation.skipTo(0)
+ } else {
+ shadeAnimation.animateTo(0)
+ shadeAnimation.finishIfRunning()
+ }
}
@Deprecated(
message =
@@ -487,6 +497,22 @@ constructor(
scheduleUpdate()
}
+ fun onTransitionAnimationProgress(progress: Float) {
+ if (!Flags.notificationShadeBlur() || !Flags.moveTransitionAnimationLayer()) return
+ // Because the Shade takes a few frames to actually trigger the unblur after a transition
+ // has ended, we need to disable it manually, or the opening window itself will be blurred
+ // for a few frames due to relative ordering. We do this towards the end, so that the
+ // window is already covering the background and the unblur is not visible.
+ if (progress >= TRANSITION_THRESHOLD && shadeAnimation.radius > 0) {
+ blursDisabledForAppLaunch = true
+ }
+ }
+
+ fun onTransitionAnimationEnd() {
+ if (!Flags.notificationShadeBlur() || !Flags.moveTransitionAnimationLayer()) return
+ blursDisabledForAppLaunch = false
+ }
+
private fun updateShadeAnimationBlur(
expansion: Float,
tracking: Boolean,
@@ -631,6 +657,20 @@ constructor(
springAnimation.addEndListener { _, _, _, _ -> pendingRadius = -1 }
}
+ /**
+ * Starts an animation to [newRadius], or updates the current one if already ongoing.
+ * IMPORTANT: do NOT use this method + [finishIfRunning] to instantaneously change the value
+ * of the animation. The change will NOT be instantaneous. Use [skipTo] instead.
+ *
+ * Explanation:
+ * 1. If idle, [SpringAnimation.animateToFinalPosition] requests a start to the animation.
+ * 2. On the first frame after an idle animation is requested to start, the animation simply
+ * acquires the starting value and does nothing else.
+ * 3. [SpringAnimation.skipToEnd] requests a fast-forward to the end value, but this happens
+ * during calculation of the next animation value. Because on the first frame no such
+ * calculation happens (point #2), there is one lagging frame where we still see the old
+ * value.
+ */
fun animateTo(newRadius: Int) {
if (pendingRadius == newRadius) {
return
@@ -639,6 +679,19 @@ constructor(
springAnimation.animateToFinalPosition(newRadius.toFloat())
}
+ /**
+ * Instantaneously set a new blur radius to this animation. Always use this instead of
+ * [animateTo] and [finishIfRunning] to make sure that the change takes effect in the next
+ * frame. See the doc for [animateTo] for an explanation.
+ */
+ fun skipTo(newRadius: Int) {
+ if (pendingRadius == newRadius) return
+ pendingRadius = newRadius
+ springAnimation.cancel()
+ springAnimation.setStartValue(newRadius.toFloat())
+ springAnimation.animateToFinalPosition(newRadius.toFloat())
+ }
+
fun finishIfRunning() {
if (springAnimation.isRunning) {
springAnimation.skipToEnd()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/StatusBarDataLayerModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/StatusBarDataLayerModule.kt
index 5e7e1793ab35..9db2f4b46dae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/data/StatusBarDataLayerModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/StatusBarDataLayerModule.kt
@@ -20,9 +20,9 @@ import com.android.systemui.statusbar.data.repository.KeyguardStatusBarRepositor
import com.android.systemui.statusbar.data.repository.LightBarControllerStoreModule
import com.android.systemui.statusbar.data.repository.RemoteInputRepositoryModule
import com.android.systemui.statusbar.data.repository.StatusBarConfigurationControllerModule
-import com.android.systemui.statusbar.data.repository.StatusBarConfigurationStateModule
import com.android.systemui.statusbar.data.repository.StatusBarContentInsetsProviderStoreModule
import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryModule
+import com.android.systemui.statusbar.data.repository.StatusBarPerDisplayConfigurationStateModule
import com.android.systemui.statusbar.data.repository.SystemEventChipAnimationControllerStoreModule
import com.android.systemui.statusbar.phone.data.StatusBarPhoneDataLayerModule
import dagger.Module
@@ -35,7 +35,7 @@ import dagger.Module
LightBarControllerStoreModule::class,
RemoteInputRepositoryModule::class,
StatusBarConfigurationControllerModule::class,
- StatusBarConfigurationStateModule::class,
+ StatusBarPerDisplayConfigurationStateModule::class,
StatusBarContentInsetsProviderStoreModule::class,
StatusBarModeRepositoryModule::class,
StatusBarPhoneDataLayerModule::class,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarConfigurationStateStore.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarConfigurationStateStore.kt
deleted file mode 100644
index 4e6c5ddc3066..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarConfigurationStateStore.kt
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2025 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.systemui.statusbar.data.repository
-
-import android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR
-import com.android.systemui.CoreStartable
-import com.android.systemui.common.ui.ConfigurationState
-import com.android.systemui.common.ui.ConfigurationStateImpl
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.display.data.repository.DisplayRepository
-import com.android.systemui.display.data.repository.DisplayWindowPropertiesRepository
-import com.android.systemui.display.data.repository.PerDisplayStore
-import com.android.systemui.display.data.repository.PerDisplayStoreImpl
-import com.android.systemui.display.data.repository.SingleDisplayStore
-import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
-import dagger.Lazy
-import dagger.Module
-import dagger.Provides
-import dagger.multibindings.ClassKey
-import dagger.multibindings.IntoMap
-import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
-
-/** Status bar specific interface to disambiguate from the global [ConfigurationState]. */
-interface StatusBarConfigurationState : ConfigurationState
-
-/** Provides per display instances of [ConfigurationState], specifically for the Status Bar. */
-interface StatusBarConfigurationStateStore : PerDisplayStore<StatusBarConfigurationState>
-
-@SysUISingleton
-class MultiDisplayStatusBarConfigurationStateStore
-@Inject
-constructor(
- @Background backgroundApplicationScope: CoroutineScope,
- displayRepository: DisplayRepository,
- private val displayWindowPropertiesRepository: DisplayWindowPropertiesRepository,
- private val statusBarConfigurationControllerStore: StatusBarConfigurationControllerStore,
- private val factory: ConfigurationStateImpl.Factory,
-) :
- StatusBarConfigurationStateStore,
- PerDisplayStoreImpl<StatusBarConfigurationState>(
- backgroundApplicationScope,
- displayRepository,
- ) {
-
- init {
- StatusBarConnectedDisplays.unsafeAssertInNewMode()
- }
-
- override fun createInstanceForDisplay(displayId: Int): StatusBarConfigurationState? {
- val displayWindowProperties =
- displayWindowPropertiesRepository.get(displayId, TYPE_STATUS_BAR) ?: return null
- val configController =
- statusBarConfigurationControllerStore.forDisplay(displayId) ?: return null
- return factory.create(displayWindowProperties.context, configController)
- }
-
- override val instanceClass = StatusBarConfigurationState::class.java
-}
-
-@SysUISingleton
-class SingleDisplayStatusBarConfigurationStateStore
-@Inject
-constructor(@Main globalConfigState: ConfigurationState) :
- StatusBarConfigurationStateStore,
- PerDisplayStore<StatusBarConfigurationState> by SingleDisplayStore(
- globalConfigState as StatusBarConfigurationState
- ) {
-
- init {
- StatusBarConnectedDisplays.assertInLegacyMode()
- }
-}
-
-@Module
-object StatusBarConfigurationStateModule {
-
- @Provides
- @SysUISingleton
- fun store(
- singleDisplayLazy: Lazy<SingleDisplayStatusBarConfigurationStateStore>,
- multiDisplayLazy: Lazy<MultiDisplayStatusBarConfigurationStateStore>,
- ): StatusBarConfigurationStateStore {
- return if (StatusBarConnectedDisplays.isEnabled) {
- multiDisplayLazy.get()
- } else {
- singleDisplayLazy.get()
- }
- }
-
- @Provides
- @SysUISingleton
- @IntoMap
- @ClassKey(StatusBarConfigurationStateStore::class)
- fun storeAsCoreStartable(
- multiDisplayLazy: Lazy<MultiDisplayStatusBarConfigurationStateStore>
- ): CoreStartable {
- return if (StatusBarConnectedDisplays.isEnabled) {
- multiDisplayLazy.get()
- } else {
- CoreStartable.NOP
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarPerDisplayConfigurationStateRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarPerDisplayConfigurationStateRepository.kt
new file mode 100644
index 000000000000..3168a22c56ad
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarPerDisplayConfigurationStateRepository.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2025 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.systemui.statusbar.data.repository
+
+import android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR
+import com.android.systemui.common.ui.ConfigurationState
+import com.android.systemui.common.ui.ConfigurationStateImpl
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.display.data.repository.DisplayWindowPropertiesRepository
+import com.android.systemui.display.data.repository.PerDisplayInstanceProvider
+import com.android.systemui.display.data.repository.PerDisplayInstanceRepositoryImpl
+import com.android.systemui.display.data.repository.PerDisplayRepository
+import com.android.systemui.display.data.repository.SingleInstanceRepositoryImpl
+import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
+import dagger.Lazy
+import dagger.Module
+import dagger.Provides
+import javax.inject.Inject
+
+@SysUISingleton
+class StatusBarPerDisplayConfigurationStateProvider
+@Inject
+constructor(
+ private val displayWindowPropertiesRepository: DisplayWindowPropertiesRepository,
+ private val statusBarConfigurationControllerStore: StatusBarConfigurationControllerStore,
+ private val factory: ConfigurationStateImpl.Factory,
+) : PerDisplayInstanceProvider<ConfigurationState> {
+
+ override fun createInstance(displayId: Int): ConfigurationState? {
+ val displayWindowProperties =
+ displayWindowPropertiesRepository.get(displayId, TYPE_STATUS_BAR) ?: return null
+ val configController =
+ statusBarConfigurationControllerStore.forDisplay(displayId) ?: return null
+ return factory.create(displayWindowProperties.context, configController)
+ }
+}
+
+@Module
+object StatusBarPerDisplayConfigurationStateModule {
+
+ @Provides
+ @SysUISingleton
+ fun store(
+ instanceProvider: Lazy<StatusBarPerDisplayConfigurationStateProvider>,
+ factory: PerDisplayInstanceRepositoryImpl.Factory<ConfigurationState>,
+ defaultInstance: ConfigurationState,
+ ): PerDisplayRepository<ConfigurationState> {
+ val name = "ConfigurationState"
+ return if (StatusBarConnectedDisplays.isEnabled) {
+ factory.create(name, instanceProvider.get())
+ } else {
+ SingleInstanceRepositoryImpl(name, defaultInstance)
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerStatusBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerStatusBarViewBinder.kt
index 30aec8dabcaa..147a5afea306 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerStatusBarViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerStatusBarViewBinder.kt
@@ -20,8 +20,8 @@ import android.view.Display
import androidx.lifecycle.lifecycleScope
import com.android.app.tracing.traceSection
import com.android.systemui.common.ui.ConfigurationState
+import com.android.systemui.display.data.repository.PerDisplayRepository
import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.statusbar.data.repository.StatusBarConfigurationStateStore
import com.android.systemui.statusbar.notification.collection.NotifCollection
import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerViewBinder.IconViewStore
import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerStatusBarViewModel
@@ -36,7 +36,7 @@ class NotificationIconContainerStatusBarViewBinder
@Inject
constructor(
private val viewModel: NotificationIconContainerStatusBarViewModel,
- private val configurationStore: StatusBarConfigurationStateStore,
+ private val configurationStateRepository: PerDisplayRepository<ConfigurationState>,
private val defaultConfigurationState: ConfigurationState,
private val systemBarUtilsState: SystemBarUtilsState,
private val failureTracker: StatusBarIconViewBindingFailureTracker,
@@ -57,7 +57,7 @@ constructor(
}
}
val configurationState: ConfigurationState =
- configurationStore.forDisplay(displayId) ?: defaultConfigurationState
+ configurationStateRepository[displayId] ?: defaultConfigurationState
lifecycleScope.launch {
NotificationIconContainerViewBinder.bind(
displayId = displayId,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 428b503102b3..68ad4fad31c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -1685,13 +1685,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
if (notificationRowTransparency() && mBackgroundNormal != null) {
if (NotificationBundleUi.isEnabled() && mEntryAdapter != null) {
- mBackgroundNormal.setBgIsColorized(
- usesTransparentBackground() && mEntryAdapter.isColorized());
+ mBackgroundNormal.setBgIsColorized(mEntryAdapter.isColorized());
} else {
if (mEntry != null) {
mBackgroundNormal.setBgIsColorized(
- usesTransparentBackground()
- && mEntry.getSbn().getNotification().isColorized());
+ mEntry.getSbn().getNotification().isColorized());
}
}
}
@@ -3068,7 +3066,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mUserLocked = userLocked;
mPrivateLayout.setUserExpanding(userLocked);
- mPublicLayout.setUserExpanding(userLocked);
// This is intentionally not guarded with mIsSummaryWithChildren since we might have had
// children but not anymore.
if (mChildrenContainer != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index daa598b5f297..51569c1596ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -57,7 +57,6 @@ import com.android.systemui.statusbar.notification.ConversationNotificationProce
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NmSummarizationUiFlag;
import com.android.systemui.statusbar.notification.NotificationUtils;
-import com.android.systemui.statusbar.notification.collection.EntryAdapter;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.promoted.PromotedNotificationContentExtractor;
import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUiForceExpanded;
@@ -441,8 +440,12 @@ public class NotificationContentInflater implements NotificationRowContentBinder
NotificationRowContentBinderLogger logger) {
return TraceUtils.trace("NotificationContentInflater.createRemoteViews", () -> {
InflationProgress result = new InflationProgress();
+
+ // inflating the contracted view is the legacy invalidation trigger
+ boolean reinflating = (reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0;
// create an image inflater
- result.mRowImageInflater = RowImageInflater.newInstance(row.mImageModelIndex);
+ result.mRowImageInflater = RowImageInflater.newInstance(row.mImageModelIndex,
+ reinflating);
if ((reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0) {
logger.logAsyncTaskProgress(row.getLoggingKey(), "creating contracted remote view");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt
index 3586078c9e82..482b315aa14d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt
@@ -499,7 +499,10 @@ constructor(
logger.logAsyncTaskProgress(entry.logKey, "loading RON images")
inflationProgress.rowImageInflater.loadImagesSynchronously(packageContext)
- logger.logAsyncTaskProgress(entry.logKey, "getting row image resolver (on wrong thread!)")
+ logger.logAsyncTaskProgress(
+ entry.logKey,
+ "getting row image resolver (on wrong thread!)",
+ )
val imageResolver = row.imageResolver
// wait for image resolver to finish preloading
logger.logAsyncTaskProgress(entry.logKey, "waiting for preloaded images")
@@ -685,13 +688,17 @@ constructor(
logger: NotificationRowContentBinderLogger,
): InflationProgress {
val rowImageInflater =
- RowImageInflater.newInstance(previousIndex = row.mImageModelIndex)
+ RowImageInflater.newInstance(
+ previousIndex = row.mImageModelIndex,
+ // inflating the contracted view is the legacy invalidation trigger
+ reinflating = reInflateFlags and FLAG_CONTENT_VIEW_CONTRACTED != 0,
+ )
val promotedContent =
if (PromotedNotificationContentModel.featureFlagEnabled()) {
logger.logAsyncTaskProgress(
entry.logKey,
- "extracting promoted notification content"
+ "extracting promoted notification content",
)
val imageModelProvider = rowImageInflater.useForContentModel()
promotedNotificationContentExtractor
@@ -750,7 +757,7 @@ constructor(
) {
logger.logAsyncTaskProgress(
entry.logKey,
- "inflating public single line view model"
+ "inflating public single line view model",
)
if (bindParams.redactionType == REDACTION_TYPE_SENSITIVE_CONTENT) {
SingleLineViewInflater.inflateSingleLineViewModel(
@@ -852,18 +859,12 @@ constructor(
} else null
val expanded =
if (reInflateFlags and FLAG_CONTENT_VIEW_EXPANDED != 0) {
- logger.logAsyncTaskProgress(
- row.loggingKey,
- "creating expanded remote view",
- )
+ logger.logAsyncTaskProgress(row.loggingKey, "creating expanded remote view")
createExpandedView(builder, bindParams.isMinimized)
} else null
val headsUp =
if (reInflateFlags and FLAG_CONTENT_VIEW_HEADS_UP != 0) {
- logger.logAsyncTaskProgress(
- row.loggingKey,
- "creating heads up remote view",
- )
+ logger.logAsyncTaskProgress(row.loggingKey, "creating heads up remote view")
val isHeadsUpCompact = headsUpStyleProvider.shouldApplyCompactStyle()
if (isHeadsUpCompact) {
builder.createCompactHeadsUpContentView()
@@ -873,10 +874,7 @@ constructor(
} else null
val public =
if (reInflateFlags and FLAG_CONTENT_VIEW_PUBLIC != 0) {
- logger.logAsyncTaskProgress(
- row.loggingKey,
- "creating public remote view"
- )
+ logger.logAsyncTaskProgress(row.loggingKey, "creating public remote view")
if (
LockscreenOtpRedaction.isEnabled &&
bindParams.redactionType == REDACTION_TYPE_SENSITIVE_CONTENT
@@ -1142,7 +1140,7 @@ constructor(
override fun setResultView(v: View) {
logger.logAsyncTaskProgress(
entry.logKey,
- "group header view applied"
+ "group header view applied",
)
result.inflatedGroupHeaderView = v as NotificationHeaderView?
}
@@ -1198,7 +1196,7 @@ constructor(
}
logger.logAsyncTaskProgress(
entry.logKey,
- "applying low priority group header view"
+ "applying low priority group header view",
)
applyRemoteView(
inflationExecutor = inflationExecutor,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowImageInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowImageInflater.kt
index 95ef60fdcefe..7bac17f4c227 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowImageInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowImageInflater.kt
@@ -83,9 +83,9 @@ interface RowImageInflater {
inline fun featureFlagEnabled() = PromotedNotificationUiAod.isEnabled
@JvmStatic
- fun newInstance(previousIndex: ImageModelIndex?): RowImageInflater =
+ fun newInstance(previousIndex: ImageModelIndex?, reinflating: Boolean): RowImageInflater =
if (featureFlagEnabled()) {
- RowImageInflaterImpl(previousIndex)
+ RowImageInflaterImpl(previousIndex, reinflating)
} else {
RowImageInflaterStub
}
@@ -110,7 +110,8 @@ private object RowImageInflaterStub : RowImageInflater {
override fun getNewImageIndex(): ImageModelIndex? = null
}
-class RowImageInflaterImpl(private val previousIndex: ImageModelIndex?) : RowImageInflater {
+class RowImageInflaterImpl(private val previousIndex: ImageModelIndex?, val reinflating: Boolean) :
+ RowImageInflater {
private val providedImages = mutableListOf<LazyImage>()
/**
@@ -139,10 +140,15 @@ class RowImageInflaterImpl(private val previousIndex: ImageModelIndex?) : RowIma
// ensure all entries are stored
providedImages.add(newImage)
// load the image result from the index into our new object
- previousIndex?.findImage(iconData, sizeClass, transform)?.let {
- // copy the result into our new object
- newImage.result = it
- }
+ previousIndex
+ // skip the cached image when we are "reinflating" to avoid stale content
+ // being displayed from the same URI after the app updated the notif
+ ?.takeUnless { reinflating }
+ ?.findImage(iconData, sizeClass, transform)
+ ?.let {
+ // copy the result into our new object
+ newImage.result = it
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt
index a277597e23df..c1aa5f12aa99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt
@@ -266,7 +266,7 @@ constructor(
combine(shadeModeInteractor.shadeMode, shadeInteractor.qsExpansion) { shadeMode, qsExpansion
->
when (shadeMode) {
- is ShadeMode.Dual -> false
+ is ShadeMode.Dual,
is ShadeMode.Split -> true
is ShadeMode.Single -> qsExpansion < 0.5f
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index face1c7512ce..fc721bfae369 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -109,6 +109,7 @@ import com.android.systemui.AutoReinflateContainer;
import com.android.systemui.CoreStartable;
import com.android.systemui.DejankUtils;
import com.android.systemui.EventLogTags;
+import com.android.systemui.Flags;
import com.android.systemui.InitController;
import com.android.systemui.Prefs;
import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController;
@@ -3183,12 +3184,27 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
new ActivityTransitionAnimator.Listener() {
@Override
public void onTransitionAnimationStart() {
- mKeyguardViewMediator.setBlursDisabledForAppLaunch(true);
+ if (!Flags.notificationShadeBlur() || !Flags.moveTransitionAnimationLayer()) {
+ mKeyguardViewMediator.setBlursDisabledForAppLaunch(true);
+ }
+ }
+
+ @Override
+ public void onTransitionAnimationProgress(float linearProgress) {
+ if (Flags.notificationShadeBlur() && Flags.moveTransitionAnimationLayer()) {
+ mNotificationShadeDepthControllerLazy.get()
+ .onTransitionAnimationProgress(linearProgress);
+ }
}
@Override
public void onTransitionAnimationEnd() {
- mKeyguardViewMediator.setBlursDisabledForAppLaunch(false);
+ if (Flags.notificationShadeBlur() && Flags.moveTransitionAnimationLayer()) {
+ mNotificationShadeDepthControllerLazy.get()
+ .onTransitionAnimationEnd();
+ } else {
+ mKeyguardViewMediator.setBlursDisabledForAppLaunch(false);
+ }
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTileGrid.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTileGrid.kt
index 16f24f1d5821..5d7ce91b332c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTileGrid.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTileGrid.kt
@@ -34,7 +34,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.systemui.Flags
-import com.android.systemui.qs.panels.ui.compose.PagerDots
+import com.android.systemui.common.ui.compose.PagerDots
import com.android.systemui.statusbar.policy.ui.dialog.viewmodel.ModesDialogViewModel
@Composable
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactoryTest.kt
index 7c8822bc11ec..96ef8b690145 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactoryTest.kt
@@ -18,8 +18,6 @@ package com.android.systemui.bluetooth.qsdialog
import android.bluetooth.BluetoothDevice
import android.graphics.drawable.Drawable
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
import android.testing.TestableLooper
import android.util.Pair
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -29,7 +27,6 @@ import com.android.dx.mockito.inline.extended.StaticMockitoSession
import com.android.settingslib.bluetooth.BluetoothUtils
import com.android.settingslib.bluetooth.CachedBluetoothDevice
import com.android.settingslib.bluetooth.LocalBluetoothManager
-import com.android.settingslib.flags.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.res.R
import com.google.common.truth.Truth.assertThat
@@ -208,42 +205,6 @@ class DeviceItemFactoryTest : SysuiTestCase() {
}
@Test
- @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
- fun testSavedFactory_isFilterMatched_bondedAndNotConnected_returnsTrue() {
- `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
- `when`(cachedDevice.isConnected).thenReturn(false)
-
- assertThat(
- savedDeviceItemFactory.isFilterMatched(context, cachedDevice, isOngoingCall = false)
- )
- .isTrue()
- }
-
- @Test
- @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
- fun testSavedFactory_isFilterMatched_connected_returnsFalse() {
- `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
- `when`(cachedDevice.isConnected).thenReturn(true)
-
- assertThat(
- savedDeviceItemFactory.isFilterMatched(context, cachedDevice, isOngoingCall = false)
- )
- .isFalse()
- }
-
- @Test
- @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
- fun testSavedFactory_isFilterMatched_notBonded_returnsFalse() {
- `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE)
-
- assertThat(
- savedDeviceItemFactory.isFilterMatched(context, cachedDevice, isOngoingCall = false)
- )
- .isFalse()
- }
-
- @Test
- @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
fun testSavedFactory_isFilterMatched_exclusivelyManaged_returnsFalse() {
`when`(cachedDevice.device).thenReturn(bluetoothDevice)
`when`(BluetoothUtils.isExclusivelyManagedBluetoothDevice(any(), any())).thenReturn(true)
@@ -255,7 +216,6 @@ class DeviceItemFactoryTest : SysuiTestCase() {
}
@Test
- @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
fun testSavedFactory_isFilterMatched_notExclusiveManaged_returnsTrue() {
`when`(cachedDevice.device).thenReturn(bluetoothDevice)
`when`(BluetoothUtils.isExclusivelyManagedBluetoothDevice(any(), any())).thenReturn(false)
@@ -269,7 +229,6 @@ class DeviceItemFactoryTest : SysuiTestCase() {
}
@Test
- @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
fun testSavedFactory_isFilterMatched_notExclusivelyManaged_connected_returnsFalse() {
`when`(cachedDevice.device).thenReturn(bluetoothDevice)
`when`(BluetoothUtils.isExclusivelyManagedBluetoothDevice(any(), any())).thenReturn(false)
@@ -283,35 +242,6 @@ class DeviceItemFactoryTest : SysuiTestCase() {
}
@Test
- @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
- fun testConnectedFactory_isFilterMatched_bondedAndConnected_returnsTrue() {
- `when`(BluetoothUtils.isConnectedBluetoothDevice(any(), any())).thenReturn(true)
-
- assertThat(
- connectedDeviceItemFactory.isFilterMatched(
- context,
- cachedDevice,
- isOngoingCall = false,
- )
- )
- .isTrue()
- }
-
- @Test
- @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
- fun testConnectedFactory_isFilterMatched_notConnected_returnsFalse() {
- assertThat(
- connectedDeviceItemFactory.isFilterMatched(
- context,
- cachedDevice,
- isOngoingCall = false,
- )
- )
- .isFalse()
- }
-
- @Test
- @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
fun testConnectedFactory_isFilterMatched_exclusivelyManaged_returnsFalse() {
`when`(cachedDevice.device).thenReturn(bluetoothDevice)
`when`(BluetoothUtils.isExclusivelyManagedBluetoothDevice(any(), any())).thenReturn(true)
@@ -327,7 +257,6 @@ class DeviceItemFactoryTest : SysuiTestCase() {
}
@Test
- @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
fun testConnectedFactory_isFilterMatched_noExclusiveManager_returnsTrue() {
`when`(cachedDevice.device).thenReturn(bluetoothDevice)
`when`(BluetoothUtils.isExclusivelyManagedBluetoothDevice(any(), any())).thenReturn(false)
@@ -344,7 +273,6 @@ class DeviceItemFactoryTest : SysuiTestCase() {
}
@Test
- @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
fun testConnectedFactory_isFilterMatched_notExclusivelyManaged_notConnected_returnsFalse() {
`when`(cachedDevice.device).thenReturn(bluetoothDevice)
`when`(BluetoothUtils.isExclusivelyManagedBluetoothDevice(any(), any())).thenReturn(false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java
index 562481567536..5c893da45b8d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java
@@ -28,7 +28,6 @@ import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBO
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SHOWN_EXPANDED;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SHOWN_MINIMIZED;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SWIPE_DISMISSED;
-import static com.android.systemui.flags.Flags.CLIPBOARD_IMAGE_TIMEOUT;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -60,7 +59,6 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastSender;
-import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.screenshot.TimeoutHandler;
import com.android.systemui.settings.FakeDisplayTracker;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -102,7 +100,6 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
@Mock
private UiEventLogger mUiEventLogger;
private FakeDisplayTracker mDisplayTracker = new FakeDisplayTracker(mContext);
- private FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags();
@Mock
private Animator mAnimator;
@@ -152,8 +149,6 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
mSampleClipData = new ClipData("Test", new String[]{"text/plain"},
new ClipData.Item("Test Item"));
-
- mFeatureFlags.set(CLIPBOARD_IMAGE_TIMEOUT, true); // turned off for legacy tests
}
/**
@@ -170,13 +165,13 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
getFakeBroadcastDispatcher(),
mBroadcastSender,
mTimeoutHandler,
- mFeatureFlags,
mClipboardUtils,
mExecutor,
mClipboardImageLoader,
mClipboardTransitionExecutor,
mClipboardIndicationProvider,
- mUiEventLogger);
+ mUiEventLogger,
+ new ActionIntentCreator());
verify(mClipboardOverlayView).setCallbacks(mOverlayCallbacksCaptor.capture());
mCallbacks = mOverlayCallbacksCaptor.getValue();
}
@@ -193,7 +188,6 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
ClipData clipData = new ClipData("", new String[]{"image/png"},
new ClipData.Item(Uri.parse("")));
- mFeatureFlags.set(CLIPBOARD_IMAGE_TIMEOUT, false);
mOverlayController.setClipData(clipData, "");
@@ -208,7 +202,6 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
ClipData clipData = new ClipData("", new String[]{"resource/png"},
new ClipData.Item(Uri.parse("")));
- mFeatureFlags.set(CLIPBOARD_IMAGE_TIMEOUT, false);
mOverlayController.setClipData(clipData, "");
@@ -219,7 +212,6 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
@Test
public void test_setClipData_textData_legacy() {
- mFeatureFlags.set(CLIPBOARD_IMAGE_TIMEOUT, false);
initController();
mOverlayController.setClipData(mSampleClipData, "abc");
@@ -232,7 +224,6 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
@Test
public void test_setClipData_sensitiveTextData_legacy() {
- mFeatureFlags.set(CLIPBOARD_IMAGE_TIMEOUT, false);
initController();
ClipDescription description = mSampleClipData.getDescription();
@@ -250,7 +241,6 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
@Test
public void test_setClipData_repeatedCalls_legacy() {
when(mAnimator.isRunning()).thenReturn(true);
- mFeatureFlags.set(CLIPBOARD_IMAGE_TIMEOUT, false);
initController();
mOverlayController.setClipData(mSampleClipData, "");
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/LauncherProxyServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recents/LauncherProxyServiceTest.kt
index 0a5efb7bb286..2d3f538689b3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/LauncherProxyServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/recents/LauncherProxyServiceTest.kt
@@ -162,8 +162,7 @@ class LauncherProxyServiceTest : SysuiTestCase() {
wakefulnessLifecycle.dispatchFinishedGoingToSleep()
clearInvocations(launcherProxy)
- wakefulnessLifecycle
- .dispatchFinishedWakingUp()
+ wakefulnessLifecycle.dispatchFinishedWakingUp()
verify(launcherProxy)
.onSystemUiStateChanged(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/CombinedConditionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/CombinedConditionTest.kt
index 8418598c256b..116a2caa6dda 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/CombinedConditionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/CombinedConditionTest.kt
@@ -19,9 +19,9 @@ package com.android.systemui.shared.condition
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.shared.condition.Condition.START_EAGERLY
-import com.android.systemui.shared.condition.Condition.START_LAZILY
-import com.android.systemui.shared.condition.Condition.START_WHEN_NEEDED
+import com.android.systemui.shared.condition.Condition.Companion.START_EAGERLY
+import com.android.systemui.shared.condition.Condition.Companion.START_LAZILY
+import com.android.systemui.shared.condition.Condition.Companion.START_WHEN_NEEDED
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -40,7 +40,7 @@ class CombinedConditionTest : SysuiTestCase() {
scope: CoroutineScope,
initialValue: Boolean?,
overriding: Boolean = false,
- @StartStrategy private val startStrategy: Int = START_WHEN_NEEDED,
+ @StartStrategy override val startStrategy: Int = START_WHEN_NEEDED,
) : Condition(scope, initialValue, overriding) {
private var _started = false
val started: Boolean
@@ -54,10 +54,6 @@ class CombinedConditionTest : SysuiTestCase() {
_started = false
}
- override fun getStartStrategy(): Int {
- return startStrategy
- }
-
fun setValue(value: Boolean?) {
value?.also { updateCondition(value) } ?: clearCondition()
}
@@ -75,13 +71,8 @@ class CombinedConditionTest : SysuiTestCase() {
val combinedCondition =
CombinedCondition(
scope = this,
- conditions =
- listOf(
- eagerCondition,
- lazyCondition,
- startWhenNeededCondition,
- ),
- operand = Evaluator.OP_OR
+ conditions = listOf(eagerCondition, lazyCondition, startWhenNeededCondition),
+ operand = Evaluator.OP_OR,
)
val callback = Condition.Callback {}
@@ -124,13 +115,8 @@ class CombinedConditionTest : SysuiTestCase() {
val combinedCondition =
CombinedCondition(
scope = this,
- conditions =
- listOf(
- startWhenNeededCondition,
- lazyCondition,
- eagerCondition,
- ),
- operand = Evaluator.OP_AND
+ conditions = listOf(startWhenNeededCondition, lazyCondition, eagerCondition),
+ operand = Evaluator.OP_AND,
)
val callback = Condition.Callback {}
@@ -175,7 +161,7 @@ class CombinedConditionTest : SysuiTestCase() {
FakeCondition(
scope = this,
initialValue = false,
- startStrategy = START_WHEN_NEEDED
+ startStrategy = START_WHEN_NEEDED,
)
}
.toList()
@@ -214,7 +200,7 @@ class CombinedConditionTest : SysuiTestCase() {
FakeCondition(
scope = this,
initialValue = false,
- startStrategy = START_WHEN_NEEDED
+ startStrategy = START_WHEN_NEEDED,
)
}
.toList()
@@ -262,7 +248,7 @@ class CombinedConditionTest : SysuiTestCase() {
FakeCondition(
scope = this,
initialValue = false,
- startStrategy = START_WHEN_NEEDED
+ startStrategy = START_WHEN_NEEDED,
)
}
.toList()
@@ -300,9 +286,9 @@ class CombinedConditionTest : SysuiTestCase() {
overridingCondition1,
lazyCondition,
startWhenNeededCondition,
- overridingCondition2
+ overridingCondition2,
),
- operand = Evaluator.OP_OR
+ operand = Evaluator.OP_OR,
)
val callback = Condition.Callback {}
@@ -414,11 +400,7 @@ class CombinedConditionTest : SysuiTestCase() {
fun testEmptyConditions() = runSelfCancelingTest {
for (operand in intArrayOf(Evaluator.OP_OR, Evaluator.OP_AND)) {
val combinedCondition =
- CombinedCondition(
- scope = this,
- conditions = emptyList(),
- operand = operand,
- )
+ CombinedCondition(scope = this, conditions = emptyList(), operand = operand)
val callback = Condition.Callback {}
combinedCondition.addCallback(callback)
@@ -435,9 +417,7 @@ class CombinedConditionTest : SysuiTestCase() {
* Executes the given block of execution within the scope of a dedicated [CoroutineScope] which
* is then automatically canceled and cleaned-up.
*/
- private fun runSelfCancelingTest(
- block: suspend CoroutineScope.() -> Unit,
- ) =
+ private fun runSelfCancelingTest(block: suspend CoroutineScope.() -> Unit) =
runBlocking(IMMEDIATE) {
val scope = CoroutineScope(coroutineContext + Job())
block(scope)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowImageInflaterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowImageInflaterTest.kt
index 86689cb88569..d0357603665d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowImageInflaterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowImageInflaterTest.kt
@@ -21,6 +21,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUiAod
+import com.android.systemui.statusbar.notification.row.shared.IconData
import com.android.systemui.statusbar.notification.row.shared.ImageModel
import com.android.systemui.statusbar.notification.row.shared.ImageModelProvider.ImageSizeClass.SmallSquare
import com.google.common.truth.Truth.assertThat
@@ -38,20 +39,22 @@ class RowImageInflaterTest : SysuiTestCase() {
private val resIcon2 = Icon.createWithResource(context, android.R.drawable.ic_delete)
private val badUriIcon = Icon.createWithContentUri("content://com.test/does_not_exist")
+ private var latestImageModelIndex: ImageModelIndex? = null
+
@Before
fun setUp() {
- rowImageInflater = RowImageInflater.newInstance(null)
+ rowImageInflater = RowImageInflater.newInstance(null, reinflating = false)
}
@Test
fun getNewImageIndex_returnsNullWhenUnused() {
- assertThat(rowImageInflater.getNewImageIndex()).isNull()
+ assertThat(getNewImageIndex()).isNull()
}
@Test
fun getNewImageIndex_returnsEmptyIndexWhenZeroImagesLoaded() {
assertThat(getImageModelsForIcons()).isEmpty()
- val result = rowImageInflater.getNewImageIndex()
+ val result = getNewImageIndex()
assertThat(result).isNotNull()
assertThat(result?.contentsForTesting).isEmpty()
}
@@ -59,7 +62,7 @@ class RowImageInflaterTest : SysuiTestCase() {
@Test
fun getNewImageIndex_returnsSingleImageWhenOneImageLoaded() {
assertThat(getImageModelsForIcons(resIcon1)).hasSize(1)
- val result = rowImageInflater.getNewImageIndex()
+ val result = getNewImageIndex()
assertThat(result).isNotNull()
assertThat(result?.contentsForTesting).hasSize(1)
}
@@ -85,7 +88,7 @@ class RowImageInflaterTest : SysuiTestCase() {
assertThat(providedModels[3].drawable).isNotNull()
// VERIFY the returned index has all 3 entries, 2 of which have drawables
- val indexGen1 = rowImageInflater.getNewImageIndex()
+ val indexGen1 = getNewImageIndex()
assertThat(indexGen1).isNotNull()
assertThat(indexGen1?.contentsForTesting).hasSize(3)
assertThat(indexGen1?.contentsForTesting?.mapNotNull { it.drawable }).hasSize(2)
@@ -96,7 +99,7 @@ class RowImageInflaterTest : SysuiTestCase() {
exampleFirstGeneration()
// THEN start a new generation of the inflation
- rowImageInflater = RowImageInflater.newInstance(rowImageInflater.getNewImageIndex())
+ rowImageInflater = RowImageInflater.newInstance(getNewImageIndex(), reinflating = false)
getNewImageIndex_returnsEmptyIndexWhenZeroImagesLoaded()
}
@@ -104,13 +107,47 @@ class RowImageInflaterTest : SysuiTestCase() {
@Test
fun exampleSecondGeneration_whichLoadsOneImage() {
exampleFirstGeneration()
+ val gen1Index = latestImageModelIndex!!
// THEN start a new generation of the inflation
- rowImageInflater = RowImageInflater.newInstance(rowImageInflater.getNewImageIndex())
+ rowImageInflater = RowImageInflater.newInstance(gen1Index, reinflating = false)
getNewImageIndex_returnsSingleImageWhenOneImageLoaded()
+ val gen2Index = latestImageModelIndex!!
+
+ // VERIFY that the drawable was copied from the previous index
+ val gen1model = gen1Index.findModel(resIcon1)
+ val gen2model = gen2Index.findModel(resIcon1)
+ assertThat(gen2model).isNotSameInstanceAs(gen1model)
+ assertThat(gen2model.drawable).isSameInstanceAs(gen1model.drawable)
}
+ @Test
+ fun exampleSecondGeneration_reinflating_whichLoadsOneImage() {
+ exampleFirstGeneration()
+ val gen1Index = latestImageModelIndex!!
+
+ // THEN start a new generation of the inflation
+ rowImageInflater = RowImageInflater.newInstance(gen1Index, reinflating = true)
+
+ getNewImageIndex_returnsSingleImageWhenOneImageLoaded()
+ val gen2Index = latestImageModelIndex!!
+
+ // VERIFY that the drawable was reloaded rather than copied from the previous index
+ val gen1model = gen1Index.findModel(resIcon1)
+ val gen2model = gen2Index.findModel(resIcon1)
+ assertThat(gen2model).isNotSameInstanceAs(gen1model)
+ assertThat(gen2model.drawable).isNotSameInstanceAs(gen1model.drawable)
+ }
+
+ private fun ImageModelIndex.findModel(icon: Icon): LazyImage =
+ IconData.fromIcon(icon)
+ .let { iconData -> contentsForTesting.find { it.icon == iconData } }
+ .also { assertThat(it).isNotNull() }!!
+
+ private fun getNewImageIndex(): ImageModelIndex? =
+ rowImageInflater.getNewImageIndex().also { latestImageModelIndex = it }
+
private fun getImageModelsForIcons(vararg icons: Icon): List<ImageModel> {
val provider = rowImageInflater.useForContentModel()
return icons.map { icon ->
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
index af89403c5397..623989ec5809 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
@@ -67,6 +67,7 @@ import com.android.systemui.scene.shared.model.sceneDataSource
import com.android.systemui.scene.ui.view.mockWindowRootViewProvider
import com.android.systemui.settings.brightness.data.repository.brightnessMirrorShowingRepository
import com.android.systemui.settings.displayTracker
+import com.android.systemui.shade.data.repository.fakeShadeDisplaysRepository
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.shade.domain.interactor.shadeLayoutParams
@@ -203,5 +204,6 @@ class KosmosJavaAdapter() {
val windowRootViewBlurInteractor by lazy { kosmos.windowRootViewBlurInteractor }
val sysuiState by lazy { kosmos.sysUiState }
val displayTracker by lazy { kosmos.displayTracker }
+ val fakeShadeDisplaysRepository by lazy { kosmos.fakeShadeDisplaysRepository }
val sysUIStateDispatcher by lazy { kosmos.sysUIStateDispatcher }
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/model/SysUiStateKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/model/SysUiStateKosmos.kt
index 848fed6b0590..11bd4c7b7940 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/model/SysUiStateKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/model/SysUiStateKosmos.kt
@@ -32,12 +32,7 @@ val Kosmos.sysUiStateFactory by Fixture {
object : SysUiStateImpl.Factory {
override fun create(displayId: Int): SysUiStateImpl {
return spy(
- SysUiStateImpl(
- displayId,
- sceneContainerPlugin,
- dumpManager,
- sysUIStateDispatcher,
- )
+ SysUiStateImpl(displayId, sceneContainerPlugin, dumpManager, sysUIStateDispatcher)
)
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorKosmos.kt
index da879d9e314d..2b3158da38f9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorKosmos.kt
@@ -39,7 +39,8 @@ fun Kosmos.setPromotedContent(entry: NotificationEntry) {
promotedNotificationContentExtractor.extractContent(
entry,
Notification.Builder.recoverBuilder(applicationContext, entry.sbn.notification),
- RowImageInflater.newInstance(null).useForContentModel(),
+ RowImageInflater.newInstance(previousIndex = null, reinflating = false)
+ .useForContentModel(),
)
entry.promotedNotificationContentModel =
requireNotNull(extractedContent) { "extractContent returned null" }
diff --git a/ravenwood/scripts/list-ravenwood-tests.sh b/ravenwood/scripts/list-ravenwood-tests.sh
index 05f3fdffdaa7..5d7daeb1c304 100755
--- a/ravenwood/scripts/list-ravenwood-tests.sh
+++ b/ravenwood/scripts/list-ravenwood-tests.sh
@@ -15,4 +15,20 @@
# List all the ravenwood test modules.
-jq -r 'to_entries[] | select( .value.compatibility_suites | index("ravenwood-tests") ) | .key' "$OUT/module-info.json" | sort
+set -e
+
+in="$OUT/module-info.json"
+cache="$OUT/ravenwood-test-list.cached.tmp"
+cache_temp="$OUT/ravenwood-test-list.temp.tmp"
+
+if [[ "$in" -nt "$cache" ]] ; then
+ rm -f "$cache_temp" "$cache"
+
+ # First, create to a temp file, and once it's completed, rename it
+ # to the actual cache file, so that if the command failed or is interrupted,
+ # we don't update the cache.
+ jq -r 'to_entries[] | select( .value.compatibility_suites | index("ravenwood-tests") ) | .key' "$OUT/module-info.json" | sort > "$cache_temp"
+ mv "$cache_temp" "$cache"
+fi
+
+cat "$cache"
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 1503d889c298..eea667ef2f39 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1443,17 +1443,32 @@ class ProcessRecord implements WindowProcessListener {
void onProcessFrozen() {
mProfile.onProcessFrozen();
- if (mThread != null) mThread.onProcessPaused();
+ final ApplicationThreadDeferred t;
+ synchronized (mService) {
+ t = mThread;
+ }
+ // Release the lock before calling the notifier, in case that calls back into AM.
+ if (t != null) t.onProcessPaused();
}
void onProcessUnfrozen() {
- if (mThread != null) mThread.onProcessUnpaused();
+ final ApplicationThreadDeferred t;
+ synchronized (mService) {
+ t = mThread;
+ }
+ // Release the lock before calling the notifier, in case that calls back into AM.
+ if (t != null) t.onProcessUnpaused();
mProfile.onProcessUnfrozen();
mServices.onProcessUnfrozen();
}
void onProcessFrozenCancelled() {
- if (mThread != null) mThread.onProcessPausedCancelled();
+ final ApplicationThreadDeferred t;
+ synchronized (mService) {
+ t = mThread;
+ }
+ // Release the lock before calling the notifier, in case that calls back into AM.
+ if (t != null) t.onProcessPausedCancelled();
mServices.onProcessFrozenCancelled();
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index d402f010281f..7016c11b69e7 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -2442,7 +2442,10 @@ public final class DisplayManagerService extends SystemService {
applyDisplayChangedLocked(display);
}
- if (mDisplayTopologyCoordinator != null) {
+ // The default display should always be added to the topology. Other displays will be added
+ // upon calling onDisplayBelongToTopologyChanged().
+ if (mDisplayTopologyCoordinator != null
+ && display.getDisplayIdLocked() == Display.DEFAULT_DISPLAY) {
mDisplayTopologyCoordinator.onDisplayAdded(display.getDisplayInfoLocked());
}
}
@@ -6037,6 +6040,18 @@ public final class DisplayManagerService extends SystemService {
}
@Override
+ public void onDisplayBelongToTopologyChanged(int displayId, boolean inTopology) {
+ if (mDisplayTopologyCoordinator == null) {
+ return;
+ }
+ if (inTopology) {
+ mDisplayTopologyCoordinator.onDisplayAdded(getDisplayInfo(displayId));
+ } else {
+ mDisplayTopologyCoordinator.onDisplayRemoved(displayId);
+ }
+ }
+
+ @Override
public void reloadTopologies(final int userId) {
// Reload topologies only if the userId matches the current user id.
if (userId == mCurrentUserId) {
diff --git a/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java b/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java
index 2618cf40d113..997fff58b952 100644
--- a/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java
+++ b/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java
@@ -267,11 +267,6 @@ class DisplayTopologyCoordinator {
+ "type is EXTERNAL or OVERLAY and !mIsExtendedDisplayEnabled");
return false;
}
- if (info.displayGroupId != Display.DEFAULT_DISPLAY_GROUP) {
- Slog.d(TAG, "Display " + info.displayId + " not allowed in topology because "
- + "it is not in the default display group");
- return false;
- }
return true;
}
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 6ab30595e46b..098f113dc11a 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -897,7 +897,7 @@ final class DefaultPermissionGrantPolicy {
SearchManager.INTENT_ACTION_GLOBAL_SEARCH, userId);
grantPermissionsToSystemPackage(pm, voiceSearchPackage,
userId, PHONE_PERMISSIONS, CALENDAR_PERMISSIONS, NEARBY_DEVICES_PERMISSIONS,
- COARSE_BACKGROUND_LOCATION_PERMISSIONS);
+ COARSE_BACKGROUND_LOCATION_PERMISSIONS, CONTACTS_PERMISSIONS);
revokeRuntimePermissions(pm, voiceSearchPackage,
FINE_LOCATION_PERMISSIONS, false, userId);
}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index d620e98d3437..bac732637d8d 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1173,12 +1173,19 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
return;
}
- final ComponentName wpService = mWallpaper.getComponent();
// The broadcast of package update could be delayed after service disconnected. Try
// to re-bind the service for 10 seconds.
mWallpaper.mBindSource = BindSource.CONNECTION_TRY_TO_REBIND;
- if (bindWallpaperComponentLocked(
- wpService, true, false, mWallpaper, null)) {
+ boolean success;
+ if (liveWallpaperContentHandling()) {
+ success = bindWallpaperDescriptionLocked(
+ mWallpaper.getDescription(), /* force= */ true,
+ /* fromUser= */ false, mWallpaper, /* reply= */ null);
+ } else {
+ success = bindWallpaperComponentLocked(mWallpaper.getComponent(), /* force= */
+ true, /* fromUser= */false, mWallpaper, /* reply= */ null);
+ }
+ if (success) {
mWallpaper.connection.scheduleTimeoutLocked();
} else if (SystemClock.uptimeMillis() - mWallpaper.lastDiedTime
< WALLPAPER_RECONNECT_TIMEOUT_MS) {
@@ -1189,7 +1196,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
// Timeout
Slog.w(TAG, "Reverting to built-in wallpaper!");
clearWallpaperLocked(mWallpaper.mWhich, mWallpaper.userId, false, null);
- final String flattened = wpService.flattenToString();
+ final String flattened = mWallpaper.getComponent().flattenToString();
EventLog.writeEvent(EventLogTags.WP_WALLPAPER_CRASHED,
flattened.substring(0, Math.min(flattened.length(),
MAX_WALLPAPER_COMPONENT_LOG_LENGTH)));
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index 36686fc086f1..2287a687700c 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -288,9 +288,10 @@ public class BackgroundActivityStartController {
}
private boolean isHomeApp(int uid, @Nullable String packageName) {
- if (getService().mHomeProcess != null) {
- // Fast check
- return uid == getService().mHomeProcess.mUid;
+ WindowProcessController homeProcess = getService().mHomeProcess;
+ if (homeProcess != null && (homeProcess.mUid != SYSTEM_UID || packageName == null)) {
+ // Fast check (skip if sharing system UID and we have a package name)
+ return uid == homeProcess.mUid;
}
if (packageName == null) {
return false;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 530b507bcc0f..353ccd5836c8 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3262,12 +3262,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
Slog.e(TAG, "ShouldShowSystemDecors shouldn't be updated when the flag is off.");
}
- final boolean shouldShowContent;
if (!allowContentModeSwitch()) {
return;
}
- shouldShowContent = mDisplay.canHostTasks();
+ final boolean shouldShowContent = mDisplay.canHostTasks();
if (shouldShowContent == mWmService.mDisplayWindowSettings
.shouldShowSystemDecorsLocked(this)) {
return;
@@ -3277,6 +3276,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
if (!shouldShowContent) {
clearAllTasksOnDisplay(null /* clearTasksCallback */, false /* isRemovingDisplay */);
}
+
+ // If the display is allowed to show content, then it belongs to the display topology;
+ // vice versa.
+ mWmService.mDisplayManagerInternal.onDisplayBelongToTopologyChanged(mDisplayId,
+ /* inTopology= */ shouldShowContent);
}
/**
@@ -3302,6 +3306,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return false;
}
+ if (shouldNeverShowSystemDecorations()) {
+ return false;
+ }
+
// TODO(b/391965805): Remove this after introducing FLAG_ALLOW_CONTENT_MODE_SWITCH.
if ((mDisplay.getFlags() & Display.FLAG_REAR) != 0) {
return false;
@@ -5666,16 +5674,23 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return type == TRANSIT_OPEN || type == TRANSIT_TO_FRONT;
}
- /**
- * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
- */
- boolean isSystemDecorationsSupported() {
+ private boolean shouldNeverShowSystemDecorations() {
if (mDisplayId == mWmService.mVr2dDisplayId) {
// VR virtual display will be used to run and render 2D app within a VR experience.
- return false;
+ return true;
}
if (!isTrusted()) {
// Do not show system decorations on untrusted virtual display.
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
+ */
+ boolean isSystemDecorationsSupported() {
+ if (shouldNeverShowSystemDecorations()) {
return false;
}
if (mWmService.mDisplayWindowSettings.shouldShowSystemDecorsLocked(this)
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index 48ffccbca935..56579206566f 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -240,6 +240,11 @@ class DisplayWindowSettings {
mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
}
+ /**
+ * Returns {@code true} if either the display is the default display, or the display is allowed
+ * to dynamically add/remove system decorations and the system decorations should be shown on it
+ * currently.
+ */
boolean shouldShowSystemDecorsLocked(@NonNull DisplayContent dc) {
if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) {
// Default display should show system decors.
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 394fe6f0e8ed..cf201c9f34f0 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2772,11 +2772,17 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
return;
}
- if (ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT.isTrue()
- && display.allowContentModeSwitch()) {
- mWindowManager.mDisplayWindowSettings
- .setShouldShowSystemDecorsInternalLocked(display,
- display.mDisplay.canHostTasks());
+ if (ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT.isTrue()) {
+ if (display.allowContentModeSwitch()) {
+ mWindowManager.mDisplayWindowSettings
+ .setShouldShowSystemDecorsInternalLocked(display,
+ display.mDisplay.canHostTasks());
+ }
+
+ final boolean inTopology = mWindowManager.mDisplayWindowSettings
+ .shouldShowSystemDecorsLocked(display);
+ mWmService.mDisplayManagerInternal.onDisplayBelongToTopologyChanged(displayId,
+ inTopology);
}
startSystemDecorations(display, "displayAdded");
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 22f0278b3a30..d16c301cec40 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -4497,7 +4497,7 @@ class Task extends TaskFragment {
}
void onPictureInPictureParamsChanged() {
- if (inPinnedWindowingMode() || Flags.enableDesktopWindowingPip()) {
+ if (inPinnedWindowingMode() || DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PIP.isTrue()) {
dispatchTaskInfoChangedIfNeeded(true /* force */);
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
index a81a0b3251c8..4b98a723fc2d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -50,6 +50,7 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
+import android.util.PrintWriterPrinter;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
@@ -1484,5 +1485,12 @@ class ActiveAdmin {
pw.print("mProvisioningContext=");
pw.println(mProvisioningContext);
}
+
+ if (info != null) {
+ pw.println("DeviceAdminInfo:");
+ pw.increaseIndent();
+ info.dump(new PrintWriterPrinter(pw), "");
+ pw.decreaseIndent();
+ }
}
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index 65585d06ff06..1f8ccde98d35 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -3914,6 +3914,7 @@ public class DisplayManagerServiceTest {
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
DisplayManagerService.BinderService displayManagerBinderService =
displayManager.new BinderService();
+ DisplayManagerInternal localService = displayManager.new LocalService();
Handler handler = displayManager.getDisplayHandler();
waitForIdleHandler(handler);
@@ -3922,8 +3923,8 @@ public class DisplayManagerServiceTest {
INTERNAL_EVENT_FLAG_TOPOLOGY_UPDATED);
waitForIdleHandler(handler);
- var topology = initDisplayTopology(displayManager, displayManagerBinderService, callback,
- handler, /*shouldEmitTopologyChangeEvent=*/ true);
+ var topology = initDisplayTopology(displayManager, displayManagerBinderService,
+ localService, callback, handler, /*shouldEmitTopologyChangeEvent=*/ true);
callback.clear();
callback.expectsEvent(TOPOLOGY_CHANGED_EVENT);
displayManagerBinderService.setDisplayTopology(topology);
@@ -3938,6 +3939,7 @@ public class DisplayManagerServiceTest {
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
DisplayManagerService.BinderService displayManagerBinderService =
displayManager.new BinderService();
+ DisplayManagerInternal localService = displayManager.new LocalService();
Handler handler = displayManager.getDisplayHandler();
waitForIdleHandler(handler);
@@ -3947,8 +3949,8 @@ public class DisplayManagerServiceTest {
STANDARD_DISPLAY_EVENTS);
waitForIdleHandler(handler);
- var topology = initDisplayTopology(displayManager, displayManagerBinderService, callback,
- handler, /*shouldEmitTopologyChangeEvent=*/ false);
+ var topology = initDisplayTopology(displayManager, displayManagerBinderService,
+ localService, callback, handler, /*shouldEmitTopologyChangeEvent=*/ false);
callback.clear();
callback.expectsEvent(TOPOLOGY_CHANGED_EVENT); // should not happen
displayManagerBinderService.setDisplayTopology(topology);
@@ -4706,15 +4708,16 @@ public class DisplayManagerServiceTest {
private DisplayTopology initDisplayTopology(DisplayManagerService displayManager,
DisplayManagerService.BinderService displayManagerBinderService,
- FakeDisplayManagerCallback callback,
+ DisplayManagerInternal localService, FakeDisplayManagerCallback callback,
Handler handler, boolean shouldEmitTopologyChangeEvent) {
Settings.Global.putInt(mContext.getContentResolver(),
DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS, 1);
callback.expectsEvent(TOPOLOGY_CHANGED_EVENT);
FakeDisplayDevice displayDevice0 =
- createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
+ createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_EXTERNAL);
int displayId0 = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService,
displayDevice0);
+ waitForIdleHandler(handler);
if (shouldEmitTopologyChangeEvent) {
callback.waitForExpectedEvent();
} else {
@@ -4728,6 +4731,11 @@ public class DisplayManagerServiceTest {
int displayId1 = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService,
displayDevice1);
waitForIdleHandler(handler);
+ // Non-default display should not be added until onDisplayBelongToTopologyChanged is called
+ // with true
+ callback.waitForNonExpectedEvent();
+ localService.onDisplayBelongToTopologyChanged(displayId1, true);
+ waitForIdleHandler(handler);
if (shouldEmitTopologyChangeEvent) {
callback.waitForExpectedEvent();
} else {
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt b/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt
index 3c134b5d5482..206c90d0481a 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt
@@ -220,17 +220,6 @@ class DisplayTopologyCoordinatorTest {
}
@Test
- fun addDisplay_notInDefaultDisplayGroup() {
- displayInfos[0].displayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1
-
- coordinator.onDisplayAdded(displayInfos[0])
-
- verify(mockTopology, never()).addDisplay(anyInt(), anyFloat(), anyFloat())
- verify(mockTopologyChangedCallback, never()).invoke(any())
- verify(mockTopologyStore, never()).restoreTopology(any())
- }
-
- @Test
fun updateDisplay() {
whenever(mockTopology.updateDisplay(eq(displayInfos[0].displayId), anyFloat(), anyFloat()))
.thenReturn(true)
@@ -349,17 +338,6 @@ class DisplayTopologyCoordinatorTest {
}
@Test
- fun updateDisplay_notInDefaultDisplayGroup() {
- displayInfos[0].displayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1
-
- coordinator.onDisplayChanged(displayInfos[0])
-
- verify(mockTopology, never()).updateDisplay(anyInt(), anyFloat(), anyFloat())
- verify(mockTopologyCopy, never()).getGraph(any())
- verify(mockTopologyChangedCallback, never()).invoke(any())
- }
-
- @Test
fun removeDisplay() {
addDisplay()
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index e4a1bf603cf0..34e9bed8463a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -31,6 +31,7 @@ import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.server.display.feature.flags.Flags.FLAG_ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT;
import static com.android.server.wm.ActivityRecord.State.FINISHING;
import static com.android.server.wm.ActivityRecord.State.PAUSED;
import static com.android.server.wm.ActivityRecord.State.PAUSING;
@@ -82,6 +83,7 @@ import android.os.UserHandle;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.util.Pair;
+import android.view.DisplayInfo;
import androidx.test.filters.MediumTest;
@@ -1379,6 +1381,23 @@ public class RootWindowContainerTests extends WindowTestsBase {
verify(controller, never()).notifyTaskProfileLocked(any(), anyInt());
}
+ @EnableFlags(FLAG_ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT)
+ @Test
+ public void testOnDisplayBelongToTopologyChanged() {
+ final DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.copyFrom(mDisplayInfo);
+ displayInfo.displayId = DEFAULT_DISPLAY + 1;
+ final DisplayContent dc = createNewDisplay(displayInfo);
+ final int displayId = dc.getDisplayId();
+
+ doReturn(dc).when(mRootWindowContainer).getDisplayContentOrCreate(displayId);
+ doReturn(true).when(mWm.mDisplayWindowSettings).shouldShowSystemDecorsLocked(dc);
+
+ mRootWindowContainer.onDisplayAdded(displayId);
+ verify(mWm.mDisplayManagerInternal, times(1)).onDisplayBelongToTopologyChanged(anyInt(),
+ anyBoolean());
+ }
+
/**
* Mock {@link RootWindowContainer#resolveHomeActivity} for returning consistent activity
* info for test cases.
diff --git a/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index d7f91e009c92..2093ccc86653 100644
--- a/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -156,19 +156,6 @@ class SeamlessAppRotationTest(flicker: LegacyFlickerTest) : RotationTransition(f
flicker.assertLayers { isVisible(testApp) }
}
- /** Checks that [testApp] layer covers the entire screen during the whole transition */
- @Presubmit
- @Test
- fun appLayerRotates() {
- flicker.assertLayers {
- this.invoke("entireScreenCovered") { entry ->
- entry.entry.displays.map { display ->
- entry.visibleRegion(testApp).coversExactly(display.layerStackSpace)
- }
- }
- }
- }
-
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. App is full screen")
@@ -225,7 +212,6 @@ class SeamlessAppRotationTest(flicker: LegacyFlickerTest) : RotationTransition(f
visibleLayersShownMoreThanOneConsecutiveEntry()
visibleWindowsShownMoreThanOneConsecutiveEntry()
- runAndIgnoreAssumptionViolation { appLayerRotates() }
runAndIgnoreAssumptionViolation { appLayerAlwaysVisible() }
runAndIgnoreAssumptionViolation { navBarLayerIsVisibleAtStartAndEnd() }
runAndIgnoreAssumptionViolation { navBarWindowIsAlwaysVisible() }
diff --git a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
index 7c24a4adca3d..98af8b2f53b5 100644
--- a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
@@ -39,7 +39,6 @@
android:value="true" />
<activity android:name=".SimpleActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.SimpleActivity"
- android:theme="@style/CutoutShortEdges"
android:label="SimpleActivity"
android:exported="true">
<intent-filter>
@@ -49,7 +48,6 @@
</activity>
<activity android:name=".ImeActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.ImeActivity"
- android:theme="@style/CutoutShortEdges"
android:label="ImeActivity"
android:exported="true">
<intent-filter>
@@ -58,7 +56,6 @@
</intent-filter>
</activity>
<activity android:name=".ImeActivityAutoFocus"
- android:theme="@style/CutoutShortEdges"
android:taskAffinity="com.android.server.wm.flicker.testapp.ImeActivityAutoFocus"
android:windowSoftInputMode="stateVisible"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
@@ -81,7 +78,6 @@
</activity>
<activity android:name=".SeamlessRotationActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.SeamlessRotationActivity"
- android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize"
android:showWhenLocked="true"
android:label="SeamlessActivity"
@@ -92,7 +88,6 @@
</intent-filter>
</activity>
<activity android:name=".NonResizeableActivity"
- android:theme="@style/CutoutShortEdges"
android:resizeableActivity="false"
android:taskAffinity="com.android.server.wm.flicker.testapp.NonResizeableActivity"
android:label="NonResizeableActivity"
@@ -174,7 +169,6 @@
</activity>
<activity android:name=".LaunchNewActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.LaunchNewActivity"
- android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize"
android:label="LaunchNewActivity"
android:exported="true">
@@ -185,7 +179,6 @@
</activity>
<activity android:name=".LaunchNewTaskActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.LaunchNewTaskActivity"
- android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize"
android:label="LaunchNewTaskActivity"
android:exported="true">
@@ -207,7 +200,6 @@
</activity>
<activity android:name=".PortraitOnlyActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.PortraitOnlyActivity"
- android:theme="@style/CutoutShortEdges"
android:screenOrientation="portrait"
android:configChanges="orientation|screenSize"
android:exported="true">
@@ -219,7 +211,6 @@
<activity android:name=".ImeEditorPopupDialogActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.ImeEditorPopupDialogActivity"
android:configChanges="orientation|screenSize"
- android:theme="@style/CutoutShortEdges"
android:label="ImeEditorPopupDialogActivity"
android:exported="true">
<intent-filter>
@@ -229,7 +220,6 @@
</activity>
<activity android:name=".ShowWhenLockedActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.ShowWhenLockedActivity"
- android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize"
android:label="ShowWhenLockedActivity"
android:showWhenLocked="true"
@@ -241,7 +231,6 @@
</activity>
<activity android:name=".NotificationActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.NotificationActivity"
- android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize"
android:label="NotificationActivity"
android:exported="true">
@@ -254,7 +243,6 @@
android:name=".ActivityEmbeddingMainActivity"
android:label="ActivityEmbedding Main"
android:taskAffinity="com.android.server.wm.flicker.testapp.ActivityEmbedding"
- android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:exported="true">
<intent-filter>
@@ -266,7 +254,6 @@
android:name=".ActivityEmbeddingTrampolineActivity"
android:label="ActivityEmbedding Trampoline"
android:taskAffinity="com.android.server.wm.flicker.testapp.ActivityEmbedding"
- android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:exported="false">
</activity>
@@ -274,7 +261,6 @@
android:name=".ActivityEmbeddingSecondaryActivity"
android:label="ActivityEmbedding Secondary"
android:taskAffinity="com.android.server.wm.flicker.testapp.ActivityEmbedding"
- android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:supportsPictureInPicture="true"
android:exported="false"/>
@@ -282,21 +268,18 @@
android:name=".ActivityEmbeddingThirdActivity"
android:label="ActivityEmbedding Third"
android:taskAffinity="com.android.server.wm.flicker.testapp.ActivityEmbedding"
- android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:exported="false"/>
<activity
android:name=".ActivityEmbeddingAlwaysExpandActivity"
android:label="ActivityEmbedding AlwaysExpand"
android:taskAffinity="com.android.server.wm.flicker.testapp.ActivityEmbedding"
- android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:exported="false"/>
<activity
android:name=".ActivityEmbeddingPlaceholderPrimaryActivity"
android:label="ActivityEmbedding Placeholder Primary"
android:taskAffinity="com.android.server.wm.flicker.testapp.ActivityEmbedding"
- android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:exported="false">
</activity>
@@ -304,7 +287,6 @@
android:name=".ActivityEmbeddingPlaceholderSecondaryActivity"
android:label="ActivityEmbedding Placeholder Secondary"
android:taskAffinity="com.android.server.wm.flicker.testapp.ActivityEmbedding"
- android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:exported="false"/>
<activity android:name=".MailActivity"
@@ -334,7 +316,6 @@
android:supportsPictureInPicture="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:taskAffinity="com.android.server.wm.flicker.testapp.PipActivity"
- android:theme="@style/CutoutShortEdges"
android:launchMode="singleTop"
android:label="PipActivity"
android:exported="true">
@@ -350,7 +331,6 @@
<activity android:name=".BottomHalfPipLaunchingActivity"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:taskAffinity="com.android.server.wm.flicker.testapp.BottomHalfPipLaunchingActivity"
- android:theme="@style/CutoutShortEdges"
android:label="BottomHalfPipLaunchingActivity"
android:exported="true">
<intent-filter>
@@ -371,7 +351,6 @@
<activity android:name=".SplitScreenActivity"
android:resizeableActivity="true"
android:taskAffinity="com.android.server.wm.flicker.testapp.SplitScreenActivity"
- android:theme="@style/CutoutShortEdges"
android:label="SplitScreenPrimaryActivity"
android:exported="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation">
@@ -383,7 +362,6 @@
<activity android:name=".SplitScreenSecondaryActivity"
android:resizeableActivity="true"
android:taskAffinity="com.android.server.wm.flicker.testapp.SplitScreenSecondaryActivity"
- android:theme="@style/CutoutShortEdges"
android:label="SplitScreenSecondaryActivity"
android:exported="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation">
@@ -396,7 +374,6 @@
</activity>
<activity android:name=".SendNotificationActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.SendNotificationActivity"
- android:theme="@style/CutoutShortEdges"
android:label="SendNotificationActivity"
android:exported="true">
<intent-filter>
@@ -408,7 +385,6 @@
android:name=".LaunchBubbleActivity"
android:label="LaunchBubbleActivity"
android:exported="true"
- android:theme="@style/CutoutShortEdges"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
@@ -420,7 +396,6 @@
android:name=".BubbleActivity"
android:label="BubbleActivity"
android:exported="false"
- android:theme="@style/CutoutShortEdges"
android:resizeableActivity="true"/>
<activity
android:name=".TransferSplashscreenActivity"
@@ -468,4 +443,4 @@
</service>
</application>
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
-</manifest>
+</manifest> \ No newline at end of file
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_bottom_half_pip.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_bottom_half_pip.xml
index 2f9c3aa82057..15e2a798b2cf 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_bottom_half_pip.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_bottom_half_pip.xml
@@ -18,6 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
android:orientation="vertical"
android:background="@android:color/holo_blue_bright">
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_bubble.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_bubble.xml
index 7c7b2cacaefb..4bc70996eba8 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_bubble.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_bubble.xml
@@ -16,6 +16,7 @@
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_base_layout.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_base_layout.xml
index f0dfdfce035f..e98ffd045d3d 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_base_layout.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_base_layout.xml
@@ -19,5 +19,6 @@
android:id="@+id/root_activity_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
android:orientation="vertical">
</LinearLayout>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml
index 939ba81a47ea..16c906d9ee42 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml
@@ -18,6 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
android:background="@android:color/holo_orange_light">
<LinearLayout
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_secondary_activity_layout.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_secondary_activity_layout.xml
index 6d4de995bd73..eedb910b2b4e 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_secondary_activity_layout.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_secondary_activity_layout.xml
@@ -19,6 +19,7 @@
android:id="@+id/secondary_activity_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
android:orientation="vertical">
<Button
@@ -49,4 +50,4 @@
android:layout_height="48dp"
android:text="Enter pip" />
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_ime.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_ime.xml
index 507c1b622613..5e5203cb0545 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_ime.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_ime.xml
@@ -17,6 +17,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_green_light"
+ android:fitsSystemWindows="true"
android:focusableInTouchMode="true"
android:orientation="vertical">
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_launch_new.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_launch_new.xml
index fe7bced690f9..2ab5fe7b9d6c 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_launch_new.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_launch_new.xml
@@ -18,6 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
android:background="@android:color/holo_orange_light">
<Button
android:id="@+id/launch_second_activity"
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_mail.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_mail.xml
index 8a97433ede04..fcef791afe2e 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_mail.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_mail.xml
@@ -19,6 +19,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
+ android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_non_resizeable.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_non_resizeable.xml
index 6d5a9dd29248..aeb8423680a3 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_non_resizeable.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_non_resizeable.xml
@@ -18,6 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
android:orientation="vertical"
android:background="@android:color/holo_orange_light">
@@ -29,4 +30,4 @@
android:text="NonResizeableActivity"
android:textAppearance="?android:attr/textAppearanceLarge"/>
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_pip.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_pip.xml
index 365a0ea017f6..d66b3d74e114 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_pip.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_pip.xml
@@ -18,6 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
android:orientation="vertical"
android:background="@android:color/holo_blue_bright">
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_simple.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_simple.xml
index 5d94e5177dcc..42213d6812da 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_simple.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_simple.xml
@@ -18,6 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
android:background="@android:color/holo_orange_light">
</LinearLayout>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_splitscreen.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_splitscreen.xml
index 79e88e49b99e..16c3bc07d55c 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_splitscreen.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_splitscreen.xml
@@ -18,6 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
android:orientation="vertical"
android:background="@android:color/holo_green_light">
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_splitscreen_secondary.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_splitscreen_secondary.xml
index ed9feaf1eade..7643cf5de216 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_splitscreen_secondary.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_splitscreen_secondary.xml
@@ -18,6 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
android:orientation="vertical"
android:background="@android:color/holo_blue_light">
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_start_media_projection.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_start_media_projection.xml
index c34d2003ef42..79e7bb5de96e 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_start_media_projection.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_start_media_projection.xml
@@ -18,6 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
android:gravity="center"
android:orientation="vertical"
android:background="@android:color/holo_orange_light">
@@ -39,4 +40,4 @@
android:gravity="center_vertical|center_horizontal"
android:text="Start Media Projection with extra intent"
android:textAppearance="?android:attr/textAppearanceLarge"/>
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_surfaceview.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_surfaceview.xml
index 0b4693dec6e1..4d12168ca8db 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_surfaceview.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_surfaceview.xml
@@ -19,6 +19,7 @@
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
android:background="@android:color/holo_orange_light">
<SurfaceView
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_transparent.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_transparent.xml
index 0730ded66ce4..32df5f015414 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_transparent.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_transparent.xml
@@ -15,6 +15,7 @@
~ limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_transparent_launch.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_transparent_launch.xml
index ff4ead95f16e..a0c87fd17fc3 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_transparent_launch.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_transparent_launch.xml
@@ -17,6 +17,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
android:orientation="vertical"
android:background="@android:color/black">
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/notification_button.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/notification_button.xml
index 78072006f681..da58b3f43c73 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/notification_button.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/notification_button.xml
@@ -18,10 +18,12 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
android:background="@android:color/holo_orange_light">
<Button
android:id="@+id/post_notification"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal|center_vertical"
android:text="Post Notification" />
</LinearLayout>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/task_button.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/task_button.xml
index 8f75d175d00a..ec3135c0a42d 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/task_button.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/task_button.xml
@@ -18,6 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
android:background="@android:color/holo_orange_light">
<Button
android:id="@+id/launch_new_task"
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/values/styles.xml b/tests/FlickerTests/test-apps/flickerapp/res/values/styles.xml
index 837d050b73ff..ca3244820893 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/values/styles.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/values/styles.xml
@@ -36,10 +36,6 @@
<item name="android:windowLayoutInDisplayCutoutMode">default</item>
</style>
- <style name="CutoutShortEdges" parent="@style/DefaultTheme">
- <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
- </style>
-
<style name="CutoutNever" parent="@style/DefaultTheme">
<item name="android:windowLayoutInDisplayCutoutMode">never</item>
</style>
@@ -78,4 +74,4 @@
<!-- Here we want to match the duration of our AVD -->
<item name="android:windowSplashScreenAnimationDuration">900</item>
</style>
-</resources>
+</resources> \ No newline at end of file
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ImeActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ImeActivity.java
index 4418b5a5ff82..30bf616cfe74 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ImeActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ImeActivity.java
@@ -30,7 +30,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
-import android.view.WindowManager;
public class ImeActivity extends Activity {
@@ -64,10 +63,6 @@ public class ImeActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- WindowManager.LayoutParams p = getWindow().getAttributes();
- p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
- .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
- getWindow().setAttributes(p);
setContentView(R.layout.activity_ime);
final var filter = new IntentFilter();
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ImeEditorPopupDialogActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ImeEditorPopupDialogActivity.java
index 95f933f97bb2..887a15c9ea90 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ImeEditorPopupDialogActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ImeEditorPopupDialogActivity.java
@@ -30,8 +30,6 @@ public class ImeEditorPopupDialogActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WindowManager.LayoutParams p = getWindow().getAttributes();
- p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
- .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
p.softInputMode = SOFT_INPUT_STATE_ALWAYS_HIDDEN;
getWindow().setAttributes(p);
LinearLayout layout = new LinearLayout(this);
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchNewActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchNewActivity.java
index e5710c850f07..97d7a64d5ebf 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchNewActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchNewActivity.java
@@ -19,17 +19,12 @@ package com.android.server.wm.flicker.testapp;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
-import android.view.WindowManager;
import android.widget.Button;
public class LaunchNewActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- WindowManager.LayoutParams p = getWindow().getAttributes();
- p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
- .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
- getWindow().setAttributes(p);
setContentView(R.layout.activity_launch_new);
Button button = findViewById(R.id.launch_second_activity);
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchNewTaskActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchNewTaskActivity.java
index 1809781b33e6..402a393e7028 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchNewTaskActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchNewTaskActivity.java
@@ -21,17 +21,12 @@ import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
-import android.view.WindowManager;
import android.widget.Button;
public class LaunchNewTaskActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- WindowManager.LayoutParams p = getWindow().getAttributes();
- p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
- .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
- getWindow().setAttributes(p);
setContentView(R.layout.task_button);
Button button = findViewById(R.id.launch_new_task);
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/NotificationActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/NotificationActivity.java
index d6427abcc65a..61254385e980 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/NotificationActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/NotificationActivity.java
@@ -45,14 +45,10 @@ public class NotificationActivity extends Activity {
requestPermissions(new String[] { POST_NOTIFICATIONS }, 0);
}
- WindowManager.LayoutParams p = getWindow().getAttributes();
- p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
- .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
- getWindow().setAttributes(p);
setContentView(R.layout.notification_button);
- Button button = findViewById(R.id.post_notification);
- button.setOnClickListener(v -> postNotification());
+ ((Button) findViewById(R.id.post_notification))
+ .setOnClickListener(v -> postNotification());
createNotificationChannel();
}
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java
index ee25ab2fb66c..e030dcf0db9b 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java
@@ -47,8 +47,6 @@ import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Rational;
import android.view.View;
-import android.view.Window;
-import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.RadioButton;
@@ -145,12 +143,6 @@ public class PipActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- final Window window = getWindow();
- final WindowManager.LayoutParams layoutParams = window.getAttributes();
- layoutParams.layoutInDisplayCutoutMode = WindowManager.LayoutParams
- .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
- window.setAttributes(layoutParams);
-
setContentView(R.layout.activity_pip);
findViewById(R.id.media_session_start)
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PortraitOnlyActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PortraitOnlyActivity.java
index b1876b5e5511..552d843676bb 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PortraitOnlyActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PortraitOnlyActivity.java
@@ -18,16 +18,11 @@ package com.android.server.wm.flicker.testapp;
import android.app.Activity;
import android.os.Bundle;
-import android.view.WindowManager;
public class PortraitOnlyActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- WindowManager.LayoutParams p = getWindow().getAttributes();
- p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
- .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
- getWindow().setAttributes(p);
setContentView(R.layout.activity_simple);
}
}
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SeamlessRotationActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SeamlessRotationActivity.java
index ce7a0059fa2d..e98c34db0cd9 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SeamlessRotationActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SeamlessRotationActivity.java
@@ -61,8 +61,6 @@ public class SeamlessRotationActivity extends Activity {
private void enableSeamlessRotation() {
WindowManager.LayoutParams p = getWindow().getAttributes();
p.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
- p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
- .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ShowWhenLockedActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ShowWhenLockedActivity.java
index 6f94b74ccf41..a533c9052574 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ShowWhenLockedActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ShowWhenLockedActivity.java
@@ -18,16 +18,11 @@ package com.android.server.wm.flicker.testapp;
import android.app.Activity;
import android.os.Bundle;
-import android.view.WindowManager;
public class ShowWhenLockedActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- WindowManager.LayoutParams p = getWindow().getAttributes();
- p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
- .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
- getWindow().setAttributes(p);
setContentView(R.layout.activity_simple);
}
}
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SimpleActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SimpleActivity.java
index 699abf87d341..c56eefe32189 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SimpleActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SimpleActivity.java
@@ -18,16 +18,11 @@ package com.android.server.wm.flicker.testapp;
import android.app.Activity;
import android.os.Bundle;
-import android.view.WindowManager;
public class SimpleActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- WindowManager.LayoutParams p = getWindow().getAttributes();
- p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
- .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
- getWindow().setAttributes(p);
setContentView(R.layout.activity_simple);
}
}
diff --git a/tools/codegen/src/com/android/codegen/Debug.kt b/tools/codegen/src/com/android/codegen/Debug.kt
index de3184468540..6423c4f7f6c0 100644
--- a/tools/codegen/src/com/android/codegen/Debug.kt
+++ b/tools/codegen/src/com/android/codegen/Debug.kt
@@ -21,7 +21,7 @@ import com.github.javaparser.ast.Node
fun Node.dump(indent: String = ""): String {
return buildString {
append(indent)
- appendln(dumpOneLineNoChildren())
+ appendLine(dumpOneLineNoChildren())
childNodes.forEach { child ->
append(child.dump(indent + " "))
}
diff --git a/tools/codegen/src/com/android/codegen/FeatureFlag.kt b/tools/codegen/src/com/android/codegen/FeatureFlag.kt
index 24150d637a7b..f305429f516f 100644
--- a/tools/codegen/src/com/android/codegen/FeatureFlag.kt
+++ b/tools/codegen/src/com/android/codegen/FeatureFlag.kt
@@ -22,6 +22,6 @@ enum class FeatureFlag(val onByDefault: Boolean, val desc: String = "") {
CONST_DEFS(true, "@Int/StringDef's based on declared static constants"),
FOR_EACH_FIELD(false, "forEachField((name, value) -> ...)");
- val kebabCase = name.toLowerCase().replace("_", "-")
- val upperCamelCase = name.split("_").map { it.toLowerCase().capitalize() }.joinToString("")
+ val kebabCase = name.lowercase().replace("_", "-")
+ val upperCamelCase = name.split("_").map { it.lowercase().capitalize() }.joinToString("")
}
diff --git a/tools/codegen/src/com/android/codegen/FileInfo.kt b/tools/codegen/src/com/android/codegen/FileInfo.kt
index cc3a15654956..ca04f1eb9ab7 100644
--- a/tools/codegen/src/com/android/codegen/FileInfo.kt
+++ b/tools/codegen/src/com/android/codegen/FileInfo.kt
@@ -126,7 +126,7 @@ class FileInfo(
+"\n}"
}
// Print general code as-is
- is CodeChunk.Code -> chunk.lines.forEach { stringBuilder.appendln(it) }
+ is CodeChunk.Code -> chunk.lines.forEach { stringBuilder.appendLine(it) }
// Recursively render data classes
is CodeChunk.DataClass -> chunk.chunks.forEach { print(it) }
}
@@ -175,11 +175,11 @@ class FileInfo(
/** Debug info */
override fun toString(): String {
return buildString {
- appendln("class $name $range")
+ appendLine("class $name $range")
nested.forEach {
- appendln(it)
+ appendLine(it)
}
- appendln("end $name")
+ appendLine("end $name")
}
}
}
diff --git a/tools/codegen/src/com/android/codegen/Generators.kt b/tools/codegen/src/com/android/codegen/Generators.kt
index d3a8b033dfff..710960249661 100644
--- a/tools/codegen/src/com/android/codegen/Generators.kt
+++ b/tools/codegen/src/com/android/codegen/Generators.kt
@@ -43,7 +43,7 @@ fun ClassPrinter.generateConstDef(consts: List<Pair<VariableDeclarator, FieldDec
}
var AnnotationName = prefix.split("_")
.filterNot { it.isBlank() }
- .map { it.toLowerCase().capitalize() }
+ .map { it.lowercase().capitalize() }
.joinToString("")
val annotatedConst = consts.find { it.second.annotations.isNonEmpty }
if (annotatedConst != null) {
@@ -122,7 +122,7 @@ fun FileInfo.generateAidl() {
if (aidl.exists()) return
aidl.writeText(buildString {
sourceLines.dropLastWhile { !it.startsWith("package ") }.forEach {
- appendln(it)
+ appendLine(it)
}
append("\nparcelable ${mainClass.nameAsString};\n")
})
diff --git a/tools/codegen/src/com/android/codegen/Utils.kt b/tools/codegen/src/com/android/codegen/Utils.kt
index a40bdd7ba8e1..96314435d1b7 100644
--- a/tools/codegen/src/com/android/codegen/Utils.kt
+++ b/tools/codegen/src/com/android/codegen/Utils.kt
@@ -62,7 +62,7 @@ fun String.toLowerCamel(): String {
if (length >= 2 && this[0] == 'm' && this[1].isUpperCase()) return substring(1).capitalize()
if (all { it.isLetterOrDigit() }) return decapitalize()
return split("[^a-zA-Z0-9]".toRegex())
- .map { it.toLowerCase().capitalize() }
+ .map { it.lowercase().capitalize() }
.joinToString("")
.decapitalize()
}