diff options
79 files changed, 1371 insertions, 1525 deletions
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index b42f7bc0ca94..e8571757c6f7 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -1,6 +1,7 @@ [Builtin Hooks] clang_format = true bpfmt = true +ktfmt = true [Builtin Hooks Options] # Only turn on clang-format check for the following subfolders. @@ -17,6 +18,7 @@ clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp tests/ tools/ bpfmt = -d +ktfmt = --kotlinlang-style --include-dirs=services/permission,packages/SystemUI [Hook Scripts] checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT} @@ -25,9 +27,10 @@ hidden_api_txt_checksorted_hook = ${REPO_ROOT}/tools/platform-compat/hiddenapi/c hidden_api_txt_exclude_hook = ${REPO_ROOT}/frameworks/base/tools/hiddenapi/exclude.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT} -ktfmt_hook = ${REPO_ROOT}/external/ktfmt/ktfmt.py --check -i ${REPO_ROOT}/frameworks/base/ktfmt_includes.txt ${PREUPLOAD_FILES} - ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py --no-verify-format -f ${PREUPLOAD_FILES} # This flag check hook runs only for "packages/SystemUI" subdirectory. If you want to include this check for other subdirectories, please modify flag_check.py. flag_hook = ${REPO_ROOT}/frameworks/base/packages/SystemUI/flag_check.py --msg=${PREUPLOAD_COMMIT_MESSAGE} --files=${PREUPLOAD_FILES} --project=${REPO_PATH} + +[Tool Paths] +ktfmt = ${REPO_ROOT}/prebuilts/build-tools/common/framework/ktfmt.jar diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 4c839f1762cb..6c9566558505 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -1632,6 +1632,7 @@ public class Notification implements Parcelable private Icon mSmallIcon; @UnsupportedAppUsage private Icon mLargeIcon; + private Icon mAppIcon; @UnsupportedAppUsage private String mChannelId; @@ -3109,16 +3110,17 @@ public class Notification implements Parcelable } /** + * Get the resource ID of the app icon from application info. * @hide */ - public int loadHeaderAppIconRes(Context context) { + public int getHeaderAppIconRes(Context context) { ApplicationInfo info = null; if (extras.containsKey(EXTRA_BUILDER_APPLICATION_INFO)) { info = extras.getParcelable( EXTRA_BUILDER_APPLICATION_INFO, ApplicationInfo.class); } - if (info == null) { + if (info == null && context != null) { info = context.getApplicationInfo(); } if (info != null) { @@ -3128,6 +3130,29 @@ public class Notification implements Parcelable } /** + * Load the app icon drawable from the package manager. This could result in a binder call. + * @hide + */ + public Drawable loadHeaderAppIcon(Context context) { + Trace.beginSection("Notification#loadHeaderAppIcon"); + + try { + final PackageManager pm = context.getPackageManager(); + if (extras.containsKey(EXTRA_BUILDER_APPLICATION_INFO)) { + final ApplicationInfo info = extras.getParcelable( + EXTRA_BUILDER_APPLICATION_INFO, + ApplicationInfo.class); + if (info != null) { + return pm.getApplicationIcon(info); + } + } + return pm.getApplicationIcon(context.getApplicationInfo()); + } finally { + Trace.endSection(); + } + } + + /** * Removes heavyweight parts of the Notification object for archival or for sending to * listeners when the full contents are not necessary. * @hide @@ -4124,6 +4149,52 @@ public class Notification implements Parcelable } /** + * The colored app icon that can replace the small icon in the notification starting in V. + * + * Before using this value, you should first check whether it's actually being used by the + * notification by calling {@link Notification#shouldUseAppIcon()}. + * + * @hide + */ + public Icon getAppIcon() { + if (mAppIcon != null) { + return mAppIcon; + } + // If the app icon hasn't been loaded yet, check if we can load it without a context. + if (extras.containsKey(EXTRA_BUILDER_APPLICATION_INFO)) { + final ApplicationInfo info = extras.getParcelable( + EXTRA_BUILDER_APPLICATION_INFO, + ApplicationInfo.class); + if (info != null) { + int appIconRes = info.icon; + if (appIconRes == 0) { + Log.w(TAG, "Failed to get the app icon: no icon in application info"); + return null; + } + mAppIcon = Icon.createWithResource(info.packageName, appIconRes); + return mAppIcon; + } else { + Log.e(TAG, "Failed to get the app icon: " + + "there's an EXTRA_BUILDER_APPLICATION_INFO in extras but it's null"); + } + } else { + Log.w(TAG, "Failed to get the app icon: no application info in extras"); + } + return null; + } + + /** + * Whether the notification is using the app icon instead of the small icon. + * @hide + */ + public boolean shouldUseAppIcon() { + if (Flags.notificationsUseAppIconInRow()) { + return getAppIcon() != null; + } + return false; + } + + /** * The large icon shown in this notification's content view. * @see Builder#getLargeIcon() * @see Builder#setLargeIcon(Icon) @@ -6116,16 +6187,30 @@ public class Notification implements Parcelable if (Flags.notificationsUseAppIcon()) { // Override small icon with app icon mN.mSmallIcon = Icon.createWithResource(mContext, - mN.loadHeaderAppIconRes(mContext)); + mN.getHeaderAppIconRes(mContext)); } else if (mN.mSmallIcon == null && mN.icon != 0) { mN.mSmallIcon = Icon.createWithResource(mContext, mN.icon); } - contentView.setImageViewIcon(R.id.icon, mN.mSmallIcon); + boolean usingAppIcon = false; + if (Flags.notificationsUseAppIconInRow()) { + // Use the app icon in the view + int appIconRes = mN.getHeaderAppIconRes(mContext); + if (appIconRes != 0) { + mN.mAppIcon = Icon.createWithResource(mContext, appIconRes); + contentView.setImageViewIcon(R.id.icon, mN.mAppIcon); + usingAppIcon = true; + } else { + Log.w(TAG, "bindSmallIcon: could not get the app icon"); + } + } + if (!usingAppIcon) { + contentView.setImageViewIcon(R.id.icon, mN.mSmallIcon); + } contentView.setInt(R.id.icon, "setImageLevel", mN.iconLevel); // Don't change color if we're using the app icon. - if (!Flags.notificationsUseAppIcon()) { + if (!Flags.notificationsUseAppIcon() && !usingAppIcon) { processSmallIconColor(mN.mSmallIcon, contentView, p); } } diff --git a/core/java/android/app/notification.aconfig b/core/java/android/app/notification.aconfig index 55c3bb60e9c7..6edae0b60fd9 100644 --- a/core/java/android/app/notification.aconfig +++ b/core/java/android/app/notification.aconfig @@ -52,14 +52,32 @@ flag { bug: "281044385" } +# vvv Prototypes for using app icons in notifications vvv + flag { name: "notifications_use_app_icon" namespace: "systemui" - description: "Experiment to replace the small icon in a notification with the app icon." + description: "Experiment to replace the small icon in a notification with the app icon. This includes the status bar, AOD, shelf and notification row itself." + bug: "335211019" +} + +flag { + name: "notifications_use_app_icon_in_row" + namespace: "systemui" + description: "Experiment to replace the small icon in a notification row with the app icon." bug: "335211019" } flag { + name: "notifications_use_monochrome_app_icon" + namespace: "systemui" + description: "Experiment to replace the notification icon in the status bar and shelf with the monochrome app icon, if available." + bug: "335211019" +} + +# ^^^ Prototypes for using app icons in notifications ^^^ + +flag { name: "notification_expansion_optional" namespace: "systemui" description: "Experiment to restore the pre-S behavior where standard notifications are not expandable unless they have actions." diff --git a/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig b/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig index 983f46c58c4b..5b99ff9703e0 100644 --- a/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig +++ b/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig @@ -73,6 +73,16 @@ flag { } flag { + name: "immersive_app_repositioning" + namespace: "large_screen_experiences_app_compat" + description: "Fix immersive apps changing size when repositioning" + bug: "334076352" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "camera_compat_for_freeform" namespace: "large_screen_experiences_app_compat" description: "Whether to apply Camera Compat treatment to fixed-orientation apps in freeform windowing mode" diff --git a/core/java/com/android/internal/widget/NotificationRowIconView.java b/core/java/com/android/internal/widget/NotificationRowIconView.java index 0f4615a12ea2..58bddaecd3e7 100644 --- a/core/java/com/android/internal/widget/NotificationRowIconView.java +++ b/core/java/com/android/internal/widget/NotificationRowIconView.java @@ -59,7 +59,7 @@ public class NotificationRowIconView extends CachingIconView { @Override protected void onFinishInflate() { // If showing the app icon, we don't need background or padding. - if (Flags.notificationsUseAppIcon()) { + if (Flags.notificationsUseAppIcon() || Flags.notificationsUseAppIconInRow()) { setPadding(0, 0, 0, 0); setBackground(null); } diff --git a/ktfmt_includes.txt b/ktfmt_includes.txt deleted file mode 100644 index 0ac6265ecf27..000000000000 --- a/ktfmt_includes.txt +++ /dev/null @@ -1,740 +0,0 @@ -+services/permission -+packages/SystemUI --packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt --packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt --packages/SystemUI/checks/src/com/android/internal/systemui/lint/BroadcastSentViaContextDetector.kt --packages/SystemUI/checks/src/com/android/internal/systemui/lint/RegisterReceiverViaContextDetector.kt --packages/SystemUI/checks/src/com/android/internal/systemui/lint/SoftwareBitmapDetector.kt --packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt --packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/View.kt --packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt --packages/SystemUI/shared/src/com/android/systemui/flags/FlagListenable.kt --packages/SystemUI/shared/src/com/android/systemui/flags/FlagManager.kt --packages/SystemUI/shared/src/com/android/systemui/flags/FlagSerializer.kt --packages/SystemUI/shared/src/com/android/systemui/flags/FlagSettingsHelper.kt --packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt --packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionDarkness.kt --packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonPositionCalculator.kt --packages/SystemUI/shared/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerManager.kt --packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/SmartspaceState.kt --packages/SystemUI/shared/src/com/android/systemui/unfold/system/ActivityManagerActivityTypeProvider.kt --packages/SystemUI/shared/src/com/android/systemui/unfold/system/DeviceStateManagerFoldProvider.kt --packages/SystemUI/shared/src/com/android/systemui/unfold/system/SystemUnfoldSharedModule.kt --packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt --packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt --packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt --packages/SystemUI/src/com/android/keyguard/BouncerPanelExpansionCalculator.kt --packages/SystemUI/src/com/android/keyguard/ClockEventController.kt --packages/SystemUI/src/com/android/keyguard/KeyguardBiometricLockoutLogger.kt --packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt --packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherAnchor.kt --packages/SystemUI/src/com/android/keyguard/clock/ClockPalette.kt --packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt --packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt --packages/SystemUI/src/com/android/systemui/BootCompleteCache.kt --packages/SystemUI/src/com/android/systemui/BootCompleteCacheImpl.kt --packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt --packages/SystemUI/src/com/android/systemui/ChooserSelector.kt --packages/SystemUI/src/com/android/systemui/DarkReceiverImpl.kt --packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt --packages/SystemUI/src/com/android/systemui/DualToneHandler.kt --packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt --packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt --packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactoryBase.kt --packages/SystemUI/src/com/android/systemui/SystemUIInitializerFactory.kt --packages/SystemUI/src/com/android/systemui/SystemUIInitializerImpl.kt --packages/SystemUI/src/com/android/systemui/assist/AssistLogger.kt --packages/SystemUI/src/com/android/systemui/assist/AssistantInvocationEvent.kt --packages/SystemUI/src/com/android/systemui/assist/AssistantSessionEvent.kt --packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt --packages/SystemUI/src/com/android/systemui/biometrics/AlternateUdfpsTouchProvider.kt --packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceIconController.kt --packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceView.kt --packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceIconController.kt --packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceView.kt --packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt --packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt --packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt --packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt --packages/SystemUI/src/com/android/systemui/biometrics/BiometricDisplayListener.kt --packages/SystemUI/src/com/android/systemui/biometrics/DwellRippleShader.kt --packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.kt --packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpView.kt --packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt --packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt --packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDrawable.kt --packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpDrawable.kt --packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmEmptyView.kt --packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmEmptyViewController.kt --packages/SystemUI/src/com/android/systemui/biometrics/UdfpsHapticsSimulator.kt --packages/SystemUI/src/com/android/systemui/biometrics/UdfpsShell.kt --packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt --packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt --packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt --packages/SystemUI/src/com/android/systemui/broadcast/ActionReceiver.kt --packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt --packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcherStartable.kt --packages/SystemUI/src/com/android/systemui/broadcast/BroadcastSender.kt --packages/SystemUI/src/com/android/systemui/broadcast/PendingRemovalStore.kt --packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt --packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt --packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt --packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt --packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt --packages/SystemUI/src/com/android/systemui/controls/ControlsMetricsLogger.kt --packages/SystemUI/src/com/android/systemui/controls/ControlsMetricsLoggerImpl.kt --packages/SystemUI/src/com/android/systemui/controls/ControlsServiceInfo.kt --packages/SystemUI/src/com/android/systemui/controls/CustomIconCache.kt --packages/SystemUI/src/com/android/systemui/controls/TooltipManager.kt --packages/SystemUI/src/com/android/systemui/controls/controller/ControlInfo.kt --packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt --packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt --packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt --packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt --packages/SystemUI/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapper.kt --packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt --packages/SystemUI/src/com/android/systemui/controls/controller/ControlsTileResourceConfiguration.kt --packages/SystemUI/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImpl.kt --packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt --packages/SystemUI/src/com/android/systemui/controls/controller/StatefulControlSubscriber.kt --packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt --packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsFeatureEnabled.kt --packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt --packages/SystemUI/src/com/android/systemui/controls/management/AllModel.kt --packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt --packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt --packages/SystemUI/src/com/android/systemui/controls/management/ControlsAnimations.kt --packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt --packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt --packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt --packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt --packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt --packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt --packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt --packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestReceiver.kt --packages/SystemUI/src/com/android/systemui/controls/management/FavoritesModel.kt --packages/SystemUI/src/com/android/systemui/controls/management/ManagementPageIndicator.kt --packages/SystemUI/src/com/android/systemui/controls/management/StructureAdapter.kt --packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt --packages/SystemUI/src/com/android/systemui/controls/ui/Behavior.kt --packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt --packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt --packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt --packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt --packages/SystemUI/src/com/android/systemui/controls/ui/ControlWithState.kt --packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt --packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt --packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt --packages/SystemUI/src/com/android/systemui/controls/ui/CornerDrawable.kt --packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt --packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt --packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt --packages/SystemUI/src/com/android/systemui/controls/ui/TemperatureControlBehavior.kt --packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt --packages/SystemUI/src/com/android/systemui/controls/ui/ToggleBehavior.kt --packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt --packages/SystemUI/src/com/android/systemui/controls/ui/TouchBehavior.kt --packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt --packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderFactory.kt --packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderImpl.kt --packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt --packages/SystemUI/src/com/android/systemui/decor/DecorProviderFactory.kt --packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt --packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt --packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt --packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderFactory.kt --packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt --packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt --packages/SystemUI/src/com/android/systemui/demomode/DemoModeAvailabilityTracker.kt --packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt --packages/SystemUI/src/com/android/systemui/doze/util/BurnInHelper.kt --packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt --packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt --packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt --packages/SystemUI/src/com/android/systemui/dump/DumpsysTableLogger.kt --packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt --packages/SystemUI/src/com/android/systemui/dump/LogBufferFreezer.kt --packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt --packages/SystemUI/src/com/android/systemui/flags/Flags.kt --packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt --packages/SystemUI/src/com/android/systemui/flags/SystemPropertiesHelper.kt --packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt --packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt --packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfig.kt --packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartable.kt --packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt --packages/SystemUI/src/com/android/systemui/log/LogBufferFactory.kt --packages/SystemUI/src/com/android/systemui/media/MediaProjectionCaptureTarget.kt --packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt --packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt --packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt --packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionCli.kt --packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManager.kt --packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerFactory.kt --packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitLogger.kt --packages/SystemUI/src/com/android/systemui/media/nearby/NearbyMediaDevicesLogger.kt --packages/SystemUI/src/com/android/systemui/media/nearby/NearbyMediaDevicesManager.kt --packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt --packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttFlags.kt --packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt --packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt --packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt --packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt --packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLogger.kt --packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorResultHandler.kt --packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt --packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt --packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RecentTasksAdapter.kt --packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolver.kt --packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt --packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt --packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt --packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt --packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt --packages/SystemUI/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitor.kt --packages/SystemUI/src/com/android/systemui/privacy/MediaProjectionPrivacyItemMonitor.kt --packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt --packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt --packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipEvent.kt --packages/SystemUI/src/com/android/systemui/privacy/PrivacyConfig.kt --packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt --packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt --packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogEvent.kt --packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt --packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt --packages/SystemUI/src/com/android/systemui/privacy/logging/PrivacyLogger.kt --packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt --packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt --packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt --packages/SystemUI/src/com/android/systemui/qs/QSEvents.kt --packages/SystemUI/src/com/android/systemui/qs/QSExpansionPathInterpolator.kt --packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt --packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt --packages/SystemUI/src/com/android/systemui/qs/QSUtils.kt --packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt --packages/SystemUI/src/com/android/systemui/qs/VisibilityChangedDispatcher.kt --packages/SystemUI/src/com/android/systemui/qs/carrier/CellSignalState.kt --packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.kt --packages/SystemUI/src/com/android/systemui/qs/external/CustomTileStatePersister.kt --packages/SystemUI/src/com/android/systemui/qs/external/QSExternalModule.kt --packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialog.kt --packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialogEventLogger.kt --packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt --packages/SystemUI/src/com/android/systemui/qs/tileimpl/HeightOverrideable.kt --packages/SystemUI/src/com/android/systemui/qs/tileimpl/IgnorableChildLinearLayout.kt --packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt --packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt --packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt --packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt --packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt --packages/SystemUI/src/com/android/systemui/screenshot/ImageCaptureImpl.kt --packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt --packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt --packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicyImpl.kt --packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt --packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt --packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt --packages/SystemUI/src/com/android/systemui/settings/UserContentResolverProvider.kt --packages/SystemUI/src/com/android/systemui/settings/UserContextProvider.kt --packages/SystemUI/src/com/android/systemui/settings/UserFileManager.kt --packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt --packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt --packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessMirrorHandler.kt --packages/SystemUI/src/com/android/systemui/settings/brightness/MirroredBrightnessController.kt --packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt --packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt --packages/SystemUI/src/com/android/systemui/shade/NPVCDownEventState.kt --packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt --packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt --packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt --packages/SystemUI/src/com/android/systemui/shade/ShadeHeightLogger.kt --packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt --packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt --packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt --packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt --packages/SystemUI/src/com/android/systemui/smartspace/SmartspacePrecondition.kt --packages/SystemUI/src/com/android/systemui/smartspace/SmartspaceTargetFilter.kt --packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt --packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceViewComponent.kt --packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenAndDreamTargetFilter.kt --packages/SystemUI/src/com/android/systemui/smartspace/preconditions/LockscreenPrecondition.kt --packages/SystemUI/src/com/android/systemui/statusbar/AbstractLockscreenShadeTransitionController.kt --packages/SystemUI/src/com/android/systemui/statusbar/ActionClickLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt --packages/SystemUI/src/com/android/systemui/statusbar/LockScreenShadeOverScroller.kt --packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt --packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeScrimTransitionController.kt --packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt --packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt --packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt --packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt --packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt --packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt --packages/SystemUI/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScroller.kt --packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt --packages/SystemUI/src/com/android/systemui/statusbar/commandline/CommandRegistry.kt --packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointController.kt --packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityState.kt --packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalControllerFactory.kt --packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileState.kt --packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileStatusTrackerFactory.kt --packages/SystemUI/src/com/android/systemui/statusbar/connectivity/SignalCallback.kt --packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiState.kt --packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiStatusTrackerFactory.kt --packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt --packages/SystemUI/src/com/android/systemui/statusbar/dagger/StartCentralSurfacesModule.kt --packages/SystemUI/src/com/android/systemui/statusbar/disableflags/DisableFlagsLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt --packages/SystemUI/src/com/android/systemui/statusbar/events/StatusBarEventsModule.kt --packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt --packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt --packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt --packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt --packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt --packages/SystemUI/src/com/android/systemui/statusbar/gesture/GesturePointerEventDetector.kt --packages/SystemUI/src/com/android/systemui/statusbar/gesture/GenericGestureDetector.kt --packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureHandler.kt --packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/gesture/TapGestureDetector.kt --packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/FeedbackIcon.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/ViewGroupFadeHelper.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImpl.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipelineChoreographer.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/PipelineDumper.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DebugModeCoordinator.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinator.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinator.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinator.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/BindEventManager.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/BindEventManagerImpl.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustment.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifStabilityManager.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTracker.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifEvent.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtender.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/NotificationVisibilityProviderImpl.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionHeaderVisibilityProvider.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/MediaContainerController.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeController.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGroupController.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGutsViewListener.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGutsViewManager.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifRowController.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifShadeEventSource.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifStackController.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewController.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotificationVisibilityProvider.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderExtensions.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RootNodeController.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationSectionHeadersModule.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconBuilder.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryViewWalker.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/people/NotificationPersonExtractor.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/people/ViewPipeline.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStageLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/RemoteInputViewModule.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationPriorityBucket.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt --packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaViewController.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/LSShadeTransitionLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/LetterboxAppearanceCalculator.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProvider.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenOffAnimationController.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHideIconsForBouncerManager.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLocationPublisher.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemBarAttributesListener.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarIconBlocklist.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallChronometer.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallFlags.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherContainer.kt --packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt --packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsController.kt --packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt --packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.kt --packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplyState.kt --packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplyViewHolder.kt --packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.kt --packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt --packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt --packages/SystemUI/src/com/android/systemui/statusbar/policy/VariableDateView.kt --packages/SystemUI/src/com/android/systemui/statusbar/policy/VariableDateViewController.kt --packages/SystemUI/src/com/android/systemui/statusbar/policy/WalletController.kt --packages/SystemUI/src/com/android/systemui/statusbar/policy/WalletControllerImpl.kt --packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/RemoteInput.kt --packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/SmartRepliesInflationModule.kt --packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt --packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt --packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt --packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt --packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarRootView.kt --packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt --packages/SystemUI/src/com/android/systemui/toast/ToastLogger.kt --packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt --packages/SystemUI/src/com/android/systemui/unfold/FoldStateLogger.kt --packages/SystemUI/src/com/android/systemui/unfold/SysUIUnfoldModule.kt --packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt --packages/SystemUI/src/com/android/systemui/unfold/UnfoldProgressProvider.kt --packages/SystemUI/src/com/android/systemui/user/UserSwitcherPopupMenu.kt --packages/SystemUI/src/com/android/systemui/user/UserSwitcherRootView.kt --packages/SystemUI/src/com/android/systemui/util/AsyncActivityLauncher.kt --packages/SystemUI/src/com/android/systemui/util/ColorUtil.kt --packages/SystemUI/src/com/android/systemui/util/ConvenienceExtensions.kt --packages/SystemUI/src/com/android/systemui/util/DelayableMarqueeTextView.kt --packages/SystemUI/src/com/android/systemui/util/DumpUtils.kt --packages/SystemUI/src/com/android/systemui/util/InitializationChecker.kt --packages/SystemUI/src/com/android/systemui/util/LargeScreenUtils.kt --packages/SystemUI/src/com/android/systemui/util/ListenerSet.kt --packages/SystemUI/src/com/android/systemui/util/NeverExactlyLinearLayout.kt --packages/SystemUI/src/com/android/systemui/util/NoRemeasureMotionLayout.kt --packages/SystemUI/src/com/android/systemui/util/PluralMessageFormater.kt --packages/SystemUI/src/com/android/systemui/util/RingerModeTracker.kt --packages/SystemUI/src/com/android/systemui/util/RingerModeTrackerImpl.kt --packages/SystemUI/src/com/android/systemui/util/RoundedCornerProgressDrawable.kt --packages/SystemUI/src/com/android/systemui/util/SafeMarqueeTextView.kt --packages/SystemUI/src/com/android/systemui/util/SparseArrayUtils.kt --packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt --packages/SystemUI/src/com/android/systemui/util/UserAwareController.kt --packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt --packages/SystemUI/src/com/android/systemui/util/animation/AnimationUtil.kt --packages/SystemUI/src/com/android/systemui/util/animation/MeasurementInput.kt --packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayout.kt --packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt --packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt --packages/SystemUI/src/com/android/systemui/util/concurrency/Execution.kt --packages/SystemUI/src/com/android/systemui/util/concurrency/PendingTasksContainer.kt --packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt --packages/SystemUI/src/com/android/systemui/util/kotlin/CoroutinesModule.kt --packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt --packages/SystemUI/src/com/android/systemui/util/kotlin/IpcSerializer.kt --packages/SystemUI/src/com/android/systemui/util/kotlin/nullability.kt --packages/SystemUI/src/com/android/systemui/util/recycler/HorizontalSpacerItemDecoration.kt --packages/SystemUI/src/com/android/systemui/util/view/ViewUtil.kt --packages/SystemUI/src/com/android/systemui/util/wrapper/RotationPolicyWrapper.kt --packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialogReceiver.kt --packages/SystemUI/src/com/android/systemui/volume/VolumePanelFactory.kt --packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt --packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt --packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt --packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt --packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt --packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt --packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt --packages/SystemUI/tests/src/com/android/keyguard/KeyguardUserSwitcherAnchorTest.kt --packages/SystemUI/tests/src/com/android/keyguard/clock/ClockPaletteTest.kt --packages/SystemUI/tests/src/com/android/keyguard/clock/ViewPreviewerTest.kt --packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/BootCompleteCacheTest.kt --packages/SystemUI/tests/src/com/android/systemui/ChooserSelectorTest.kt --packages/SystemUI/tests/src/com/android/systemui/DisplayCutoutBaseViewTest.kt --packages/SystemUI/tests/src/com/android/systemui/InstanceIdSequenceFake.kt --packages/SystemUI/tests/src/com/android/systemui/ScreenDecorHwcLayerTest.kt --packages/SystemUI/tests/src/com/android/systemui/animation/DialogTransitionAnimatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/animation/GhostedViewTransitionAnimatorControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/animation/TextAnimatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/animation/TextInterpolatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewTest.kt --packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt --packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt --packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt --packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt --packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt --packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt --packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt --packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastSenderTest.kt --packages/SystemUI/tests/src/com/android/systemui/broadcast/PendingRemovalStoreTest.kt --packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt --packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt --packages/SystemUI/tests/src/com/android/systemui/camera/CameraIntentsTest.kt --packages/SystemUI/tests/src/com/android/systemui/charging/WiredChargingRippleControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/CustomIconCacheTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapperTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapperTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/controller/StatefulControlSubscriberTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/management/AllModelTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/management/AppAdapterTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestDialogTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestReceiverTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/management/FavoritesModelTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlViewHolderTest.kt --packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt --packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt --packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt --packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt --packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt --packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt --packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt --packages/SystemUI/tests/src/com/android/systemui/dump/DumpsysTableLoggerTest.kt --packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferFreezerTest.kt --packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt --packages/SystemUI/tests/src/com/android/systemui/dump/LogEulogizerTest.kt --packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt --packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt --packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt --packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt --packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt --packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt --packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt --packages/SystemUI/tests/src/com/android/systemui/lifecycle/InstantTaskExecutorRule.kt --packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt --packages/SystemUI/tests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt --packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt --packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt --packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLoggerTest.kt --packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt --packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitorTest.kt --packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyChipBuilderTest.kt --packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyConfigFlagsTest.kt --packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt --packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/HeaderPrivacyIconsControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/QSContainerImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentDisableFlagsLoggerTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelSwitchToParentTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/QSSquishinessControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/SettingObserverTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/carrier/CellSignalStateTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileStatePersisterTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/external/TileRequestDialogEventLoggerTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/external/TileRequestDialogTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceRequestControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/ResourceIconTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/TilesStatesTextTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt --packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordDialogTest.kt --packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt --packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt --packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt --packages/SystemUI/tests/src/com/android/systemui/shared/navigationbar/RegionSamplingHelperTest.kt --packages/SystemUI/tests/src/com/android/systemui/shared/rotation/RotationButtonControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt --packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenPreconditionTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/DragDownHelperTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/LightRevealScrimTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/MediaArtworkProcessorTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScrollerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateEventTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/VibratorHelperTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableFlagsLoggerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableStateTrackerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/gesture/GenericGestureDetectorTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifPipelineChoreographerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolverTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTrackerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtenderTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/provider/VisualStabilityProviderTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/MediaContainerViewTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FoldStateListenerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxAppearanceCalculatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProviderTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconContainerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemBarAttributesListenerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallChronometerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLoggerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ClockTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FlashlightControllerImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SafetyControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/VariableDateViewControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/WalletControllerImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateLoggingProviderTest.kt --packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt --packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt --packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt --packages/SystemUI/tests/src/com/android/systemui/unfold/util/FoldableTestUtils.kt --packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt --packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt --packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt --packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/util/FakeSharedPreferencesTest.kt --packages/SystemUI/tests/src/com/android/systemui/util/FloatingContentCoordinatorTest.kt --packages/SystemUI/tests/src/com/android/systemui/util/ListenerSetTest.kt --packages/SystemUI/tests/src/com/android/systemui/util/RingerModeLiveDataTest.kt --packages/SystemUI/tests/src/com/android/systemui/util/WallpaperControllerTest.kt --packages/SystemUI/tests/src/com/android/systemui/util/animation/AnimationUtilTest.kt --packages/SystemUI/tests/src/com/android/systemui/util/drawable/DrawableSizeTest.kt --packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt --packages/SystemUI/tests/src/com/android/systemui/util/kotlin/IpcSerializerTest.kt --packages/SystemUI/tests/src/com/android/systemui/util/kotlin/SuspendUtilTests.kt --packages/SystemUI/tests/src/com/android/systemui/util/view/ViewUtilTest.kt --packages/SystemUI/tests/utils/src/com/android/systemui/flags/FakeFeatureFlags.kt --packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSharedPreferences.kt --packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt --packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt --packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt --packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionProgressProvider.kt --packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/ScreenSizeFoldProvider.kt --packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/SizeScreenStatusProvider.kt --packages/SystemUI/unfold/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt --packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldMain.kt --packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt --packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt --packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt --packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/screen/ScreenStatusProvider.kt diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/DividerPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/DividerPresenter.java index 6b957114c00b..774b2129497d 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/DividerPresenter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/DividerPresenter.java @@ -200,6 +200,10 @@ class DividerPresenter implements View.OnTouchListener { } // At this point, a divider is required. + final TaskFragmentContainer primaryContainer = + topSplitContainer.getPrimaryContainer(); + final TaskFragmentContainer secondaryContainer = + topSplitContainer.getSecondaryContainer(); // Create the decor surface if one is not available yet. final SurfaceControl decorSurface = parentInfo.getDecorSurface(); @@ -207,41 +211,44 @@ class DividerPresenter implements View.OnTouchListener { // Clean up when the decor surface is currently unavailable. removeDivider(); // Request to create the decor surface - createOrMoveDecorSurfaceLocked(wct, topSplitContainer.getPrimaryContainer()); + createOrMoveDecorSurfaceLocked(wct, primaryContainer); return; } // Update the decor surface owner if needed. boolean isDraggableExpandType = SplitAttributesHelper.isDraggableExpandType(splitAttributes); - final TaskFragmentContainer decorSurfaceOwnerContainer = isDraggableExpandType - ? topSplitContainer.getSecondaryContainer() - : topSplitContainer.getPrimaryContainer(); + final TaskFragmentContainer decorSurfaceOwnerContainer = + isDraggableExpandType ? secondaryContainer : primaryContainer; if (!Objects.equals( mDecorSurfaceOwner, decorSurfaceOwnerContainer.getTaskFragmentToken())) { createOrMoveDecorSurfaceLocked(wct, decorSurfaceOwnerContainer); } - final boolean isVerticalSplit = isVerticalSplit(topSplitContainer); - final boolean isReversedLayout = isReversedLayout( - topSplitContainer.getCurrentSplitAttributes(), - parentInfo.getConfiguration()); + + final Configuration parentConfiguration = parentInfo.getConfiguration(); + final Rect taskBounds = parentConfiguration.windowConfiguration.getBounds(); + final boolean isVerticalSplit = isVerticalSplit(splitAttributes); + final boolean isReversedLayout = isReversedLayout(splitAttributes, parentConfiguration); + final int dividerWidthPx = getDividerWidthPx(dividerAttributes); updateProperties( new Properties( - parentInfo.getConfiguration(), + parentConfiguration, dividerAttributes, decorSurface, getInitialDividerPosition( - topSplitContainer, isVerticalSplit, isReversedLayout), + primaryContainer, secondaryContainer, taskBounds, + dividerWidthPx, isDraggableExpandType, isVerticalSplit, + isReversedLayout), isVerticalSplit, isReversedLayout, parentInfo.getDisplayId(), isDraggableExpandType, - getContainerBackgroundColor(topSplitContainer.getPrimaryContainer(), - DEFAULT_PRIMARY_VEIL_COLOR), - getContainerBackgroundColor(topSplitContainer.getSecondaryContainer(), - DEFAULT_SECONDARY_VEIL_COLOR) + getContainerBackgroundColor( + primaryContainer, DEFAULT_PRIMARY_VEIL_COLOR), + getContainerBackgroundColor( + secondaryContainer, DEFAULT_SECONDARY_VEIL_COLOR) )); } } @@ -338,32 +345,31 @@ class DividerPresenter implements View.OnTouchListener { @VisibleForTesting static int getInitialDividerPosition( - @NonNull SplitContainer splitContainer, + @NonNull TaskFragmentContainer primaryContainer, + @NonNull TaskFragmentContainer secondaryContainer, + @NonNull Rect taskBounds, + int dividerWidthPx, + boolean isDraggableExpandType, boolean isVerticalSplit, boolean isReversedLayout) { - final Rect primaryBounds = - splitContainer.getPrimaryContainer().getLastRequestedBounds(); - final Rect secondaryBounds = - splitContainer.getSecondaryContainer().getLastRequestedBounds(); - final SplitAttributes splitAttributes = splitContainer.getCurrentSplitAttributes(); - - if (SplitAttributesHelper.isDraggableExpandType(splitAttributes)) { - // If the container is fully expanded by dragging the divider, we display the divider - // on the edge. - final int dividerWidth = getDividerWidthPx(splitAttributes.getDividerAttributes()); + if (isDraggableExpandType) { + // If the secondary container is fully expanded by dragging the divider, we display the + // divider on the edge. final int fullyExpandedPosition = isVerticalSplit - ? primaryBounds.right - dividerWidth - : primaryBounds.bottom - dividerWidth; + ? taskBounds.width() - dividerWidthPx + : taskBounds.height() - dividerWidthPx; return isReversedLayout ? fullyExpandedPosition : 0; } else { + final Rect primaryBounds = primaryContainer.getLastRequestedBounds(); + final Rect secondaryBounds = secondaryContainer.getLastRequestedBounds(); return isVerticalSplit ? Math.min(primaryBounds.right, secondaryBounds.right) : Math.min(primaryBounds.bottom, secondaryBounds.bottom); } } - private static boolean isVerticalSplit(@NonNull SplitContainer splitContainer) { - final int layoutDirection = splitContainer.getCurrentSplitAttributes().getLayoutDirection(); + private static boolean isVerticalSplit(@NonNull SplitAttributes splitAttributes) { + final int layoutDirection = splitAttributes.getLayoutDirection(); switch (layoutDirection) { case SplitAttributes.LayoutDirection.LEFT_TO_RIGHT: case SplitAttributes.LayoutDirection.RIGHT_TO_LEFT: @@ -510,7 +516,7 @@ class DividerPresenter implements View.OnTouchListener { if (mProperties != null && mRenderer != null) { final Rect taskBounds = mProperties.mConfiguration.windowConfiguration.getBounds(); mDividerPosition = calculateDividerPosition( - event, taskBounds, mRenderer.mDividerWidthPx, + event, taskBounds, mProperties.mDividerWidthPx, mProperties.mDividerAttributes, mProperties.mIsVerticalSplit, calculateMinPosition(), calculateMaxPosition()); mRenderer.setDividerPosition(mDividerPosition); @@ -676,8 +682,8 @@ class DividerPresenter implements View.OnTouchListener { final int minPosition = calculateMinPosition(); final int maxPosition = calculateMaxPosition(); final int fullyExpandedPosition = mProperties.mIsVerticalSplit - ? taskBounds.right - mRenderer.mDividerWidthPx - : taskBounds.bottom - mRenderer.mDividerWidthPx; + ? taskBounds.width() - mProperties.mDividerWidthPx + : taskBounds.height() - mProperties.mDividerWidthPx; if (isDraggingToFullscreenAllowed(mProperties.mDividerAttributes)) { final float displayDensity = getDisplayDensity(); @@ -782,7 +788,7 @@ class DividerPresenter implements View.OnTouchListener { private int calculateMinPosition() { return calculateMinPosition( mProperties.mConfiguration.windowConfiguration.getBounds(), - mRenderer.mDividerWidthPx, mProperties.mDividerAttributes, + mProperties.mDividerWidthPx, mProperties.mDividerAttributes, mProperties.mIsVerticalSplit, mProperties.mIsReversedLayout); } @@ -790,7 +796,7 @@ class DividerPresenter implements View.OnTouchListener { private int calculateMaxPosition() { return calculateMaxPosition( mProperties.mConfiguration.windowConfiguration.getBounds(), - mRenderer.mDividerWidthPx, mProperties.mDividerAttributes, + mProperties.mDividerWidthPx, mProperties.mDividerAttributes, mProperties.mIsVerticalSplit, mProperties.mIsReversedLayout); } @@ -828,13 +834,12 @@ class DividerPresenter implements View.OnTouchListener { * Returns the new split ratio of the {@link SplitContainer} based on the current divider * position. */ - float calculateNewSplitRatio(@NonNull SplitContainer topSplitContainer) { + float calculateNewSplitRatio() { synchronized (mLock) { return calculateNewSplitRatio( - topSplitContainer, mDividerPosition, mProperties.mConfiguration.windowConfiguration.getBounds(), - mRenderer.mDividerWidthPx, + mProperties.mDividerWidthPx, mProperties.mIsVerticalSplit, mProperties.mIsReversedLayout, calculateMinPosition(), @@ -846,21 +851,20 @@ class DividerPresenter implements View.OnTouchListener { private static boolean isDraggingToFullscreenAllowed( @NonNull DividerAttributes dividerAttributes) { // TODO(b/293654166) Use DividerAttributes.isDraggingToFullscreenAllowed when extension is - // updated. - return true; + // updated to v7. + return false; } /** * Returns the new split ratio of the {@link SplitContainer} based on the current divider * position. * - * @param topSplitContainer the {@link SplitContainer} for which to compute the split ratio. * @param dividerPosition the divider position. See {@link #mDividerPosition}. * @param taskBounds the task bounds * @param dividerWidthPx the width of the divider in pixels. * @param isVerticalSplit if {@code true}, the split is a vertical split. If {@code false}, the * split is a horizontal split. See - * {@link #isVerticalSplit(SplitContainer)}. + * {@link #isVerticalSplit(SplitAttributes)}. * @param isReversedLayout if {@code true}, the split layout is reversed, i.e. right-to-left or * bottom-to-top. If {@code false}, the split is not reversed, i.e. * left-to-right or top-to-bottom. See @@ -871,7 +875,6 @@ class DividerPresenter implements View.OnTouchListener { */ @VisibleForTesting static float calculateNewSplitRatio( - @NonNull SplitContainer topSplitContainer, int dividerPosition, @NonNull Rect taskBounds, int dividerWidthPx, @@ -896,8 +899,6 @@ class DividerPresenter implements View.OnTouchListener { dividerPosition = Math.clamp(dividerPosition, minPosition, maxPosition); } - final TaskFragmentContainer primaryContainer = topSplitContainer.getPrimaryContainer(); - final Rect origPrimaryBounds = primaryContainer.getLastRequestedBounds(); final int usableSize = isVerticalSplit ? taskBounds.width() - dividerWidthPx : taskBounds.height() - dividerWidthPx; @@ -905,13 +906,13 @@ class DividerPresenter implements View.OnTouchListener { final float newRatio; if (isVerticalSplit) { final int newPrimaryWidth = isReversedLayout - ? (origPrimaryBounds.right - (dividerPosition + dividerWidthPx)) - : (dividerPosition - origPrimaryBounds.left); + ? taskBounds.width() - (dividerPosition + dividerWidthPx) + : dividerPosition; newRatio = 1.0f * newPrimaryWidth / usableSize; } else { final int newPrimaryHeight = isReversedLayout - ? (origPrimaryBounds.bottom - (dividerPosition + dividerWidthPx)) - : (dividerPosition - origPrimaryBounds.top); + ? taskBounds.height() - (dividerPosition + dividerWidthPx) + : dividerPosition; newRatio = 1.0f * newPrimaryHeight / usableSize; } return newRatio; @@ -966,6 +967,7 @@ class DividerPresenter implements View.OnTouchListener { private final boolean mIsDraggableExpandType; private final Color mPrimaryVeilColor; private final Color mSecondaryVeilColor; + private final int mDividerWidthPx; @VisibleForTesting Properties( @@ -989,6 +991,7 @@ class DividerPresenter implements View.OnTouchListener { mIsDraggableExpandType = isDraggableExpandType; mPrimaryVeilColor = primaryVeilColor; mSecondaryVeilColor = secondaryVeilColor; + mDividerWidthPx = getDividerWidthPx(dividerAttributes); } /** @@ -1055,7 +1058,6 @@ class DividerPresenter implements View.OnTouchListener { private final View.OnTouchListener mListener; @NonNull private Properties mProperties; - private int mDividerWidthPx; private int mHandleWidthPx; @Nullable private SurfaceControl mPrimaryVeil; @@ -1095,7 +1097,6 @@ class DividerPresenter implements View.OnTouchListener { /** Updates the divider when initializing or when properties are changed */ @VisibleForTesting void update() { - mDividerWidthPx = getDividerWidthPx(mProperties.mDividerAttributes); mDividerPosition = mProperties.mInitialDividerPosition; mWindowlessWindowManager.setConfiguration(mProperties.mConfiguration); @@ -1161,15 +1162,17 @@ class DividerPresenter implements View.OnTouchListener { // When the divider drag handle width is larger than the divider width, the position // of the divider surface is adjusted so that it is large enough to host both the // divider line and the divider drag handle. - mDividerSurfaceWidthPx = Math.max(mDividerWidthPx, mHandleWidthPx); + mDividerSurfaceWidthPx = Math.max(mProperties.mDividerWidthPx, mHandleWidthPx); + dividerSurfacePosition = mProperties.mIsReversedLayout + ? mDividerPosition + : mDividerPosition + mProperties.mDividerWidthPx - mDividerSurfaceWidthPx; dividerSurfacePosition = - mProperties.mIsReversedLayout - ? mDividerPosition - : mDividerPosition + mDividerWidthPx - mDividerSurfaceWidthPx; - dividerSurfacePosition = Math.clamp(dividerSurfacePosition, 0, - mProperties.mIsVerticalSplit ? taskBounds.width() : taskBounds.height()); + Math.clamp(dividerSurfacePosition, 0, + mProperties.mIsVerticalSplit + ? taskBounds.width() - mDividerSurfaceWidthPx + : taskBounds.height() - mDividerSurfaceWidthPx); } else { - mDividerSurfaceWidthPx = mDividerWidthPx; + mDividerSurfaceWidthPx = mProperties.mDividerWidthPx; dividerSurfacePosition = mDividerPosition; } @@ -1182,16 +1185,9 @@ class DividerPresenter implements View.OnTouchListener { } // Update divider line position in the surface - if (!mProperties.mIsReversedLayout) { - final int offset = mDividerPosition - dividerSurfacePosition; - mDividerLine.setX(mProperties.mIsVerticalSplit ? offset : 0); - mDividerLine.setY(mProperties.mIsVerticalSplit ? 0 : offset); - } else { - // For reversed layout, the divider line is always at the start of the divider - // surface. - mDividerLine.setX(0); - mDividerLine.setY(0); - } + final int offset = mDividerPosition - dividerSurfacePosition; + mDividerLine.setX(mProperties.mIsVerticalSplit ? offset : 0); + mDividerLine.setY(mProperties.mIsVerticalSplit ? 0 : offset); if (mIsDragging) { updateVeils(t); @@ -1241,8 +1237,10 @@ class DividerPresenter implements View.OnTouchListener { final Rect taskBounds = mProperties.mConfiguration.windowConfiguration.getBounds(); mDividerLine.setLayoutParams( mProperties.mIsVerticalSplit - ? new FrameLayout.LayoutParams(mDividerWidthPx, taskBounds.height()) - : new FrameLayout.LayoutParams(taskBounds.width(), mDividerWidthPx) + ? new FrameLayout.LayoutParams( + mProperties.mDividerWidthPx, taskBounds.height()) + : new FrameLayout.LayoutParams( + taskBounds.width(), mProperties.mDividerWidthPx) ); if (mProperties.mDividerAttributes.getDividerType() == DividerAttributes.DIVIDER_TYPE_DRAGGABLE) { @@ -1352,13 +1350,14 @@ class DividerPresenter implements View.OnTouchListener { Rect secondaryBounds; if (mProperties.mIsVerticalSplit) { final Rect boundsLeft = new Rect(0, 0, mDividerPosition, taskBounds.height()); - final Rect boundsRight = new Rect(mDividerPosition + mDividerWidthPx, 0, + final Rect boundsRight = new Rect(mDividerPosition + mProperties.mDividerWidthPx, 0, taskBounds.width(), taskBounds.height()); primaryBounds = mProperties.mIsReversedLayout ? boundsRight : boundsLeft; secondaryBounds = mProperties.mIsReversedLayout ? boundsLeft : boundsRight; } else { final Rect boundsTop = new Rect(0, 0, taskBounds.width(), mDividerPosition); - final Rect boundsBottom = new Rect(0, mDividerPosition + mDividerWidthPx, + final Rect boundsBottom = new Rect( + 0, mDividerPosition + mProperties.mDividerWidthPx, taskBounds.width(), taskBounds.height()); primaryBounds = mProperties.mIsReversedLayout ? boundsBottom : boundsTop; secondaryBounds = mProperties.mIsReversedLayout ? boundsTop : boundsBottom; diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java index c708da97d908..ee00c4cd67eb 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java @@ -510,7 +510,7 @@ class TaskContainer { return; } final TaskFragmentContainer primaryContainer = topSplitContainer.getPrimaryContainer(); - final float newRatio = dividerPresenter.calculateNewSplitRatio(topSplitContainer); + final float newRatio = dividerPresenter.calculateNewSplitRatio(); // If the primary container is fully expanded, we should finish all the associated // secondary containers. diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/DividerPresenterTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/DividerPresenterTest.java index 20626c79714e..4515187f231e 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/DividerPresenterTest.java +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/DividerPresenterTest.java @@ -144,6 +144,7 @@ public class DividerPresenterTest { new SplitAttributes.Builder() .setDividerAttributes(DEFAULT_DIVIDER_ATTRIBUTES) .build()); + final Rect mockTaskBounds = new Rect(0, 0, 2000, 1000); final TaskFragmentContainer mockPrimaryContainer = createMockTaskFragmentContainer( mPrimaryContainerToken, new Rect(0, 0, 950, 1000)); @@ -158,7 +159,9 @@ public class DividerPresenterTest { DEFAULT_DIVIDER_ATTRIBUTES, mSurfaceControl, getInitialDividerPosition( - mSplitContainer, true /* isVerticalSplit */, false /* isReversedLayout */), + mockPrimaryContainer, mockSecondaryContainer, mockTaskBounds, + 50 /* divideWidthPx */, false /* isDraggableExpandType */, + true /* isVerticalSplit */, false /* isReversedLayout */), true /* isVerticalSplit */, false /* isReversedLayout */, Display.DEFAULT_DISPLAY, @@ -502,7 +505,6 @@ public class DividerPresenterTest { assertEquals( 0.3f, // Primary is 300px after dragging. DividerPresenter.calculateNewSplitRatio( - mSplitContainer, dividerPosition, taskBounds, dividerWidthPx, @@ -518,7 +520,6 @@ public class DividerPresenterTest { assertEquals( DividerPresenter.RATIO_EXPANDED_SECONDARY, DividerPresenter.calculateNewSplitRatio( - mSplitContainer, dividerPosition, taskBounds, dividerWidthPx, @@ -535,7 +536,6 @@ public class DividerPresenterTest { assertEquals( 0.2f, // Adjusted to the minPosition 200 DividerPresenter.calculateNewSplitRatio( - mSplitContainer, dividerPosition, taskBounds, dividerWidthPx, @@ -569,7 +569,6 @@ public class DividerPresenterTest { // After dragging, secondary is [0, 0, 2000, 300]. Primary is [0, 400, 2000, 1100]. 0.7f, DividerPresenter.calculateNewSplitRatio( - mSplitContainer, dividerPosition, taskBounds, dividerWidthPx, @@ -587,7 +586,6 @@ public class DividerPresenterTest { // The primary (bottom) container is expanded DividerPresenter.RATIO_EXPANDED_PRIMARY, DividerPresenter.calculateNewSplitRatio( - mSplitContainer, dividerPosition, taskBounds, dividerWidthPx, @@ -605,7 +603,6 @@ public class DividerPresenterTest { // Adjusted to minPosition 200, so the primary (bottom) container is 800. 0.8f, DividerPresenter.calculateNewSplitRatio( - mSplitContainer, dividerPosition, taskBounds, dividerWidthPx, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java index 6fcea1fe5560..b52b0d8dee74 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java @@ -489,6 +489,14 @@ public class PipTransition extends PipTransitionController { // activity windowing mode, and set the task bounds to the final bounds wct.setActivityWindowingMode(taskInfo.token, WINDOWING_MODE_UNDEFINED); wct.setBounds(taskInfo.token, destinationBounds); + // If the animation is only used to apply destination bounds immediately and + // invisibly, then reshow it until the pip is drawn with the bounds. + final PipAnimationController.PipTransitionAnimator<?> animator = + mPipAnimationController.getCurrentAnimator(); + if (animator != null && animator.getEndValue().equals(0f)) { + tx.addTransactionCommittedListener(mTransitions.getMainExecutor(), + () -> fadeExistingPip(true /* show */)); + } } else { wct.setBounds(taskInfo.token, null /* bounds */); } @@ -1026,6 +1034,7 @@ public class PipTransition extends PipTransitionController { } startTransaction.apply(); + int animationDuration = mEnterExitAnimationDuration; PipAnimationController.PipTransitionAnimator animator; if (enterAnimationType == ANIM_TYPE_BOUNDS) { animator = mPipAnimationController.getAnimator(taskInfo, leash, currentBounds, @@ -1057,8 +1066,17 @@ public class PipTransition extends PipTransitionController { } } } else if (enterAnimationType == ANIM_TYPE_ALPHA) { + // In case augmentRequest() is unable to apply the entering bounds (e.g. the request + // info only contains display change), keep the animation invisible (alpha 0) and + // duration 0 to apply the destination bounds. The actual fade-in animation will be + // done in onFinishResize() after the bounds are applied. + final boolean fadeInAfterOnFinishResize = rotationDelta != Surface.ROTATION_0 + && mFixedRotationState == FIXED_ROTATION_CALLBACK; animator = mPipAnimationController.getAnimator(taskInfo, leash, destinationBounds, - 0f, 1f); + 0f, fadeInAfterOnFinishResize ? 0f : 1f); + if (fadeInAfterOnFinishResize) { + animationDuration = 0; + } mSurfaceTransactionHelper .crop(finishTransaction, leash, destinationBounds) .round(finishTransaction, leash, true /* applyCornerRadius */); @@ -1068,7 +1086,7 @@ public class PipTransition extends PipTransitionController { mPipOrganizer.setContentOverlay(animator.getContentOverlayLeash(), currentBounds); animator.setTransitionDirection(TRANSITION_DIRECTION_TO_PIP) .setPipAnimationCallback(mPipAnimationCallback) - .setDuration(mEnterExitAnimationDuration); + .setDuration(animationDuration); if (rotationDelta != Surface.ROTATION_0 && mFixedRotationState == FIXED_ROTATION_TRANSITION) { // For fixed rotation, the animation destination bounds is in old rotation coordinates. diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLoggerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLoggerTest.kt index 285e5b6a04a5..51b291c0b7a4 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLoggerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLoggerTest.kt @@ -39,7 +39,7 @@ import org.junit.runner.RunWith class DesktopModeUiEventLoggerTest : ShellTestCase() { private lateinit var uiEventLoggerFake: UiEventLoggerFake private lateinit var logger: DesktopModeUiEventLogger - private val instanceIdSequence = InstanceIdSequence(10) + private val instanceIdSequence = InstanceIdSequence(/* instanceIdMax */ 1 shl 20) @Before diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java index 70462effaa54..442ccdcddb2b 100644 --- a/media/java/android/media/session/MediaController.java +++ b/media/java/android/media/session/MediaController.java @@ -141,10 +141,9 @@ public final class MediaController { } try { return mSessionBinder.sendMediaButton(mContext.getPackageName(), keyEvent); - } catch (RemoteException e) { - // System is dead. =( + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } - return false; } /** @@ -155,9 +154,8 @@ public final class MediaController { public @Nullable PlaybackState getPlaybackState() { try { return mSessionBinder.getPlaybackState(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getPlaybackState.", e); - return null; + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -169,9 +167,8 @@ public final class MediaController { public @Nullable MediaMetadata getMetadata() { try { return mSessionBinder.getMetadata(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getMetadata.", e); - return null; + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -185,10 +182,9 @@ public final class MediaController { try { ParceledListSlice list = mSessionBinder.getQueue(); return list == null ? null : list.getList(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getQueue.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } - return null; } /** @@ -197,10 +193,9 @@ public final class MediaController { public @Nullable CharSequence getQueueTitle() { try { return mSessionBinder.getQueueTitle(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getQueueTitle", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } - return null; } /** @@ -209,10 +204,9 @@ public final class MediaController { public @Nullable Bundle getExtras() { try { return mSessionBinder.getExtras(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getExtras", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } - return null; } /** @@ -232,9 +226,8 @@ public final class MediaController { public int getRatingType() { try { return mSessionBinder.getRatingType(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getRatingType.", e); - return Rating.RATING_NONE; + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -246,10 +239,9 @@ public final class MediaController { public long getFlags() { try { return mSessionBinder.getFlags(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getFlags.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } - return 0; } /** Returns the current playback info for this session. */ @@ -271,10 +263,9 @@ public final class MediaController { public @Nullable PendingIntent getSessionActivity() { try { return mSessionBinder.getLaunchPendingIntent(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getPendingIntent.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } - return null; } /** @@ -304,8 +295,8 @@ public final class MediaController { // AppOpsManager usages. mSessionBinder.setVolumeTo(mContext.getPackageName(), mContext.getOpPackageName(), value, flags); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling setVolumeTo.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -329,8 +320,8 @@ public final class MediaController { // AppOpsManager usages. mSessionBinder.adjustVolume(mContext.getPackageName(), mContext.getOpPackageName(), direction, flags); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling adjustVolumeBy.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -395,8 +386,8 @@ public final class MediaController { } try { mSessionBinder.sendCommand(mContext.getPackageName(), command, args, cb); - } catch (RemoteException e) { - Log.d(TAG, "Dead object in sendCommand.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -409,8 +400,8 @@ public final class MediaController { if (mPackageName == null) { try { mPackageName = mSessionBinder.getPackageName(); - } catch (RemoteException e) { - Log.d(TAG, "Dead object in getPackageName.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } return mPackageName; @@ -430,8 +421,8 @@ public final class MediaController { // Get info from the connected session. try { mSessionInfo = mSessionBinder.getSessionInfo(); - } catch (RemoteException e) { - Log.d(TAG, "Dead object in getSessionInfo.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } if (mSessionInfo == null) { @@ -454,8 +445,8 @@ public final class MediaController { if (mTag == null) { try { mTag = mSessionBinder.getTag(); - } catch (RemoteException e) { - Log.d(TAG, "Dead object in getTag.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } return mTag; @@ -485,8 +476,8 @@ public final class MediaController { try { mSessionBinder.registerCallback(mContext.getPackageName(), mCbStub); mCbRegistered = true; - } catch (RemoteException e) { - Log.e(TAG, "Dead object in registerCallback", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } } @@ -504,8 +495,8 @@ public final class MediaController { if (mCbRegistered && mCallbacks.size() == 0) { try { mSessionBinder.unregisterCallback(mCbStub); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in removeCallbackLocked"); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } mCbRegistered = false; } @@ -641,8 +632,8 @@ public final class MediaController { public void prepare() { try { mSessionBinder.prepare(mContext.getPackageName()); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling prepare.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -665,8 +656,8 @@ public final class MediaController { } try { mSessionBinder.prepareFromMediaId(mContext.getPackageName(), mediaId, extras); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -691,8 +682,8 @@ public final class MediaController { } try { mSessionBinder.prepareFromSearch(mContext.getPackageName(), query, extras); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling prepare(" + query + ").", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -715,8 +706,8 @@ public final class MediaController { } try { mSessionBinder.prepareFromUri(mContext.getPackageName(), uri, extras); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling prepare(" + uri + ").", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -726,8 +717,8 @@ public final class MediaController { public void play() { try { mSessionBinder.play(mContext.getPackageName()); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling play.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -745,8 +736,8 @@ public final class MediaController { } try { mSessionBinder.playFromMediaId(mContext.getPackageName(), mediaId, extras); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling play(" + mediaId + ").", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -767,8 +758,8 @@ public final class MediaController { } try { mSessionBinder.playFromSearch(mContext.getPackageName(), query, extras); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling play(" + query + ").", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -786,8 +777,8 @@ public final class MediaController { } try { mSessionBinder.playFromUri(mContext.getPackageName(), uri, extras); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling play(" + uri + ").", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -798,8 +789,8 @@ public final class MediaController { public void skipToQueueItem(long id) { try { mSessionBinder.skipToQueueItem(mContext.getPackageName(), id); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -810,8 +801,8 @@ public final class MediaController { public void pause() { try { mSessionBinder.pause(mContext.getPackageName()); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling pause.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -822,8 +813,8 @@ public final class MediaController { public void stop() { try { mSessionBinder.stop(mContext.getPackageName()); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling stop.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -835,8 +826,8 @@ public final class MediaController { public void seekTo(long pos) { try { mSessionBinder.seekTo(mContext.getPackageName(), pos); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling seekTo.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -847,8 +838,8 @@ public final class MediaController { public void fastForward() { try { mSessionBinder.fastForward(mContext.getPackageName()); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling fastForward.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -858,8 +849,8 @@ public final class MediaController { public void skipToNext() { try { mSessionBinder.next(mContext.getPackageName()); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling next.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -870,8 +861,8 @@ public final class MediaController { public void rewind() { try { mSessionBinder.rewind(mContext.getPackageName()); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling rewind.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -881,8 +872,8 @@ public final class MediaController { public void skipToPrevious() { try { mSessionBinder.previous(mContext.getPackageName()); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling previous.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -896,8 +887,8 @@ public final class MediaController { public void setRating(Rating rating) { try { mSessionBinder.rate(mContext.getPackageName(), rating); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling rate.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -914,8 +905,8 @@ public final class MediaController { } try { mSessionBinder.setPlaybackSpeed(mContext.getPackageName(), speed); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling setPlaybackSpeed.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } @@ -949,8 +940,8 @@ public final class MediaController { } try { mSessionBinder.sendCustomAction(mContext.getPackageName(), action, args); - } catch (RemoteException e) { - Log.d(TAG, "Dead object in sendCustomAction.", e); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); } } } diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/LifecycleEffect.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/LifecycleEffect.kt index e91fa65401a4..e9f9689cb319 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/LifecycleEffect.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/LifecycleEffect.kt @@ -18,9 +18,9 @@ package com.android.settingslib.spa.framework.compose import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect -import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver +import androidx.lifecycle.compose.LocalLifecycleOwner @Composable fun LifecycleEffect( diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/OnBackEffect.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/OnBackEffect.kt index 3991f26e1b0c..0b1c92d78a57 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/OnBackEffect.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/OnBackEffect.kt @@ -24,7 +24,7 @@ import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.runtime.rememberUpdatedState -import androidx.compose.ui.platform.LocalLifecycleOwner +import androidx.lifecycle.compose.LocalLifecycleOwner /** * An effect for detecting presses of the system back button, and the back event will not be diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/slice/presenter/Demo.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/slice/presenter/Demo.kt index ee24a09d4395..007f47bd3c82 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/slice/presenter/Demo.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/slice/presenter/Demo.kt @@ -21,8 +21,8 @@ import androidx.compose.material3.HorizontalDivider import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.viewinterop.AndroidView +import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.slice.widget.SliceLiveData import androidx.slice.widget.SliceView diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialog.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialog.kt index de080e3d8ef4..022ddedd1062 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialog.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialog.kt @@ -38,6 +38,7 @@ import androidx.compose.ui.window.DialogProperties data class AlertDialogButton( val text: String, + val enabled: Boolean = true, val onClick: () -> Unit = {}, ) @@ -114,6 +115,7 @@ private fun AlertDialogPresenter.Button(button: AlertDialogButton) { close() button.onClick() }, + enabled = button.enabled, ) { Text(button.text) } diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/DropdownTextBox.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/DropdownTextBox.kt index b471e50be275..bdbe62c07425 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/DropdownTextBox.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/DropdownTextBox.kt @@ -22,6 +22,7 @@ import androidx.compose.foundation.layout.width import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExposedDropdownMenuBox import androidx.compose.material3.ExposedDropdownMenuDefaults +import androidx.compose.material3.MenuAnchorType import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -65,7 +66,7 @@ internal fun DropdownTextBox( OutlinedTextField( // The `menuAnchor` modifier must be passed to the text field for correctness. modifier = Modifier - .menuAnchor() + .menuAnchor(MenuAnchorType.PrimaryNotEditable) .fillMaxWidth(), value = text, onValueChange = { }, diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/compose/LifecycleEffectTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/compose/LifecycleEffectTest.kt index fe7baff43101..8b0efff591f2 100644 --- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/compose/LifecycleEffectTest.kt +++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/compose/LifecycleEffectTest.kt @@ -18,9 +18,9 @@ package com.android.settingslib.spa.framework.compose import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect -import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.test.junit4.createComposeRule import androidx.lifecycle.Lifecycle +import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.testing.TestLifecycleOwner import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.common.truth.Truth.assertThat diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialogTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialogTest.kt index 9468f95a094e..20ea397d7222 100644 --- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialogTest.kt +++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialogTest.kt @@ -20,6 +20,8 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.assertIsEnabled +import androidx.compose.ui.test.assertIsNotEnabled import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.performClick import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -67,7 +69,18 @@ class SettingsAlertDialogTest { rememberAlertDialogPresenter(confirmButton = AlertDialogButton(CONFIRM_TEXT)) } - composeTestRule.onDialogText(CONFIRM_TEXT).assertIsDisplayed() + composeTestRule.onDialogText(CONFIRM_TEXT).assertIsDisplayed().assertIsEnabled() + } + + @Test + fun confirmButton_disabled() { + setAndOpenDialog { + rememberAlertDialogPresenter( + confirmButton = AlertDialogButton(text = CONFIRM_TEXT, enabled = false) + ) + } + + composeTestRule.onDialogText(CONFIRM_TEXT).assertIsDisplayed().assertIsNotEnabled() } @Test @@ -90,7 +103,18 @@ class SettingsAlertDialogTest { rememberAlertDialogPresenter(dismissButton = AlertDialogButton(DISMISS_TEXT)) } - composeTestRule.onDialogText(DISMISS_TEXT).assertIsDisplayed() + composeTestRule.onDialogText(DISMISS_TEXT).assertIsDisplayed().assertIsEnabled() + } + + @Test + fun dismissButton_disabled() { + setAndOpenDialog { + rememberAlertDialogPresenter( + dismissButton = AlertDialogButton(text = DISMISS_TEXT, enabled = false) + ) + } + + composeTestRule.onDialogText(DISMISS_TEXT).assertIsDisplayed().assertIsNotEnabled() } @Test diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/scaffold/RestrictedMenuItem.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/scaffold/RestrictedMenuItem.kt index 977615b55a6a..f95cfc3191c8 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/scaffold/RestrictedMenuItem.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/scaffold/RestrictedMenuItem.kt @@ -30,22 +30,24 @@ import com.android.settingslib.spaprivileged.model.enterprise.rememberRestricted @Composable fun MoreOptionsScope.RestrictedMenuItem( text: String, + enabled: Boolean = true, restrictions: Restrictions, onClick: () -> Unit, ) { - RestrictedMenuItemImpl(text, restrictions, onClick, ::RestrictionsProviderImpl) + RestrictedMenuItemImpl(text, enabled, restrictions, onClick, ::RestrictionsProviderImpl) } @VisibleForTesting @Composable internal fun MoreOptionsScope.RestrictedMenuItemImpl( text: String, + enabled: Boolean = true, restrictions: Restrictions, onClick: () -> Unit, restrictionsProviderFactory: RestrictionsProviderFactory, ) { val restrictedMode = restrictionsProviderFactory.rememberRestrictedMode(restrictions).value - MenuItem(text = text, enabled = restrictedMode !== BaseUserRestricted) { + MenuItem(text = text, enabled = enabled && restrictedMode !== BaseUserRestricted) { when (restrictedMode) { is BlockedByAdmin -> restrictedMode.sendShowAdminSupportDetailsIntent() is BlockedByEcm -> restrictedMode.showRestrictedSettingsDetails() diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/scaffold/RestrictedMenuItemTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/scaffold/RestrictedMenuItemTest.kt index 556adc750763..4068bceb1475 100644 --- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/scaffold/RestrictedMenuItemTest.kt +++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/scaffold/RestrictedMenuItemTest.kt @@ -49,6 +49,15 @@ class RestrictedMenuItemTest { private var menuItemOnClickIsCalled = false @Test + fun whenDisabled() { + val restrictions = Restrictions(userId = USER_ID, keys = emptyList()) + + setContent(restrictions, enabled = false) + + composeTestRule.onNodeWithText(TEXT).assertIsDisplayed().assertIsNotEnabled() + } + + @Test fun whenRestrictionsKeysIsEmpty_enabled() { val restrictions = Restrictions(userId = USER_ID, keys = emptyList()) @@ -153,13 +162,14 @@ class RestrictedMenuItemTest { assertThat(menuItemOnClickIsCalled).isFalse() } - private fun setContent(restrictions: Restrictions) { + private fun setContent(restrictions: Restrictions, enabled: Boolean = true) { val fakeMoreOptionsScope = object : MoreOptionsScope() { override fun dismiss() {} } composeTestRule.setContent { fakeMoreOptionsScope.RestrictedMenuItemImpl( text = TEXT, + enabled = enabled, restrictions = restrictions, onClick = { menuItemOnClickIsCalled = true }, restrictionsProviderFactory = { _, _ -> fakeRestrictionsProvider }, diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java index ca1e4c10d339..e4898daf3cbf 100644 --- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java +++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java @@ -27,11 +27,11 @@ import android.support.test.uiautomator.UiDevice; import androidx.test.platform.app.InstrumentationRegistry; +import com.android.bedstead.enterprise.annotations.EnsureHasNoWorkProfile; +import com.android.bedstead.enterprise.annotations.EnsureHasWorkProfile; import com.android.bedstead.harrier.BedsteadJUnit4; import com.android.bedstead.harrier.DeviceState; -import com.android.bedstead.harrier.annotations.EnsureHasNoWorkProfile; import com.android.bedstead.harrier.annotations.EnsureHasSecondaryUser; -import com.android.bedstead.harrier.annotations.EnsureHasWorkProfile; import com.android.bedstead.harrier.annotations.RequireFeature; import com.android.bedstead.harrier.annotations.RequireRunOnInitialUser; import com.android.bedstead.harrier.annotations.RequireRunOnPrimaryUser; diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt index 271eb9601dbd..fbf91b702fb9 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt @@ -68,9 +68,7 @@ fun VolumeSlider( state.a11yClickDescription?.let { customActions = listOf( - CustomAccessibilityAction( - it, - ) { + CustomAccessibilityAction(it) { onIconTapped() true } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt index d630a2f64c5f..6c5001ab9415 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt @@ -136,20 +136,20 @@ class FromAodTransitionInteractorTest : SysuiTestCase() { @Test @EnableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR) - fun testTransitionToOccluded_onWakeUp_ifPowerButtonGestureDetected_fromAod_nonDismissableKeyguard() = + fun testTransitionToOccluded_onWakeUp_ifPowerButtonGestureDetected_fromAod_nonDismissibleKeyguard() = testScope.runTest { powerInteractor.onCameraLaunchGestureDetected() powerInteractor.setAwakeForTest() advanceTimeBy(100) // account for debouncing - // We should head back to GONE since we started there. + // We should head to OCCLUDED because keyguard is not dismissible. assertThat(transitionRepository) .startedTransition(from = KeyguardState.AOD, to = KeyguardState.OCCLUDED) } @Test @EnableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR) - fun testTransitionToGone_onWakeUp_ifPowerButtonGestureDetected_fromAod_dismissableKeyguard() = + fun testTransitionToGone_onWakeUp_ifPowerButtonGestureDetected_fromAod_dismissibleKeyguard() = testScope.runTest { kosmos.fakeKeyguardRepository.setKeyguardDismissible(true) powerInteractor.onCameraLaunchGestureDetected() @@ -188,6 +188,7 @@ class FromAodTransitionInteractorTest : SysuiTestCase() { ) // Detect a power gesture and then wake up. + kosmos.fakeKeyguardRepository.setKeyguardDismissible(true) reset(transitionRepository) powerInteractor.onCameraLaunchGestureDetected() powerInteractor.setAwakeForTest() @@ -355,6 +356,7 @@ class FromAodTransitionInteractorTest : SysuiTestCase() { ) // Detect a power gesture and then wake up. + kosmos.fakeKeyguardRepository.setKeyguardDismissible(true) reset(transitionRepository) powerInteractor.onCameraLaunchGestureDetected() powerInteractor.setAwakeForTest() diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt index bfc777509c7b..612f2e73e4bb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt @@ -56,13 +56,13 @@ import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.se import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.testKosmos import junit.framework.Assert.assertEquals -import kotlin.test.Test import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before +import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.reset import org.mockito.Mockito.spy @@ -230,6 +230,7 @@ class FromDozingTransitionInteractorTest : SysuiTestCase() { ) // Detect a power gesture and then wake up. + kosmos.fakeKeyguardRepository.setKeyguardDismissible(true) reset(transitionRepository) powerInteractor.onCameraLaunchGestureDetected() powerInteractor.setAwakeForTest() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt index 78a116737349..5068f6830fa1 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt @@ -350,7 +350,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { } @Test - fun quickAffordance_updateOncePerShadeExpansion() = + fun quickAffordance_doNotSendUpdatesWhileShadeExpandingAndStillHidden() = testScope.runTest { val shadeExpansion = MutableStateFlow(0f) whenever(shadeInteractor.anyExpansion).thenReturn(shadeExpansion) @@ -365,7 +365,9 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { shadeExpansion.value = i / 10f } - assertThat(collectedValue.size).isEqualTo(initialSize + 1) + assertThat(collectedValue[0]) + .isInstanceOf(KeyguardQuickAffordanceModel.Hidden::class.java) + assertThat(collectedValue.size).isEqualTo(initialSize) } @Test diff --git a/packages/SystemUI/res/layout-sw600dp/biometric_prompt_constraint_layout.xml b/packages/SystemUI/res/layout-sw600dp/biometric_prompt_constraint_layout.xml deleted file mode 100644 index 8b9eabc5bd93..000000000000 --- a/packages/SystemUI/res/layout-sw600dp/biometric_prompt_constraint_layout.xml +++ /dev/null @@ -1,237 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<androidx.constraintlayout.widget.ConstraintLayout 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" - xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" - android:id="@+id/biometric_prompt_constraint_layout" - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <ImageView - android:id="@+id/background" - android:layout_width="0dp" - android:layout_height="0dp" - android:contentDescription="@string/biometric_dialog_empty_space_description" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" /> - - <View - android:id="@+id/panel" - style="@style/AuthCredentialPanelStyle" - android:layout_width="0dp" - android:layout_height="0dp" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toStartOf="@+id/rightGuideline" - app:layout_constraintStart_toStartOf="@+id/leftGuideline" - app:layout_constraintTop_toTopOf="@+id/topBarrier" - app:layout_constraintWidth_max="640dp" /> - - <include - android:id="@+id/button_bar" - layout="@layout/biometric_prompt_button_bar" - android:layout_width="0dp" - android:layout_height="wrap_content" - app:layout_constraintBottom_toBottomOf="@id/bottomGuideline" - app:layout_constraintEnd_toEndOf="@id/panel" - app:layout_constraintStart_toStartOf="@id/panel" /> - - <ScrollView - android:id="@+id/scrollView" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:fadeScrollbars="false" - android:fillViewport="true" - android:paddingBottom="32dp" - android:paddingHorizontal="32dp" - android:paddingTop="24dp" - app:layout_constrainedHeight="true" - app:layout_constrainedWidth="true" - app:layout_constraintBottom_toTopOf="@+id/scrollBarrier" - app:layout_constraintEnd_toEndOf="@id/panel" - app:layout_constraintStart_toStartOf="@id/panel" - app:layout_constraintTop_toTopOf="@+id/topGuideline" - app:layout_constraintVertical_bias="1.0"> - - <androidx.constraintlayout.widget.ConstraintLayout - android:id="@+id/innerConstraint" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - - <ImageView - android:id="@+id/logo" - android:layout_width="@dimen/biometric_prompt_logo_size" - android:layout_height="@dimen/biometric_prompt_logo_size" - android:layout_gravity="center" - android:contentDescription="@string/biometric_dialog_logo" - android:scaleType="fitXY" - android:visibility="visible" - app:layout_constraintBottom_toTopOf="@+id/logo_description" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" /> - - <TextView - android:id="@+id/logo_description" - style="@style/TextAppearance.AuthCredential.LogoDescription" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingTop="16dp" - app:layout_constraintBottom_toTopOf="@+id/title" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/logo" /> - - <TextView - android:id="@+id/title" - style="@style/TextAppearance.AuthCredential.Title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:gravity="@integer/biometric_dialog_text_gravity" - android:paddingTop="16dp" - app:layout_constraintBottom_toTopOf="@+id/subtitle" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/logo_description" /> - - <TextView - android:id="@+id/subtitle" - style="@style/TextAppearance.AuthCredential.Subtitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:gravity="@integer/biometric_dialog_text_gravity" - android:paddingTop="16dp" - app:layout_constraintBottom_toTopOf="@+id/contentBarrier" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/title" /> - - <LinearLayout - android:id="@+id/customized_view_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:gravity="center_vertical" - android:orientation="vertical" - android:paddingTop="24dp" - android:visibility="gone" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/subtitle" /> - - <TextView - android:id="@+id/description" - style="@style/TextAppearance.AuthCredential.Description" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:gravity="@integer/biometric_dialog_text_gravity" - android:paddingTop="16dp" - android:textAlignment="viewStart" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/subtitle" /> - - <androidx.constraintlayout.widget.Barrier - android:id="@+id/contentBarrier" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - app:barrierAllowsGoneWidgets="false" - app:barrierDirection="top" - app:constraint_referenced_ids="description, customized_view_container" /> - - </androidx.constraintlayout.widget.ConstraintLayout> - </ScrollView> - - <!-- Cancel Button, replaces negative button when biometric is accepted --> - <TextView - android:id="@+id/indicator" - style="@style/TextAppearance.AuthCredential.Indicator" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="24dp" - android:accessibilityLiveRegion="assertive" - android:fadingEdge="horizontal" - android:gravity="center_horizontal" - android:scrollHorizontally="true" - app:layout_constraintBottom_toTopOf="@+id/button_bar" - app:layout_constraintEnd_toEndOf="@+id/panel" - app:layout_constraintStart_toStartOf="@+id/panel" - app:layout_constraintTop_toBottomOf="@+id/biometric_icon" - app:layout_constraintVertical_bias="0.0" /> - - <!-- "Use Credential" Button, replaces if device credential is allowed --> - - <!-- Positive Button --> - <androidx.constraintlayout.widget.Barrier - android:id="@+id/topBarrier" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - app:barrierAllowsGoneWidgets="false" - app:barrierDirection="top" - app:constraint_referenced_ids="scrollView" /> - - <!-- Try Again Button --> - <androidx.constraintlayout.widget.Barrier - android:id="@+id/scrollBarrier" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - app:barrierAllowsGoneWidgets="false" - app:barrierDirection="top" - app:constraint_referenced_ids="biometric_icon, button_bar" /> - - <!-- Guidelines for setting panel border --> - <androidx.constraintlayout.widget.Guideline - android:id="@+id/leftGuideline" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="vertical" - app:layout_constraintGuide_begin="@dimen/biometric_dialog_border_padding" /> - - <androidx.constraintlayout.widget.Guideline - android:id="@+id/rightGuideline" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="vertical" - app:layout_constraintGuide_end="@dimen/biometric_dialog_border_padding" /> - - <androidx.constraintlayout.widget.Guideline - android:id="@+id/bottomGuideline" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal" - app:layout_constraintGuide_end="40dp" /> - - <androidx.constraintlayout.widget.Guideline - android:id="@+id/topGuideline" - android:layout_width="0dp" - android:layout_height="0dp" - android:orientation="horizontal" - app:layout_constraintGuide_begin="56dp" /> - - <com.android.systemui.biometrics.BiometricPromptLottieViewWrapper - android:id="@+id/biometric_icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintVertical_bias="1.0" - tools:srcCompat="@tools:sample/avatars" /> - - <com.android.systemui.biometrics.BiometricPromptLottieViewWrapper - android:id="@+id/biometric_icon_overlay" - android:layout_width="0dp" - android:layout_height="0dp" - android:layout_gravity="center" - android:contentDescription="@null" - android:scaleType="fitXY" - android:importantForAccessibility="no" - app:layout_constraintBottom_toBottomOf="@+id/biometric_icon" - app:layout_constraintEnd_toEndOf="@+id/biometric_icon" - app:layout_constraintStart_toStartOf="@+id/biometric_icon" - app:layout_constraintTop_toTopOf="@+id/biometric_icon" /> - -</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/packages/SystemUI/res/layout/biometric_prompt_constraint_layout.xml b/packages/SystemUI/res/layout/biometric_prompt_one_pane_layout.xml index 9b5b59fc116f..8d50bfa00fd5 100644 --- a/packages/SystemUI/res/layout/biometric_prompt_constraint_layout.xml +++ b/packages/SystemUI/res/layout/biometric_prompt_one_pane_layout.xml @@ -22,9 +22,11 @@ android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="@id/rightGuideline" + app:layout_constraintEnd_toStartOf="@id/rightGuideline" app:layout_constraintStart_toStartOf="@id/leftGuideline" - app:layout_constraintTop_toTopOf="@id/topBarrier" /> + app:layout_constraintTop_toTopOf="@id/topBarrier" + app:layout_constraintWidth_max="@dimen/biometric_prompt_panel_max_width" /> + <include android:id="@+id/button_bar" @@ -41,8 +43,8 @@ android:layout_height="wrap_content" android:fillViewport="true" android:fadeScrollbars="false" - android:paddingBottom="24dp" - android:paddingHorizontal="24dp" + android:paddingBottom="@dimen/biometric_prompt_top_scroll_view_bottom_padding" + android:paddingHorizontal="@dimen/biometric_prompt_top_scroll_view_horizontal_padding" android:paddingTop="24dp" app:layout_constrainedHeight="true" app:layout_constrainedWidth="true" @@ -76,7 +78,7 @@ style="@style/TextAppearance.AuthCredential.LogoDescription" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingTop="8dp" + android:paddingTop="@dimen/biometric_prompt_logo_description_top_padding" app:layout_constraintBottom_toTopOf="@+id/title" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -180,14 +182,14 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" - app:layout_constraintGuide_begin="0dp" /> + app:layout_constraintGuide_begin="@dimen/biometric_prompt_one_pane_medium_horizontal_guideline_padding" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/rightGuideline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" - app:layout_constraintGuide_end="0dp" /> + app:layout_constraintGuide_end="@dimen/biometric_prompt_one_pane_medium_horizontal_guideline_padding" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/bottomGuideline" @@ -201,7 +203,7 @@ android:layout_width="0dp" android:layout_height="0dp" android:orientation="horizontal" - app:layout_constraintGuide_begin="119dp" /> + app:layout_constraintGuide_begin="@dimen/biometric_prompt_one_pane_medium_top_guideline_padding" /> <com.android.systemui.biometrics.BiometricPromptLottieViewWrapper android:id="@+id/biometric_icon" diff --git a/packages/SystemUI/res/layout-land/biometric_prompt_constraint_layout.xml b/packages/SystemUI/res/layout/biometric_prompt_two_pane_layout.xml index 01b9f7e2e38a..01b9f7e2e38a 100644 --- a/packages/SystemUI/res/layout-land/biometric_prompt_constraint_layout.xml +++ b/packages/SystemUI/res/layout/biometric_prompt_two_pane_layout.xml diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml index 2cfba01fe1c8..664fbeb29c8e 100644 --- a/packages/SystemUI/res/values-sw600dp/dimens.xml +++ b/packages/SystemUI/res/values-sw600dp/dimens.xml @@ -102,6 +102,17 @@ <dimen name="lockscreen_shade_status_bar_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen> <dimen name="lockscreen_shade_keyguard_transition_distance">@dimen/lockscreen_shade_media_transition_distance</dimen> + <!-- Dimensions for biometric prompt panel padding --> + <dimen name="biometric_prompt_one_pane_medium_top_guideline_padding">56dp</dimen> + <dimen name="biometric_prompt_one_pane_medium_horizontal_guideline_padding">@dimen/biometric_dialog_border_padding</dimen> + + <!-- Dimensions for biometric prompt scroll view padding --> + <dimen name="biometric_prompt_top_scroll_view_bottom_padding">32dp</dimen> + <dimen name="biometric_prompt_top_scroll_view_horizontal_padding">32dp</dimen> + + <!-- Dimensions for biometric prompt custom content view. --> + <dimen name="biometric_prompt_logo_description_top_padding">16dp</dimen> + <!-- Biometric Auth pattern view size, better to align keyguard_security_width --> <dimen name="biometric_auth_pattern_view_size">348dp</dimen> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index edd3d77555f7..380a79e5a289 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1119,11 +1119,18 @@ <dimen name="biometric_dialog_height">240dp</dimen> <!-- Dimensions for biometric prompt panel padding --> - <dimen name="biometric_prompt_small_horizontal_guideline_padding">344dp</dimen> - <dimen name="biometric_prompt_udfps_horizontal_guideline_padding">114dp</dimen> - <dimen name="biometric_prompt_udfps_mid_guideline_padding">409dp</dimen> - <dimen name="biometric_prompt_medium_horizontal_guideline_padding">640dp</dimen> - <dimen name="biometric_prompt_medium_mid_guideline_padding">330dp</dimen> + <dimen name="biometric_prompt_panel_max_width">640dp</dimen> + <dimen name="biometric_prompt_land_small_horizontal_guideline_padding">344dp</dimen> + <dimen name="biometric_prompt_two_pane_udfps_horizontal_guideline_padding">114dp</dimen> + <dimen name="biometric_prompt_two_pane_udfps_mid_guideline_padding">409dp</dimen> + <dimen name="biometric_prompt_two_pane_medium_horizontal_guideline_padding">640dp</dimen> + <dimen name="biometric_prompt_two_pane_medium_mid_guideline_padding">330dp</dimen> + <dimen name="biometric_prompt_one_pane_medium_top_guideline_padding">119dp</dimen> + <dimen name="biometric_prompt_one_pane_medium_horizontal_guideline_padding">0dp</dimen> + + <!-- Dimensions for biometric prompt scroll view padding --> + <dimen name="biometric_prompt_top_scroll_view_bottom_padding">24dp</dimen> + <dimen name="biometric_prompt_top_scroll_view_horizontal_padding">24dp</dimen> <!-- Dimensions for biometric prompt icon padding --> <dimen name="biometric_prompt_portrait_small_bottom_padding">60dp</dimen> @@ -1136,6 +1143,7 @@ <!-- Dimensions for biometric prompt custom content view. --> <dimen name="biometric_prompt_logo_size">32dp</dimen> + <dimen name="biometric_prompt_logo_description_top_padding">8dp</dimen> <dimen name="biometric_prompt_content_corner_radius">28dp</dimen> <dimen name="biometric_prompt_content_padding_horizontal">24dp</dimen> <dimen name="biometric_prompt_content_padding_vertical">16dp</dimen> diff --git a/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/PromptKind.kt b/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/PromptKind.kt index b99c51489521..44f2059d4e41 100644 --- a/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/PromptKind.kt +++ b/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/PromptKind.kt @@ -22,15 +22,28 @@ sealed interface PromptKind { data class Biometric( /** The available modalities for the authentication on the prompt. */ val activeModalities: BiometricModalities = BiometricModalities(), - // TODO(b/330908557): Use this value to decide whether to show two pane layout, instead of - // simply depending on rotations. - val showTwoPane: Boolean = false, - ) : PromptKind + val paneType: PaneType = PaneType.ONE_PANE_PORTRAIT, + ) : PromptKind { + enum class PaneType { + TWO_PANE_LANDSCAPE, + ONE_PANE_PORTRAIT, + ONE_PANE_NO_SENSOR_LANDSCAPE, + ONE_PANE_LARGE_SCREEN_LANDSCAPE + } + } - object Pin : PromptKind - object Pattern : PromptKind - object Password : PromptKind + data object Pin : PromptKind + data object Pattern : PromptKind + data object Password : PromptKind fun isBiometric() = this is Biometric - fun isCredential() = (this is Pin) or (this is Pattern) or (this is Password) + fun isTwoPaneLandscapeBiometric(): Boolean = + (this as? Biometric)?.paneType == Biometric.PaneType.TWO_PANE_LANDSCAPE + fun isOnePanePortraitBiometric() = + (this as? Biometric)?.paneType == Biometric.PaneType.ONE_PANE_PORTRAIT + fun isOnePaneNoSensorLandscapeBiometric() = + (this as? Biometric)?.paneType == Biometric.PaneType.ONE_PANE_NO_SENSOR_LANDSCAPE + fun isOnePaneLargeScreenLandscapeBiometric() = + (this as? Biometric)?.paneType == Biometric.PaneType.ONE_PANE_LARGE_SCREEN_LANDSCAPE + fun isCredential() = (this is Pin) || (this is Pattern) || (this is Password) } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java index 3d7accbd961f..1ee4908437a6 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java @@ -29,6 +29,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AlertDialog; import android.content.Context; +import android.content.res.Configuration; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.PixelFormat; @@ -360,15 +361,23 @@ public class AuthContainerView extends LinearLayout Utils.findFirstSensorProperties(fpProps, mConfig.mSensorIds), Utils.findFirstSensorProperties(faceProps, mConfig.mSensorIds)); + final boolean isLandscape = mContext.getResources().getConfiguration().orientation + == Configuration.ORIENTATION_LANDSCAPE; mPromptSelectorInteractorProvider = promptSelectorInteractorProvider; mPromptSelectorInteractorProvider.get().setPrompt(mConfig.mPromptInfo, mEffectiveUserId, getRequestId(), biometricModalities, mConfig.mOperationId, mConfig.mOpPackageName, - false /*onSwitchToCredential*/); + false /*onSwitchToCredential*/, isLandscape); final LayoutInflater layoutInflater = LayoutInflater.from(mContext); - if (constraintBp() && mPromptViewModel.getPromptKind().getValue().isBiometric()) { - mLayout = (ConstraintLayout) layoutInflater.inflate( - R.layout.biometric_prompt_constraint_layout, this, false /* attachToRoot */); + final PromptKind kind = mPromptViewModel.getPromptKind().getValue(); + if (constraintBp() && kind.isBiometric()) { + if (kind.isTwoPaneLandscapeBiometric()) { + mLayout = (ConstraintLayout) layoutInflater.inflate( + R.layout.biometric_prompt_two_pane_layout, this, false /* attachToRoot */); + } else { + mLayout = (ConstraintLayout) layoutInflater.inflate( + R.layout.biometric_prompt_one_pane_layout, this, false /* attachToRoot */); + } } else { mLayout = (FrameLayout) layoutInflater.inflate( R.layout.auth_container_view, this, false /* attachToRoot */); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/DisplayStateRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/DisplayStateRepository.kt index 8e5a97bd5d8d..9b14d6f68e35 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/DisplayStateRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/DisplayStateRepository.kt @@ -29,11 +29,10 @@ import com.android.systemui.display.data.repository.DeviceStateRepository import com.android.systemui.display.data.repository.DeviceStateRepository.DeviceState.REAR_DISPLAY import com.android.systemui.display.data.repository.DisplayRepository import javax.inject.Inject +import kotlin.math.min import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn @@ -58,7 +57,7 @@ interface DisplayStateRepository { val currentDisplaySize: StateFlow<Size> /** Provides whether the current display is large screen */ - val isLargeScreen: Flow<Boolean> + val isLargeScreen: StateFlow<Boolean> } @SysUISingleton @@ -127,16 +126,29 @@ constructor( ), ) - override val isLargeScreen: Flow<Boolean> = + override val isLargeScreen: StateFlow<Boolean> = currentDisplayInfo .map { - // TODO: This works, but investigate better way to handle this - it.logicalWidth * 160 / it.logicalDensityDpi > DisplayMetrics.DENSITY_XXXHIGH && - it.logicalHeight * 160 / it.logicalDensityDpi > DisplayMetrics.DENSITY_XXHIGH + // copied from systemui/shared/...Utilities.java + val smallestWidth = + dpiFromPx( + min(it.logicalWidth, it.logicalHeight).toFloat(), + context.resources.configuration.densityDpi + ) + smallestWidth >= LARGE_SCREEN_MIN_DPS } - .distinctUntilChanged() + .stateIn( + backgroundScope, + started = SharingStarted.WhileSubscribed(), + initialValue = false, + ) + private fun dpiFromPx(size: Float, densityDpi: Int): Float { + val densityRatio = densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT + return size / densityRatio + } companion object { const val TAG = "DisplayStateRepositoryImpl" + const val LARGE_SCREEN_MIN_DPS = 600f } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt index 591da4096956..40313e3158aa 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt @@ -65,7 +65,8 @@ interface DisplayStateInteractor { /** Called on configuration changes, used to keep the display state in sync */ fun onConfigurationChanged(newConfig: Configuration) - val isLargeScreen: Flow<Boolean> + /** Provides whether the current display is large screen */ + val isLargeScreen: StateFlow<Boolean> } /** Encapsulates logic for interacting with the display state. */ @@ -127,7 +128,7 @@ constructor( override val isDefaultDisplayOff = displayRepository.defaultDisplayOff - override val isLargeScreen: Flow<Boolean> = displayStateRepository.isLargeScreen + override val isLargeScreen: StateFlow<Boolean> = displayStateRepository.isLargeScreen companion object { private const val TAG = "DisplayStateInteractor" diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractor.kt index dc338d07f9e7..c08756f6ae36 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractor.kt @@ -91,6 +91,7 @@ interface PromptSelectorInteractor { challenge: Long, opPackageName: String, onSwitchToCredential: Boolean, + isLandscape: Boolean, ) /** Unset the current authentication request. */ @@ -102,6 +103,7 @@ class PromptSelectorInteractorImpl @Inject constructor( fingerprintPropertyRepository: FingerprintPropertyRepository, + private val displayStateInteractor: DisplayStateInteractor, private val promptRepository: PromptRepository, private val lockPatternUtils: LockPatternUtils, ) : PromptSelectorInteractor { @@ -166,7 +168,9 @@ constructor( modalities, promptRepository.challenge.value!!, promptRepository.opPackageName.value!!, - true /*onSwitchToCredential*/ + onSwitchToCredential = true, + // isLandscape value is not important when onSwitchToCredential is true + isLandscape = false, ) } @@ -178,6 +182,7 @@ constructor( challenge: Long, opPackageName: String, onSwitchToCredential: Boolean, + isLandscape: Boolean, ) { val hasCredentialViewShown = promptKind.value.isCredential() val showBpForCredential = @@ -189,11 +194,30 @@ constructor( !promptInfo.isContentViewMoreOptionsButtonUsed val showBpWithoutIconForCredential = showBpForCredential && !hasCredentialViewShown var kind: PromptKind = PromptKind.None + if (onSwitchToCredential) { kind = getCredentialType(lockPatternUtils, effectiveUserId) } else if (Utils.isBiometricAllowed(promptInfo) || showBpWithoutIconForCredential) { - // TODO(b/330908557): check to show one pane or two pane - kind = PromptKind.Biometric(modalities) + // TODO(b/330908557): Subscribe to + // displayStateInteractor.currentRotation.value.isDefaultOrientation() for checking + // `isLandscape` after removing AuthContinerView. + kind = + if (isLandscape) { + val paneType = + when { + displayStateInteractor.isLargeScreen.value -> + PromptKind.Biometric.PaneType.ONE_PANE_LARGE_SCREEN_LANDSCAPE + showBpWithoutIconForCredential -> + PromptKind.Biometric.PaneType.ONE_PANE_NO_SENSOR_LANDSCAPE + else -> PromptKind.Biometric.PaneType.TWO_PANE_LANDSCAPE + } + PromptKind.Biometric( + modalities, + paneType = paneType, + ) + } else { + PromptKind.Biometric(modalities) + } } else if (isDeviceCredentialAllowed(promptInfo)) { kind = getCredentialType(lockPatternUtils, effectiveUserId) } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt index 47174c006735..c836f89a8ff4 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt @@ -93,6 +93,7 @@ object BiometricViewSizeBinder { if (constraintBp()) { val leftGuideline = view.requireViewById<Guideline>(R.id.leftGuideline) + val topGuideline = view.requireViewById<Guideline>(R.id.topGuideline) val rightGuideline = view.requireViewById<Guideline>(R.id.rightGuideline) val midGuideline = view.findViewById<Guideline>(R.id.midGuideline) @@ -355,6 +356,18 @@ object BiometricViewSizeBinder { ) } + if (bounds.top >= 0) { + mediumConstraintSet.setGuidelineBegin(topGuideline.id, bounds.top) + smallConstraintSet.setGuidelineBegin(topGuideline.id, bounds.top) + } else if (bounds.top < 0) { + mediumConstraintSet.setGuidelineEnd( + topGuideline.id, + abs(bounds.top) + ) + smallConstraintSet.setGuidelineEnd(topGuideline.id, abs(bounds.top)) + } + + // Use rect bottom to set mid guideline of two-pane. if (midGuideline != null) { if (bounds.bottom >= 0) { midGuideline.setGuidelineEnd(bounds.bottom) diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt index 156ec6b975a5..c17b83dd4fbe 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt @@ -261,10 +261,13 @@ constructor( combine( _forceLargeSize, displayStateInteractor.isLargeScreen, - displayStateInteractor.currentRotation + displayStateInteractor.currentRotation, ) { forceLarge, isLargeScreen, rotation -> when { - forceLarge || isLargeScreen -> PromptPosition.Bottom + forceLarge || + isLargeScreen || + promptKind.value.isOnePaneNoSensorLandscapeBiometric() -> + PromptPosition.Bottom rotation == DisplayRotation.ROTATION_90 -> PromptPosition.Right rotation == DisplayRotation.ROTATION_270 -> PromptPosition.Left rotation == DisplayRotation.ROTATION_180 -> PromptPosition.Top @@ -297,23 +300,27 @@ constructor( /** Prompt panel size padding */ private val smallHorizontalGuidelinePadding = context.resources.getDimensionPixelSize( - R.dimen.biometric_prompt_small_horizontal_guideline_padding + R.dimen.biometric_prompt_land_small_horizontal_guideline_padding ) private val udfpsHorizontalGuidelinePadding = context.resources.getDimensionPixelSize( - R.dimen.biometric_prompt_udfps_horizontal_guideline_padding + R.dimen.biometric_prompt_two_pane_udfps_horizontal_guideline_padding ) private val udfpsMidGuidelinePadding = context.resources.getDimensionPixelSize( - R.dimen.biometric_prompt_udfps_mid_guideline_padding + R.dimen.biometric_prompt_two_pane_udfps_mid_guideline_padding + ) + private val mediumTopGuidelinePadding = + context.resources.getDimensionPixelSize( + R.dimen.biometric_prompt_one_pane_medium_top_guideline_padding ) private val mediumHorizontalGuidelinePadding = context.resources.getDimensionPixelSize( - R.dimen.biometric_prompt_medium_horizontal_guideline_padding + R.dimen.biometric_prompt_two_pane_medium_horizontal_guideline_padding ) private val mediumMidGuidelinePadding = context.resources.getDimensionPixelSize( - R.dimen.biometric_prompt_medium_mid_guideline_padding + R.dimen.biometric_prompt_two_pane_medium_mid_guideline_padding ) /** Rect for positioning biometric icon */ @@ -416,9 +423,9 @@ constructor( * asset to be loaded before determining the prompt size. */ val isIconViewLoaded: Flow<Boolean> = - combine(modalities, _isIconViewLoaded.asStateFlow()) { modalities, isIconViewLoaded -> - val noIcon = modalities.isEmpty - noIcon || isIconViewLoaded + combine(hideSensorIcon, _isIconViewLoaded.asStateFlow()) { hideSensorIcon, isIconViewLoaded + -> + hideSensorIcon || isIconViewLoaded } .distinctUntilChanged() @@ -448,17 +455,24 @@ constructor( * from opposite side of the screen */ val guidelineBounds: Flow<Rect> = - combine(iconPosition, size, position, modalities) { _, size, position, modalities -> + combine(iconPosition, promptKind, size, position, modalities) { + _, + promptKind, + size, + position, + modalities -> when (position) { - PromptPosition.Bottom -> Rect(0, 0, 0, 0) + PromptPosition.Bottom -> + if (promptKind.isOnePaneNoSensorLandscapeBiometric()) { + Rect(0, 0, 0, 0) + } else { + Rect(0, mediumTopGuidelinePadding, 0, 0) + } PromptPosition.Right -> if (size.isSmall) { Rect(-smallHorizontalGuidelinePadding, 0, 0, 0) } else if (modalities.hasUdfps) { Rect(udfpsHorizontalGuidelinePadding, 0, 0, udfpsMidGuidelinePadding) - } else if (modalities.isEmpty) { - // TODO: Temporary fix until no biometric landscape layout is added - Rect(-mediumHorizontalGuidelinePadding, 0, 0, 6) } else { Rect(-mediumHorizontalGuidelinePadding, 0, 0, mediumMidGuidelinePadding) } @@ -467,9 +481,6 @@ constructor( Rect(0, 0, -smallHorizontalGuidelinePadding, 0) } else if (modalities.hasUdfps) { Rect(0, 0, udfpsHorizontalGuidelinePadding, -udfpsMidGuidelinePadding) - } else if (modalities.isEmpty) { - // TODO: Temporary fix until no biometric landscape layout is added - Rect(0, 0, -mediumHorizontalGuidelinePadding, -6) } else { Rect( 0, diff --git a/packages/SystemUI/src/com/android/systemui/dock/DockManagerExtensions.kt b/packages/SystemUI/src/com/android/systemui/dock/DockManagerExtensions.kt index 4dbb32da62c2..1bbdfcd88548 100644 --- a/packages/SystemUI/src/com/android/systemui/dock/DockManagerExtensions.kt +++ b/packages/SystemUI/src/com/android/systemui/dock/DockManagerExtensions.kt @@ -19,16 +19,18 @@ package com.android.systemui.dock import com.android.systemui.common.coroutine.ConflatedCallbackFlow import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged /** - * Retrieves whether or not the device is docked according to DockManager. Emits a starting value - * of isDocked. + * Retrieves whether or not the device is docked according to DockManager. Emits a starting value of + * isDocked. */ fun DockManager.retrieveIsDocked(): Flow<Boolean> = ConflatedCallbackFlow.conflatedCallbackFlow { - val callback = DockManager.DockEventListener { trySend(isDocked) } - addListener(callback) - trySend(isDocked) + val callback = DockManager.DockEventListener { trySend(isDocked) } + addListener(callback) + trySend(isDocked) - awaitClose { removeListener(callback) } - }
\ No newline at end of file + awaitClose { removeListener(callback) } + } + .distinctUntilChanged() diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt index 9b07675f672c..756c6c20e58d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt @@ -57,7 +57,7 @@ constructor( @Background private val scope: CoroutineScope, @Background bgDispatcher: CoroutineDispatcher, @Main mainDispatcher: CoroutineDispatcher, - private val keyguardInteractor: KeyguardInteractor, + keyguardInteractor: KeyguardInteractor, private val communalInteractor: CommunalInteractor, powerInteractor: PowerInteractor, keyguardOcclusionInteractor: KeyguardOcclusionInteractor, @@ -70,6 +70,7 @@ constructor( bgDispatcher = bgDispatcher, powerInteractor = powerInteractor, keyguardOcclusionInteractor = keyguardOcclusionInteractor, + keyguardInteractor = keyguardInteractor, ) { override fun start() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt index 01109af79c1d..2a9ee9fb8779 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt @@ -48,7 +48,7 @@ constructor( @Background private val scope: CoroutineScope, @Background bgDispatcher: CoroutineDispatcher, @Main mainDispatcher: CoroutineDispatcher, - private val keyguardInteractor: KeyguardInteractor, + keyguardInteractor: KeyguardInteractor, powerInteractor: PowerInteractor, keyguardOcclusionInteractor: KeyguardOcclusionInteractor, val deviceEntryRepository: DeviceEntryRepository, @@ -60,6 +60,7 @@ constructor( bgDispatcher = bgDispatcher, powerInteractor = powerInteractor, keyguardOcclusionInteractor = keyguardOcclusionInteractor, + keyguardInteractor = keyguardInteractor, ) { override fun start() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt index 7d3de306d621..f5e98f1fedfe 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt @@ -47,7 +47,7 @@ constructor( @Background private val scope: CoroutineScope, @Background bgDispatcher: CoroutineDispatcher, @Main mainDispatcher: CoroutineDispatcher, - private val keyguardInteractor: KeyguardInteractor, + keyguardInteractor: KeyguardInteractor, powerInteractor: PowerInteractor, private val communalInteractor: CommunalInteractor, keyguardOcclusionInteractor: KeyguardOcclusionInteractor, @@ -60,6 +60,7 @@ constructor( bgDispatcher = bgDispatcher, powerInteractor = powerInteractor, keyguardOcclusionInteractor = keyguardOcclusionInteractor, + keyguardInteractor = keyguardInteractor, ) { override fun start() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingLockscreenHostedTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingLockscreenHostedTransitionInteractor.kt index 63294f7609a2..47aa02a0be52 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingLockscreenHostedTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingLockscreenHostedTransitionInteractor.kt @@ -45,7 +45,7 @@ constructor( @Background private val scope: CoroutineScope, @Background bgDispatcher: CoroutineDispatcher, @Main mainDispatcher: CoroutineDispatcher, - private val keyguardInteractor: KeyguardInteractor, + keyguardInteractor: KeyguardInteractor, powerInteractor: PowerInteractor, keyguardOcclusionInteractor: KeyguardOcclusionInteractor, ) : @@ -56,6 +56,7 @@ constructor( bgDispatcher = bgDispatcher, powerInteractor = powerInteractor, keyguardOcclusionInteractor = keyguardOcclusionInteractor, + keyguardInteractor = keyguardInteractor, ) { override fun start() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt index 7961b45830d4..25c3b0d395c0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt @@ -51,7 +51,7 @@ constructor( @Background private val scope: CoroutineScope, @Background bgDispatcher: CoroutineDispatcher, @Main mainDispatcher: CoroutineDispatcher, - private val keyguardInteractor: KeyguardInteractor, + keyguardInteractor: KeyguardInteractor, private val glanceableHubTransitions: GlanceableHubTransitions, powerInteractor: PowerInteractor, keyguardOcclusionInteractor: KeyguardOcclusionInteractor, @@ -63,6 +63,7 @@ constructor( bgDispatcher = bgDispatcher, powerInteractor = powerInteractor, keyguardOcclusionInteractor = keyguardOcclusionInteractor, + keyguardInteractor = keyguardInteractor, ) { override fun start() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt index ca6ab3ef52d8..e516fa3c44bb 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt @@ -48,7 +48,7 @@ constructor( @Main mainDispatcher: CoroutineDispatcher, @Background bgDispatcher: CoroutineDispatcher, private val glanceableHubTransitions: GlanceableHubTransitions, - private val keyguardInteractor: KeyguardInteractor, + keyguardInteractor: KeyguardInteractor, override val transitionRepository: KeyguardTransitionRepository, transitionInteractor: KeyguardTransitionInteractor, powerInteractor: PowerInteractor, @@ -61,6 +61,7 @@ constructor( bgDispatcher = bgDispatcher, powerInteractor = powerInteractor, keyguardOcclusionInteractor = keyguardOcclusionInteractor, + keyguardInteractor = keyguardInteractor, ) { override fun start() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt index 8ca29c80c2e9..a540d761c38f 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt @@ -49,7 +49,7 @@ constructor( @Background private val scope: CoroutineScope, @Background bgDispatcher: CoroutineDispatcher, @Main mainDispatcher: CoroutineDispatcher, - private val keyguardInteractor: KeyguardInteractor, + keyguardInteractor: KeyguardInteractor, powerInteractor: PowerInteractor, private val communalInteractor: CommunalInteractor, keyguardOcclusionInteractor: KeyguardOcclusionInteractor, @@ -64,6 +64,7 @@ constructor( bgDispatcher = bgDispatcher, powerInteractor = powerInteractor, keyguardOcclusionInteractor = keyguardOcclusionInteractor, + keyguardInteractor = keyguardInteractor, ) { override fun start() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt index f1e98f3bbe6d..8cab3cd35dcf 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt @@ -58,7 +58,7 @@ constructor( @Background private val scope: CoroutineScope, @Background bgDispatcher: CoroutineDispatcher, @Main mainDispatcher: CoroutineDispatcher, - private val keyguardInteractor: KeyguardInteractor, + keyguardInteractor: KeyguardInteractor, private val flags: FeatureFlags, private val shadeRepository: ShadeRepository, powerInteractor: PowerInteractor, @@ -73,6 +73,7 @@ constructor( bgDispatcher = bgDispatcher, powerInteractor = powerInteractor, keyguardOcclusionInteractor = keyguardOcclusionInteractor, + keyguardInteractor = keyguardInteractor, ) { override fun start() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt index 2603aab2781b..86d4cfb916ed 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt @@ -45,7 +45,7 @@ constructor( @Background private val scope: CoroutineScope, @Background bgDispatcher: CoroutineDispatcher, @Main mainDispatcher: CoroutineDispatcher, - private val keyguardInteractor: KeyguardInteractor, + keyguardInteractor: KeyguardInteractor, powerInteractor: PowerInteractor, private val communalInteractor: CommunalInteractor, keyguardOcclusionInteractor: KeyguardOcclusionInteractor, @@ -57,6 +57,7 @@ constructor( bgDispatcher = bgDispatcher, powerInteractor = powerInteractor, keyguardOcclusionInteractor = keyguardOcclusionInteractor, + keyguardInteractor = keyguardInteractor, ) { override fun start() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt index 76a822369b0c..19b2b81c4b27 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt @@ -52,7 +52,7 @@ constructor( @Background private val scope: CoroutineScope, @Background bgDispatcher: CoroutineDispatcher, @Main mainDispatcher: CoroutineDispatcher, - private val keyguardInteractor: KeyguardInteractor, + keyguardInteractor: KeyguardInteractor, private val communalInteractor: CommunalInteractor, private val flags: FeatureFlags, private val keyguardSecurityModel: KeyguardSecurityModel, @@ -67,6 +67,7 @@ constructor( bgDispatcher = bgDispatcher, powerInteractor = powerInteractor, keyguardOcclusionInteractor = keyguardOcclusionInteractor, + keyguardInteractor = keyguardInteractor, ) { override fun start() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt index ccce3bf1397c..8ffa4bb8e4fb 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt @@ -105,33 +105,35 @@ constructor( } return combine( - quickAffordanceAlwaysVisible(position), - keyguardInteractor.isDozing, - if (SceneContainerFlag.isEnabled) { - sceneInteractor - .get() - .transitionState - .map { - when (it) { - is ObservableTransitionState.Idle -> - it.currentScene == Scenes.Lockscreen - is ObservableTransitionState.Transition -> - it.fromScene == Scenes.Lockscreen || it.toScene == Scenes.Lockscreen + quickAffordanceAlwaysVisible(position), + keyguardInteractor.isDozing, + if (SceneContainerFlag.isEnabled) { + sceneInteractor + .get() + .transitionState + .map { + when (it) { + is ObservableTransitionState.Idle -> + it.currentScene == Scenes.Lockscreen + is ObservableTransitionState.Transition -> + it.fromScene == Scenes.Lockscreen || + it.toScene == Scenes.Lockscreen + } } - } - .distinctUntilChanged() - } else { - keyguardInteractor.isKeyguardShowing - }, - shadeInteractor.anyExpansion.map { it < 1.0f }.distinctUntilChanged(), - biometricSettingsRepository.isCurrentUserInLockdown, - ) { affordance, isDozing, isKeyguardShowing, isQuickSettingsVisible, isUserInLockdown -> - if (!isDozing && isKeyguardShowing && isQuickSettingsVisible && !isUserInLockdown) { - affordance - } else { - KeyguardQuickAffordanceModel.Hidden + .distinctUntilChanged() + } else { + keyguardInteractor.isKeyguardShowing + }, + shadeInteractor.anyExpansion.map { it < 1.0f }.distinctUntilChanged(), + biometricSettingsRepository.isCurrentUserInLockdown, + ) { affordance, isDozing, isKeyguardShowing, isQuickSettingsVisible, isUserInLockdown -> + if (!isDozing && isKeyguardShowing && isQuickSettingsVisible && !isUserInLockdown) { + affordance + } else { + KeyguardQuickAffordanceModel.Hidden + } } - } + .distinctUntilChanged() } /** diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt index 323ceef06a97..e14820714c9b 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt @@ -53,6 +53,7 @@ sealed class TransitionInteractor( val bgDispatcher: CoroutineDispatcher, val powerInteractor: PowerInteractor, val keyguardOcclusionInteractor: KeyguardOcclusionInteractor, + val keyguardInteractor: KeyguardInteractor, ) { val name = this::class.simpleName ?: "UnknownTransitionInteractor" abstract val transitionRepository: KeyguardTransitionRepository @@ -164,14 +165,10 @@ sealed class TransitionInteractor( @Deprecated("Will be merged into maybeStartTransitionToOccludedOrInsecureCamera") suspend fun maybeHandleInsecurePowerGesture(): Boolean { if (keyguardOcclusionInteractor.shouldTransitionFromPowerButtonGesture()) { - if (transitionInteractor.getCurrentState() == KeyguardState.GONE) { - // If the current state is GONE when the launch gesture is triggered, it means we - // were in transition from GONE -> DOZING/AOD due to the first power button tap. The - // second tap indicates that the user's intent was actually to launch the unlocked - // (insecure) camera, so we should transition back to GONE. + if (keyguardInteractor.isKeyguardDismissible.value) { startTransitionTo( KeyguardState.GONE, - ownerReason = "Power button gesture while GONE" + ownerReason = "Power button gesture while keyguard is dismissible" ) return true diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt index 23c2491813f7..807c322cc566 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt @@ -65,7 +65,7 @@ object KeyguardIndicationAreaBinder { val configurationBasedDimensions = MutableStateFlow(loadFromResources(view)) val disposableHandle = view.repeatWhenAttached { - repeatOnLifecycle(Lifecycle.State.STARTED) { + repeatOnLifecycle(Lifecycle.State.CREATED) { launch("$TAG#viewModel.alpha") { // Do not independently apply alpha, as [KeyguardRootViewModel] should work // for this and all its children diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt index b9a79dccf76b..1cf009d13e9b 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt @@ -30,6 +30,7 @@ import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle +import com.android.app.tracing.coroutines.launch import com.android.settingslib.Utils import com.android.systemui.animation.Expandable import com.android.systemui.animation.view.LaunchableImageView @@ -80,8 +81,8 @@ object KeyguardQuickAffordanceViewBinder { val configurationBasedDimensions = MutableStateFlow(loadFromResources(view)) val disposableHandle = view.repeatWhenAttached { - repeatOnLifecycle(Lifecycle.State.STARTED) { - launch { + repeatOnLifecycle(Lifecycle.State.CREATED) { + launch("$TAG#viewModel.collect") { viewModel.collect { buttonModel -> updateButton( view = button, @@ -93,7 +94,7 @@ object KeyguardQuickAffordanceViewBinder { } } - launch { + launch("$TAG#updateButtonAlpha") { updateButtonAlpha( view = button, viewModel = viewModel, @@ -101,7 +102,7 @@ object KeyguardQuickAffordanceViewBinder { ) } - launch { + launch("$TAG#configurationBasedDimensions") { configurationBasedDimensions.collect { dimensions -> button.updateLayoutParams<ViewGroup.LayoutParams> { width = dimensions.buttonSizePx.width @@ -323,4 +324,6 @@ object KeyguardQuickAffordanceViewBinder { private data class ConfigurationBasedDimensions( val buttonSizePx: Size, ) + + private const val TAG = "KeyguardQuickAffordanceViewBinder" } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt index c4383fc0857d..244d842b7073 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt @@ -18,6 +18,7 @@ package com.android.systemui.keyguard.ui.viewmodel import androidx.annotation.VisibleForTesting +import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor @@ -28,19 +29,23 @@ import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAfforda import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge +import kotlinx.coroutines.flow.stateIn @OptIn(ExperimentalCoroutinesApi::class) class KeyguardQuickAffordancesCombinedViewModel @Inject constructor( + @Application applicationScope: CoroutineScope, private val quickAffordanceInteractor: KeyguardQuickAffordanceInteractor, private val keyguardInteractor: KeyguardInteractor, shadeInteractor: ShadeInteractor, @@ -84,15 +89,20 @@ constructor( /** The only time the expansion is important is while lockscreen is actively displayed */ private val shadeExpansionAlpha = combine( - showingLockscreen, - shadeInteractor.anyExpansion, - ) { showingLockscreen, expansion -> - if (showingLockscreen) { - 1 - expansion - } else { - 0f + showingLockscreen, + shadeInteractor.anyExpansion, + ) { showingLockscreen, expansion -> + if (showingLockscreen) { + 1 - expansion + } else { + 0f + } } - } + .stateIn( + scope = applicationScope, + started = SharingStarted.Lazily, + initialValue = 0f, + ) /** * ID of the slot that's currently selected in the preview that renders exclusively in the diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java index 3cf61e211e42..8d3f7284e359 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java @@ -362,20 +362,34 @@ public class NotificationGroupingUtil { } protected boolean hasSameIcon(Object parentData, Object childData) { - Icon parentIcon = ((Notification) parentData).getSmallIcon(); - Icon childIcon = ((Notification) childData).getSmallIcon(); + Icon parentIcon = getIcon((Notification) parentData); + Icon childIcon = getIcon((Notification) childData); return parentIcon.sameAs(childIcon); } + private static Icon getIcon(Notification notification) { + if (notification.shouldUseAppIcon()) { + return notification.getAppIcon(); + } + return notification.getSmallIcon(); + } + /** * @return whether two ImageViews have the same colorFilterSet or none at all */ protected boolean hasSameColor(Object parentData, Object childData) { - int parentColor = ((Notification) parentData).color; - int childColor = ((Notification) childData).color; + int parentColor = getColor((Notification) parentData); + int childColor = getColor((Notification) childData); return parentColor == childColor; } + private static int getColor(Notification notification) { + if (notification.shouldUseAppIcon()) { + return 0; // the color filter isn't applied if using the app icon + } + return notification.color; + } + @Override public boolean isEmpty(View view) { return false; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconBuilder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconBuilder.kt index 319b49972bd2..16d0cc42db7f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconBuilder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconBuilder.kt @@ -18,25 +18,27 @@ package com.android.systemui.statusbar.notification.icon import android.app.Notification import android.content.Context +import android.graphics.drawable.Drawable import com.android.systemui.statusbar.StatusBarIconView import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.contentDescForNotification import javax.inject.Inject -/** - * Testable wrapper around Context. - */ -class IconBuilder @Inject constructor( - private val context: Context -) { +/** Testable wrapper around Context. */ +class IconBuilder @Inject constructor(private val context: Context) { fun createIconView(entry: NotificationEntry): StatusBarIconView { return StatusBarIconView( - context, - "${entry.sbn.packageName}/0x${Integer.toHexString(entry.sbn.id)}", - entry.sbn) + context, + "${entry.sbn.packageName}/0x${Integer.toHexString(entry.sbn.id)}", + entry.sbn + ) } fun getIconContentDescription(n: Notification): CharSequence { return contentDescForNotification(context, n) } + + fun getAppIcon(n: Notification): Drawable { + return n.loadHeaderAppIcon(context) + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt index 271b0a86ca12..19a08a330db1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt @@ -20,6 +20,8 @@ import android.app.Notification import android.app.Notification.MessagingStyle import android.app.Person import android.content.pm.LauncherApps +import android.graphics.drawable.AdaptiveIconDrawable +import android.graphics.drawable.Drawable import android.graphics.drawable.Icon import android.os.Build import android.os.Bundle @@ -165,7 +167,7 @@ constructor( Log.wtf( TAG, "Updating using the cache is not supported when the " + - "notifications_background_conversation_icons flag is off" + "notifications_background_icons flag is off" ) } if (!usingCache || !Flags.notificationsBackgroundIcons()) { @@ -216,39 +218,79 @@ constructor( @Throws(InflationException::class) private fun getIconDescriptor(entry: NotificationEntry, redact: Boolean): StatusBarIcon { - val n = entry.sbn.notification val showPeopleAvatar = !redact && isImportantConversation(entry) + // If the descriptor is already cached, return it + getCachedIconDescriptor(entry, showPeopleAvatar)?.also { + return it + } + + val smallIcon = entry.sbn.notification.smallIcon + var usingMonochromeAppIcon = false + val icon: Icon? + if (showPeopleAvatar) { + icon = createPeopleAvatar(entry) + } else if (android.app.Flags.notificationsUseMonochromeAppIcon()) { + icon = getMonochromeAppIcon(entry)?.also { usingMonochromeAppIcon = true } ?: smallIcon + } else { + icon = smallIcon + } + + if (icon == null) { + throw InflationException("No icon in notification from ${entry.sbn.packageName}") + } + + val sbi = icon.toStatusBarIcon(entry) + cacheIconDescriptor(entry, sbi, showPeopleAvatar, usingMonochromeAppIcon) + return sbi + } + + private fun getCachedIconDescriptor( + entry: NotificationEntry, + showPeopleAvatar: Boolean + ): StatusBarIcon? { val peopleAvatarDescriptor = entry.icons.peopleAvatarDescriptor + val appIconDescriptor = entry.icons.appIconDescriptor val smallIconDescriptor = entry.icons.smallIconDescriptor // If cached, return corresponding cached values - if (showPeopleAvatar && peopleAvatarDescriptor != null) { - return peopleAvatarDescriptor - } else if (!showPeopleAvatar && smallIconDescriptor != null) { - return smallIconDescriptor + return when { + showPeopleAvatar && peopleAvatarDescriptor != null -> peopleAvatarDescriptor + android.app.Flags.notificationsUseMonochromeAppIcon() && appIconDescriptor != null -> + appIconDescriptor + smallIconDescriptor != null -> smallIconDescriptor + else -> null } + } - val icon = - (if (showPeopleAvatar) { - createPeopleAvatar(entry) + private fun cacheIconDescriptor( + entry: NotificationEntry, + descriptor: StatusBarIcon, + showPeopleAvatar: Boolean, + usingMonochromeAppIcon: Boolean + ) { + if (android.app.Flags.notificationsUseAppIcon() || + android.app.Flags.notificationsUseMonochromeAppIcon() + ) { + // If either of the new icon flags is enabled, we cache the icon all the time. + if (showPeopleAvatar) { + entry.icons.peopleAvatarDescriptor = descriptor + } else if (usingMonochromeAppIcon) { + // When notificationsUseMonochromeAppIcon is enabled, we use the appIconDescriptor. + entry.icons.appIconDescriptor = descriptor } else { - n.smallIcon - }) - ?: throw InflationException("No icon in notification from " + entry.sbn.packageName) - - val sbi = icon.toStatusBarIcon(entry) - - // Cache if important conversation or app icon. - if (isImportantConversation(entry) || android.app.Flags.notificationsUseAppIcon()) { + // When notificationsUseAppIcon is enabled, the app icon overrides the small icon. + // But either way, it's a good idea to cache the descriptor. + entry.icons.smallIconDescriptor = descriptor + } + } else if (isImportantConversation(entry)) { + // Old approach: cache only if important conversation. if (showPeopleAvatar) { - entry.icons.peopleAvatarDescriptor = sbi + entry.icons.peopleAvatarDescriptor = descriptor } else { - entry.icons.smallIconDescriptor = sbi + entry.icons.smallIconDescriptor = descriptor } } - - return sbi } @Throws(InflationException::class) @@ -276,6 +318,29 @@ constructor( ) } + // TODO(b/335211019): Should we merge this with the method in GroupHelper? + private fun getMonochromeAppIcon(entry: NotificationEntry): Icon? { + // TODO(b/335211019): This should be done in the background. + var monochromeIcon: Icon? = null + try { + val appIcon: Drawable = iconBuilder.getAppIcon(entry.sbn.notification) + if (appIcon is AdaptiveIconDrawable) { + if (appIcon.monochrome != null) { + monochromeIcon = + Icon.createWithResourceAdaptiveDrawable( + /* resPackage = */ entry.sbn.packageName, + /* resId = */ appIcon.sourceDrawableResId, + /* useMonochrome = */ true, + /* inset = */ -3.0f * AdaptiveIconDrawable.getExtraInsetFraction() + ) + } + } + } catch (e: Exception) { + Log.e(TAG, "Failed to getAppIcon() in getMonochromeAppIcon()", e) + } + return monochromeIcon + } + private suspend fun getLauncherShortcutIconForPeopleAvatar(entry: NotificationEntry) = withContext(bgCoroutineContext) { var icon: Icon? = null diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconPack.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconPack.java index 442c0978fd77..d029ce722af9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconPack.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconPack.java @@ -33,6 +33,7 @@ public final class IconPack { @Nullable private final StatusBarIconView mAodIcon; @Nullable private StatusBarIcon mSmallIconDescriptor; + @Nullable private StatusBarIcon mAppIconDescriptor; @Nullable private StatusBarIcon mPeopleAvatarDescriptor; private boolean mIsImportantConversation; @@ -111,6 +112,15 @@ public final class IconPack { mPeopleAvatarDescriptor = peopleAvatarDescriptor; } + @Nullable + StatusBarIcon getAppIconDescriptor() { + return mAppIconDescriptor; + } + + void setAppIconDescriptor(@Nullable StatusBarIcon appIconDescriptor) { + mAppIconDescriptor = appIconDescriptor; + } + boolean isImportantConversation() { return mIsImportantConversation; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java index bd7f766c6860..d1fabb168d90 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java @@ -191,8 +191,12 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper imple updateTransformedTypes(); addRemainingTransformTypes(); updateCropToPaddingForImageViews(); - Notification notification = row.getEntry().getSbn().getNotification(); - mIcon.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon()); + Notification n = row.getEntry().getSbn().getNotification(); + if (n.shouldUseAppIcon()) { + mIcon.setTag(ImageTransformState.ICON_TAG, n.getAppIcon()); + } else { + mIcon.setTag(ImageTransformState.ICON_TAG, n.getSmallIcon()); + } // We need to reset all views that are no longer transforming in case a view was previously // transformed, but now we decided to transform its container instead. diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt index fd01b4864772..850162e65aa6 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt @@ -146,14 +146,18 @@ constructor( isEnabled = isEnabled, a11yStep = volumeRange.step, a11yClickDescription = - context.getString( - if (isMuted) { - R.string.volume_panel_hint_unmute - } else { - R.string.volume_panel_hint_mute - }, - label, - ), + if (isAffectedByMute) { + context.getString( + if (isMuted) { + R.string.volume_panel_hint_unmute + } else { + R.string.volume_panel_hint_mute + }, + label, + ) + } else { + null + }, a11yStateDescription = if (volume == volumeRange.first) { context.getString( diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt index 63426a43e552..9a99ed7bb512 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt @@ -128,6 +128,12 @@ open class AuthContainerViewTest : SysuiTestCase() { private lateinit var packageManager: PackageManager @Mock private lateinit var activityTaskManager: ActivityTaskManager + private lateinit var displayRepository: FakeDisplayRepository + private lateinit var displayStateInteractor: DisplayStateInteractor + private lateinit var udfpsOverlayInteractor: UdfpsOverlayInteractor + private lateinit var biometricStatusInteractor: BiometricStatusInteractor + private lateinit var iconProvider: IconProvider + private val testScope = TestScope(StandardTestDispatcher()) private val fakeExecutor = FakeExecutor(FakeSystemClock()) private val biometricPromptRepository = FakePromptRepository() @@ -143,17 +149,12 @@ open class AuthContainerViewTest : SysuiTestCase() { private val promptSelectorInteractor by lazy { PromptSelectorInteractorImpl( fingerprintRepository, + displayStateInteractor, biometricPromptRepository, lockPatternUtils, ) } - private lateinit var displayRepository: FakeDisplayRepository - private lateinit var displayStateInteractor: DisplayStateInteractor - private lateinit var udfpsOverlayInteractor: UdfpsOverlayInteractor - private lateinit var biometricStatusInteractor: BiometricStatusInteractor - private lateinit var iconProvider: IconProvider - private val credentialViewModel = CredentialViewModel(mContext, bpCredentialInteractor) private val defaultLogoIcon = context.getDrawable(R.drawable.ic_android) diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt index 3102a84b852a..6e78e334891b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt @@ -25,13 +25,16 @@ import android.hardware.biometrics.PromptVerticalListContentView import androidx.test.filters.SmallTest import com.android.internal.widget.LockPatternUtils import com.android.systemui.SysuiTestCase +import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository import com.android.systemui.biometrics.data.repository.FakePromptRepository import com.android.systemui.biometrics.faceSensorPropertiesInternal import com.android.systemui.biometrics.fingerprintSensorPropertiesInternal import com.android.systemui.biometrics.shared.model.BiometricModalities +import com.android.systemui.biometrics.shared.model.DisplayRotation import com.android.systemui.biometrics.shared.model.PromptKind import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.display.data.repository.FakeDisplayRepository import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.whenever @@ -75,12 +78,30 @@ class PromptSelectorInteractorImplTest : SysuiTestCase() { private val promptRepository = FakePromptRepository() private val fakeExecutor = FakeExecutor(FakeSystemClock()) + private lateinit var displayStateRepository: FakeDisplayStateRepository + private lateinit var displayRepository: FakeDisplayRepository + private lateinit var displayStateInteractor: DisplayStateInteractor private lateinit var interactor: PromptSelectorInteractor @Before fun setup() { + displayStateRepository = FakeDisplayStateRepository() + displayRepository = FakeDisplayRepository() + displayStateInteractor = + DisplayStateInteractorImpl( + testScope.backgroundScope, + mContext, + fakeExecutor, + displayStateRepository, + displayRepository, + ) interactor = - PromptSelectorInteractorImpl(fingerprintRepository, promptRepository, lockPatternUtils) + PromptSelectorInteractorImpl( + fingerprintRepository, + displayStateInteractor, + promptRepository, + lockPatternUtils + ) } private fun basicPromptInfo() = @@ -155,7 +176,8 @@ class PromptSelectorInteractorImplTest : SysuiTestCase() { modalities, CHALLENGE, OP_PACKAGE_NAME, - false /*onSwitchToCredential*/ + onSwitchToCredential = false, + isLandscape = false, ) assertThat(currentPrompt).isNotNull() @@ -200,22 +222,49 @@ class PromptSelectorInteractorImplTest : SysuiTestCase() { fun promptKind_isBiometric_whenBiometricAllowed() = testScope.runTest { setUserCredentialType(isPassword = true) - val info = basicPromptInfo() val promptKind by collectLastValue(interactor.promptKind) assertThat(promptKind).isEqualTo(PromptKind.None) - interactor.setPrompt( - info, - USER_ID, - REQUEST_ID, - modalities, - CHALLENGE, - OP_PACKAGE_NAME, - false /*onSwitchToCredential*/ - ) + setPrompt() + + assertThat(promptKind?.isOnePanePortraitBiometric()).isTrue() + + interactor.resetPrompt(REQUEST_ID) + verifyUnset() + } + + @Test + fun promptKind_isBiometricTwoPane_whenBiometricAllowed_landscape() = + testScope.runTest { + setUserCredentialType(isPassword = true) + displayStateRepository.setIsLargeScreen(false) + displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_90) + + val promptKind by collectLastValue(interactor.promptKind) + assertThat(promptKind).isEqualTo(PromptKind.None) + + setPrompt() + + assertThat(promptKind?.isTwoPaneLandscapeBiometric()).isTrue() + + interactor.resetPrompt(REQUEST_ID) + verifyUnset() + } + + @Test + fun promptKind_isBiometricOnePane_whenBiometricAllowed_largeScreenLandscape() = + testScope.runTest { + setUserCredentialType(isPassword = true) + displayStateRepository.setIsLargeScreen(true) + displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_90) + + val promptKind by collectLastValue(interactor.promptKind) + assertThat(promptKind).isEqualTo(PromptKind.None) - assertThat(promptKind?.isBiometric()).isTrue() + setPrompt() + + assertThat(promptKind?.isOnePaneLargeScreenLandscapeBiometric()).isTrue() interactor.resetPrompt(REQUEST_ID) verifyUnset() @@ -225,20 +274,11 @@ class PromptSelectorInteractorImplTest : SysuiTestCase() { fun promptKind_isCredential_onSwitchToCredential() = testScope.runTest { setUserCredentialType(isPassword = true) - val info = basicPromptInfo() val promptKind by collectLastValue(interactor.promptKind) assertThat(promptKind).isEqualTo(PromptKind.None) - interactor.setPrompt( - info, - USER_ID, - REQUEST_ID, - modalities, - CHALLENGE, - OP_PACKAGE_NAME, - true /*onSwitchToCredential*/ - ) + setPrompt(onSwitchToCredential = true) assertThat(promptKind).isEqualTo(PromptKind.Password) @@ -259,15 +299,7 @@ class PromptSelectorInteractorImplTest : SysuiTestCase() { val promptKind by collectLastValue(interactor.promptKind) assertThat(promptKind).isEqualTo(PromptKind.None) - interactor.setPrompt( - info, - USER_ID, - REQUEST_ID, - modalities, - CHALLENGE, - OP_PACKAGE_NAME, - false /*onSwitchToCredential*/ - ) + setPrompt(info) assertThat(promptKind).isEqualTo(PromptKind.Password) @@ -292,15 +324,7 @@ class PromptSelectorInteractorImplTest : SysuiTestCase() { val promptKind by collectLastValue(interactor.promptKind) assertThat(promptKind).isEqualTo(PromptKind.None) - interactor.setPrompt( - info, - USER_ID, - REQUEST_ID, - modalities, - CHALLENGE, - OP_PACKAGE_NAME, - false /*onSwitchToCredential*/ - ) + setPrompt(info) assertThat(promptKind).isEqualTo(PromptKind.Password) @@ -312,6 +336,7 @@ class PromptSelectorInteractorImplTest : SysuiTestCase() { fun promptKind_isBiometric_whenBiometricIsNotAllowed_withVerticalList() = testScope.runTest { setUserCredentialType(isPassword = true) + displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_90) val info = basicPromptInfo().apply { isDeviceCredentialAllowed = true @@ -322,22 +347,32 @@ class PromptSelectorInteractorImplTest : SysuiTestCase() { val promptKind by collectLastValue(interactor.promptKind) assertThat(promptKind).isEqualTo(PromptKind.None) - interactor.setPrompt( - info, - USER_ID, - REQUEST_ID, - modalities, - CHALLENGE, - OP_PACKAGE_NAME, - false /*onSwitchToCredential*/ - ) + setPrompt(info) - assertThat(promptKind?.isBiometric()).isTrue() + assertThat(promptKind?.isOnePaneNoSensorLandscapeBiometric()).isTrue() interactor.resetPrompt(REQUEST_ID) verifyUnset() } + private fun setPrompt( + info: PromptInfo = basicPromptInfo(), + onSwitchToCredential: Boolean = false + ) { + interactor.setPrompt( + info, + USER_ID, + REQUEST_ID, + modalities, + CHALLENGE, + OP_PACKAGE_NAME, + onSwitchToCredential = onSwitchToCredential, + isLandscape = + displayStateRepository.currentRotation.value == DisplayRotation.ROTATION_90 || + displayStateRepository.currentRotation.value == DisplayRotation.ROTATION_270, + ) + } + private fun TestScope.useCredentialAndReset(kind: PromptKind) { setUserCredentialType( isPin = kind == PromptKind.Pin, @@ -366,7 +401,8 @@ class PromptSelectorInteractorImplTest : SysuiTestCase() { BiometricModalities(), CHALLENGE, OP_PACKAGE_NAME, - false /*onSwitchToCredential*/ + onSwitchToCredential = false, + isLandscape = false, ) // not using biometrics, should be null with no fallback option diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt index c177511a2df4..1167fce7524b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt @@ -1407,7 +1407,12 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa runningTaskInfo.topActivity = topActivity whenever(activityTaskManager.getTasks(1)).thenReturn(listOf(runningTaskInfo)) selector = - PromptSelectorInteractorImpl(fingerprintRepository, promptRepository, lockPatternUtils) + PromptSelectorInteractorImpl( + fingerprintRepository, + displayStateInteractor, + promptRepository, + lockPatternUtils + ) selector.resetPrompt(REQUEST_ID) viewModel = @@ -1643,7 +1648,8 @@ private fun PromptSelectorInteractor.initializePrompt( BiometricModalities(fingerprintProperties = fingerprint, faceProperties = face), CHALLENGE, packageName, - false /*onUseDeviceCredential*/ + onSwitchToCredential = false, + isLandscape = false, ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt index 8a12a90efc4c..c1e3e84f2bf4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt @@ -49,6 +49,7 @@ import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.quickaffordance.ActivationState import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLogger +import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.plugins.ActivityStarter @@ -289,6 +290,7 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() { underTest = KeyguardQuickAffordancesCombinedViewModel( + applicationScope = kosmos.applicationCoroutineScope, quickAffordanceInteractor = KeyguardQuickAffordanceInteractor( keyguardInteractor = keyguardInteractor, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeDisplayStateRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeDisplayStateRepository.kt index 9765d531472c..53285eb715ba 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeDisplayStateRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeDisplayStateRepository.kt @@ -23,7 +23,6 @@ import com.android.systemui.dagger.SysUISingleton import dagger.Binds import dagger.Module import javax.inject.Inject -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow @@ -40,7 +39,7 @@ class FakeDisplayStateRepository @Inject constructor() : DisplayStateRepository override val currentDisplaySize: StateFlow<Size> = _currentDisplaySize.asStateFlow() private val _isLargeScreen = MutableStateFlow<Boolean>(false) - override val isLargeScreen: Flow<Boolean> = _isLargeScreen.asStateFlow() + override val isLargeScreen: StateFlow<Boolean> = _isLargeScreen.asStateFlow() override val isReverseDefaultRotation = false @@ -55,6 +54,10 @@ class FakeDisplayStateRepository @Inject constructor() : DisplayStateRepository fun setCurrentDisplaySize(size: Size) { _currentDisplaySize.value = size } + + fun setIsLargeScreen(isLargeScreen: Boolean) { + _isLargeScreen.value = isLargeScreen + } } @Module diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorKosmos.kt index 7f9a71cd149e..56297f0d7f43 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorKosmos.kt @@ -25,6 +25,7 @@ import com.android.systemui.kosmos.Kosmos.Fixture val Kosmos.promptSelectorInteractor by Fixture { PromptSelectorInteractorImpl( fingerprintPropertyRepository = fingerprintPropertyRepository, + displayStateInteractor = displayStateInteractor, promptRepository = promptRepository, lockPatternUtils = lockPatternUtils ) diff --git a/packages/services/VirtualCamera/OWNERS b/packages/services/VirtualCamera/OWNERS deleted file mode 100644 index c66443fb8a14..000000000000 --- a/packages/services/VirtualCamera/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -include /services/companion/java/com/android/server/companion/virtual/OWNERS -caen@google.com -jsebechlebsky@google.com
\ No newline at end of file diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java index 07daecdfc9f6..b1ea85cf3fd3 100644 --- a/services/core/java/com/android/server/audio/BtHelper.java +++ b/services/core/java/com/android/server/audio/BtHelper.java @@ -94,14 +94,14 @@ public class BtHelper { private final Map<BluetoothDevice, AudioDeviceAttributes> mResolvedScoAudioDevices = new HashMap<>(); - private @Nullable BluetoothHearingAid mHearingAid; + private @Nullable BluetoothHearingAid mHearingAid = null; - private @Nullable BluetoothLeAudio mLeAudio; + private @Nullable BluetoothLeAudio mLeAudio = null; private @Nullable BluetoothLeAudioCodecConfig mLeAudioCodecConfig; // Reference to BluetoothA2dp to query for AbsoluteVolume. - private @Nullable BluetoothA2dp mA2dp; + private @Nullable BluetoothA2dp mA2dp = null; private @Nullable BluetoothCodecConfig mA2dpCodecConfig; @@ -577,7 +577,11 @@ public class BtHelper { mHearingAid = null; break; case BluetoothProfile.LE_AUDIO: + if (mLeAudio != null && mLeAudioCallback != null) { + mLeAudio.unregisterCallback(mLeAudioCallback); + } mLeAudio = null; + mLeAudioCallback = null; mLeAudioCodecConfig = null; break; case BluetoothProfile.LE_AUDIO_BROADCAST: @@ -596,8 +600,6 @@ public class BtHelper { // BluetoothLeAudio callback used to update the list of addresses in the same group as a // connected LE Audio device - MyLeAudioCallback mLeAudioCallback = null; - class MyLeAudioCallback implements BluetoothLeAudio.Callback { @Override public void onCodecConfigChanged(int groupId, @@ -620,6 +622,8 @@ public class BtHelper { } } + MyLeAudioCallback mLeAudioCallback = null; + // @GuardedBy("mDeviceBroker.mSetModeLock") @GuardedBy("AudioDeviceBroker.this.mDeviceStateLock") /*package*/ synchronized void onBtProfileConnected(int profile, BluetoothProfile proxy) { @@ -635,18 +639,28 @@ public class BtHelper { onHeadsetProfileConnected((BluetoothHeadset) proxy); return; case BluetoothProfile.A2DP: + if (((BluetoothA2dp) proxy).equals(mA2dp)) { + return; + } mA2dp = (BluetoothA2dp) proxy; break; case BluetoothProfile.HEARING_AID: + if (((BluetoothHearingAid) proxy).equals(mHearingAid)) { + return; + } mHearingAid = (BluetoothHearingAid) proxy; break; case BluetoothProfile.LE_AUDIO: - if (mLeAudio == null) { - mLeAudioCallback = new MyLeAudioCallback(); - ((BluetoothLeAudio) proxy).registerCallback( - mContext.getMainExecutor(), mLeAudioCallback); + if (((BluetoothLeAudio) proxy).equals(mLeAudio)) { + return; + } + if (mLeAudio != null && mLeAudioCallback != null) { + mLeAudio.unregisterCallback(mLeAudioCallback); } mLeAudio = (BluetoothLeAudio) proxy; + mLeAudioCallback = new MyLeAudioCallback(); + mLeAudio.registerCallback( + mContext.getMainExecutor(), mLeAudioCallback); break; case BluetoothProfile.A2DP_SINK: case BluetoothProfile.LE_AUDIO_BROADCAST: diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index 182b05a68028..44846f310348 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -168,6 +168,12 @@ final class LocalDisplayAdapter extends DisplayAdapter { } SurfaceControl.DesiredDisplayModeSpecs modeSpecs = mSurfaceControlProxy.getDesiredDisplayModeSpecs(displayToken); + if (modeSpecs == null) { + // If mode specs is null, it most probably means that display got + // unplugged very rapidly. + Slog.w(TAG, "Desired display mode specs from SurfaceFlinger are null"); + return; + } LocalDisplayDevice device = mDevices.get(physicalDisplayId); if (device == null) { // Display was added. diff --git a/services/core/java/com/android/server/locales/LocaleManagerBackupHelper.java b/services/core/java/com/android/server/locales/LocaleManagerBackupHelper.java index 563f93e96331..b9e09605477a 100644 --- a/services/core/java/com/android/server/locales/LocaleManagerBackupHelper.java +++ b/services/core/java/com/android/server/locales/LocaleManagerBackupHelper.java @@ -84,9 +84,16 @@ class LocaleManagerBackupHelper { * from the delegate selector. */ private static final String LOCALES_FROM_DELEGATE_PREFS = "LocalesFromDelegatePrefs.xml"; + private static final String LOCALES_STAGED_DATA_PREFS = "LocalesStagedDataPrefs.xml"; + private static final String ARCHIVED_PACKAGES_PREFS = "ArchivedPackagesPrefs.xml"; // Stage data would be deleted on reboot since it's stored in memory. So it's retained until // retention period OR next reboot, whichever happens earlier. private static final Duration STAGE_DATA_RETENTION_PERIOD = Duration.ofDays(3); + // Store the locales staged data for the specified package in the SharedPreferences. The format + // is locales s:setFromDelegate + // For example: en-US s:true + private static final String STRING_SPLIT = " s:"; + private static final String KEY_STAGED_DATA_TIME = "staged_data_time"; private final LocaleManagerService mLocaleManagerService; private final PackageManager mPackageManager; @@ -94,39 +101,34 @@ class LocaleManagerBackupHelper { private final Context mContext; private final Object mStagedDataLock = new Object(); - // Staged data map keyed by user-id to handle multi-user scenario / work profiles. We are using - // SparseArray because it is more memory-efficient than a HashMap. - private final SparseArray<StagedData> mStagedData; - // SharedPreferences to store packages whose app-locale was set by a delegate, as opposed to // the application setting the app-locale itself. private final SharedPreferences mDelegateAppLocalePackages; + // For unit tests + private final SparseArray<File> mStagedDataFiles; + private final File mArchivedPackagesFile; + private final BroadcastReceiver mUserMonitor; - // To determine whether an app is pre-archived, check for Intent.EXTRA_ARCHIVAL upon receiving - // the initial PACKAGE_ADDED broadcast. If it is indeed pre-archived, perform the data - // restoration during the second PACKAGE_ADDED broadcast, which is sent subsequently when the - // app is installed. - private final Set<String> mPkgsToRestore; LocaleManagerBackupHelper(LocaleManagerService localeManagerService, PackageManager packageManager, HandlerThread broadcastHandlerThread) { this(localeManagerService.mContext, localeManagerService, packageManager, Clock.systemUTC(), - new SparseArray<>(), broadcastHandlerThread, null); + broadcastHandlerThread, null, null, null); } - @VisibleForTesting LocaleManagerBackupHelper(Context context, - LocaleManagerService localeManagerService, - PackageManager packageManager, Clock clock, SparseArray<StagedData> stagedData, - HandlerThread broadcastHandlerThread, SharedPreferences delegateAppLocalePackages) { + @VisibleForTesting + LocaleManagerBackupHelper(Context context, LocaleManagerService localeManagerService, + PackageManager packageManager, Clock clock, HandlerThread broadcastHandlerThread, + SparseArray<File> stagedDataFiles, File archivedPackagesFile, + SharedPreferences delegateAppLocalePackages) { mContext = context; mLocaleManagerService = localeManagerService; mPackageManager = packageManager; mClock = clock; - mStagedData = stagedData; mDelegateAppLocalePackages = delegateAppLocalePackages != null ? delegateAppLocalePackages - : createPersistedInfo(); - mPkgsToRestore = new ArraySet<>(); - + : createPersistedInfo(); + mArchivedPackagesFile = archivedPackagesFile; + mStagedDataFiles = stagedDataFiles; mUserMonitor = new UserMonitor(); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_USER_REMOVED); @@ -148,7 +150,7 @@ class LocaleManagerBackupHelper { } synchronized (mStagedDataLock) { - cleanStagedDataForOldEntriesLocked(); + cleanStagedDataForOldEntriesLocked(userId); } HashMap<String, LocalesInfo> pkgStates = new HashMap<>(); @@ -207,14 +209,11 @@ class LocaleManagerBackupHelper { return out.toByteArray(); } - private void cleanStagedDataForOldEntriesLocked() { - for (int i = 0; i < mStagedData.size(); i++) { - int userId = mStagedData.keyAt(i); - StagedData stagedData = mStagedData.get(userId); - if (stagedData.mCreationTimeMillis - < mClock.millis() - STAGE_DATA_RETENTION_PERIOD.toMillis()) { - deleteStagedDataLocked(userId); - } + private void cleanStagedDataForOldEntriesLocked(@UserIdInt int userId) { + Long created_time = getStagedDataSp(userId).getLong(KEY_STAGED_DATA_TIME, -1); + if (created_time != -1 + && created_time < mClock.millis() - STAGE_DATA_RETENTION_PERIOD.toMillis()) { + deleteStagedDataLocked(userId); } } @@ -252,20 +251,16 @@ class LocaleManagerBackupHelper { // performed simultaneously. synchronized (mStagedDataLock) { // Backups for apps which are yet to be installed. - StagedData stagedData = new StagedData(mClock.millis(), new HashMap<>()); - for (String pkgName : pkgStates.keySet()) { LocalesInfo localesInfo = pkgStates.get(pkgName); // Check if the application is already installed for the concerned user. if (isPackageInstalledForUser(pkgName, userId)) { - if (mPkgsToRestore != null) { - mPkgsToRestore.remove(pkgName); - } + removeFromArchivedPackagesInfo(userId, pkgName); // Don't apply the restore if the locales have already been set for the app. checkExistingLocalesAndApplyRestore(pkgName, localesInfo, userId); } else { // Stage the data if the app isn't installed. - stagedData.mPackageStates.put(pkgName, localesInfo); + storeStagedDataInfo(userId, pkgName, localesInfo); if (DEBUG) { Slog.d(TAG, "Add locales=" + localesInfo.mLocales + " fromDelegate=" + localesInfo.mSetFromDelegate @@ -274,8 +269,9 @@ class LocaleManagerBackupHelper { } } - if (!stagedData.mPackageStates.isEmpty()) { - mStagedData.put(userId, stagedData); + // Create the time if the data is being staged. + if (!getStagedDataSp(userId).getAll().isEmpty()) { + storeStagedDataCreatedTime(userId); } } } @@ -293,14 +289,23 @@ class LocaleManagerBackupHelper { * added on device. */ void onPackageAddedWithExtras(String packageName, int uid, Bundle extras) { - boolean archived = false; + int userId = UserHandle.getUserId(uid); if (extras != null) { - archived = extras.getBoolean(Intent.EXTRA_ARCHIVAL, false); - if (archived && mPkgsToRestore != null) { - mPkgsToRestore.add(packageName); + // To determine whether an app is pre-archived, check for Intent.EXTRA_ARCHIVAL upon + // receiving the initial PACKAGE_ADDED broadcast. If it is indeed pre-archived, perform + // the data restoration during the second PACKAGE_ADDED broadcast, which is sent + // subsequently when the app is installed. + boolean archived = extras.getBoolean(Intent.EXTRA_ARCHIVAL, false); + if (DEBUG) { + Slog.d(TAG, + "onPackageAddedWithExtras packageName: " + packageName + ", userId: " + + userId + ", archived: " + archived); + } + if (archived) { + addInArchivedPackagesInfo(userId, packageName); } } - checkStageDataAndApplyRestore(packageName, uid); + checkStageDataAndApplyRestore(packageName, userId); } /** @@ -310,9 +315,32 @@ class LocaleManagerBackupHelper { */ void onPackageUpdateFinished(String packageName, int uid) { int userId = UserHandle.getUserId(uid); - if (mPkgsToRestore != null && mPkgsToRestore.contains(packageName)) { - mPkgsToRestore.remove(packageName); - checkStageDataAndApplyRestore(packageName, uid); + if (DEBUG) { + Slog.d(TAG, + "onPackageUpdateFinished userId: " + userId + ", packageName: " + packageName); + } + String user = Integer.toString(userId); + File file = getArchivedPackagesFile(); + if (file.exists()) { + SharedPreferences sp = getArchivedPackagesSp(file); + Set<String> packageNames = new ArraySet<>(sp.getStringSet(user, new ArraySet<>())); + if (packageNames.remove(packageName)) { + SharedPreferences.Editor editor = sp.edit(); + if (packageNames.isEmpty()) { + if (!editor.remove(user).commit()) { + Slog.e(TAG, "Failed to remove the user"); + } + if (sp.getAll().isEmpty()) { + file.delete(); + } + } else { + // commit and log the result. + if (!editor.putStringSet(user, packageNames).commit()) { + Slog.e(TAG, "failed to remove the package"); + } + } + checkStageDataAndApplyRestore(packageName, userId); + } } cleanApplicationLocalesIfNeeded(packageName, userId); } @@ -347,16 +375,16 @@ class LocaleManagerBackupHelper { } } - private void checkStageDataAndApplyRestore(String packageName, int uid) { + private void checkStageDataAndApplyRestore(String packageName, int userId) { try { synchronized (mStagedDataLock) { - cleanStagedDataForOldEntriesLocked(); - - int userId = UserHandle.getUserId(uid); - if (mStagedData.contains(userId)) { - if (mPkgsToRestore != null) { - mPkgsToRestore.remove(packageName); + cleanStagedDataForOldEntriesLocked(userId); + if (!getStagedDataSp(userId).getString(packageName, "").isEmpty()) { + if (DEBUG) { + Slog.d(TAG, + "checkStageDataAndApplyRestore, remove package and restore data"); } + removeFromArchivedPackagesInfo(userId, packageName); // Perform lazy restore only if the staged data exists. doLazyRestoreLocked(packageName, userId); } @@ -417,8 +445,17 @@ class LocaleManagerBackupHelper { } } - private void deleteStagedDataLocked(@UserIdInt int userId) { - mStagedData.remove(userId); + void deleteStagedDataLocked(@UserIdInt int userId) { + File stagedFile = getStagedDataFile(userId); + SharedPreferences sp = getStagedDataSp(stagedFile); + // commit and log the result. + if (!sp.edit().clear().commit()) { + Slog.e(TAG, "Failed to commit data!"); + } + + if (stagedFile.exists()) { + stagedFile.delete(); + } } /** @@ -473,16 +510,6 @@ class LocaleManagerBackupHelper { out.endDocument(); } - static class StagedData { - final long mCreationTimeMillis; - final HashMap<String, LocalesInfo> mPackageStates; - - StagedData(long creationTimeMillis, HashMap<String, LocalesInfo> pkgStates) { - mCreationTimeMillis = creationTimeMillis; - mPackageStates = pkgStates; - } - } - static class LocalesInfo { final String mLocales; final boolean mSetFromDelegate; @@ -508,6 +535,7 @@ class LocaleManagerBackupHelper { synchronized (mStagedDataLock) { deleteStagedDataLocked(userId); removeProfileFromPersistedInfo(userId); + removeArchivedPackagesForUser(userId); } } } catch (Exception e) { @@ -533,29 +561,162 @@ class LocaleManagerBackupHelper { return; } - StagedData stagedData = mStagedData.get(userId); - for (String pkgName : stagedData.mPackageStates.keySet()) { - LocalesInfo localesInfo = stagedData.mPackageStates.get(pkgName); + SharedPreferences sp = getStagedDataSp(userId); + String value = sp.getString(packageName, ""); + if (!value.isEmpty()) { + String[] info = value.split(STRING_SPLIT); + if (info == null || info.length != 2) { + Slog.e(TAG, "Failed to restore data"); + return; + } + LocalesInfo localesInfo = new LocalesInfo(info[0], Boolean.parseBoolean(info[1])); + checkExistingLocalesAndApplyRestore(packageName, localesInfo, userId); - if (pkgName.equals(packageName)) { + // Remove the restored entry from the staged data list. + if (!sp.edit().remove(packageName).commit()) { + Slog.e(TAG, "Failed to commit data!"); + } + } - checkExistingLocalesAndApplyRestore(pkgName, localesInfo, userId); + // Remove the stage data entry for user if there are no more packages to restore. + if (sp.getAll().size() == 1 && sp.getLong(KEY_STAGED_DATA_TIME, -1) != -1) { + deleteStagedDataLocked(userId); + } + } - // Remove the restored entry from the staged data list. - stagedData.mPackageStates.remove(pkgName); + private File getStagedDataFile(@UserIdInt int userId) { + return mStagedDataFiles == null ? new File(Environment.getDataSystemDeDirectory(userId), + LOCALES_STAGED_DATA_PREFS) : mStagedDataFiles.get(userId); + } - // Remove the stage data entry for user if there are no more packages to restore. - if (stagedData.mPackageStates.isEmpty()) { - mStagedData.remove(userId); - } + private SharedPreferences getStagedDataSp(File file) { + return mStagedDataFiles == null ? mContext.createDeviceProtectedStorageContext() + .getSharedPreferences(file, Context.MODE_PRIVATE) + : mContext.getSharedPreferences(file, Context.MODE_PRIVATE); + } + + private SharedPreferences getStagedDataSp(@UserIdInt int userId) { + return mStagedDataFiles == null ? mContext.createDeviceProtectedStorageContext() + .getSharedPreferences(getStagedDataFile(userId), Context.MODE_PRIVATE) + : mContext.getSharedPreferences(mStagedDataFiles.get(userId), Context.MODE_PRIVATE); + } - // No need to loop further after restoring locales because the staged data will - // contain at most one entry for the newly added package. - break; + /** + * Store the staged locales info. + */ + private void storeStagedDataInfo(@UserIdInt int userId, @NonNull String packageName, + @NonNull LocalesInfo localesInfo) { + if (DEBUG) { + Slog.d(TAG, "storeStagedDataInfo, userId: " + userId + ", packageName: " + packageName + + ", localesInfo.mLocales: " + localesInfo.mLocales + + ", localesInfo.mSetFromDelegate: " + localesInfo.mSetFromDelegate); + } + String info = + localesInfo.mLocales + STRING_SPLIT + String.valueOf(localesInfo.mSetFromDelegate); + SharedPreferences sp = getStagedDataSp(userId); + // commit and log the result. + if (!sp.edit().putString(packageName, info).commit()) { + Slog.e(TAG, "Failed to commit data!"); + } + } + + /** + * Store the time of creation for staged locales info. + */ + private void storeStagedDataCreatedTime(@UserIdInt int userId) { + SharedPreferences sp = getStagedDataSp(userId); + // commit and log the result. + if (!sp.edit().putLong(KEY_STAGED_DATA_TIME, mClock.millis()).commit()) { + Slog.e(TAG, "Failed to commit data!"); + } + } + + private File getArchivedPackagesFile() { + return mArchivedPackagesFile == null ? new File( + Environment.getDataSystemDeDirectory(UserHandle.USER_SYSTEM), + ARCHIVED_PACKAGES_PREFS) : mArchivedPackagesFile; + } + + private SharedPreferences getArchivedPackagesSp(File file) { + return mArchivedPackagesFile == null ? mContext.createDeviceProtectedStorageContext() + .getSharedPreferences(file, Context.MODE_PRIVATE) + : mContext.getSharedPreferences(file, Context.MODE_PRIVATE); + } + + /** + * Add the package into the archived packages list. + */ + private void addInArchivedPackagesInfo(@UserIdInt int userId, @NonNull String packageName) { + String user = Integer.toString(userId); + SharedPreferences sp = getArchivedPackagesSp(getArchivedPackagesFile()); + Set<String> packageNames = new ArraySet<>(sp.getStringSet(user, new ArraySet<>())); + if (DEBUG) { + Slog.d(TAG, "addInArchivedPackagesInfo before packageNames: " + packageNames + + ", packageName: " + packageName); + } + if (packageNames.add(packageName)) { + // commit and log the result. + if (!sp.edit().putStringSet(user, packageNames).commit()) { + Slog.e(TAG, "failed to add the package"); + } + } + } + + /** + * Remove the package from the archived packages list. + */ + private void removeFromArchivedPackagesInfo(@UserIdInt int userId, + @NonNull String packageName) { + File file = getArchivedPackagesFile(); + if (file.exists()) { + String user = Integer.toString(userId); + SharedPreferences sp = getArchivedPackagesSp(getArchivedPackagesFile()); + Set<String> packageNames = new ArraySet<>(sp.getStringSet(user, new ArraySet<>())); + if (DEBUG) { + Slog.d(TAG, "removeFromArchivedPackagesInfo before packageNames: " + packageNames + + ", packageName: " + packageName); + } + if (packageNames.remove(packageName)) { + SharedPreferences.Editor editor = sp.edit(); + if (packageNames.isEmpty()) { + if (!editor.remove(user).commit()) { + Slog.e(TAG, "Failed to remove user"); + } + if (sp.getAll().isEmpty()) { + file.delete(); + } + } else { + // commit and log the result. + if (!editor.putStringSet(user, packageNames).commit()) { + Slog.e(TAG, "failed to remove the package"); + } + } } } } + /** + * Remove the user from the archived packages list. + */ + private void removeArchivedPackagesForUser(@UserIdInt int userId) { + String user = Integer.toString(userId); + File file = getArchivedPackagesFile(); + SharedPreferences sp = getArchivedPackagesSp(file); + + if (sp == null || !sp.contains(user)) { + Slog.w(TAG, "The profile is not existed in the archived package info"); + return; + } + + if (!sp.edit().remove(user).commit()) { + Slog.e(TAG, "Failed to remove user"); + } + + if (sp.getAll().isEmpty() && file.exists()) { + file.delete(); + } + } + SharedPreferences createPersistedInfo() { final File prefsFile = new File( Environment.getDataSystemDeDirectory(UserHandle.USER_SYSTEM), diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 434e92f7978a..86115990f746 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -3964,7 +3964,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } if (isCurrentVisible) { - if (isNextNotYetVisible || delayRemoval) { + if (isNextNotYetVisible || delayRemoval || isInTransition()) { // Add this activity to the list of stopping activities. It will be processed and // destroyed when the next activity reports idle. addToStopping(false /* scheduleIdle */, false /* idleDelayed */, @@ -8551,7 +8551,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // If activity in fullscreen mode is letterboxed because of fixed orientation then bounds // are already calculated in resolveFixedOrientationConfiguration. // Don't apply aspect ratio if app is overridden to fullscreen by device user/manufacturer. - if (!isLetterboxedForFixedOrientationAndAspectRatio() + if (Flags.immersiveAppRepositioning() && !isLetterboxedForFixedOrientationAndAspectRatio() && !mLetterboxUiController.hasFullscreenOverride()) { resolveAspectRatioRestriction(newParentConfiguration); } @@ -8568,6 +8568,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A computeConfigByResolveHint(resolvedConfig, newParentConfiguration); } } + // If activity in fullscreen mode is letterboxed because of fixed orientation then bounds + // are already calculated in resolveFixedOrientationConfiguration, or if in size compat + // mode, it should already be calculated in resolveSizeCompatModeConfiguration. + // Don't apply aspect ratio if app is overridden to fullscreen by device user/manufacturer. + if (!Flags.immersiveAppRepositioning() && !isLetterboxedForFixedOrientationAndAspectRatio() + && !mInSizeCompatModeForBounds && !mLetterboxUiController.hasFullscreenOverride()) { + resolveAspectRatioRestriction(newParentConfiguration); + } if (isFixedOrientationLetterboxAllowed || compatDisplayInsets != null // In fullscreen, can be letterboxed for aspect ratio. @@ -8903,7 +8911,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } boolean isImmersiveMode(@NonNull Rect parentBounds) { - if (!mResolveConfigHint.mUseOverrideInsetsForConfig) { + if (!Flags.immersiveAppRepositioning()) { + return false; + } + if (!mResolveConfigHint.mUseOverrideInsetsForConfig + && mWmService.mFlags.mInsetsDecoupledConfiguration) { return false; } final Insets navBarInsets = mDisplayContent.getInsetsStateController() @@ -9252,10 +9264,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // orientation bounds (stored in resolved bounds) instead of parent bounds since the // activity will be displayed within them even if it is in size compat mode. They should be // saved here before resolved bounds are overridden below. - final Rect containerBounds = isAspectRatioApplied() + final boolean useResolvedBounds = Flags.immersiveAppRepositioning() + ? isAspectRatioApplied() : isLetterboxedForFixedOrientationAndAspectRatio(); + final Rect containerBounds = useResolvedBounds ? new Rect(resolvedBounds) : newParentConfiguration.windowConfiguration.getBounds(); - final Rect containerAppBounds = isAspectRatioApplied() + final Rect containerAppBounds = useResolvedBounds ? new Rect(resolvedConfig.windowConfiguration.getAppBounds()) : newParentConfiguration.windowConfiguration.getAppBounds(); diff --git a/services/core/jni/BroadcastRadio/convert.cpp b/services/core/jni/BroadcastRadio/convert.cpp index ddbc5354358c..e42f7f8be0ca 100644 --- a/services/core/jni/BroadcastRadio/convert.cpp +++ b/services/core/jni/BroadcastRadio/convert.cpp @@ -433,7 +433,7 @@ static JavaRef<jobject> BandDescriptorFromHal(JNIEnv *env, const V1_0::BandConfi gjni.AmBandDescriptor.clazz, gjni.AmBandDescriptor.cstor, region, config.type, config.lowerLimit, config.upperLimit, spacing, am.stereo)); } else { - ALOGE("Unsupported band type: %d", config.type); + ALOGE("Unsupported band type: %d", static_cast<int>(config.type)); return nullptr; } } @@ -451,7 +451,7 @@ JavaRef<jobject> BandConfigFromHal(JNIEnv *env, const V1_0::BandConfig &config, return make_javaref(env, env->NewObject( gjni.AmBandConfig.clazz, gjni.AmBandConfig.cstor, descriptor.get())); } else { - ALOGE("Unsupported band type: %d", config.type); + ALOGE("Unsupported band type: %d", static_cast<int>(config.type)); return nullptr; } } @@ -539,9 +539,9 @@ JavaRef<jobject> MetadataFromHal(JNIEnv *env, const hidl_vec<V1_0::MetaData> &me item.clockValue.timezoneOffsetInMinutes); break; default: - ALOGW("invalid metadata type %d", item.type); + ALOGW("invalid metadata type %d", static_cast<int>(item.type)); } - ALOGE_IF(status != 0, "Failed inserting metadata %d (of type %d)", key, item.type); + ALOGE_IF(status != 0, "Failed inserting metadata %d (of type %d)", key, static_cast<int>(item.type)); } return jMetadata; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java index e763c9eccceb..669a999c921e 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java @@ -1588,7 +1588,7 @@ final class DevicePolicyEngine { private Set<EnforcingAdmin> getEnforcingAdminsOnUser(int userId) { synchronized (mLock) { return mEnforcingAdmins.contains(userId) - ? mEnforcingAdmins.get(userId) : Collections.emptySet(); + ? new HashSet<>(mEnforcingAdmins.get(userId)) : Collections.emptySet(); } } diff --git a/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java index 12050e1beaed..01ff35fc088c 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java @@ -1142,6 +1142,20 @@ public class LocalDisplayAdapterTest { } @Test + public void test_createLocalExternalDisplay_displayManagementEnabled_doesNotCrash() + throws Exception { + FakeDisplay display = new FakeDisplay(PORT_A); + display.info.isInternal = false; + setUpDisplay(display); + updateAvailableDisplays(); + mAdapter.registerLocked(); + when(mSurfaceControlProxy.getDesiredDisplayModeSpecs(display.token)).thenReturn(null); + mInjector.getTransmitter().sendHotplug(display, /* connected */ true); + waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); + assertThat(mListener.addedDisplays.size()).isEqualTo(1); + } + + @Test public void test_createLocalExternalDisplay_displayManagementEnabled_shouldHaveDefaultGroup() throws Exception { FakeDisplay display = new FakeDisplay(PORT_A); diff --git a/services/tests/servicestests/src/com/android/server/locales/LocaleManagerBackupRestoreTest.java b/services/tests/servicestests/src/com/android/server/locales/LocaleManagerBackupRestoreTest.java index 7dd1847114c8..50cfa753ebdb 100644 --- a/services/tests/servicestests/src/com/android/server/locales/LocaleManagerBackupRestoreTest.java +++ b/services/tests/servicestests/src/com/android/server/locales/LocaleManagerBackupRestoreTest.java @@ -20,7 +20,6 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; -import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; @@ -52,6 +51,7 @@ import android.util.ArraySet; import android.util.SparseArray; import android.util.Xml; +import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.internal.content.PackageMonitor; @@ -70,6 +70,7 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; @@ -95,21 +96,21 @@ public class LocaleManagerBackupRestoreTest { private static final int DEFAULT_USER_ID = 0; private static final int WORK_PROFILE_USER_ID = 10; private static final int DEFAULT_UID = Binder.getCallingUid() + 100; + private static final int WORK_PROFILE_UID = Binder.getCallingUid() + 1000100; private static final long DEFAULT_CREATION_TIME_MILLIS = 1000; private static final Duration RETENTION_PERIOD = Duration.ofDays(3); private static final LocaleList DEFAULT_LOCALES = LocaleList.forLanguageTags(DEFAULT_LOCALE_TAGS); private static final Map<String, LocalesInfo> DEFAULT_PACKAGE_LOCALES_INFO_MAP = Map.of( DEFAULT_PACKAGE_NAME, new LocalesInfo(DEFAULT_LOCALE_TAGS, false)); - private static final SparseArray<LocaleManagerBackupHelper.StagedData> STAGE_DATA = - new SparseArray<>(); + private final SparseArray<File> mStagedDataFiles = new SparseArray<>(); + private File mArchivedPackageFile; private LocaleManagerBackupHelper mBackupHelper; private long mCurrentTimeMillis; + private Context mContext = spy(ApplicationProvider.getApplicationContext()); @Mock - private Context mMockContext; - @Mock private PackageManager mMockPackageManager; @Mock private LocaleManagerService mMockLocaleManagerService; @@ -138,23 +139,28 @@ public class LocaleManagerBackupRestoreTest { @Before public void setUp() throws Exception { - mMockContext = mock(Context.class); mMockPackageManager = mock(PackageManager.class); mMockLocaleManagerService = mock(LocaleManagerService.class); mMockDelegateAppLocalePackages = mock(SharedPreferences.class); mMockSpEditor = mock(SharedPreferences.Editor.class); SystemAppUpdateTracker systemAppUpdateTracker = mock(SystemAppUpdateTracker.class); - doReturn(mMockPackageManager).when(mMockContext).getPackageManager(); + doReturn(mMockPackageManager).when(mContext).getPackageManager(); doReturn(mMockSpEditor).when(mMockDelegateAppLocalePackages).edit(); HandlerThread broadcastHandlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND); broadcastHandlerThread.start(); - mBackupHelper = spy(new ShadowLocaleManagerBackupHelper(mMockContext, - mMockLocaleManagerService, mMockPackageManager, mClock, STAGE_DATA, - broadcastHandlerThread, mMockDelegateAppLocalePackages)); + File file0 = new File(mContext.getCacheDir(), "file_user_0.txt"); + File file10 = new File(mContext.getCacheDir(), "file_user_10.txt"); + mStagedDataFiles.put(DEFAULT_USER_ID, file0); + mStagedDataFiles.put(WORK_PROFILE_USER_ID, file10); + mArchivedPackageFile = new File(mContext.getCacheDir(), "file_archived.txt"); + + mBackupHelper = spy(new ShadowLocaleManagerBackupHelper(mContext, + mMockLocaleManagerService, mMockPackageManager, mClock, broadcastHandlerThread, + mStagedDataFiles, mArchivedPackageFile, mMockDelegateAppLocalePackages)); doNothing().when(mBackupHelper).notifyBackupManager(); mUserMonitor = mBackupHelper.getUserMonitor(); @@ -165,7 +171,16 @@ public class LocaleManagerBackupRestoreTest { @After public void tearDown() throws Exception { - STAGE_DATA.clear(); + for (int i = 0; i < mStagedDataFiles.size(); i++) { + int userId = mStagedDataFiles.keyAt(i); + File file = mStagedDataFiles.get(userId); + SharedPreferences sp = mContext.getSharedPreferences(file, Context.MODE_PRIVATE); + sp.edit().clear().commit(); + if (file.exists()) { + file.delete(); + } + } + mStagedDataFiles.clear(); } @Test @@ -543,17 +558,21 @@ public class LocaleManagerBackupRestoreTest { mPackageMonitor.onPackageAddedWithExtras(pkgNameA, DEFAULT_UID, bundle); mPackageMonitor.onPackageAddedWithExtras(pkgNameB, DEFAULT_UID, bundle); + checkArchivedFileExists(); + mBackupHelper.stageAndApplyRestoredPayload(out.toByteArray(), DEFAULT_USER_ID); verifyNothingRestored(); setUpPackageInstalled(pkgNameA); - mPackageMonitor.onPackageUpdateFinished(pkgNameA, DEFAULT_UID); + mBackupHelper.onPackageUpdateFinished(pkgNameA, DEFAULT_UID); verify(mMockLocaleManagerService, times(1)).setApplicationLocales(pkgNameA, DEFAULT_USER_ID, LocaleList.forLanguageTags(langTagsA), false, FrameworkStatsLog .APPLICATION_LOCALES_CHANGED__CALLER__CALLER_BACKUP_RESTORE); + checkArchivedFileExists(); + mBackupHelper.persistLocalesModificationInfo(DEFAULT_USER_ID, pkgNameA, false, false); @@ -565,11 +584,12 @@ public class LocaleManagerBackupRestoreTest { setUpPackageInstalled(pkgNameB); - mPackageMonitor.onPackageUpdateFinished(pkgNameB, DEFAULT_UID); + mBackupHelper.onPackageUpdateFinished(pkgNameB, DEFAULT_UID); verify(mMockLocaleManagerService, times(1)).setApplicationLocales(pkgNameB, DEFAULT_USER_ID, LocaleList.forLanguageTags(langTagsB), true, FrameworkStatsLog .APPLICATION_LOCALES_CHANGED__CALLER__CALLER_BACKUP_RESTORE); + checkArchivedFileDoesNotExist(); mBackupHelper.persistLocalesModificationInfo(DEFAULT_USER_ID, pkgNameB, true, false); @@ -723,7 +743,7 @@ public class LocaleManagerBackupRestoreTest { Intent intent = new Intent(); intent.setAction(Intent.ACTION_USER_REMOVED); intent.putExtra(Intent.EXTRA_USER_HANDLE, DEFAULT_USER_ID); - mUserMonitor.onReceive(mMockContext, intent); + mUserMonitor.onReceive(mContext, intent); // Stage data should be removed only for DEFAULT_USER_ID. checkStageDataDoesNotExist(DEFAULT_USER_ID); @@ -732,6 +752,72 @@ public class LocaleManagerBackupRestoreTest { } @Test + public void testRestore_multipleProfile_restoresFromStage_ArchiveEnabled() throws Exception { + final ByteArrayOutputStream outDefault = new ByteArrayOutputStream(); + writeTestPayload(outDefault, DEFAULT_PACKAGE_LOCALES_INFO_MAP); + final ByteArrayOutputStream outWorkProfile = new ByteArrayOutputStream(); + String anotherPackage = "com.android.anotherapp"; + String anotherLangTags = "mr,zh"; + LocalesInfo localesInfo = new LocalesInfo(anotherLangTags, true); + HashMap<String, LocalesInfo> pkgLocalesMapWorkProfile = new HashMap<>(); + pkgLocalesMapWorkProfile.put(anotherPackage, localesInfo); + writeTestPayload(outWorkProfile, pkgLocalesMapWorkProfile); + // DEFAULT_PACKAGE_NAME is NOT installed on the device. + setUpPackageNotInstalled(DEFAULT_PACKAGE_NAME); + setUpPackageNotInstalled(anotherPackage); + setUpLocalesForPackage(DEFAULT_PACKAGE_NAME, LocaleList.getEmptyLocaleList()); + setUpLocalesForPackage(anotherPackage, LocaleList.getEmptyLocaleList()); + setUpPackageNamesForSp(new ArraySet<>()); + + Bundle bundle = new Bundle(); + bundle.putBoolean(Intent.EXTRA_ARCHIVAL, true); + mPackageMonitor.onPackageAddedWithExtras(DEFAULT_PACKAGE_NAME, DEFAULT_UID, bundle); + mPackageMonitor.onPackageAddedWithExtras(anotherPackage, WORK_PROFILE_UID, bundle); + + checkArchivedFileExists(); + + mBackupHelper.stageAndApplyRestoredPayload(outDefault.toByteArray(), DEFAULT_USER_ID); + mBackupHelper.stageAndApplyRestoredPayload(outWorkProfile.toByteArray(), + WORK_PROFILE_USER_ID); + + verifyNothingRestored(); + verifyStageDataForUser(DEFAULT_PACKAGE_LOCALES_INFO_MAP, + DEFAULT_CREATION_TIME_MILLIS, DEFAULT_USER_ID); + verifyStageDataForUser(pkgLocalesMapWorkProfile, + DEFAULT_CREATION_TIME_MILLIS, WORK_PROFILE_USER_ID); + + setUpPackageInstalled(DEFAULT_PACKAGE_NAME); + mBackupHelper.onPackageUpdateFinished(DEFAULT_PACKAGE_NAME, DEFAULT_UID); + + verify(mMockLocaleManagerService, times(1)).setApplicationLocales(DEFAULT_PACKAGE_NAME, + DEFAULT_USER_ID, + LocaleList.forLanguageTags(DEFAULT_LOCALE_TAGS), false, FrameworkStatsLog + .APPLICATION_LOCALES_CHANGED__CALLER__CALLER_BACKUP_RESTORE); + checkArchivedFileExists(); + checkStageDataDoesNotExist(DEFAULT_USER_ID); + + mBackupHelper.persistLocalesModificationInfo(DEFAULT_USER_ID, DEFAULT_PACKAGE_NAME, false, + false); + + verify(mMockSpEditor, times(0)).putStringSet(anyString(), any()); + + setUpPackageInstalled(anotherPackage); + mBackupHelper.onPackageUpdateFinished(anotherPackage, WORK_PROFILE_UID); + + verify(mMockLocaleManagerService, times(1)).setApplicationLocales(anotherPackage, + WORK_PROFILE_USER_ID, + LocaleList.forLanguageTags(anotherLangTags), true, FrameworkStatsLog + .APPLICATION_LOCALES_CHANGED__CALLER__CALLER_BACKUP_RESTORE); + checkArchivedFileDoesNotExist(); + + mBackupHelper.persistLocalesModificationInfo(DEFAULT_USER_ID, anotherPackage, true, false); + + verify(mMockSpEditor, times(1)).putStringSet(Integer.toString(DEFAULT_USER_ID), + new ArraySet<>(Arrays.asList(anotherPackage))); + checkStageDataDoesNotExist(WORK_PROFILE_USER_ID); + } + + @Test public void testPackageRemoved_noInfoInSp() throws Exception { String pkgNameA = "com.android.myAppA"; String pkgNameB = "com.android.myAppB"; @@ -858,10 +944,22 @@ public class LocaleManagerBackupRestoreTest { private void verifyStageDataForUser(Map<String, LocalesInfo> expectedPkgLocalesMap, long expectedCreationTimeMillis, int userId) { - LocaleManagerBackupHelper.StagedData stagedDataForUser = STAGE_DATA.get(userId); - assertNotNull(stagedDataForUser); - assertEquals(expectedCreationTimeMillis, stagedDataForUser.mCreationTimeMillis); - verifyStageData(expectedPkgLocalesMap, stagedDataForUser.mPackageStates); + SharedPreferences sp = mContext.getSharedPreferences(mStagedDataFiles.get(userId), + Context.MODE_PRIVATE); + assertTrue(sp.getAll().size() > 0); + assertEquals(expectedCreationTimeMillis, sp.getLong("staged_data_time", -1)); + verifyStageData(expectedPkgLocalesMap, sp); + } + + private static void verifyStageData(Map<String, LocalesInfo> expectedPkgLocalesMap, + SharedPreferences sp) { + for (String pkg : expectedPkgLocalesMap.keySet()) { + assertTrue(!sp.getString(pkg, "").isEmpty()); + String[] info = sp.getString(pkg, "").split(" s:"); + assertEquals(expectedPkgLocalesMap.get(pkg).mLocales, info[0]); + assertEquals(expectedPkgLocalesMap.get(pkg).mSetFromDelegate, + Boolean.parseBoolean(info[1])); + } } private static void verifyStageData(Map<String, LocalesInfo> expectedPkgLocalesMap, @@ -875,11 +973,19 @@ public class LocaleManagerBackupRestoreTest { } } - private static void checkStageDataExists(int userId) { - assertNotNull(STAGE_DATA.get(userId)); + private void checkStageDataExists(int userId) { + assertTrue(mStagedDataFiles.get(userId) != null && mStagedDataFiles.get(userId).exists()); + } + + private void checkStageDataDoesNotExist(int userId) { + assertTrue(mStagedDataFiles.get(userId) == null || !mStagedDataFiles.get(userId).exists()); + } + + private void checkArchivedFileExists() { + assertTrue(mArchivedPackageFile.exists()); } - private static void checkStageDataDoesNotExist(int userId) { - assertNull(STAGE_DATA.get(userId)); + private void checkArchivedFileDoesNotExist() { + assertTrue(!mArchivedPackageFile.exists()); } -} +}
\ No newline at end of file diff --git a/services/tests/servicestests/src/com/android/server/locales/ShadowLocaleManagerBackupHelper.java b/services/tests/servicestests/src/com/android/server/locales/ShadowLocaleManagerBackupHelper.java index 9f7cbe3170f0..b46902d9904a 100644 --- a/services/tests/servicestests/src/com/android/server/locales/ShadowLocaleManagerBackupHelper.java +++ b/services/tests/servicestests/src/com/android/server/locales/ShadowLocaleManagerBackupHelper.java @@ -22,6 +22,7 @@ import android.content.pm.PackageManager; import android.os.HandlerThread; import android.util.SparseArray; +import java.io.File; import java.time.Clock; /** @@ -33,9 +34,9 @@ public class ShadowLocaleManagerBackupHelper extends LocaleManagerBackupHelper { ShadowLocaleManagerBackupHelper(Context context, LocaleManagerService localeManagerService, PackageManager packageManager, Clock clock, - SparseArray<LocaleManagerBackupHelper.StagedData> stagedData, - HandlerThread broadcastHandlerThread, SharedPreferences delegateAppLocalePackages) { - super(context, localeManagerService, packageManager, clock, stagedData, - broadcastHandlerThread, delegateAppLocalePackages); + HandlerThread broadcastHandlerThread, SparseArray<File> stagedDataFiles, + File archivedPackagesFile, SharedPreferences delegateAppLocalePackages) { + super(context, localeManagerService, packageManager, clock, broadcastHandlerThread, + stagedDataFiles, archivedPackagesFile, delegateAppLocalePackages); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index 96ddfe8d5ac9..7ced9d50ab3f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -107,6 +107,7 @@ import android.graphics.Rect; import android.os.Binder; import android.os.RemoteException; import android.os.UserHandle; +import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.platform.test.annotations.RequiresFlagsDisabled; import android.provider.DeviceConfig; @@ -401,6 +402,7 @@ public class SizeCompatTests extends WindowTestsBase { // TODO(b/333663877): Enable test after fix @Test @RequiresFlagsDisabled({Flags.FLAG_INSETS_DECOUPLED_CONFIGURATION}) + @EnableFlags(Flags.FLAG_IMMERSIVE_APP_REPOSITIONING) public void testRepositionLandscapeImmersiveAppWithDisplayCutout() { final int dw = 2100; final int dh = 2000; @@ -4059,6 +4061,7 @@ public class SizeCompatTests extends WindowTestsBase { } @Test + @EnableFlags(Flags.FLAG_IMMERSIVE_APP_REPOSITIONING) public void testImmersiveLetterboxAlignedToBottom_OverlappingNavbar() { assertLandscapeActivityAlignedToBottomWithNavbar(true /* immersive */); } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index 1d014201cf46..a7dbecbb5255 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -794,9 +794,8 @@ public class VoiceInteractionManagerService extends SystemService { if (curService != null && !curService.isEmpty()) { try { serviceComponent = ComponentName.unflattenFromString(curService); - serviceInfo = AppGlobals.getPackageManager() - .getServiceInfo(serviceComponent, 0, mCurUser); - } catch (RuntimeException | RemoteException e) { + serviceInfo = getValidVoiceInteractionServiceInfo(serviceComponent); + } catch (RuntimeException e) { Slog.wtf(TAG, "Bad voice interaction service name " + curService, e); serviceComponent = null; serviceInfo = null; @@ -834,6 +833,27 @@ public class VoiceInteractionManagerService extends SystemService { } } + @Nullable + private ServiceInfo getValidVoiceInteractionServiceInfo( + @Nullable ComponentName serviceComponent) { + if (serviceComponent == null) { + return null; + } + List<ResolveInfo> services = queryInteractorServices( + mCurUser, serviceComponent.getPackageName()); + for (int i = 0; i < services.size(); i++) { + ResolveInfo service = services.get(i); + VoiceInteractionServiceInfo info = new VoiceInteractionServiceInfo( + mContext.getPackageManager(), service.serviceInfo); + ServiceInfo candidateInfo = info.getServiceInfo(); + if (candidateInfo != null + && candidateInfo.getComponentName().equals(serviceComponent)) { + return candidateInfo; + } + } + return null; + } + private List<ResolveInfo> queryInteractorServices( @UserIdInt int user, @Nullable String packageName) { diff --git a/tests/FlickerTests/ActivityEmbedding/Android.bp b/tests/FlickerTests/ActivityEmbedding/Android.bp index 2cdf54248ebc..e09fbf6adc02 100644 --- a/tests/FlickerTests/ActivityEmbedding/Android.bp +++ b/tests/FlickerTests/ActivityEmbedding/Android.bp @@ -20,17 +20,65 @@ package { // all of the 'license_kinds' from "frameworks_base_license" // to get the below license kinds: // SPDX-license-identifier-Apache-2.0 + default_team: "trendy_team_windowing_sdk", default_applicable_licenses: ["frameworks_base_license"], } -android_test { - name: "FlickerTestsOther", +filegroup { + name: "FlickerTestsOtherCommon-src", + srcs: ["src/**/ActivityEmbeddingTestBase.kt"], +} + +filegroup { + name: "FlickerTestsOtherOpen-src", + srcs: ["src/**/open/*"], +} + +filegroup { + name: "FlickerTestsOtherRotation-src", + srcs: ["src/**/rotation/*"], +} + +java_library { + name: "FlickerTestsOtherCommon", + defaults: ["FlickerTestsDefault"], + srcs: [":FlickerTestsOtherCommon-src"], + static_libs: ["FlickerTestsBase"], +} + +java_defaults { + name: "FlickerTestsOtherDefaults", defaults: ["FlickerTestsDefault"], manifest: "AndroidManifest.xml", package_name: "com.android.server.wm.flicker", instrumentation_target_package: "com.android.server.wm.flicker", test_config_template: "AndroidTestTemplate.xml", - srcs: ["src/**/*"], - static_libs: ["FlickerTestsBase"], + static_libs: [ + "FlickerTestsBase", + "FlickerTestsOtherCommon", + ], data: ["trace_config/*"], } + +android_test { + name: "FlickerTestsOtherOpen", + defaults: ["FlickerTestsOtherDefaults"], + srcs: [":FlickerTestsOtherOpen-src"], +} + +android_test { + name: "FlickerTestsOtherRotation", + defaults: ["FlickerTestsOtherDefaults"], + srcs: [":FlickerTestsOtherRotation-src"], +} + +android_test { + name: "FlickerTestsOther", + defaults: ["FlickerTestsOtherDefaults"], + srcs: ["src/**/*"], + exclude_srcs: [ + ":FlickerTestsOtherOpen-src", + ":FlickerTestsOtherRotation-src", + ":FlickerTestsOtherCommon-src", + ], +} |