summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp1
-rw-r--r--core/java/android/app/Notification.java48
-rw-r--r--core/java/android/app/admin/flags/flags.aconfig10
-rw-r--r--core/java/android/content/pm/multiuser.aconfig2
-rw-r--r--core/java/android/os/health/SystemHealthManager.java10
-rw-r--r--core/java/android/provider/Settings.java28
-rw-r--r--core/java/android/window/DesktopExperienceFlags.java1
-rw-r--r--core/java/android/window/DesktopModeFlags.java6
-rw-r--r--core/java/android/window/flags/lse_desktop_experience.aconfig22
-rw-r--r--core/java/android/window/flags/windowing_frontend.aconfig19
-rw-r--r--core/java/com/android/internal/policy/DecorView.java130
-rw-r--r--core/java/com/android/internal/widget/ActionBarContextView.java12
-rw-r--r--core/java/com/android/internal/widget/ActionBarOverlayLayout.java85
-rw-r--r--core/java/com/android/internal/widget/NotificationExpandButton.java10
-rw-r--r--core/res/res/layout/notification_2025_expand_button.xml1
-rw-r--r--core/res/res/layout/notification_2025_right_icon.xml31
-rw-r--r--core/res/res/layout/notification_2025_template_collapsed_base.xml5
-rw-r--r--core/res/res/layout/notification_2025_template_collapsed_call.xml5
-rw-r--r--core/res/res/layout/notification_2025_template_collapsed_conversation.xml11
-rw-r--r--core/res/res/layout/notification_2025_template_collapsed_media.xml5
-rw-r--r--core/res/res/layout/notification_2025_template_collapsed_messaging.xml11
-rw-r--r--core/res/res/layout/notification_2025_template_expanded_base.xml2
-rw-r--r--core/res/res/layout/notification_2025_template_expanded_big_picture.xml2
-rw-r--r--core/res/res/layout/notification_2025_template_expanded_big_text.xml2
-rw-r--r--core/res/res/layout/notification_2025_template_expanded_call.xml2
-rw-r--r--core/res/res/layout/notification_2025_template_expanded_conversation.xml2
-rw-r--r--core/res/res/layout/notification_2025_template_expanded_inbox.xml2
-rw-r--r--core/res/res/layout/notification_2025_template_expanded_media.xml2
-rw-r--r--core/res/res/layout/notification_2025_template_expanded_messaging.xml2
-rw-r--r--core/res/res/layout/notification_2025_template_expanded_progress.xml2
-rw-r--r--core/res/res/values/dimens.xml17
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--libs/WindowManager/Shell/aconfig/multitasking.aconfig10
-rw-r--r--libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/DropTargetView.kt14
-rw-r--r--libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java34
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java51
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java20
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PhonePipMenuController.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTaskListener.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java38
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/common/AppHandleAndHeaderVisibilityHelper.kt100
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt6
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PipBoundsStateTest.java27
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipTaskListenerTest.java35
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatusTest.kt13
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt5
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt7
-rw-r--r--libs/androidfw/include/androidfw/ResourceTypes.h10
-rw-r--r--media/java/Android.bp1
-rw-r--r--media/java/android/media/quality/Android.bp39
-rw-r--r--media/java/android/media/quality/MediaQualityManager.java86
-rw-r--r--media/java/android/media/quality/SoundProfileHandle.java72
-rw-r--r--media/java/android/media/quality/aidl/android/media/quality/ActiveProcessingPicture.aidl (renamed from media/java/android/media/quality/ActiveProcessingPicture.aidl)0
-rw-r--r--media/java/android/media/quality/aidl/android/media/quality/AmbientBacklightEvent.aidl (renamed from media/java/android/media/quality/AmbientBacklightEvent.aidl)0
-rw-r--r--media/java/android/media/quality/aidl/android/media/quality/AmbientBacklightMetadata.aidl (renamed from media/java/android/media/quality/AmbientBacklightMetadata.aidl)0
-rw-r--r--media/java/android/media/quality/aidl/android/media/quality/AmbientBacklightSettings.aidl (renamed from media/java/android/media/quality/AmbientBacklightSettings.aidl)0
-rw-r--r--media/java/android/media/quality/aidl/android/media/quality/IAmbientBacklightCallback.aidl (renamed from media/java/android/media/quality/IAmbientBacklightCallback.aidl)0
-rw-r--r--media/java/android/media/quality/aidl/android/media/quality/IMediaQualityManager.aidl (renamed from media/java/android/media/quality/IMediaQualityManager.aidl)70
-rw-r--r--media/java/android/media/quality/aidl/android/media/quality/IPictureProfileCallback.aidl (renamed from media/java/android/media/quality/IPictureProfileCallback.aidl)0
-rw-r--r--media/java/android/media/quality/aidl/android/media/quality/ISoundProfileCallback.aidl (renamed from media/java/android/media/quality/ISoundProfileCallback.aidl)0
-rw-r--r--media/java/android/media/quality/aidl/android/media/quality/ParameterCapability.aidl (renamed from media/java/android/media/quality/ParameterCapability.aidl)0
-rw-r--r--media/java/android/media/quality/aidl/android/media/quality/PictureProfile.aidl (renamed from media/java/android/media/quality/PictureProfile.aidl)0
-rw-r--r--media/java/android/media/quality/aidl/android/media/quality/PictureProfileHandle.aidl (renamed from media/java/android/media/quality/PictureProfileHandle.aidl)0
-rw-r--r--media/java/android/media/quality/aidl/android/media/quality/SoundProfile.aidl (renamed from media/java/android/media/quality/SoundProfile.aidl)0
-rw-r--r--media/java/android/media/quality/aidl/android/media/quality/SoundProfileHandle.aidl (renamed from media/java/android/media/quality/SoundProfileHandle.aidl)5
-rw-r--r--packages/SettingsLib/RestrictedLockUtils/res/values/strings.xml4
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictedMode.kt4
-rw-r--r--packages/SettingsLib/SpaPrivileged/tests/unit/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictedModeTest.kt12
-rw-r--r--packages/SettingsLib/SpaPrivileged/tests/unit/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPageTest.kt8
-rw-r--r--packages/SettingsLib/res/values/strings.xml2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java13
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java15
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java11
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java2
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/GSFAxes.kt1
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt1
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ComposedDigitalLayerController.kt10
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt9
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleDigitalHandLayerController.kt10
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt3
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt30
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/log/LogWtfHandlerRuleTest.kt155
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt32
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java20
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt47
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockFaceEvents.kt11
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/WeatherData.kt70
-rw-r--r--packages/SystemUI/res/values/dimens.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/effects/TopLevelWindowEffects.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/effects/dagger/TopLevelWindowEffectsModule.kt33
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java7
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorKosmos.kt3
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/log/LogWtfHandlerRule.kt102
-rw-r--r--services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java31
-rw-r--r--services/backup/java/com/android/server/backup/BackupRestoreTask.java31
-rw-r--r--services/backup/java/com/android/server/backup/UserBackupManagerService.java47
-rw-r--r--services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java2
-rw-r--r--services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java38
-rw-r--r--services/backup/java/com/android/server/backup/internal/BackupHandler.java5
-rw-r--r--services/backup/java/com/android/server/backup/internal/LifecycleOperationStorage.java21
-rw-r--r--services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java10
-rw-r--r--services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java2
-rw-r--r--services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java4
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceBroker.java4
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceInventory.java4
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java4
-rw-r--r--services/core/java/com/android/server/audio/SoundDoseHelper.java2
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java19
-rw-r--r--services/core/java/com/android/server/display/DisplayTopologyCoordinator.java16
-rw-r--r--services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java24
-rw-r--r--services/core/java/com/android/server/inputmethod/ImeProtoLogGroup.java6
-rw-r--r--services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java38
-rw-r--r--services/core/java/com/android/server/media/quality/MediaQualityService.java85
-rw-r--r--services/core/java/com/android/server/media/quality/MediaQualityUtils.java7
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivitySnapshotController.java8
-rw-r--r--services/core/java/com/android/server/wm/BaseAppSnapshotPersister.java84
-rw-r--r--services/core/java/com/android/server/wm/DesktopModeHelper.java10
-rw-r--r--services/core/java/com/android/server/wm/DisplayWindowListenerController.java6
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java64
-rw-r--r--services/java/com/android/server/SystemServer.java9
-rw-r--r--services/java/com/android/server/flags.aconfig8
-rw-r--r--services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java9
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt14
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/backup/BackupAgentConnectionManagerTest.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java42
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivitySnapshotControllerTests.java14
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DesktopModeHelperTest.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java28
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java32
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java27
146 files changed, 1636 insertions, 1045 deletions
diff --git a/Android.bp b/Android.bp
index 444725eb2c79..127556f8e075 100644
--- a/Android.bp
+++ b/Android.bp
@@ -415,6 +415,7 @@ java_defaults {
"mimemap",
"av-types-aidl-java",
"tv_tuner_resource_manager_aidl_interface-java",
+ "media_quality_aidl_interface-java",
"soundtrigger_middleware-aidl-java",
"modules-utils-binary-xml",
"modules-utils-build",
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 8d4925d8182d..127a08b04e87 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -6143,6 +6143,20 @@ public class Notification implements Parcelable
result.mTitleMarginSet.applyToView(contentView, p.mTextViewId);
contentView.setInt(p.mTextViewId, "setNumIndentLines", p.hasTitle() ? 0 : 1);
}
+ // The expand button uses paddings rather than margins, so we'll adjust it
+ // separately.
+ adjustExpandButtonPadding(contentView, result.mRightIconVisible);
+ }
+
+ private void adjustExpandButtonPadding(RemoteViews contentView, boolean rightIconVisible) {
+ if (notificationsRedesignTemplates()) {
+ final Resources res = mContext.getResources();
+ int normalPadding = res.getDimensionPixelSize(R.dimen.notification_2025_margin);
+ int iconSpacing = res.getDimensionPixelSize(
+ R.dimen.notification_2025_expand_button_right_icon_spacing);
+ contentView.setInt(R.id.expand_button, "setStartPadding",
+ rightIconVisible ? iconSpacing : normalPadding);
+ }
}
// This code is executed on behalf of other apps' notifications, sometimes even by 3p apps,
@@ -6154,12 +6168,21 @@ public class Notification implements Parcelable
@NonNull TemplateBindResult result) {
final Resources resources = mContext.getResources();
final float density = resources.getDisplayMetrics().density;
- final float iconMarginDp = resources.getDimension(
- R.dimen.notification_right_icon_content_margin) / density;
+ int iconMarginId = notificationsRedesignTemplates()
+ ? R.dimen.notification_2025_right_icon_content_margin
+ : R.dimen.notification_right_icon_content_margin;
+ final float iconMarginDp = resources.getDimension(iconMarginId) / density;
final float contentMarginDp = resources.getDimension(
R.dimen.notification_content_margin_end) / density;
- final float expanderSizeDp = resources.getDimension(
- R.dimen.notification_header_expand_icon_size) / density - contentMarginDp;
+ float spaceForExpanderDp;
+ if (notificationsRedesignTemplates()) {
+ spaceForExpanderDp = resources.getDimension(
+ R.dimen.notification_2025_right_icon_expanded_margin_end) / density
+ - contentMarginDp;
+ } else {
+ spaceForExpanderDp = resources.getDimension(
+ R.dimen.notification_header_expand_icon_size) / density - contentMarginDp;
+ }
final float viewHeightDp = resources.getDimension(
R.dimen.notification_right_icon_size) / density;
float viewWidthDp = viewHeightDp; // icons are 1:1 by default
@@ -6176,9 +6199,10 @@ public class Notification implements Parcelable
}
}
}
+ // Margin needed for the header to accommodate the icon when shown
final float extraMarginEndDpIfVisible = viewWidthDp + iconMarginDp;
result.setRightIconState(rightIcon != null /* visible */, viewWidthDp,
- viewHeightDp, extraMarginEndDpIfVisible, expanderSizeDp);
+ viewHeightDp, extraMarginEndDpIfVisible, spaceForExpanderDp);
}
/**
@@ -14658,13 +14682,19 @@ public class Notification implements Parcelable
public final MarginSet mTitleMarginSet = new MarginSet();
public void setRightIconState(boolean visible, float widthDp, float heightDp,
- float marginEndDpIfVisible, float expanderSizeDp) {
+ float marginEndDpIfVisible, float spaceForExpanderDp) {
mRightIconVisible = visible;
mRightIconWidthDp = widthDp;
mRightIconHeightDp = heightDp;
- mHeadingExtraMarginSet.setValues(0, marginEndDpIfVisible);
- mHeadingFullMarginSet.setValues(expanderSizeDp, marginEndDpIfVisible + expanderSizeDp);
- mTitleMarginSet.setValues(0, marginEndDpIfVisible + expanderSizeDp);
+ mHeadingExtraMarginSet.setValues(
+ /* valueIfGone = */ 0,
+ /* valueIfVisible = */ marginEndDpIfVisible);
+ mHeadingFullMarginSet.setValues(
+ /* valueIfGone = */ spaceForExpanderDp,
+ /* valueIfVisible = */ marginEndDpIfVisible + spaceForExpanderDp);
+ mTitleMarginSet.setValues(
+ /* valueIfGone = */ 0,
+ /* valueIfVisible = */ marginEndDpIfVisible + spaceForExpanderDp);
}
/**
diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig
index 0ecd2754b1f0..572bffe6c6a4 100644
--- a/core/java/android/app/admin/flags/flags.aconfig
+++ b/core/java/android/app/admin/flags/flags.aconfig
@@ -402,3 +402,13 @@ flag {
description: "Add new API for secondary lockscreen"
bug: "336297680"
}
+
+flag {
+ name: "remove_managed_esim_on_work_profile_deletion"
+ namespace: "enterprise"
+ description: "Remove managed eSIM when work profile is deleted"
+ bug: "347925470"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig
index 5c904c15e706..7f4fd3eff57e 100644
--- a/core/java/android/content/pm/multiuser.aconfig
+++ b/core/java/android/content/pm/multiuser.aconfig
@@ -617,8 +617,8 @@ flag {
}
flag {
- namespace: "multi_user"
name: "logout_user_api"
+ namespace: "multiuser"
description: "Add API to logout user"
bug: "350045389"
}
diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java
index a8a22f675e08..b82f278ef7d5 100644
--- a/core/java/android/os/health/SystemHealthManager.java
+++ b/core/java/android/os/health/SystemHealthManager.java
@@ -216,7 +216,7 @@ public class SystemHealthManager {
/**
* Gets the maximum number of TIDs this device supports for getting CPU headroom.
* <p>
- * See {@link CpuHeadroomParams#setTids(int...)}.
+ * See {@link CpuHeadroomParams.Builder#setTids(int...)}.
*
* @return the maximum size of TIDs supported
* @throws UnsupportedOperationException if the CPU headroom API is unsupported.
@@ -288,9 +288,7 @@ public class SystemHealthManager {
/**
* Gets the range of the calculation window size for CPU headroom.
* <p>
- * In API version 36, the range will be a superset of [50, 10000].
- * <p>
- * See {@link CpuHeadroomParams#setCalculationWindowMillis(int)}.
+ * See {@link CpuHeadroomParams.Builder#setCalculationWindowMillis(int)}.
*
* @return the range of the calculation window size supported in milliseconds.
* @throws UnsupportedOperationException if the CPU headroom API is unsupported.
@@ -310,9 +308,7 @@ public class SystemHealthManager {
/**
* Gets the range of the calculation window size for GPU headroom.
* <p>
- * In API version 36, the range will be a superset of [50, 10000].
- * <p>
- * See {@link GpuHeadroomParams#setCalculationWindowMillis(int)}.
+ * See {@link GpuHeadroomParams.Builder#setCalculationWindowMillis(int)}.
*
* @return the range of the calculation window size supported in milliseconds.
* @throws UnsupportedOperationException if the GPU headroom API is unsupported.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b5a42448809b..f91056dbce30 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8651,6 +8651,34 @@ public final class Settings {
public static final String DOCKED_CLOCK_FACE = "docked_clock_face";
/**
+ * Setting to indicate that content filters should be enabled on web browsers.
+ *
+ * <ul>
+ * <li>0 = Allow all sites
+ * <li>1 = Try to block explicit sites
+ * </ul>
+ *
+ * @hide
+ */
+ @Readable
+ public static final String BROWSER_CONTENT_FILTERS_ENABLED =
+ "browser_content_filters_enabled";
+
+ /**
+ * Setting to indicate that content filters should be enabled in web search engines.
+ *
+ * <ul>
+ * <li>0 = Off
+ * <li>1 = Filter
+ * </ul>
+ *
+ * @hide
+ */
+ @Readable
+ public static final String SEARCH_CONTENT_FILTERS_ENABLED =
+ "search_content_filters_enabled";
+
+ /**
* Set by the system to track if the user needs to see the call to action for
* the lockscreen notification policy.
* @hide
diff --git a/core/java/android/window/DesktopExperienceFlags.java b/core/java/android/window/DesktopExperienceFlags.java
index b4ff8e70ec36..cf582176a9f7 100644
--- a/core/java/android/window/DesktopExperienceFlags.java
+++ b/core/java/android/window/DesktopExperienceFlags.java
@@ -66,7 +66,6 @@ public enum DesktopExperienceFlags {
false),
ENABLE_PER_DISPLAY_PACKAGE_CONTEXT_CACHE_IN_STATUSBAR_NOTIF(
Flags::enablePerDisplayPackageContextCacheInStatusbarNotif, false),
- ENABLE_PROJECTED_DISPLAY_DESKTOP_MODE(Flags::enableProjectedDisplayDesktopMode, false),
ENABLE_TASKBAR_CONNECTED_DISPLAYS(Flags::enableTaskbarConnectedDisplays, false),
ENTER_DESKTOP_BY_DEFAULT_ON_FREEFORM_DISPLAYS(Flags::enterDesktopByDefaultOnFreeformDisplays,
false),
diff --git a/core/java/android/window/DesktopModeFlags.java b/core/java/android/window/DesktopModeFlags.java
index 78769248c013..17165cdcf7b1 100644
--- a/core/java/android/window/DesktopModeFlags.java
+++ b/core/java/android/window/DesktopModeFlags.java
@@ -138,10 +138,14 @@ public enum DesktopModeFlags {
ENABLE_WINDOWING_TRANSITION_HANDLERS_OBSERVERS(
Flags::enableWindowingTransitionHandlersObservers, false),
EXCLUDE_CAPTION_FROM_APP_BOUNDS(Flags::excludeCaptionFromAppBounds, false),
+ FORCE_CLOSE_TOP_TRANSPARENT_FULLSCREEN_TASK(
+ Flags::forceCloseTopTransparentFullscreenTask, false),
IGNORE_ASPECT_RATIO_RESTRICTIONS_FOR_RESIZEABLE_FREEFORM_ACTIVITIES(
Flags::ignoreAspectRatioRestrictionsForResizeableFreeformActivities, true),
INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC(
- Flags::includeTopTransparentFullscreenTaskInDesktopHeuristic, true)
+ Flags::includeTopTransparentFullscreenTaskInDesktopHeuristic, true),
+ INHERIT_TASK_BOUNDS_FOR_TRAMPOLINE_TASK_LAUNCHES(
+ Flags::inheritTaskBoundsForTrampolineTaskLaunches, false),
// go/keep-sorted end
;
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index 1f710c1cc8c0..ce3a101a7519 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -27,6 +27,17 @@ flag {
}
flag {
+ name: "inherit_task_bounds_for_trampoline_task_launches"
+ namespace: "lse_desktop_experience"
+ description: "Forces trampoline task launches to inherit the bounds of the previous instance /n"
+ "before is closes to prevent each task from cascading."
+ bug: "392815318"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "include_top_transparent_fullscreen_task_in_desktop_heuristic"
namespace: "lse_desktop_experience"
description: "Whether to include any top transparent fullscreen task launched in desktop /n"
@@ -50,6 +61,17 @@ flag {
}
flag {
+ name: "force_close_top_transparent_fullscreen_task"
+ namespace: "lse_desktop_experience"
+ description: "If a top transparent fullscreen task is on top of desktop mode, force it to /n"
+ "close if another task is opened or brought to front."
+ bug: "395041610"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "enable_windowing_dynamic_initial_bounds"
namespace: "lse_desktop_experience"
description: "Enables new initial bounds for desktop windowing which adjust depending on app constraints"
diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig
index b4fec416bd5f..3927c713e500 100644
--- a/core/java/android/window/flags/windowing_frontend.aconfig
+++ b/core/java/android/window/flags/windowing_frontend.aconfig
@@ -86,6 +86,14 @@ flag {
}
flag {
+ name: "action_mode_edge_to_edge"
+ namespace: "windowing_frontend"
+ description: "Make contextual action bar edge-to-edge"
+ bug: "379783298"
+ is_fixed_read_only: true
+}
+
+flag {
name: "keyguard_going_away_timeout"
namespace: "windowing_frontend"
description: "Allow a maximum of 10 seconds with keyguardGoingAway=true before force-resetting"
@@ -501,6 +509,17 @@ flag {
description: "Sets Launch powermode for activity launches earlier"
bug: "399380676"
is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "scramble_snapshot_file_name"
+ namespace: "windowing_frontend"
+ description: "Scramble the file name of task snapshot."
+ bug: "293139053"
+ is_fixed_read_only: true
metadata {
purpose: PURPOSE_BUGFIX
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index e20a52b24485..3d81e4fc7acd 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -120,6 +120,7 @@ import com.android.internal.view.menu.MenuHelper;
import com.android.internal.widget.ActionBarContextView;
import com.android.internal.widget.BackgroundFallback;
import com.android.internal.widget.floatingtoolbar.FloatingToolbar;
+import com.android.window.flags.Flags;
import java.util.List;
import java.util.concurrent.Executor;
@@ -1003,7 +1004,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
public void onWindowSystemUiVisibilityChanged(int visible) {
updateColorViews(null /* insets */, true /* animate */);
- if (mStatusGuard != null && mStatusGuard.getVisibility() == VISIBLE) {
+ if (!Flags.actionModeEdgeToEdge()
+ && mStatusGuard != null && mStatusGuard.getVisibility() == VISIBLE) {
updateStatusGuardColor();
}
}
@@ -1040,7 +1042,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
}
mFrameOffsets.set(insets.getSystemWindowInsetsAsRect());
insets = updateColorViews(insets, true /* animate */);
- insets = updateStatusGuard(insets);
+ insets = updateActionModeInsets(insets);
if (getForeground() != null) {
drawableChanged();
}
@@ -1592,7 +1594,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
}
}
- private WindowInsets updateStatusGuard(WindowInsets insets) {
+ private WindowInsets updateActionModeInsets(WindowInsets insets) {
boolean showStatusGuard = false;
// Show the status guard when the non-overlay contextual action bar is showing
if (mPrimaryActionModeView != null) {
@@ -1608,54 +1610,78 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
final Rect rect = mTempRect;
// Apply the insets that have not been applied by the contentParent yet.
- WindowInsets innerInsets =
+ final WindowInsets innerInsets =
mWindow.mContentParent.computeSystemWindowInsets(insets, rect);
- int newTopMargin = innerInsets.getSystemWindowInsetTop();
- int newLeftMargin = innerInsets.getSystemWindowInsetLeft();
- int newRightMargin = innerInsets.getSystemWindowInsetRight();
-
- // Must use root window insets for the guard, because the color views consume
- // the navigation bar inset if the window does not request LAYOUT_HIDE_NAV - but
- // the status guard is attached at the root.
- WindowInsets rootInsets = getRootWindowInsets();
- int newGuardLeftMargin = rootInsets.getSystemWindowInsetLeft();
- int newGuardRightMargin = rootInsets.getSystemWindowInsetRight();
-
- if (mlp.topMargin != newTopMargin || mlp.leftMargin != newLeftMargin
- || mlp.rightMargin != newRightMargin) {
- mlpChanged = true;
- mlp.topMargin = newTopMargin;
- mlp.leftMargin = newLeftMargin;
- mlp.rightMargin = newRightMargin;
- }
+ final boolean consumesSystemWindowInsetsTop;
+ if (Flags.actionModeEdgeToEdge()) {
+ final Insets newPadding = innerInsets.getSystemWindowInsets();
+ final Insets newMargin = innerInsets.getInsets(
+ WindowInsets.Type.navigationBars());
+
+ // Don't extend into navigation bar area so the width can align with status
+ // bar color view.
+ if (mlp.leftMargin != newMargin.left
+ || mlp.rightMargin != newMargin.right) {
+ mlpChanged = true;
+ mlp.leftMargin = newMargin.left;
+ mlp.rightMargin = newMargin.right;
+ }
+
+ mPrimaryActionModeView.setPadding(
+ newPadding.left - newMargin.left,
+ newPadding.top,
+ newPadding.right - newMargin.right,
+ 0);
+ consumesSystemWindowInsetsTop = newPadding.top > 0;
+ } else {
+ int newTopMargin = innerInsets.getSystemWindowInsetTop();
+ int newLeftMargin = innerInsets.getSystemWindowInsetLeft();
+ int newRightMargin = innerInsets.getSystemWindowInsetRight();
+
+ // Must use root window insets for the guard, because the color views
+ // consume the navigation bar inset if the window does not request
+ // LAYOUT_HIDE_NAV - but the status guard is attached at the root.
+ WindowInsets rootInsets = getRootWindowInsets();
+ int newGuardLeftMargin = rootInsets.getSystemWindowInsetLeft();
+ int newGuardRightMargin = rootInsets.getSystemWindowInsetRight();
+
+ if (mlp.topMargin != newTopMargin || mlp.leftMargin != newLeftMargin
+ || mlp.rightMargin != newRightMargin) {
+ mlpChanged = true;
+ mlp.topMargin = newTopMargin;
+ mlp.leftMargin = newLeftMargin;
+ mlp.rightMargin = newRightMargin;
+ }
- if (newTopMargin > 0 && mStatusGuard == null) {
- mStatusGuard = new View(mContext);
- mStatusGuard.setVisibility(GONE);
- final LayoutParams lp = new LayoutParams(MATCH_PARENT,
- mlp.topMargin, Gravity.LEFT | Gravity.TOP);
- lp.leftMargin = newGuardLeftMargin;
- lp.rightMargin = newGuardRightMargin;
- addView(mStatusGuard, indexOfChild(mStatusColorViewState.view), lp);
- } else if (mStatusGuard != null) {
- final LayoutParams lp = (LayoutParams)
- mStatusGuard.getLayoutParams();
- if (lp.height != mlp.topMargin || lp.leftMargin != newGuardLeftMargin
- || lp.rightMargin != newGuardRightMargin) {
- lp.height = mlp.topMargin;
+ if (newTopMargin > 0 && mStatusGuard == null) {
+ mStatusGuard = new View(mContext);
+ mStatusGuard.setVisibility(GONE);
+ final LayoutParams lp = new LayoutParams(MATCH_PARENT,
+ mlp.topMargin, Gravity.LEFT | Gravity.TOP);
lp.leftMargin = newGuardLeftMargin;
lp.rightMargin = newGuardRightMargin;
- mStatusGuard.setLayoutParams(lp);
+ addView(mStatusGuard, indexOfChild(mStatusColorViewState.view), lp);
+ } else if (mStatusGuard != null) {
+ final LayoutParams lp = (LayoutParams)
+ mStatusGuard.getLayoutParams();
+ if (lp.height != mlp.topMargin || lp.leftMargin != newGuardLeftMargin
+ || lp.rightMargin != newGuardRightMargin) {
+ lp.height = mlp.topMargin;
+ lp.leftMargin = newGuardLeftMargin;
+ lp.rightMargin = newGuardRightMargin;
+ mStatusGuard.setLayoutParams(lp);
+ }
}
- }
- // The action mode's theme may differ from the app, so
- // always show the status guard above it if we have one.
- showStatusGuard = mStatusGuard != null;
+ // The action mode's theme may differ from the app, so
+ // always show the status guard above it if we have one.
+ showStatusGuard = mStatusGuard != null;
- if (showStatusGuard && mStatusGuard.getVisibility() != VISIBLE) {
- // If it wasn't previously shown, the color may be stale
- updateStatusGuardColor();
+ if (showStatusGuard && mStatusGuard.getVisibility() != VISIBLE) {
+ // If it wasn't previously shown, the color may be stale
+ updateStatusGuardColor();
+ }
+ consumesSystemWindowInsetsTop = showStatusGuard;
}
// We only need to consume the insets if the action
@@ -1664,14 +1690,16 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
// screen_simple_overlay_action_mode.xml).
final boolean nonOverlay = (mWindow.getLocalFeaturesPrivate()
& (1 << Window.FEATURE_ACTION_MODE_OVERLAY)) == 0;
- if (nonOverlay && showStatusGuard) {
+ if (nonOverlay && consumesSystemWindowInsetsTop) {
insets = insets.inset(0, insets.getSystemWindowInsetTop(), 0, 0);
}
} else {
- // reset top margin
- if (mlp.topMargin != 0 || mlp.leftMargin != 0 || mlp.rightMargin != 0) {
- mlpChanged = true;
- mlp.topMargin = 0;
+ if (!Flags.actionModeEdgeToEdge()) {
+ // reset top margin
+ if (mlp.topMargin != 0 || mlp.leftMargin != 0 || mlp.rightMargin != 0) {
+ mlpChanged = true;
+ mlp.topMargin = 0;
+ }
}
}
if (mlpChanged) {
@@ -1679,7 +1707,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
}
}
}
- if (mStatusGuard != null) {
+ if (!Flags.actionModeEdgeToEdge() && mStatusGuard != null) {
mStatusGuard.setVisibility(showStatusGuard ? VISIBLE : GONE);
}
return insets;
@@ -2183,7 +2211,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
for (int i = getChildCount() - 1; i >= 0; i--) {
View v = getChildAt(i);
if (v != mStatusColorViewState.view && v != mNavigationColorViewState.view
- && v != mStatusGuard) {
+ && (Flags.actionModeEdgeToEdge() || v != mStatusGuard)) {
removeViewAt(i);
}
}
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index 80fc218839d5..d5bb51187ba4 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -34,6 +34,7 @@ import android.widget.TextView;
import com.android.internal.R;
import com.android.internal.view.menu.MenuBuilder;
+import com.android.window.flags.Flags;
/**
* @hide
@@ -315,12 +316,14 @@ public class ActionBarContextView extends AbsActionBarView {
final int contentWidth = MeasureSpec.getSize(widthMeasureSpec);
- int maxHeight = mContentHeight > 0 ?
- mContentHeight : MeasureSpec.getSize(heightMeasureSpec);
+ final int maxHeight = !Flags.actionModeEdgeToEdge() && mContentHeight > 0
+ ? mContentHeight : MeasureSpec.getSize(heightMeasureSpec);
final int verticalPadding = getPaddingTop() + getPaddingBottom();
int availableWidth = contentWidth - getPaddingLeft() - getPaddingRight();
- final int height = maxHeight - verticalPadding;
+ final int height = Flags.actionModeEdgeToEdge()
+ ? mContentHeight > 0 ? mContentHeight : maxHeight
+ : maxHeight - verticalPadding;
final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
if (mClose != null) {
@@ -376,7 +379,8 @@ public class ActionBarContextView extends AbsActionBarView {
}
setMeasuredDimension(contentWidth, measuredHeight);
} else {
- setMeasuredDimension(contentWidth, maxHeight);
+ setMeasuredDimension(contentWidth, Flags.actionModeEdgeToEdge()
+ ? mContentHeight + verticalPadding : maxHeight);
}
}
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
index ff57fd4fe2ce..362b79db4003 100644
--- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -294,54 +294,24 @@ public class ActionBarOverlayLayout extends ViewGroup implements DecorContentPar
}
}
- private boolean applyInsets(View view, Rect insets, boolean toPadding,
- boolean left, boolean top, boolean right, boolean bottom) {
- boolean changed;
- if (toPadding) {
- changed = setMargin(view, EMPTY_RECT, left, top, right, bottom);
- changed |= setPadding(view, insets, left, top, right, bottom);
- } else {
- changed = setPadding(view, EMPTY_RECT, left, top, right, bottom);
- changed |= setMargin(view, insets, left, top, right, bottom);
- }
- return changed;
- }
-
- private boolean setPadding(View view, Rect insets,
- boolean left, boolean top, boolean right, boolean bottom) {
- if ((left && view.getPaddingLeft() != insets.left)
- || (top && view.getPaddingTop() != insets.top)
- || (right && view.getPaddingRight() != insets.right)
- || (bottom && view.getPaddingBottom() != insets.bottom)) {
- view.setPadding(
- left ? insets.left : view.getPaddingLeft(),
- top ? insets.top : view.getPaddingTop(),
- right ? insets.right : view.getPaddingRight(),
- bottom ? insets.bottom : view.getPaddingBottom());
- return true;
- }
- return false;
- }
-
- private boolean setMargin(View view, Rect insets,
- boolean left, boolean top, boolean right, boolean bottom) {
+ private boolean setMargin(View view, int left, int top, int right, int bottom) {
final LayoutParams lp = (LayoutParams) view.getLayoutParams();
boolean changed = false;
- if (left && lp.leftMargin != insets.left) {
+ if (lp.leftMargin != left) {
changed = true;
- lp.leftMargin = insets.left;
+ lp.leftMargin = left;
}
- if (top && lp.topMargin != insets.top) {
+ if (lp.topMargin != top) {
changed = true;
- lp.topMargin = insets.top;
+ lp.topMargin = top;
}
- if (right && lp.rightMargin != insets.right) {
+ if (lp.rightMargin != right) {
changed = true;
- lp.rightMargin = insets.right;
+ lp.rightMargin = right;
}
- if (bottom && lp.bottomMargin != insets.bottom) {
+ if (lp.bottomMargin != bottom) {
changed = true;
- lp.bottomMargin = insets.bottom;
+ lp.bottomMargin = bottom;
}
return changed;
}
@@ -367,12 +337,30 @@ public class ActionBarOverlayLayout extends ViewGroup implements DecorContentPar
final Insets sysInsets = insets.getSystemWindowInsets();
mSystemInsets.set(sysInsets.left, sysInsets.top, sysInsets.right, sysInsets.bottom);
- // The top and bottom action bars are always within the content area.
- boolean changed = applyInsets(mActionBarTop, mSystemInsets,
- mActionBarExtendsIntoSystemInsets, true, true, true, false);
- if (mActionBarBottom != null) {
- changed |= applyInsets(mActionBarBottom, mSystemInsets,
- mActionBarExtendsIntoSystemInsets, true, false, true, true);
+ boolean changed = false;
+ if (mActionBarExtendsIntoSystemInsets) {
+ // Don't extend into navigation bar area so the width can align with status bar
+ // color view.
+ final Insets navBarInsets = insets.getInsets(WindowInsets.Type.navigationBars());
+ final int paddingLeft = sysInsets.left - navBarInsets.left;
+ final int paddingRight = sysInsets.right - navBarInsets.right;
+ mActionBarTop.setPadding(paddingLeft, sysInsets.top, paddingRight, 0);
+ changed |= setMargin(
+ mActionBarTop, navBarInsets.left, 0, navBarInsets.right, 0);
+ if (mActionBarBottom != null) {
+ mActionBarBottom.setPadding(paddingLeft, 0, paddingRight, sysInsets.bottom);
+ changed |= setMargin(
+ mActionBarBottom, navBarInsets.left, 0, navBarInsets.right, 0);
+ }
+ } else {
+ mActionBarTop.setPadding(0, 0, 0, 0);
+ changed |= setMargin(
+ mActionBarTop, sysInsets.left, sysInsets.top, sysInsets.right, 0);
+ if (mActionBarBottom != null) {
+ mActionBarBottom.setPadding(0, 0, 0, 0);
+ changed |= setMargin(
+ mActionBarTop, sysInsets.left, 0, sysInsets.right, sysInsets.bottom);
+ }
}
// Cannot use the result of computeSystemWindowInsets, because that consumes the
@@ -521,7 +509,12 @@ public class ActionBarOverlayLayout extends ViewGroup implements DecorContentPar
);
}
}
- setMargin(mContent, mContentInsets, true, true, true, true);
+ setMargin(
+ mContent,
+ mContentInsets.left,
+ mContentInsets.top,
+ mContentInsets.right,
+ mContentInsets.bottom);
if (!mLastInnerInsets.equals(mInnerInsets)) {
// If the inner insets have changed, we need to dispatch this down to
diff --git a/core/java/com/android/internal/widget/NotificationExpandButton.java b/core/java/com/android/internal/widget/NotificationExpandButton.java
index dd12f69a56fb..42b1bdbc51b2 100644
--- a/core/java/com/android/internal/widget/NotificationExpandButton.java
+++ b/core/java/com/android/internal/widget/NotificationExpandButton.java
@@ -129,6 +129,16 @@ public class NotificationExpandButton extends FrameLayout {
updateExpandedState();
}
+ /**
+ * Adjust the padding at the start of the view based on the layout direction (RTL/LTR).
+ * This is needed because RemoteViews don't have an equivalent for
+ * {@link this#setPaddingRelative}.
+ */
+ @RemotableViewMethod
+ public void setStartPadding(int startPadding) {
+ setPaddingRelative(startPadding, getPaddingTop(), getPaddingEnd(), getPaddingBottom());
+ }
+
private void updateExpandedState() {
int drawableId;
int contentDescriptionId;
diff --git a/core/res/res/layout/notification_2025_expand_button.xml b/core/res/res/layout/notification_2025_expand_button.xml
index 1c367544c90a..8ba844a4868b 100644
--- a/core/res/res/layout/notification_2025_expand_button.xml
+++ b/core/res/res/layout/notification_2025_expand_button.xml
@@ -15,6 +15,7 @@
-->
<!-- extends FrameLayout -->
+<!-- Note: The button's padding may be dynamically adjusted in code -->
<com.android.internal.widget.NotificationExpandButton
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/expand_button"
diff --git a/core/res/res/layout/notification_2025_right_icon.xml b/core/res/res/layout/notification_2025_right_icon.xml
new file mode 100644
index 000000000000..24d381d10501
--- /dev/null
+++ b/core/res/res/layout/notification_2025_right_icon.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2025 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<!-- Large icon to be used in expanded notification layouts. -->
+<com.android.internal.widget.CachingIconView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/right_icon"
+ android:layout_width="@dimen/notification_right_icon_size"
+ android:layout_height="@dimen/notification_right_icon_size"
+ android:layout_gravity="top|end"
+ android:layout_marginEnd="@dimen/notification_2025_right_icon_expanded_margin_end"
+ android:layout_marginVertical="@dimen/notification_2025_right_icon_vertical_margin"
+ android:background="@drawable/notification_large_icon_outline"
+ android:clipToOutline="true"
+ android:importantForAccessibility="no"
+ android:scaleType="centerCrop"
+ android:maxDrawableWidth="@dimen/notification_right_icon_size"
+ android:maxDrawableHeight="@dimen/notification_right_icon_size"
+ />
diff --git a/core/res/res/layout/notification_2025_template_collapsed_base.xml b/core/res/res/layout/notification_2025_template_collapsed_base.xml
index d29b7af9e24e..cfc2a997ab54 100644
--- a/core/res/res/layout/notification_2025_template_collapsed_base.xml
+++ b/core/res/res/layout/notification_2025_template_collapsed_base.xml
@@ -146,9 +146,8 @@
android:layout_width="@dimen/notification_right_icon_size"
android:layout_height="@dimen/notification_right_icon_size"
android:layout_gravity="center_vertical|end"
- android:layout_marginTop="@dimen/notification_right_icon_headerless_margin"
- android:layout_marginBottom="@dimen/notification_right_icon_headerless_margin"
- android:layout_marginStart="@dimen/notification_right_icon_content_margin"
+ android:layout_marginVertical="@dimen/notification_2025_right_icon_vertical_margin"
+ android:layout_marginStart="@dimen/notification_2025_right_icon_content_margin"
android:background="@drawable/notification_large_icon_outline"
android:clipToOutline="true"
android:importantForAccessibility="no"
diff --git a/core/res/res/layout/notification_2025_template_collapsed_call.xml b/core/res/res/layout/notification_2025_template_collapsed_call.xml
index ee691e4d6894..9fb63f6eff13 100644
--- a/core/res/res/layout/notification_2025_template_collapsed_call.xml
+++ b/core/res/res/layout/notification_2025_template_collapsed_call.xml
@@ -147,9 +147,8 @@
android:layout_width="@dimen/notification_right_icon_size"
android:layout_height="@dimen/notification_right_icon_size"
android:layout_gravity="center_vertical|end"
- android:layout_marginTop="@dimen/notification_right_icon_headerless_margin"
- android:layout_marginBottom="@dimen/notification_right_icon_headerless_margin"
- android:layout_marginStart="@dimen/notification_right_icon_content_margin"
+ android:layout_marginVertical="@dimen/notification_2025_right_icon_vertical_margin"
+ android:layout_marginStart="@dimen/notification_2025_right_icon_content_margin"
android:background="@drawable/notification_large_icon_outline"
android:clipToOutline="true"
android:importantForAccessibility="no"
diff --git a/core/res/res/layout/notification_2025_template_collapsed_conversation.xml b/core/res/res/layout/notification_2025_template_collapsed_conversation.xml
index f80411103501..a6fdcd95399e 100644
--- a/core/res/res/layout/notification_2025_template_collapsed_conversation.xml
+++ b/core/res/res/layout/notification_2025_template_collapsed_conversation.xml
@@ -149,9 +149,9 @@
android:layout_width="@dimen/notification_right_icon_size"
android:layout_height="@dimen/notification_right_icon_size"
android:layout_gravity="center_vertical|end"
- android:layout_marginTop="@dimen/notification_right_icon_headerless_margin"
- android:layout_marginBottom="@dimen/notification_right_icon_headerless_margin"
- android:layout_marginStart="@dimen/notification_right_icon_content_margin"
+ android:layout_marginTop="@dimen/notification_2025_margin"
+ android:layout_marginBottom="@dimen/notification_2025_margin"
+ android:layout_marginStart="@dimen/notification_2025_right_icon_content_margin"
android:forceHasOverlappingRendering="false"
android:spacing="0dp"
android:clipChildren="false"
@@ -163,9 +163,8 @@
android:layout_width="@dimen/notification_right_icon_size"
android:layout_height="@dimen/notification_right_icon_size"
android:layout_gravity="center_vertical|end"
- android:layout_marginTop="@dimen/notification_right_icon_headerless_margin"
- android:layout_marginBottom="@dimen/notification_right_icon_headerless_margin"
- android:layout_marginStart="@dimen/notification_right_icon_content_margin"
+ android:layout_marginVertical="@dimen/notification_2025_right_icon_vertical_margin"
+ android:layout_marginStart="@dimen/notification_2025_right_icon_content_margin"
android:background="@drawable/notification_large_icon_outline"
android:clipToOutline="true"
android:importantForAccessibility="no"
diff --git a/core/res/res/layout/notification_2025_template_collapsed_media.xml b/core/res/res/layout/notification_2025_template_collapsed_media.xml
index 5beab508aecf..c4ca5b5217ba 100644
--- a/core/res/res/layout/notification_2025_template_collapsed_media.xml
+++ b/core/res/res/layout/notification_2025_template_collapsed_media.xml
@@ -147,9 +147,8 @@
android:layout_width="@dimen/notification_right_icon_size"
android:layout_height="@dimen/notification_right_icon_size"
android:layout_gravity="center_vertical|end"
- android:layout_marginTop="@dimen/notification_right_icon_headerless_margin"
- android:layout_marginBottom="@dimen/notification_right_icon_headerless_margin"
- android:layout_marginStart="@dimen/notification_right_icon_content_margin"
+ android:layout_marginVertical="@dimen/notification_2025_right_icon_vertical_margin"
+ android:layout_marginStart="@dimen/notification_2025_right_icon_content_margin"
android:background="@drawable/notification_large_icon_outline"
android:clipToOutline="true"
android:importantForAccessibility="no"
diff --git a/core/res/res/layout/notification_2025_template_collapsed_messaging.xml b/core/res/res/layout/notification_2025_template_collapsed_messaging.xml
index d7c3263904d4..3716fa6825b3 100644
--- a/core/res/res/layout/notification_2025_template_collapsed_messaging.xml
+++ b/core/res/res/layout/notification_2025_template_collapsed_messaging.xml
@@ -159,9 +159,9 @@
android:layout_width="@dimen/notification_right_icon_size"
android:layout_height="@dimen/notification_right_icon_size"
android:layout_gravity="center_vertical|end"
- android:layout_marginTop="@dimen/notification_right_icon_headerless_margin"
- android:layout_marginBottom="@dimen/notification_right_icon_headerless_margin"
- android:layout_marginStart="@dimen/notification_right_icon_content_margin"
+ android:layout_marginTop="@dimen/notification_2025_margin"
+ android:layout_marginBottom="@dimen/notification_2025_margin"
+ android:layout_marginStart="@dimen/notification_2025_right_icon_content_margin"
android:forceHasOverlappingRendering="false"
android:spacing="0dp"
android:clipChildren="false"
@@ -173,9 +173,8 @@
android:layout_width="@dimen/notification_right_icon_size"
android:layout_height="@dimen/notification_right_icon_size"
android:layout_gravity="center_vertical|end"
- android:layout_marginTop="@dimen/notification_right_icon_headerless_margin"
- android:layout_marginBottom="@dimen/notification_right_icon_headerless_margin"
- android:layout_marginStart="@dimen/notification_right_icon_content_margin"
+ android:layout_marginVertical="@dimen/notification_2025_right_icon_vertical_margin"
+ android:layout_marginStart="@dimen/notification_2025_right_icon_content_margin"
android:background="@drawable/notification_large_icon_outline"
android:clipToOutline="true"
android:importantForAccessibility="no"
diff --git a/core/res/res/layout/notification_2025_template_expanded_base.xml b/core/res/res/layout/notification_2025_template_expanded_base.xml
index e12db2783191..8d99e47c5386 100644
--- a/core/res/res/layout/notification_2025_template_expanded_base.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_base.xml
@@ -63,7 +63,7 @@
/>
</LinearLayout>
- <include layout="@layout/notification_template_right_icon" />
+ <include layout="@layout/notification_2025_right_icon" />
</FrameLayout>
<ViewStub
diff --git a/core/res/res/layout/notification_2025_template_expanded_big_picture.xml b/core/res/res/layout/notification_2025_template_expanded_big_picture.xml
index fac9d1c47f41..e8e460d1b4ae 100644
--- a/core/res/res/layout/notification_2025_template_expanded_big_picture.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_big_picture.xml
@@ -25,7 +25,7 @@
<include layout="@layout/notification_2025_template_header" />
- <include layout="@layout/notification_template_right_icon" />
+ <include layout="@layout/notification_2025_right_icon" />
<LinearLayout
android:id="@+id/notification_action_list_margin_target"
diff --git a/core/res/res/layout/notification_2025_template_expanded_big_text.xml b/core/res/res/layout/notification_2025_template_expanded_big_text.xml
index 4a807cb674c6..b68db7f0a638 100644
--- a/core/res/res/layout/notification_2025_template_expanded_big_text.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_big_text.xml
@@ -91,5 +91,5 @@
<include layout="@layout/notification_material_action_list" />
</com.android.internal.widget.RemeasuringLinearLayout>
- <include layout="@layout/notification_template_right_icon" />
+ <include layout="@layout/notification_2025_right_icon" />
</FrameLayout>
diff --git a/core/res/res/layout/notification_2025_template_expanded_call.xml b/core/res/res/layout/notification_2025_template_expanded_call.xml
index bbc29664d594..7b45b55ba15b 100644
--- a/core/res/res/layout/notification_2025_template_expanded_call.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_call.xml
@@ -68,6 +68,6 @@
</com.android.internal.widget.RemeasuringLinearLayout>
- <include layout="@layout/notification_template_right_icon" />
+ <include layout="@layout/notification_2025_right_icon" />
</com.android.internal.widget.CallLayout>
diff --git a/core/res/res/layout/notification_2025_template_expanded_conversation.xml b/core/res/res/layout/notification_2025_template_expanded_conversation.xml
index d7e8bb3b6da2..592785d53018 100644
--- a/core/res/res/layout/notification_2025_template_expanded_conversation.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_conversation.xml
@@ -70,6 +70,6 @@
</com.android.internal.widget.RemeasuringLinearLayout>
- <include layout="@layout/notification_template_right_icon" />
+ <include layout="@layout/notification_2025_right_icon" />
</com.android.internal.widget.ConversationLayout>
diff --git a/core/res/res/layout/notification_2025_template_expanded_inbox.xml b/core/res/res/layout/notification_2025_template_expanded_inbox.xml
index ccab02e312cc..6459e1eab862 100644
--- a/core/res/res/layout/notification_2025_template_expanded_inbox.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_inbox.xml
@@ -130,5 +130,5 @@
android:layout_marginTop="@dimen/notification_content_margin" />
<include layout="@layout/notification_material_action_list" />
</LinearLayout>
- <include layout="@layout/notification_template_right_icon" />
+ <include layout="@layout/notification_2025_right_icon" />
</FrameLayout>
diff --git a/core/res/res/layout/notification_2025_template_expanded_media.xml b/core/res/res/layout/notification_2025_template_expanded_media.xml
index e90ab792581f..801e339b3a92 100644
--- a/core/res/res/layout/notification_2025_template_expanded_media.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_media.xml
@@ -99,6 +99,6 @@
</LinearLayout>
- <include layout="@layout/notification_template_right_icon" />
+ <include layout="@layout/notification_2025_right_icon" />
</com.android.internal.widget.MediaNotificationView>
diff --git a/core/res/res/layout/notification_2025_template_expanded_messaging.xml b/core/res/res/layout/notification_2025_template_expanded_messaging.xml
index 20abfee6a4b6..82c71527a291 100644
--- a/core/res/res/layout/notification_2025_template_expanded_messaging.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_messaging.xml
@@ -70,6 +70,6 @@
</com.android.internal.widget.RemeasuringLinearLayout>
- <include layout="@layout/notification_template_right_icon" />
+ <include layout="@layout/notification_2025_right_icon" />
</com.android.internal.widget.MessagingLayout>
diff --git a/core/res/res/layout/notification_2025_template_expanded_progress.xml b/core/res/res/layout/notification_2025_template_expanded_progress.xml
index 87ded8975cb0..2ff252747fd2 100644
--- a/core/res/res/layout/notification_2025_template_expanded_progress.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_progress.xml
@@ -99,7 +99,7 @@
</LinearLayout>
</LinearLayout>
- <include layout="@layout/notification_template_right_icon" />
+ <include layout="@layout/notification_2025_right_icon" />
</FrameLayout>
<ViewStub
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index a1961aedf6b7..7a4f568fe4a4 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -390,6 +390,16 @@
<!-- The absolute size of the notification expand icon. -->
<dimen name="notification_header_expand_icon_size">56dp</dimen>
+ <!-- Margin to allow space for the expand button when showing the right icon in expanded -->
+ <!-- notifications. This is equal to notification_2025_expand_button_pill_width -->
+ <!-- + notification_2025_margin (end padding for expand button) -->
+ <!-- + notification_2025_expand_button_right_icon_spacing (space between pill and icon) -->
+ <dimen name="notification_2025_right_icon_expanded_margin_end">52dp</dimen>
+
+ <!-- The large icon has a smaller vertical margin than most other notification content, to -->
+ <!-- allow it to grow up to 48dp. -->
+ <dimen name="notification_2025_right_icon_vertical_margin">12dp</dimen>
+
<!-- the height of the expand button pill -->
<dimen name="notification_expand_button_pill_height">24dp</dimen>
@@ -411,9 +421,12 @@
<!-- the padding of the expand icon in the notification header -->
<dimen name="notification_2025_expand_button_horizontal_icon_padding">6dp</dimen>
- <!-- a smaller padding for the end of the expand button, for use when showing the number -->
+ <!-- smaller padding for the end of the expand icon, for use when showing the number -->
<dimen name="notification_2025_expand_button_reduced_end_padding">4dp</dimen>
+ <!-- the space needed between the expander pill and the large icon when visible -->
+ <dimen name="notification_2025_expand_button_right_icon_spacing">8dp</dimen>
+
<!-- the size of the notification close button -->
<dimen name="notification_close_button_size">16dp</dimen>
@@ -893,6 +906,8 @@
<dimen name="notification_right_icon_size">48dp</dimen>
<!-- The margin between the right icon and the content. -->
<dimen name="notification_right_icon_content_margin">12dp</dimen>
+ <!-- The margin between the right icon and the content. (2025 redesign version) -->
+ <dimen name="notification_2025_right_icon_content_margin">16dp</dimen>
<!-- The top and bottom margin of the right icon in the normal notification states -->
<dimen name="notification_right_icon_headerless_margin">20dp</dimen>
<!-- The top margin of the right icon in the "big" notification states -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c87ab283e188..833761bad734 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3267,6 +3267,8 @@
<java-symbol type="dimen" name="notification_2025_content_margin_start" />
<java-symbol type="dimen" name="notification_2025_expand_button_horizontal_icon_padding" />
<java-symbol type="dimen" name="notification_2025_expand_button_reduced_end_padding" />
+ <java-symbol type="dimen" name="notification_2025_expand_button_right_icon_spacing" />
+ <java-symbol type="dimen" name="notification_2025_right_icon_expanded_margin_end" />
<java-symbol type="dimen" name="notification_progress_margin_horizontal" />
<java-symbol type="dimen" name="notification_header_background_height" />
<java-symbol type="dimen" name="notification_header_touchable_height" />
@@ -3957,6 +3959,7 @@
<java-symbol type="dimen" name="notification_big_picture_max_width"/>
<java-symbol type="dimen" name="notification_right_icon_size"/>
<java-symbol type="dimen" name="notification_right_icon_content_margin"/>
+ <java-symbol type="dimen" name="notification_2025_right_icon_content_margin"/>
<java-symbol type="dimen" name="notification_actions_icon_drawable_size"/>
<java-symbol type="dimen" name="notification_custom_view_max_image_height"/>
<java-symbol type="dimen" name="notification_custom_view_max_image_width"/>
diff --git a/libs/WindowManager/Shell/aconfig/multitasking.aconfig b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
index 1e72d64397d7..ab2804626361 100644
--- a/libs/WindowManager/Shell/aconfig/multitasking.aconfig
+++ b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
@@ -194,3 +194,13 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "enable_gsf"
+ namespace: "multitasking"
+ description: "Applies GSF font styles to multitasking."
+ bug: "400534660"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/DropTargetView.kt b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/DropTargetView.kt
index 2bb6cf4ec3aa..73277310ffe4 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/DropTargetView.kt
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/DropTargetView.kt
@@ -20,6 +20,7 @@ import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.RectF
+import android.util.TypedValue
import android.view.View
import com.android.wm.shell.shared.R
@@ -37,14 +38,21 @@ class DropTargetView(context: Context) : View(context) {
private val strokePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
color = context.getColor(com.android.internal.R.color.materialColorPrimaryContainer)
style = Paint.Style.STROKE
- strokeWidth = context.resources.getDimensionPixelSize(R.dimen.drop_target_stroke).toFloat()
+ strokeWidth = 1.dpToPx()
}
- private val cornerRadius = context.resources.getDimensionPixelSize(
- R.dimen.drop_target_radius).toFloat()
+ private val cornerRadius = 28.dpToPx()
private val rect = RectF(0f, 0f, 0f, 0f)
+ // TODO b/396539130: Use shared xml resources once we can access them in launcher
+ private fun Int.dpToPx() =
+ TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP,
+ this.toFloat(),
+ context.resources.displayMetrics
+ )
+
override fun onDraw(canvas: Canvas) {
canvas.save()
canvas.drawRoundRect(rect, cornerRadius, cornerRadius, rectPaint)
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java
index ed5e0c608675..2e33253b5e09 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java
@@ -17,9 +17,7 @@
package com.android.wm.shell.shared.desktopmode;
import static android.hardware.display.DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED;
-import static android.window.DesktopExperienceFlags.ENABLE_PROJECTED_DISPLAY_DESKTOP_MODE;
-import static com.android.server.display.feature.flags.Flags.enableDisplayContentModeManagement;
import static com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper.enableBubbleToFullscreen;
import android.annotation.NonNull;
@@ -226,7 +224,7 @@ public class DesktopModeStatus {
/**
* Return {@code true} if the current device can host desktop sessions on its internal display.
*/
- private static boolean canInternalDisplayHostDesktops(@NonNull Context context) {
+ public static boolean canInternalDisplayHostDesktops(@NonNull Context context) {
return context.getResources().getBoolean(R.bool.config_canInternalDisplayHostDesktops);
}
@@ -271,29 +269,6 @@ public class DesktopModeStatus {
}
/**
- * Check to see if a display should have desktop mode enabled or not. Internal
- * and external displays have separate logic.
- */
- public static boolean isDesktopModeSupportedOnDisplay(Context context, Display display) {
- if (!canEnterDesktopMode(context)) {
- return false;
- }
- if (display.getType() == Display.TYPE_INTERNAL) {
- return canInternalDisplayHostDesktops(context);
- }
-
- // TODO (b/395014779): Change this to use WM API
- if ((display.getType() == Display.TYPE_EXTERNAL
- || display.getType() == Display.TYPE_OVERLAY)
- && enableDisplayContentModeManagement()) {
- final WindowManager wm = context.getSystemService(WindowManager.class);
- return wm != null && wm.shouldShowSystemDecors(display.getDisplayId());
- }
-
- return false;
- }
-
- /**
* Returns whether the multiple desktops feature is enabled for this device (both backend and
* frontend implementations).
*/
@@ -366,11 +341,8 @@ public class DesktopModeStatus {
if (!enforceDeviceRestrictions()) {
return true;
}
- // If projected display is enabled, #canInternalDisplayHostDesktops is no longer a
- // requirement.
- final boolean desktopModeSupported = ENABLE_PROJECTED_DISPLAY_DESKTOP_MODE.isTrue()
- ? isDesktopModeSupported(context) : (isDesktopModeSupported(context)
- && canInternalDisplayHostDesktops(context));
+ final boolean desktopModeSupported = isDesktopModeSupported(context)
+ && canInternalDisplayHostDesktops(context);
final boolean desktopModeSupportedByDevOptions =
Flags.enableDesktopModeThroughDevOption()
&& isDesktopModeDevOptionSupported(context);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java
index 214e6ad455a1..aeef211ae3f3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java
@@ -143,6 +143,9 @@ public class PipBoundsState {
*/
public final Rect mCachedLauncherShelfHeightKeepClearArea = new Rect();
+ private final List<OnPipComponentChangedListener> mOnPipComponentChangedListeners =
+ new ArrayList<>();
+
// the size of the current bounds relative to the max size spec
private float mBoundsScale;
@@ -156,9 +159,7 @@ public class PipBoundsState {
// Update the relative proportion of the bounds compared to max possible size. Max size
// spec takes the aspect ratio of the bounds into account, so both width and height
// scale by the same factor.
- addPipExclusionBoundsChangeCallback((bounds) -> {
- updateBoundsScale();
- });
+ addPipExclusionBoundsChangeCallback((bounds) -> updateBoundsScale());
}
/** Reloads the resources. */
@@ -341,11 +342,14 @@ public class PipBoundsState {
/** Set the last {@link ComponentName} to enter PIP mode. */
public void setLastPipComponentName(@Nullable ComponentName lastPipComponentName) {
final boolean changed = !Objects.equals(mLastPipComponentName, lastPipComponentName);
+ if (!changed) return;
+ clearReentryState();
+ setHasUserResizedPip(false);
+ setHasUserMovedPip(false);
+ final ComponentName oldComponentName = mLastPipComponentName;
mLastPipComponentName = lastPipComponentName;
- if (changed) {
- clearReentryState();
- setHasUserResizedPip(false);
- setHasUserMovedPip(false);
+ for (OnPipComponentChangedListener listener : mOnPipComponentChangedListeners) {
+ listener.onPipComponentChanged(oldComponentName, mLastPipComponentName);
}
}
@@ -616,6 +620,21 @@ public class PipBoundsState {
}
}
+ /** Adds callback to listen on component change. */
+ public void addOnPipComponentChangedListener(@NonNull OnPipComponentChangedListener listener) {
+ if (!mOnPipComponentChangedListeners.contains(listener)) {
+ mOnPipComponentChangedListeners.add(listener);
+ }
+ }
+
+ /** Removes callback to listen on component change. */
+ public void removeOnPipComponentChangedListener(
+ @NonNull OnPipComponentChangedListener listener) {
+ if (mOnPipComponentChangedListeners.contains(listener)) {
+ mOnPipComponentChangedListeners.remove(listener);
+ }
+ }
+
public LauncherState getLauncherState() {
return mLauncherState;
}
@@ -695,7 +714,7 @@ public class PipBoundsState {
* Represents the state of pip to potentially restore upon reentry.
*/
@VisibleForTesting
- public static final class PipReentryState {
+ static final class PipReentryState {
private static final String TAG = PipReentryState.class.getSimpleName();
private final float mSnapFraction;
@@ -722,6 +741,22 @@ public class PipBoundsState {
}
}
+ /**
+ * Listener interface for PiP component change, i.e. the app in pip mode changes
+ * TODO: Move this out of PipBoundsState once pip1 is deprecated.
+ */
+ public interface OnPipComponentChangedListener {
+ /**
+ * Callback when the component in pip mode changes.
+ * @param oldPipComponent previous component in pip mode,
+ * {@code null} if this is the very first time PiP appears.
+ * @param newPipComponent new component that enters pip mode.
+ */
+ void onPipComponentChanged(
+ @Nullable ComponentName oldPipComponent,
+ @NonNull ComponentName newPipComponent);
+ }
+
/** Dumps internal state. */
public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index f959683701d2..0c654616507d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -169,7 +169,6 @@ import com.android.wm.shell.windowdecor.CaptionWindowDecorViewModel;
import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel;
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer;
-import com.android.wm.shell.windowdecor.common.AppHandleAndHeaderVisibilityHelper;
import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader;
import com.android.wm.shell.windowdecor.common.viewhost.DefaultWindowDecorViewHostSupplier;
import com.android.wm.shell.windowdecor.common.viewhost.PooledWindowDecorViewHostSupplier;
@@ -1016,7 +1015,6 @@ public abstract class WMShellModule {
Optional<DesktopTasksLimiter> desktopTasksLimiter,
AppHandleEducationController appHandleEducationController,
AppToWebEducationController appToWebEducationController,
- AppHandleAndHeaderVisibilityHelper appHandleAndHeaderVisibilityHelper,
WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler,
FocusTransitionObserver focusTransitionObserver,
@@ -1040,10 +1038,10 @@ public abstract class WMShellModule {
rootTaskDisplayAreaOrganizer, interactionJankMonitor, genericLinksParser,
assistContentRequester, windowDecorViewHostSupplier, multiInstanceHelper,
desktopTasksLimiter, appHandleEducationController, appToWebEducationController,
- appHandleAndHeaderVisibilityHelper, windowDecorCaptionHandleRepository,
- activityOrientationChangeHandler, focusTransitionObserver, desktopModeEventLogger,
- desktopModeUiEventLogger, taskResourceLoader, recentsTransitionHandler,
- desktopModeCompatPolicy, desktopTilingDecorViewModel,
+ windowDecorCaptionHandleRepository, activityOrientationChangeHandler,
+ focusTransitionObserver, desktopModeEventLogger, desktopModeUiEventLogger,
+ taskResourceLoader, recentsTransitionHandler, desktopModeCompatPolicy,
+ desktopTilingDecorViewModel,
multiDisplayDragMoveIndicatorController));
}
@@ -1071,16 +1069,6 @@ public abstract class WMShellModule {
@WMSingleton
@Provides
- static AppHandleAndHeaderVisibilityHelper provideAppHandleAndHeaderVisibilityHelper(
- @NonNull Context context,
- @NonNull DisplayController displayController,
- @NonNull DesktopModeCompatPolicy desktopModeCompatPolicy) {
- return new AppHandleAndHeaderVisibilityHelper(context, displayController,
- desktopModeCompatPolicy);
- }
-
- @WMSingleton
- @Provides
static WindowDecorTaskResourceLoader provideWindowDecorTaskResourceLoader(
@NonNull Context context, @NonNull ShellInit shellInit,
@NonNull ShellController shellController,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index f67323bb7eb1..09ebebda5cfa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -763,7 +763,9 @@ class DesktopTasksController(
fun minimizeTask(taskInfo: RunningTaskInfo, minimizeReason: MinimizeReason) {
val wct = WindowContainerTransaction()
- val isMinimizingToPip = taskInfo.pictureInPictureParams?.isAutoEnterEnabled() ?: false
+ val isMinimizingToPip =
+ DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PIP.isTrue &&
+ (taskInfo.pictureInPictureParams?.isAutoEnterEnabled() ?: false)
// If task is going to PiP, start a PiP transition instead of a minimize transition
if (isMinimizingToPip) {
val requestInfo =
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PhonePipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PhonePipMenuController.java
index 65099c2dfb9d..671eae3d84ef 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PhonePipMenuController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PhonePipMenuController.java
@@ -153,7 +153,12 @@ public class PhonePipMenuController implements PipMenuController,
mPipUiEventLogger = pipUiEventLogger;
mPipTransitionState.addPipTransitionStateChangedListener(this);
-
+ // Clear actions after exit PiP. Otherwise, next PiP could accidentally inherit the
+ // actions provided by the previous app in PiP mode.
+ mPipBoundsState.addOnPipComponentChangedListener(((oldPipComponent, newPipComponent) -> {
+ if (mAppActions != null) mAppActions.clear();
+ mCloseAction = null;
+ }));
mPipTaskListener.addParamsChangedListener(new PipTaskListener.PipParamsChangedCallback() {
@Override
public void onActionsChanged(List<RemoteAction> actions, RemoteAction closeAction) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTaskListener.java
index d6634845ee21..294ef48c01d0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTaskListener.java
@@ -61,7 +61,7 @@ public class PipTaskListener implements ShellTaskOrganizer.TaskListener,
private final PipBoundsState mPipBoundsState;
private final PipBoundsAlgorithm mPipBoundsAlgorithm;
private final ShellExecutor mMainExecutor;
- private final PictureInPictureParams mPictureInPictureParams =
+ private PictureInPictureParams mPictureInPictureParams =
new PictureInPictureParams.Builder().build();
private boolean mWaitingForAspectRatioChange = false;
@@ -92,6 +92,11 @@ public class PipTaskListener implements ShellTaskOrganizer.TaskListener,
}
mPipResizeAnimatorSupplier = PipResizeAnimator::new;
mPipScheduler.setPipParamsSupplier(this::getPictureInPictureParams);
+ // Reset {@link #mPictureInPictureParams} after exiting PiP. For instance, next Activity
+ // with null aspect ratio would accidentally inherit the aspect ratio from a previous
+ // PiP Activity.
+ mPipBoundsState.addOnPipComponentChangedListener(((oldPipComponent, newPipComponent) ->
+ mPictureInPictureParams = new PictureInPictureParams.Builder().build()));
}
void setPictureInPictureParams(@Nullable PictureInPictureParams params) {
@@ -138,9 +143,8 @@ public class PipTaskListener implements ShellTaskOrganizer.TaskListener,
if (mPictureInPictureParams.hasSetAspectRatio()
&& mPipBoundsAlgorithm.isValidPictureInPictureAspectRatio(newAspectRatio)
&& PipUtils.aspectRatioChanged(newAspectRatio, mPipBoundsState.getAspectRatio())) {
- mPipTransitionState.setOnIdlePipTransitionStateRunnable(() -> {
- onAspectRatioChanged(newAspectRatio);
- });
+ mPipTransitionState.setOnIdlePipTransitionStateRunnable(
+ () -> onAspectRatioChanged(newAspectRatio));
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 7472b0ea56ca..c370c0cb0930 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -2920,7 +2920,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
prepareEnterSplitScreen(out);
mSplitTransitions.setEnterTransition(transition, request.getRemoteTransition(),
TRANSIT_SPLIT_SCREEN_PAIR_OPEN, !mIsDropEntering, SNAP_TO_2_50_50);
- } else if (isSplitScreenVisible() && isOpening) {
+ } else if (enableFlexibleTwoAppSplit() && isSplitScreenVisible() && isOpening) {
// launching into an existing split stage; possibly launchAdjacent
// If we're replacing a pip-able app, we need to let mixed handler take care of
// it. Otherwise we'll just treat it as an enter+resize
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index ffb81f8c33e5..7ef1a93cbe45 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -17,9 +17,11 @@
package com.android.wm.shell.windowdecor;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_HOVER_ENTER;
@@ -77,6 +79,7 @@ import android.view.SurfaceControl.Transaction;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewRootImpl;
+import android.view.WindowManager;
import android.window.DesktopModeFlags;
import android.window.TaskSnapshot;
import android.window.WindowContainerToken;
@@ -118,6 +121,7 @@ import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition;
import com.android.wm.shell.desktopmode.DesktopTasksLimiter;
import com.android.wm.shell.desktopmode.DesktopUserRepositories;
+import com.android.wm.shell.desktopmode.DesktopWallpaperActivity;
import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository;
import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction;
import com.android.wm.shell.desktopmode.common.ToggleTaskSizeUtilsKt;
@@ -142,7 +146,6 @@ import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.FocusTransitionObserver;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration.ExclusionRegionListener;
-import com.android.wm.shell.windowdecor.common.AppHandleAndHeaderVisibilityHelper;
import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader;
import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHost;
import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHostSupplier;
@@ -204,7 +207,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
private final Optional<DesktopTasksLimiter> mDesktopTasksLimiter;
private final AppHandleEducationController mAppHandleEducationController;
private final AppToWebEducationController mAppToWebEducationController;
- private final AppHandleAndHeaderVisibilityHelper mAppHandleAndHeaderVisibilityHelper;
private final AppHeaderViewHolder.Factory mAppHeaderViewHolderFactory;
private boolean mTransitionDragActive;
@@ -292,7 +294,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
Optional<DesktopTasksLimiter> desktopTasksLimiter,
AppHandleEducationController appHandleEducationController,
AppToWebEducationController appToWebEducationController,
- AppHandleAndHeaderVisibilityHelper appHandleAndHeaderVisibilityHelper,
WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler,
FocusTransitionObserver focusTransitionObserver,
@@ -337,7 +338,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
desktopTasksLimiter,
appHandleEducationController,
appToWebEducationController,
- appHandleAndHeaderVisibilityHelper,
windowDecorCaptionHandleRepository,
activityOrientationChangeHandler,
new TaskPositionerFactory(),
@@ -386,7 +386,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
Optional<DesktopTasksLimiter> desktopTasksLimiter,
AppHandleEducationController appHandleEducationController,
AppToWebEducationController appToWebEducationController,
- AppHandleAndHeaderVisibilityHelper appHandleAndHeaderVisibilityHelper,
WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler,
TaskPositionerFactory taskPositionerFactory,
@@ -432,7 +431,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
mDesktopTasksLimiter = desktopTasksLimiter;
mAppHandleEducationController = appHandleEducationController;
mAppToWebEducationController = appToWebEducationController;
- mAppHandleAndHeaderVisibilityHelper = appHandleAndHeaderVisibilityHelper;
mWindowDecorCaptionHandleRepository = windowDecorCaptionHandleRepository;
mActivityOrientationChangeHandler = activityOrientationChangeHandler;
mAssistContentRequester = assistContentRequester;
@@ -530,7 +528,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
@Override
public void setSplitScreenController(SplitScreenController splitScreenController) {
mSplitScreenController = splitScreenController;
- mAppHandleAndHeaderVisibilityHelper.setSplitScreenController(splitScreenController);
}
@Override
@@ -1720,7 +1717,32 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
}
private boolean shouldShowWindowDecor(RunningTaskInfo taskInfo) {
- return mAppHandleAndHeaderVisibilityHelper.shouldShowAppHandleOrHeader(taskInfo);
+ if (mDisplayController.getDisplay(taskInfo.displayId) == null) {
+ // If DisplayController doesn't have it tracked, it could be a private/managed display.
+ return false;
+ }
+ if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) return true;
+ if (mSplitScreenController != null
+ && mSplitScreenController.isTaskRootOrStageRoot(taskInfo.taskId)) {
+ return false;
+ }
+ if (mDesktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(taskInfo)) {
+ return false;
+ }
+ final boolean isOnLargeScreen =
+ mDisplayController.getDisplay(taskInfo.displayId).getMinSizeDimensionDp()
+ >= WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
+ if (!DesktopModeStatus.canEnterDesktopMode(mContext)
+ && DesktopModeStatus.overridesShowAppHandle(mContext) && !isOnLargeScreen) {
+ // Devices with multiple screens may enable the app handle but it should not show on
+ // small screens
+ return false;
+ }
+ return DesktopModeStatus.canEnterDesktopModeOrShowAppHandle(mContext)
+ && !DesktopWallpaperActivity.isWallpaperTask(taskInfo)
+ && taskInfo.getWindowingMode() != WINDOWING_MODE_PINNED
+ && taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD
+ && !taskInfo.configuration.windowConfiguration.isAlwaysOnTop();
}
private void createWindowDecoration(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/common/AppHandleAndHeaderVisibilityHelper.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/common/AppHandleAndHeaderVisibilityHelper.kt
deleted file mode 100644
index 39ccf5bd03a7..000000000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/common/AppHandleAndHeaderVisibilityHelper.kt
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2025 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.windowdecor.common
-
-import android.app.ActivityManager
-import android.app.WindowConfiguration
-import android.content.Context
-import android.view.WindowManager
-import android.window.DesktopExperienceFlags.ENABLE_BUG_FIXES_FOR_SECONDARY_DISPLAY
-import com.android.wm.shell.common.DisplayController
-import com.android.wm.shell.desktopmode.DesktopWallpaperActivity.Companion.isWallpaperTask
-import com.android.wm.shell.shared.desktopmode.DesktopModeCompatPolicy
-import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
-import com.android.wm.shell.splitscreen.SplitScreenController
-
-/**
- * Resolves whether, given a task and its associated display that it is currently on, to show the
- * app handle/header or not.
- */
-class AppHandleAndHeaderVisibilityHelper (
- private val context: Context,
- private val displayController: DisplayController,
- private val desktopModeCompatPolicy: DesktopModeCompatPolicy
-) {
- var splitScreenController: SplitScreenController? = null
-
- /**
- * Returns, given a task's attribute and its display attribute, whether the app
- * handle/header should show or not for this task.
- */
- fun shouldShowAppHandleOrHeader(taskInfo: ActivityManager.RunningTaskInfo): Boolean {
- if (!ENABLE_BUG_FIXES_FOR_SECONDARY_DISPLAY.isTrue) {
- return allowedForTask(taskInfo)
- }
- return allowedForTask(taskInfo) && allowedForDisplay(taskInfo.displayId)
- }
-
- private fun allowedForTask(taskInfo: ActivityManager.RunningTaskInfo): Boolean {
- // TODO (b/382023296): Remove once we no longer rely on
- // Flags.enableBugFixesForSecondaryDisplay as it is taken care of in #allowedForDisplay
- if (displayController.getDisplay(taskInfo.displayId) == null) {
- // If DisplayController doesn't have it tracked, it could be a private/managed display.
- return false
- }
- if (taskInfo.windowingMode == WindowConfiguration.WINDOWING_MODE_FREEFORM) return true
- if (splitScreenController?.isTaskRootOrStageRoot(taskInfo.taskId) == true) {
- return false
- }
-
- if (desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(taskInfo)) {
- return false
- }
-
- // TODO (b/382023296): Remove once we no longer rely on
- // Flags.enableBugFixesForSecondaryDisplay as it is taken care of in #allowedForDisplay
- val isOnLargeScreen =
- displayController.getDisplay(taskInfo.displayId).minSizeDimensionDp >=
- WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP
- if (!DesktopModeStatus.canEnterDesktopMode(context)
- && DesktopModeStatus.overridesShowAppHandle(context)
- && !isOnLargeScreen
- ) {
- // Devices with multiple screens may enable the app handle but it should not show on
- // small screens
- return false
- }
- return DesktopModeStatus.canEnterDesktopModeOrShowAppHandle(context)
- && !isWallpaperTask(taskInfo)
- && taskInfo.windowingMode != WindowConfiguration.WINDOWING_MODE_PINNED
- && taskInfo.activityType == WindowConfiguration.ACTIVITY_TYPE_STANDARD
- && !taskInfo.configuration.windowConfiguration.isAlwaysOnTop
- }
-
- private fun allowedForDisplay(displayId: Int): Boolean {
- // If DisplayController doesn't have it tracked, it could be a private/managed display.
- val display = displayController.getDisplay(displayId)
- if (display == null) return false
-
- if (DesktopModeStatus.isDesktopModeSupportedOnDisplay(context, display)) {
- return true
- }
- // If on default display and on Large Screen (unfolded), show app handle
- return DesktopModeStatus.overridesShowAppHandle(context)
- && display.minSizeDimensionDp >= WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP
- }
-} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt
index c3f5b3f20f4a..30712b55bdfa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt
@@ -466,11 +466,7 @@ class AppHeaderViewHolder(
override fun onHandleMenuOpened() {}
- override fun onHandleMenuClosed() {
- openMenuButton.post {
- openMenuButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
- }
- }
+ override fun onHandleMenuClosed() {}
fun onMaximizeWindowHoverExit() {
maximizeButtonView.cancelHoverAnimation()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PipBoundsStateTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PipBoundsStateTest.java
index 01b76edd9b25..1066276becc7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PipBoundsStateTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PipBoundsStateTest.java
@@ -19,6 +19,8 @@ package com.android.wm.shell.common.pip;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -128,6 +130,31 @@ public class PipBoundsStateTest extends ShellTestCase {
}
@Test
+ public void setLastPipComponentName_notChanged_doesNotCallbackComponentChangedListener() {
+ mPipBoundsState.setLastPipComponentName(mTestComponentName1);
+ PipBoundsState.OnPipComponentChangedListener mockListener =
+ mock(PipBoundsState.OnPipComponentChangedListener.class);
+
+ mPipBoundsState.addOnPipComponentChangedListener(mockListener);
+ mPipBoundsState.setLastPipComponentName(mTestComponentName1);
+
+ verify(mockListener, never()).onPipComponentChanged(any(), any());
+ }
+
+ @Test
+ public void setLastPipComponentName_changed_callbackComponentChangedListener() {
+ mPipBoundsState.setLastPipComponentName(mTestComponentName1);
+ PipBoundsState.OnPipComponentChangedListener mockListener =
+ mock(PipBoundsState.OnPipComponentChangedListener.class);
+
+ mPipBoundsState.addOnPipComponentChangedListener(mockListener);
+ mPipBoundsState.setLastPipComponentName(mTestComponentName2);
+
+ verify(mockListener).onPipComponentChanged(
+ eq(mTestComponentName1), eq(mTestComponentName2));
+ }
+
+ @Test
public void testSetLastPipComponentName_notChanged_doesNotClearReentryState() {
mPipBoundsState.setLastPipComponentName(mTestComponentName1);
mPipBoundsState.saveReentryState(DEFAULT_SNAP_FRACTION);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipTaskListenerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipTaskListenerTest.java
index 333569a7206e..5029371c3419 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipTaskListenerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipTaskListenerTest.java
@@ -24,6 +24,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.kotlin.MatchersKt.eq;
import static org.mockito.kotlin.VerificationKt.clearInvocations;
@@ -35,7 +36,9 @@ import android.app.ActivityManager;
import android.app.PendingIntent;
import android.app.PictureInPictureParams;
import android.app.RemoteAction;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.drawable.Icon;
import android.os.Bundle;
@@ -48,8 +51,10 @@ import androidx.test.filters.SmallTest;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.pip.PhoneSizeSpecSource;
import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
import com.android.wm.shell.common.pip.PipBoundsState;
+import com.android.wm.shell.common.pip.PipDisplayLayoutState;
import com.android.wm.shell.pip2.animation.PipResizeAnimator;
import org.junit.Before;
@@ -107,6 +112,16 @@ public class PipTaskListenerTest {
}
@Test
+ public void constructor_addOnPipComponentChangedListener() {
+ mPipTaskListener = new PipTaskListener(mMockContext, mMockShellTaskOrganizer,
+ mMockPipTransitionState, mMockPipScheduler, mMockPipBoundsState,
+ mMockPipBoundsAlgorithm, mMockShellExecutor);
+
+ verify(mMockPipBoundsState).addOnPipComponentChangedListener(
+ any(PipBoundsState.OnPipComponentChangedListener.class));
+ }
+
+ @Test
public void setPictureInPictureParams_updatePictureInPictureParams() {
mPipTaskListener = new PipTaskListener(mMockContext, mMockShellTaskOrganizer,
mMockPipTransitionState, mMockPipScheduler, mMockPipBoundsState,
@@ -359,6 +374,26 @@ public class PipTaskListenerTest {
verify(mMockPipResizeAnimator, times(0)).start();
}
+ @Test
+ public void onPipComponentChanged_clearPictureInPictureParams() {
+ when(mMockContext.getResources()).thenReturn(mock(Resources.class));
+ PipBoundsState pipBoundsState = new PipBoundsState(mMockContext,
+ mock(PhoneSizeSpecSource.class), mock(PipDisplayLayoutState.class));
+ pipBoundsState.setLastPipComponentName(new ComponentName("org.test", "test1"));
+
+ mPipTaskListener = new PipTaskListener(mMockContext, mMockShellTaskOrganizer,
+ mMockPipTransitionState, mMockPipScheduler, pipBoundsState,
+ mMockPipBoundsAlgorithm, mMockShellExecutor);
+ Rational aspectRatio = new Rational(4, 3);
+ String action1 = "action1";
+ mPipTaskListener.setPictureInPictureParams(getPictureInPictureParams(
+ aspectRatio, action1));
+
+ pipBoundsState.setLastPipComponentName(new ComponentName("org.test", "test2"));
+
+ assertTrue(mPipTaskListener.getPictureInPictureParams().empty());
+ }
+
private PictureInPictureParams getPictureInPictureParams(Rational aspectRatio,
String... actions) {
final PictureInPictureParams.Builder builder = new PictureInPictureParams.Builder();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatusTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatusTest.kt
index edf91fe62e7d..fb62ba75e056 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatusTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatusTest.kt
@@ -234,23 +234,12 @@ class DesktopModeStatusTest : ShellTestCase() {
assertThat(DesktopModeStatus.isDeviceEligibleForDesktopMode(mockContext)).isFalse()
}
- @DisableFlags(Flags.FLAG_ENABLE_PROJECTED_DISPLAY_DESKTOP_MODE)
@Test
fun isDeviceEligibleForDesktopMode_configDEModeOnAndIntDispHostsDesktopOff_returnsFalse() {
doReturn(true).whenever(mockResources).getBoolean(eq(R.bool.config_isDesktopModeSupported))
- doReturn(false).whenever(mockResources)
- .getBoolean(eq(R.bool.config_canInternalDisplayHostDesktops))
-
- assertThat(DesktopModeStatus.isDeviceEligibleForDesktopMode(mockContext)).isFalse()
- }
-
- @EnableFlags(Flags.FLAG_ENABLE_PROJECTED_DISPLAY_DESKTOP_MODE)
- @Test
- fun isPDDeviceEligibleForDesktopMode_configDEModeOnAndIntDispHostsDesktopOff_returnsTrue() {
- doReturn(true).whenever(mockResources).getBoolean(eq(R.bool.config_isDesktopModeSupported))
doReturn(false).whenever(mockResources).getBoolean(eq(R.bool.config_canInternalDisplayHostDesktops))
- assertThat(DesktopModeStatus.isDeviceEligibleForDesktopMode(mockContext)).isTrue()
+ assertThat(DesktopModeStatus.isDeviceEligibleForDesktopMode(mockContext)).isFalse()
}
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
index d69509faf4ec..e89a122595d5 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
@@ -115,8 +115,7 @@ class DesktopModeWindowDecorViewModelTests : DesktopModeWindowDecorViewModelTest
.spyStatic(DragPositioningCallbackUtility::class.java)
.startMocking()
- doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupportedOnDisplay(Mockito.any(),
- Mockito.any()) }
+ doReturn(true).`when` { DesktopModeStatus.canInternalDisplayHostDesktops(Mockito.any()) }
doReturn(true).`when` { DesktopModeStatus.canEnterDesktopMode(Mockito.any()) }
doReturn(false).`when` { DesktopModeStatus.overridesShowAppHandle(Mockito.any()) }
@@ -395,7 +394,7 @@ class DesktopModeWindowDecorViewModelTests : DesktopModeWindowDecorViewModelTest
whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(true)
val task = createTask(windowingMode = WINDOWING_MODE_FULLSCREEN)
- doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupportedOnDisplay(any(), any()) }
+ doReturn(true).`when` { DesktopModeStatus.canInternalDisplayHostDesktops(any()) }
setUpMockDecorationsForTasks(task)
onTaskOpening(task)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt
index a1f40fdefee9..81dfaed56b6f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt
@@ -79,7 +79,6 @@ import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.util.StubTransaction
import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel.DesktopModeKeyguardChangeListener
import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel.DesktopModeOnInsetsChangedListener
-import com.android.wm.shell.windowdecor.common.AppHandleAndHeaderVisibilityHelper
import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader
import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHost
import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHostSupplier
@@ -175,7 +174,6 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() {
internal lateinit var desktopModeOnKeyguardChangedListener: DesktopModeKeyguardChangeListener
protected lateinit var desktopModeWindowDecorViewModel: DesktopModeWindowDecorViewModel
protected lateinit var desktopModeCompatPolicy: DesktopModeCompatPolicy
- protected lateinit var appHandleAndHeaderVisibilityHelper: AppHandleAndHeaderVisibilityHelper
fun setUpCommon() {
spyContext = spy(mContext)
@@ -187,13 +185,9 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() {
whenever(mockDesktopUserRepositories.current).thenReturn(mockDesktopRepository)
whenever(mockDisplayController.getDisplayContext(any())).thenReturn(spyContext)
whenever(mockDisplayController.getDisplay(any())).thenReturn(display)
- whenever(display.type).thenReturn(Display.TYPE_INTERNAL)
whenever(mockDesktopUserRepositories.getProfile(anyInt()))
.thenReturn(mockDesktopRepository)
desktopModeCompatPolicy = DesktopModeCompatPolicy(spyContext)
- appHandleAndHeaderVisibilityHelper =
- AppHandleAndHeaderVisibilityHelper(spyContext, mockDisplayController,
- desktopModeCompatPolicy)
desktopModeWindowDecorViewModel = DesktopModeWindowDecorViewModel(
spyContext,
testShellExecutor,
@@ -228,7 +222,6 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() {
Optional.of(mockTasksLimiter),
mockAppHandleEducationController,
mockAppToWebEducationController,
- appHandleAndHeaderVisibilityHelper,
mockCaptionHandleRepository,
Optional.of(mockActivityOrientationChangeHandler),
mockTaskPositionerFactory,
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 30594dcfa939..0d45149267cf 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1265,6 +1265,9 @@ struct ResTable_config
// Varies in length from 3 to 8 chars. Zero-filled value.
char localeNumberingSystem[8];
+ // Mark all padding explicitly so it's clear how much we can expand it.
+ char endPadding[3];
+
void copyFromDeviceNoSwap(const ResTable_config& o) {
const auto o_size = dtohl(o.size);
if (o_size >= sizeof(ResTable_config)) [[likely]] {
@@ -1422,6 +1425,13 @@ struct ResTable_config
void swapHtoD_slow();
};
+// Fix the struct size for backward compatibility
+static_assert(sizeof(ResTable_config) == 64);
+
+// Make sure there's no unaccounted padding in the structure.
+static_assert(offsetof(ResTable_config, endPadding) +
+ sizeof(ResTable_config::endPadding) == sizeof(ResTable_config));
+
/**
* A specification of the resources defined by a particular type.
*
diff --git a/media/java/Android.bp b/media/java/Android.bp
index 6878f9d61f6d..28b9d3bbc167 100644
--- a/media/java/Android.bp
+++ b/media/java/Android.bp
@@ -15,6 +15,7 @@ filegroup {
],
exclude_srcs: [
":framework-media-tv-tunerresourcemanager-sources-aidl",
+ ":framework-media-quality-sources-aidl",
],
visibility: [
"//frameworks/base",
diff --git a/media/java/android/media/quality/Android.bp b/media/java/android/media/quality/Android.bp
new file mode 100644
index 000000000000..080d5266ccb7
--- /dev/null
+++ b/media/java/android/media/quality/Android.bp
@@ -0,0 +1,39 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+filegroup {
+ name: "framework-media-quality-sources-aidl",
+ srcs: [
+ "aidl/android/media/quality/*.aidl",
+ ],
+ path: "aidl",
+}
+
+aidl_interface {
+ name: "media_quality_aidl_interface",
+ unstable: true,
+ local_include_dir: "aidl",
+ backend: {
+ java: {
+ enabled: true,
+ },
+ cpp: {
+ enabled: false,
+ },
+ ndk: {
+ enabled: false,
+ },
+ rust: {
+ enabled: false,
+ },
+ },
+ srcs: [
+ ":framework-media-quality-sources-aidl",
+ ],
+}
diff --git a/media/java/android/media/quality/MediaQualityManager.java b/media/java/android/media/quality/MediaQualityManager.java
index 0d6d32a22dae..bfd01380a2ee 100644
--- a/media/java/android/media/quality/MediaQualityManager.java
+++ b/media/java/android/media/quality/MediaQualityManager.java
@@ -274,9 +274,9 @@ public final class MediaQualityManager {
@NonNull String name,
@Nullable ProfileQueryParams options) {
try {
- Bundle optionsBundle = options == null
- ? ProfileQueryParams.DEFAULT.toBundle() : options.toBundle();
- return mService.getPictureProfile(type, name, optionsBundle, mUserHandle);
+ boolean includeParams = options == null || options.mParametersIncluded;
+ return mService.getPictureProfile(
+ type, name, includeParams, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -299,10 +299,9 @@ public final class MediaQualityManager {
public List<PictureProfile> getPictureProfilesByPackage(
@NonNull String packageName, @Nullable ProfileQueryParams options) {
try {
- Bundle optionsBundle = options == null
- ? ProfileQueryParams.DEFAULT.toBundle() : options.toBundle();
+ boolean includeParams = options == null || options.mParametersIncluded;
return mService.getPictureProfilesByPackage(
- packageName, optionsBundle, mUserHandle);
+ packageName, includeParams, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -321,9 +320,8 @@ public final class MediaQualityManager {
@NonNull
public List<PictureProfile> getAvailablePictureProfiles(@Nullable ProfileQueryParams options) {
try {
- Bundle optionsBundle = options == null
- ? ProfileQueryParams.DEFAULT.toBundle() : options.toBundle();
- return mService.getAvailablePictureProfiles(optionsBundle, mUserHandle);
+ boolean includeParams = options == null || options.mParametersIncluded;
+ return mService.getAvailablePictureProfiles(includeParams, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -344,7 +342,7 @@ public final class MediaQualityManager {
@RequiresPermission(android.Manifest.permission.MANAGE_GLOBAL_PICTURE_QUALITY_SERVICE)
public boolean setDefaultPictureProfile(@Nullable String pictureProfileId) {
try {
- return mService.setDefaultPictureProfile(pictureProfileId, mUserHandle);
+ return mService.setDefaultPictureProfile(pictureProfileId, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -361,7 +359,7 @@ public final class MediaQualityManager {
@RequiresPermission(android.Manifest.permission.MANAGE_GLOBAL_PICTURE_QUALITY_SERVICE)
public List<String> getPictureProfilePackageNames() {
try {
- return mService.getPictureProfilePackageNames(mUserHandle);
+ return mService.getPictureProfilePackageNames(mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -373,7 +371,7 @@ public final class MediaQualityManager {
*/
public List<PictureProfileHandle> getPictureProfileHandle(String[] id) {
try {
- return mService.getPictureProfileHandle(id, mUserHandle);
+ return mService.getPictureProfileHandle(id, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -385,7 +383,7 @@ public final class MediaQualityManager {
*/
public List<SoundProfileHandle> getSoundProfileHandle(String[] id) {
try {
- return mService.getSoundProfileHandle(id, mUserHandle);
+ return mService.getSoundProfileHandle(id, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -401,7 +399,7 @@ public final class MediaQualityManager {
*/
public void createPictureProfile(@NonNull PictureProfile pp) {
try {
- mService.createPictureProfile(pp, mUserHandle);
+ mService.createPictureProfile(pp, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -416,7 +414,7 @@ public final class MediaQualityManager {
*/
public void updatePictureProfile(@NonNull String profileId, @NonNull PictureProfile pp) {
try {
- mService.updatePictureProfile(profileId, pp, mUserHandle);
+ mService.updatePictureProfile(profileId, pp, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -430,7 +428,7 @@ public final class MediaQualityManager {
*/
public void removePictureProfile(@NonNull String profileId) {
try {
- mService.removePictureProfile(profileId, mUserHandle);
+ mService.removePictureProfile(profileId, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -484,9 +482,8 @@ public final class MediaQualityManager {
@NonNull String name,
@Nullable ProfileQueryParams options) {
try {
- Bundle optionsBundle = options == null
- ? ProfileQueryParams.DEFAULT.toBundle() : options.toBundle();
- return mService.getSoundProfile(type, name, optionsBundle, mUserHandle);
+ boolean includeParams = options == null || options.mParametersIncluded;
+ return mService.getSoundProfile(type, name, includeParams, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -510,9 +507,9 @@ public final class MediaQualityManager {
public List<SoundProfile> getSoundProfilesByPackage(
@NonNull String packageName, @Nullable ProfileQueryParams options) {
try {
- Bundle optionsBundle = options == null
- ? ProfileQueryParams.DEFAULT.toBundle() : options.toBundle();
- return mService.getSoundProfilesByPackage(packageName, optionsBundle, mUserHandle);
+ boolean includeParams = options == null || options.mParametersIncluded;
+ return mService.getSoundProfilesByPackage(
+ packageName, includeParams, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -531,9 +528,8 @@ public final class MediaQualityManager {
@NonNull
public List<SoundProfile> getAvailableSoundProfiles(@Nullable ProfileQueryParams options) {
try {
- Bundle optionsBundle = options == null
- ? ProfileQueryParams.DEFAULT.toBundle() : options.toBundle();
- return mService.getAvailableSoundProfiles(optionsBundle, mUserHandle);
+ boolean includeParams = options == null || options.mParametersIncluded;
+ return mService.getAvailableSoundProfiles(includeParams, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -554,7 +550,7 @@ public final class MediaQualityManager {
@RequiresPermission(android.Manifest.permission.MANAGE_GLOBAL_SOUND_QUALITY_SERVICE)
public boolean setDefaultSoundProfile(@Nullable String soundProfileId) {
try {
- return mService.setDefaultSoundProfile(soundProfileId, mUserHandle);
+ return mService.setDefaultSoundProfile(soundProfileId, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -572,7 +568,7 @@ public final class MediaQualityManager {
@RequiresPermission(android.Manifest.permission.MANAGE_GLOBAL_SOUND_QUALITY_SERVICE)
public List<String> getSoundProfilePackageNames() {
try {
- return mService.getSoundProfilePackageNames(mUserHandle);
+ return mService.getSoundProfilePackageNames(mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -589,7 +585,7 @@ public final class MediaQualityManager {
*/
public void createSoundProfile(@NonNull SoundProfile sp) {
try {
- mService.createSoundProfile(sp, mUserHandle);
+ mService.createSoundProfile(sp, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -604,7 +600,7 @@ public final class MediaQualityManager {
*/
public void updateSoundProfile(@NonNull String profileId, @NonNull SoundProfile sp) {
try {
- mService.updateSoundProfile(profileId, sp, mUserHandle);
+ mService.updateSoundProfile(profileId, sp, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -618,7 +614,7 @@ public final class MediaQualityManager {
*/
public void removeSoundProfile(@NonNull String profileId) {
try {
- mService.removeSoundProfile(profileId, mUserHandle);
+ mService.removeSoundProfile(profileId, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -636,7 +632,7 @@ public final class MediaQualityManager {
@NonNull
public List<ParameterCapability> getParameterCapabilities(@NonNull List<String> names) {
try {
- return mService.getParameterCapabilities(names, mUserHandle);
+ return mService.getParameterCapabilities(names, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -654,7 +650,7 @@ public final class MediaQualityManager {
@NonNull
public List<String> getPictureProfileAllowList() {
try {
- return mService.getPictureProfileAllowList(mUserHandle);
+ return mService.getPictureProfileAllowList(mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -668,7 +664,7 @@ public final class MediaQualityManager {
@RequiresPermission(android.Manifest.permission.MANAGE_GLOBAL_PICTURE_QUALITY_SERVICE)
public void setPictureProfileAllowList(@NonNull List<String> packageNames) {
try {
- mService.setPictureProfileAllowList(packageNames, mUserHandle);
+ mService.setPictureProfileAllowList(packageNames, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -686,7 +682,7 @@ public final class MediaQualityManager {
@NonNull
public List<String> getSoundProfileAllowList() {
try {
- return mService.getSoundProfileAllowList(mUserHandle);
+ return mService.getSoundProfileAllowList(mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -700,7 +696,7 @@ public final class MediaQualityManager {
@RequiresPermission(android.Manifest.permission.MANAGE_GLOBAL_SOUND_QUALITY_SERVICE)
public void setSoundProfileAllowList(@NonNull List<String> packageNames) {
try {
- mService.setSoundProfileAllowList(packageNames, mUserHandle);
+ mService.setSoundProfileAllowList(packageNames, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -712,7 +708,7 @@ public final class MediaQualityManager {
*/
public boolean isSupported() {
try {
- return mService.isSupported(mUserHandle);
+ return mService.isSupported(mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -730,7 +726,7 @@ public final class MediaQualityManager {
@RequiresPermission(android.Manifest.permission.MANAGE_GLOBAL_PICTURE_QUALITY_SERVICE)
public void setAutoPictureQualityEnabled(boolean enabled) {
try {
- mService.setAutoPictureQualityEnabled(enabled, mUserHandle);
+ mService.setAutoPictureQualityEnabled(enabled, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -741,7 +737,7 @@ public final class MediaQualityManager {
*/
public boolean isAutoPictureQualityEnabled() {
try {
- return mService.isAutoPictureQualityEnabled(mUserHandle);
+ return mService.isAutoPictureQualityEnabled(mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -758,7 +754,7 @@ public final class MediaQualityManager {
@RequiresPermission(android.Manifest.permission.MANAGE_GLOBAL_PICTURE_QUALITY_SERVICE)
public void setSuperResolutionEnabled(boolean enabled) {
try {
- mService.setSuperResolutionEnabled(enabled, mUserHandle);
+ mService.setSuperResolutionEnabled(enabled, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -769,7 +765,7 @@ public final class MediaQualityManager {
*/
public boolean isSuperResolutionEnabled() {
try {
- return mService.isSuperResolutionEnabled(mUserHandle);
+ return mService.isSuperResolutionEnabled(mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -787,7 +783,7 @@ public final class MediaQualityManager {
@RequiresPermission(android.Manifest.permission.MANAGE_GLOBAL_SOUND_QUALITY_SERVICE)
public void setAutoSoundQualityEnabled(boolean enabled) {
try {
- mService.setAutoSoundQualityEnabled(enabled, mUserHandle);
+ mService.setAutoSoundQualityEnabled(enabled, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -798,7 +794,7 @@ public final class MediaQualityManager {
*/
public boolean isAutoSoundQualityEnabled() {
try {
- return mService.isAutoSoundQualityEnabled(mUserHandle);
+ return mService.isAutoSoundQualityEnabled(mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -847,7 +843,7 @@ public final class MediaQualityManager {
@NonNull AmbientBacklightSettings settings) {
Preconditions.checkNotNull(settings);
try {
- mService.setAmbientBacklightSettings(settings, mUserHandle);
+ mService.setAmbientBacklightSettings(settings, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -858,7 +854,7 @@ public final class MediaQualityManager {
*/
public boolean isAmbientBacklightEnabled() {
try {
- return mService.isAmbientBacklightEnabled(mUserHandle);
+ return mService.isAmbientBacklightEnabled(mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -872,7 +868,7 @@ public final class MediaQualityManager {
@RequiresPermission(android.Manifest.permission.READ_COLOR_ZONES)
public void setAmbientBacklightEnabled(boolean enabled) {
try {
- mService.setAmbientBacklightEnabled(enabled, mUserHandle);
+ mService.setAmbientBacklightEnabled(enabled, mUserHandle.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/media/java/android/media/quality/SoundProfileHandle.java b/media/java/android/media/quality/SoundProfileHandle.java
deleted file mode 100644
index edb546efdaf3..000000000000
--- a/media/java/android/media/quality/SoundProfileHandle.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.quality;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * A type-safe handle to a sound profile.
- *
- * @hide
- */
-public final class SoundProfileHandle implements Parcelable {
- public static final @NonNull SoundProfileHandle NONE = new SoundProfileHandle(-1000);
-
- private final long mId;
-
- /** @hide */
- public SoundProfileHandle(long id) {
- mId = id;
- }
-
- /** @hide */
- public long getId() {
- return mId;
- }
-
- /** @hide */
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeLong(mId);
- }
-
- /** @hide */
- @Override
- public int describeContents() {
- return 0;
- }
-
- /** @hide */
- public static final @NonNull Creator<SoundProfileHandle> CREATOR =
- new Creator<SoundProfileHandle>() {
- @Override
- public SoundProfileHandle createFromParcel(Parcel in) {
- return new SoundProfileHandle(in);
- }
-
- @Override
- public SoundProfileHandle[] newArray(int size) {
- return new SoundProfileHandle[size];
- }
- };
-
- private SoundProfileHandle(@NonNull Parcel in) {
- mId = in.readLong();
- }
-}
diff --git a/media/java/android/media/quality/ActiveProcessingPicture.aidl b/media/java/android/media/quality/aidl/android/media/quality/ActiveProcessingPicture.aidl
index 2851306f6e4d..2851306f6e4d 100644
--- a/media/java/android/media/quality/ActiveProcessingPicture.aidl
+++ b/media/java/android/media/quality/aidl/android/media/quality/ActiveProcessingPicture.aidl
diff --git a/media/java/android/media/quality/AmbientBacklightEvent.aidl b/media/java/android/media/quality/aidl/android/media/quality/AmbientBacklightEvent.aidl
index 174cd461e846..174cd461e846 100644
--- a/media/java/android/media/quality/AmbientBacklightEvent.aidl
+++ b/media/java/android/media/quality/aidl/android/media/quality/AmbientBacklightEvent.aidl
diff --git a/media/java/android/media/quality/AmbientBacklightMetadata.aidl b/media/java/android/media/quality/aidl/android/media/quality/AmbientBacklightMetadata.aidl
index b95a474fbf90..b95a474fbf90 100644
--- a/media/java/android/media/quality/AmbientBacklightMetadata.aidl
+++ b/media/java/android/media/quality/aidl/android/media/quality/AmbientBacklightMetadata.aidl
diff --git a/media/java/android/media/quality/AmbientBacklightSettings.aidl b/media/java/android/media/quality/aidl/android/media/quality/AmbientBacklightSettings.aidl
index e2cdd03194cd..e2cdd03194cd 100644
--- a/media/java/android/media/quality/AmbientBacklightSettings.aidl
+++ b/media/java/android/media/quality/aidl/android/media/quality/AmbientBacklightSettings.aidl
diff --git a/media/java/android/media/quality/IAmbientBacklightCallback.aidl b/media/java/android/media/quality/aidl/android/media/quality/IAmbientBacklightCallback.aidl
index 159f5b7b5e71..159f5b7b5e71 100644
--- a/media/java/android/media/quality/IAmbientBacklightCallback.aidl
+++ b/media/java/android/media/quality/aidl/android/media/quality/IAmbientBacklightCallback.aidl
diff --git a/media/java/android/media/quality/IMediaQualityManager.aidl b/media/java/android/media/quality/aidl/android/media/quality/IMediaQualityManager.aidl
index 6e9fa1dcf93d..0191ea786de0 100644
--- a/media/java/android/media/quality/IMediaQualityManager.aidl
+++ b/media/java/android/media/quality/aidl/android/media/quality/IMediaQualityManager.aidl
@@ -25,57 +25,57 @@ import android.media.quality.PictureProfileHandle;
import android.media.quality.PictureProfile;
import android.media.quality.SoundProfileHandle;
import android.media.quality.SoundProfile;
-import android.os.Bundle;
-import android.os.UserHandle;
/**
* Interface for Media Quality Manager
* @hide
*/
interface IMediaQualityManager {
- PictureProfile createPictureProfile(in PictureProfile pp, in UserHandle user);
- void updatePictureProfile(in String id, in PictureProfile pp, in UserHandle user);
- void removePictureProfile(in String id, in UserHandle user);
- boolean setDefaultPictureProfile(in String id, in UserHandle user);
+ // TODO: use UserHandle
+ PictureProfile createPictureProfile(in PictureProfile pp, int userId);
+ void updatePictureProfile(in String id, in PictureProfile pp, int userId);
+ void removePictureProfile(in String id, int userId);
+ boolean setDefaultPictureProfile(in String id, int userId);
+ // TODO: use Bundle for includeParams
PictureProfile getPictureProfile(
- in int type, in String name, in Bundle options, in UserHandle user);
+ in int type, in String name, in boolean includeParams, int userId);
List<PictureProfile> getPictureProfilesByPackage(
- in String packageName, in Bundle options, in UserHandle user);
- List<PictureProfile> getAvailablePictureProfiles(in Bundle options, in UserHandle user);
- List<String> getPictureProfilePackageNames(in UserHandle user);
- List<String> getPictureProfileAllowList(in UserHandle user);
- void setPictureProfileAllowList(in List<String> packages, in UserHandle user);
- List<PictureProfileHandle> getPictureProfileHandle(in String[] id, in UserHandle user);
+ in String packageName, in boolean includeParams, int userId);
+ List<PictureProfile> getAvailablePictureProfiles(in boolean includeParams, int userId);
+ List<String> getPictureProfilePackageNames(int userId);
+ List<String> getPictureProfileAllowList(int userId);
+ void setPictureProfileAllowList(in List<String> packages, int userId);
+ List<PictureProfileHandle> getPictureProfileHandle(in String[] id, int userId);
- SoundProfile createSoundProfile(in SoundProfile pp, in UserHandle user);
- void updateSoundProfile(in String id, in SoundProfile pp, in UserHandle user);
- void removeSoundProfile(in String id, in UserHandle user);
- boolean setDefaultSoundProfile(in String id, in UserHandle user);
+ SoundProfile createSoundProfile(in SoundProfile pp, int userId);
+ void updateSoundProfile(in String id, in SoundProfile pp, int userId);
+ void removeSoundProfile(in String id, int userId);
+ boolean setDefaultSoundProfile(in String id, int userId);
SoundProfile getSoundProfile(
- in int type, in String name, in Bundle options, in UserHandle user);
+ in int type, in String name, in boolean includeParams, int userId);
List<SoundProfile> getSoundProfilesByPackage(
- in String packageName, in Bundle options, in UserHandle user);
- List<SoundProfile> getAvailableSoundProfiles(in Bundle options, in UserHandle user);
- List<String> getSoundProfilePackageNames(in UserHandle user);
- List<String> getSoundProfileAllowList(in UserHandle user);
- void setSoundProfileAllowList(in List<String> packages, in UserHandle user);
- List<SoundProfileHandle> getSoundProfileHandle(in String[] id, in UserHandle user);
+ in String packageName, in boolean includeParams, int userId);
+ List<SoundProfile> getAvailableSoundProfiles(in boolean includeParams, int userId);
+ List<String> getSoundProfilePackageNames(int userId);
+ List<String> getSoundProfileAllowList(int userId);
+ void setSoundProfileAllowList(in List<String> packages, int userId);
+ List<SoundProfileHandle> getSoundProfileHandle(in String[] id, int userId);
void registerPictureProfileCallback(in IPictureProfileCallback cb);
void registerSoundProfileCallback(in ISoundProfileCallback cb);
void registerAmbientBacklightCallback(in IAmbientBacklightCallback cb);
- List<ParameterCapability> getParameterCapabilities(in List<String> names, in UserHandle user);
+ List<ParameterCapability> getParameterCapabilities(in List<String> names, int userId);
- boolean isSupported(in UserHandle user);
- void setAutoPictureQualityEnabled(in boolean enabled, in UserHandle user);
- boolean isAutoPictureQualityEnabled(in UserHandle user);
- void setSuperResolutionEnabled(in boolean enabled, in UserHandle user);
- boolean isSuperResolutionEnabled(in UserHandle user);
- void setAutoSoundQualityEnabled(in boolean enabled, in UserHandle user);
- boolean isAutoSoundQualityEnabled(in UserHandle user);
+ boolean isSupported(int userId);
+ void setAutoPictureQualityEnabled(in boolean enabled, int userId);
+ boolean isAutoPictureQualityEnabled(int userId);
+ void setSuperResolutionEnabled(in boolean enabled, int userId);
+ boolean isSuperResolutionEnabled(int userId);
+ void setAutoSoundQualityEnabled(in boolean enabled, int userId);
+ boolean isAutoSoundQualityEnabled(int userId);
- void setAmbientBacklightSettings(in AmbientBacklightSettings settings, in UserHandle user);
- void setAmbientBacklightEnabled(in boolean enabled, in UserHandle user);
- boolean isAmbientBacklightEnabled(in UserHandle user);
+ void setAmbientBacklightSettings(in AmbientBacklightSettings settings, int userId);
+ void setAmbientBacklightEnabled(in boolean enabled, int userId);
+ boolean isAmbientBacklightEnabled(int userId);
}
diff --git a/media/java/android/media/quality/IPictureProfileCallback.aidl b/media/java/android/media/quality/aidl/android/media/quality/IPictureProfileCallback.aidl
index eed77f695416..eed77f695416 100644
--- a/media/java/android/media/quality/IPictureProfileCallback.aidl
+++ b/media/java/android/media/quality/aidl/android/media/quality/IPictureProfileCallback.aidl
diff --git a/media/java/android/media/quality/ISoundProfileCallback.aidl b/media/java/android/media/quality/aidl/android/media/quality/ISoundProfileCallback.aidl
index 3871fb212259..3871fb212259 100644
--- a/media/java/android/media/quality/ISoundProfileCallback.aidl
+++ b/media/java/android/media/quality/aidl/android/media/quality/ISoundProfileCallback.aidl
diff --git a/media/java/android/media/quality/ParameterCapability.aidl b/media/java/android/media/quality/aidl/android/media/quality/ParameterCapability.aidl
index eb2ac97916f3..eb2ac97916f3 100644
--- a/media/java/android/media/quality/ParameterCapability.aidl
+++ b/media/java/android/media/quality/aidl/android/media/quality/ParameterCapability.aidl
diff --git a/media/java/android/media/quality/PictureProfile.aidl b/media/java/android/media/quality/aidl/android/media/quality/PictureProfile.aidl
index 41d018b12f33..41d018b12f33 100644
--- a/media/java/android/media/quality/PictureProfile.aidl
+++ b/media/java/android/media/quality/aidl/android/media/quality/PictureProfile.aidl
diff --git a/media/java/android/media/quality/PictureProfileHandle.aidl b/media/java/android/media/quality/aidl/android/media/quality/PictureProfileHandle.aidl
index 5d14631dbb73..5d14631dbb73 100644
--- a/media/java/android/media/quality/PictureProfileHandle.aidl
+++ b/media/java/android/media/quality/aidl/android/media/quality/PictureProfileHandle.aidl
diff --git a/media/java/android/media/quality/SoundProfile.aidl b/media/java/android/media/quality/aidl/android/media/quality/SoundProfile.aidl
index e79fcaac97be..e79fcaac97be 100644
--- a/media/java/android/media/quality/SoundProfile.aidl
+++ b/media/java/android/media/quality/aidl/android/media/quality/SoundProfile.aidl
diff --git a/media/java/android/media/quality/SoundProfileHandle.aidl b/media/java/android/media/quality/aidl/android/media/quality/SoundProfileHandle.aidl
index 6b8161c8cc43..ea26b19d84d7 100644
--- a/media/java/android/media/quality/SoundProfileHandle.aidl
+++ b/media/java/android/media/quality/aidl/android/media/quality/SoundProfileHandle.aidl
@@ -16,4 +16,7 @@
package android.media.quality;
-parcelable SoundProfileHandle;
+// TODO: add SoundProfileHandle.java
+parcelable SoundProfileHandle {
+ long id;
+}
diff --git a/packages/SettingsLib/RestrictedLockUtils/res/values/strings.xml b/packages/SettingsLib/RestrictedLockUtils/res/values/strings.xml
index 75809730a514..2ffdc930ccea 100644
--- a/packages/SettingsLib/RestrictedLockUtils/res/values/strings.xml
+++ b/packages/SettingsLib/RestrictedLockUtils/res/values/strings.xml
@@ -21,8 +21,4 @@
<string name="enabled_by_admin">Enabled by admin</string>
<!-- Summary for switch preference to denote it is switched off by an admin [CHAR LIMIT=50] -->
<string name="disabled_by_admin">Disabled by admin</string>
- <!-- Summary for switch preference to denote it is switched on by Advanced protection [CHAR LIMIT=50] -->
- <string name="enabled_by_advanced_protection">Enabled by Advanced Protection</string>
- <!-- Summary for switch preference to denote it is switched off by Advanced protection [CHAR LIMIT=50] -->
- <string name="disabled_by_advanced_protection">Disabled by Advanced Protection</string>
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictedMode.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictedMode.kt
index a8483308556d..6f37f0cc5799 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictedMode.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictedMode.kt
@@ -46,7 +46,7 @@ internal data class BlockedByAdminImpl(
) : BlockedByAdmin {
override fun getSummary(checked: Boolean?) = when (checked) {
true -> enterpriseRepository.getAdminSummaryString(
- advancedProtectionStringId = R.string.enabled_by_advanced_protection,
+ advancedProtectionStringId = com.android.settingslib.R.string.enabled,
updatableStringId = Settings.ENABLED_BY_ADMIN_SWITCH_SUMMARY,
resId = R.string.enabled_by_admin,
enforcedAdmin = enforcedAdmin,
@@ -54,7 +54,7 @@ internal data class BlockedByAdminImpl(
)
false -> enterpriseRepository.getAdminSummaryString(
- advancedProtectionStringId = R.string.disabled_by_advanced_protection,
+ advancedProtectionStringId = com.android.settingslib.R.string.disabled,
updatableStringId = Settings.DISABLED_BY_ADMIN_SWITCH_SUMMARY,
resId = R.string.disabled_by_admin,
enforcedAdmin = enforcedAdmin,
diff --git a/packages/SettingsLib/SpaPrivileged/tests/unit/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictedModeTest.kt b/packages/SettingsLib/SpaPrivileged/tests/unit/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictedModeTest.kt
index f3245c9085e7..189bf363420c 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/unit/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictedModeTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/unit/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictedModeTest.kt
@@ -77,8 +77,8 @@ class RestrictedModeTest {
if (RestrictedLockUtilsInternal.isPolicyEnforcedByAdvancedProtection(context,
RESTRICTION, userId)) {
return when (advancedProtectionStringId) {
- R.string.enabled_by_advanced_protection -> ENABLED_BY_ADVANCED_PROTECTION
- R.string.disabled_by_advanced_protection -> DISABLED_BY_ADVANCED_PROTECTION
+ com.android.settingslib.R.string.enabled -> ENABLED
+ com.android.settingslib.R.string.disabled -> DISABLED
else -> ""
}
}
@@ -129,7 +129,7 @@ class RestrictedModeTest {
val summary = blockedByAdmin.getSummary(true)
- assertThat(summary).isEqualTo(ENABLED_BY_ADVANCED_PROTECTION)
+ assertThat(summary).isEqualTo(ENABLED)
}
@RequiresFlagsEnabled(Flags.FLAG_AAPM_API)
@@ -148,7 +148,7 @@ class RestrictedModeTest {
val summary = blockedByAdmin.getSummary(false)
- assertThat(summary).isEqualTo(DISABLED_BY_ADVANCED_PROTECTION)
+ assertThat(summary).isEqualTo(DISABLED)
}
@RequiresFlagsEnabled(Flags.FLAG_AAPM_API)
@@ -202,7 +202,7 @@ class RestrictedModeTest {
const val ENABLED_BY_ADMIN = "Enabled by admin"
const val DISABLED_BY_ADMIN = "Disabled by admin"
- const val ENABLED_BY_ADVANCED_PROTECTION = "Enabled by advanced protection"
- const val DISABLED_BY_ADVANCED_PROTECTION = "Disabled by advanced protection"
+ const val ENABLED = "Enabled"
+ const val DISABLED = "Disabled"
}
}
diff --git a/packages/SettingsLib/SpaPrivileged/tests/unit/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPageTest.kt b/packages/SettingsLib/SpaPrivileged/tests/unit/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPageTest.kt
index 79085af63c6d..308b285e0cfc 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/unit/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPageTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/unit/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPageTest.kt
@@ -175,13 +175,7 @@ class TogglePermissionAppListPageTest {
val summary = getSummary(listModel)
- assertThat(summary)
- .isEqualTo(
- context.getString(
- com.android.settingslib.widget.restricted.R.string
- .disabled_by_advanced_protection
- )
- )
+ assertThat(summary).isEqualTo(context.getString(com.android.settingslib.R.string.disabled))
}
@RequiresFlagsEnabled(Flags.FLAG_AAPM_API)
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 91ec83690722..03cb1ffbdef1 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1263,6 +1263,8 @@
<!-- [CHAR LIMIT=25] Manage applications, text telling using an application is disabled. -->
<string name="disabled">Disabled</string>
+ <!-- Summary for a settings preference indicating it is enabled [CHAR LIMIT = 30] -->
+ <string name="enabled">Enabled</string>
<!-- Summary of app trusted to install apps [CHAR LIMIT=45] -->
<string name="external_source_trusted">Allowed</string>
<!-- Summary of app not trusted to install apps [CHAR LIMIT=45] -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
index 1044750bae25..9d979019be58 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
@@ -120,7 +120,7 @@ public class RestrictedPreferenceHelper {
final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
if (summaryView != null) {
final CharSequence disabledText = getDisabledByAdminSummaryString();
- if (mDisabledByAdmin) {
+ if (mDisabledByAdmin && disabledText != null) {
summaryView.setText(disabledText);
} else if (mDisabledByEcm) {
summaryView.setText(getEcmTextResId());
@@ -132,10 +132,10 @@ public class RestrictedPreferenceHelper {
}
}
- private String getDisabledByAdminSummaryString() {
+ private @Nullable String getDisabledByAdminSummaryString() {
if (isRestrictionEnforcedByAdvancedProtection()) {
- return mContext.getString(com.android.settingslib.widget.restricted
- .R.string.disabled_by_advanced_protection);
+ // Advanced Protection doesn't set the summary string, it keeps the current summary.
+ return null;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
return mContext.getSystemService(DevicePolicyManager.class).getResources().getString(
@@ -321,7 +321,10 @@ public class RestrictedPreferenceHelper {
}
if (android.security.Flags.aapmApi() && !isEnabled && mDisabledByAdmin) {
- mPreference.setSummary(getDisabledByAdminSummaryString());
+ String summary = getDisabledByAdminSummaryString();
+ if (summary != null) {
+ mPreference.setSummary(summary);
+ }
}
if (!isEnabled && mDisabledByEcm) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
index a5fa6a854e97..67c4207cb8be 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
@@ -36,6 +36,7 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceViewHolder;
@@ -141,7 +142,7 @@ public class RestrictedSwitchPreference extends SwitchPreferenceCompat implement
final TextView additionalSummaryView = (TextView) holder.findViewById(
R.id.additional_summary);
if (additionalSummaryView != null) {
- if (isDisabledByAdmin()) {
+ if (isDisabledByAdmin() && switchSummary != null) {
additionalSummaryView.setText(switchSummary);
additionalSummaryView.setVisibility(View.VISIBLE);
} else {
@@ -151,7 +152,7 @@ public class RestrictedSwitchPreference extends SwitchPreferenceCompat implement
} else {
final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
if (summaryView != null) {
- if (isDisabledByAdmin()) {
+ if (isDisabledByAdmin() && switchSummary != null) {
summaryView.setText(switchSummary);
summaryView.setVisibility(View.VISIBLE);
}
@@ -171,14 +172,10 @@ public class RestrictedSwitchPreference extends SwitchPreferenceCompat implement
() -> context.getString(resId));
}
- private String getRestrictedSwitchSummary() {
+ private @Nullable String getRestrictedSwitchSummary() {
if (mHelper.isRestrictionEnforcedByAdvancedProtection()) {
- final int apmResId = isChecked()
- ? com.android.settingslib.widget.restricted.R.string
- .enabled_by_advanced_protection
- : com.android.settingslib.widget.restricted.R.string
- .disabled_by_advanced_protection;
- return getContext().getString(apmResId);
+ // Advanced Protection doesn't set the summary string, it keeps the current summary.
+ return null;
}
return isChecked()
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java
index dbbbd5bf8089..f9769fa61e0d 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java
@@ -23,6 +23,7 @@ import static com.google.common.truth.Truth.assertWithMessage;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.atMostOnce;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -130,7 +131,7 @@ public class RestrictedPreferenceHelperTest {
@RequiresFlagsEnabled(android.security.Flags.FLAG_AAPM_API)
@Test
- public void bindPreference_disabled_byAdvancedProtection_shouldDisplayDisabledSummary() {
+ public void bindPreference_disabled_byAdvancedProtection_shouldKeepExistingSummary() {
final TextView summaryView = mock(TextView.class, RETURNS_DEEP_STUBS);
final String userRestriction = UserManager.DISALLOW_UNINSTALL_APPS;
final RestrictedLockUtils.EnforcedAdmin enforcedAdmin = new RestrictedLockUtils
@@ -143,16 +144,14 @@ public class RestrictedPreferenceHelperTest {
.thenReturn(summaryView);
when(mDevicePolicyManager.getEnforcingAdmin(UserHandle.myUserId(), userRestriction))
.thenReturn(advancedProtectionEnforcingAdmin);
- when(mContext.getString(
- com.android.settingslib.widget.restricted.R.string.disabled_by_advanced_protection))
- .thenReturn("advanced_protection");
+ summaryView.setText("existing summary");
mHelper.useAdminDisabledSummary(true);
mHelper.setDisabledByAdmin(enforcedAdmin);
mHelper.onBindViewHolder(mViewHolder);
- verify(summaryView).setText("advanced_protection");
- verify(summaryView, never()).setVisibility(View.GONE);
+ verify(summaryView, atMostOnce()).setText(any()); // To set it to existing summary
+ verify(summaryView, never()).setVisibility(View.VISIBLE);
}
@RequiresFlagsEnabled(android.security.Flags.FLAG_AAPM_API)
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 8e2f02ad55ac..f0a0483aa17c 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -294,5 +294,7 @@ public class SecureSettings {
Settings.Secure.FINGERPRINT_APP_ENABLED,
Settings.Secure.FINGERPRINT_KEYGUARD_ENABLED,
Settings.Secure.DUAL_SHADE,
+ Settings.Secure.BROWSER_CONTENT_FILTERS_ENABLED,
+ Settings.Secure.SEARCH_CONTENT_FILTERS_ENABLED,
};
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 0fd51a7c35ab..b5de7e719043 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -462,5 +462,7 @@ public class SecureSettingsValidators {
VALIDATORS.put(Secure.FINGERPRINT_APP_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.FINGERPRINT_KEYGUARD_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.DUAL_SHADE, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Secure.BROWSER_CONTENT_FILTERS_ENABLED, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Secure.SEARCH_CONTENT_FILTERS_ENABLED, BOOLEAN_VALIDATOR);
}
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/GSFAxes.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/GSFAxes.kt
index 96feeedb8793..e734dd26eb15 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/GSFAxes.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/GSFAxes.kt
@@ -25,6 +25,7 @@ data class AxisDefinition(
)
object GSFAxes {
+ @JvmStatic
val WEIGHT =
AxisDefinition(
tag = "wght",
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
index 5b073e49192a..4a39cff388a9 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
@@ -39,6 +39,7 @@ interface TypefaceVariantCache {
fun getTypefaceForVariant(fvar: String?): Typeface?
companion object {
+ @JvmStatic
fun createVariantTypeface(baseTypeface: Typeface, fVar: String?): Typeface {
if (fVar.isNullOrEmpty()) {
return baseTypeface
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ComposedDigitalLayerController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ComposedDigitalLayerController.kt
index e9e61a718f08..37acbe261f76 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ComposedDigitalLayerController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ComposedDigitalLayerController.kt
@@ -161,15 +161,7 @@ class ComposedDigitalLayerController(private val clockCtx: ClockContext) :
}
override fun onThemeChanged(theme: ThemeConfig) {
- val color =
- when {
- theme.seedColor != null -> theme.seedColor!!
- theme.isDarkTheme ->
- clockCtx.resources.getColor(android.R.color.system_accent1_100)
- else -> clockCtx.resources.getColor(android.R.color.system_accent2_600)
- }
-
- view.updateColor(color)
+ view.updateColor(theme.getDefaultColor(clockCtx.context))
}
override fun onFontSettingChanged(fontSizePx: Float) {
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
index 365567b17ec0..bc4bdf4243cb 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
@@ -149,14 +149,7 @@ class DefaultClockController(
override fun onThemeChanged(theme: ThemeConfig) {
this@DefaultClockFaceController.theme = theme
- val color =
- when {
- theme.seedColor != null -> theme.seedColor!!
- theme.isDarkTheme ->
- resources.getColor(android.R.color.system_accent1_100)
- else -> resources.getColor(android.R.color.system_accent2_600)
- }
-
+ val color = theme.getDefaultColor(ctx)
if (currentColor == color) {
return
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleDigitalHandLayerController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleDigitalHandLayerController.kt
index 97004ef6f9a9..1d963af3ad22 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleDigitalHandLayerController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleDigitalHandLayerController.kt
@@ -229,15 +229,7 @@ open class SimpleDigitalHandLayerController(
}
override fun onThemeChanged(theme: ThemeConfig) {
- val color =
- when {
- theme.seedColor != null -> theme.seedColor!!
- theme.isDarkTheme ->
- clockCtx.resources.getColor(android.R.color.system_accent1_100)
- else -> clockCtx.resources.getColor(android.R.color.system_accent2_600)
- }
-
- view.updateColor(color)
+ view.updateColor(theme.getDefaultColor(clockCtx.context))
refreshTime()
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt
index fae17a5321ff..0ec2d188833a 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt
@@ -45,6 +45,7 @@ import com.android.systemui.plugins.clocks.ClockFontAxisSetting
import com.android.systemui.plugins.clocks.ClockFontAxisSetting.Companion.replace
import com.android.systemui.plugins.clocks.ClockFontAxisSetting.Companion.toFVar
import com.android.systemui.plugins.clocks.ClockLogger
+import com.android.systemui.shared.Flags.ambientAod
import com.android.systemui.shared.clocks.CanvasUtil.translate
import com.android.systemui.shared.clocks.CanvasUtil.use
import com.android.systemui.shared.clocks.ClockContext
@@ -330,7 +331,7 @@ open class SimpleDigitalClockTextView(
textAnimator.setTextStyle(
TextAnimator.Style(
fVar = if (isDozing) aodFontVariation else lsFontVariation,
- color = if (isDozing) AOD_COLOR else lockscreenColor,
+ color = if (isDozing && !ambientAod()) AOD_COLOR else lockscreenColor,
textSize = if (isDozing) aodFontSizePx else lockScreenPaint.textSize,
),
TextAnimator.Animation(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt
index e0515000b232..454c15667f22 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt
@@ -56,6 +56,7 @@ import com.android.systemui.statusbar.phone.dozeScrimController
import com.android.systemui.statusbar.phone.screenOffAnimationController
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.advanceTimeBy
@@ -105,7 +106,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() {
@Test
fun nonPowerButtonFPS_vibrateSuccess() =
testScope.runTest {
- val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)
+ val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry)
enrollFingerprint(FingerprintSensorType.UDFPS_ULTRASONIC)
runCurrent()
enterDeviceFromFingerprintUnlockLegacy()
@@ -116,7 +117,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() {
@Test
fun powerButtonFPS_vibrateSuccess() =
testScope.runTest {
- val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)
+ val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry)
enrollFingerprint(FingerprintSensorType.POWER_BUTTON)
kosmos.fakeKeyEventRepository.setPowerButtonDown(false)
@@ -133,7 +134,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() {
@Test
fun powerButtonFPS_powerDown_doNotVibrateSuccess() =
testScope.runTest {
- val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)
+ val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry)
enrollFingerprint(FingerprintSensorType.POWER_BUTTON)
kosmos.fakeKeyEventRepository.setPowerButtonDown(true) // power button is currently DOWN
@@ -150,7 +151,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() {
@Test
fun powerButtonFPS_powerButtonRecentlyPressed_doNotVibrateSuccess() =
testScope.runTest {
- val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)
+ val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry)
enrollFingerprint(FingerprintSensorType.POWER_BUTTON)
kosmos.fakeKeyEventRepository.setPowerButtonDown(false)
@@ -174,14 +175,14 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() {
}
@Test
- fun nonPowerButtonFPS_coExFaceFailure_vibrateError() =
+ fun nonPowerButtonFPS_coExFaceFailure_doNotVibrateError() =
testScope.runTest {
val playErrorHaptic by collectLastValue(underTest.playErrorHaptic)
enrollFingerprint(FingerprintSensorType.UDFPS_ULTRASONIC)
enrollFace()
runCurrent()
faceFailure()
- assertThat(playErrorHaptic).isNotNull()
+ assertThat(playErrorHaptic).isNull()
}
@Test
@@ -211,7 +212,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() {
testScope.runTest {
kosmos.configureKeyguardBypass(isBypassAvailable = false)
underTest = kosmos.deviceEntryHapticsInteractor
- val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)
+ val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry)
enrollFingerprint(FingerprintSensorType.UDFPS_ULTRASONIC)
runCurrent()
configureDeviceEntryFromBiometricSource(isFpUnlock = true)
@@ -225,7 +226,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() {
testScope.runTest {
kosmos.configureKeyguardBypass(isBypassAvailable = false)
underTest = kosmos.deviceEntryHapticsInteractor
- val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)
+ val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry)
enrollFingerprint(FingerprintSensorType.POWER_BUTTON)
kosmos.fakeKeyEventRepository.setPowerButtonDown(false)
@@ -246,18 +247,19 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() {
enrollFace()
kosmos.configureKeyguardBypass(isBypassAvailable = true)
underTest = kosmos.deviceEntryHapticsInteractor
- val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)
+ val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry)
configureDeviceEntryFromBiometricSource(isFaceUnlock = true)
verifyDeviceEntryFromFaceAuth()
assertThat(playSuccessHaptic).isNotNull()
}
+ @OptIn(ExperimentalCoroutinesApi::class)
@EnableSceneContainer
@Test
- fun playSuccessHaptic_onFaceAuthSuccess_whenBypassDisabled_sceneContainer() =
+ fun skipSuccessHaptic_onFaceAuthSuccess_whenBypassDisabled_sceneContainer() =
testScope.runTest {
underTest = kosmos.deviceEntryHapticsInteractor
- val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)
+ val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry)
enrollFace()
kosmos.configureKeyguardBypass(isBypassAvailable = false)
@@ -265,7 +267,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() {
configureDeviceEntryFromBiometricSource(isFaceUnlock = true, bypassEnabled = false)
kosmos.fakeDeviceEntryFaceAuthRepository.isAuthenticated.value = true
- assertThat(playSuccessHaptic).isNotNull()
+ assertThat(playSuccessHaptic).isNull()
}
@EnableSceneContainer
@@ -274,7 +276,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() {
testScope.runTest {
kosmos.configureKeyguardBypass(isBypassAvailable = false)
underTest = kosmos.deviceEntryHapticsInteractor
- val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)
+ val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry)
enrollFingerprint(FingerprintSensorType.POWER_BUTTON)
// power button is currently DOWN
kosmos.fakeKeyEventRepository.setPowerButtonDown(true)
@@ -295,7 +297,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() {
testScope.runTest {
kosmos.configureKeyguardBypass(isBypassAvailable = false)
underTest = kosmos.deviceEntryHapticsInteractor
- val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)
+ val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry)
enrollFingerprint(FingerprintSensorType.POWER_BUTTON)
kosmos.fakeKeyEventRepository.setPowerButtonDown(false)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/log/LogWtfHandlerRuleTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/log/LogWtfHandlerRuleTest.kt
new file mode 100644
index 000000000000..d5d256e5cd97
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/log/LogWtfHandlerRuleTest.kt
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log
+
+import android.util.Log
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.model.Statement
+import org.mockito.kotlin.mock
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class LogWtfHandlerRuleTest : SysuiTestCase() {
+
+ val underTest = LogWtfHandlerRule()
+
+ @Test
+ fun passingTestWithoutWtf_shouldPass() {
+ val result = runTestCodeWithRule {
+ Log.e(TAG, "just an error", IndexOutOfBoundsException())
+ }
+ assertThat(result.isSuccess).isTrue()
+ }
+
+ @Test
+ fun passingTestWithWtf_shouldFail() {
+ val result = runTestCodeWithRule {
+ Log.wtf(TAG, "some terrible failure", IllegalStateException())
+ }
+ assertThat(result.isFailure).isTrue()
+ val exception = result.exceptionOrNull()
+ assertThat(exception).isInstanceOf(AssertionError::class.java)
+ assertThat(exception?.cause).isInstanceOf(Log.TerribleFailure::class.java)
+ assertThat(exception?.cause?.cause).isInstanceOf(IllegalStateException::class.java)
+ }
+
+ @Test
+ fun failingTestWithoutWtf_shouldFail() {
+ val result = runTestCodeWithRule {
+ Log.e(TAG, "just an error", IndexOutOfBoundsException())
+ throw NullPointerException("some npe")
+ }
+ assertThat(result.isFailure).isTrue()
+ assertThat(result.exceptionOrNull()).isInstanceOf(NullPointerException::class.java)
+ }
+
+ @Test
+ fun failingTestWithWtf_shouldFail() {
+ val result = runTestCodeWithRule {
+ Log.wtf(TAG, "some terrible failure", IllegalStateException())
+ throw NullPointerException("some npe")
+ }
+ assertThat(result.isFailure).isTrue()
+ assertThat(result.exceptionOrNull()).isInstanceOf(NullPointerException::class.java)
+ val suppressedExceptions = result.exceptionOrNull()!!.suppressedExceptions
+ assertThat(suppressedExceptions).hasSize(1)
+ val suppressed = suppressedExceptions.first()
+ assertThat(suppressed).isInstanceOf(AssertionError::class.java)
+ assertThat(suppressed.cause).isInstanceOf(Log.TerribleFailure::class.java)
+ assertThat(suppressed.cause?.cause).isInstanceOf(IllegalStateException::class.java)
+ }
+
+ @Test
+ fun passingTestWithExemptWtf_shouldPass() {
+ underTest.addFailureLogExemption { it.tag == TAG_EXPECTED }
+ val result = runTestCodeWithRule {
+ Log.wtf(TAG_EXPECTED, "some expected failure", IllegalStateException())
+ }
+ assertThat(result.isSuccess).isTrue()
+ }
+
+ @Test
+ fun failingTestWithExemptWtf_shouldFail() {
+ underTest.addFailureLogExemption { it.tag == TAG_EXPECTED }
+ val result = runTestCodeWithRule {
+ Log.wtf(TAG_EXPECTED, "some expected failure", IllegalStateException())
+ throw NullPointerException("some npe")
+ }
+ assertThat(result.isFailure).isTrue()
+ assertThat(result.exceptionOrNull()).isInstanceOf(NullPointerException::class.java)
+ val suppressedExceptions = result.exceptionOrNull()!!.suppressedExceptions
+ assertThat(suppressedExceptions).isEmpty()
+ }
+
+ @Test
+ fun passingTestWithOneExemptWtfOfTwo_shouldFail() {
+ underTest.addFailureLogExemption { it.tag == TAG_EXPECTED }
+ val result = runTestCodeWithRule {
+ Log.wtf(TAG_EXPECTED, "some expected failure", IllegalStateException())
+ Log.wtf(TAG, "some terrible failure", IllegalStateException())
+ }
+ assertThat(result.isFailure).isTrue()
+ val exception = result.exceptionOrNull()
+ assertThat(exception).isInstanceOf(AssertionError::class.java)
+ assertThat(exception?.cause).isInstanceOf(Log.TerribleFailure::class.java)
+ assertThat(exception?.cause?.cause).isInstanceOf(IllegalStateException::class.java)
+ }
+
+ @Test
+ fun failingTestWithOneExemptWtfOfTwo_shouldFail() {
+ underTest.addFailureLogExemption { it.tag == TAG_EXPECTED }
+ val result = runTestCodeWithRule {
+ Log.wtf(TAG_EXPECTED, "some expected failure", IllegalStateException())
+ Log.wtf(TAG, "some terrible failure", IllegalStateException())
+ throw NullPointerException("some npe")
+ }
+ assertThat(result.isFailure).isTrue()
+ assertThat(result.exceptionOrNull()).isInstanceOf(NullPointerException::class.java)
+ val suppressedExceptions = result.exceptionOrNull()!!.suppressedExceptions
+ assertThat(suppressedExceptions).hasSize(1)
+ val suppressed = suppressedExceptions.first()
+ assertThat(suppressed).isInstanceOf(AssertionError::class.java)
+ assertThat(suppressed.cause).isInstanceOf(Log.TerribleFailure::class.java)
+ assertThat(suppressed.cause?.cause).isInstanceOf(IllegalStateException::class.java)
+ }
+
+ private fun runTestCodeWithRule(testCode: () -> Unit): Result<Unit> {
+ val testCodeStatement =
+ object : Statement() {
+ override fun evaluate() {
+ testCode()
+ }
+ }
+ val wrappedTest = underTest.apply(testCodeStatement, mock())
+ return try {
+ wrappedTest.evaluate()
+ Result.success(Unit)
+ } catch (e: Throwable) {
+ Result.failure(e)
+ }
+ }
+
+ companion object {
+ const val TAG = "LogWtfHandlerRuleTest"
+ const val TAG_EXPECTED = "EXPECTED"
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index 9adf24f32c0c..1743e056b65c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -863,7 +863,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
val playSuccessHaptic by
- collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+ collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry)
setupBiometricAuth(hasUdfps = true)
assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
@@ -885,7 +885,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
val playSuccessHaptic by
- collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+ collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry)
setupBiometricAuth(hasUdfps = true)
assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
@@ -907,7 +907,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
val playSuccessHaptic by
- collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+ collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry)
setupBiometricAuth(hasSfps = true)
assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
@@ -930,7 +930,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
val playSuccessHaptic by
- collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+ collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry)
setupBiometricAuth(hasSfps = true)
assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
@@ -1033,7 +1033,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
val playSuccessHaptic by
- collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+ collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry)
setupBiometricAuth(hasSfps = true)
assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
@@ -1056,7 +1056,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
val playSuccessHaptic by
- collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+ collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry)
setupBiometricAuth(hasSfps = true)
assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
@@ -1079,7 +1079,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
val playSuccessHaptic by
- collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+ collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry)
setupBiometricAuth(hasSfps = true)
assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
@@ -1102,7 +1102,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
val playSuccessHaptic by
- collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+ collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry)
setupBiometricAuth(hasSfps = true)
assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
@@ -1160,7 +1160,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
@DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
- fun playsFaceErrorHaptics_nonSfps_coEx() =
+ fun skipsFaceErrorHaptics_nonSfps_coEx() =
testScope.runTest {
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic)
@@ -1172,15 +1172,14 @@ class SceneContainerStartableTest : SysuiTestCase() {
underTest.start()
updateFaceAuthStatus(isSuccess = false)
- assertThat(playErrorHaptic).isNotNull()
- assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
- verify(vibratorHelper).vibrateAuthError(anyString())
+ assertThat(playErrorHaptic).isNull()
+ verify(vibratorHelper, never()).vibrateAuthError(anyString())
verify(vibratorHelper, never()).vibrateAuthSuccess(anyString())
}
@Test
@EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
- fun playsMSDLFaceErrorHaptics_nonSfps_coEx() =
+ fun skipsMSDLFaceErrorHaptics_nonSfps_coEx() =
testScope.runTest {
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic)
@@ -1192,10 +1191,9 @@ class SceneContainerStartableTest : SysuiTestCase() {
underTest.start()
updateFaceAuthStatus(isSuccess = false)
- assertThat(playErrorHaptic).isNotNull()
- assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
- assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.FAILURE)
- assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(authInteractionProperties)
+ assertThat(playErrorHaptic).isNull()
+ assertThat(msdlPlayer.latestTokenPlayed).isNull()
+ assertThat(msdlPlayer.latestPropertiesPlayed).isNull()
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
index 3407cd50e76f..4a304071ee97 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
@@ -41,7 +41,6 @@ import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.platform.test.flag.junit.FlagsParameterization;
-import android.provider.Settings;
import android.testing.TestableLooper.RunWithLooper;
import android.view.View;
import android.view.WindowManager;
@@ -71,7 +70,6 @@ import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
-import com.android.systemui.util.settings.FakeSettings;
import com.google.common.util.concurrent.MoreExecutors;
@@ -113,7 +111,6 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase {
@Captor private ArgumentCaptor<WindowManager.LayoutParams> mLayoutParameters;
@Captor private ArgumentCaptor<StatusBarStateController.StateListener> mStateListener;
- private FakeSettings mSecureSettings;
private final Executor mMainExecutor = MoreExecutors.directExecutor();
private final Executor mBackgroundExecutor = MoreExecutors.directExecutor();
private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this);
@@ -135,9 +132,6 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase {
public void setUp() {
MockitoAnnotations.initMocks(this);
- mSecureSettings = new FakeSettings();
- mSecureSettings.putInt(Settings.Secure.DISABLE_SECURE_WINDOWS, 0);
-
// Preferred refresh rate is equal to the first displayMode's refresh rate
mPreferredRefreshRate = mContext.getDisplay().getSystemSupportedModes()[0].getRefreshRate();
overrideResource(
@@ -171,7 +165,6 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase {
() -> mSelectedUserInteractor,
mUserTracker,
mKosmos.getNotificationShadeWindowModel(),
- mSecureSettings,
mKosmos::getCommunalInteractor,
mKosmos.getShadeLayoutParams());
mNotificationShadeWindowController.setScrimsVisibilityListener((visibility) -> {});
@@ -355,19 +348,6 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase {
}
@Test
- public void setKeyguardShowingWithSecureWindowsDisabled_disablesSecureFlag() {
- mSecureSettings.putInt(Settings.Secure.DISABLE_SECURE_WINDOWS, 1);
- mNotificationShadeWindowController.setBouncerShowing(true);
-
- verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
- assertThat((mLayoutParameters.getValue().flags & FLAG_SECURE) == 0).isTrue();
- assertThat(
- (mLayoutParameters.getValue().inputFeatures & INPUT_FEATURE_SENSITIVE_FOR_PRIVACY)
- != 0)
- .isTrue();
- }
-
- @Test
public void setKeyguardNotShowing_disablesSecureFlag() {
mNotificationShadeWindowController.setBouncerShowing(false);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
index fad66581682f..0642467a001b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
@@ -19,6 +19,8 @@ package com.android.systemui.shared.clocks
import android.content.res.Resources
import android.graphics.Color
import android.graphics.drawable.Drawable
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import android.util.TypedValue
import android.view.LayoutInflater
import android.widget.FrameLayout
@@ -29,6 +31,7 @@ import com.android.systemui.customization.R
import com.android.systemui.plugins.clocks.ClockId
import com.android.systemui.plugins.clocks.ClockSettings
import com.android.systemui.plugins.clocks.ThemeConfig
+import com.android.systemui.shared.Flags
import com.android.systemui.shared.clocks.DefaultClockController.Companion.DOZE_COLOR
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
@@ -103,6 +106,26 @@ class DefaultClockProviderTest : SysuiTestCase() {
}
@Test
+ @DisableFlags(Flags.FLAG_AMBIENT_AOD)
+ fun defaultClock_initialize_flagOff() {
+ val clock = provider.createClock(DEFAULT_CLOCK_ID)
+ verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, Color.MAGENTA)
+
+ clock.initialize(true, 0f, 0f, null)
+
+ // This is the default darkTheme color
+ val expectedColor = context.resources.getColor(android.R.color.system_accent1_100)
+ verify(mockSmallClockView).setColors(DOZE_COLOR, expectedColor)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, expectedColor)
+ verify(mockSmallClockView).onTimeZoneChanged(notNull())
+ verify(mockLargeClockView).onTimeZoneChanged(notNull())
+ verify(mockSmallClockView).refreshTime()
+ verify(mockLargeClockView).refreshTime()
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_AMBIENT_AOD)
fun defaultClock_initialize() {
val clock = provider.createClock(DEFAULT_CLOCK_ID)
verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA)
@@ -110,7 +133,7 @@ class DefaultClockProviderTest : SysuiTestCase() {
clock.initialize(true, 0f, 0f, null)
- val expectedColor = 0
+ val expectedColor = Color.MAGENTA
verify(mockSmallClockView).setColors(DOZE_COLOR, expectedColor)
verify(mockLargeClockView).setColors(DOZE_COLOR, expectedColor)
verify(mockSmallClockView).onTimeZoneChanged(notNull())
@@ -165,8 +188,10 @@ class DefaultClockProviderTest : SysuiTestCase() {
}
@Test
- fun defaultClock_events_onThemeChanged_noSeed() {
- val expectedColor = 0
+ @DisableFlags(Flags.FLAG_AMBIENT_AOD)
+ fun defaultClock_events_onThemeChanged_noSeed_flagOff() {
+ // This is the default darkTheme color
+ val expectedColor = context.resources.getColor(android.R.color.system_accent1_100)
val clock = provider.createClock(DEFAULT_CLOCK_ID)
verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA)
@@ -180,6 +205,22 @@ class DefaultClockProviderTest : SysuiTestCase() {
}
@Test
+ @EnableFlags(Flags.FLAG_AMBIENT_AOD)
+ fun defaultClock_events_onThemeChanged_noSeedn() {
+ val expectedColor = Color.TRANSPARENT
+ val clock = provider.createClock(DEFAULT_CLOCK_ID)
+
+ verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, Color.MAGENTA)
+
+ clock.smallClock.events.onThemeChanged(ThemeConfig(true, null))
+ clock.largeClock.events.onThemeChanged(ThemeConfig(true, null))
+
+ verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, Color.MAGENTA)
+ }
+
+ @Test
fun defaultClock_events_onThemeChanged_newSeed() {
val initSeedColor = 10
val newSeedColor = 20
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockFaceEvents.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockFaceEvents.kt
index 029e54658f60..20ee6c120ee8 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockFaceEvents.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockFaceEvents.kt
@@ -13,6 +13,7 @@
*/
package com.android.systemui.plugins.clocks
+import android.content.Context
import android.graphics.Rect
import com.android.systemui.plugins.annotations.ProtectedInterface
@@ -60,4 +61,12 @@ data class ThemeConfig(
* value denotes that we should use the seed color for the current system theme.
*/
val seedColor: Int?,
-)
+) {
+ fun getDefaultColor(context: Context): Int {
+ return when {
+ seedColor != null -> seedColor!!
+ isDarkTheme -> context.resources.getColor(android.R.color.system_accent1_100)
+ else -> context.resources.getColor(android.R.color.system_accent2_600)
+ }
+ }
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/WeatherData.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/WeatherData.kt
index f920b187e7e5..f59dda049aa1 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/WeatherData.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/WeatherData.kt
@@ -24,6 +24,8 @@ data class WeatherData(
@VisibleForTesting const val TEMPERATURE_KEY = "temperature"
private const val INVALID_WEATHER_ICON_STATE = -1
+ @JvmStatic
+ @JvmOverloads
fun fromBundle(extras: Bundle, touchAction: WeatherTouchAction? = null): WeatherData? {
val description = extras.getString(DESCRIPTION_KEY)
val state =
@@ -46,7 +48,7 @@ data class WeatherData(
state = state,
useCelsius = extras.getBoolean(USE_CELSIUS_KEY),
temperature = temperature,
- touchAction = touchAction
+ touchAction = touchAction,
)
if (DEBUG) {
Log.i(TAG, "Weather data parsed $result from $extras")
@@ -87,53 +89,53 @@ data class WeatherData(
}
// Values for WeatherStateIcon must stay in sync with go/g3-WeatherStateIcon
- enum class WeatherStateIcon(val id: Int) {
- UNKNOWN_ICON(0),
+ enum class WeatherStateIcon(val id: Int, val icon: String) {
+ UNKNOWN_ICON(0, ""),
// Clear, day & night.
- SUNNY(1),
- CLEAR_NIGHT(2),
+ SUNNY(1, "a"),
+ CLEAR_NIGHT(2, "f"),
// Mostly clear, day & night.
- MOSTLY_SUNNY(3),
- MOSTLY_CLEAR_NIGHT(4),
+ MOSTLY_SUNNY(3, "b"),
+ MOSTLY_CLEAR_NIGHT(4, "n"),
// Partly cloudy, day & night.
- PARTLY_CLOUDY(5),
- PARTLY_CLOUDY_NIGHT(6),
+ PARTLY_CLOUDY(5, "b"),
+ PARTLY_CLOUDY_NIGHT(6, "n"),
// Mostly cloudy, day & night.
- MOSTLY_CLOUDY_DAY(7),
- MOSTLY_CLOUDY_NIGHT(8),
- CLOUDY(9),
- HAZE_FOG_DUST_SMOKE(10),
- DRIZZLE(11),
- HEAVY_RAIN(12),
- SHOWERS_RAIN(13),
+ MOSTLY_CLOUDY_DAY(7, "e"),
+ MOSTLY_CLOUDY_NIGHT(8, "e"),
+ CLOUDY(9, "e"),
+ HAZE_FOG_DUST_SMOKE(10, "d"),
+ DRIZZLE(11, "c"),
+ HEAVY_RAIN(12, "c"),
+ SHOWERS_RAIN(13, "c"),
// Scattered showers, day & night.
- SCATTERED_SHOWERS_DAY(14),
- SCATTERED_SHOWERS_NIGHT(15),
+ SCATTERED_SHOWERS_DAY(14, "c"),
+ SCATTERED_SHOWERS_NIGHT(15, "c"),
// Isolated scattered thunderstorms, day & night.
- ISOLATED_SCATTERED_TSTORMS_DAY(16),
- ISOLATED_SCATTERED_TSTORMS_NIGHT(17),
- STRONG_TSTORMS(18),
- BLIZZARD(19),
- BLOWING_SNOW(20),
- FLURRIES(21),
- HEAVY_SNOW(22),
+ ISOLATED_SCATTERED_TSTORMS_DAY(16, "i"),
+ ISOLATED_SCATTERED_TSTORMS_NIGHT(17, "i"),
+ STRONG_TSTORMS(18, "i"),
+ BLIZZARD(19, "j"),
+ BLOWING_SNOW(20, "j"),
+ FLURRIES(21, "h"),
+ HEAVY_SNOW(22, "j"),
// Scattered snow showers, day & night.
- SCATTERED_SNOW_SHOWERS_DAY(23),
- SCATTERED_SNOW_SHOWERS_NIGHT(24),
- SNOW_SHOWERS_SNOW(25),
- MIXED_RAIN_HAIL_RAIN_SLEET(26),
- SLEET_HAIL(27),
- TORNADO(28),
- TROPICAL_STORM_HURRICANE(29),
- WINDY_BREEZY(30),
- WINTRY_MIX_RAIN_SNOW(31);
+ SCATTERED_SNOW_SHOWERS_DAY(23, "h"),
+ SCATTERED_SNOW_SHOWERS_NIGHT(24, "h"),
+ SNOW_SHOWERS_SNOW(25, "g"),
+ MIXED_RAIN_HAIL_RAIN_SLEET(26, "h"),
+ SLEET_HAIL(27, "h"),
+ TORNADO(28, "l"),
+ TROPICAL_STORM_HURRICANE(29, "m"),
+ WINDY_BREEZY(30, "k"),
+ WINTRY_MIX_RAIN_SNOW(31, "h");
companion object {
fun fromInt(value: Int) = values().firstOrNull { it.id == value }
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 8342a9cc244b..19e05871c035 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -2166,7 +2166,7 @@
<dimen name="volume_dialog_background_top_margin">-28dp</dimen>
<dimen name="volume_dialog_window_margin">14dp</dimen>
- <dimen name="volume_dialog_components_spacing">8dp</dimen>
+ <dimen name="volume_dialog_components_spacing">10dp</dimen>
<dimen name="volume_dialog_floating_sliders_spacing">8dp</dimen>
<dimen name="volume_dialog_floating_sliders_vertical_padding">10dp</dimen>
<dimen name="volume_dialog_floating_sliders_vertical_padding_negative">
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
index 140db7b7a0b7..62a98d7a48ea 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
@@ -377,12 +377,15 @@ constructor(
MutableStateFlow(false)
}
- val inAllowedKeyguardState =
- keyguardTransitionInteractor.startedKeyguardTransitionStep.map {
- it.to == KeyguardState.LOCKSCREEN || it.to == KeyguardState.GLANCEABLE_HUB
- }
-
- allOf(inAllowedDeviceState, inAllowedKeyguardState)
+ if (v2FlagEnabled()) {
+ val inAllowedKeyguardState =
+ keyguardTransitionInteractor.startedKeyguardTransitionStep.map {
+ it.to == KeyguardState.LOCKSCREEN || it.to == KeyguardState.GLANCEABLE_HUB
+ }
+ allOf(inAllowedDeviceState, inAllowedKeyguardState)
+ } else {
+ inAllowedDeviceState
+ }
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
index a25faa3a7aec..1ef3a950ba0d 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
@@ -36,6 +36,7 @@ import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManagerImpl;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.education.dagger.ContextualEducationModule;
+import com.android.systemui.effects.dagger.TopLevelWindowEffectsModule;
import com.android.systemui.emergency.EmergencyGestureModule;
import com.android.systemui.inputdevice.tutorial.KeyboardTouchpadTutorialModule;
import com.android.systemui.keyboard.shortcut.ShortcutHelperModule;
@@ -166,6 +167,7 @@ import javax.inject.Named;
SysUIUnfoldStartableModule.class,
UnfoldTransitionModule.Startables.class,
ToastModule.class,
+ TopLevelWindowEffectsModule.class,
TouchpadTutorialModule.class,
VolumeModule.class,
WallpaperModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt
index 69da67e055fe..1e7bec257432 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt
@@ -68,10 +68,4 @@ constructor(
emptyFlow()
}
}
-
- /** Triggered if a face failure occurs regardless of the mode. */
- val faceFailure: Flow<FailedFaceAuthenticationStatus> =
- deviceEntryFaceAuthInteractor.authenticationStatus.filterIsInstance<
- FailedFaceAuthenticationStatus
- >()
}
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt
index 38e0503440f9..09936839c590 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt
@@ -22,7 +22,6 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyevent.domain.interactor.KeyEventInteractor
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardBypassInteractor
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.util.kotlin.FlowDumperImpl
@@ -49,8 +48,6 @@ class DeviceEntryHapticsInteractor
constructor(
biometricSettingsRepository: BiometricSettingsRepository,
deviceEntryBiometricAuthInteractor: DeviceEntryBiometricAuthInteractor,
- deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor,
- keyguardBypassInteractor: KeyguardBypassInteractor,
deviceEntryFingerprintAuthInteractor: DeviceEntryFingerprintAuthInteractor,
deviceEntrySourceInteractor: DeviceEntrySourceInteractor,
fingerprintPropertyRepository: FingerprintPropertyRepository,
@@ -83,7 +80,12 @@ constructor(
emit(recentPowerButtonPressThresholdMs * -1L - 1L)
}
- private val playHapticsOnDeviceEntry: Flow<Boolean> =
+ /**
+ * Indicates when success haptics should play when the device is entered. This always occurs on
+ * successful fingerprint authentications. It also occurs on successful face authentication but
+ * only if the lockscreen is bypassed.
+ */
+ val playSuccessHapticOnDeviceEntry: Flow<Unit> =
deviceEntrySourceInteractor.deviceEntryFromBiometricSource
.sample(
combine(
@@ -93,29 +95,17 @@ constructor(
::Triple,
)
)
- .map { (sideFpsEnrolled, powerButtonDown, lastPowerButtonWakeup) ->
+ .filter { (sideFpsEnrolled, powerButtonDown, lastPowerButtonWakeup) ->
val sideFpsAllowsHaptic =
!powerButtonDown &&
systemClock.uptimeMillis() - lastPowerButtonWakeup >
recentPowerButtonPressThresholdMs
val allowHaptic = !sideFpsEnrolled || sideFpsAllowsHaptic
if (!allowHaptic) {
- logger.d(
- "Skip success entry haptic from power button. Recent power button press or button is down."
- )
+ logger.d("Skip success haptic. Recent power button press or button is down.")
}
allowHaptic
}
-
- private val playHapticsOnFaceAuthSuccessAndBypassDisabled: Flow<Boolean> =
- deviceEntryFaceAuthInteractor.isAuthenticated
- .filter { it }
- .sample(keyguardBypassInteractor.isBypassAvailable)
- .map { !it }
-
- val playSuccessHaptic: Flow<Unit> =
- merge(playHapticsOnDeviceEntry, playHapticsOnFaceAuthSuccessAndBypassDisabled)
- .filter { it }
// map to Unit
.map {}
.dumpWhileCollecting("playSuccessHaptic")
@@ -123,7 +113,7 @@ constructor(
private val playErrorHapticForBiometricFailure: Flow<Unit> =
merge(
deviceEntryFingerprintAuthInteractor.fingerprintFailure,
- deviceEntryBiometricAuthInteractor.faceFailure,
+ deviceEntryBiometricAuthInteractor.faceOnlyFaceFailure,
)
// map to Unit
.map {}
diff --git a/packages/SystemUI/src/com/android/systemui/effects/TopLevelWindowEffects.kt b/packages/SystemUI/src/com/android/systemui/effects/TopLevelWindowEffects.kt
new file mode 100644
index 000000000000..91530078e378
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/effects/TopLevelWindowEffects.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.effects;
+
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.SysUISingleton;
+import javax.inject.Inject
+
+@SysUISingleton
+class TopLevelWindowEffects @Inject constructor() : CoreStartable {
+ override fun start() {
+
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/effects/dagger/TopLevelWindowEffectsModule.kt b/packages/SystemUI/src/com/android/systemui/effects/dagger/TopLevelWindowEffectsModule.kt
new file mode 100644
index 000000000000..70c4636e25c5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/effects/dagger/TopLevelWindowEffectsModule.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.effects.dagger
+
+import com.android.systemui.CoreStartable
+import com.android.systemui.effects.TopLevelWindowEffects
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
+
+@Module
+interface TopLevelWindowEffectsModule {
+
+ @Binds
+ @IntoMap
+ @ClassKey(TopLevelWindowEffects::class)
+ fun bindTopLevelWindowEffectsCoreStartable(impl: TopLevelWindowEffects): CoreStartable
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
index 45801ba3517a..aeb327035c79 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
@@ -333,7 +333,7 @@ object KeyguardRootViewBinder {
if (deviceEntryHapticsInteractor != null && vibratorHelper != null) {
launch {
- deviceEntryHapticsInteractor.playSuccessHaptic.collect {
+ deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry.collect {
if (msdlFeedback()) {
msdlPlayer?.playToken(
MSDLToken.UNLOCK,
@@ -474,7 +474,7 @@ object KeyguardRootViewBinder {
val transition = blueprintViewModel.currentTransition.value
val shouldAnimate = transition != null && transition.config.type.animateNotifChanges
if (prevTransition == transition && shouldAnimate) {
- logger.w("Skipping; layout during transition")
+ logger.w("Skipping onNotificationContainerBoundsChanged during transition")
return
}
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index faa6c52162ce..a85b9b04c1ce 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -327,7 +327,8 @@ public class LogModule {
@SysUISingleton
@KeyguardBlueprintLog
public static LogBuffer provideKeyguardBlueprintLog(LogBufferFactory factory) {
- return factory.create("KeyguardBlueprintLog", 100);
+ // TODO(b/389987229): Reduce back to 100
+ return factory.create("KeyguardBlueprintLog", 1000);
}
/**
@@ -337,7 +338,8 @@ public class LogModule {
@SysUISingleton
@KeyguardClockLog
public static LogBuffer provideKeyguardClockLog(LogBufferFactory factory) {
- return factory.create("KeyguardClockLog", 100);
+ // TODO(b/389987229): Reduce back to 100
+ return factory.create("KeyguardClockLog", 1000);
}
/**
@@ -347,7 +349,8 @@ public class LogModule {
@SysUISingleton
@KeyguardSmallClockLog
public static LogBuffer provideKeyguardSmallClockLog(LogBufferFactory factory) {
- return factory.create("KeyguardSmallClockLog", 100);
+ // TODO(b/389987229): Reduce back to 100
+ return factory.create("KeyguardSmallClockLog", 1000);
}
/**
@@ -357,7 +360,8 @@ public class LogModule {
@SysUISingleton
@KeyguardLargeClockLog
public static LogBuffer provideKeyguardLargeClockLog(LogBufferFactory factory) {
- return factory.create("KeyguardLargeClockLog", 100);
+ // TODO(b/389987229): Reduce back to 100
+ return factory.create("KeyguardLargeClockLog", 1000);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index 4753b9ac0457..7bb831baec20 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -687,7 +687,7 @@ constructor(
if (!isDeviceEntered) {
coroutineScope {
launch {
- deviceEntryHapticsInteractor.playSuccessHaptic
+ deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry
.sample(sceneInteractor.currentScene)
.collect { currentScene ->
if (Flags.msdlFeedback()) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index 305444f7ab5e..fa17b4fad592 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -30,8 +30,6 @@ import android.graphics.Region;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.Trace;
-import android.os.UserHandle;
-import android.provider.Settings;
import android.util.Log;
import android.view.Display;
import android.view.IWindow;
@@ -75,7 +73,6 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
-import com.android.systemui.util.settings.SecureSettings;
import dagger.Lazy;
@@ -134,7 +131,6 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
private final SysuiColorExtractor mColorExtractor;
private final NotificationShadeWindowModel mNotificationShadeWindowModel;
- private final SecureSettings mSecureSettings;
/**
* Layout params would be aggregated and dispatched all at once if this is > 0.
*
@@ -168,7 +164,6 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
Lazy<SelectedUserInteractor> userInteractor,
UserTracker userTracker,
NotificationShadeWindowModel notificationShadeWindowModel,
- SecureSettings secureSettings,
Lazy<CommunalInteractor> communalInteractor,
@ShadeDisplayAware LayoutParams shadeWindowLayoutParams) {
mContext = context;
@@ -186,7 +181,6 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
mBackgroundExecutor = backgroundExecutor;
mColorExtractor = colorExtractor;
mNotificationShadeWindowModel = notificationShadeWindowModel;
- mSecureSettings = secureSettings;
// prefix with {slow} to make sure this dumps at the END of the critical section.
dumpManager.registerCriticalDumpable("{slow}NotificationShadeWindowControllerImpl", this);
mAuthController = authController;
@@ -424,7 +418,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
(long) mLpChanged.preferredMaxDisplayRefreshRate);
}
- if (state.bouncerShowing && !isSecureWindowsDisabled()) {
+ if (state.bouncerShowing) {
mLpChanged.flags |= LayoutParams.FLAG_SECURE;
} else {
mLpChanged.flags &= ~LayoutParams.FLAG_SECURE;
@@ -437,13 +431,6 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
}
}
- private boolean isSecureWindowsDisabled() {
- return mSecureSettings.getIntForUser(
- Settings.Secure.DISABLE_SECURE_WINDOWS,
- 0,
- UserHandle.USER_CURRENT) == 1;
- }
-
private void adjustScreenOrientation(NotificationShadeWindowState state) {
if (state.bouncerShowing || state.isKeyguardShowingAndNotOccluded() || state.dozing) {
if (mKeyguardStateController.isKeyguardScreenRotationAllowed()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index 6837cb2a6292..76d8fb8d3c15 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -129,8 +129,13 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
}
private void updateColors() {
- if (usesTransparentBackground()) {
- mNormalColor = SurfaceEffectColors.surfaceEffect1(getContext());
+ if (notificationRowTransparency()) {
+ if (mIsBlurSupported) {
+ mNormalColor = SurfaceEffectColors.surfaceEffect1(getContext());
+ } else {
+ mNormalColor = mContext.getColor(
+ com.android.internal.R.color.materialColorSurfaceContainer);
+ }
} else {
mNormalColor = mContext.getColor(
com.android.internal.R.color.materialColorSurfaceContainerHigh);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index e8054c07eac8..8105ae0960ad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -283,7 +283,6 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
() -> mSelectedUserInteractor,
mock(UserTracker.class),
mKosmos.getNotificationShadeWindowModel(),
- mSecureSettings,
mKosmos::getCommunalInteractor,
mKosmos.getShadeLayoutParams());
mFeatureFlags = new FakeFeatureFlags();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index 341bd3a38999..a978ecdb3534 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -33,6 +33,8 @@ import static com.android.wm.shell.Flags.FLAG_ENABLE_BUBBLE_BAR;
import static com.google.common.truth.Truth.assertThat;
+import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -55,8 +57,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
-import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
-
import android.app.ActivityManager;
import android.app.IActivityManager;
import android.app.INotificationManager;
@@ -136,7 +136,6 @@ import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
-import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -166,7 +165,6 @@ import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvision
import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
import com.android.systemui.util.FakeEventLog;
import com.android.systemui.util.settings.FakeGlobalSettings;
-import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.SystemSettings;
import com.android.systemui.util.time.SystemClock;
import com.android.wm.shell.Flags;
@@ -451,7 +449,6 @@ public class BubblesTest extends SysuiTestCase {
() -> mSelectedUserInteractor,
mUserTracker,
mNotificationShadeWindowModel,
- new FakeSettings(),
mKosmos::getCommunalInteractor,
mKosmos.getShadeLayoutParams()
);
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorKosmos.kt
index 6f570a86b19e..cd4b09c5267a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorKosmos.kt
@@ -21,7 +21,6 @@ import com.android.systemui.biometrics.data.repository.fingerprintPropertyReposi
import com.android.systemui.dump.dumpManager
import com.android.systemui.keyevent.domain.interactor.keyEventInteractor
import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
-import com.android.systemui.keyguard.domain.interactor.keyguardBypassInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.util.time.systemClock
@@ -31,8 +30,6 @@ val Kosmos.deviceEntryHapticsInteractor by
DeviceEntryHapticsInteractor(
biometricSettingsRepository = biometricSettingsRepository,
deviceEntryBiometricAuthInteractor = deviceEntryBiometricAuthInteractor,
- deviceEntryFaceAuthInteractor = deviceEntryFaceAuthInteractor,
- keyguardBypassInteractor = keyguardBypassInteractor,
deviceEntryFingerprintAuthInteractor = deviceEntryFingerprintAuthInteractor,
deviceEntrySourceInteractor = deviceEntrySourceInteractor,
fingerprintPropertyRepository = fingerprintPropertyRepository,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/log/LogWtfHandlerRule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/log/LogWtfHandlerRule.kt
index e639326bd7a1..0e348c88f058 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/log/LogWtfHandlerRule.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/log/LogWtfHandlerRule.kt
@@ -24,21 +24,23 @@ import org.junit.runners.model.Statement
class LogWtfHandlerRule : TestRule {
- private var started = false
- private var handler = ThrowAndFailAtEnd
+ private var failureLogExemptions = mutableListOf<FailureLogExemption>()
override fun apply(base: Statement, description: Description): Statement {
return object : Statement() {
override fun evaluate() {
- started = true
+ val handler = TerribleFailureTestHandler()
val originalWtfHandler = Log.setWtfHandler(handler)
var failure: Throwable? = null
try {
base.evaluate()
} catch (ex: Throwable) {
- failure = ex.runAndAddSuppressed { handler.onTestFailure(ex) }
+ failure = ex
} finally {
- failure = failure.runAndAddSuppressed { handler.onTestFinished() }
+ failure =
+ runAndAddSuppressed(failure) {
+ handler.onTestFinished(failureLogExemptions)
+ }
Log.setWtfHandler(originalWtfHandler)
}
if (failure != null) {
@@ -48,74 +50,52 @@ class LogWtfHandlerRule : TestRule {
}
}
- fun Throwable?.runAndAddSuppressed(block: () -> Unit): Throwable? {
+ /** Adds a log failure exemption. Exemptions are evaluated at the end of the test. */
+ fun addFailureLogExemption(exemption: FailureLogExemption) {
+ failureLogExemptions.add(exemption)
+ }
+
+ /** Clears and sets exemptions. Exemptions are evaluated at the end of the test. */
+ fun resetFailureLogExemptions(vararg exemptions: FailureLogExemption) {
+ failureLogExemptions = exemptions.toMutableList()
+ }
+
+ private fun runAndAddSuppressed(currentError: Throwable?, block: () -> Unit): Throwable? {
try {
block()
} catch (t: Throwable) {
- if (this == null) {
+ if (currentError == null) {
return t
}
- addSuppressed(t)
+ currentError.addSuppressed(t)
}
- return this
+ return currentError
}
- fun setWtfHandler(handler: TerribleFailureTestHandler) {
- check(!started) { "Should only be called before the test starts" }
- this.handler = handler
- }
-
- fun interface TerribleFailureTestHandler : TerribleFailureHandler {
- fun onTestFailure(failure: Throwable) {}
- fun onTestFinished() {}
- }
-
- companion object Handlers {
- val ThrowAndFailAtEnd
- get() =
- object : TerribleFailureTestHandler {
- val failures = mutableListOf<Log.TerribleFailure>()
-
- override fun onTerribleFailure(
- tag: String,
- what: Log.TerribleFailure,
- system: Boolean
- ) {
- failures.add(what)
- throw what
- }
+ private class TerribleFailureTestHandler : TerribleFailureHandler {
+ private val failureLogs = mutableListOf<FailureLog>()
- override fun onTestFailure(failure: Throwable) {
- super.onTestFailure(failure)
- }
+ override fun onTerribleFailure(tag: String, what: Log.TerribleFailure, system: Boolean) {
+ failureLogs.add(FailureLog(tag = tag, failure = what, system = system))
+ }
- override fun onTestFinished() {
- if (failures.isNotEmpty()) {
- throw AssertionError("Unexpected Log.wtf calls: $failures", failures[0])
- }
- }
+ fun onTestFinished(exemptions: List<FailureLogExemption>) {
+ val failures =
+ failureLogs.filter { failureLog ->
+ !exemptions.any { it.isFailureLogExempt(failureLog) }
}
+ if (failures.isNotEmpty()) {
+ throw AssertionError("Unexpected Log.wtf calls: $failures", failures[0].failure)
+ }
+ }
+ }
- val JustThrow = TerribleFailureTestHandler { _, what, _ -> throw what }
-
- val JustFailAtEnd
- get() =
- object : TerribleFailureTestHandler {
- val failures = mutableListOf<Log.TerribleFailure>()
-
- override fun onTerribleFailure(
- tag: String,
- what: Log.TerribleFailure,
- system: Boolean
- ) {
- failures.add(what)
- }
+ /** All the information from a call to [Log.wtf] that was handed to [TerribleFailureHandler] */
+ data class FailureLog(val tag: String, val failure: Log.TerribleFailure, val system: Boolean)
- override fun onTestFinished() {
- if (failures.isNotEmpty()) {
- throw AssertionError("Unexpected Log.wtf calls: $failures", failures[0])
- }
- }
- }
+ /** An interface for exempting a [FailureLog] from causing a test failure. */
+ fun interface FailureLogExemption {
+ /** Determines whether a log should be except from failing the test. */
+ fun isFailureLogExempt(log: FailureLog): Boolean
}
}
diff --git a/services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java b/services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java
index 9a353fbc45bf..867cd51e1c2b 100644
--- a/services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java
+++ b/services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java
@@ -44,6 +44,7 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
+import com.android.server.backup.BackupRestoreTask.CancellationReason;
import com.android.server.backup.internal.LifecycleOperationStorage;
import java.util.Set;
@@ -298,20 +299,22 @@ public class BackupAgentConnectionManager {
// Offload operation cancellation off the main thread as the cancellation callbacks
// might call out to BackupTransport. Other operations started on the same package
// before the cancellation callback has executed will also be cancelled by the callback.
- Runnable cancellationRunnable = () -> {
- // handleCancel() causes the PerformFullTransportBackupTask to go on to
- // tearDownAgentAndKill: that will unbindBackupAgent in the Activity Manager, so
- // that the package being backed up doesn't get stuck in restricted mode until the
- // backup time-out elapses.
- for (int token : mOperationStorage.operationTokensForPackage(packageName)) {
- if (DEBUG) {
- Slog.d(TAG,
- mUserIdMsg + "agentDisconnected: will handleCancel(all) for token:"
- + Integer.toHexString(token));
- }
- mUserBackupManagerService.handleCancel(token, true /* cancelAll */);
- }
- };
+ Runnable cancellationRunnable =
+ () -> {
+ // On handleCancel(), the operation will call unbindAgent() which will make
+ // sure the app doesn't get stuck in restricted mode.
+ for (int token : mOperationStorage.operationTokensForPackage(packageName)) {
+ if (DEBUG) {
+ Slog.d(
+ TAG,
+ mUserIdMsg
+ + "agentDisconnected: cancelling for token:"
+ + Integer.toHexString(token));
+ }
+ mUserBackupManagerService.handleCancel(
+ token, CancellationReason.AGENT_DISCONNECTED);
+ }
+ };
getThreadForCancellation(cancellationRunnable).start();
mAgentConnectLock.notifyAll();
diff --git a/services/backup/java/com/android/server/backup/BackupRestoreTask.java b/services/backup/java/com/android/server/backup/BackupRestoreTask.java
index acaab0c54191..7ec5f0d786ed 100644
--- a/services/backup/java/com/android/server/backup/BackupRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/BackupRestoreTask.java
@@ -16,9 +16,12 @@
package com.android.server.backup;
-/**
- * Interface and methods used by the asynchronous-with-timeout backup/restore operations.
- */
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/** Interface and methods used by the asynchronous-with-timeout backup/restore operations. */
public interface BackupRestoreTask {
// Execute one tick of whatever state machine the task implements
@@ -27,6 +30,24 @@ public interface BackupRestoreTask {
// An operation that wanted a callback has completed
void operationComplete(long result);
- // An operation that wanted a callback has timed out
- void handleCancel(boolean cancelAll);
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ CancellationReason.TIMEOUT,
+ CancellationReason.AGENT_DISCONNECTED,
+ CancellationReason.EXTERNAL,
+ CancellationReason.SCHEDULED_JOB_STOPPED,
+ })
+ @interface CancellationReason {
+ // The task timed out.
+ int TIMEOUT = 0;
+ // The agent went away before the task was able to finish (e.g. due to an app crash).
+ int AGENT_DISCONNECTED = 1;
+ // An external caller cancelled the operation (e.g. via BackupManager#cancelBackups).
+ int EXTERNAL = 2;
+ // The job scheduler has stopped an ongoing scheduled backup pass.
+ int SCHEDULED_JOB_STOPPED = 3;
+ }
+
+ /** The task is cancelled for the given {@link CancellationReason}. */
+ void handleCancel(@CancellationReason int cancellationReason);
}
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 2143aaaa4cd6..b3af444ff9bd 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -102,6 +102,7 @@ import com.android.internal.util.Preconditions;
import com.android.server.AppWidgetBackupBridge;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
+import com.android.server.backup.BackupRestoreTask.CancellationReason;
import com.android.server.backup.OperationStorage.OpState;
import com.android.server.backup.OperationStorage.OpType;
import com.android.server.backup.fullbackup.FullBackupEntry;
@@ -168,6 +169,7 @@ import java.util.Random;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.IntConsumer;
/** System service that performs backup/restore operations. */
public class UserBackupManagerService {
@@ -1816,11 +1818,9 @@ public class UserBackupManagerService {
for (Integer token : operationsToCancel) {
mOperationStorage.cancelOperation(
- token, /* cancelAll */
- true,
- operationType -> {
- /* no callback needed here */
- });
+ token,
+ operationType -> {}, // no callback needed here
+ CancellationReason.EXTERNAL);
}
// We don't want the backup jobs to kick in any time soon.
// Reschedules them to run in the distant future.
@@ -1897,19 +1897,17 @@ public class UserBackupManagerService {
}
/** Cancel the operation associated with {@code token}. */
- public void handleCancel(int token, boolean cancelAll) {
+ public void handleCancel(int token, @CancellationReason int cancellationReason) {
// Remove all pending timeout messages of types OpType.BACKUP_WAIT and
// OpType.RESTORE_WAIT. On the other hand, OP_TYPE_BACKUP cannot time out and
// doesn't require cancellation.
- mOperationStorage.cancelOperation(
- token,
- cancelAll,
- operationType -> {
- if (operationType == OpType.BACKUP_WAIT
- || operationType == OpType.RESTORE_WAIT) {
- mBackupHandler.removeMessages(getMessageIdForOperationType(operationType));
+ IntConsumer timeoutCallback =
+ opType -> {
+ if (opType == OpType.BACKUP_WAIT || opType == OpType.RESTORE_WAIT) {
+ mBackupHandler.removeMessages(getMessageIdForOperationType(opType));
}
- });
+ };
+ mOperationStorage.cancelOperation(token, timeoutCallback, cancellationReason);
}
/** Returns {@code true} if a backup is currently running, else returns {@code false}. */
@@ -2219,20 +2217,17 @@ public class UserBackupManagerService {
// offload the mRunningFullBackupTask.handleCancel() call to another thread,
// as we might have to wait for mCancelLock
Runnable endFullBackupRunnable =
- new Runnable() {
- @Override
- public void run() {
- PerformFullTransportBackupTask pftbt = null;
- synchronized (mQueueLock) {
- if (mRunningFullBackupTask != null) {
- pftbt = mRunningFullBackupTask;
- }
- }
- if (pftbt != null) {
- Slog.i(TAG, mLogIdMsg + "Telling running backup to stop");
- pftbt.handleCancel(true);
+ () -> {
+ PerformFullTransportBackupTask pftbt = null;
+ synchronized (mQueueLock) {
+ if (mRunningFullBackupTask != null) {
+ pftbt = mRunningFullBackupTask;
}
}
+ if (pftbt != null) {
+ Slog.i(TAG, mLogIdMsg + "Telling running backup to stop");
+ pftbt.handleCancel(CancellationReason.SCHEDULED_JOB_STOPPED);
+ }
};
new Thread(endFullBackupRunnable, "end-full-backup").start();
}
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
index 0d4364e14e03..7fc9ed3e0213 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
@@ -484,7 +484,7 @@ public class PerformAdbBackupTask extends FullBackupTask implements BackupRestor
}
@Override
- public void handleCancel(boolean cancelAll) {
+ public void handleCancel(@CancellationReason int cancellationReason) {
final PackageInfo target = mCurrentTarget;
Slog.w(TAG, "adb backup cancel of " + target);
if (target != null) {
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
index c182c2618fdf..f677c9dbf4d0 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -162,7 +162,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
// This is true when a backup operation for some package is in progress.
private volatile boolean mIsDoingBackup;
- private volatile boolean mCancelAll;
+ private volatile boolean mCancelled;
private final int mCurrentOpToken;
private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
private final BackupEligibilityRules mBackupEligibilityRules;
@@ -199,7 +199,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
if (backupManagerService.isBackupOperationInProgress()) {
Slog.d(TAG, "Skipping full backup. A backup is already in progress.");
- mCancelAll = true;
+ mCancelled = true;
return;
}
@@ -287,25 +287,23 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
}
@Override
- public void handleCancel(boolean cancelAll) {
+ public void handleCancel(@CancellationReason int cancellationReason) {
synchronized (mCancelLock) {
- // We only support 'cancelAll = true' case for this task. Cancelling of a single package
-
- // due to timeout is handled by SinglePackageBackupRunner and
+ // This callback is only used for cancelling the entire backup operation. Cancelling of
+ // a single package due to timeout is handled by SinglePackageBackupRunner and
// SinglePackageBackupPreflight.
-
- if (!cancelAll) {
- Slog.wtf(TAG, "Expected cancelAll to be true.");
+ if (cancellationReason == CancellationReason.TIMEOUT) {
+ Slog.wtf(TAG, "This task cannot time out");
}
- if (mCancelAll) {
+ if (mCancelled) {
Slog.d(TAG, "Ignoring duplicate cancel call.");
return;
}
- mCancelAll = true;
+ mCancelled = true;
if (mIsDoingBackup) {
- mUserBackupManagerService.handleCancel(mBackupRunnerOpToken, cancelAll);
+ mUserBackupManagerService.handleCancel(mBackupRunnerOpToken, cancellationReason);
try {
// If we're running a backup we should be connected to a transport
BackupTransportClient transport =
@@ -410,7 +408,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
int backupPackageStatus;
long quota = Long.MAX_VALUE;
synchronized (mCancelLock) {
- if (mCancelAll) {
+ if (mCancelled) {
break;
}
backupPackageStatus = transport.performFullBackup(currentPackage,
@@ -478,7 +476,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
if (nRead > 0) {
out.write(buffer, 0, nRead);
synchronized (mCancelLock) {
- if (!mCancelAll) {
+ if (!mCancelled) {
backupPackageStatus = transport.sendBackupData(nRead);
}
}
@@ -509,7 +507,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
synchronized (mCancelLock) {
mIsDoingBackup = false;
// If mCancelCurrent is true, we have already called cancelFullBackup().
- if (!mCancelAll) {
+ if (!mCancelled) {
if (backupRunnerResult == BackupTransport.TRANSPORT_OK) {
// If we were otherwise in a good state, now interpret the final
// result based on what finishBackup() returns. If we're in a
@@ -607,7 +605,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
.sendBackupOnPackageResult(mBackupObserver, packageName,
BackupManager.ERROR_BACKUP_CANCELLED);
Slog.w(TAG, "Backup cancelled. package=" + packageName +
- ", cancelAll=" + mCancelAll);
+ ", entire session cancelled=" + mCancelled);
EventLog.writeEvent(EventLogTags.FULL_BACKUP_CANCELLED, packageName);
mUserBackupManagerService.getBackupAgentConnectionManager().unbindAgent(
currentPackage.applicationInfo, /* allowKill= */ true);
@@ -654,7 +652,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
} finally {
- if (mCancelAll) {
+ if (mCancelled) {
backupRunStatus = BackupManager.ERROR_BACKUP_CANCELLED;
}
@@ -820,7 +818,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
}
@Override
- public void handleCancel(boolean cancelAll) {
+ public void handleCancel(@CancellationReason int cancellationReason) {
if (DEBUG) {
Slog.i(TAG, "Preflight cancelled; failing");
}
@@ -974,7 +972,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
public void operationComplete(long result) { /* intentionally empty */ }
@Override
- public void handleCancel(boolean cancelAll) {
+ public void handleCancel(@CancellationReason int cancellationReason) {
Slog.w(TAG, "Full backup cancel of " + mTarget.packageName);
mBackupManagerMonitorEventSender.monitorEvent(
@@ -984,7 +982,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
/* extras= */ null);
mIsCancelled = true;
// Cancel tasks spun off by this task.
- mUserBackupManagerService.handleCancel(mEphemeralToken, cancelAll);
+ mUserBackupManagerService.handleCancel(mEphemeralToken, cancellationReason);
mUserBackupManagerService.getBackupAgentConnectionManager().unbindAgent(
mTarget.applicationInfo, /* allowKill= */ true);
// Free up everyone waiting on this task and its children.
diff --git a/services/backup/java/com/android/server/backup/internal/BackupHandler.java b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
index 87cf8a313651..464dc2dfe1ec 100644
--- a/services/backup/java/com/android/server/backup/internal/BackupHandler.java
+++ b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
@@ -34,6 +34,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.server.EventLogTags;
import com.android.server.backup.BackupAgentTimeoutParameters;
import com.android.server.backup.BackupRestoreTask;
+import com.android.server.backup.BackupRestoreTask.CancellationReason;
import com.android.server.backup.DataChangedJournal;
import com.android.server.backup.OperationStorage;
import com.android.server.backup.TransportManager;
@@ -410,8 +411,8 @@ public class BackupHandler extends Handler {
case MSG_BACKUP_OPERATION_TIMEOUT:
case MSG_RESTORE_OPERATION_TIMEOUT: {
- Slog.d(TAG, "Timeout message received for token=" + Integer.toHexString(msg.arg1));
- backupManagerService.handleCancel(msg.arg1, false);
+ Slog.d(TAG, "Timeout for token=" + Integer.toHexString(msg.arg1));
+ backupManagerService.handleCancel(msg.arg1, CancellationReason.TIMEOUT);
break;
}
diff --git a/services/backup/java/com/android/server/backup/internal/LifecycleOperationStorage.java b/services/backup/java/com/android/server/backup/internal/LifecycleOperationStorage.java
index 0b974e2d0a8a..5aacb2f4f007 100644
--- a/services/backup/java/com/android/server/backup/internal/LifecycleOperationStorage.java
+++ b/services/backup/java/com/android/server/backup/internal/LifecycleOperationStorage.java
@@ -24,6 +24,7 @@ import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.server.backup.BackupRestoreTask;
+import com.android.server.backup.BackupRestoreTask.CancellationReason;
import com.android.server.backup.OperationStorage;
import com.google.android.collect.Sets;
@@ -296,20 +297,18 @@ public class LifecycleOperationStorage implements OperationStorage {
}
/**
- * Cancel the operation associated with {@code token}. Cancellation may be
- * propagated to the operation's callback (a {@link BackupRestoreTask}) if
- * the operation has one, and the cancellation is due to the operation
- * timing out.
+ * Cancel the operation associated with {@code token}. Cancellation may be propagated to the
+ * operation's callback (a {@link BackupRestoreTask}) if the operation has one, and the
+ * cancellation is due to the operation timing out.
*
* @param token the operation token specified when registering the operation
- * @param cancelAll this is passed on when propagating the cancellation
- * @param operationTimedOutCallback a lambda that is invoked with the
- * operation type where the operation is
- * cancelled due to timeout, allowing the
- * caller to do type-specific clean-ups.
+ * @param operationTimedOutCallback a lambda that is invoked with the operation type where the
+ * operation is cancelled due to timeout, allowing the caller to do type-specific clean-ups.
*/
public void cancelOperation(
- int token, boolean cancelAll, IntConsumer operationTimedOutCallback) {
+ int token,
+ IntConsumer operationTimedOutCallback,
+ @CancellationReason int cancellationReason) {
// Notify any synchronous waiters
Operation op = null;
synchronized (mOperationsLock) {
@@ -343,7 +342,7 @@ public class LifecycleOperationStorage implements OperationStorage {
if (DEBUG) {
Slog.v(TAG, "[UserID:" + mUserId + " Invoking cancel on " + op.callback);
}
- op.callback.handleCancel(cancelAll);
+ op.callback.handleCancel(cancellationReason);
}
}
}
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
index 494b9d59a238..8e7a23ccbb25 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -171,7 +171,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* complete backup should be performed.
*
* <p>This task is designed to run on a dedicated thread, with the exception of the {@link
- * #handleCancel(boolean)} method, which can be called from any thread.
+ * BackupRestoreTask#handleCancel(int)} method, which can be called from any thread.
*/
// TODO: Stop poking into BMS state and doing things for it (e.g. synchronizing on public locks)
// TODO: Consider having the caller responsible for some clean-up (like resetting state)
@@ -1208,13 +1208,13 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable {
*
* <p>Note: This method is inherently racy since there are no guarantees about how much of the
* task will be executed after you made the call.
- *
- * @param cancelAll MUST be {@code true}. Will be removed.
*/
@Override
- public void handleCancel(boolean cancelAll) {
+ public void handleCancel(@CancellationReason int cancellationReason) {
// This is called in a thread different from the one that executes method run().
- Preconditions.checkArgument(cancelAll, "Can't partially cancel a key-value backup task");
+ Preconditions.checkArgument(
+ cancellationReason != CancellationReason.TIMEOUT,
+ "Key-value backup task cannot time out");
markCancel();
waitCancel();
}
diff --git a/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java b/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java
index cb491c6f384e..f1829b6966a8 100644
--- a/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java
+++ b/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java
@@ -79,7 +79,7 @@ public class AdbRestoreFinishedLatch implements BackupRestoreTask {
}
@Override
- public void handleCancel(boolean cancelAll) {
+ public void handleCancel(@CancellationReason int cancellationReason) {
Slog.w(TAG, "adb onRestoreFinished() timed out");
mLatch.countDown();
mOperationStorage.removeOperation(mCurrentOpToken);
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 707ae03b3964..1263146fe405 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -1307,7 +1307,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
// The app has timed out handling a restoring file
@Override
- public void handleCancel(boolean cancelAll) {
+ public void handleCancel(@CancellationReason int cancellationReason) {
mOperationStorage.removeOperation(mEphemeralOpToken);
Slog.w(TAG, "Full-data restore target timed out; shutting down");
Bundle monitoringExtras = addRestoreOperationTypeToEvent(/* extras= */ null);
@@ -1555,7 +1555,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
// A call to agent.doRestore() or agent.doRestoreFinished() has timed out
@Override
- public void handleCancel(boolean cancelAll) {
+ public void handleCancel(@CancellationReason int cancellationReason) {
mOperationStorage.removeOperation(mEphemeralOpToken);
Slog.e(TAG, "Timeout restoring application " + mCurrentPackage.packageName);
Bundle monitoringExtras = addRestoreOperationTypeToEvent(/* extras= */ null);
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 8ef79a916530..4b5f06b13885 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1472,8 +1472,8 @@ public class AudioDeviceBroker {
mAudioService.postAccessoryPlugMediaUnmute(device);
}
- /*package*/ int getVssVolumeForDevice(int streamType, int device) {
- return mAudioService.getVssVolumeForDevice(streamType, device);
+ /*package*/ int getVolumeForDeviceIgnoreMute(int streamType, int device) {
+ return mAudioService.getVolumeForDeviceIgnoreMute(streamType, device);
}
/*package*/ int getMaxVssVolumeForStream(int streamType) {
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 829d9ea7495f..2e6d98485e85 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -2482,7 +2482,7 @@ public class AudioDeviceInventory {
@GuardedBy("mDevicesLock")
private void makeHearingAidDeviceAvailable(
String address, String name, int streamType, String eventSource) {
- final int hearingAidVolIndex = mDeviceBroker.getVssVolumeForDevice(streamType,
+ final int hearingAidVolIndex = mDeviceBroker.getVolumeForDeviceIgnoreMute(streamType,
DEVICE_OUT_HEARING_AID);
mDeviceBroker.postSetHearingAidVolumeIndex(hearingAidVolIndex, streamType);
@@ -2672,7 +2672,7 @@ public class AudioDeviceInventory {
}
final int leAudioVolIndex = (volumeIndex == -1)
- ? mDeviceBroker.getVssVolumeForDevice(streamType, device)
+ ? mDeviceBroker.getVolumeForDeviceIgnoreMute(streamType, device)
: volumeIndex;
final int maxIndex = mDeviceBroker.getMaxVssVolumeForStream(streamType);
mDeviceBroker.postSetLeAudioVolumeIndex(leAudioVolIndex, maxIndex, streamType);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index ada1cd73f775..a43e4d98c077 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -529,7 +529,7 @@ public class AudioService extends IAudioService.Stub
*/
private InputDeviceVolumeHelper mInputDeviceVolumeHelper;
- /*package*/ int getVssVolumeForDevice(int stream, int device) {
+ /*package*/ int getVolumeForDeviceIgnoreMute(int stream, int device) {
final VolumeStreamState streamState = mStreamStates.get(stream);
return streamState != null ? streamState.getIndex(device) : -1;
}
@@ -5098,7 +5098,7 @@ public class AudioService extends IAudioService.Stub
}
final int device = absVolumeDevices.toArray(new Integer[0])[0].intValue();
- final int index = getStreamVolume(streamType, device);
+ final int index = getVolumeForDeviceIgnoreMute(streamType, device);
if (DEBUG_VOL) {
Slog.i(TAG, "onUpdateContextualVolumes streamType: " + streamType
diff --git a/services/core/java/com/android/server/audio/SoundDoseHelper.java b/services/core/java/com/android/server/audio/SoundDoseHelper.java
index 643f3308d8f5..67afff79dffd 100644
--- a/services/core/java/com/android/server/audio/SoundDoseHelper.java
+++ b/services/core/java/com/android/server/audio/SoundDoseHelper.java
@@ -724,7 +724,7 @@ public class SoundDoseHelper {
int device = mAudioService.getDeviceForStream(AudioSystem.STREAM_MUSIC);
if (safeDevicesContains(device) && isStreamActive) {
scheduleMusicActiveCheck();
- int index = mAudioService.getVssVolumeForDevice(AudioSystem.STREAM_MUSIC,
+ int index = mAudioService.getVolumeForDeviceIgnoreMute(AudioSystem.STREAM_MUSIC,
device);
if (index > safeMediaVolumeIndex(device)) {
// Approximate cumulative active music time
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 7016c11b69e7..a28069bbf050 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -674,9 +674,9 @@ public final class DisplayManagerService extends SystemService {
mConfigParameterProvider = new DeviceConfigParameterProvider(DeviceConfigInterface.REAL);
mExtraDisplayLoggingPackageName = DisplayProperties.debug_vri_package().orElse(null);
mExtraDisplayEventLogging = !TextUtils.isEmpty(mExtraDisplayLoggingPackageName);
-
+ // TODO(b/400384229): stats service needs to react to mirror-extended switch
mExternalDisplayStatsService = new ExternalDisplayStatsService(mContext, mHandler,
- this::isExtendedDisplayEnabled);
+ this::isExtendedDisplayAllowed);
mDisplayNotificationManager = new DisplayNotificationManager(mFlags, mContext,
mExternalDisplayStatsService);
mExternalDisplayPolicy = new ExternalDisplayPolicy(new ExternalDisplayPolicyInjector());
@@ -690,7 +690,7 @@ public final class DisplayManagerService extends SystemService {
deliverTopologyUpdate(update.first);
};
mDisplayTopologyCoordinator = new DisplayTopologyCoordinator(
- this::isExtendedDisplayEnabled, topologyChangedCallback,
+ this::isExtendedDisplayAllowed, topologyChangedCallback,
new HandlerExecutor(mHandler), mSyncRoot, backupManager::dataChanged);
} else {
mDisplayTopologyCoordinator = null;
@@ -2411,7 +2411,10 @@ public final class DisplayManagerService extends SystemService {
updateLogicalDisplayState(display);
}
- private boolean isExtendedDisplayEnabled() {
+ private boolean isExtendedDisplayAllowed() {
+ if (mFlags.isDisplayContentModeManagementEnabled()) {
+ return true;
+ }
try {
return 0 != Settings.Global.getInt(
mContext.getContentResolver(),
@@ -6045,7 +6048,13 @@ public final class DisplayManagerService extends SystemService {
return;
}
if (inTopology) {
- mDisplayTopologyCoordinator.onDisplayAdded(getDisplayInfo(displayId));
+ var info = getDisplayInfo(displayId);
+ if (info == null) {
+ Slog.w(TAG, "onDisplayBelongToTopologyChanged: cancelled displayId="
+ + displayId + " info=null");
+ return;
+ }
+ mDisplayTopologyCoordinator.onDisplayAdded(info);
} else {
mDisplayTopologyCoordinator.onDisplayRemoved(displayId);
}
diff --git a/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java b/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java
index 997fff58b952..b4df1f76dccb 100644
--- a/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java
+++ b/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java
@@ -69,9 +69,9 @@ class DisplayTopologyCoordinator {
private final SparseArray<String> mDisplayIdToUniqueIdMapping = new SparseArray<>();
/**
- * Check if extended displays are enabled. If not, a topology is not needed.
+ * Check if extended displays are allowed. If not, a topology is not needed.
*/
- private final BooleanSupplier mIsExtendedDisplayEnabled;
+ private final BooleanSupplier mIsExtendedDisplayAllowed;
/**
* Callback used to send topology updates.
@@ -83,21 +83,21 @@ class DisplayTopologyCoordinator {
private final DisplayManagerService.SyncRoot mSyncRoot;
private final Runnable mTopologySavedCallback;
- DisplayTopologyCoordinator(BooleanSupplier isExtendedDisplayEnabled,
+ DisplayTopologyCoordinator(BooleanSupplier isExtendedDisplayAllowed,
Consumer<Pair<DisplayTopology, DisplayTopologyGraph>> onTopologyChangedCallback,
Executor topologyChangeExecutor, DisplayManagerService.SyncRoot syncRoot,
Runnable topologySavedCallback) {
- this(new Injector(), isExtendedDisplayEnabled, onTopologyChangedCallback,
+ this(new Injector(), isExtendedDisplayAllowed, onTopologyChangedCallback,
topologyChangeExecutor, syncRoot, topologySavedCallback);
}
@VisibleForTesting
- DisplayTopologyCoordinator(Injector injector, BooleanSupplier isExtendedDisplayEnabled,
+ DisplayTopologyCoordinator(Injector injector, BooleanSupplier isExtendedDisplayAllowed,
Consumer<Pair<DisplayTopology, DisplayTopologyGraph>> onTopologyChangedCallback,
Executor topologyChangeExecutor, DisplayManagerService.SyncRoot syncRoot,
Runnable topologySavedCallback) {
mTopology = injector.getTopology();
- mIsExtendedDisplayEnabled = isExtendedDisplayEnabled;
+ mIsExtendedDisplayAllowed = isExtendedDisplayAllowed;
mOnTopologyChangedCallback = onTopologyChangedCallback;
mTopologyChangeExecutor = topologyChangeExecutor;
mSyncRoot = syncRoot;
@@ -262,9 +262,9 @@ class DisplayTopologyCoordinator {
return false;
}
if ((info.type == Display.TYPE_EXTERNAL || info.type == Display.TYPE_OVERLAY)
- && !mIsExtendedDisplayEnabled.getAsBoolean()) {
+ && !mIsExtendedDisplayAllowed.getAsBoolean()) {
Slog.d(TAG, "Display " + info.displayId + " not allowed in topology because "
- + "type is EXTERNAL or OVERLAY and !mIsExtendedDisplayEnabled");
+ + "type is EXTERNAL or OVERLAY and !mIsExtendedDisplayAllowed");
return false;
}
return true;
diff --git a/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java b/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
index 600cf7f06981..1a4ead22f658 100644
--- a/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
+++ b/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
@@ -22,6 +22,7 @@ import static com.android.internal.inputmethod.SoftInputShowHideReason.REMOVE_IM
import static com.android.internal.inputmethod.SoftInputShowHideReason.SHOW_IME_SCREENSHOT_FROM_IMMS;
import static com.android.server.EventLogTags.IMF_HIDE_IME;
import static com.android.server.EventLogTags.IMF_SHOW_IME;
+import static com.android.server.inputmethod.ImeProtoLogGroup.IME_VISIBILITY_APPLIER_DEBUG;
import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME;
import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME_EXPLICIT;
import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME_NOT_ALWAYS;
@@ -36,7 +37,6 @@ import android.annotation.UserIdInt;
import android.os.IBinder;
import android.os.ResultReceiver;
import android.util.EventLog;
-import android.util.Slog;
import android.view.MotionEvent;
import android.view.inputmethod.Flags;
import android.view.inputmethod.ImeTracker;
@@ -46,6 +46,7 @@ import android.view.inputmethod.InputMethodManager;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.inputmethod.InputMethodDebug;
import com.android.internal.inputmethod.SoftInputShowHideReason;
+import com.android.internal.protolog.ProtoLog;
import com.android.server.LocalServices;
import com.android.server.wm.ImeTargetVisibilityPolicy;
import com.android.server.wm.WindowManagerInternal;
@@ -58,9 +59,7 @@ import java.util.Objects;
*/
final class DefaultImeVisibilityApplier {
- private static final String TAG = "DefaultImeVisibilityApplier";
-
- private static final boolean DEBUG = InputMethodManagerService.DEBUG;
+ static final String TAG = "DefaultImeVisibilityApplier";
private InputMethodManagerService mService;
@@ -93,11 +92,10 @@ final class DefaultImeVisibilityApplier {
final var bindingController = userData.mBindingController;
final IInputMethodInvoker curMethod = bindingController.getCurMethod();
if (curMethod != null) {
- if (DEBUG) {
- Slog.v(TAG, "Calling " + curMethod + ".showSoftInput(" + showInputToken
- + ", " + showFlags + ", " + resultReceiver + ") for reason: "
- + InputMethodDebug.softInputDisplayReasonToString(reason));
- }
+ ProtoLog.v(IME_VISIBILITY_APPLIER_DEBUG,
+ "Calling %s.showSoftInput(%s, %s, %s) for reason: %s", curMethod,
+ showInputToken, showFlags, resultReceiver,
+ InputMethodDebug.softInputDisplayReasonToString(reason));
// TODO(b/192412909): Check if we can always call onShowHideSoftInputRequested() or not.
if (curMethod.showSoftInput(showInputToken, statsToken, showFlags, resultReceiver)) {
if (DEBUG_IME_VISIBILITY) {
@@ -136,11 +134,9 @@ final class DefaultImeVisibilityApplier {
// delivered to the IME process as an IPC. Hence the inconsistency between
// IMMS#mInputShown and IMMS#mImeWindowVis should be resolved spontaneously in
// the final state.
- if (DEBUG) {
- Slog.v(TAG, "Calling " + curMethod + ".hideSoftInput(0, " + hideInputToken
- + ", " + resultReceiver + ") for reason: "
- + InputMethodDebug.softInputDisplayReasonToString(reason));
- }
+ ProtoLog.v(IME_VISIBILITY_APPLIER_DEBUG,
+ "Calling %s.hideSoftInput(0, %s, %s) for reason: %s", curMethod, hideInputToken,
+ resultReceiver, InputMethodDebug.softInputDisplayReasonToString(reason));
// TODO(b/192412909): Check if we can always call onShowHideSoftInputRequested() or not.
if (curMethod.hideSoftInput(hideInputToken, statsToken, 0, resultReceiver)) {
if (DEBUG_IME_VISIBILITY) {
diff --git a/services/core/java/com/android/server/inputmethod/ImeProtoLogGroup.java b/services/core/java/com/android/server/inputmethod/ImeProtoLogGroup.java
index f9a56effc800..ea4e29564cc0 100644
--- a/services/core/java/com/android/server/inputmethod/ImeProtoLogGroup.java
+++ b/services/core/java/com/android/server/inputmethod/ImeProtoLogGroup.java
@@ -23,7 +23,11 @@ import java.util.UUID;
public enum ImeProtoLogGroup implements IProtoLogGroup {
// TODO(b/393561240): add info/warn/error log level and replace in IMMS
IMMS_DEBUG(Consts.ENABLE_DEBUG, false, false,
- InputMethodManagerService.TAG);
+ InputMethodManagerService.TAG),
+ IME_VISIBILITY_APPLIER_DEBUG(Consts.ENABLE_DEBUG, false, false,
+ DefaultImeVisibilityApplier.TAG),
+ IME_VIS_STATE_COMPUTER_DEBUG(Consts.ENABLE_DEBUG, false, false,
+ ImeVisibilityStateComputer.TAG);
private final boolean mEnabled;
private volatile boolean mLogToProto;
diff --git a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
index 5fe8318dbb3f..69353becc692 100644
--- a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
+++ b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
@@ -32,6 +32,7 @@ import static android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import static com.android.internal.inputmethod.InputMethodDebug.softInputModeToString;
import static com.android.internal.inputmethod.SoftInputShowHideReason.REMOVE_IME_SCREENSHOT_FROM_IMMS;
import static com.android.internal.inputmethod.SoftInputShowHideReason.SHOW_IME_SCREENSHOT_FROM_IMMS;
+import static com.android.server.inputmethod.ImeProtoLogGroup.IME_VIS_STATE_COMPUTER_DEBUG;
import static com.android.server.inputmethod.InputMethodManagerService.computeImeDisplayIdForTarget;
import android.accessibilityservice.AccessibilityService;
@@ -58,6 +59,7 @@ import android.view.inputmethod.InputMethodManager;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.inputmethod.SoftInputShowHideReason;
+import com.android.internal.protolog.ProtoLog;
import com.android.server.LocalServices;
import com.android.server.pm.UserManagerInternal;
import com.android.server.wm.WindowManagerInternal;
@@ -72,9 +74,7 @@ import java.util.WeakHashMap;
*/
public final class ImeVisibilityStateComputer {
- private static final String TAG = "ImeVisibilityStateComputer";
-
- private static final boolean DEBUG = InputMethodManagerService.DEBUG;
+ static final String TAG = "ImeVisibilityStateComputer";
@UserIdInt
private final int mUserId;
@@ -292,12 +292,14 @@ public final class ImeVisibilityStateComputer {
@InputMethodManager.HideFlags int hideFlags) {
if ((hideFlags & InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
&& (mRequestedShowExplicitly || mShowForced)) {
- if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
+ ProtoLog.v(IME_VIS_STATE_COMPUTER_DEBUG,
+ "Not hiding: explicit show not cancelled by non-explicit hide");
ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_IMPLICIT);
return false;
}
if (mShowForced && (hideFlags & InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
- if (DEBUG) Slog.v(TAG, "Not hiding: forced show not cancelled by not-always hide");
+ ProtoLog.v(IME_VIS_STATE_COMPUTER_DEBUG,
+ "Not hiding: forced show not cancelled by not-always hide");
ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS);
return false;
}
@@ -417,8 +419,8 @@ public final class ImeVisibilityStateComputer {
@GuardedBy("ImfLock.class")
private void setWindowStateInner(IBinder windowToken, @NonNull ImeTargetWindowState newState) {
- if (DEBUG) Slog.d(TAG, "setWindowStateInner, windowToken=" + windowToken
- + ", state=" + newState);
+ ProtoLog.v(IME_VIS_STATE_COMPUTER_DEBUG, "setWindowStateInner, windowToken=%s, state=%s",
+ windowToken, newState);
mRequestWindowStateMap.put(windowToken, newState);
}
@@ -466,7 +468,7 @@ public final class ImeVisibilityStateComputer {
// Because the app might leverage these flags to hide soft-keyboard with showing their own
// UI for input.
if (state.hasEditorFocused() && shouldRestoreImeVisibility(state)) {
- if (DEBUG) Slog.v(TAG, "Will show input to restore visibility");
+ ProtoLog.v(IME_VIS_STATE_COMPUTER_DEBUG, "Will show input to restore visibility");
// Inherit the last requested IME visible state when the target window is still
// focused with an editor.
state.setRequestedImeVisible(true);
@@ -483,7 +485,8 @@ public final class ImeVisibilityStateComputer {
// There is no focus view, and this window will
// be behind any soft input window, so hide the
// soft input window if it is shown.
- if (DEBUG) Slog.v(TAG, "Unspecified window will hide input");
+ ProtoLog.v(IME_VIS_STATE_COMPUTER_DEBUG,
+ "Unspecified window will hide input");
return new ImeVisibilityResult(STATE_HIDE_IME_NOT_ALWAYS,
SoftInputShowHideReason.HIDE_UNSPECIFIED_WINDOW);
}
@@ -495,7 +498,7 @@ public final class ImeVisibilityStateComputer {
// them good context without input information being obscured
// by the IME) or if running on a large screen where there
// is more room for the target window + IME.
- if (DEBUG) Slog.v(TAG, "Unspecified window will show input");
+ ProtoLog.v(IME_VIS_STATE_COMPUTER_DEBUG, "Unspecified window will show input");
return new ImeVisibilityResult(STATE_SHOW_IME_IMPLICIT,
SoftInputShowHideReason.SHOW_AUTO_EDITOR_FORWARD_NAV);
}
@@ -513,7 +516,8 @@ public final class ImeVisibilityStateComputer {
// the WindowState, as they're already in the correct state
break;
} else if (isForwardNavigation) {
- if (DEBUG) Slog.v(TAG, "Window asks to hide input going forward");
+ ProtoLog.v(IME_VIS_STATE_COMPUTER_DEBUG,
+ "Window asks to hide input going forward");
return new ImeVisibilityResult(STATE_HIDE_IME_EXPLICIT,
SoftInputShowHideReason.HIDE_STATE_HIDDEN_FORWARD_NAV);
}
@@ -524,7 +528,7 @@ public final class ImeVisibilityStateComputer {
// the WindowState, as they're already in the correct state
break;
} else if (state.hasImeFocusChanged()) {
- if (DEBUG) Slog.v(TAG, "Window asks to hide input");
+ ProtoLog.v(IME_VIS_STATE_COMPUTER_DEBUG, "Window asks to hide input");
return new ImeVisibilityResult(STATE_HIDE_IME_EXPLICIT,
SoftInputShowHideReason.HIDE_ALWAYS_HIDDEN_STATE);
}
@@ -532,7 +536,8 @@ public final class ImeVisibilityStateComputer {
case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
if (isForwardNavigation) {
if (allowVisible) {
- if (DEBUG) Slog.v(TAG, "Window asks to show input going forward");
+ ProtoLog.v(IME_VIS_STATE_COMPUTER_DEBUG,
+ "Window asks to show input going forward");
return new ImeVisibilityResult(STATE_SHOW_IME_IMPLICIT,
SoftInputShowHideReason.SHOW_STATE_VISIBLE_FORWARD_NAV);
} else {
@@ -543,7 +548,7 @@ public final class ImeVisibilityStateComputer {
}
break;
case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
- if (DEBUG) Slog.v(TAG, "Window asks to always show input");
+ ProtoLog.v(IME_VIS_STATE_COMPUTER_DEBUG, "Window asks to always show input");
if (allowVisible) {
if (state.hasImeFocusChanged()) {
return new ImeVisibilityResult(STATE_SHOW_IME_IMPLICIT,
@@ -565,7 +570,8 @@ public final class ImeVisibilityStateComputer {
// To maintain compatibility, we are now hiding the IME when we don't have
// an editor upon refocusing a window.
if (state.isStartInputByGainFocus()) {
- if (DEBUG) Slog.v(TAG, "Same window without editor will hide input");
+ ProtoLog.v(IME_VIS_STATE_COMPUTER_DEBUG,
+ "Same window without editor will hide input");
return new ImeVisibilityResult(STATE_HIDE_IME_EXPLICIT,
SoftInputShowHideReason.HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR);
}
@@ -579,7 +585,7 @@ public final class ImeVisibilityStateComputer {
// 1) SOFT_INPUT_STATE_UNCHANGED state without an editor
// 2) SOFT_INPUT_STATE_VISIBLE state without an editor
// 3) SOFT_INPUT_STATE_ALWAYS_VISIBLE state without an editor
- if (DEBUG) Slog.v(TAG, "Window without editor will hide input");
+ ProtoLog.v(IME_VIS_STATE_COMPUTER_DEBUG, "Window without editor will hide input");
if (Flags.refactorInsetsController()) {
state.setRequestedImeVisible(false);
}
diff --git a/services/core/java/com/android/server/media/quality/MediaQualityService.java b/services/core/java/com/android/server/media/quality/MediaQualityService.java
index 91a2843ccaf7..9e38435ff7f1 100644
--- a/services/core/java/com/android/server/media/quality/MediaQualityService.java
+++ b/services/core/java/com/android/server/media/quality/MediaQualityService.java
@@ -48,7 +48,6 @@ import android.media.quality.IMediaQualityManager;
import android.media.quality.IPictureProfileCallback;
import android.media.quality.ISoundProfileCallback;
import android.media.quality.MediaQualityContract.BaseParameters;
-import android.media.quality.MediaQualityManager;
import android.media.quality.ParameterCapability;
import android.media.quality.PictureProfile;
import android.media.quality.PictureProfileHandle;
@@ -187,7 +186,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mPictureProfileLock")
@Override
- public PictureProfile createPictureProfile(PictureProfile pp, UserHandle user) {
+ public PictureProfile createPictureProfile(PictureProfile pp, int userId) {
if ((pp.getPackageName() != null && !pp.getPackageName().isEmpty()
&& !incomingPackageEqualsCallingUidPackage(pp.getPackageName()))
&& !hasGlobalPictureQualityServicePermission()) {
@@ -221,7 +220,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mPictureProfileLock")
@Override
- public void updatePictureProfile(String id, PictureProfile pp, UserHandle user) {
+ public void updatePictureProfile(String id, PictureProfile pp, int userId) {
Long dbId = mPictureProfileTempIdMap.getKey(id);
if (!hasPermissionToUpdatePictureProfile(dbId, pp)) {
mMqManagerNotifier.notifyOnPictureProfileError(id,
@@ -249,7 +248,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mPictureProfileLock")
@Override
- public void removePictureProfile(String id, UserHandle user) {
+ public void removePictureProfile(String id, int userId) {
synchronized (mPictureProfileLock) {
Long dbId = mPictureProfileTempIdMap.getKey(id);
@@ -290,10 +289,8 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mPictureProfileLock")
@Override
- public PictureProfile getPictureProfile(int type, String name, Bundle options,
- UserHandle user) {
- boolean includeParams =
- options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false);
+ public PictureProfile getPictureProfile(int type, String name, boolean includeParams,
+ int userId) {
String selection = BaseParameters.PARAMETER_TYPE + " = ? AND "
+ BaseParameters.PARAMETER_NAME + " = ? AND "
+ BaseParameters.PARAMETER_PACKAGE + " = ?";
@@ -327,7 +324,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mPictureProfileLock")
@Override
public List<PictureProfile> getPictureProfilesByPackage(
- String packageName, Bundle options, UserHandle user) {
+ String packageName, boolean includeParams, int userId) {
if (!hasGlobalPictureQualityServicePermission()) {
mMqManagerNotifier.notifyOnPictureProfileError(null,
PictureProfile.ERROR_NO_PERMISSION,
@@ -335,8 +332,6 @@ public class MediaQualityService extends SystemService {
}
synchronized (mPictureProfileLock) {
- boolean includeParams =
- options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false);
String selection = BaseParameters.PARAMETER_PACKAGE + " = ?";
String[] selectionArguments = {packageName};
return mMqDatabaseUtils.getPictureProfilesBasedOnConditions(MediaQualityUtils
@@ -347,17 +342,17 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mPictureProfileLock")
@Override
- public List<PictureProfile> getAvailablePictureProfiles(Bundle options, UserHandle user) {
+ public List<PictureProfile> getAvailablePictureProfiles(boolean includeParams, int userId) {
String packageName = getPackageOfCallingUid();
if (packageName != null) {
- return getPictureProfilesByPackage(packageName, options, user);
+ return getPictureProfilesByPackage(packageName, includeParams, userId);
}
return new ArrayList<>();
}
@GuardedBy("mPictureProfileLock")
@Override
- public boolean setDefaultPictureProfile(String profileId, UserHandle user) {
+ public boolean setDefaultPictureProfile(String profileId, int userId) {
if (!hasGlobalPictureQualityServicePermission()) {
mMqManagerNotifier.notifyOnPictureProfileError(profileId,
PictureProfile.ERROR_NO_PERMISSION,
@@ -387,7 +382,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mPictureProfileLock")
@Override
- public List<String> getPictureProfilePackageNames(UserHandle user) {
+ public List<String> getPictureProfilePackageNames(int userId) {
if (!hasGlobalPictureQualityServicePermission()) {
mMqManagerNotifier.notifyOnPictureProfileError(null,
PictureProfile.ERROR_NO_PERMISSION,
@@ -406,7 +401,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mPictureProfileLock")
@Override
- public List<PictureProfileHandle> getPictureProfileHandle(String[] ids, UserHandle user) {
+ public List<PictureProfileHandle> getPictureProfileHandle(String[] ids, int userId) {
List<PictureProfileHandle> toReturn = new ArrayList<>();
synchronized (mPictureProfileLock) {
for (String id : ids) {
@@ -423,13 +418,13 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mSoundProfileLock")
@Override
- public List<SoundProfileHandle> getSoundProfileHandle(String[] ids, UserHandle user) {
+ public List<SoundProfileHandle> getSoundProfileHandle(String[] ids, int userId) {
List<SoundProfileHandle> toReturn = new ArrayList<>();
synchronized (mSoundProfileLock) {
for (String id : ids) {
Long key = mSoundProfileTempIdMap.getKey(id);
if (key != null) {
- toReturn.add(new SoundProfileHandle(key));
+ toReturn.add(MediaQualityUtils.SOUND_PROFILE_HANDLE_NONE);
} else {
toReturn.add(null);
}
@@ -440,7 +435,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mSoundProfileLock")
@Override
- public SoundProfile createSoundProfile(SoundProfile sp, UserHandle user) {
+ public SoundProfile createSoundProfile(SoundProfile sp, int userId) {
if ((sp.getPackageName() != null && !sp.getPackageName().isEmpty()
&& !incomingPackageEqualsCallingUidPackage(sp.getPackageName()))
&& !hasGlobalPictureQualityServicePermission()) {
@@ -473,7 +468,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mSoundProfileLock")
@Override
- public void updateSoundProfile(String id, SoundProfile sp, UserHandle user) {
+ public void updateSoundProfile(String id, SoundProfile sp, int userId) {
Long dbId = mSoundProfileTempIdMap.getKey(id);
if (!hasPermissionToUpdateSoundProfile(dbId, sp)) {
mMqManagerNotifier.notifyOnSoundProfileError(id, SoundProfile.ERROR_NO_PERMISSION,
@@ -502,7 +497,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mSoundProfileLock")
@Override
- public void removeSoundProfile(String id, UserHandle user) {
+ public void removeSoundProfile(String id, int userId) {
synchronized (mSoundProfileLock) {
Long dbId = mSoundProfileTempIdMap.getKey(id);
SoundProfile toDelete = mMqDatabaseUtils.getSoundProfile(dbId);
@@ -542,10 +537,8 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mSoundProfileLock")
@Override
- public SoundProfile getSoundProfile(int type, String name, Bundle options,
- UserHandle user) {
- boolean includeParams =
- options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false);
+ public SoundProfile getSoundProfile(int type, String name, boolean includeParams,
+ int userId) {
String selection = BaseParameters.PARAMETER_TYPE + " = ? AND "
+ BaseParameters.PARAMETER_NAME + " = ? AND "
+ BaseParameters.PARAMETER_PACKAGE + " = ?";
@@ -579,15 +572,13 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mSoundProfileLock")
@Override
public List<SoundProfile> getSoundProfilesByPackage(
- String packageName, Bundle options, UserHandle user) {
+ String packageName, boolean includeParams, int userId) {
if (!hasGlobalSoundQualityServicePermission()) {
mMqManagerNotifier.notifyOnSoundProfileError(null, SoundProfile.ERROR_NO_PERMISSION,
Binder.getCallingUid(), Binder.getCallingPid());
}
synchronized (mSoundProfileLock) {
- boolean includeParams =
- options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false);
String selection = BaseParameters.PARAMETER_PACKAGE + " = ?";
String[] selectionArguments = {packageName};
return mMqDatabaseUtils.getSoundProfilesBasedOnConditions(MediaQualityUtils
@@ -598,17 +589,17 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mSoundProfileLock")
@Override
- public List<SoundProfile> getAvailableSoundProfiles(Bundle options, UserHandle user) {
+ public List<SoundProfile> getAvailableSoundProfiles(boolean includeParams, int userId) {
String packageName = getPackageOfCallingUid();
if (packageName != null) {
- return getSoundProfilesByPackage(packageName, options, user);
+ return getSoundProfilesByPackage(packageName, includeParams, userId);
}
return new ArrayList<>();
}
@GuardedBy("mSoundProfileLock")
@Override
- public boolean setDefaultSoundProfile(String profileId, UserHandle user) {
+ public boolean setDefaultSoundProfile(String profileId, int userId) {
if (!hasGlobalSoundQualityServicePermission()) {
mMqManagerNotifier.notifyOnSoundProfileError(profileId,
SoundProfile.ERROR_NO_PERMISSION,
@@ -638,7 +629,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mSoundProfileLock")
@Override
- public List<String> getSoundProfilePackageNames(UserHandle user) {
+ public List<String> getSoundProfilePackageNames(int userId) {
if (!hasGlobalSoundQualityServicePermission()) {
mMqManagerNotifier.notifyOnSoundProfileError(null, SoundProfile.ERROR_NO_PERMISSION,
Binder.getCallingUid(), Binder.getCallingPid());
@@ -737,7 +728,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mAmbientBacklightLock")
@Override
public void setAmbientBacklightSettings(
- AmbientBacklightSettings settings, UserHandle user) {
+ AmbientBacklightSettings settings, int userId) {
if (DEBUG) {
Slogf.d(TAG, "setAmbientBacklightSettings " + settings);
}
@@ -775,7 +766,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mAmbientBacklightLock")
@Override
- public void setAmbientBacklightEnabled(boolean enabled, UserHandle user) {
+ public void setAmbientBacklightEnabled(boolean enabled, int userId) {
if (DEBUG) {
Slogf.d(TAG, "setAmbientBacklightEnabled " + enabled);
}
@@ -795,7 +786,7 @@ public class MediaQualityService extends SystemService {
@Override
public List<ParameterCapability> getParameterCapabilities(
- List<String> names, UserHandle user) {
+ List<String> names, int userId) {
byte[] byteArray = MediaQualityUtils.convertParameterToByteArray(names);
ParamCapability[] caps = new ParamCapability[byteArray.length];
try {
@@ -828,7 +819,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mPictureProfileLock")
@Override
- public List<String> getPictureProfileAllowList(UserHandle user) {
+ public List<String> getPictureProfileAllowList(int userId) {
if (!hasGlobalPictureQualityServicePermission()) {
mMqManagerNotifier.notifyOnPictureProfileError(null,
PictureProfile.ERROR_NO_PERMISSION,
@@ -844,7 +835,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mPictureProfileLock")
@Override
- public void setPictureProfileAllowList(List<String> packages, UserHandle user) {
+ public void setPictureProfileAllowList(List<String> packages, int userId) {
if (!hasGlobalPictureQualityServicePermission()) {
mMqManagerNotifier.notifyOnPictureProfileError(null,
PictureProfile.ERROR_NO_PERMISSION,
@@ -857,7 +848,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mSoundProfileLock")
@Override
- public List<String> getSoundProfileAllowList(UserHandle user) {
+ public List<String> getSoundProfileAllowList(int userId) {
if (!hasGlobalSoundQualityServicePermission()) {
mMqManagerNotifier.notifyOnSoundProfileError(null, SoundProfile.ERROR_NO_PERMISSION,
Binder.getCallingUid(), Binder.getCallingPid());
@@ -872,7 +863,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mSoundProfileLock")
@Override
- public void setSoundProfileAllowList(List<String> packages, UserHandle user) {
+ public void setSoundProfileAllowList(List<String> packages, int userId) {
if (!hasGlobalSoundQualityServicePermission()) {
mMqManagerNotifier.notifyOnSoundProfileError(null, SoundProfile.ERROR_NO_PERMISSION,
Binder.getCallingUid(), Binder.getCallingPid());
@@ -883,13 +874,13 @@ public class MediaQualityService extends SystemService {
}
@Override
- public boolean isSupported(UserHandle user) {
+ public boolean isSupported(int userId) {
return false;
}
@GuardedBy("mPictureProfileLock")
@Override
- public void setAutoPictureQualityEnabled(boolean enabled, UserHandle user) {
+ public void setAutoPictureQualityEnabled(boolean enabled, int userId) {
if (!hasGlobalPictureQualityServicePermission()) {
mMqManagerNotifier.notifyOnPictureProfileError(null,
PictureProfile.ERROR_NO_PERMISSION,
@@ -910,7 +901,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mPictureProfileLock")
@Override
- public boolean isAutoPictureQualityEnabled(UserHandle user) {
+ public boolean isAutoPictureQualityEnabled(int userId) {
synchronized (mPictureProfileLock) {
try {
if (mMediaQuality != null) {
@@ -927,7 +918,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mPictureProfileLock")
@Override
- public void setSuperResolutionEnabled(boolean enabled, UserHandle user) {
+ public void setSuperResolutionEnabled(boolean enabled, int userId) {
if (!hasGlobalPictureQualityServicePermission()) {
mMqManagerNotifier.notifyOnPictureProfileError(null,
PictureProfile.ERROR_NO_PERMISSION,
@@ -948,7 +939,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mPictureProfileLock")
@Override
- public boolean isSuperResolutionEnabled(UserHandle user) {
+ public boolean isSuperResolutionEnabled(int userId) {
synchronized (mPictureProfileLock) {
try {
if (mMediaQuality != null) {
@@ -965,7 +956,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mSoundProfileLock")
@Override
- public void setAutoSoundQualityEnabled(boolean enabled, UserHandle user) {
+ public void setAutoSoundQualityEnabled(boolean enabled, int userId) {
if (!hasGlobalSoundQualityServicePermission()) {
mMqManagerNotifier.notifyOnSoundProfileError(null, SoundProfile.ERROR_NO_PERMISSION,
Binder.getCallingUid(), Binder.getCallingPid());
@@ -986,7 +977,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mSoundProfileLock")
@Override
- public boolean isAutoSoundQualityEnabled(UserHandle user) {
+ public boolean isAutoSoundQualityEnabled(int userId) {
synchronized (mSoundProfileLock) {
try {
if (mMediaQuality != null) {
@@ -1003,7 +994,7 @@ public class MediaQualityService extends SystemService {
@GuardedBy("mAmbientBacklightLock")
@Override
- public boolean isAmbientBacklightEnabled(UserHandle user) {
+ public boolean isAmbientBacklightEnabled(int userId) {
return false;
}
}
diff --git a/services/core/java/com/android/server/media/quality/MediaQualityUtils.java b/services/core/java/com/android/server/media/quality/MediaQualityUtils.java
index 88d3f1ff7c52..303c96750098 100644
--- a/services/core/java/com/android/server/media/quality/MediaQualityUtils.java
+++ b/services/core/java/com/android/server/media/quality/MediaQualityUtils.java
@@ -60,6 +60,11 @@ public final class MediaQualityUtils {
private static final String TAG = "MediaQualityUtils";
public static final String SETTINGS = "settings";
+ public static final SoundProfileHandle SOUND_PROFILE_HANDLE_NONE = new SoundProfileHandle();
+ static {
+ SOUND_PROFILE_HANDLE_NONE.id = -10000;
+ }
+
/**
* Convert PictureParameter List to PersistableBundle.
*/
@@ -1022,7 +1027,7 @@ public final class MediaQualityUtils {
getInputId(cursor),
getPackageName(cursor),
jsonToPersistableBundle(getSettingsString(cursor)),
- SoundProfileHandle.NONE
+ SOUND_PROFILE_HANDLE_NONE
);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index bfe0d32f4cb6..7a544cf1c26c 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1075,6 +1075,7 @@ public class NotificationManagerService extends SystemService {
summary.getSbn().getNotification().getGroupAlertBehavior();
if (notificationForceGrouping()) {
+ summary.getNotification().flags |= Notification.FLAG_SILENT;
if (!summary.getChannel().getId().equals(summaryAttr.channelId)) {
NotificationChannel newChannel = mPreferencesHelper.getNotificationChannel(pkg,
summary.getUid(), summaryAttr.channelId, false);
@@ -7450,6 +7451,7 @@ public class NotificationManagerService extends SystemService {
// Override group key early for forced grouped notifications
r.setOverrideGroupKey(groupName);
}
+ r.getNotification().flags |= Notification.FLAG_SILENT;
}
addAutoGroupAdjustment(r, groupName);
diff --git a/services/core/java/com/android/server/wm/ActivitySnapshotController.java b/services/core/java/com/android/server/wm/ActivitySnapshotController.java
index 21628341ea62..cb122f2080a2 100644
--- a/services/core/java/com/android/server/wm/ActivitySnapshotController.java
+++ b/services/core/java/com/android/server/wm/ActivitySnapshotController.java
@@ -107,8 +107,7 @@ class ActivitySnapshotController extends AbsAppSnapshotController<ActivityRecord
&& !ActivityManager.isLowRamDeviceStatic(); // Don't support Android Go
setSnapshotEnabled(snapshotEnabled);
mSnapshotPersistQueue = persistQueue;
- mPersistInfoProvider = createPersistInfoProvider(service,
- Environment::getDataSystemCeDirectory);
+ mPersistInfoProvider = createPersistInfoProvider(service);
mPersister = new TaskSnapshotPersister(
persistQueue,
mPersistInfoProvider,
@@ -117,6 +116,11 @@ class ActivitySnapshotController extends AbsAppSnapshotController<ActivityRecord
initialize(new ActivitySnapshotCache());
}
+ @VisibleForTesting
+ PersistInfoProvider createPersistInfoProvider(WindowManagerService service) {
+ return createPersistInfoProvider(service, Environment::getDataSystemCeDirectory);
+ }
+
@Override
protected float initSnapshotScale() {
final float config = mService.mContext.getResources().getFloat(
diff --git a/services/core/java/com/android/server/wm/BaseAppSnapshotPersister.java b/services/core/java/com/android/server/wm/BaseAppSnapshotPersister.java
index 5db02dff8351..aaa5a0074506 100644
--- a/services/core/java/com/android/server/wm/BaseAppSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/BaseAppSnapshotPersister.java
@@ -16,10 +16,20 @@
package com.android.server.wm;
+import static com.android.server.wm.AbsAppSnapshotController.TAG;
+
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import android.window.TaskSnapshot;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.window.flags.Flags;
+
import java.io.File;
+import java.util.UUID;
class BaseAppSnapshotPersister {
static final String LOW_RES_FILE_POSTFIX = "_reduced";
@@ -29,6 +39,7 @@ class BaseAppSnapshotPersister {
// Shared with SnapshotPersistQueue
protected final Object mLock;
protected final SnapshotPersistQueue mSnapshotPersistQueue;
+ @VisibleForTesting
protected final PersistInfoProvider mPersistInfoProvider;
BaseAppSnapshotPersister(SnapshotPersistQueue persistQueue,
@@ -79,6 +90,8 @@ class BaseAppSnapshotPersister {
private final boolean mEnableLowResSnapshots;
private final float mLowResScaleFactor;
private final boolean mUse16BitFormat;
+ private final SparseBooleanArray mInitializedUsers = new SparseBooleanArray();
+ private final SparseArray<File> mScrambleDirectories = new SparseArray<>();
PersistInfoProvider(DirectoryResolver directoryResolver, String dirName,
boolean enableLowResSnapshots, float lowResScaleFactor, boolean use16BitFormat) {
@@ -91,9 +104,80 @@ class BaseAppSnapshotPersister {
@NonNull
File getDirectory(int userId) {
+ if (Flags.scrambleSnapshotFileName()) {
+ final File directory = getOrInitScrambleDirectory(userId);
+ if (directory != null) {
+ return directory;
+ }
+ }
+ return getBaseDirectory(userId);
+ }
+
+ @NonNull
+ private File getBaseDirectory(int userId) {
return new File(mDirectoryResolver.getSystemDirectoryForUser(userId), mDirName);
}
+ @Nullable
+ private File getOrInitScrambleDirectory(int userId) {
+ synchronized (mScrambleDirectories) {
+ if (mInitializedUsers.get(userId)) {
+ return mScrambleDirectories.get(userId);
+ }
+ mInitializedUsers.put(userId, true);
+ final File scrambledDirectory = getScrambleDirectory(userId);
+ final File baseDir = getBaseDirectory(userId);
+ String newName = null;
+ // If directory exists, rename
+ if (scrambledDirectory.exists()) {
+ newName = UUID.randomUUID().toString();
+ final File scrambleTo = new File(baseDir, newName);
+ if (!scrambledDirectory.renameTo(scrambleTo)) {
+ Slog.w(TAG, "SnapshotPersister rename scramble folder fail.");
+ return null;
+ }
+ } else {
+ // If directory not exists, mkDir.
+ if (!baseDir.exists() && !baseDir.mkdir()) {
+ Slog.w(TAG, "SnapshotPersister make base folder fail.");
+ return null;
+ }
+ if (!scrambledDirectory.mkdir()) {
+ Slog.e(TAG, "SnapshotPersister make scramble folder fail");
+ return null;
+ }
+ // Move any existing files to this folder.
+ final String[] files = baseDir.list();
+ if (files != null) {
+ for (String file : files) {
+ final File original = new File(baseDir, file);
+ if (original.isDirectory()) {
+ newName = file;
+ } else {
+ File to = new File(scrambledDirectory, file);
+ original.renameTo(to);
+ }
+ }
+ }
+ }
+ final File newFolder = new File(baseDir, newName);
+ mScrambleDirectories.put(userId, newFolder);
+ return newFolder;
+ }
+ }
+
+ @NonNull
+ private File getScrambleDirectory(int userId) {
+ final File dir = getBaseDirectory(userId);
+ final String[] directories = dir.list(
+ (current, name) -> new File(current, name).isDirectory());
+ if (directories != null && directories.length > 0) {
+ return new File(dir, directories[0]);
+ } else {
+ return new File(dir, UUID.randomUUID().toString());
+ }
+ }
+
/**
* Return if task snapshots are stored in 16 bit pixel format.
*
diff --git a/services/core/java/com/android/server/wm/DesktopModeHelper.java b/services/core/java/com/android/server/wm/DesktopModeHelper.java
index d91fca9e2816..dc42b32967e2 100644
--- a/services/core/java/com/android/server/wm/DesktopModeHelper.java
+++ b/services/core/java/com/android/server/wm/DesktopModeHelper.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import static android.app.Flags.enableConnectedDisplaysWallpaper;
-import static android.window.DesktopExperienceFlags.ENABLE_PROJECTED_DISPLAY_DESKTOP_MODE;
import android.annotation.NonNull;
import android.content.Context;
@@ -67,7 +66,7 @@ public final class DesktopModeHelper {
* Return {@code true} if the current device can hosts desktop sessions on its internal display.
*/
@VisibleForTesting
- private static boolean canInternalDisplayHostDesktops(@NonNull Context context) {
+ static boolean canInternalDisplayHostDesktops(@NonNull Context context) {
return context.getResources().getBoolean(R.bool.config_canInternalDisplayHostDesktops);
}
@@ -84,11 +83,8 @@ public final class DesktopModeHelper {
if (!shouldEnforceDeviceRestrictions()) {
return true;
}
- // If projected display is enabled, #canInternalDisplayHostDesktops is no longer a
- // requirement.
- final boolean desktopModeSupported = ENABLE_PROJECTED_DISPLAY_DESKTOP_MODE.isTrue()
- ? isDesktopModeSupported(context) : (isDesktopModeSupported(context)
- && canInternalDisplayHostDesktops(context));
+ final boolean desktopModeSupported = isDesktopModeSupported(context)
+ && canInternalDisplayHostDesktops(context);
final boolean desktopModeSupportedByDevOptions =
Flags.enableDesktopModeThroughDevOption()
&& isDesktopModeDevOptionsSupported(context);
diff --git a/services/core/java/com/android/server/wm/DisplayWindowListenerController.java b/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
index fa7a99d55896..d90fff229cd9 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
@@ -40,14 +40,14 @@ class DisplayWindowListenerController {
}
int[] registerListener(IDisplayWindowListener listener) {
+ mDisplayListeners.register(listener);
+ final IntArray displayIds = new IntArray();
synchronized (mService.mGlobalLock) {
- mDisplayListeners.register(listener);
- final IntArray displayIds = new IntArray();
mService.mAtmService.mRootWindowContainer.forAllDisplays((displayContent) -> {
displayIds.add(displayContent.mDisplayId);
});
- return displayIds.toArray();
}
+ return displayIds.toArray();
}
void unregisterListener(IDisplayWindowListener listener) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 215d6ca964eb..0ad976c38565 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -245,6 +245,7 @@ import static android.app.admin.ProvisioningException.ERROR_REMOVE_NON_REQUIRED_
import static android.app.admin.ProvisioningException.ERROR_SETTING_PROFILE_OWNER_FAILED;
import static android.app.admin.ProvisioningException.ERROR_SET_DEVICE_OWNER_FAILED;
import static android.app.admin.ProvisioningException.ERROR_STARTING_PROFILE_FAILED;
+import static android.content.Context.RECEIVER_NOT_EXPORTED;
import static android.content.Intent.ACTION_MANAGED_PROFILE_AVAILABLE;
import static android.content.Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
@@ -486,6 +487,7 @@ import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
+import android.telephony.euicc.EuiccManager;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.ArrayMap;
@@ -643,6 +645,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
static final String ACTION_PROFILE_OFF_DEADLINE =
"com.android.server.ACTION_PROFILE_OFF_DEADLINE";
+ /** Broadcast action invoked when a managed eSIM is removed while deleting work profile. */
+ private static final String ACTION_ESIM_REMOVED_WITH_MANAGED_PROFILE =
+ "com.android.server.ACTION_ESIM_REMOVED_WITH_MANAGED_PROFILE";
+
+ /** Extra for the subscription ID of the managed eSIM removed while deleting work profile. */
+ private static final String EXTRA_REMOVED_ESIM_SUBSCRIPTION_ID =
+ "com.android.server.EXTRA_ESIM_REMOVED_WITH_MANAGED_PROFILE_SUBSCRIPTION_ID";
+
private static final String CALLED_FROM_PARENT = "calledFromParent";
private static final String NOT_CALLED_FROM_PARENT = "notCalledFromParent";
@@ -1266,6 +1276,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
removeCredentialManagementApp(intent.getData().getSchemeSpecificPart());
} else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)) {
clearWipeProfileNotification();
+ } else if (Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
+ removeManagedEmbeddedSubscriptionsForUser(userHandle);
} else if (Intent.ACTION_DATE_CHANGED.equals(action)
|| Intent.ACTION_TIME_CHANGED.equals(action)) {
// Update freeze period record when clock naturally progresses to the next day
@@ -1298,6 +1310,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
triggerPolicyComplianceCheckIfNeeded(userHandle, suspended);
} else if (LOGIN_ACCOUNTS_CHANGED_ACTION.equals(action)) {
calculateHasIncompatibleAccounts();
+ } else if (ACTION_ESIM_REMOVED_WITH_MANAGED_PROFILE.equals(action)) {
+ int removedSubscriptionId = intent.getIntExtra(EXTRA_REMOVED_ESIM_SUBSCRIPTION_ID,
+ -1);
+ Slogf.i(LOG_TAG,
+ "Deleted subscription with ID %d because owning managed profile was "
+ + "removed",
+ removedSubscriptionId);
}
}
@@ -2219,9 +2238,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
+ filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_DATE_CHANGED);
mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
+ filter = new IntentFilter();
+ filter.addAction(ACTION_ESIM_REMOVED_WITH_MANAGED_PROFILE);
+ mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null,
+ mHandler, RECEIVER_NOT_EXPORTED);
LocalServices.addService(DevicePolicyManagerInternal.class, mLocalService);
@@ -3970,6 +3994,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
deletedUsers.remove(userInfo.id);
}
for (Integer userId : deletedUsers) {
+ removeManagedEmbeddedSubscriptionsForUser(userId);
removeUserData(userId);
mDevicePolicyEngine.handleUserRemoved(userId);
}
@@ -8099,6 +8124,45 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mInjector.getNotificationManager().cancel(SystemMessage.NOTE_PROFILE_WIPED);
}
+ /**
+ * Remove eSIM subscriptions that are managed by any of the admin packages of the given
+ * userHandle.
+ */
+ private void removeManagedEmbeddedSubscriptionsForUser(int userHandle) {
+ if (!Flags.removeManagedEsimOnWorkProfileDeletion()) {
+ return;
+ }
+
+ Slogf.i(LOG_TAG,
+ "Managed profile with ID=%d deleted: going to remove managed embedded "
+ + "subscriptions", userHandle);
+ String profileOwnerPackage = mOwners.getProfileOwnerPackage(userHandle);
+ if (profileOwnerPackage == null) {
+ Slogf.wtf(LOG_TAG, "Profile owner package for managed profile is null");
+ return;
+ }
+ IntArray managedSubscriptionIds = getSubscriptionIdsInternal(profileOwnerPackage);
+ deleteEmbeddedSubscriptions(managedSubscriptionIds);
+ }
+
+ private void deleteEmbeddedSubscriptions(IntArray subscriptionIds) {
+ EuiccManager euiccManager = mContext.getSystemService(EuiccManager.class);
+ for (int subscriptionId : subscriptionIds.toArray()) {
+ Slogf.i(LOG_TAG, "Deleting embedded subscription with ID %d", subscriptionId);
+ euiccManager.deleteSubscription(subscriptionId,
+ createCallbackPendingIntentForRemovingManagedSubscription(
+ subscriptionId));
+ }
+ }
+
+ private PendingIntent createCallbackPendingIntentForRemovingManagedSubscription(
+ Integer subscriptionId) {
+ Intent intent = new Intent(ACTION_ESIM_REMOVED_WITH_MANAGED_PROFILE);
+ intent.putExtra(EXTRA_REMOVED_ESIM_SUBSCRIPTION_ID, subscriptionId);
+ return PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_IMMUTABLE);
+ }
+
+
@Override
public void setFactoryResetProtectionPolicy(ComponentName who, String callerPackageName,
@Nullable FactoryResetProtectionPolicy policy) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 860b6fb1dcd1..788b3b883160 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -366,6 +366,8 @@ public final class SystemServer implements Dumpable {
"com.android.clockwork.time.WearTimeService";
private static final String WEAR_SETTINGS_SERVICE_CLASS =
"com.android.clockwork.settings.WearSettingsService";
+ private static final String WEAR_GESTURE_SERVICE_CLASS =
+ "com.android.clockwork.gesture.WearGestureService";
private static final String WRIST_ORIENTATION_SERVICE_CLASS =
"com.android.clockwork.wristorientation.WristOrientationService";
private static final String IOT_SERVICE_CLASS =
@@ -2844,6 +2846,13 @@ public final class SystemServer implements Dumpable {
mSystemServiceManager.startService(WRIST_ORIENTATION_SERVICE_CLASS);
t.traceEnd();
}
+
+ if (android.server.Flags.wearGestureApi()
+ && SystemProperties.getBoolean("config.enable_gesture_api", false)) {
+ t.traceBegin("StartWearGestureService");
+ mSystemServiceManager.startService(WEAR_GESTURE_SERVICE_CLASS);
+ t.traceEnd();
+ }
}
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_SLICES_DISABLED)) {
diff --git a/services/java/com/android/server/flags.aconfig b/services/java/com/android/server/flags.aconfig
index 86ccd878de7c..7a6bd75e5893 100644
--- a/services/java/com/android/server/flags.aconfig
+++ b/services/java/com/android/server/flags.aconfig
@@ -65,4 +65,12 @@ flag {
namespace: "package_manager_service"
description: "Remove AppIntegrityManagerService"
bug: "364200023"
+}
+
+flag {
+ name: "wear_gesture_api"
+ namespace: "wear_frameworks"
+ description: "Whether the Wear Gesture API is available."
+ bug: "396154116"
+ is_exported: true
} \ No newline at end of file
diff --git a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index 2dd16f68dc56..80a3a8788d80 100644
--- a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -109,6 +109,7 @@ import com.android.server.EventLogTags;
import com.android.server.LocalServices;
import com.android.server.backup.BackupAgentConnectionManager;
import com.android.server.backup.BackupRestoreTask;
+import com.android.server.backup.BackupRestoreTask.CancellationReason;
import com.android.server.backup.BackupWakeLock;
import com.android.server.backup.DataChangedJournal;
import com.android.server.backup.KeyValueBackupJob;
@@ -2412,7 +2413,7 @@ public class KeyValueBackupTaskTest {
KeyValueBackupTask task = spy(createKeyValueBackupTask(transportMock, PACKAGE_1));
doNothing().when(task).waitCancel();
- task.handleCancel(true);
+ task.handleCancel(CancellationReason.EXTERNAL);
InOrder inOrder = inOrder(task);
inOrder.verify(task).markCancel();
@@ -2420,12 +2421,14 @@ public class KeyValueBackupTaskTest {
}
@Test
- public void testHandleCancel_whenCancelAllFalse_throws() throws Exception {
+ public void testHandleCancel_timeout_throws() throws Exception {
TransportMock transportMock = setUpInitializedTransport(mTransport);
setUpAgentWithData(PACKAGE_1);
KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
- expectThrows(IllegalArgumentException.class, () -> task.handleCancel(false));
+ expectThrows(
+ IllegalArgumentException.class,
+ () -> task.handleCancel(CancellationReason.TIMEOUT));
}
/** Do not update backup token if no data was moved. */
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt b/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt
index 206c90d0481a..6dc7361e5366 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt
@@ -47,7 +47,7 @@ class DisplayTopologyCoordinatorTest {
private val mockTopology = mock<DisplayTopology>()
private val mockTopologyCopy = mock<DisplayTopology>()
private val mockTopologyGraph = mock<DisplayTopologyGraph>()
- private val mockIsExtendedDisplayEnabled = mock<() -> Boolean>()
+ private val mockIsExtendedDisplayAllowed = mock<() -> Boolean>()
private val mockTopologySavedCallback = mock<() -> Unit>()
private val mockTopologyChangedCallback =
mock<(android.util.Pair<DisplayTopology, DisplayTopologyGraph>) -> Unit>()
@@ -73,10 +73,10 @@ class DisplayTopologyCoordinatorTest {
) =
mockTopologyStore
}
- whenever(mockIsExtendedDisplayEnabled()).thenReturn(true)
+ whenever(mockIsExtendedDisplayAllowed()).thenReturn(true)
whenever(mockTopology.copy()).thenReturn(mockTopologyCopy)
whenever(mockTopologyCopy.getGraph(any())).thenReturn(mockTopologyGraph)
- coordinator = DisplayTopologyCoordinator(injector, mockIsExtendedDisplayEnabled,
+ coordinator = DisplayTopologyCoordinator(injector, mockIsExtendedDisplayAllowed,
mockTopologyChangedCallback, topologyChangeExecutor, DisplayManagerService.SyncRoot(),
mockTopologySavedCallback)
}
@@ -195,7 +195,7 @@ class DisplayTopologyCoordinatorTest {
@Test
fun addDisplay_external_extendedDisplaysDisabled() {
- whenever(mockIsExtendedDisplayEnabled()).thenReturn(false)
+ whenever(mockIsExtendedDisplayAllowed()).thenReturn(false)
for (displayInfo in displayInfos) {
coordinator.onDisplayAdded(displayInfo)
@@ -208,7 +208,7 @@ class DisplayTopologyCoordinatorTest {
@Test
fun addDisplay_overlay_extendedDisplaysDisabled() {
displayInfos[0].type = Display.TYPE_OVERLAY
- whenever(mockIsExtendedDisplayEnabled()).thenReturn(false)
+ whenever(mockIsExtendedDisplayAllowed()).thenReturn(false)
for (displayInfo in displayInfos) {
coordinator.onDisplayAdded(displayInfo)
@@ -314,7 +314,7 @@ class DisplayTopologyCoordinatorTest {
@Test
fun updateDisplay_external_extendedDisplaysDisabled() {
- whenever(mockIsExtendedDisplayEnabled()).thenReturn(false)
+ whenever(mockIsExtendedDisplayAllowed()).thenReturn(false)
for (displayInfo in displayInfos) {
coordinator.onDisplayChanged(displayInfo)
@@ -328,7 +328,7 @@ class DisplayTopologyCoordinatorTest {
@Test
fun updateDisplay_overlay_extendedDisplaysDisabled() {
displayInfos[0].type = Display.TYPE_OVERLAY
- whenever(mockIsExtendedDisplayEnabled()).thenReturn(false)
+ whenever(mockIsExtendedDisplayAllowed()).thenReturn(false)
coordinator.onDisplayChanged(displayInfos[0])
diff --git a/services/tests/mockingservicestests/src/com/android/server/backup/BackupAgentConnectionManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/backup/BackupAgentConnectionManagerTest.java
index 8aaa72339c5b..33bd95ec9f5b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/backup/BackupAgentConnectionManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/backup/BackupAgentConnectionManagerTest.java
@@ -51,6 +51,7 @@ import android.platform.test.flag.junit.SetFlagsRule;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.LocalServices;
+import com.android.server.backup.BackupRestoreTask.CancellationReason;
import com.android.server.backup.internal.LifecycleOperationStorage;
import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
@@ -368,9 +369,12 @@ public class BackupAgentConnectionManagerTest {
mConnectionManager.agentDisconnected(TEST_PACKAGE);
mTestThread.join();
- verify(mUserBackupManagerService).handleCancel(eq(123), eq(true));
- verify(mUserBackupManagerService).handleCancel(eq(456), eq(true));
- verify(mUserBackupManagerService).handleCancel(eq(789), eq(true));
+ verify(mUserBackupManagerService)
+ .handleCancel(eq(123), eq(CancellationReason.AGENT_DISCONNECTED));
+ verify(mUserBackupManagerService)
+ .handleCancel(eq(456), eq(CancellationReason.AGENT_DISCONNECTED));
+ verify(mUserBackupManagerService)
+ .handleCancel(eq(789), eq(CancellationReason.AGENT_DISCONNECTED));
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 30aa8cebdff6..01bcc2584fe1 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -143,6 +143,7 @@ import android.provider.DeviceConfig;
import android.provider.Settings;
import android.security.KeyChain;
import android.security.keystore.AttestationUtils;
+import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.test.MoreAsserts;
@@ -8715,6 +8716,47 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
}
+ @RequiresFlagsEnabled(Flags.FLAG_REMOVE_MANAGED_ESIM_ON_WORK_PROFILE_DELETION)
+ @Test
+ public void testManagedProfileDeleted_managedEmbeddedSubscriptionDeleted() throws Exception {
+ // Setup PO mode.
+ setupProfileOwner();
+ // Mock SubscriptionManager to return a subscription managed by the profile owner package.
+ int managedSubscriptionId = 42;
+ SubscriptionInfo managedSubscription = new SubscriptionInfo.Builder().setCardId(1).setId(
+ managedSubscriptionId).setGroupOwner(admin1.getPackageName()).build();
+ when(getServices().subscriptionManager.getAvailableSubscriptionInfoList()).thenReturn(
+ List.of(managedSubscription));
+
+ // Send a ACTION_MANAGED_PROFILE_REMOVED broadcast to emulate a managed profile being
+ // removed.
+ sendBroadcastWithUser(dpms, Intent.ACTION_MANAGED_PROFILE_REMOVED, CALLER_USER_HANDLE);
+
+ // Verify that EuiccManager was called to delete the subscription.
+ verify(getServices().euiccManager).deleteSubscription(eq(managedSubscriptionId), any());
+ }
+
+ @RequiresFlagsDisabled(Flags.FLAG_REMOVE_MANAGED_ESIM_ON_WORK_PROFILE_DELETION)
+ @Test
+ public void testManagedProfileDeleted_flagDisabled_managedEmbeddedSubscriptionDeleted()
+ throws Exception {
+ // Set up PO mode.
+ setupProfileOwner();
+ // Mock SubscriptionManager to return a subscription managed by the profile owner package.
+ int managedSubscriptionId = 42;
+ SubscriptionInfo managedSubscription = new SubscriptionInfo.Builder().setCardId(1).setId(
+ managedSubscriptionId).setGroupOwner(admin1.getPackageName()).build();
+ when(getServices().subscriptionManager.getAvailableSubscriptionInfoList()).thenReturn(
+ List.of(managedSubscription));
+
+ // Send a ACTION_MANAGED_PROFILE_REMOVED broadcast to emulate a managed profile being
+ // removed.
+ sendBroadcastWithUser(dpms, Intent.ACTION_MANAGED_PROFILE_REMOVED, CALLER_USER_HANDLE);
+
+ // Verify that EuiccManager was not called to delete the subscription.
+ verifyZeroInteractions(getServices().euiccManager);
+ }
+
private void setupVpnAuthorization(String userVpnPackage, int userVpnUid) {
final AppOpsManager.PackageOps vpnOp = new AppOpsManager.PackageOps(userVpnPackage,
userVpnUid, List.of(new AppOpsManager.OpEntry(
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 00b0c558b4e3..479af73bae3c 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -253,6 +253,8 @@ public class DpmMockContext extends MockContext {
return mMockSystemServices.subscriptionManager;
case Context.USB_SERVICE:
return mMockSystemServices.usbManager;
+ case Context.EUICC_SERVICE:
+ return mMockSystemServices.euiccManager;
}
throw new UnsupportedOperationException();
}
@@ -487,6 +489,14 @@ public class DpmMockContext extends MockContext {
}
@Override
+ public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
+ IntentFilter filter, String broadcastPermission, Handler scheduler, int flags) {
+ mMockSystemServices.registerReceiver(receiver, filter, scheduler);
+ return spiedContext.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
+ scheduler, flags);
+ }
+
+ @Override
public void unregisterReceiver(BroadcastReceiver receiver) {
mMockSystemServices.unregisterReceiver(receiver);
spiedContext.unregisterReceiver(receiver);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
index 3e4448c1dafa..d01fa91e22c2 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
@@ -68,6 +68,7 @@ import android.provider.Settings;
import android.security.KeyChain;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.euicc.EuiccManager;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;
import android.util.ArrayMap;
@@ -151,6 +152,7 @@ public class MockSystemServices {
public final File dataDir;
public final PolicyPathProvider pathProvider;
public final SupervisionManagerInternal supervisionManagerInternal;
+ public final EuiccManager euiccManager;
private final Map<String, PackageState> mTestPackageStates = new ArrayMap<>();
@@ -206,6 +208,7 @@ public class MockSystemServices {
roleManagerForMock = mock(RoleManagerForMock.class);
subscriptionManager = mock(SubscriptionManager.class);
supervisionManagerInternal = mock(SupervisionManagerInternal.class);
+ euiccManager = mock(EuiccManager.class);
// Package manager is huge, so we use a partial mock instead.
packageManager = spy(realContext.getPackageManager());
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivitySnapshotControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivitySnapshotControllerTests.java
index 948371f74a9c..ad706e879b72 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivitySnapshotControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivitySnapshotControllerTests.java
@@ -63,11 +63,23 @@ public class ActivitySnapshotControllerTests extends TaskSnapshotPersisterTestBa
super(0.8f /* highResScale */, 0.5f /* lowResScale */);
}
+ private class TestActivitySnapshotController extends ActivitySnapshotController {
+ TestActivitySnapshotController(WindowManagerService service,
+ SnapshotPersistQueue persistQueue) {
+ super(service, persistQueue);
+ }
+ @Override
+ BaseAppSnapshotPersister.PersistInfoProvider createPersistInfoProvider(
+ WindowManagerService service) {
+ return mPersister.mPersistInfoProvider;
+ }
+ }
@Override
@Before
public void setUp() {
super.setUp();
- mActivitySnapshotController = new ActivitySnapshotController(mWm, mSnapshotPersistQueue);
+ mActivitySnapshotController = new TestActivitySnapshotController(
+ mWm, mSnapshotPersistQueue);
spyOn(mActivitySnapshotController);
doReturn(false).when(mActivitySnapshotController).shouldDisableSnapshots();
mActivitySnapshotController.resetTmpFields();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DesktopModeHelperTest.java b/services/tests/wmtests/src/com/android/server/wm/DesktopModeHelperTest.java
index 43755ea3165e..1e91bedb5c18 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DesktopModeHelperTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DesktopModeHelperTest.java
@@ -181,7 +181,6 @@ public class DesktopModeHelperTest {
assertThat(DesktopModeHelper.isDeviceEligibleForDesktopMode(mMockContext)).isTrue();
}
- @DisableFlags(Flags.FLAG_ENABLE_PROJECTED_DISPLAY_DESKTOP_MODE)
@Test
public void isDeviceEligibleForDesktopMode_configDEModeOffAndIntDispHostsDesktop_returnsFalse() {
doReturn(true).when(mMockResources).getBoolean(eq(R.bool.config_isDesktopModeSupported));
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java
index 51ea498811fc..f22ecb5eb3f9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java
@@ -68,11 +68,8 @@ public class TaskSnapshotLowResDisabledTest extends TaskSnapshotPersisterTestBas
public void testPersistAndLoadSnapshot() {
mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
mSnapshotPersistQueue.waitForQueueEmpty();
- final File[] files = new File[]{
- new File(FILES_DIR.getPath() + "/snapshots/1.proto"),
- new File(FILES_DIR.getPath() + "/snapshots/1.jpg")};
- final File[] nonExistsFiles = new File[]{
- new File(FILES_DIR.getPath() + "/snapshots/1_reduced.jpg")};
+ final File[] files = convertFilePath("1.proto", "1.jpg");
+ final File[] nonExistsFiles = convertFilePath("1_reduced.proto");
assertTrueForFiles(files, File::exists, " must exist");
assertTrueForFiles(nonExistsFiles, file -> !file.exists(), " must not exist");
final TaskSnapshot snapshot = mLoader.loadTask(1, mTestUserId, false /* isLowResolution */);
@@ -92,14 +89,9 @@ public class TaskSnapshotLowResDisabledTest extends TaskSnapshotPersisterTestBas
taskIds.add(1);
mPersister.removeObsoleteFiles(taskIds, new int[]{mTestUserId});
mSnapshotPersistQueue.waitForQueueEmpty();
- final File[] existsFiles = new File[]{
- new File(FILES_DIR.getPath() + "/snapshots/1.proto"),
- new File(FILES_DIR.getPath() + "/snapshots/1.jpg")};
- final File[] nonExistsFiles = new File[]{
- new File(FILES_DIR.getPath() + "/snapshots/1_reduced.jpg"),
- new File(FILES_DIR.getPath() + "/snapshots/2.proto"),
- new File(FILES_DIR.getPath() + "/snapshots/2.jpg"),
- new File(FILES_DIR.getPath() + "/snapshots/2_reduced.jpg")};
+ final File[] existsFiles = convertFilePath("1.proto", "1.jpg");
+ final File[] nonExistsFiles = convertFilePath("1_reduced.proto", "2.proto", "2.jpg",
+ "2_reduced.jpg");
assertTrueForFiles(existsFiles, File::exists, " must exist");
assertTrueForFiles(nonExistsFiles, file -> !file.exists(), " must not exist");
}
@@ -112,14 +104,8 @@ public class TaskSnapshotLowResDisabledTest extends TaskSnapshotPersisterTestBas
mPersister.removeObsoleteFiles(taskIds, new int[]{mTestUserId});
mPersister.persistSnapshot(2, mTestUserId, createSnapshot());
mSnapshotPersistQueue.waitForQueueEmpty();
- final File[] existsFiles = new File[]{
- new File(FILES_DIR.getPath() + "/snapshots/1.proto"),
- new File(FILES_DIR.getPath() + "/snapshots/1.jpg"),
- new File(FILES_DIR.getPath() + "/snapshots/2.proto"),
- new File(FILES_DIR.getPath() + "/snapshots/2.jpg")};
- final File[] nonExistsFiles = new File[]{
- new File(FILES_DIR.getPath() + "/snapshots/1_reduced.jpg"),
- new File(FILES_DIR.getPath() + "/snapshots/2_reduced.jpg")};
+ final File[] existsFiles = convertFilePath("1.proto", "1.jpg", "2.proto", "2.jpg");
+ final File[] nonExistsFiles = convertFilePath("1_reduced.jpg", "2_reduced.jpg");
assertTrueForFiles(existsFiles, File::exists, " must exist");
assertTrueForFiles(nonExistsFiles, file -> !file.exists(), " must not exist");
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
index 4b54e4464ca7..af06c14516a1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
@@ -75,9 +75,7 @@ public class TaskSnapshotPersisterLoaderTest extends TaskSnapshotPersisterTestBa
public void testPersistAndLoadSnapshot() {
mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
mSnapshotPersistQueue.waitForQueueEmpty();
- final File[] files = new File[]{new File(FILES_DIR.getPath() + "/snapshots/1.proto"),
- new File(FILES_DIR.getPath() + "/snapshots/1.jpg"),
- new File(FILES_DIR.getPath() + "/snapshots/1_reduced.jpg")};
+ final File[] files = convertFilePath("1.proto", "1.jpg", "1_reduced.jpg");
assertTrueForFiles(files, File::exists, " must exist");
final TaskSnapshot snapshot = mLoader.loadTask(1, mTestUserId, false /* isLowResolution */);
assertNotNull(snapshot);
@@ -140,13 +138,8 @@ public class TaskSnapshotPersisterLoaderTest extends TaskSnapshotPersisterTestBa
mSnapshotPersistQueue.waitForQueueEmpty();
// Make sure 1,2 were purged but removeObsoleteFiles wasn't.
- final File[] existsFiles = new File[]{
- new File(FILES_DIR.getPath() + "/snapshots/3.proto"),
- new File(FILES_DIR.getPath() + "/snapshots/4.proto")};
- final File[] nonExistsFiles = new File[]{
- new File(FILES_DIR.getPath() + "/snapshots/100.proto"),
- new File(FILES_DIR.getPath() + "/snapshots/1.proto"),
- new File(FILES_DIR.getPath() + "/snapshots/1.proto")};
+ final File[] existsFiles = convertFilePath("3.proto", "4.proto");
+ final File[] nonExistsFiles = convertFilePath("100.proto", "1.proto", "2.proto");
assertTrueForFiles(existsFiles, File::exists, " must exist");
assertTrueForFiles(nonExistsFiles, file -> !file.exists(), " must not exist");
}
@@ -427,14 +420,8 @@ public class TaskSnapshotPersisterLoaderTest extends TaskSnapshotPersisterTestBa
taskIds.add(1);
mPersister.removeObsoleteFiles(taskIds, new int[]{mTestUserId});
mSnapshotPersistQueue.waitForQueueEmpty();
- final File[] existsFiles = new File[]{
- new File(FILES_DIR.getPath() + "/snapshots/1.proto"),
- new File(FILES_DIR.getPath() + "/snapshots/1.jpg"),
- new File(FILES_DIR.getPath() + "/snapshots/1_reduced.jpg")};
- final File[] nonExistsFiles = new File[]{
- new File(FILES_DIR.getPath() + "/snapshots/2.proto"),
- new File(FILES_DIR.getPath() + "/snapshots/2.jpg"),
- new File(FILES_DIR.getPath() + "/snapshots/2_reduced.jpg")};
+ final File[] existsFiles = convertFilePath("1.proto", "1.jpg", "1_reduced.jpg");
+ final File[] nonExistsFiles = convertFilePath("2.proto", "2.jpg", "2_reduced.jpg");
assertTrueForFiles(existsFiles, File::exists, " must exist");
assertTrueForFiles(nonExistsFiles, file -> !file.exists(), " must not exist");
}
@@ -447,13 +434,8 @@ public class TaskSnapshotPersisterLoaderTest extends TaskSnapshotPersisterTestBa
mPersister.removeObsoleteFiles(taskIds, new int[]{mTestUserId});
mPersister.persistSnapshot(2, mTestUserId, createSnapshot());
mSnapshotPersistQueue.waitForQueueEmpty();
- final File[] existsFiles = new File[]{
- new File(FILES_DIR.getPath() + "/snapshots/1.proto"),
- new File(FILES_DIR.getPath() + "/snapshots/1.jpg"),
- new File(FILES_DIR.getPath() + "/snapshots/1_reduced.jpg"),
- new File(FILES_DIR.getPath() + "/snapshots/2.proto"),
- new File(FILES_DIR.getPath() + "/snapshots/2.jpg"),
- new File(FILES_DIR.getPath() + "/snapshots/2_reduced.jpg")};
+ final File[] existsFiles = convertFilePath("1.proto", "1.jpg", "1_reduced.jpg", "2.proto",
+ "2.jpg", "2_reduced.jpg");
assertTrueForFiles(existsFiles, File::exists, " must exist");
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index 1e16c97de647..b2c195e8ebaa 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
+import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.ContextWrapper;
import android.content.res.Resources;
@@ -46,6 +47,7 @@ import android.window.TaskSnapshot;
import com.android.server.LocalServices;
import com.android.server.pm.UserManagerInternal;
import com.android.server.wm.BaseAppSnapshotPersister.PersistInfoProvider;
+import com.android.window.flags.Flags;
import org.junit.After;
import org.junit.AfterClass;
@@ -129,12 +131,33 @@ class TaskSnapshotPersisterTestBase extends WindowTestsBase {
return;
}
for (File file : files) {
- if (!file.isDirectory()) {
- file.delete();
+ if (file.isDirectory()) {
+ final File[] subFiles = file.listFiles();
+ if (subFiles == null) {
+ continue;
+ }
+ for (File subFile : subFiles) {
+ subFile.delete();
+ }
}
+ file.delete();
}
}
+ File[] convertFilePath(@NonNull String... fileNames) {
+ final File[] files = new File[fileNames.length];
+ final String path;
+ if (Flags.scrambleSnapshotFileName()) {
+ path = mPersister.mPersistInfoProvider.getDirectory(mTestUserId).getPath();
+ } else {
+ path = FILES_DIR.getPath() + "/snapshots/";
+ }
+ for (int i = 0; i < fileNames.length; i++) {
+ files[i] = new File(path + fileNames[i]);
+ }
+ return files;
+ }
+
TaskSnapshot createSnapshot() {
return new TaskSnapshotBuilder().setTopActivityComponent(getUniqueComponentName()).build();
}