summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt8
-rw-r--r--core/api/test-current.txt1
-rw-r--r--core/java/android/app/WallpaperManager.java82
-rw-r--r--core/java/android/hardware/Camera.java24
-rw-r--r--core/java/android/hardware/camera2/CameraManager.java43
-rw-r--r--core/java/android/hardware/display/AmbientDisplayConfiguration.java6
-rw-r--r--core/java/android/view/ViewRootImpl.java26
-rw-r--r--core/java/android/window/ClientWindowFrames.java10
-rw-r--r--core/java/android/window/TaskFragmentCreationParams.java66
-rw-r--r--core/jni/android_hardware_Camera.cpp144
-rw-r--r--core/res/res/values/config.xml4
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java59
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java11
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java25
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java15
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java2
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java10
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java6
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java68
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java26
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java4
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java9
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java5
-rw-r--r--packages/SystemUI/res-keyguard/layout/fgs_footer.xml105
-rw-r--r--packages/SystemUI/res-keyguard/layout/footer_actions.xml76
-rw-r--r--packages/SystemUI/res/layout/activity_rear_display_education.xml2
-rw-r--r--packages/SystemUI/res/layout/activity_rear_display_education_opened.xml2
-rw-r--r--packages/SystemUI/res/layout/quick_settings_security_footer.xml61
-rw-r--r--packages/SystemUI/res/layout/super_notification_shade.xml18
-rw-r--r--packages/SystemUI/res/values/strings.xml4
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/condition/CombinedCondition.kt (renamed from packages/SystemUI/src/com/android/systemui/util/condition/CombinedCondition.kt)2
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.java (renamed from packages/SystemUI/src/com/android/systemui/util/condition/Condition.java)50
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt (renamed from packages/SystemUI/src/com/android/systemui/util/condition/Evaluator.kt)18
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/condition/Monitor.java (renamed from packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java)12
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java3
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java3
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java25
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java18
-rw-r--r--packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt231
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsRepository.kt (renamed from packages/SystemUI/src/com/android/systemui/controls/ControlsSettingsRepository.kt)2
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsRepositoryImpl.kt (renamed from packages/SystemUI/src/com/android/systemui/controls/ControlsSettingsRepositoryImpl.kt)2
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt123
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt266
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt135
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/NewFooterActionsController.kt33
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFgsManagerFooter.java178
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFragment.java66
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java262
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/security/data/model/SecurityModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java171
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java33
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt159
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt136
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt53
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt328
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsRepositoryImplTest.kt (renamed from packages/SystemUI/tests/src/com/android/systemui/controls/ControlsSettingsRepositoryImplTest.kt)2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/settings/FakeControlsSettingsRepository.kt (renamed from packages/SystemUI/tests/src/com/android/systemui/controls/FakeControlsSettingsRepository.kt)2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java51
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt440
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java63
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java382
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt82
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java (renamed from packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java)49
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionTest.java (renamed from packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionTest.java)67
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/condition/FakeCondition.java (renamed from packages/SystemUI/tests/utils/src/com/android/systemui/util/condition/FakeCondition.java)4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java8
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt2
-rw-r--r--packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt3
-rw-r--r--services/core/java/com/android/server/wm/ActivityMetricsLogger.java8
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java15
-rw-r--r--services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartController.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java2
-rw-r--r--services/core/java/com/android/server/wm/BackNavigationController.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java8
-rw-r--r--services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java6
-rw-r--r--services/core/java/com/android/server/wm/LetterboxUiController.java5
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimation.java4
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java4
-rw-r--r--services/core/java/com/android/server/wm/Task.java16
-rw-r--r--services/core/java/com/android/server/wm/TaskFragment.java12
-rw-r--r--services/core/java/com/android/server/wm/Transition.java6
-rw-r--r--services/core/java/com/android/server/wm/WallpaperController.java4
-rw-r--r--services/core/java/com/android/server/wm/WallpaperWindowToken.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java13
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java14
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java40
-rw-r--r--services/core/java/com/android/server/wm/WindowToken.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java12
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java80
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java14
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java54
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java44
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TransitionTests.java128
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java12
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java4
142 files changed, 2214 insertions, 3004 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index c8a43db2f9c2..487e57d114c9 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -7216,8 +7216,8 @@ package android.app {
method public android.content.Intent getCropAndSetWallpaperIntent(android.net.Uri);
method public int getDesiredMinimumHeight();
method public int getDesiredMinimumWidth();
- method @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public android.graphics.drawable.Drawable getDrawable();
- method @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public android.graphics.drawable.Drawable getFastDrawable();
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public android.graphics.drawable.Drawable getDrawable();
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public android.graphics.drawable.Drawable getFastDrawable();
method public static android.app.WallpaperManager getInstance(android.content.Context);
method @Nullable public android.app.WallpaperColors getWallpaperColors(int);
method @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public android.os.ParcelFileDescriptor getWallpaperFile(int);
@@ -7226,8 +7226,8 @@ package android.app {
method public boolean hasResourceWallpaper(@RawRes int);
method public boolean isSetWallpaperAllowed();
method public boolean isWallpaperSupported();
- method public android.graphics.drawable.Drawable peekDrawable();
- method @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public android.graphics.drawable.Drawable peekFastDrawable();
+ method @Nullable public android.graphics.drawable.Drawable peekDrawable();
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public android.graphics.drawable.Drawable peekFastDrawable();
method public void removeOnColorsChangedListener(@NonNull android.app.WallpaperManager.OnColorsChangedListener);
method public void sendWallpaperCommand(android.os.IBinder, String, int, int, int, android.os.Bundle);
method @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) public void setBitmap(android.graphics.Bitmap) throws java.io.IOException;
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 93c0c4d7a024..70a23cdf106b 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1139,6 +1139,7 @@ package android.hardware.camera2 {
public final class CameraManager {
method public String[] getCameraIdListNoLazy() throws android.hardware.camera2.CameraAccessException;
method @RequiresPermission(allOf={android.Manifest.permission.SYSTEM_CAMERA, android.Manifest.permission.CAMERA}) public void openCamera(@NonNull String, int, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.camera2.CameraDevice.StateCallback) throws android.hardware.camera2.CameraAccessException;
+ field public static final long OVERRIDE_FRONT_CAMERA_APP_COMPAT = 250678880L; // 0xef10e60L
}
public abstract static class CameraManager.AvailabilityCallback {
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 3e6283e25aa5..162a9976f4f3 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -786,6 +786,7 @@ public class WallpaperManager {
* is not able to access the wallpaper.
*/
@RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
+ @Nullable
public Drawable getDrawable() {
final ColorManagementProxy cmProxy = getColorManagementProxy();
Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, cmProxy);
@@ -798,6 +799,29 @@ public class WallpaperManager {
}
/**
+ * Retrieve the requested wallpaper; if
+ * no wallpaper is set, the requested built-in static wallpaper is returned.
+ * This is returned as an
+ * abstract Drawable that you can install in a View to display whatever
+ * wallpaper the user has currently set.
+ * <p>
+ * This method can return null if the requested wallpaper is not available, if
+ * wallpapers are not supported in the current user, or if the calling app is not
+ * permitted to access the requested wallpaper.
+ *
+ * @param which The {@code FLAG_*} identifier of a valid wallpaper type. Throws
+ * IllegalArgumentException if an invalid wallpaper is requested.
+ * @return Returns a Drawable object that will draw the requested wallpaper,
+ * or {@code null} if the requested wallpaper does not exist or if the calling application
+ * is not able to access the wallpaper.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
+ @Nullable
+ public Drawable getDrawable(@SetWallpaperFlags int which) {
+ return getDrawable();
+ }
+ /**
* Obtain a drawable for the built-in static system wallpaper.
*/
public Drawable getBuiltInDrawable() {
@@ -1018,6 +1042,7 @@ public class WallpaperManager {
* @return Returns a Drawable object that will draw the wallpaper or a
* null pointer if these is none.
*/
+ @Nullable
public Drawable peekDrawable() {
final ColorManagementProxy cmProxy = getColorManagementProxy();
Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM, cmProxy);
@@ -1030,6 +1055,23 @@ public class WallpaperManager {
}
/**
+ * Retrieve the requested wallpaper; if there is no wallpaper set,
+ * a null pointer is returned. This is returned as an
+ * abstract Drawable that you can install in a View to display whatever
+ * wallpaper the user has currently set.
+ *
+ * @param which The {@code FLAG_*} identifier of a valid wallpaper type. Throws
+ * IllegalArgumentException if an invalid wallpaper is requested.
+ * @return Returns a Drawable object that will draw the wallpaper or a null pointer if these
+ * is none.
+ * @hide
+ */
+ @Nullable
+ public Drawable peekDrawable(@SetWallpaperFlags int which) {
+ return peekDrawable();
+ }
+
+ /**
* Like {@link #getDrawable()}, but the returned Drawable has a number
* of limitations to reduce its overhead as much as possible. It will
* never scale the wallpaper (only centering it if the requested bounds
@@ -1043,6 +1085,7 @@ public class WallpaperManager {
* @return Returns a Drawable object that will draw the wallpaper.
*/
@RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
+ @Nullable
public Drawable getFastDrawable() {
final ColorManagementProxy cmProxy = getColorManagementProxy();
Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, cmProxy);
@@ -1053,6 +1096,28 @@ public class WallpaperManager {
}
/**
+ * Like {@link #getFastDrawable(int)}, but the returned Drawable has a number
+ * of limitations to reduce its overhead as much as possible. It will
+ * never scale the wallpaper (only centering it if the requested bounds
+ * do match the bitmap bounds, which should not be typical), doesn't
+ * allow setting an alpha, color filter, or other attributes, etc. The
+ * bounds of the returned drawable will be initialized to the same bounds
+ * as the wallpaper, so normally you will not need to touch it. The
+ * drawable also assumes that it will be used in a context running in
+ * the same density as the screen (not in density compatibility mode).
+ *
+ * @param which The {@code FLAG_*} identifier of a valid wallpaper type. Throws
+ * IllegalArgumentException if an invalid wallpaper is requested.
+ * @return Returns a Drawable object that will draw the wallpaper.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
+ @Nullable
+ public Drawable getFastDrawable(@SetWallpaperFlags int which) {
+ return getFastDrawable();
+ }
+
+ /**
* Like {@link #getFastDrawable()}, but if there is no wallpaper set,
* a null pointer is returned.
*
@@ -1060,6 +1125,7 @@ public class WallpaperManager {
* wallpaper or a null pointer if these is none.
*/
@RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
+ @Nullable
public Drawable peekFastDrawable() {
final ColorManagementProxy cmProxy = getColorManagementProxy();
Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM, cmProxy);
@@ -1070,6 +1136,22 @@ public class WallpaperManager {
}
/**
+ * Like {@link #getFastDrawable()}, but if there is no wallpaper set,
+ * a null pointer is returned.
+ *
+ * @param which The {@code FLAG_*} identifier of a valid wallpaper type. Throws
+ * IllegalArgumentException if an invalid wallpaper is requested.
+ * @return Returns an optimized Drawable object that will draw the
+ * wallpaper or a null pointer if these is none.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
+ @Nullable
+ public Drawable peekFastDrawable(@SetWallpaperFlags int which) {
+ return peekFastDrawable();
+ }
+
+ /**
* Whether the wallpaper supports Wide Color Gamut or not.
* @param which The wallpaper whose image file is to be retrieved. Must be a single
* defined kind of wallpaper, either {@link #FLAG_SYSTEM} or {@link #FLAG_LOCK}.
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 3bdd39f5d7d7..5291d2b73891 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -29,12 +29,14 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.ActivityThread;
import android.app.AppOpsManager;
+import android.app.compat.CompatChanges;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
+import android.hardware.camera2.CameraManager;
import android.media.AudioAttributes;
import android.media.IAudioService;
import android.os.Build;
@@ -45,6 +47,7 @@ import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemProperties;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RSIllegalArgumentException;
@@ -281,6 +284,14 @@ public class Camera {
*/
public native static int getNumberOfCameras();
+ private static final boolean sLandscapeToPortrait =
+ SystemProperties.getBoolean(CameraManager.LANDSCAPE_TO_PORTRAIT_PROP, false);
+
+ private static boolean shouldOverrideToPortrait() {
+ return CompatChanges.isChangeEnabled(CameraManager.OVERRIDE_FRONT_CAMERA_APP_COMPAT)
+ && sLandscapeToPortrait;
+ }
+
/**
* Returns the information about a particular camera.
* If {@link #getNumberOfCameras()} returns N, the valid id is 0 to N-1.
@@ -290,7 +301,9 @@ public class Camera {
* low-level failure).
*/
public static void getCameraInfo(int cameraId, CameraInfo cameraInfo) {
- _getCameraInfo(cameraId, cameraInfo);
+ boolean overrideToPortrait = shouldOverrideToPortrait();
+
+ _getCameraInfo(cameraId, overrideToPortrait, cameraInfo);
IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
IAudioService audioService = IAudioService.Stub.asInterface(b);
try {
@@ -303,7 +316,8 @@ public class Camera {
Log.e(TAG, "Audio service is unavailable for queries");
}
}
- private native static void _getCameraInfo(int cameraId, CameraInfo cameraInfo);
+ private native static void _getCameraInfo(int cameraId, boolean overrideToPortrait,
+ CameraInfo cameraInfo);
/**
* Information about a camera
@@ -484,8 +498,9 @@ public class Camera {
mEventHandler = null;
}
+ boolean overrideToPortrait = shouldOverrideToPortrait();
return native_setup(new WeakReference<Camera>(this), cameraId,
- ActivityThread.currentOpPackageName());
+ ActivityThread.currentOpPackageName(), overrideToPortrait);
}
/** used by Camera#open, Camera#open(int) */
@@ -555,7 +570,8 @@ public class Camera {
}
@UnsupportedAppUsage
- private native int native_setup(Object cameraThis, int cameraId, String packageName);
+ private native int native_setup(Object cameraThis, int cameraId, String packageName,
+ boolean overrideToPortrait);
private native final void native_release();
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index dff2f7ed1cf3..7fed2200d606 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -23,6 +23,10 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.Disabled;
+import android.compat.annotation.Overridable;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Point;
@@ -104,6 +108,24 @@ public final class CameraManager {
private final boolean mHasOpenCloseListenerPermission;
/**
+ * Force camera output to be rotated to portrait orientation on landscape cameras.
+ * Many apps do not handle this situation and display stretched images otherwise.
+ * @hide
+ */
+ @ChangeId
+ @Overridable
+ @Disabled
+ @TestApi
+ public static final long OVERRIDE_FRONT_CAMERA_APP_COMPAT = 250678880L;
+
+ /**
+ * System property for allowing the above
+ * @hide
+ */
+ public static final String LANDSCAPE_TO_PORTRAIT_PROP =
+ "camera.enable_landscape_to_portrait";
+
+ /**
* @hide
*/
public CameraManager(Context context) {
@@ -520,7 +542,8 @@ public final class CameraManager {
for (String physicalCameraId : physicalCameraIds) {
CameraMetadataNative physicalCameraInfo =
cameraService.getCameraCharacteristics(physicalCameraId,
- mContext.getApplicationInfo().targetSdkVersion);
+ mContext.getApplicationInfo().targetSdkVersion,
+ /*overrideToPortrait*/false);
StreamConfiguration[] configs = physicalCameraInfo.get(
CameraCharacteristics.
SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS);
@@ -579,8 +602,9 @@ public final class CameraManager {
try {
Size displaySize = getDisplaySize();
+ boolean overrideToPortrait = shouldOverrideToPortrait();
CameraMetadataNative info = cameraService.getCameraCharacteristics(cameraId,
- mContext.getApplicationInfo().targetSdkVersion);
+ mContext.getApplicationInfo().targetSdkVersion, overrideToPortrait);
try {
info.setCameraId(Integer.parseInt(cameraId));
} catch (NumberFormatException e) {
@@ -697,9 +721,12 @@ public final class CameraManager {
ICameraService.ERROR_DISCONNECTED,
"Camera service is currently unavailable");
}
+
+ boolean overrideToPortrait = shouldOverrideToPortrait();
cameraUser = cameraService.connectDevice(callbacks, cameraId,
- mContext.getOpPackageName(), mContext.getAttributionTag(), uid,
- oomScoreOffset, mContext.getApplicationInfo().targetSdkVersion);
+ mContext.getOpPackageName(), mContext.getAttributionTag(), uid,
+ oomScoreOffset, mContext.getApplicationInfo().targetSdkVersion,
+ overrideToPortrait);
} catch (ServiceSpecificException e) {
if (e.errorCode == ICameraService.ERROR_DEPRECATED_HAL) {
throw new AssertionError("Should've gone down the shim path");
@@ -1127,6 +1154,11 @@ public final class CameraManager {
return CameraManagerGlobal.get().getTorchStrengthLevel(cameraId);
}
+ private static boolean shouldOverrideToPortrait() {
+ return CompatChanges.isChangeEnabled(OVERRIDE_FRONT_CAMERA_APP_COMPAT)
+ && CameraManagerGlobal.sLandscapeToPortrait;
+ }
+
/**
* A callback for camera devices becoming available or unavailable to open.
*
@@ -1573,6 +1605,9 @@ public final class CameraManager {
public static final boolean sCameraServiceDisabled =
SystemProperties.getBoolean("config.disable_cameraservice", false);
+ public static final boolean sLandscapeToPortrait =
+ SystemProperties.getBoolean(LANDSCAPE_TO_PORTRAIT_PROP, false);
+
public static CameraManagerGlobal get() {
return gCameraManager;
}
diff --git a/core/java/android/hardware/display/AmbientDisplayConfiguration.java b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
index 8c71b363eb7b..47541ca16cda 100644
--- a/core/java/android/hardware/display/AmbientDisplayConfiguration.java
+++ b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
@@ -40,6 +40,7 @@ public class AmbientDisplayConfiguration {
private static final String TAG = "AmbientDisplayConfig";
private final Context mContext;
private final boolean mAlwaysOnByDefault;
+ private final boolean mPickupGestureEnabledByDefault;
/** Copied from android.provider.Settings.Secure since these keys are hidden. */
private static final String[] DOZE_SETTINGS = {
@@ -65,6 +66,8 @@ public class AmbientDisplayConfiguration {
public AmbientDisplayConfiguration(Context context) {
mContext = context;
mAlwaysOnByDefault = mContext.getResources().getBoolean(R.bool.config_dozeAlwaysOnEnabled);
+ mPickupGestureEnabledByDefault =
+ mContext.getResources().getBoolean(R.bool.config_dozePickupGestureEnabled);
}
/** @hide */
@@ -95,7 +98,8 @@ public class AmbientDisplayConfiguration {
/** @hide */
public boolean pickupGestureEnabled(int user) {
- return boolSettingDefaultOn(Settings.Secure.DOZE_PICK_UP_GESTURE, user)
+ return boolSetting(Settings.Secure.DOZE_PICK_UP_GESTURE, user,
+ mPickupGestureEnabledByDefault ? 1 : 0)
&& dozePickupSensorAvailable();
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index d21ba014e166..550bf348d1c7 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -720,7 +720,7 @@ public final class ViewRootImpl implements ViewParent,
private final InsetsState mTempInsets = new InsetsState();
private final InsetsSourceControl[] mTempControls = new InsetsSourceControl[SIZE];
private final WindowConfiguration mTempWinConfig = new WindowConfiguration();
- private float mInvSizeCompatScale = 1f;
+ private float mInvCompatScale = 1f;
final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets
= new ViewTreeObserver.InternalInsetsInfo();
@@ -1119,11 +1119,11 @@ public final class ViewRootImpl implements ViewParent,
private WindowConfiguration getCompatWindowConfiguration() {
final WindowConfiguration winConfig = getConfiguration().windowConfiguration;
- if (mInvSizeCompatScale == 1f) {
+ if (mInvCompatScale == 1f) {
return winConfig;
}
mTempWinConfig.setTo(winConfig);
- mTempWinConfig.scale(mInvSizeCompatScale);
+ mTempWinConfig.scale(mInvCompatScale);
return mTempWinConfig;
}
@@ -1257,11 +1257,11 @@ public final class ViewRootImpl implements ViewParent,
controlInsetsForCompatibility(mWindowAttributes);
Rect attachedFrame = new Rect();
- final float[] sizeCompatScale = { 1f };
+ final float[] compatScale = { 1f };
res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId,
mInsetsController.getRequestedVisibilities(), inputChannel, mTempInsets,
- mTempControls, attachedFrame, sizeCompatScale);
+ mTempControls, attachedFrame, compatScale);
if (!attachedFrame.isValid()) {
attachedFrame = null;
}
@@ -1271,8 +1271,8 @@ public final class ViewRootImpl implements ViewParent,
mTranslator.translateRectInScreenToAppWindow(attachedFrame);
}
mTmpFrames.attachedFrame = attachedFrame;
- mTmpFrames.sizeCompatScale = sizeCompatScale[0];
- mInvSizeCompatScale = 1f / sizeCompatScale[0];
+ mTmpFrames.compatScale = compatScale[0];
+ mInvCompatScale = 1f / compatScale[0];
} catch (RemoteException e) {
mAdded = false;
mView = null;
@@ -1794,24 +1794,24 @@ public final class ViewRootImpl implements ViewParent,
mTranslator.translateRectInScreenToAppWindow(displayFrame);
mTranslator.translateRectInScreenToAppWindow(attachedFrame);
}
- final float sizeCompatScale = frames.sizeCompatScale;
+ final float compatScale = frames.compatScale;
final boolean frameChanged = !mWinFrame.equals(frame);
final boolean configChanged = !mLastReportedMergedConfiguration.equals(mergedConfiguration);
final boolean attachedFrameChanged = LOCAL_LAYOUT
&& !Objects.equals(mTmpFrames.attachedFrame, attachedFrame);
final boolean displayChanged = mDisplay.getDisplayId() != displayId;
final boolean resizeModeChanged = mResizeMode != resizeMode;
- final boolean sizeCompatScaleChanged = mTmpFrames.sizeCompatScale != sizeCompatScale;
+ final boolean compatScaleChanged = mTmpFrames.compatScale != compatScale;
if (msg == MSG_RESIZED && !frameChanged && !configChanged && !attachedFrameChanged
&& !displayChanged && !resizeModeChanged && !forceNextWindowRelayout
- && !sizeCompatScaleChanged) {
+ && !compatScaleChanged) {
return;
}
mPendingDragResizing = resizeMode != RESIZE_MODE_INVALID;
mResizeMode = resizeMode;
- mTmpFrames.sizeCompatScale = sizeCompatScale;
- mInvSizeCompatScale = 1f / sizeCompatScale;
+ mTmpFrames.compatScale = compatScale;
+ mInvCompatScale = 1f / compatScale;
if (configChanged) {
// If configuration changed - notify about that and, maybe, about move to display.
@@ -8240,7 +8240,7 @@ public final class ViewRootImpl implements ViewParent,
mTranslator.translateInsetsStateInScreenToAppWindow(mTempInsets);
mTranslator.translateSourceControlsInScreenToAppWindow(mTempControls);
}
- mInvSizeCompatScale = 1f / mTmpFrames.sizeCompatScale;
+ mInvCompatScale = 1f / mTmpFrames.compatScale;
mInsetsController.onStateChanged(mTempInsets);
mInsetsController.onControlsChanged(mTempControls);
diff --git a/core/java/android/window/ClientWindowFrames.java b/core/java/android/window/ClientWindowFrames.java
index f274d1a15ba5..0ce076b6eb96 100644
--- a/core/java/android/window/ClientWindowFrames.java
+++ b/core/java/android/window/ClientWindowFrames.java
@@ -49,7 +49,7 @@ public class ClientWindowFrames implements Parcelable {
public boolean isParentFrameClippedByDisplayCutout;
- public float sizeCompatScale = 1f;
+ public float compatScale = 1f;
public ClientWindowFrames() {
}
@@ -62,7 +62,7 @@ public class ClientWindowFrames implements Parcelable {
attachedFrame = new Rect(other.attachedFrame);
}
isParentFrameClippedByDisplayCutout = other.isParentFrameClippedByDisplayCutout;
- sizeCompatScale = other.sizeCompatScale;
+ compatScale = other.compatScale;
}
private ClientWindowFrames(Parcel in) {
@@ -76,7 +76,7 @@ public class ClientWindowFrames implements Parcelable {
parentFrame.readFromParcel(in);
attachedFrame = in.readTypedObject(Rect.CREATOR);
isParentFrameClippedByDisplayCutout = in.readBoolean();
- sizeCompatScale = in.readFloat();
+ compatScale = in.readFloat();
}
@Override
@@ -86,7 +86,7 @@ public class ClientWindowFrames implements Parcelable {
parentFrame.writeToParcel(dest, flags);
dest.writeTypedObject(attachedFrame, flags);
dest.writeBoolean(isParentFrameClippedByDisplayCutout);
- dest.writeFloat(sizeCompatScale);
+ dest.writeFloat(compatScale);
}
@Override
@@ -97,7 +97,7 @@ public class ClientWindowFrames implements Parcelable {
+ " parentFrame=" + parentFrame.toShortString(sb)
+ (attachedFrame != null ? " attachedFrame=" + attachedFrame.toShortString() : "")
+ (isParentFrameClippedByDisplayCutout ? " parentClippedByDisplayCutout" : "")
- + (sizeCompatScale != 1f ? " sizeCompatScale=" + sizeCompatScale : "") + "}";
+ + (compatScale != 1f ? " sizeCompatScale=" + compatScale : "") + "}";
}
@Override
diff --git a/core/java/android/window/TaskFragmentCreationParams.java b/core/java/android/window/TaskFragmentCreationParams.java
index 81ab7836435d..c9ddf92d3740 100644
--- a/core/java/android/window/TaskFragmentCreationParams.java
+++ b/core/java/android/window/TaskFragmentCreationParams.java
@@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.WindowingMode;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.TestApi;
import android.graphics.Rect;
import android.os.IBinder;
@@ -57,14 +58,33 @@ public final class TaskFragmentCreationParams implements Parcelable {
/** The initial windowing mode of the TaskFragment. Inherits from parent if not set. */
@WindowingMode
- private int mWindowingMode = WINDOWING_MODE_UNDEFINED;
+ private final int mWindowingMode;
+
+ /**
+ * The fragment token of the paired primary TaskFragment.
+ * When it is set, the new TaskFragment will be positioned right above the paired TaskFragment.
+ * Otherwise, the new TaskFragment will be positioned on the top of the Task by default.
+ *
+ * This is different from {@link WindowContainerTransaction#setAdjacentTaskFragments} as we may
+ * set this when the pair of TaskFragments are stacked, while adjacent is only set on the pair
+ * of TaskFragments that are in split.
+ *
+ * This is needed in case we need to launch a placeholder Activity to split below a transparent
+ * always-expand Activity.
+ */
+ @Nullable
+ private final IBinder mPairedPrimaryFragmentToken;
private TaskFragmentCreationParams(
- @NonNull TaskFragmentOrganizerToken organizer,
- @NonNull IBinder fragmentToken, @NonNull IBinder ownerToken) {
+ @NonNull TaskFragmentOrganizerToken organizer, @NonNull IBinder fragmentToken,
+ @NonNull IBinder ownerToken, @NonNull Rect initialBounds,
+ @WindowingMode int windowingMode, @Nullable IBinder pairedPrimaryFragmentToken) {
mOrganizer = organizer;
mFragmentToken = fragmentToken;
mOwnerToken = ownerToken;
+ mInitialBounds.set(initialBounds);
+ mWindowingMode = windowingMode;
+ mPairedPrimaryFragmentToken = pairedPrimaryFragmentToken;
}
@NonNull
@@ -92,12 +112,22 @@ public final class TaskFragmentCreationParams implements Parcelable {
return mWindowingMode;
}
+ /**
+ * TODO(b/232476698): remove the hide with adding CTS for this in next release.
+ * @hide
+ */
+ @Nullable
+ public IBinder getPairedPrimaryFragmentToken() {
+ return mPairedPrimaryFragmentToken;
+ }
+
private TaskFragmentCreationParams(Parcel in) {
mOrganizer = TaskFragmentOrganizerToken.CREATOR.createFromParcel(in);
mFragmentToken = in.readStrongBinder();
mOwnerToken = in.readStrongBinder();
mInitialBounds.readFromParcel(in);
mWindowingMode = in.readInt();
+ mPairedPrimaryFragmentToken = in.readStrongBinder();
}
/** @hide */
@@ -108,6 +138,7 @@ public final class TaskFragmentCreationParams implements Parcelable {
dest.writeStrongBinder(mOwnerToken);
mInitialBounds.writeToParcel(dest, flags);
dest.writeInt(mWindowingMode);
+ dest.writeStrongBinder(mPairedPrimaryFragmentToken);
}
@NonNull
@@ -132,6 +163,7 @@ public final class TaskFragmentCreationParams implements Parcelable {
+ " ownerToken=" + mOwnerToken
+ " initialBounds=" + mInitialBounds
+ " windowingMode=" + mWindowingMode
+ + " pairedFragmentToken=" + mPairedPrimaryFragmentToken
+ "}";
}
@@ -159,6 +191,9 @@ public final class TaskFragmentCreationParams implements Parcelable {
@WindowingMode
private int mWindowingMode = WINDOWING_MODE_UNDEFINED;
+ @Nullable
+ private IBinder mPairedPrimaryFragmentToken;
+
public Builder(@NonNull TaskFragmentOrganizerToken organizer,
@NonNull IBinder fragmentToken, @NonNull IBinder ownerToken) {
mOrganizer = organizer;
@@ -180,14 +215,29 @@ public final class TaskFragmentCreationParams implements Parcelable {
return this;
}
+ /**
+ * Sets the fragment token of the paired primary TaskFragment.
+ * When it is set, the new TaskFragment will be positioned right above the paired
+ * TaskFragment. Otherwise, the new TaskFragment will be positioned on the top of the Task
+ * by default.
+ *
+ * This is needed in case we need to launch a placeholder Activity to split below a
+ * transparent always-expand Activity.
+ *
+ * TODO(b/232476698): remove the hide with adding CTS for this in next release.
+ * @hide
+ */
+ @NonNull
+ public Builder setPairedPrimaryFragmentToken(@Nullable IBinder fragmentToken) {
+ mPairedPrimaryFragmentToken = fragmentToken;
+ return this;
+ }
+
/** Constructs the options to create TaskFragment with. */
@NonNull
public TaskFragmentCreationParams build() {
- final TaskFragmentCreationParams result = new TaskFragmentCreationParams(
- mOrganizer, mFragmentToken, mOwnerToken);
- result.mInitialBounds.set(mInitialBounds);
- result.mWindowingMode = mWindowingMode;
- return result;
+ return new TaskFragmentCreationParams(mOrganizer, mFragmentToken, mOwnerToken,
+ mInitialBounds, mWindowingMode, mPairedPrimaryFragmentToken);
}
}
}
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 365a18d174c9..a8abe50a9755 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -529,9 +529,8 @@ static jint android_hardware_Camera_getNumberOfCameras(JNIEnv *env, jobject thiz
return Camera::getNumberOfCameras();
}
-static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz,
- jint cameraId, jobject info_obj)
-{
+static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz, jint cameraId,
+ jboolean overrideToPortrait, jobject info_obj) {
CameraInfo cameraInfo;
if (cameraId >= Camera::getNumberOfCameras() || cameraId < 0) {
ALOGE("%s: Unknown camera ID %d", __FUNCTION__, cameraId);
@@ -539,7 +538,7 @@ static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz,
return;
}
- status_t rc = Camera::getCameraInfo(cameraId, &cameraInfo);
+ status_t rc = Camera::getCameraInfo(cameraId, overrideToPortrait, &cameraInfo);
if (rc != NO_ERROR) {
jniThrowRuntimeException(env, "Fail to get camera info");
return;
@@ -555,9 +554,9 @@ static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz,
}
// connect to camera service
-static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
- jobject weak_this, jint cameraId, jstring clientPackageName)
-{
+static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
+ jint cameraId, jstring clientPackageName,
+ jboolean overrideToPortrait) {
// Convert jstring to String16
const char16_t *rawClientName = reinterpret_cast<const char16_t*>(
env->GetStringChars(clientPackageName, NULL));
@@ -567,8 +566,9 @@ static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
reinterpret_cast<const jchar*>(rawClientName));
int targetSdkVersion = android_get_application_target_sdk_version();
- sp<Camera> camera = Camera::connect(cameraId, clientName, Camera::USE_CALLING_UID,
- Camera::USE_CALLING_PID, targetSdkVersion);
+ sp<Camera> camera =
+ Camera::connect(cameraId, clientName, Camera::USE_CALLING_UID, Camera::USE_CALLING_PID,
+ targetSdkVersion, overrideToPortrait);
if (camera == NULL) {
return -EACCES;
}
@@ -596,7 +596,7 @@ static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
// Update default display orientation in case the sensor is reverse-landscape
CameraInfo cameraInfo;
- status_t rc = Camera::getCameraInfo(cameraId, &cameraInfo);
+ status_t rc = Camera::getCameraInfo(cameraId, overrideToPortrait, &cameraInfo);
if (rc != NO_ERROR) {
ALOGE("%s: getCameraInfo error: %d", __FUNCTION__, rc);
return rc;
@@ -1051,93 +1051,43 @@ static int32_t android_hardware_Camera_getAudioRestriction(
//-------------------------------------------------
static const JNINativeMethod camMethods[] = {
- { "getNumberOfCameras",
- "()I",
- (void *)android_hardware_Camera_getNumberOfCameras },
- { "_getCameraInfo",
- "(ILandroid/hardware/Camera$CameraInfo;)V",
- (void*)android_hardware_Camera_getCameraInfo },
- { "native_setup",
- "(Ljava/lang/Object;ILjava/lang/String;)I",
- (void*)android_hardware_Camera_native_setup },
- { "native_release",
- "()V",
- (void*)android_hardware_Camera_release },
- { "setPreviewSurface",
- "(Landroid/view/Surface;)V",
- (void *)android_hardware_Camera_setPreviewSurface },
- { "setPreviewTexture",
- "(Landroid/graphics/SurfaceTexture;)V",
- (void *)android_hardware_Camera_setPreviewTexture },
- { "setPreviewCallbackSurface",
- "(Landroid/view/Surface;)V",
- (void *)android_hardware_Camera_setPreviewCallbackSurface },
- { "startPreview",
- "()V",
- (void *)android_hardware_Camera_startPreview },
- { "_stopPreview",
- "()V",
- (void *)android_hardware_Camera_stopPreview },
- { "previewEnabled",
- "()Z",
- (void *)android_hardware_Camera_previewEnabled },
- { "setHasPreviewCallback",
- "(ZZ)V",
- (void *)android_hardware_Camera_setHasPreviewCallback },
- { "_addCallbackBuffer",
- "([BI)V",
- (void *)android_hardware_Camera_addCallbackBuffer },
- { "native_autoFocus",
- "()V",
- (void *)android_hardware_Camera_autoFocus },
- { "native_cancelAutoFocus",
- "()V",
- (void *)android_hardware_Camera_cancelAutoFocus },
- { "native_takePicture",
- "(I)V",
- (void *)android_hardware_Camera_takePicture },
- { "native_setParameters",
- "(Ljava/lang/String;)V",
- (void *)android_hardware_Camera_setParameters },
- { "native_getParameters",
- "()Ljava/lang/String;",
- (void *)android_hardware_Camera_getParameters },
- { "reconnect",
- "()V",
- (void*)android_hardware_Camera_reconnect },
- { "lock",
- "()V",
- (void*)android_hardware_Camera_lock },
- { "unlock",
- "()V",
- (void*)android_hardware_Camera_unlock },
- { "startSmoothZoom",
- "(I)V",
- (void *)android_hardware_Camera_startSmoothZoom },
- { "stopSmoothZoom",
- "()V",
- (void *)android_hardware_Camera_stopSmoothZoom },
- { "setDisplayOrientation",
- "(I)V",
- (void *)android_hardware_Camera_setDisplayOrientation },
- { "_enableShutterSound",
- "(Z)Z",
- (void *)android_hardware_Camera_enableShutterSound },
- { "_startFaceDetection",
- "(I)V",
- (void *)android_hardware_Camera_startFaceDetection },
- { "_stopFaceDetection",
- "()V",
- (void *)android_hardware_Camera_stopFaceDetection},
- { "enableFocusMoveCallback",
- "(I)V",
- (void *)android_hardware_Camera_enableFocusMoveCallback},
- { "setAudioRestriction",
- "(I)V",
- (void *)android_hardware_Camera_setAudioRestriction},
- { "getAudioRestriction",
- "()I",
- (void *)android_hardware_Camera_getAudioRestriction},
+ {"getNumberOfCameras", "()I", (void *)android_hardware_Camera_getNumberOfCameras},
+ {"_getCameraInfo", "(IZLandroid/hardware/Camera$CameraInfo;)V",
+ (void *)android_hardware_Camera_getCameraInfo},
+ {"native_setup", "(Ljava/lang/Object;ILjava/lang/String;Z)I",
+ (void *)android_hardware_Camera_native_setup},
+ {"native_release", "()V", (void *)android_hardware_Camera_release},
+ {"setPreviewSurface", "(Landroid/view/Surface;)V",
+ (void *)android_hardware_Camera_setPreviewSurface},
+ {"setPreviewTexture", "(Landroid/graphics/SurfaceTexture;)V",
+ (void *)android_hardware_Camera_setPreviewTexture},
+ {"setPreviewCallbackSurface", "(Landroid/view/Surface;)V",
+ (void *)android_hardware_Camera_setPreviewCallbackSurface},
+ {"startPreview", "()V", (void *)android_hardware_Camera_startPreview},
+ {"_stopPreview", "()V", (void *)android_hardware_Camera_stopPreview},
+ {"previewEnabled", "()Z", (void *)android_hardware_Camera_previewEnabled},
+ {"setHasPreviewCallback", "(ZZ)V", (void *)android_hardware_Camera_setHasPreviewCallback},
+ {"_addCallbackBuffer", "([BI)V", (void *)android_hardware_Camera_addCallbackBuffer},
+ {"native_autoFocus", "()V", (void *)android_hardware_Camera_autoFocus},
+ {"native_cancelAutoFocus", "()V", (void *)android_hardware_Camera_cancelAutoFocus},
+ {"native_takePicture", "(I)V", (void *)android_hardware_Camera_takePicture},
+ {"native_setParameters", "(Ljava/lang/String;)V",
+ (void *)android_hardware_Camera_setParameters},
+ {"native_getParameters", "()Ljava/lang/String;",
+ (void *)android_hardware_Camera_getParameters},
+ {"reconnect", "()V", (void *)android_hardware_Camera_reconnect},
+ {"lock", "()V", (void *)android_hardware_Camera_lock},
+ {"unlock", "()V", (void *)android_hardware_Camera_unlock},
+ {"startSmoothZoom", "(I)V", (void *)android_hardware_Camera_startSmoothZoom},
+ {"stopSmoothZoom", "()V", (void *)android_hardware_Camera_stopSmoothZoom},
+ {"setDisplayOrientation", "(I)V", (void *)android_hardware_Camera_setDisplayOrientation},
+ {"_enableShutterSound", "(Z)Z", (void *)android_hardware_Camera_enableShutterSound},
+ {"_startFaceDetection", "(I)V", (void *)android_hardware_Camera_startFaceDetection},
+ {"_stopFaceDetection", "()V", (void *)android_hardware_Camera_stopFaceDetection},
+ {"enableFocusMoveCallback", "(I)V",
+ (void *)android_hardware_Camera_enableFocusMoveCallback},
+ {"setAudioRestriction", "(I)V", (void *)android_hardware_Camera_setAudioRestriction},
+ {"getAudioRestriction", "()I", (void *)android_hardware_Camera_getAudioRestriction},
};
struct field {
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 0c707fce7c7e..18c29d196ada 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2543,6 +2543,10 @@
states. -->
<bool name="config_dozeAlwaysOnDisplayAvailable">false</bool>
+ <!-- Control whether the pickup gesture is enabled by default. This value will be used
+ during initialization when the setting is still null. -->
+ <bool name="config_dozePickupGestureEnabled">true</bool>
+
<!-- Control whether the always on display mode is enabled by default. This value will be used
during initialization when the setting is still null. -->
<bool name="config_dozeAlwaysOnEnabled">true</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 9722e79b700a..b9259218c2d3 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3814,6 +3814,7 @@
<java-symbol type="string" name="config_cameraShutterSound" />
<java-symbol type="integer" name="config_autoGroupAtCount" />
<java-symbol type="bool" name="config_dozeAlwaysOnDisplayAvailable" />
+ <java-symbol type="bool" name="config_dozePickupGestureEnabled" />
<java-symbol type="bool" name="config_dozeAlwaysOnEnabled" />
<java-symbol type="bool" name="config_dozeSupportsAodWallpaper" />
<java-symbol type="bool" name="config_displayBlanksAfterDoze" />
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
index d7d43aa19757..b910287aa535 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
@@ -133,8 +133,18 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
}
// Create a TaskFragment for the secondary activity.
- createTaskFragmentAndStartActivity(wct, secondaryFragmentToken, ownerToken,
- secondaryFragmentBounds, windowingMode, activityIntent,
+ final TaskFragmentCreationParams fragmentOptions = new TaskFragmentCreationParams.Builder(
+ getOrganizerToken(), secondaryFragmentToken, ownerToken)
+ .setInitialBounds(secondaryFragmentBounds)
+ .setWindowingMode(windowingMode)
+ // Make sure to set the paired fragment token so that the new TaskFragment will be
+ // positioned right above the paired TaskFragment.
+ // This is needed in case we need to launch a placeholder Activity to split below a
+ // transparent always-expand Activity.
+ .setPairedPrimaryFragmentToken(launchingFragmentToken)
+ .build();
+ createTaskFragment(wct, fragmentOptions);
+ wct.startActivityInTaskFragment(secondaryFragmentToken, ownerToken, activityIntent,
activityOptions);
// Set adjacent to each other so that the containers below will be invisible.
@@ -173,8 +183,21 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
*/
void createTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
@NonNull IBinder ownerToken, @NonNull Rect bounds, @WindowingMode int windowingMode) {
- final TaskFragmentCreationParams fragmentOptions =
- createFragmentOptions(fragmentToken, ownerToken, bounds, windowingMode);
+ final TaskFragmentCreationParams fragmentOptions = new TaskFragmentCreationParams.Builder(
+ getOrganizerToken(), fragmentToken, ownerToken)
+ .setInitialBounds(bounds)
+ .setWindowingMode(windowingMode)
+ .build();
+ createTaskFragment(wct, fragmentOptions);
+ }
+
+ void createTaskFragment(@NonNull WindowContainerTransaction wct,
+ @NonNull TaskFragmentCreationParams fragmentOptions) {
+ if (mFragmentInfos.containsKey(fragmentOptions.getFragmentToken())) {
+ throw new IllegalArgumentException(
+ "There is an existing TaskFragment with fragmentToken="
+ + fragmentOptions.getFragmentToken());
+ }
wct.createTaskFragment(fragmentOptions);
}
@@ -189,18 +212,6 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
wct.reparentActivityToTaskFragment(fragmentToken, activity.getActivityToken());
}
- /**
- * @param ownerToken The token of the activity that creates this task fragment. It does not
- * have to be a child of this task fragment, but must belong to the same task.
- */
- private void createTaskFragmentAndStartActivity(@NonNull WindowContainerTransaction wct,
- @NonNull IBinder fragmentToken, @NonNull IBinder ownerToken, @NonNull Rect bounds,
- @WindowingMode int windowingMode, @NonNull Intent activityIntent,
- @Nullable Bundle activityOptions) {
- createTaskFragment(wct, fragmentToken, ownerToken, bounds, windowingMode);
- wct.startActivityInTaskFragment(fragmentToken, ownerToken, activityIntent, activityOptions);
- }
-
void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
@NonNull IBinder primary, @Nullable IBinder secondary, @Nullable SplitRule splitRule) {
WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams = null;
@@ -238,22 +249,6 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
wct.setCompanionTaskFragment(secondary, finishSecondaryWithPrimary ? primary : null);
}
- TaskFragmentCreationParams createFragmentOptions(@NonNull IBinder fragmentToken,
- @NonNull IBinder ownerToken, @NonNull Rect bounds, @WindowingMode int windowingMode) {
- if (mFragmentInfos.containsKey(fragmentToken)) {
- throw new IllegalArgumentException(
- "There is an existing TaskFragment with fragmentToken=" + fragmentToken);
- }
-
- return new TaskFragmentCreationParams.Builder(
- getOrganizerToken(),
- fragmentToken,
- ownerToken)
- .setInitialBounds(bounds)
- .setWindowingMode(windowingMode)
- .build();
- }
-
void resizeTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
@Nullable Rect bounds) {
if (!mFragmentInfos.containsKey(fragmentToken)) {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 6f9a4ff8188a..d3dc05fb92d4 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -1218,14 +1218,14 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
TaskFragmentContainer newContainer(@NonNull Activity pendingAppearedActivity,
@NonNull Activity activityInTask, int taskId) {
return newContainer(pendingAppearedActivity, null /* pendingAppearedIntent */,
- activityInTask, taskId);
+ activityInTask, taskId, null /* pairedPrimaryContainer */);
}
@GuardedBy("mLock")
TaskFragmentContainer newContainer(@NonNull Intent pendingAppearedIntent,
@NonNull Activity activityInTask, int taskId) {
return newContainer(null /* pendingAppearedActivity */, pendingAppearedIntent,
- activityInTask, taskId);
+ activityInTask, taskId, null /* pairedPrimaryContainer */);
}
/**
@@ -1237,10 +1237,13 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
* @param activityInTask activity in the same Task so that we can get the Task bounds
* if needed.
* @param taskId parent Task of the new TaskFragment.
+ * @param pairedPrimaryContainer the paired primary {@link TaskFragmentContainer}. When it is
+ * set, the new container will be added right above it.
*/
@GuardedBy("mLock")
TaskFragmentContainer newContainer(@Nullable Activity pendingAppearedActivity,
- @Nullable Intent pendingAppearedIntent, @NonNull Activity activityInTask, int taskId) {
+ @Nullable Intent pendingAppearedIntent, @NonNull Activity activityInTask, int taskId,
+ @Nullable TaskFragmentContainer pairedPrimaryContainer) {
if (activityInTask == null) {
throw new IllegalArgumentException("activityInTask must not be null,");
}
@@ -1249,7 +1252,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
}
final TaskContainer taskContainer = mTaskContainers.get(taskId);
final TaskFragmentContainer container = new TaskFragmentContainer(pendingAppearedActivity,
- pendingAppearedIntent, taskContainer, this);
+ pendingAppearedIntent, taskContainer, this, pairedPrimaryContainer);
return container;
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index 5395fb2ef5ed..47253d388f0d 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -36,6 +36,7 @@ import android.util.Size;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowMetrics;
+import android.window.TaskFragmentCreationParams;
import android.window.WindowContainerTransaction;
import androidx.annotation.GuardedBy;
@@ -307,10 +308,13 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
}
final int taskId = primaryContainer.getTaskId();
- final TaskFragmentContainer secondaryContainer = mController.newContainer(activityIntent,
- launchingActivity, taskId);
- final int windowingMode = mController.getTaskContainer(taskId)
- .getWindowingModeForSplitTaskFragment(primaryRectBounds);
+ final TaskFragmentContainer secondaryContainer = mController.newContainer(
+ null /* pendingAppearedActivity */, activityIntent, launchingActivity, taskId,
+ // Pass in the primary container to make sure it is added right above the primary.
+ primaryContainer);
+ final TaskContainer taskContainer = mController.getTaskContainer(taskId);
+ final int windowingMode = taskContainer.getWindowingModeForSplitTaskFragment(
+ primaryRectBounds);
mController.registerSplit(wct, primaryContainer, launchingActivity, secondaryContainer,
rule, splitAttributes);
startActivityToSide(wct, primaryContainer.getTaskFragmentToken(), primaryRectBounds,
@@ -412,17 +416,18 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
}
@Override
- void createTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
- @NonNull IBinder ownerToken, @NonNull Rect bounds, @WindowingMode int windowingMode) {
- final TaskFragmentContainer container = mController.getContainer(fragmentToken);
+ void createTaskFragment(@NonNull WindowContainerTransaction wct,
+ @NonNull TaskFragmentCreationParams fragmentOptions) {
+ final TaskFragmentContainer container = mController.getContainer(
+ fragmentOptions.getFragmentToken());
if (container == null) {
throw new IllegalStateException(
"Creating a task fragment that is not registered with controller.");
}
- container.setLastRequestedBounds(bounds);
- container.setLastRequestedWindowingMode(windowingMode);
- super.createTaskFragment(wct, fragmentToken, ownerToken, bounds, windowingMode);
+ container.setLastRequestedBounds(fragmentOptions.getInitialBounds());
+ container.setLastRequestedWindowingMode(fragmentOptions.getWindowingMode());
+ super.createTaskFragment(wct, fragmentOptions);
}
@Override
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index e31792ad718f..fcf0ac78af38 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -118,10 +118,12 @@ class TaskFragmentContainer {
/**
* Creates a container with an existing activity that will be re-parented to it in a window
* container transaction.
+ * @param pairedPrimaryContainer when it is set, the new container will be add right above it
*/
TaskFragmentContainer(@Nullable Activity pendingAppearedActivity,
@Nullable Intent pendingAppearedIntent, @NonNull TaskContainer taskContainer,
- @NonNull SplitController controller) {
+ @NonNull SplitController controller,
+ @Nullable TaskFragmentContainer pairedPrimaryContainer) {
if ((pendingAppearedActivity == null && pendingAppearedIntent == null)
|| (pendingAppearedActivity != null && pendingAppearedIntent != null)) {
throw new IllegalArgumentException(
@@ -130,7 +132,16 @@ class TaskFragmentContainer {
mController = controller;
mToken = new Binder("TaskFragmentContainer");
mTaskContainer = taskContainer;
- taskContainer.mContainers.add(this);
+ if (pairedPrimaryContainer != null) {
+ if (pairedPrimaryContainer.getTaskContainer() != taskContainer) {
+ throw new IllegalArgumentException(
+ "pairedPrimaryContainer must be in the same Task");
+ }
+ final int primaryIndex = taskContainer.mContainers.indexOf(pairedPrimaryContainer);
+ taskContainer.mContainers.add(primaryIndex + 1, this);
+ } else {
+ taskContainer.mContainers.add(this);
+ }
if (pendingAppearedActivity != null) {
addPendingAppearedActivity(pendingAppearedActivity);
}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
index 31aa09c902b1..bbb454d31c38 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
@@ -102,7 +102,7 @@ public class JetpackTaskFragmentOrganizerTest {
public void testExpandTaskFragment() {
final TaskContainer taskContainer = createTestTaskContainer();
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
- new Intent(), taskContainer, mSplitController);
+ new Intent(), taskContainer, mSplitController, null /* pairedPrimaryContainer */);
final TaskFragmentInfo info = createMockInfo(container);
mOrganizer.mFragmentInfos.put(container.getTaskFragmentToken(), info);
container.setInfo(mTransaction, info);
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
index 221c7640ef0b..6725dfdb94e8 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
@@ -169,7 +169,7 @@ public class SplitControllerTest {
final TaskContainer taskContainer = createTestTaskContainer();
// tf1 has no running activity so is not active.
final TaskFragmentContainer tf1 = new TaskFragmentContainer(null /* activity */,
- new Intent(), taskContainer, mSplitController);
+ new Intent(), taskContainer, mSplitController, null /* pairedPrimaryContainer */);
// tf2 has running activity so is active.
final TaskFragmentContainer tf2 = mock(TaskFragmentContainer.class);
doReturn(1).when(tf2).getRunningActivityCount();
@@ -375,7 +375,7 @@ public class SplitControllerTest {
final Intent intent = new Intent();
final TaskContainer taskContainer = createTestTaskContainer();
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
- intent, taskContainer, mSplitController);
+ intent, taskContainer, mSplitController, null /* pairedPrimaryContainer */);
final SplitController.ActivityStartMonitor monitor =
mSplitController.getActivityStartMonitor();
@@ -609,7 +609,7 @@ public class SplitControllerTest {
false /* isOnReparent */);
assertFalse(result);
- verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt());
+ verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt(), any());
}
@Test
@@ -771,7 +771,7 @@ public class SplitControllerTest {
false /* isOnReparent */);
assertTrue(result);
- verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt());
+ verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt(), any());
verify(mSplitController, never()).registerSplit(any(), any(), any(), any(), any(), any());
}
@@ -813,7 +813,7 @@ public class SplitControllerTest {
false /* isOnReparent */);
assertTrue(result);
- verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt());
+ verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt(), any());
verify(mSplitController, never()).registerSplit(any(), any(), any(), any(), any(), any());
}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
index 95328ce700e3..13e709271221 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
@@ -122,7 +122,7 @@ public class TaskContainerTest {
assertTrue(taskContainer.isEmpty());
final TaskFragmentContainer tf = new TaskFragmentContainer(null /* activity */,
- new Intent(), taskContainer, mController);
+ new Intent(), taskContainer, mController, null /* pairedPrimaryContainer */);
assertFalse(taskContainer.isEmpty());
@@ -138,11 +138,11 @@ public class TaskContainerTest {
assertNull(taskContainer.getTopTaskFragmentContainer());
final TaskFragmentContainer tf0 = new TaskFragmentContainer(null /* activity */,
- new Intent(), taskContainer, mController);
+ new Intent(), taskContainer, mController, null /* pairedPrimaryContainer */);
assertEquals(tf0, taskContainer.getTopTaskFragmentContainer());
final TaskFragmentContainer tf1 = new TaskFragmentContainer(null /* activity */,
- new Intent(), taskContainer, mController);
+ new Intent(), taskContainer, mController, null /* pairedPrimaryContainer */);
assertEquals(tf1, taskContainer.getTopTaskFragmentContainer());
}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
index 99f56b4ceb17..5c3ba72e2361 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
@@ -94,18 +94,21 @@ public class TaskFragmentContainerTest {
// One of the activity and the intent must be non-null
assertThrows(IllegalArgumentException.class,
- () -> new TaskFragmentContainer(null, null, taskContainer, mController));
+ () -> new TaskFragmentContainer(null, null, taskContainer, mController,
+ null /* pairedPrimaryContainer */));
// One of the activity and the intent must be null.
assertThrows(IllegalArgumentException.class,
- () -> new TaskFragmentContainer(mActivity, mIntent, taskContainer, mController));
+ () -> new TaskFragmentContainer(mActivity, mIntent, taskContainer, mController,
+ null /* pairedPrimaryContainer */));
}
@Test
public void testFinish() {
final TaskContainer taskContainer = createTestTaskContainer();
final TaskFragmentContainer container = new TaskFragmentContainer(mActivity,
- null /* pendingAppearedIntent */, taskContainer, mController);
+ null /* pendingAppearedIntent */, taskContainer, mController,
+ null /* pairedPrimaryContainer */);
doReturn(container).when(mController).getContainerWithActivity(mActivity);
// Only remove the activity, but not clear the reference until appeared.
@@ -137,12 +140,14 @@ public class TaskFragmentContainerTest {
public void testFinish_notFinishActivityThatIsReparenting() {
final TaskContainer taskContainer = createTestTaskContainer();
final TaskFragmentContainer container0 = new TaskFragmentContainer(mActivity,
- null /* pendingAppearedIntent */, taskContainer, mController);
+ null /* pendingAppearedIntent */, taskContainer, mController,
+ null /* pairedPrimaryContainer */);
final TaskFragmentInfo info = createMockTaskFragmentInfo(container0, mActivity);
container0.setInfo(mTransaction, info);
// Request to reparent the activity to a new TaskFragment.
final TaskFragmentContainer container1 = new TaskFragmentContainer(mActivity,
- null /* pendingAppearedIntent */, taskContainer, mController);
+ null /* pendingAppearedIntent */, taskContainer, mController,
+ null /* pairedPrimaryContainer */);
doReturn(container1).when(mController).getContainerWithActivity(mActivity);
final WindowContainerTransaction wct = new WindowContainerTransaction();
@@ -159,7 +164,8 @@ public class TaskFragmentContainerTest {
final TaskContainer taskContainer = createTestTaskContainer();
// Pending activity should be cleared when it has appeared on server side.
final TaskFragmentContainer pendingActivityContainer = new TaskFragmentContainer(mActivity,
- null /* pendingAppearedIntent */, taskContainer, mController);
+ null /* pendingAppearedIntent */, taskContainer, mController,
+ null /* pairedPrimaryContainer */);
assertTrue(pendingActivityContainer.mPendingAppearedActivities.contains(
mActivity.getActivityToken()));
@@ -172,7 +178,8 @@ public class TaskFragmentContainerTest {
// Pending intent should be cleared when the container becomes non-empty.
final TaskFragmentContainer pendingIntentContainer = new TaskFragmentContainer(
- null /* pendingAppearedActivity */, mIntent, taskContainer, mController);
+ null /* pendingAppearedActivity */, mIntent, taskContainer, mController,
+ null /* pairedPrimaryContainer */);
assertEquals(mIntent, pendingIntentContainer.getPendingAppearedIntent());
@@ -187,7 +194,7 @@ public class TaskFragmentContainerTest {
public void testIsWaitingActivityAppear() {
final TaskContainer taskContainer = createTestTaskContainer();
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
- mIntent, taskContainer, mController);
+ mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
assertTrue(container.isWaitingActivityAppear());
@@ -209,7 +216,7 @@ public class TaskFragmentContainerTest {
doNothing().when(mController).onTaskFragmentAppearEmptyTimeout(any(), any());
final TaskContainer taskContainer = createTestTaskContainer();
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
- mIntent, taskContainer, mController);
+ mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
assertNull(container.mAppearEmptyTimeout);
@@ -249,7 +256,7 @@ public class TaskFragmentContainerTest {
public void testCollectNonFinishingActivities() {
final TaskContainer taskContainer = createTestTaskContainer();
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
- mIntent, taskContainer, mController);
+ mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
List<Activity> activities = container.collectNonFinishingActivities();
assertTrue(activities.isEmpty());
@@ -277,7 +284,7 @@ public class TaskFragmentContainerTest {
public void testAddPendingActivity() {
final TaskContainer taskContainer = createTestTaskContainer();
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
- mIntent, taskContainer, mController);
+ mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
container.addPendingAppearedActivity(mActivity);
assertEquals(1, container.collectNonFinishingActivities().size());
@@ -291,9 +298,9 @@ public class TaskFragmentContainerTest {
public void testIsAbove() {
final TaskContainer taskContainer = createTestTaskContainer();
final TaskFragmentContainer container0 = new TaskFragmentContainer(null /* activity */,
- mIntent, taskContainer, mController);
+ mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
final TaskFragmentContainer container1 = new TaskFragmentContainer(null /* activity */,
- mIntent, taskContainer, mController);
+ mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
assertTrue(container1.isAbove(container0));
assertFalse(container0.isAbove(container1));
@@ -303,7 +310,7 @@ public class TaskFragmentContainerTest {
public void testGetBottomMostActivity() {
final TaskContainer taskContainer = createTestTaskContainer();
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
- mIntent, taskContainer, mController);
+ mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
container.addPendingAppearedActivity(mActivity);
assertEquals(mActivity, container.getBottomMostActivity());
@@ -320,7 +327,7 @@ public class TaskFragmentContainerTest {
public void testOnActivityDestroyed() {
final TaskContainer taskContainer = createTestTaskContainer(mController);
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
- mIntent, taskContainer, mController);
+ mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
container.addPendingAppearedActivity(mActivity);
final List<IBinder> activities = new ArrayList<>();
activities.add(mActivity.getActivityToken());
@@ -340,7 +347,7 @@ public class TaskFragmentContainerTest {
// True if no info set.
final TaskContainer taskContainer = createTestTaskContainer();
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
- mIntent, taskContainer, mController);
+ mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
spyOn(taskContainer);
doReturn(true).when(taskContainer).isVisible();
@@ -403,7 +410,7 @@ public class TaskFragmentContainerTest {
public void testHasAppearedActivity() {
final TaskContainer taskContainer = createTestTaskContainer();
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
- mIntent, taskContainer, mController);
+ mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
container.addPendingAppearedActivity(mActivity);
assertFalse(container.hasAppearedActivity(mActivity.getActivityToken()));
@@ -420,7 +427,7 @@ public class TaskFragmentContainerTest {
public void testHasPendingAppearedActivity() {
final TaskContainer taskContainer = createTestTaskContainer();
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
- mIntent, taskContainer, mController);
+ mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
container.addPendingAppearedActivity(mActivity);
assertTrue(container.hasPendingAppearedActivity(mActivity.getActivityToken()));
@@ -437,9 +444,9 @@ public class TaskFragmentContainerTest {
public void testHasActivity() {
final TaskContainer taskContainer = createTestTaskContainer(mController);
final TaskFragmentContainer container1 = new TaskFragmentContainer(null /* activity */,
- mIntent, taskContainer, mController);
+ mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
final TaskFragmentContainer container2 = new TaskFragmentContainer(null /* activity */,
- mIntent, taskContainer, mController);
+ mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
// Activity is pending appeared on container2.
container2.addPendingAppearedActivity(mActivity);
@@ -472,6 +479,27 @@ public class TaskFragmentContainerTest {
assertTrue(container2.hasActivity(mActivity.getActivityToken()));
}
+ @Test
+ public void testNewContainerWithPairedPrimaryContainer() {
+ final TaskContainer taskContainer = createTestTaskContainer();
+ final TaskFragmentContainer tf0 = new TaskFragmentContainer(
+ null /* pendingAppearedActivity */, new Intent(), taskContainer, mController,
+ null /* pairedPrimaryTaskFragment */);
+ final TaskFragmentContainer tf1 = new TaskFragmentContainer(
+ null /* pendingAppearedActivity */, new Intent(), taskContainer, mController,
+ null /* pairedPrimaryTaskFragment */);
+ taskContainer.mContainers.add(tf0);
+ taskContainer.mContainers.add(tf1);
+
+ // When tf2 is created with using tf0 as pairedPrimaryContainer, tf2 should be inserted
+ // right above tf0.
+ final TaskFragmentContainer tf2 = new TaskFragmentContainer(
+ null /* pendingAppearedActivity */, new Intent(), taskContainer, mController, tf0);
+ assertEquals(0, taskContainer.indexOf(tf0));
+ assertEquals(1, taskContainer.indexOf(tf2));
+ assertEquals(2, taskContainer.indexOf(tf1));
+ }
+
/** Creates a mock activity in the organizer process. */
private Activity createMockActivity() {
final Activity activity = mock(Activity.class);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java
index d3a9a672ec76..56b13b8dcd46 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java
@@ -19,7 +19,6 @@ package com.android.wm.shell.bubbles;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.drawable.AdaptiveIconDrawable;
@@ -59,7 +58,8 @@ public class BubbleBadgeIconFactory extends BaseIconFactory {
private class CircularRingDrawable extends CircularAdaptiveIcon {
final int mImportantConversationColor;
- final Rect mTempBounds = new Rect();
+ final int mRingWidth;
+ final Rect mInnerBounds = new Rect();
final Drawable mDr;
@@ -68,6 +68,8 @@ public class BubbleBadgeIconFactory extends BaseIconFactory {
mDr = dr;
mImportantConversationColor = mContext.getResources().getColor(
R.color.important_conversation, null);
+ mRingWidth = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.importance_ring_stroke_width);
}
@Override
@@ -75,11 +77,10 @@ public class BubbleBadgeIconFactory extends BaseIconFactory {
int save = canvas.save();
canvas.clipPath(getIconMask());
canvas.drawColor(mImportantConversationColor);
- int ringStrokeWidth = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.importance_ring_stroke_width);
- mTempBounds.set(getBounds());
- mTempBounds.inset(ringStrokeWidth, ringStrokeWidth);
- mDr.setBounds(mTempBounds);
+ mInnerBounds.set(getBounds());
+ mInnerBounds.inset(mRingWidth, mRingWidth);
+ canvas.translate(mInnerBounds.left, mInnerBounds.top);
+ mDr.setBounds(0, 0, mInnerBounds.width(), mInnerBounds.height());
mDr.draw(canvas);
canvas.restoreToCount(save);
}
@@ -106,7 +107,6 @@ public class BubbleBadgeIconFactory extends BaseIconFactory {
int save = canvas.save();
canvas.clipPath(getIconMask());
- canvas.drawColor(Color.BLACK);
Drawable d;
if ((d = getBackground()) != null) {
d.draw(canvas);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index ad0adc6c84c4..c743582c3264 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -692,7 +692,7 @@ public abstract class WMShellBaseModule {
// Use optional-of-lazy for the dependency that this provider relies on.
// Lazy ensures that this provider will not be the cause the dependency is created
// when it will not be returned due to the condition below.
- if (DesktopModeStatus.IS_SUPPORTED) {
+ if (DesktopModeStatus.isProto1Enabled()) {
return desktopModeController.map(Lazy::get);
}
return Optional.empty();
@@ -709,7 +709,7 @@ public abstract class WMShellBaseModule {
// Use optional-of-lazy for the dependency that this provider relies on.
// Lazy ensures that this provider will not be the cause the dependency is created
// when it will not be returned due to the condition below.
- if (DesktopModeStatus.IS_SUPPORTED) {
+ if (DesktopModeStatus.isAnyEnabled()) {
return desktopModeTaskRepository.map(Lazy::get);
}
return Optional.empty();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
index 5824f51a1d33..7eb01a79f14f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
@@ -100,7 +100,7 @@ public class DesktopModeController implements RemoteCallable<DesktopModeControll
mDesktopModeTaskRepository = desktopModeTaskRepository;
mMainExecutor = mainExecutor;
mSettingsObserver = new SettingsObserver(mContext, mainHandler);
- if (DesktopModeStatus.isSupported()) {
+ if (DesktopModeStatus.isProto1Enabled()) {
shellInit.addInitCallback(this::onInit, this);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
index e3eb2b746969..67f4a1914c49 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
@@ -33,17 +33,38 @@ public class DesktopModeStatus {
/**
* Flag to indicate whether desktop mode is available on the device
*/
- public static final boolean IS_SUPPORTED = SystemProperties.getBoolean(
+ private static final boolean IS_SUPPORTED = SystemProperties.getBoolean(
"persist.wm.debug.desktop_mode", false);
/**
+ * Flag to indicate whether desktop mode proto 2 is available on the device
+ */
+ private static final boolean IS_PROTO2_ENABLED = SystemProperties.getBoolean(
+ "persist.wm.debug.desktop_mode_2", false);
+
+ /**
* Return {@code true} if desktop mode support is enabled
*/
- public static boolean isSupported() {
+ public static boolean isProto1Enabled() {
return IS_SUPPORTED;
}
/**
+ * Return {@code true} is desktop windowing proto 2 is enabled
+ */
+ public static boolean isProto2Enabled() {
+ return IS_PROTO2_ENABLED;
+ }
+
+ /**
+ * Return {@code true} if proto 1 or 2 is enabled.
+ * Can be used to guard logic that is common for both prototypes.
+ */
+ public static boolean isAnyEnabled() {
+ return isProto1Enabled() || isProto2Enabled();
+ }
+
+ /**
* Check if desktop mode is active
*
* @return {@code true} if active
@@ -61,5 +82,4 @@ public class DesktopModeStatus {
return false;
}
}
-
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
index 8a9b74fd72b1..793bad86d873 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -68,7 +68,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
private void onInit() {
mShellTaskOrganizer.addListenerForType(this, TASK_LISTENER_TYPE_FREEFORM);
- if (DesktopModeStatus.IS_SUPPORTED) {
+ if (DesktopModeStatus.isAnyEnabled()) {
mShellTaskOrganizer.addFocusListener(this);
}
}
@@ -90,7 +90,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
t.apply();
}
- if (DesktopModeStatus.IS_SUPPORTED) {
+ if (DesktopModeStatus.isAnyEnabled()) {
mDesktopModeTaskRepository.ifPresent(repository -> {
repository.addOrMoveFreeformTaskToTop(taskInfo.taskId);
if (taskInfo.isVisible) {
@@ -110,7 +110,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
taskInfo.taskId);
mTasks.remove(taskInfo.taskId);
- if (DesktopModeStatus.IS_SUPPORTED) {
+ if (DesktopModeStatus.isAnyEnabled()) {
mDesktopModeTaskRepository.ifPresent(repository -> {
repository.removeFreeformTask(taskInfo.taskId);
if (repository.removeActiveTask(taskInfo.taskId)) {
@@ -134,7 +134,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
taskInfo.taskId);
mWindowDecorationViewModel.onTaskInfoChanged(state.mTaskInfo);
- if (DesktopModeStatus.IS_SUPPORTED) {
+ if (DesktopModeStatus.isAnyEnabled()) {
mDesktopModeTaskRepository.ifPresent(repository -> {
if (taskInfo.isVisible) {
if (repository.addActiveTask(taskInfo.taskId)) {
@@ -152,7 +152,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG,
"Freeform Task Focus Changed: #%d focused=%b",
taskInfo.taskId, taskInfo.isFocused);
- if (DesktopModeStatus.IS_SUPPORTED && taskInfo.isFocused) {
+ if (DesktopModeStatus.isAnyEnabled() && taskInfo.isFocused) {
mDesktopModeTaskRepository.ifPresent(repository -> {
repository.addOrMoveFreeformTaskToTop(taskInfo.taskId);
});
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index 85bad174194c..e6c7e101d078 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -358,8 +358,10 @@ public class PipTransition extends PipTransitionController {
WindowContainerTransaction wct = null;
if (isOutPipDirection(direction)) {
// Only need to reset surface properties. The server-side operations were already
- // done at the start.
- if (tx != null) {
+ // done at the start. But if it is running fixed rotation, there will be a seamless
+ // display transition later. So the last rotation transform needs to be kept to
+ // avoid flickering, and then the display transition will reset the transform.
+ if (tx != null && !mInFixedRotation) {
mFinishTransaction.merge(tx);
}
} else {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index 56554020f3cc..afefd5dc6344 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -517,7 +517,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
private boolean shouldShowWindowDecor(RunningTaskInfo taskInfo) {
if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) return true;
- return DesktopModeStatus.IS_SUPPORTED
+ return DesktopModeStatus.isAnyEnabled()
&& taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD
&& mDisplayController.getDisplayContext(taskInfo.displayId)
.getResources().getConfiguration().smallestScreenWidthDp >= 600;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java
index dad913300711..b3c9e238a614 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java
@@ -100,7 +100,7 @@ public class DesktopModeControllerTest extends ShellTestCase {
@Before
public void setUp() {
mMockitoSession = mockitoSession().mockStatic(DesktopModeStatus.class).startMocking();
- when(DesktopModeStatus.isSupported()).thenReturn(true);
+ when(DesktopModeStatus.isProto1Enabled()).thenReturn(true);
when(DesktopModeStatus.isActive(any())).thenReturn(true);
mShellInit = Mockito.spy(new ShellInit(mTestExecutor));
@@ -129,7 +129,7 @@ public class DesktopModeControllerTest extends ShellTestCase {
@Test
public void instantiate_flagOff_doNotAddInitCallback() {
- when(DesktopModeStatus.isSupported()).thenReturn(false);
+ when(DesktopModeStatus.isProto1Enabled()).thenReturn(false);
clearInvocations(mShellInit);
createController();
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index a2eae2c9579a..2b7bcbee79fd 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -85,7 +85,8 @@ public class CameraBinderTest extends AndroidTestCase {
public void testCameraInfo() throws Exception {
for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
- CameraInfo info = mUtils.getCameraService().getCameraInfo(cameraId);
+ CameraInfo info = mUtils.getCameraService().getCameraInfo(cameraId,
+ /*overrideToPortrait*/false);
assertTrue("Facing was not set for camera " + cameraId, info.info.facing != -1);
assertTrue("Orientation was not set for camera " + cameraId,
info.info.orientation != -1);
@@ -159,7 +160,8 @@ public class CameraBinderTest extends AndroidTestCase {
.connect(dummyCallbacks, cameraId, clientPackageName,
ICameraService.USE_CALLING_UID,
ICameraService.USE_CALLING_PID,
- getContext().getApplicationInfo().targetSdkVersion);
+ getContext().getApplicationInfo().targetSdkVersion,
+ /*overrideToPortrait*/false);
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
Log.v(TAG, String.format("Camera %s connected", cameraId));
@@ -264,7 +266,8 @@ public class CameraBinderTest extends AndroidTestCase {
dummyCallbacks, String.valueOf(cameraId),
clientPackageName, clientAttributionTag,
ICameraService.USE_CALLING_UID, 0 /*oomScoreOffset*/,
- getContext().getApplicationInfo().targetSdkVersion);
+ getContext().getApplicationInfo().targetSdkVersion,
+ /*overrideToPortrait*/false);
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
Log.v(TAG, String.format("Camera %s connected", cameraId));
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index 0890346db198..9d09dcc5c440 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -244,7 +244,8 @@ public class CameraDeviceBinderTest extends AndroidTestCase {
mCameraUser = mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
clientPackageName, clientAttributionTag, ICameraService.USE_CALLING_UID,
- /*oomScoreOffset*/0, getContext().getApplicationInfo().targetSdkVersion);
+ /*oomScoreOffset*/0, getContext().getApplicationInfo().targetSdkVersion,
+ /*overrideToPortrait*/false);
assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser);
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
@@ -417,7 +418,7 @@ public class CameraDeviceBinderTest extends AndroidTestCase {
@SmallTest
public void testCameraCharacteristics() throws RemoteException {
CameraMetadataNative info = mUtils.getCameraService().getCameraCharacteristics(mCameraId,
- getContext().getApplicationInfo().targetSdkVersion);
+ getContext().getApplicationInfo().targetSdkVersion, /*overrideToPortrait*/false);
assertFalse(info.isEmpty());
assertNotNull(info.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS));
diff --git a/packages/SystemUI/res-keyguard/layout/fgs_footer.xml b/packages/SystemUI/res-keyguard/layout/fgs_footer.xml
deleted file mode 100644
index ee588f997ab8..000000000000
--- a/packages/SystemUI/res-keyguard/layout/fgs_footer.xml
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2022 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- TODO(b/242040009): Remove this file. -->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_security_footer_single_line_height"
- android:layout_weight="1"
- android:gravity="center"
- android:clickable="true"
- android:visibility="gone">
-
- <LinearLayout
- android:id="@+id/fgs_text_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/qs_footer_action_inset"
- android:background="@drawable/qs_security_footer_background"
- android:layout_gravity="end"
- android:gravity="center"
- android:paddingHorizontal="@dimen/qs_footer_padding"
- >
-
- <ImageView
- android:id="@+id/primary_footer_icon"
- android:layout_width="@dimen/qs_footer_icon_size"
- android:layout_height="@dimen/qs_footer_icon_size"
- android:gravity="start"
- android:layout_marginEnd="12dp"
- android:contentDescription="@null"
- android:src="@drawable/ic_info_outline"
- android:tint="?android:attr/textColorSecondary" />
-
- <TextView
- android:id="@+id/footer_text"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:maxLines="1"
- android:ellipsize="end"
- android:textAppearance="@style/TextAppearance.QS.SecurityFooter"
- android:textColor="?android:attr/textColorSecondary"/>
-
- <ImageView
- android:id="@+id/fgs_new"
- android:layout_width="12dp"
- android:layout_height="12dp"
- android:scaleType="fitCenter"
- android:src="@drawable/fgs_dot"
- android:contentDescription="@string/fgs_dot_content_description"
- />
-
- <ImageView
- android:id="@+id/footer_icon"
- android:layout_width="@dimen/qs_footer_icon_size"
- android:layout_height="@dimen/qs_footer_icon_size"
- android:layout_marginStart="8dp"
- android:contentDescription="@null"
- android:src="@*android:drawable/ic_chevron_end"
- android:autoMirrored="true"
- android:tint="?android:attr/textColorSecondary" />
- </LinearLayout>
-
- <FrameLayout
- android:id="@+id/fgs_number_container"
- android:layout_width="@dimen/qs_footer_action_button_size"
- android:layout_height="@dimen/qs_footer_action_button_size"
- android:background="@drawable/qs_footer_action_circle"
- android:focusable="true"
- android:visibility="gone">
-
- <TextView
- android:id="@+id/fgs_number"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.QS.SecurityFooter"
- android:layout_gravity="center"
- android:textColor="?android:attr/textColorPrimary"
- android:textSize="18sp"/>
- <ImageView
- android:id="@+id/fgs_collapsed_new"
- android:layout_width="12dp"
- android:layout_height="12dp"
- android:scaleType="fitCenter"
- android:layout_gravity="bottom|end"
- android:src="@drawable/fgs_dot"
- android:contentDescription="@string/fgs_dot_content_description"
- />
- </FrameLayout>
-
-</FrameLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/layout/footer_actions.xml b/packages/SystemUI/res-keyguard/layout/footer_actions.xml
index 2261ae8d7714..4a2a1cb9dc6d 100644
--- a/packages/SystemUI/res-keyguard/layout/footer_actions.xml
+++ b/packages/SystemUI/res-keyguard/layout/footer_actions.xml
@@ -16,10 +16,8 @@
-->
<!-- Action buttons for footer in QS/QQS, containing settings button, power off button etc -->
-<!-- TODO(b/242040009): Clean up this file. -->
-<com.android.systemui.qs.FooterActionsView
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/footer_actions_height"
android:elevation="@dimen/qs_panel_elevation"
@@ -28,74 +26,4 @@
android:background="@drawable/qs_footer_actions_background"
android:gravity="center_vertical|end"
android:layout_gravity="bottom"
->
-
- <LinearLayout
- android:id="@+id/security_footers_container"
- android:orientation="horizontal"
- android:layout_height="@dimen/qs_footer_action_button_size"
- android:layout_width="0dp"
- android:layout_weight="1"
- />
-
- <!-- Negative margin equal to -->
- <LinearLayout
- android:layout_height="match_parent"
- android:layout_width="wrap_content"
- android:layout_marginEnd="@dimen/qs_footer_action_inset_negative"
- >
-
- <com.android.systemui.statusbar.phone.MultiUserSwitch
- android:id="@id/multi_user_switch"
- android:layout_width="@dimen/qs_footer_action_button_size"
- android:layout_height="@dimen/qs_footer_action_button_size"
- android:background="@drawable/qs_footer_action_circle"
- android:focusable="true">
-
- <ImageView
- android:id="@+id/multi_user_avatar"
- android:layout_width="@dimen/qs_footer_icon_size"
- android:layout_height="@dimen/qs_footer_icon_size"
- android:layout_gravity="center"
- android:scaleType="centerInside" />
- </com.android.systemui.statusbar.phone.MultiUserSwitch>
-
- <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
- android:id="@id/settings_button_container"
- android:layout_width="@dimen/qs_footer_action_button_size"
- android:layout_height="@dimen/qs_footer_action_button_size"
- android:background="@drawable/qs_footer_action_circle"
- android:clipChildren="false"
- android:clipToPadding="false">
-
- <com.android.systemui.statusbar.phone.SettingsButton
- android:id="@+id/settings_button"
- android:layout_width="@dimen/qs_footer_icon_size"
- android:layout_height="@dimen/qs_footer_icon_size"
- android:layout_gravity="center"
- android:background="@android:color/transparent"
- android:focusable="false"
- android:clickable="false"
- android:importantForAccessibility="yes"
- android:contentDescription="@string/accessibility_quick_settings_settings"
- android:scaleType="centerInside"
- android:src="@drawable/ic_settings"
- android:tint="?android:attr/textColorPrimary" />
-
- </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
-
- <com.android.systemui.statusbar.AlphaOptimizedImageView
- android:id="@id/pm_lite"
- android:layout_width="@dimen/qs_footer_action_button_size"
- android:layout_height="@dimen/qs_footer_action_button_size"
- android:background="@drawable/qs_footer_action_circle_color"
- android:clickable="true"
- android:clipToPadding="false"
- android:focusable="true"
- android:padding="@dimen/qs_footer_icon_padding"
- android:src="@*android:drawable/ic_lock_power_off"
- android:contentDescription="@string/accessibility_quick_settings_power_menu"
- android:tint="?androidprv:attr/textColorOnAccent" />
-
- </LinearLayout>
-</com.android.systemui.qs.FooterActionsView> \ No newline at end of file
+/> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/activity_rear_display_education.xml b/packages/SystemUI/res/layout/activity_rear_display_education.xml
index 73d3f0236fff..f5fc48c70003 100644
--- a/packages/SystemUI/res/layout/activity_rear_display_education.xml
+++ b/packages/SystemUI/res/layout/activity_rear_display_education.xml
@@ -33,7 +33,7 @@
android:layout_width="@dimen/rear_display_animation_width"
android:layout_height="@dimen/rear_display_animation_height"
android:layout_gravity="center"
- android:contentDescription="@null"
+ android:contentDescription="@string/rear_display_accessibility_folded_animation"
android:scaleType="fitXY"
app:lottie_rawRes="@raw/rear_display_folded"
app:lottie_autoPlay="true"
diff --git a/packages/SystemUI/res/layout/activity_rear_display_education_opened.xml b/packages/SystemUI/res/layout/activity_rear_display_education_opened.xml
index 20b93d9bc40d..6de06f76ebbf 100644
--- a/packages/SystemUI/res/layout/activity_rear_display_education_opened.xml
+++ b/packages/SystemUI/res/layout/activity_rear_display_education_opened.xml
@@ -34,7 +34,7 @@
android:layout_width="@dimen/rear_display_animation_width"
android:layout_height="@dimen/rear_display_animation_height"
android:layout_gravity="center"
- android:contentDescription="@null"
+ android:contentDescription="@string/rear_display_accessibility_unfolded_animation"
android:scaleType="fitXY"
app:lottie_rawRes="@raw/rear_display_turnaround"
app:lottie_autoPlay="true"
diff --git a/packages/SystemUI/res/layout/quick_settings_security_footer.xml b/packages/SystemUI/res/layout/quick_settings_security_footer.xml
deleted file mode 100644
index 194f3dd5dc26..000000000000
--- a/packages/SystemUI/res/layout/quick_settings_security_footer.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2014 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.
--->
-<!-- TODO(b/242040009): Remove this file. -->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_security_footer_single_line_height"
- android:layout_weight="1"
- android:clickable="true"
- android:orientation="horizontal"
- android:paddingHorizontal="@dimen/qs_footer_padding"
- android:gravity="center_vertical"
- android:layout_gravity="center_vertical|center_horizontal"
- android:layout_marginEnd="@dimen/qs_footer_action_inset"
- android:background="@drawable/qs_security_footer_background"
- >
-
- <ImageView
- android:id="@+id/primary_footer_icon"
- android:layout_width="@dimen/qs_footer_icon_size"
- android:layout_height="@dimen/qs_footer_icon_size"
- android:gravity="start"
- android:layout_marginEnd="12dp"
- android:contentDescription="@null"
- android:tint="?android:attr/textColorSecondary" />
-
- <TextView
- android:id="@+id/footer_text"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:singleLine="true"
- android:ellipsize="end"
- android:textAppearance="@style/TextAppearance.QS.SecurityFooter"
- android:textColor="?android:attr/textColorSecondary"/>
-
- <ImageView
- android:id="@+id/footer_icon"
- android:layout_width="@dimen/qs_footer_icon_size"
- android:layout_height="@dimen/qs_footer_icon_size"
- android:layout_marginStart="8dp"
- android:contentDescription="@null"
- android:src="@*android:drawable/ic_chevron_end"
- android:autoMirrored="true"
- android:tint="?android:attr/textColorSecondary" />
-
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml
index bafdb11ab211..4abc1769ab54 100644
--- a/packages/SystemUI/res/layout/super_notification_shade.xml
+++ b/packages/SystemUI/res/layout/super_notification_shade.xml
@@ -98,16 +98,18 @@
android:singleLine="true"
android:ellipsize="marquee"
android:focusable="true" />
- <FrameLayout android:id="@+id/keyguard_bouncer_container"
- android:layout_height="0dp"
- android:layout_width="match_parent"
- android:layout_weight="1"
- android:background="@android:color/transparent"
- android:visibility="invisible"
- android:clipChildren="false"
- android:clipToPadding="false" />
</LinearLayout>
+ <FrameLayout android:id="@+id/keyguard_bouncer_container"
+ android:paddingTop="@dimen/status_bar_height"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:layout_weight="1"
+ android:background="@android:color/transparent"
+ android:visibility="invisible"
+ android:clipChildren="false"
+ android:clipToPadding="false" />
+
<com.android.systemui.biometrics.AuthRippleView
android:id="@+id/auth_ripple"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index c5bd976395ea..084a0e0cb62d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2755,4 +2755,8 @@
<string name="rear_display_bottom_sheet_description">Use the rear-facing camera for a wider photo with higher resolution.</string>
<!-- Text for education page description to warn user that the display will turn off if the button is clicked. [CHAR_LIMIT=NONE] -->
<string name="rear_display_bottom_sheet_warning"><b>&#x2731; This screen will turn off</b></string>
+ <!-- Text for education page content description for folded animation. [CHAR_LIMIT=NONE] -->
+ <string name="rear_display_accessibility_folded_animation">Foldable device being unfolded</string>
+ <!-- Text for education page content description for unfolded animation. [CHAR_LIMIT=NONE] -->
+ <string name="rear_display_accessibility_unfolded_animation">Foldable device being flipped around</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/util/condition/CombinedCondition.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/CombinedCondition.kt
index da81d540f189..2d83458ec2f7 100644
--- a/packages/SystemUI/src/com/android/systemui/util/condition/CombinedCondition.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/CombinedCondition.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.util.condition
+package com.android.systemui.shared.condition
/**
* A higher order [Condition] which combines multiple conditions with a specified
diff --git a/packages/SystemUI/src/com/android/systemui/util/condition/Condition.java b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.java
index b39adefa238b..cc48090e1217 100644
--- a/packages/SystemUI/src/com/android/systemui/util/condition/Condition.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-package com.android.systemui.util.condition;
+package com.android.systemui.shared.condition;
import android.util.Log;
-import com.android.systemui.statusbar.policy.CallbackController;
-
-import org.jetbrains.annotations.NotNull;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleEventObserver;
+import androidx.lifecycle.LifecycleOwner;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -33,7 +34,7 @@ import java.util.List;
* Base class for a condition that needs to be fulfilled in order for {@link Monitor} to inform
* its callbacks.
*/
-public abstract class Condition implements CallbackController<Condition.Callback> {
+public abstract class Condition {
private final String mTag = getClass().getSimpleName();
private final ArrayList<WeakReference<Callback>> mCallbacks = new ArrayList<>();
@@ -79,8 +80,7 @@ public abstract class Condition implements CallbackController<Condition.Callback
* Registers a callback to receive updates once started. This should be called before
* {@link #start()}. Also triggers the callback immediately if already started.
*/
- @Override
- public void addCallback(@NotNull Callback callback) {
+ public void addCallback(@NonNull Callback callback) {
if (shouldLog()) Log.d(mTag, "adding callback");
mCallbacks.add(new WeakReference<>(callback));
@@ -96,8 +96,7 @@ public abstract class Condition implements CallbackController<Condition.Callback
/**
* Removes the provided callback from further receiving updates.
*/
- @Override
- public void removeCallback(@NotNull Callback callback) {
+ public void removeCallback(@NonNull Callback callback) {
if (shouldLog()) Log.d(mTag, "removing callback");
final Iterator<WeakReference<Callback>> iterator = mCallbacks.iterator();
while (iterator.hasNext()) {
@@ -116,6 +115,29 @@ public abstract class Condition implements CallbackController<Condition.Callback
}
/**
+ * Wrapper to {@link #addCallback(Callback)} when a lifecycle is in the resumed state
+ * and {@link #removeCallback(Callback)} when not resumed automatically.
+ */
+ public Callback observe(LifecycleOwner owner, Callback listener) {
+ return observe(owner.getLifecycle(), listener);
+ }
+
+ /**
+ * Wrapper to {@link #addCallback(Callback)} when a lifecycle is in the resumed state
+ * and {@link #removeCallback(Condition.Callback)} when not resumed automatically.
+ */
+ public Callback observe(Lifecycle lifecycle, Callback listener) {
+ lifecycle.addObserver((LifecycleEventObserver) (lifecycleOwner, event) -> {
+ if (event == Lifecycle.Event.ON_RESUME) {
+ addCallback(listener);
+ } else if (event == Lifecycle.Event.ON_PAUSE) {
+ removeCallback(listener);
+ }
+ });
+ return listener;
+ }
+
+ /**
* Updates the value for whether the condition has been fulfilled, and sends an update if the
* value changes and any callback is registered.
*
@@ -187,7 +209,7 @@ public abstract class Condition implements CallbackController<Condition.Callback
* Creates a new condition which will only be true when both this condition and all the provided
* conditions are true.
*/
- public Condition and(Collection<Condition> others) {
+ public Condition and(@NonNull Collection<Condition> others) {
final List<Condition> conditions = new ArrayList<>(others);
conditions.add(this);
return new CombinedCondition(conditions, Evaluator.OP_AND);
@@ -197,7 +219,7 @@ public abstract class Condition implements CallbackController<Condition.Callback
* Creates a new condition which will only be true when both this condition and the provided
* condition is true.
*/
- public Condition and(Condition other) {
+ public Condition and(@NonNull Condition other) {
return new CombinedCondition(Arrays.asList(this, other), Evaluator.OP_AND);
}
@@ -205,7 +227,7 @@ public abstract class Condition implements CallbackController<Condition.Callback
* Creates a new condition which will only be true when either this condition or any of the
* provided conditions are true.
*/
- public Condition or(Collection<Condition> others) {
+ public Condition or(@NonNull Collection<Condition> others) {
final List<Condition> conditions = new ArrayList<>(others);
conditions.add(this);
return new CombinedCondition(conditions, Evaluator.OP_OR);
@@ -215,7 +237,7 @@ public abstract class Condition implements CallbackController<Condition.Callback
* Creates a new condition which will only be true when either this condition or the provided
* condition is true.
*/
- public Condition or(Condition other) {
+ public Condition or(@NonNull Condition other) {
return new CombinedCondition(Arrays.asList(this, other), Evaluator.OP_OR);
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/condition/Evaluator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
index cf44e84a563f..23742c503ed3 100644
--- a/packages/SystemUI/src/com/android/systemui/util/condition/Evaluator.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
@@ -1,4 +1,20 @@
-package com.android.systemui.util.condition
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shared.condition
import android.annotation.IntDef
diff --git a/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Monitor.java
index 24bc9078475f..95675cef9136 100644
--- a/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Monitor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package com.android.systemui.util.condition;
+package com.android.systemui.shared.condition;
import android.util.ArraySet;
import android.util.Log;
-import com.android.systemui.dagger.qualifiers.Main;
+import androidx.annotation.NonNull;
-import org.jetbrains.annotations.NotNull;
+import com.android.systemui.dagger.qualifiers.Main;
import java.util.ArrayList;
import java.util.Collections;
@@ -100,7 +100,7 @@ public class Monitor {
* @param subscription A {@link Subscription} detailing the desired conditions and callback.
* @return A {@link Subscription.Token} that can be used to remove the subscription.
*/
- public Subscription.Token addSubscription(@NotNull Subscription subscription) {
+ public Subscription.Token addSubscription(@NonNull Subscription subscription) {
final Subscription.Token token = new Subscription.Token();
final SubscriptionState state = new SubscriptionState(subscription);
@@ -131,7 +131,7 @@ public class Monitor {
* @param token The {@link Subscription.Token} returned when the {@link Subscription} was
* originally added.
*/
- public void removeSubscription(@NotNull Subscription.Token token) {
+ public void removeSubscription(@NonNull Subscription.Token token) {
mExecutor.execute(() -> {
if (shouldLog()) Log.d(mTag, "removing subscription");
if (!mSubscriptions.containsKey(token)) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java
index c9ea79432360..5883b6c0e723 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java
@@ -87,8 +87,8 @@ public class PreviewPositionHelper {
taskPercent = mDesiredStagePosition != STAGE_POSITION_TOP_OR_LEFT
? mSplitBounds.topTaskPercent
: (1 - (mSplitBounds.topTaskPercent + mSplitBounds.dividerHeightPercent));
- // Scale portrait height to that of (actual screen - taskbar inset)
- fullscreenTaskHeight = (screenHeightPx) * taskPercent;
+ // Scale portrait height to that of the actual screen
+ fullscreenTaskHeight = screenHeightPx * taskPercent;
if (mTaskbarInApp) {
canvasScreenRatio = canvasHeight / fullscreenTaskHeight;
} else {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
index 860c8e3a9f77..7da27b1d6898 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
@@ -260,7 +260,8 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey
if (reason != PROMPT_REASON_NONE) {
int promtReasonStringRes = mView.getPromptReasonStringRes(reason);
if (promtReasonStringRes != 0) {
- mMessageAreaController.setMessage(promtReasonStringRes);
+ mMessageAreaController.setMessage(
+ mView.getResources().getString(promtReasonStringRes), false);
}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
index 2e9ad5868eba..53b569af29e1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
@@ -143,7 +143,9 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
public void startAppearAnimation() {
if (TextUtils.isEmpty(mMessageAreaController.getMessage())) {
- mMessageAreaController.setMessage(getInitialMessageResId());
+ mMessageAreaController.setMessage(
+ mView.getResources().getString(getInitialMessageResId()),
+ /* animate= */ false);
}
mView.startAppearAnimation();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
index 5d86ccd5409e..67e3400670ba 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
@@ -52,6 +52,7 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
private int mYTransOffset;
private View mBouncerMessageView;
@DevicePostureInt private int mLastDevicePosture = DEVICE_POSTURE_UNKNOWN;
+ public static final long ANIMATION_DURATION = 650;
public KeyguardPINView(Context context) {
this(context, null);
@@ -181,7 +182,7 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
if (mAppearAnimator.isRunning()) {
mAppearAnimator.cancel();
}
- mAppearAnimator.setDuration(650);
+ mAppearAnimator.setDuration(ANIMATION_DURATION);
mAppearAnimator.addUpdateListener(animation -> animate(animation.getAnimatedFraction()));
mAppearAnimator.start();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 8f3484a0c99b..5d7a6f122e69 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -36,8 +36,11 @@ import static com.android.systemui.plugins.FalsingManager.LOW_PENALTY;
import static java.lang.Integer.max;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.admin.DevicePolicyManager;
@@ -967,11 +970,23 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
}
mUserSwitcherViewGroup.setAlpha(0f);
- ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(mUserSwitcherViewGroup, View.ALPHA,
- 1f);
- alphaAnim.setInterpolator(Interpolators.ALPHA_IN);
- alphaAnim.setDuration(500);
- alphaAnim.start();
+ ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
+ int yTrans = mView.getResources().getDimensionPixelSize(R.dimen.pin_view_trans_y_entry);
+ animator.setInterpolator(Interpolators.STANDARD_DECELERATE);
+ animator.setDuration(650);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mUserSwitcherViewGroup.setAlpha(1f);
+ mUserSwitcherViewGroup.setTranslationY(0f);
+ }
+ });
+ animator.addUpdateListener(animation -> {
+ float value = (float) animation.getAnimatedValue();
+ mUserSwitcherViewGroup.setAlpha(value);
+ mUserSwitcherViewGroup.setTranslationY(yTrans - yTrans * value);
+ });
+ animator.start();
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index d1a59cc334ab..71d5bf57baf6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -398,6 +398,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private static final int HAL_ERROR_RETRY_MAX = 20;
@VisibleForTesting
+ protected static final int HAL_POWER_PRESS_TIMEOUT = 50; // ms
+
+ @VisibleForTesting
protected final Runnable mFpCancelNotReceived = this::onFingerprintCancelNotReceived;
private final Runnable mFaceCancelNotReceived = this::onFaceCancelNotReceived;
@@ -918,7 +921,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
}
- private final Runnable mRetryFingerprintAuthentication = new Runnable() {
+ private final Runnable mRetryFingerprintAuthenticationAfterHwUnavailable = new Runnable() {
@SuppressLint("MissingPermission")
@Override
public void run() {
@@ -927,7 +930,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
} else if (mHardwareFingerprintUnavailableRetryCount < HAL_ERROR_RETRY_MAX) {
mHardwareFingerprintUnavailableRetryCount++;
- mHandler.postDelayed(mRetryFingerprintAuthentication, HAL_ERROR_RETRY_TIMEOUT);
+ mHandler.postDelayed(mRetryFingerprintAuthenticationAfterHwUnavailable,
+ HAL_ERROR_RETRY_TIMEOUT);
}
}
};
@@ -957,12 +961,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
if (msgId == FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE) {
mLogger.logRetryAfterFpErrorWithDelay(msgId, errString, HAL_ERROR_RETRY_TIMEOUT);
- mHandler.postDelayed(mRetryFingerprintAuthentication, HAL_ERROR_RETRY_TIMEOUT);
+ mHandler.postDelayed(mRetryFingerprintAuthenticationAfterHwUnavailable,
+ HAL_ERROR_RETRY_TIMEOUT);
}
if (msgId == FingerprintManager.BIOMETRIC_ERROR_POWER_PRESSED) {
- mLogger.logRetryAfterFpErrorWithDelay(msgId, errString, 0);
- updateFingerprintListeningState(BIOMETRIC_ACTION_START);
+ mLogger.logRetryAfterFpErrorWithDelay(msgId, errString, HAL_POWER_PRESS_TIMEOUT);
+ mHandler.postDelayed(() -> {
+ mLogger.d("Retrying fingerprint listening after power pressed error.");
+ updateFingerprintListeningState(BIOMETRIC_ACTION_START);
+ }, HAL_POWER_PRESS_TIMEOUT);
}
boolean lockedOutStateChanged = false;
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
index b66ae286171a..ceebe4c69091 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
@@ -231,7 +231,7 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
int2 = delay
str1 = "$errString"
}, {
- "Fingerprint retrying auth after $int2 ms due to($int1) -> $str1"
+ "Fingerprint scheduling retry auth after $int2 ms due to($int1) -> $str1"
})
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 5a81bd3e01b6..419cf1faf1fd 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -96,6 +96,7 @@ import java.util.Set;
import java.util.concurrent.Executor;
import javax.inject.Inject;
+import javax.inject.Provider;
import kotlin.Unit;
@@ -714,7 +715,7 @@ public class UdfpsController implements DozeReceiver, Dumpable {
@NonNull SystemUIDialogManager dialogManager,
@NonNull LatencyTracker latencyTracker,
@NonNull ActivityLaunchAnimator activityLaunchAnimator,
- @NonNull Optional<AlternateUdfpsTouchProvider> alternateTouchProvider,
+ @NonNull Optional<Provider<AlternateUdfpsTouchProvider>> alternateTouchProvider,
@NonNull @BiometricsBackground Executor biometricsExecutor,
@NonNull PrimaryBouncerInteractor primaryBouncerInteractor,
@NonNull SinglePointerTouchProcessor singlePointerTouchProcessor) {
@@ -746,7 +747,7 @@ public class UdfpsController implements DozeReceiver, Dumpable {
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
mLatencyTracker = latencyTracker;
mActivityLaunchAnimator = activityLaunchAnimator;
- mAlternateTouchProvider = alternateTouchProvider.orElse(null);
+ mAlternateTouchProvider = alternateTouchProvider.map(Provider::get).orElse(null);
mSensorProps = new FingerprintSensorPropertiesInternal(
-1 /* sensorId */,
SensorProperties.STRENGTH_CONVENIENCE,
diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
index 77d0496e43db..27466d4f58bc 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
@@ -19,7 +19,7 @@ package com.android.systemui.controls.dagger
import android.content.Context
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
-import com.android.systemui.controls.ControlsSettingsRepository
+import com.android.systemui.controls.settings.ControlsSettingsRepository
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.controls.controller.ControlsTileResourceConfiguration
import com.android.systemui.controls.controller.ControlsTileResourceConfigurationImpl
diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
index 9ae605e30a83..6d6410de1a91 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
@@ -20,8 +20,8 @@ import android.app.Activity
import android.content.pm.PackageManager
import com.android.systemui.controls.ControlsMetricsLogger
import com.android.systemui.controls.ControlsMetricsLoggerImpl
-import com.android.systemui.controls.ControlsSettingsRepository
-import com.android.systemui.controls.ControlsSettingsRepositoryImpl
+import com.android.systemui.controls.settings.ControlsSettingsRepository
+import com.android.systemui.controls.settings.ControlsSettingsRepositoryImpl
import com.android.systemui.controls.controller.ControlsBindingController
import com.android.systemui.controls.controller.ControlsBindingControllerImpl
import com.android.systemui.controls.controller.ControlsController
@@ -34,6 +34,8 @@ import com.android.systemui.controls.management.ControlsListingController
import com.android.systemui.controls.management.ControlsListingControllerImpl
import com.android.systemui.controls.management.ControlsProviderSelectorActivity
import com.android.systemui.controls.management.ControlsRequestDialog
+import com.android.systemui.controls.settings.ControlsSettingsDialogManager
+import com.android.systemui.controls.settings.ControlsSettingsDialogManagerImpl
import com.android.systemui.controls.ui.ControlActionCoordinator
import com.android.systemui.controls.ui.ControlActionCoordinatorImpl
import com.android.systemui.controls.ui.ControlsActivity
@@ -90,6 +92,11 @@ abstract class ControlsModule {
): ControlsSettingsRepository
@Binds
+ abstract fun provideDialogManager(
+ manager: ControlsSettingsDialogManagerImpl
+ ): ControlsSettingsDialogManager
+
+ @Binds
abstract fun provideMetricsLogger(logger: ControlsMetricsLoggerImpl): ControlsMetricsLogger
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt b/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt
new file mode 100644
index 000000000000..bb2e2d701aa0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.controls.settings
+
+import android.app.AlertDialog
+import android.content.Context
+import android.content.Context.MODE_PRIVATE
+import android.content.DialogInterface
+import android.content.SharedPreferences
+import android.provider.Settings
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.R
+import com.android.systemui.controls.settings.ControlsSettingsDialogManager.Companion.MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG
+import com.android.systemui.controls.settings.ControlsSettingsDialogManager.Companion.PREFS_SETTINGS_DIALOG_ATTEMPTS
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.settings.UserFileManager
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl
+import com.android.systemui.util.settings.SecureSettings
+import javax.inject.Inject
+
+/**
+ * Manager to display a dialog to prompt user to enable controls related Settings:
+ *
+ * * [Settings.Secure.LOCKSCREEN_SHOW_CONTROLS]
+ * * [Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS]
+ */
+interface ControlsSettingsDialogManager {
+
+ /**
+ * Shows the corresponding dialog. In order for a dialog to appear, the following must be true
+ *
+ * * At least one of the Settings in [ControlsSettingsRepository] are `false`.
+ * * The dialog has not been seen by the user too many times (as defined by
+ * [MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG]).
+ *
+ * When the dialogs are shown, the following outcomes are possible:
+ * * User cancels the dialog by clicking outside or going back: we register that the dialog was
+ * seen but the settings don't change.
+ * * User responds negatively to the dialog: we register that the user doesn't want to change
+ * the settings (dialog will not appear again) and the settings don't change.
+ * * User responds positively to the dialog: the settings are set to `true` and the dialog will
+ * not appear again.
+ * * SystemUI closes the dialogs (for example, the activity showing it is closed). In this case,
+ * we don't modify anything.
+ *
+ * Of those four scenarios, only the first three will cause [onAttemptCompleted] to be called.
+ * It will also be called if the dialogs are not shown.
+ */
+ fun maybeShowDialog(activityContext: Context, onAttemptCompleted: () -> Unit)
+
+ /**
+ * Closes the dialog without registering anything from the user. The state of the settings after
+ * this is called will be the same as before the dialogs were shown.
+ */
+ fun closeDialog()
+
+ companion object {
+ @VisibleForTesting internal const val MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG = 2
+ @VisibleForTesting
+ internal const val PREFS_SETTINGS_DIALOG_ATTEMPTS = "show_settings_attempts"
+ }
+}
+
+@SysUISingleton
+class ControlsSettingsDialogManagerImpl
+@VisibleForTesting
+internal constructor(
+ private val secureSettings: SecureSettings,
+ private val userFileManager: UserFileManager,
+ private val controlsSettingsRepository: ControlsSettingsRepository,
+ private val userTracker: UserTracker,
+ private val activityStarter: ActivityStarter,
+ private val dialogProvider: (context: Context, theme: Int) -> AlertDialog
+) : ControlsSettingsDialogManager {
+
+ @Inject
+ constructor(
+ secureSettings: SecureSettings,
+ userFileManager: UserFileManager,
+ controlsSettingsRepository: ControlsSettingsRepository,
+ userTracker: UserTracker,
+ activityStarter: ActivityStarter
+ ) : this(
+ secureSettings,
+ userFileManager,
+ controlsSettingsRepository,
+ userTracker,
+ activityStarter,
+ { context, theme -> SettingsDialog(context, theme) }
+ )
+
+ private var dialog: AlertDialog? = null
+ private set
+
+ private val showDeviceControlsInLockscreen: Boolean
+ get() = controlsSettingsRepository.canShowControlsInLockscreen.value
+
+ private val allowTrivialControls: Boolean
+ get() = controlsSettingsRepository.allowActionOnTrivialControlsInLockscreen.value
+
+ override fun maybeShowDialog(activityContext: Context, onAttemptCompleted: () -> Unit) {
+ closeDialog()
+
+ val prefs =
+ userFileManager.getSharedPreferences(
+ DeviceControlsControllerImpl.PREFS_CONTROLS_FILE,
+ MODE_PRIVATE,
+ userTracker.userId
+ )
+ val attempts = prefs.getInt(PREFS_SETTINGS_DIALOG_ATTEMPTS, 0)
+ if (
+ attempts >= MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG ||
+ (showDeviceControlsInLockscreen && allowTrivialControls)
+ ) {
+ onAttemptCompleted()
+ return
+ }
+
+ val listener = DialogListener(prefs, attempts, onAttemptCompleted)
+ val d =
+ dialogProvider(activityContext, R.style.Theme_SystemUI_Dialog).apply {
+ setIcon(R.drawable.ic_warning)
+ setOnCancelListener(listener)
+ setNeutralButton(R.string.controls_settings_dialog_neutral_button, listener)
+ setPositiveButton(R.string.controls_settings_dialog_positive_button, listener)
+ if (showDeviceControlsInLockscreen) {
+ setTitle(R.string.controls_settings_trivial_controls_dialog_title)
+ setMessage(R.string.controls_settings_trivial_controls_dialog_message)
+ } else {
+ setTitle(R.string.controls_settings_show_controls_dialog_title)
+ setMessage(R.string.controls_settings_show_controls_dialog_message)
+ }
+ }
+
+ SystemUIDialog.registerDismissListener(d) { dialog = null }
+ SystemUIDialog.setDialogSize(d)
+ SystemUIDialog.setShowForAllUsers(d, true)
+ dialog = d
+ d.show()
+ }
+
+ private fun turnOnSettingSecurely(settings: List<String>) {
+ val action =
+ ActivityStarter.OnDismissAction {
+ settings.forEach { setting ->
+ secureSettings.putIntForUser(setting, 1, userTracker.userId)
+ }
+ true
+ }
+ activityStarter.dismissKeyguardThenExecute(
+ action,
+ /* cancel */ null,
+ /* afterKeyguardGone */ true
+ )
+ }
+
+ override fun closeDialog() {
+ dialog?.dismiss()
+ }
+
+ private inner class DialogListener(
+ private val prefs: SharedPreferences,
+ private val attempts: Int,
+ private val onComplete: () -> Unit
+ ) : DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
+ override fun onClick(dialog: DialogInterface?, which: Int) {
+ if (dialog == null) return
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ val settings = mutableListOf(Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS)
+ if (!showDeviceControlsInLockscreen) {
+ settings.add(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS)
+ }
+ turnOnSettingSecurely(settings)
+ }
+ if (attempts != MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG) {
+ prefs
+ .edit()
+ .putInt(PREFS_SETTINGS_DIALOG_ATTEMPTS, MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG)
+ .apply()
+ }
+ onComplete()
+ }
+
+ override fun onCancel(dialog: DialogInterface?) {
+ if (dialog == null) return
+ if (attempts < MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG) {
+ prefs.edit().putInt(PREFS_SETTINGS_DIALOG_ATTEMPTS, attempts + 1).apply()
+ }
+ onComplete()
+ }
+ }
+
+ private fun AlertDialog.setNeutralButton(
+ msgId: Int,
+ listener: DialogInterface.OnClickListener
+ ) {
+ setButton(DialogInterface.BUTTON_NEUTRAL, context.getText(msgId), listener)
+ }
+
+ private fun AlertDialog.setPositiveButton(
+ msgId: Int,
+ listener: DialogInterface.OnClickListener
+ ) {
+ setButton(DialogInterface.BUTTON_POSITIVE, context.getText(msgId), listener)
+ }
+
+ private fun AlertDialog.setMessage(msgId: Int) {
+ setMessage(context.getText(msgId))
+ }
+
+ /** This is necessary because the constructors are `protected`. */
+ private class SettingsDialog(context: Context, theme: Int) : AlertDialog(context, theme)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ControlsSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsRepository.kt
index 3d10ab906f2f..df2831c6eb96 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ControlsSettingsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsRepository.kt
@@ -15,7 +15,7 @@
*
*/
-package com.android.systemui.controls
+package com.android.systemui.controls.settings
import kotlinx.coroutines.flow.StateFlow
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ControlsSettingsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsRepositoryImpl.kt
index 9dc422a09674..8e3b5109339c 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ControlsSettingsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsRepositoryImpl.kt
@@ -15,7 +15,7 @@
*
*/
-package com.android.systemui.controls
+package com.android.systemui.controls.settings
import android.provider.Settings
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
index 8472ca0731d7..99a10a33ab0f 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
@@ -18,15 +18,13 @@ package com.android.systemui.controls.ui
import android.annotation.AnyThread
import android.annotation.MainThread
-import android.app.AlertDialog
+import android.app.Activity
import android.app.Dialog
import android.app.PendingIntent
import android.content.Context
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
-import android.os.UserHandle
import android.os.VibrationEffect
-import android.provider.Settings.Secure
import android.service.controls.Control
import android.service.controls.actions.BooleanAction
import android.service.controls.actions.CommandAction
@@ -34,39 +32,36 @@ import android.service.controls.actions.FloatAction
import android.util.Log
import android.view.HapticFeedbackConstants
import com.android.internal.annotations.VisibleForTesting
-import com.android.systemui.R
import com.android.systemui.broadcast.BroadcastSender
import com.android.systemui.controls.ControlsMetricsLogger
-import com.android.systemui.controls.ControlsSettingsRepository
+import com.android.systemui.controls.settings.ControlsSettingsDialogManager
+import com.android.systemui.controls.settings.ControlsSettingsRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.settings.UserContextProvider
import com.android.systemui.statusbar.VibratorHelper
-import com.android.systemui.statusbar.phone.SystemUIDialog
-import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl.Companion.PREFS_CONTROLS_FILE
-import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl.Companion.PREFS_SETTINGS_DIALOG_ATTEMPTS
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.concurrency.DelayableExecutor
-import com.android.systemui.util.settings.SecureSettings
import com.android.wm.shell.TaskViewFactory
import java.util.Optional
import javax.inject.Inject
@SysUISingleton
class ControlActionCoordinatorImpl @Inject constructor(
- private val context: Context,
- private val bgExecutor: DelayableExecutor,
- @Main private val uiExecutor: DelayableExecutor,
- private val activityStarter: ActivityStarter,
- private val broadcastSender: BroadcastSender,
- private val keyguardStateController: KeyguardStateController,
- private val taskViewFactory: Optional<TaskViewFactory>,
- private val controlsMetricsLogger: ControlsMetricsLogger,
- private val vibrator: VibratorHelper,
- private val secureSettings: SecureSettings,
- private val userContextProvider: UserContextProvider,
- private val controlsSettingsRepository: ControlsSettingsRepository,
+ private val context: Context,
+ private val bgExecutor: DelayableExecutor,
+ @Main private val uiExecutor: DelayableExecutor,
+ private val activityStarter: ActivityStarter,
+ private val broadcastSender: BroadcastSender,
+ private val keyguardStateController: KeyguardStateController,
+ private val taskViewFactory: Optional<TaskViewFactory>,
+ private val controlsMetricsLogger: ControlsMetricsLogger,
+ private val vibrator: VibratorHelper,
+ private val controlsSettingsRepository: ControlsSettingsRepository,
+ private val controlsSettingsDialogManager: ControlsSettingsDialogManager,
+ private val featureFlags: FeatureFlags,
) : ControlActionCoordinator {
private var dialog: Dialog? = null
private var pendingAction: Action? = null
@@ -75,18 +70,26 @@ class ControlActionCoordinatorImpl @Inject constructor(
get() = !keyguardStateController.isUnlocked()
private val allowTrivialControls: Boolean
get() = controlsSettingsRepository.allowActionOnTrivialControlsInLockscreen.value
- private val showDeviceControlsInLockscreen: Boolean
- get() = controlsSettingsRepository.canShowControlsInLockscreen.value
override lateinit var activityContext: Context
companion object {
private const val RESPONSE_TIMEOUT_IN_MILLIS = 3000L
- private const val MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG = 2
}
override fun closeDialogs() {
- dialog?.dismiss()
- dialog = null
+ if (!featureFlags.isEnabled(Flags.USE_APP_PANELS)) {
+ controlsSettingsDialogManager.closeDialog()
+ }
+ val isActivityFinishing =
+ (activityContext as? Activity)?.let { it.isFinishing || it.isDestroyed }
+ if (isActivityFinishing == true) {
+ dialog = null
+ return
+ }
+ if (dialog?.isShowing == true) {
+ dialog?.dismiss()
+ dialog = null
+ }
}
override fun toggle(cvh: ControlViewHolder, templateId: String, isChecked: Boolean) {
@@ -244,71 +247,9 @@ class ControlActionCoordinatorImpl @Inject constructor(
if (action.authIsRequired) {
return
}
- val prefs = userContextProvider.userContext.getSharedPreferences(
- PREFS_CONTROLS_FILE, Context.MODE_PRIVATE)
- val attempts = prefs.getInt(PREFS_SETTINGS_DIALOG_ATTEMPTS, 0)
- if (attempts >= MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG ||
- (showDeviceControlsInLockscreen && allowTrivialControls)) {
- return
- }
- val builder = AlertDialog
- .Builder(activityContext, R.style.Theme_SystemUI_Dialog)
- .setIcon(R.drawable.ic_warning)
- .setOnCancelListener {
- if (attempts < MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG) {
- prefs.edit().putInt(PREFS_SETTINGS_DIALOG_ATTEMPTS, attempts + 1)
- .commit()
- }
- true
- }
- .setNeutralButton(R.string.controls_settings_dialog_neutral_button) { _, _ ->
- if (attempts != MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG) {
- prefs.edit().putInt(PREFS_SETTINGS_DIALOG_ATTEMPTS,
- MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG)
- .commit()
- }
- true
- }
-
- if (showDeviceControlsInLockscreen) {
- dialog = builder
- .setTitle(R.string.controls_settings_trivial_controls_dialog_title)
- .setMessage(R.string.controls_settings_trivial_controls_dialog_message)
- .setPositiveButton(R.string.controls_settings_dialog_positive_button) { _, _ ->
- if (attempts != MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG) {
- prefs.edit().putInt(PREFS_SETTINGS_DIALOG_ATTEMPTS,
- MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG)
- .commit()
- }
- secureSettings.putIntForUser(Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS, 1,
- UserHandle.USER_CURRENT)
- true
- }
- .create()
- } else {
- dialog = builder
- .setTitle(R.string.controls_settings_show_controls_dialog_title)
- .setMessage(R.string.controls_settings_show_controls_dialog_message)
- .setPositiveButton(R.string.controls_settings_dialog_positive_button) { _, _ ->
- if (attempts != MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG) {
- prefs.edit().putInt(PREFS_SETTINGS_DIALOG_ATTEMPTS,
- MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG)
- .commit()
- }
- secureSettings.putIntForUser(Secure.LOCKSCREEN_SHOW_CONTROLS,
- 1, UserHandle.USER_CURRENT)
- secureSettings.putIntForUser(Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS,
- 1, UserHandle.USER_CURRENT)
- true
- }
- .create()
+ if (!featureFlags.isEnabled(Flags.USE_APP_PANELS)) {
+ controlsSettingsDialogManager.maybeShowDialog(activityContext) {}
}
-
- SystemUIDialog.registerDismissListener(dialog)
- SystemUIDialog.setDialogSize(dialog)
-
- dialog?.create()
- dialog?.show()
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
index bd704c1ff086..5d611c4c8212 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
@@ -32,8 +32,10 @@ import androidx.activity.ComponentActivity
import com.android.systemui.R
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.controls.management.ControlsAnimations
+import com.android.systemui.controls.settings.ControlsSettingsDialogManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.statusbar.policy.KeyguardStateController
import javax.inject.Inject
/**
@@ -47,7 +49,9 @@ class ControlsActivity @Inject constructor(
private val uiController: ControlsUiController,
private val broadcastDispatcher: BroadcastDispatcher,
private val dreamManager: IDreamManager,
- private val featureFlags: FeatureFlags
+ private val featureFlags: FeatureFlags,
+ private val controlsSettingsDialogManager: ControlsSettingsDialogManager,
+ private val keyguardStateController: KeyguardStateController
) : ComponentActivity() {
private lateinit var parent: ViewGroup
@@ -92,7 +96,13 @@ class ControlsActivity @Inject constructor(
parent = requireViewById<ViewGroup>(R.id.global_actions_controls)
parent.alpha = 0f
- uiController.show(parent, { finishOrReturnToDream() }, this)
+ if (featureFlags.isEnabled(Flags.USE_APP_PANELS) && !keyguardStateController.isUnlocked) {
+ controlsSettingsDialogManager.maybeShowDialog(this) {
+ uiController.show(parent, { finishOrReturnToDream() }, this)
+ }
+ } else {
+ uiController.show(parent, { finishOrReturnToDream() }, this)
+ }
ControlsAnimations.enterAnimation(parent).start()
}
@@ -124,6 +134,7 @@ class ControlsActivity @Inject constructor(
mExitToDream = false
uiController.hide()
+ controlsSettingsDialogManager.closeDialog()
}
override fun onDestroy() {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index a07c716bc8f9..fb678aa420bf 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -49,7 +49,7 @@ import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.controls.ControlsMetricsLogger
import com.android.systemui.controls.ControlsServiceInfo
-import com.android.systemui.controls.ControlsSettingsRepository
+import com.android.systemui.controls.settings.ControlsSettingsRepository
import com.android.systemui.controls.CustomIconCache
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.controls.controller.StructureInfo
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index c322b129b908..ad6106b48328 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -71,6 +71,9 @@ object Flags {
val NOTIFICATION_MEMORY_MONITOR_ENABLED =
releasedFlag(112, "notification_memory_monitor_enabled")
+ val NOTIFICATION_MEMORY_LOGGING_ENABLED =
+ unreleasedFlag(119, "notification_memory_logging_enabled", teamfood = true)
+
// TODO(b/254512731): Tracking Bug
@JvmField
val NOTIFICATION_DISMISSAL_FADE =
@@ -91,6 +94,7 @@ object Flags {
unreleasedFlag(259217907, "notification_group_dismissal_animation", teamfood = true)
// TODO(b/257506350): Tracking Bug
+ @JvmField
val FSI_CHROME = unreleasedFlag(117, "fsi_chrome")
@JvmField
@@ -98,7 +102,7 @@ object Flags {
unreleasedFlag(259395680, "simplified_appear_fraction", teamfood = true)
// TODO(b/257315550): Tracking Bug
- val NO_HUN_FOR_OLD_WHEN = unreleasedFlag(118, "no_hun_for_old_when")
+ val NO_HUN_FOR_OLD_WHEN = unreleasedFlag(118, "no_hun_for_old_when", teamfood = true)
val FILTER_UNSEEN_NOTIFS_ON_KEYGUARD =
unreleasedFlag(254647461, "filter_unseen_notifs_on_keyguard", teamfood = true)
@@ -134,7 +138,8 @@ object Flags {
* Whether the clock on a wide lock screen should use the new "stepping" animation for moving
* the digits when the clock moves.
*/
- @JvmField val STEP_CLOCK_ANIMATION = unreleasedFlag(212, "step_clock_animation")
+ @JvmField
+ val STEP_CLOCK_ANIMATION = unreleasedFlag(212, "step_clock_animation", teamfood = true)
/**
* Migration from the legacy isDozing/dozeAmount paths to the new KeyguardTransitionRepository
@@ -204,9 +209,6 @@ object Flags {
"full_screen_user_switcher"
)
- // TODO(b/254512678): Tracking Bug
- @JvmField val NEW_FOOTER_ACTIONS = releasedFlag(507, "new_footer_actions")
-
// TODO(b/244064524): Tracking Bug
@JvmField
val QS_SECONDARY_DATA_SUB_INFO =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 6ed555056cb1..306e92e6c96c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -2214,6 +2214,9 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
case START_KEYGUARD_EXIT_ANIM:
Trace.beginSection(
"KeyguardViewMediator#handleMessage START_KEYGUARD_EXIT_ANIM");
+ synchronized (KeyguardViewMediator.this) {
+ mHiding = true;
+ }
StartKeyguardExitAnimParams params = (StartKeyguardExitAnimParams) msg.obj;
mNotificationShadeWindowControllerLazy.get().batchApplyWindowLayoutParams(
() -> {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
index 3c1077867582..930de1302c58 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
@@ -122,10 +122,6 @@ interface FgsManagerController {
/** Remove a [OnDialogDismissedListener]. */
fun removeOnDialogDismissedListener(listener: OnDialogDismissedListener)
- /** Whether we should update the footer visibility. */
- // TODO(b/242040009): Remove this.
- fun shouldUpdateFooterVisibility(): Boolean
-
@VisibleForTesting
fun visibleButtonsCount(): Int
@@ -375,8 +371,6 @@ class FgsManagerControllerImpl @Inject constructor(
}
}
- override fun shouldUpdateFooterVisibility() = dialog == null
-
override fun showDialog(expandable: Expandable?) {
synchronized(lock) {
if (dialog == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
index a9943e886339..b52233fc748b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,261 +16,17 @@
package com.android.systemui.qs
-import android.content.Intent
-import android.content.res.Configuration
-import android.os.Handler
-import android.os.UserManager
-import android.provider.Settings
-import android.provider.Settings.Global.USER_SWITCHER_ENABLED
-import android.view.View
-import android.view.ViewGroup
-import androidx.annotation.VisibleForTesting
-import com.android.internal.jank.InteractionJankMonitor
-import com.android.internal.logging.MetricsLogger
-import com.android.internal.logging.UiEventLogger
-import com.android.internal.logging.nano.MetricsProto
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.R
-import com.android.systemui.animation.ActivityLaunchAnimator
-import com.android.systemui.animation.Expandable
-import com.android.systemui.globalactions.GlobalActionsDialogLite
-import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.plugins.FalsingManager
-import com.android.systemui.qs.dagger.QSFlagsModule.PM_LITE_ENABLED
-import com.android.systemui.qs.dagger.QSScope
-import com.android.systemui.settings.UserTracker
-import com.android.systemui.statusbar.phone.MultiUserSwitchController
-import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.statusbar.policy.DeviceProvisionedController
-import com.android.systemui.statusbar.policy.UserInfoController
-import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener
-import com.android.systemui.util.LargeScreenUtils
-import com.android.systemui.util.ViewController
-import com.android.systemui.util.settings.GlobalSettings
+import com.android.systemui.dagger.SysUISingleton
import javax.inject.Inject
-import javax.inject.Named
-import javax.inject.Provider
-/**
- * Manages [FooterActionsView] behaviour, both when it's placed in QS or QQS (split shade).
- * Main difference between QS and QQS behaviour is condition when buttons should be visible,
- * determined by [buttonsVisibleState]
- */
-@QSScope
-// TODO(b/242040009): Remove this file.
-internal class FooterActionsController @Inject constructor(
- view: FooterActionsView,
- multiUserSwitchControllerFactory: MultiUserSwitchController.Factory,
- private val activityStarter: ActivityStarter,
- private val userManager: UserManager,
- private val userTracker: UserTracker,
- private val userInfoController: UserInfoController,
- private val deviceProvisionedController: DeviceProvisionedController,
- private val securityFooterController: QSSecurityFooter,
- private val fgsManagerFooterController: QSFgsManagerFooter,
- private val falsingManager: FalsingManager,
- private val metricsLogger: MetricsLogger,
- private val globalActionsDialogProvider: Provider<GlobalActionsDialogLite>,
- private val uiEventLogger: UiEventLogger,
- @Named(PM_LITE_ENABLED) private val showPMLiteButton: Boolean,
- private val globalSetting: GlobalSettings,
- private val handler: Handler,
- private val configurationController: ConfigurationController,
-) : ViewController<FooterActionsView>(view) {
-
- private var globalActionsDialog: GlobalActionsDialogLite? = null
-
- private var lastExpansion = -1f
- private var listening: Boolean = false
- private var inSplitShade = false
-
- private val singleShadeAnimator by lazy {
- // In single shade, the actions footer should only appear at the end of the expansion,
- // so that it doesn't overlap with the notifications panel.
- TouchAnimator.Builder().addFloat(mView, "alpha", 0f, 1f).setStartDelay(0.9f).build()
- }
-
- private val splitShadeAnimator by lazy {
- // The Actions footer view has its own background which is the same color as the qs panel's
- // background.
- // We don't want it to fade in at the same time as the rest of the panel, otherwise it is
- // more opaque than the rest of the panel's background. Only applies to split shade.
- val alphaAnimator = TouchAnimator.Builder().addFloat(mView, "alpha", 0f, 1f).build()
- val bgAlphaAnimator =
- TouchAnimator.Builder()
- .addFloat(mView, "backgroundAlpha", 0f, 1f)
- .setStartDelay(0.9f)
- .build()
- // In split shade, we want the actions footer to fade in exactly at the same time as the
- // rest of the shade, as there is no overlap.
- TouchAnimator.Builder()
- .addFloat(alphaAnimator, "position", 0f, 1f)
- .addFloat(bgAlphaAnimator, "position", 0f, 1f)
- .build()
- }
-
- private val animators: TouchAnimator
- get() = if (inSplitShade) splitShadeAnimator else singleShadeAnimator
-
- var visible = true
- set(value) {
- field = value
- updateVisibility()
- }
-
- private val settingsButtonContainer: View = view.findViewById(R.id.settings_button_container)
- private val securityFootersContainer: ViewGroup? =
- view.findViewById(R.id.security_footers_container)
- private val powerMenuLite: View = view.findViewById(R.id.pm_lite)
- private val multiUserSwitchController = multiUserSwitchControllerFactory.create(view)
-
- @VisibleForTesting
- internal val securityFootersSeparator = View(context).apply { visibility = View.GONE }
-
- private val onUserInfoChangedListener = OnUserInfoChangedListener { _, picture, _ ->
- val isGuestUser: Boolean = userManager.isGuestUser(KeyguardUpdateMonitor.getCurrentUser())
- mView.onUserInfoChanged(picture, isGuestUser)
- }
-
- private val multiUserSetting =
- object : SettingObserver(
- globalSetting, handler, USER_SWITCHER_ENABLED, userTracker.userId) {
- override fun handleValueChanged(value: Int, observedChange: Boolean) {
- if (observedChange) {
- updateView()
- }
- }
- }
-
- private val onClickListener = View.OnClickListener { v ->
- // Don't do anything if the tap looks suspicious.
- if (!visible || falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
- return@OnClickListener
- }
- if (v === settingsButtonContainer) {
- if (!deviceProvisionedController.isCurrentUserSetup) {
- // If user isn't setup just unlock the device and dump them back at SUW.
- activityStarter.postQSRunnableDismissingKeyguard {}
- return@OnClickListener
- }
- metricsLogger.action(MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH)
- startSettingsActivity()
- } else if (v === powerMenuLite) {
- uiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS)
- globalActionsDialog?.showOrHideDialog(false, true, Expandable.fromView(powerMenuLite))
- }
- }
-
- private val configurationListener =
- object : ConfigurationController.ConfigurationListener {
- override fun onConfigChanged(newConfig: Configuration?) {
- updateResources()
- }
- }
-
- private fun updateResources() {
- inSplitShade = LargeScreenUtils.shouldUseSplitNotificationShade(resources)
- }
-
- override fun onInit() {
- multiUserSwitchController.init()
- securityFooterController.init()
- fgsManagerFooterController.init()
- }
-
- private fun updateVisibility() {
- val previousVisibility = mView.visibility
- mView.visibility = if (visible) View.VISIBLE else View.INVISIBLE
- if (previousVisibility != mView.visibility) updateView()
- }
-
- private fun startSettingsActivity() {
- val animationController = settingsButtonContainer?.let {
- ActivityLaunchAnimator.Controller.fromView(
- it,
- InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON)
- }
- activityStarter.startActivity(Intent(Settings.ACTION_SETTINGS),
- true /* dismissShade */, animationController)
- }
-
- @VisibleForTesting
- public override fun onViewAttached() {
- globalActionsDialog = globalActionsDialogProvider.get()
- if (showPMLiteButton) {
- powerMenuLite.visibility = View.VISIBLE
- powerMenuLite.setOnClickListener(onClickListener)
- } else {
- powerMenuLite.visibility = View.GONE
- }
- settingsButtonContainer.setOnClickListener(onClickListener)
- multiUserSetting.isListening = true
-
- val securityFooter = securityFooterController.view
- securityFootersContainer?.addView(securityFooter)
- val separatorWidth = resources.getDimensionPixelSize(R.dimen.qs_footer_action_inset)
- securityFootersContainer?.addView(securityFootersSeparator, separatorWidth, 1)
-
- val fgsFooter = fgsManagerFooterController.view
- securityFootersContainer?.addView(fgsFooter)
-
- val visibilityListener =
- VisibilityChangedDispatcher.OnVisibilityChangedListener { visibility ->
- if (securityFooter.visibility == View.VISIBLE &&
- fgsFooter.visibility == View.VISIBLE) {
- securityFootersSeparator.visibility = View.VISIBLE
- } else {
- securityFootersSeparator.visibility = View.GONE
- }
- fgsManagerFooterController
- .setCollapsed(securityFooter.visibility == View.VISIBLE)
- }
- securityFooterController.setOnVisibilityChangedListener(visibilityListener)
- fgsManagerFooterController.setOnVisibilityChangedListener(visibilityListener)
-
- configurationController.addCallback(configurationListener)
-
- updateResources()
- updateView()
- }
-
- private fun updateView() {
- mView.updateEverything(multiUserSwitchController.isMultiUserEnabled)
- }
-
- override fun onViewDetached() {
- globalActionsDialog?.destroy()
- globalActionsDialog = null
- setListening(false)
- multiUserSetting.isListening = false
- configurationController.removeCallback(configurationListener)
- }
-
- fun setListening(listening: Boolean) {
- if (this.listening == listening) {
- return
- }
- this.listening = listening
- if (this.listening) {
- userInfoController.addCallback(onUserInfoChangedListener)
- updateView()
- } else {
- userInfoController.removeCallback(onUserInfoChangedListener)
- }
-
- fgsManagerFooterController.setListening(listening)
- securityFooterController.setListening(listening)
- }
-
- fun disable(state2: Int) {
- mView.disable(state2, multiUserSwitchController.isMultiUserEnabled)
- }
-
- fun setExpansion(headerExpansionFraction: Float) {
- animators.setPosition(headerExpansionFraction)
- }
-
- fun setKeyguardShowing(showing: Boolean) {
- setExpansion(lastExpansion)
+/** Controller for the footer actions. This manages the initialization of its dependencies. */
+@SysUISingleton
+class FooterActionsController
+@Inject
+constructor(
+ private val fgsManagerController: FgsManagerController,
+) {
+ fun init() {
+ fgsManagerController.init()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt
deleted file mode 100644
index d602b0b27977..000000000000
--- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2021 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.qs
-
-import android.app.StatusBarManager
-import android.content.Context
-import android.graphics.PorterDuff
-import android.graphics.drawable.Drawable
-import android.graphics.drawable.RippleDrawable
-import android.os.UserManager
-import android.util.AttributeSet
-import android.util.Log
-import android.view.MotionEvent
-import android.view.View
-import android.widget.ImageView
-import android.widget.LinearLayout
-import androidx.annotation.Keep
-import com.android.settingslib.Utils
-import com.android.settingslib.drawable.UserIconDrawable
-import com.android.systemui.R
-import com.android.systemui.statusbar.phone.MultiUserSwitch
-
-/**
- * Quick Settings bottom buttons placed in footer (aka utility bar) - always visible in expanded QS,
- * in split shade mode visible also in collapsed state. May contain up to 5 buttons: settings,
- * edit tiles, power off and conditionally: user switch and tuner
- */
-// TODO(b/242040009): Remove this file.
-class FooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs) {
- private lateinit var settingsContainer: View
- private lateinit var multiUserSwitch: MultiUserSwitch
- private lateinit var multiUserAvatar: ImageView
-
- private var qsDisabled = false
- private var expansionAmount = 0f
-
- /**
- * Sets the alpha of the background of this view.
- *
- * Used from a [TouchAnimator] in the controller.
- */
- var backgroundAlpha: Float = 1f
- @Keep
- set(value) {
- field = value
- background?.alpha = (value * 255).toInt()
- }
- @Keep get
-
- override fun onFinishInflate() {
- super.onFinishInflate()
- settingsContainer = findViewById(R.id.settings_button_container)
- multiUserSwitch = findViewById(R.id.multi_user_switch)
- multiUserAvatar = multiUserSwitch.findViewById(R.id.multi_user_avatar)
-
- // RenderThread is doing more harm than good when touching the header (to expand quick
- // settings), so disable it for this view
- if (settingsContainer.background is RippleDrawable) {
- (settingsContainer.background as RippleDrawable).setForceSoftware(true)
- }
- importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES
- }
-
- fun disable(
- state2: Int,
- multiUserEnabled: Boolean
- ) {
- val disabled = state2 and StatusBarManager.DISABLE2_QUICK_SETTINGS != 0
- if (disabled == qsDisabled) return
- qsDisabled = disabled
- updateEverything(multiUserEnabled)
- }
-
- fun updateEverything(
- multiUserEnabled: Boolean
- ) {
- post {
- updateVisibilities(multiUserEnabled)
- updateClickabilities()
- isClickable = false
- }
- }
-
- private fun updateClickabilities() {
- multiUserSwitch.isClickable = multiUserSwitch.visibility == VISIBLE
- settingsContainer.isClickable = settingsContainer.visibility == VISIBLE
- }
-
- private fun updateVisibilities(
- multiUserEnabled: Boolean
- ) {
- settingsContainer.visibility = if (qsDisabled) GONE else VISIBLE
- multiUserSwitch.visibility = if (multiUserEnabled) VISIBLE else GONE
- val isDemo = UserManager.isDeviceInDemoMode(context)
- settingsContainer.visibility = if (isDemo) INVISIBLE else VISIBLE
- }
-
- fun onUserInfoChanged(picture: Drawable?, isGuestUser: Boolean) {
- var pictureToSet = picture
- if (picture != null && isGuestUser && picture !is UserIconDrawable) {
- pictureToSet = picture.constantState.newDrawable(resources).mutate()
- pictureToSet.setColorFilter(
- Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorForeground),
- PorterDuff.Mode.SRC_IN)
- }
- multiUserAvatar.setImageDrawable(pictureToSet)
- }
-
- override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
- if (VERBOSE) Log.d(TAG, "FooterActionsView onInterceptTouchEvent ${ev?.string}")
- return super.onInterceptTouchEvent(ev)
- }
-
- override fun onTouchEvent(event: MotionEvent?): Boolean {
- if (VERBOSE) Log.d(TAG, "FooterActionsView onTouchEvent ${event?.string}")
- return super.onTouchEvent(event)
- }
-}
-private const val TAG = "FooterActionsView"
-private val VERBOSE = Log.isLoggable(TAG, Log.VERBOSE)
-private val MotionEvent.string
- get() = "($id): ($x,$y)"
diff --git a/packages/SystemUI/src/com/android/systemui/qs/NewFooterActionsController.kt b/packages/SystemUI/src/com/android/systemui/qs/NewFooterActionsController.kt
deleted file mode 100644
index 7c67d9f42b55..000000000000
--- a/packages/SystemUI/src/com/android/systemui/qs/NewFooterActionsController.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs
-
-import com.android.systemui.dagger.SysUISingleton
-import javax.inject.Inject
-
-/** Controller for the footer actions. This manages the initialization of its dependencies. */
-@SysUISingleton
-class NewFooterActionsController
-@Inject
-// TODO(b/242040009): Rename this to FooterActionsController.
-constructor(
- private val fgsManagerController: FgsManagerController,
-) {
- fun init() {
- fgsManagerController.init()
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index dc9dcc295e6e..0c242d9da25f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -215,7 +215,7 @@ public class QSContainerImpl extends FrameLayout implements Dumpable {
// Some views are always full width or have dependent padding
continue;
}
- if (!(view instanceof FooterActionsView)) {
+ if (view.getId() != R.id.qs_footer_actions) {
// Only padding for FooterActionsView, no margin. That way, the background goes
// all the way to the edge.
LayoutParams lp = (LayoutParams) view.getLayoutParams();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFgsManagerFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFgsManagerFooter.java
deleted file mode 100644
index b1b9dd721eaf..000000000000
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFgsManagerFooter.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs;
-
-import static com.android.systemui.qs.dagger.QSFragmentModule.QS_FGS_MANAGER_FOOTER_VIEW;
-import static com.android.systemui.util.PluralMessageFormaterKt.icuMessageFormat;
-
-import android.content.Context;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import androidx.annotation.Nullable;
-
-import com.android.systemui.R;
-import com.android.systemui.animation.Expandable;
-import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.qs.dagger.QSScope;
-
-import java.util.concurrent.Executor;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-
-/**
- * Footer entry point for the foreground service manager
- */
-// TODO(b/242040009): Remove this file.
-@QSScope
-public class QSFgsManagerFooter implements View.OnClickListener,
- FgsManagerController.OnDialogDismissedListener,
- FgsManagerController.OnNumberOfPackagesChangedListener,
- VisibilityChangedDispatcher {
-
- private final View mRootView;
- private final TextView mFooterText;
- private final Context mContext;
- private final Executor mMainExecutor;
- private final Executor mExecutor;
-
- private final FgsManagerController mFgsManagerController;
-
- private boolean mIsInitialized = false;
- private int mNumPackages;
-
- private final View mTextContainer;
- private final View mNumberContainer;
- private final TextView mNumberView;
- private final ImageView mDotView;
- private final ImageView mCollapsedDotView;
-
- @Nullable
- private VisibilityChangedDispatcher.OnVisibilityChangedListener mVisibilityChangedListener;
-
- @Inject
- QSFgsManagerFooter(@Named(QS_FGS_MANAGER_FOOTER_VIEW) View rootView,
- @Main Executor mainExecutor, @Background Executor executor,
- FgsManagerController fgsManagerController) {
- mRootView = rootView;
- mFooterText = mRootView.findViewById(R.id.footer_text);
- mTextContainer = mRootView.findViewById(R.id.fgs_text_container);
- mNumberContainer = mRootView.findViewById(R.id.fgs_number_container);
- mNumberView = mRootView.findViewById(R.id.fgs_number);
- mDotView = mRootView.findViewById(R.id.fgs_new);
- mCollapsedDotView = mRootView.findViewById(R.id.fgs_collapsed_new);
- mContext = rootView.getContext();
- mMainExecutor = mainExecutor;
- mExecutor = executor;
- mFgsManagerController = fgsManagerController;
- }
-
- /**
- * Whether to show the footer in collapsed mode (just a number) or not (text).
- * @param collapsed
- */
- public void setCollapsed(boolean collapsed) {
- mTextContainer.setVisibility(collapsed ? View.GONE : View.VISIBLE);
- mNumberContainer.setVisibility(collapsed ? View.VISIBLE : View.GONE);
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mRootView.getLayoutParams();
- lp.width = collapsed ? ViewGroup.LayoutParams.WRAP_CONTENT : 0;
- lp.weight = collapsed ? 0f : 1f;
- mRootView.setLayoutParams(lp);
- }
-
- public void init() {
- if (mIsInitialized) {
- return;
- }
-
- mFgsManagerController.init();
-
- mRootView.setOnClickListener(this);
-
- mIsInitialized = true;
- }
-
- public void setListening(boolean listening) {
- if (listening) {
- mFgsManagerController.addOnDialogDismissedListener(this);
- mFgsManagerController.addOnNumberOfPackagesChangedListener(this);
- mNumPackages = mFgsManagerController.getNumRunningPackages();
- refreshState();
- } else {
- mFgsManagerController.removeOnDialogDismissedListener(this);
- mFgsManagerController.removeOnNumberOfPackagesChangedListener(this);
- }
- }
-
- @Override
- public void setOnVisibilityChangedListener(
- @Nullable OnVisibilityChangedListener onVisibilityChangedListener) {
- mVisibilityChangedListener = onVisibilityChangedListener;
- }
-
- @Override
- public void onClick(View view) {
- mFgsManagerController.showDialog(Expandable.fromView(view));
- }
-
- public void refreshState() {
- mExecutor.execute(this::handleRefreshState);
- }
-
- public View getView() {
- return mRootView;
- }
-
- public void handleRefreshState() {
- mMainExecutor.execute(() -> {
- CharSequence text = icuMessageFormat(mContext.getResources(),
- R.string.fgs_manager_footer_label, mNumPackages);
- mFooterText.setText(text);
- mNumberView.setText(Integer.toString(mNumPackages));
- mNumberView.setContentDescription(text);
- if (mFgsManagerController.shouldUpdateFooterVisibility()) {
- mRootView.setVisibility(mNumPackages > 0
- && mFgsManagerController.isAvailable().getValue() ? View.VISIBLE
- : View.GONE);
- int dotVis = mFgsManagerController.getShowFooterDot().getValue()
- && mFgsManagerController.getNewChangesSinceDialogWasDismissed()
- ? View.VISIBLE : View.GONE;
- mDotView.setVisibility(dotVis);
- mCollapsedDotView.setVisibility(dotVis);
- if (mVisibilityChangedListener != null) {
- mVisibilityChangedListener.onVisibilityChanged(mRootView.getVisibility());
- }
- }
- });
- }
-
- @Override
- public void onDialogDismissed() {
- refreshState();
- }
-
- @Override
- public void onNumberOfPackagesChanged(int numPackages) {
- mNumPackages = numPackages;
- refreshState();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 71ab457659fe..f8fb4e89111e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -33,6 +33,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.widget.LinearLayout;
import androidx.annotation.FloatRange;
import androidx.annotation.Nullable;
@@ -48,7 +49,6 @@ import com.android.systemui.animation.Interpolators;
import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.media.controls.ui.MediaHost;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
@@ -114,7 +114,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
private final QSFragmentDisableFlagsLogger mQsFragmentDisableFlagsLogger;
private final QSTileHost mHost;
private final FeatureFlags mFeatureFlags;
- private final NewFooterActionsController mNewFooterActionsController;
+ private final FooterActionsController mFooterActionsController;
private final FooterActionsViewModel.Factory mFooterActionsViewModelFactory;
private final ListeningAndVisibilityLifecycleOwner mListeningAndVisibilityLifecycleOwner;
private boolean mShowCollapsedOnKeyguard;
@@ -132,9 +132,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
private QSPanelController mQSPanelController;
private QuickQSPanelController mQuickQSPanelController;
private QSCustomizerController mQSCustomizerController;
- @Nullable
- private FooterActionsController mQSFooterActionController;
- @Nullable
private FooterActionsViewModel mQSFooterActionsViewModel;
@Nullable
private ScrollListener mScrollListener;
@@ -185,7 +182,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
QSFragmentComponent.Factory qsComponentFactory,
QSFragmentDisableFlagsLogger qsFragmentDisableFlagsLogger,
FalsingManager falsingManager, DumpManager dumpManager, FeatureFlags featureFlags,
- NewFooterActionsController newFooterActionsController,
+ FooterActionsController footerActionsController,
FooterActionsViewModel.Factory footerActionsViewModelFactory) {
mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
mQsMediaHost = qsMediaHost;
@@ -199,7 +196,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
mStatusBarStateController = statusBarStateController;
mDumpManager = dumpManager;
mFeatureFlags = featureFlags;
- mNewFooterActionsController = newFooterActionsController;
+ mFooterActionsController = footerActionsController;
mFooterActionsViewModelFactory = footerActionsViewModelFactory;
mListeningAndVisibilityLifecycleOwner = new ListeningAndVisibilityLifecycleOwner();
}
@@ -226,18 +223,12 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
mQSPanelController.init();
mQuickQSPanelController.init();
- if (mFeatureFlags.isEnabled(Flags.NEW_FOOTER_ACTIONS)) {
- mQSFooterActionsViewModel = mFooterActionsViewModelFactory.create(/* lifecycleOwner */
- this);
- FooterActionsView footerActionsView = view.findViewById(R.id.qs_footer_actions);
- FooterActionsViewBinder.bind(footerActionsView, mQSFooterActionsViewModel,
- mListeningAndVisibilityLifecycleOwner);
-
- mNewFooterActionsController.init();
- } else {
- mQSFooterActionController = qsFragmentComponent.getQSFooterActionController();
- mQSFooterActionController.init();
- }
+ mQSFooterActionsViewModel = mFooterActionsViewModelFactory.create(/* lifecycleOwner */
+ this);
+ LinearLayout footerActionsView = view.findViewById(R.id.qs_footer_actions);
+ FooterActionsViewBinder.bind(footerActionsView, mQSFooterActionsViewModel,
+ mListeningAndVisibilityLifecycleOwner);
+ mFooterActionsController.init();
mQSPanelScrollView = view.findViewById(R.id.expanded_qs_scroll_view);
mQSPanelScrollView.addOnLayoutChangeListener(
@@ -436,9 +427,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
mContainer.disable(state1, state2, animate);
mHeader.disable(state1, state2, animate);
mFooter.disable(state1, state2, animate);
- if (mQSFooterActionController != null) {
- mQSFooterActionController.disable(state2);
- }
updateQsState();
}
@@ -457,11 +445,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
boolean footerVisible = qsPanelVisible && (mQsExpanded || !keyguardShowing
|| mHeaderAnimating || mShowCollapsedOnKeyguard);
mFooter.setVisibility(footerVisible ? View.VISIBLE : View.INVISIBLE);
- if (mQSFooterActionController != null) {
- mQSFooterActionController.setVisible(footerVisible);
- } else {
- mQSFooterActionsViewModel.onVisibilityChangeRequested(footerVisible);
- }
+ mQSFooterActionsViewModel.onVisibilityChangeRequested(footerVisible);
mFooter.setExpanded((keyguardShowing && !mHeaderAnimating && !mShowCollapsedOnKeyguard)
|| (mQsExpanded && !mStackScrollerOverscrolling));
mQSPanelController.setVisibility(qsPanelVisible ? View.VISIBLE : View.INVISIBLE);
@@ -534,9 +518,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
}
mFooter.setKeyguardShowing(keyguardShowing);
- if (mQSFooterActionController != null) {
- mQSFooterActionController.setKeyguardShowing(keyguardShowing);
- }
updateQsState();
}
@@ -552,9 +533,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
if (DEBUG) Log.d(TAG, "setListening " + listening);
mListening = listening;
mQSContainerImplController.setListening(listening && mQsVisible);
- if (mQSFooterActionController != null) {
- mQSFooterActionController.setListening(listening && mQsVisible);
- }
mListeningAndVisibilityLifecycleOwner.updateState();
updateQsPanelControllerListening();
}
@@ -665,12 +643,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
mFooter.setExpansion(onKeyguardAndExpanded ? 1 : expansion);
float footerActionsExpansion =
onKeyguardAndExpanded ? 1 : mInSplitShade ? alphaProgress : expansion;
- if (mQSFooterActionController != null) {
- mQSFooterActionController.setExpansion(footerActionsExpansion);
- } else {
- mQSFooterActionsViewModel.onQuickSettingsExpansionChanged(footerActionsExpansion,
- mInSplitShade);
- }
+ mQSFooterActionsViewModel.onQuickSettingsExpansionChanged(footerActionsExpansion,
+ mInSplitShade);
mQSPanelController.setRevealExpansion(expansion);
mQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation);
mQuickQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation);
@@ -835,11 +809,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
boolean customizing = isCustomizing();
mQSPanelScrollView.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE);
mFooter.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE);
- if (mQSFooterActionController != null) {
- mQSFooterActionController.setVisible(!customizing);
- } else {
- mQSFooterActionsViewModel.onVisibilityChangeRequested(!customizing);
- }
+ mQSFooterActionsViewModel.onVisibilityChangeRequested(!customizing);
mHeader.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE);
// Let the panel know the position changed and it needs to update where notifications
// and whatnot are.
@@ -927,6 +897,11 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
updateShowCollapsedOnKeyguard();
}
+ @VisibleForTesting
+ public ListeningAndVisibilityLifecycleOwner getListeningAndVisibilityLifecycleOwner() {
+ return mListeningAndVisibilityLifecycleOwner;
+ }
+
@Override
public void dump(PrintWriter pw, String[] args) {
IndentingPrintWriter indentingPw = new IndentingPrintWriter(pw, /* singleIndent= */ " ");
@@ -994,7 +969,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
* - STARTED when mListening == true && mQsVisible == false.
* - RESUMED when mListening == true && mQsVisible == true.
*/
- private class ListeningAndVisibilityLifecycleOwner implements LifecycleOwner {
+ @VisibleForTesting
+ class ListeningAndVisibilityLifecycleOwner implements LifecycleOwner {
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
private boolean mDestroyed = false;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
deleted file mode 100644
index 6c1e95645550..000000000000
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright (C) 2014 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.qs;
-
-import static com.android.systemui.qs.dagger.QSFragmentModule.QS_SECURITY_FOOTER_VIEW;
-
-import android.app.admin.DevicePolicyEventLogger;
-import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Resources;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.UserHandle;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import androidx.annotation.Nullable;
-
-import com.android.internal.util.FrameworkStatsLog;
-import com.android.systemui.FontSizeUtils;
-import com.android.systemui.R;
-import com.android.systemui.animation.Expandable;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.common.shared.model.Icon;
-import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.qs.dagger.QSScope;
-import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig;
-import com.android.systemui.security.data.model.SecurityModel;
-import com.android.systemui.statusbar.policy.SecurityController;
-import com.android.systemui.util.ViewController;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-
-/** ViewController for the footer actions. */
-// TODO(b/242040009): Remove this class.
-@QSScope
-public class QSSecurityFooter extends ViewController<View>
- implements OnClickListener, VisibilityChangedDispatcher {
- protected static final String TAG = "QSSecurityFooter";
-
- private final TextView mFooterText;
- private final ImageView mPrimaryFooterIcon;
- private Context mContext;
- private final Callback mCallback = new Callback();
- private final SecurityController mSecurityController;
- private final Handler mMainHandler;
- private final BroadcastDispatcher mBroadcastDispatcher;
- private final QSSecurityFooterUtils mQSSecurityFooterUtils;
-
- protected H mHandler;
-
- private boolean mIsVisible;
- private boolean mIsClickable;
- @Nullable
- private CharSequence mFooterTextContent = null;
- private Icon mFooterIcon;
-
- @Nullable
- private VisibilityChangedDispatcher.OnVisibilityChangedListener mVisibilityChangedListener;
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(
- DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG)) {
- showDeviceMonitoringDialog();
- }
- }
- };
-
- @Inject
- QSSecurityFooter(@Named(QS_SECURITY_FOOTER_VIEW) View rootView,
- @Main Handler mainHandler, SecurityController securityController,
- @Background Looper bgLooper, BroadcastDispatcher broadcastDispatcher,
- QSSecurityFooterUtils qSSecurityFooterUtils) {
- super(rootView);
- mFooterText = mView.findViewById(R.id.footer_text);
- mPrimaryFooterIcon = mView.findViewById(R.id.primary_footer_icon);
- mFooterIcon = new Icon.Resource(
- R.drawable.ic_info_outline, /* contentDescription= */ null);
- mContext = rootView.getContext();
- mSecurityController = securityController;
- mMainHandler = mainHandler;
- mHandler = new H(bgLooper);
- mBroadcastDispatcher = broadcastDispatcher;
- mQSSecurityFooterUtils = qSSecurityFooterUtils;
- }
-
- @Override
- protected void onViewAttached() {
- // Use background handler, as it's the same thread that handleClick is called on.
- mBroadcastDispatcher.registerReceiverWithHandler(mReceiver,
- new IntentFilter(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG),
- mHandler, UserHandle.ALL);
- mView.setOnClickListener(this);
- }
-
- @Override
- protected void onViewDetached() {
- mBroadcastDispatcher.unregisterReceiver(mReceiver);
- mView.setOnClickListener(null);
- }
-
- public void setListening(boolean listening) {
- if (listening) {
- mSecurityController.addCallback(mCallback);
- refreshState();
- } else {
- mSecurityController.removeCallback(mCallback);
- }
- }
-
- @Override
- public void setOnVisibilityChangedListener(
- @Nullable OnVisibilityChangedListener onVisibilityChangedListener) {
- mVisibilityChangedListener = onVisibilityChangedListener;
- }
-
- public void onConfigurationChanged() {
- FontSizeUtils.updateFontSize(mFooterText, R.dimen.qs_tile_text_size);
- Resources r = mContext.getResources();
-
- int padding = r.getDimensionPixelSize(R.dimen.qs_footer_padding);
- mView.setPaddingRelative(padding, 0, padding, 0);
- mView.setBackground(mContext.getDrawable(R.drawable.qs_security_footer_background));
- }
-
- public View getView() {
- return mView;
- }
-
- public boolean hasFooter() {
- return mView.getVisibility() != View.GONE;
- }
-
- @Override
- public void onClick(View v) {
- if (!hasFooter()) return;
- mHandler.sendEmptyMessage(H.CLICK);
- }
-
- private void handleClick() {
- showDeviceMonitoringDialog();
- DevicePolicyEventLogger
- .createEvent(FrameworkStatsLog.DEVICE_POLICY_EVENT__EVENT_ID__DO_USER_INFO_CLICKED)
- .write();
- }
-
- // TODO(b/242040009): Remove this.
- public void showDeviceMonitoringDialog() {
- mQSSecurityFooterUtils.showDeviceMonitoringDialog(mContext, Expandable.fromView(mView));
- }
-
- public void refreshState() {
- mHandler.sendEmptyMessage(H.REFRESH_STATE);
- }
-
- private void handleRefreshState() {
- SecurityModel securityModel = SecurityModel.create(mSecurityController);
- SecurityButtonConfig buttonConfig = mQSSecurityFooterUtils.getButtonConfig(securityModel);
-
- if (buttonConfig == null) {
- mIsVisible = false;
- } else {
- mIsVisible = true;
- mIsClickable = buttonConfig.isClickable();
- mFooterTextContent = buttonConfig.getText();
- mFooterIcon = buttonConfig.getIcon();
- }
-
- // Update the UI.
- mMainHandler.post(mUpdatePrimaryIcon);
- mMainHandler.post(mUpdateDisplayState);
- }
-
- private final Runnable mUpdatePrimaryIcon = new Runnable() {
- @Override
- public void run() {
- if (mFooterIcon instanceof Icon.Loaded) {
- mPrimaryFooterIcon.setImageDrawable(((Icon.Loaded) mFooterIcon).getDrawable());
- } else if (mFooterIcon instanceof Icon.Resource) {
- mPrimaryFooterIcon.setImageResource(((Icon.Resource) mFooterIcon).getRes());
- }
- }
- };
-
- private final Runnable mUpdateDisplayState = new Runnable() {
- @Override
- public void run() {
- if (mFooterTextContent != null) {
- mFooterText.setText(mFooterTextContent);
- }
- mView.setVisibility(mIsVisible ? View.VISIBLE : View.GONE);
- if (mVisibilityChangedListener != null) {
- mVisibilityChangedListener.onVisibilityChanged(mView.getVisibility());
- }
-
- if (mIsVisible && mIsClickable) {
- mView.setClickable(true);
- mView.findViewById(R.id.footer_icon).setVisibility(View.VISIBLE);
- } else {
- mView.setClickable(false);
- mView.findViewById(R.id.footer_icon).setVisibility(View.GONE);
- }
- }
- };
-
- private class Callback implements SecurityController.SecurityControllerCallback {
- @Override
- public void onStateChanged() {
- refreshState();
- }
- }
-
- private class H extends Handler {
- private static final int CLICK = 0;
- private static final int REFRESH_STATE = 1;
-
- private H(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- String name = null;
- try {
- if (msg.what == REFRESH_STATE) {
- name = "handleRefreshState";
- handleRefreshState();
- } else if (msg.what == CLICK) {
- name = "handleClick";
- handleClick();
- }
- } catch (Throwable t) {
- final String error = "Error in " + name;
- Log.w(TAG, error, t);
- }
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
index aa505fb0b6bd..01eb636f75d6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
@@ -28,7 +28,6 @@ import com.android.systemui.battery.BatteryMeterView;
import com.android.systemui.dagger.qualifiers.RootView;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.privacy.OngoingPrivacyChip;
-import com.android.systemui.qs.FooterActionsView;
import com.android.systemui.qs.QSContainerImpl;
import com.android.systemui.qs.QSFooter;
import com.android.systemui.qs.QSFooterView;
@@ -51,8 +50,6 @@ import dagger.Provides;
*/
@Module
public interface QSFragmentModule {
- String QS_FGS_MANAGER_FOOTER_VIEW = "qs_fgs_manager_footer";
- String QS_SECURITY_FOOTER_VIEW = "qs_security_footer";
String QS_USING_MEDIA_PLAYER = "qs_using_media_player";
String QS_USING_COLLAPSED_LANDSCAPE_MEDIA = "qs_using_collapsed_landscape_media";
@@ -119,16 +116,6 @@ public interface QSFragmentModule {
return view.findViewById(R.id.qs_footer);
}
- /**
- * Provides a {@link FooterActionsView}.
- *
- * This will replace a ViewStub either in {@link QSFooterView} or in {@link QSContainerImpl}.
- */
- @Provides
- static FooterActionsView providesQSFooterActionsView(@RootView View view) {
- return view.findViewById(R.id.qs_footer_actions);
- }
-
/** */
@Provides
@QSScope
@@ -146,18 +133,6 @@ public interface QSFragmentModule {
/** */
@Provides
- @QSScope
- @Named(QS_SECURITY_FOOTER_VIEW)
- static View providesQSSecurityFooterView(
- @QSThemedContext LayoutInflater layoutInflater,
- FooterActionsView footerActionsView
- ) {
- return layoutInflater.inflate(R.layout.quick_settings_security_footer, footerActionsView,
- false);
- }
-
- /** */
- @Provides
@Named(QS_USING_MEDIA_PLAYER)
static boolean providesQSUsingMediaPlayer(Context context) {
return useQsMediaPlayer(context);
@@ -183,15 +158,4 @@ public interface QSFragmentModule {
static StatusIconContainer providesStatusIconContainer(QuickStatusBarHeader qsHeader) {
return qsHeader.findViewById(R.id.statusIcons);
}
-
- /** */
- @Provides
- @QSScope
- @Named(QS_FGS_MANAGER_FOOTER_VIEW)
- static View providesQSFgsManagerFooterView(
- @QSThemedContext LayoutInflater layoutInflater,
- FooterActionsView footerActionsView
- ) {
- return layoutInflater.inflate(R.layout.fgs_footer, footerActionsView, false);
- }
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt
index 3e39c8ee62f1..6db3c9941b78 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt
@@ -35,35 +35,31 @@ import com.android.systemui.animation.Expandable
import com.android.systemui.common.ui.binder.IconViewBinder
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.people.ui.view.PeopleViewBinder.bind
-import com.android.systemui.qs.FooterActionsView
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsButtonViewModel
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsForegroundServicesButtonViewModel
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsSecurityButtonViewModel
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
+import kotlin.math.roundToInt
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
/** A ViewBinder for [FooterActionsViewBinder]. */
object FooterActionsViewBinder {
- /**
- * Create a [FooterActionsView] that can later be [bound][bind] to a [FooterActionsViewModel].
- */
+ /** Create a view that can later be [bound][bind] to a [FooterActionsViewModel]. */
@JvmStatic
- fun create(context: Context): FooterActionsView {
+ fun create(context: Context): LinearLayout {
return LayoutInflater.from(context).inflate(R.layout.footer_actions, /* root= */ null)
- as FooterActionsView
+ as LinearLayout
}
/** Bind [view] to [viewModel]. */
@JvmStatic
fun bind(
- view: FooterActionsView,
+ view: LinearLayout,
viewModel: FooterActionsViewModel,
qsVisibilityLifecycleOwner: LifecycleOwner,
) {
- // Remove all children of the FooterActionsView that are used by the old implementation.
- // TODO(b/242040009): Clean up the XML once the old implementation is removed.
- view.removeAllViews()
+ view.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES
// Add the views used by this new implementation.
val context = view.context
@@ -117,7 +113,11 @@ object FooterActionsViewBinder {
}
launch { viewModel.alpha.collect { view.alpha = it } }
- launch { viewModel.backgroundAlpha.collect { view.backgroundAlpha = it } }
+ launch {
+ viewModel.backgroundAlpha.collect {
+ view.background?.alpha = (it * 255).roundToInt()
+ }
+ }
}
// Listen for model changes only when QS are visible.
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
index fae938d542f1..9c7718d0e001 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
@@ -881,6 +881,13 @@ public class ScreenshotView extends FrameLayout implements
}
void addQuickShareChip(Notification.Action quickShareAction) {
+ if (mQuickShareChip != null) {
+ mSmartChips.remove(mQuickShareChip);
+ mActionsView.removeView(mQuickShareChip);
+ }
+ if (mPendingInteraction == PendingInteraction.QUICK_SHARE) {
+ mPendingInteraction = null;
+ }
if (mPendingInteraction == null) {
LayoutInflater inflater = LayoutInflater.from(mContext);
mQuickShareChip = (OverlayActionChip) inflater.inflate(
diff --git a/packages/SystemUI/src/com/android/systemui/security/data/model/SecurityModel.kt b/packages/SystemUI/src/com/android/systemui/security/data/model/SecurityModel.kt
index 50af260684f8..1cf5a8fe5f97 100644
--- a/packages/SystemUI/src/com/android/systemui/security/data/model/SecurityModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/security/data/model/SecurityModel.kt
@@ -17,6 +17,7 @@
package com.android.systemui.security.data.model
import android.graphics.drawable.Drawable
+import androidx.annotation.VisibleForTesting
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.statusbar.policy.SecurityController
import kotlinx.coroutines.CoroutineDispatcher
@@ -55,8 +56,8 @@ data class SecurityModel(
* Important: This method should be called from a background thread as this will do a lot of
* binder calls.
*/
- // TODO(b/242040009): Remove this.
@JvmStatic
+ @VisibleForTesting
fun create(securityController: SecurityController): SecurityModel {
val deviceAdminInfo =
if (securityController.isParentalControlsEnabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java
deleted file mode 100644
index 5e2a7c8ca540..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.phone;
-
-import static com.android.systemui.DejankUtils.whitelistIpcs;
-
-import android.content.Intent;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.systemui.R;
-import com.android.systemui.animation.ActivityLaunchAnimator;
-import com.android.systemui.animation.Expandable;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.qs.FooterActionsView;
-import com.android.systemui.qs.dagger.QSScope;
-import com.android.systemui.qs.user.UserSwitchDialogController;
-import com.android.systemui.statusbar.policy.BaseUserSwitcherAdapter;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.user.UserSwitcherActivity;
-import com.android.systemui.util.ViewController;
-
-import javax.inject.Inject;
-
-/** View Controller for {@link MultiUserSwitch}. */
-// TODO(b/242040009): Remove this file.
-public class MultiUserSwitchController extends ViewController<MultiUserSwitch> {
- private final UserManager mUserManager;
- private final UserSwitcherController mUserSwitcherController;
- private final FalsingManager mFalsingManager;
- private final UserSwitchDialogController mUserSwitchDialogController;
- private final ActivityStarter mActivityStarter;
- private final FeatureFlags mFeatureFlags;
-
- private BaseUserSwitcherAdapter mUserListener;
-
- private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
- return;
- }
-
- if (mFeatureFlags.isEnabled(Flags.FULL_SCREEN_USER_SWITCHER)) {
- Intent intent = new Intent(v.getContext(), UserSwitcherActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
-
- mActivityStarter.startActivity(intent, true /* dismissShade */,
- ActivityLaunchAnimator.Controller.fromView(v, null),
- true /* showOverlockscreenwhenlocked */, UserHandle.SYSTEM);
- } else {
- mUserSwitchDialogController.showDialog(v.getContext(), Expandable.fromView(v));
- }
- }
- };
-
- @QSScope
- public static class Factory {
- private final UserManager mUserManager;
- private final UserSwitcherController mUserSwitcherController;
- private final FalsingManager mFalsingManager;
- private final UserSwitchDialogController mUserSwitchDialogController;
- private final ActivityStarter mActivityStarter;
- private final FeatureFlags mFeatureFlags;
-
- @Inject
- public Factory(UserManager userManager, UserSwitcherController userSwitcherController,
- FalsingManager falsingManager,
- UserSwitchDialogController userSwitchDialogController, FeatureFlags featureFlags,
- ActivityStarter activityStarter) {
- mUserManager = userManager;
- mUserSwitcherController = userSwitcherController;
- mFalsingManager = falsingManager;
- mUserSwitchDialogController = userSwitchDialogController;
- mActivityStarter = activityStarter;
- mFeatureFlags = featureFlags;
- }
-
- public MultiUserSwitchController create(FooterActionsView view) {
- return new MultiUserSwitchController(view.findViewById(R.id.multi_user_switch),
- mUserManager, mUserSwitcherController,
- mFalsingManager, mUserSwitchDialogController, mFeatureFlags,
- mActivityStarter);
- }
- }
-
- private MultiUserSwitchController(MultiUserSwitch view, UserManager userManager,
- UserSwitcherController userSwitcherController,
- FalsingManager falsingManager, UserSwitchDialogController userSwitchDialogController,
- FeatureFlags featureFlags, ActivityStarter activityStarter) {
- super(view);
- mUserManager = userManager;
- mUserSwitcherController = userSwitcherController;
- mFalsingManager = falsingManager;
- mUserSwitchDialogController = userSwitchDialogController;
- mFeatureFlags = featureFlags;
- mActivityStarter = activityStarter;
- }
-
- @Override
- protected void onInit() {
- registerListener();
- mView.refreshContentDescription(getCurrentUser());
- }
-
- @Override
- protected void onViewAttached() {
- mView.setOnClickListener(mOnClickListener);
- }
-
- @Override
- protected void onViewDetached() {
- mView.setOnClickListener(null);
- }
-
- private void registerListener() {
- if (mUserManager.isUserSwitcherEnabled() && mUserListener == null) {
-
- final UserSwitcherController controller = mUserSwitcherController;
- if (controller != null) {
- mUserListener = new BaseUserSwitcherAdapter(controller) {
- @Override
- public void notifyDataSetChanged() {
- mView.refreshContentDescription(getCurrentUser());
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- return null;
- }
- };
- mView.refreshContentDescription(getCurrentUser());
- }
- }
- }
-
- private String getCurrentUser() {
- // TODO(b/138661450)
- if (whitelistIpcs(() -> mUserManager.isUserSwitcherEnabled())) {
- return mUserSwitcherController.getCurrentUserName();
- }
-
- return null;
- }
-
- /** Returns true if view should be made visible. */
- public boolean isMultiUserEnabled() {
- // TODO(b/138661450) Move IPC calls to background
- return whitelistIpcs(() -> mUserManager.isUserSwitcherEnabled(
- getResources().getBoolean(R.bool.qs_show_user_switcher_for_single_user)));
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt
index 6c66f0bb1e47..341eb3b0425c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt
@@ -68,7 +68,6 @@ public class DeviceControlsControllerImpl @Inject constructor(
internal const val PREFS_CONTROLS_SEEDING_COMPLETED = "SeedingCompleted"
const val PREFS_CONTROLS_FILE = "controls_prefs"
- internal const val PREFS_SETTINGS_DIALOG_ATTEMPTS = "show_settings_attempts"
private const val SEEDING_MAX = 2
}
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
index ad97ef4a79bc..ef43702e97b8 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
@@ -45,7 +45,6 @@ import androidx.annotation.NonNull;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.wallpapers.canvas.WallpaperLocalColorExtractor;
@@ -57,7 +56,6 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.Executor;
import javax.inject.Inject;
@@ -88,17 +86,12 @@ public class ImageWallpaper extends WallpaperService {
private final DelayableExecutor mBackgroundExecutor;
private static final int DELAY_UNLOAD_BITMAP = 2000;
- @Main
- private final Executor mMainExecutor;
-
@Inject
public ImageWallpaper(FeatureFlags featureFlags,
- @Background DelayableExecutor backgroundExecutor,
- @Main Executor mainExecutor) {
+ @Background DelayableExecutor backgroundExecutor) {
super();
mFeatureFlags = featureFlags;
mBackgroundExecutor = backgroundExecutor;
- mMainExecutor = mainExecutor;
}
@Override
@@ -662,13 +655,9 @@ public class ImageWallpaper extends WallpaperService {
loadWallpaperAndDrawFrameInternal();
} else {
mBitmapUsages++;
-
- // drawing is done on the main thread
- mMainExecutor.execute(() -> {
- drawFrameOnCanvas(mBitmap);
- reportEngineShown(false);
- unloadBitmapIfNotUsed();
- });
+ drawFrameOnCanvas(mBitmap);
+ reportEngineShown(false);
+ unloadBitmapIfNotUsedInternal();
}
}
@@ -706,11 +695,15 @@ public class ImageWallpaper extends WallpaperService {
private void unloadBitmapIfNotUsedSynchronized() {
synchronized (mLock) {
- mBitmapUsages -= 1;
- if (mBitmapUsages <= 0) {
- mBitmapUsages = 0;
- unloadBitmapInternal();
- }
+ unloadBitmapIfNotUsedInternal();
+ }
+ }
+
+ private void unloadBitmapIfNotUsedInternal() {
+ mBitmapUsages -= 1;
+ if (mBitmapUsages <= 0) {
+ mBitmapUsages = 0;
+ unloadBitmapInternal();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
index 8bbaf3dff1e5..4903d31f89f4 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
@@ -19,6 +19,7 @@ package com.android.keyguard;
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.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
@@ -87,6 +88,7 @@ public class KeyguardAbsKeyInputViewControllerTest extends SysuiTestCase {
when(mAbsKeyInputView.isAttachedToWindow()).thenReturn(true);
when(mAbsKeyInputView.requireViewById(R.id.bouncer_message_area))
.thenReturn(mKeyguardMessageArea);
+ when(mAbsKeyInputView.getResources()).thenReturn(getContext().getResources());
mKeyguardAbsKeyInputViewController = new KeyguardAbsKeyInputViewController(mAbsKeyInputView,
mKeyguardUpdateMonitor, mSecurityMode, mLockPatternUtils, mKeyguardSecurityCallback,
mKeyguardMessageAreaControllerFactory, mLatencyTracker, mFalsingCollector,
@@ -125,4 +127,22 @@ public class KeyguardAbsKeyInputViewControllerTest extends SysuiTestCase {
verifyZeroInteractions(mKeyguardSecurityCallback);
verifyZeroInteractions(mKeyguardMessageAreaController);
}
+
+ @Test
+ public void onPromptReasonNone_doesNotSetMessage() {
+ mKeyguardAbsKeyInputViewController.showPromptReason(0);
+ verify(mKeyguardMessageAreaController, never()).setMessage(
+ getContext().getResources().getString(R.string.kg_prompt_reason_restart_password),
+ false);
+ }
+
+ @Test
+ public void onPromptReason_setsMessage() {
+ when(mAbsKeyInputView.getPromptReasonStringRes(1)).thenReturn(
+ R.string.kg_prompt_reason_restart_password);
+ mKeyguardAbsKeyInputViewController.showPromptReason(1);
+ verify(mKeyguardMessageAreaController).setMessage(
+ getContext().getResources().getString(R.string.kg_prompt_reason_restart_password),
+ false);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
index d20be56d6c6b..d91279399341 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
@@ -30,64 +30,54 @@ import com.android.systemui.util.concurrency.DelayableExecutor
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.Mockito
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper
class KeyguardPasswordViewControllerTest : SysuiTestCase() {
- @Mock
- private lateinit var keyguardPasswordView: KeyguardPasswordView
- @Mock
- private lateinit var passwordEntry: EditText
- @Mock
- lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
- @Mock
- lateinit var securityMode: KeyguardSecurityModel.SecurityMode
- @Mock
- lateinit var lockPatternUtils: LockPatternUtils
- @Mock
- lateinit var keyguardSecurityCallback: KeyguardSecurityCallback
- @Mock
- lateinit var messageAreaControllerFactory: KeyguardMessageAreaController.Factory
- @Mock
- lateinit var latencyTracker: LatencyTracker
- @Mock
- lateinit var inputMethodManager: InputMethodManager
- @Mock
- lateinit var emergencyButtonController: EmergencyButtonController
- @Mock
- lateinit var mainExecutor: DelayableExecutor
- @Mock
- lateinit var falsingCollector: FalsingCollector
- @Mock
- lateinit var keyguardViewController: KeyguardViewController
- @Mock
- private lateinit var mKeyguardMessageArea: BouncerKeyguardMessageArea
- @Mock
- private lateinit var mKeyguardMessageAreaController:
- KeyguardMessageAreaController<BouncerKeyguardMessageArea>
+ @Mock private lateinit var keyguardPasswordView: KeyguardPasswordView
+ @Mock private lateinit var passwordEntry: EditText
+ @Mock lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+ @Mock lateinit var securityMode: KeyguardSecurityModel.SecurityMode
+ @Mock lateinit var lockPatternUtils: LockPatternUtils
+ @Mock lateinit var keyguardSecurityCallback: KeyguardSecurityCallback
+ @Mock lateinit var messageAreaControllerFactory: KeyguardMessageAreaController.Factory
+ @Mock lateinit var latencyTracker: LatencyTracker
+ @Mock lateinit var inputMethodManager: InputMethodManager
+ @Mock lateinit var emergencyButtonController: EmergencyButtonController
+ @Mock lateinit var mainExecutor: DelayableExecutor
+ @Mock lateinit var falsingCollector: FalsingCollector
+ @Mock lateinit var keyguardViewController: KeyguardViewController
+ @Mock private lateinit var mKeyguardMessageArea: BouncerKeyguardMessageArea
+ @Mock
+ private lateinit var mKeyguardMessageAreaController:
+ KeyguardMessageAreaController<BouncerKeyguardMessageArea>
- private lateinit var keyguardPasswordViewController: KeyguardPasswordViewController
+ private lateinit var keyguardPasswordViewController: KeyguardPasswordViewController
- @Before
- fun setup() {
- MockitoAnnotations.initMocks(this)
- Mockito.`when`(
- keyguardPasswordView
- .requireViewById<BouncerKeyguardMessageArea>(R.id.bouncer_message_area)
- ).thenReturn(mKeyguardMessageArea)
- Mockito.`when`(messageAreaControllerFactory.create(mKeyguardMessageArea))
- .thenReturn(mKeyguardMessageAreaController)
- Mockito.`when`(keyguardPasswordView.passwordTextViewId).thenReturn(R.id.passwordEntry)
- Mockito.`when`(keyguardPasswordView.findViewById<EditText>(R.id.passwordEntry)
- ).thenReturn(passwordEntry)
- keyguardPasswordViewController = KeyguardPasswordViewController(
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ Mockito.`when`(
+ keyguardPasswordView.requireViewById<BouncerKeyguardMessageArea>(
+ R.id.bouncer_message_area))
+ .thenReturn(mKeyguardMessageArea)
+ Mockito.`when`(messageAreaControllerFactory.create(mKeyguardMessageArea))
+ .thenReturn(mKeyguardMessageAreaController)
+ Mockito.`when`(keyguardPasswordView.passwordTextViewId).thenReturn(R.id.passwordEntry)
+ Mockito.`when`(keyguardPasswordView.findViewById<EditText>(R.id.passwordEntry))
+ .thenReturn(passwordEntry)
+ `when`(keyguardPasswordView.resources).thenReturn(context.resources)
+ keyguardPasswordViewController =
+ KeyguardPasswordViewController(
keyguardPasswordView,
keyguardUpdateMonitor,
securityMode,
@@ -100,51 +90,48 @@ class KeyguardPasswordViewControllerTest : SysuiTestCase() {
mainExecutor,
mContext.resources,
falsingCollector,
- keyguardViewController
- )
- }
+ keyguardViewController)
+ }
- @Test
- fun testFocusWhenBouncerIsShown() {
- Mockito.`when`(keyguardViewController.isBouncerShowing).thenReturn(true)
- Mockito.`when`(keyguardPasswordView.isShown).thenReturn(true)
- keyguardPasswordViewController.onResume(KeyguardSecurityView.VIEW_REVEALED)
- keyguardPasswordView.post {
- verify(keyguardPasswordView).requestFocus()
- verify(keyguardPasswordView).showKeyboard()
- }
+ @Test
+ fun testFocusWhenBouncerIsShown() {
+ Mockito.`when`(keyguardViewController.isBouncerShowing).thenReturn(true)
+ Mockito.`when`(keyguardPasswordView.isShown).thenReturn(true)
+ keyguardPasswordViewController.onResume(KeyguardSecurityView.VIEW_REVEALED)
+ keyguardPasswordView.post {
+ verify(keyguardPasswordView).requestFocus()
+ verify(keyguardPasswordView).showKeyboard()
}
+ }
- @Test
- fun testDoNotFocusWhenBouncerIsHidden() {
- Mockito.`when`(keyguardViewController.isBouncerShowing).thenReturn(false)
- Mockito.`when`(keyguardPasswordView.isShown).thenReturn(true)
- keyguardPasswordViewController.onResume(KeyguardSecurityView.VIEW_REVEALED)
- verify(keyguardPasswordView, never()).requestFocus()
- }
+ @Test
+ fun testDoNotFocusWhenBouncerIsHidden() {
+ Mockito.`when`(keyguardViewController.isBouncerShowing).thenReturn(false)
+ Mockito.`when`(keyguardPasswordView.isShown).thenReturn(true)
+ keyguardPasswordViewController.onResume(KeyguardSecurityView.VIEW_REVEALED)
+ verify(keyguardPasswordView, never()).requestFocus()
+ }
- @Test
- fun testHideKeyboardWhenOnPause() {
- keyguardPasswordViewController.onPause()
- keyguardPasswordView.post {
- verify(keyguardPasswordView).clearFocus()
- verify(keyguardPasswordView).hideKeyboard()
- }
+ @Test
+ fun testHideKeyboardWhenOnPause() {
+ keyguardPasswordViewController.onPause()
+ keyguardPasswordView.post {
+ verify(keyguardPasswordView).clearFocus()
+ verify(keyguardPasswordView).hideKeyboard()
}
+ }
- @Test
- fun startAppearAnimation() {
- keyguardPasswordViewController.startAppearAnimation()
- verify(mKeyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_password)
- }
+ @Test
+ fun startAppearAnimation() {
+ keyguardPasswordViewController.startAppearAnimation()
+ verify(mKeyguardMessageAreaController)
+ .setMessage(context.resources.getString(R.string.keyguard_enter_your_password), false)
+ }
- @Test
- fun startAppearAnimation_withExistingMessage() {
- `when`(mKeyguardMessageAreaController.message).thenReturn("Unlock to continue.")
- keyguardPasswordViewController.startAppearAnimation()
- verify(
- mKeyguardMessageAreaController,
- never()
- ).setMessage(R.string.keyguard_enter_your_password)
- }
+ @Test
+ fun startAppearAnimation_withExistingMessage() {
+ `when`(mKeyguardMessageAreaController.message).thenReturn("Unlock to continue.")
+ keyguardPasswordViewController.startAppearAnimation()
+ verify(mKeyguardMessageAreaController, never()).setMessage(anyString(), anyBoolean())
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
index b3d1c8f909d8..85dbdb8330a3 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
@@ -30,97 +30,93 @@ import com.android.systemui.statusbar.policy.DevicePostureController
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
+import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
-import org.mockito.Mockito.never
import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper
class KeyguardPatternViewControllerTest : SysuiTestCase() {
- @Mock
- private lateinit var mKeyguardPatternView: KeyguardPatternView
+ @Mock private lateinit var mKeyguardPatternView: KeyguardPatternView
- @Mock
- private lateinit var mKeyguardUpdateMonitor: KeyguardUpdateMonitor
+ @Mock private lateinit var mKeyguardUpdateMonitor: KeyguardUpdateMonitor
- @Mock
- private lateinit var mSecurityMode: KeyguardSecurityModel.SecurityMode
+ @Mock private lateinit var mSecurityMode: KeyguardSecurityModel.SecurityMode
- @Mock
- private lateinit var mLockPatternUtils: LockPatternUtils
+ @Mock private lateinit var mLockPatternUtils: LockPatternUtils
- @Mock
- private lateinit var mKeyguardSecurityCallback: KeyguardSecurityCallback
+ @Mock private lateinit var mKeyguardSecurityCallback: KeyguardSecurityCallback
- @Mock
- private lateinit var mLatencyTracker: LatencyTracker
- private var mFalsingCollector: FalsingCollector = FalsingCollectorFake()
+ @Mock private lateinit var mLatencyTracker: LatencyTracker
+ private var mFalsingCollector: FalsingCollector = FalsingCollectorFake()
- @Mock
- private lateinit var mEmergencyButtonController: EmergencyButtonController
+ @Mock private lateinit var mEmergencyButtonController: EmergencyButtonController
- @Mock
- private lateinit
- var mKeyguardMessageAreaControllerFactory: KeyguardMessageAreaController.Factory
+ @Mock
+ private lateinit var mKeyguardMessageAreaControllerFactory: KeyguardMessageAreaController.Factory
- @Mock
- private lateinit var mKeyguardMessageArea: BouncerKeyguardMessageArea
+ @Mock private lateinit var mKeyguardMessageArea: BouncerKeyguardMessageArea
- @Mock
- private lateinit var mKeyguardMessageAreaController:
- KeyguardMessageAreaController<BouncerKeyguardMessageArea>
+ @Mock
+ private lateinit var mKeyguardMessageAreaController:
+ KeyguardMessageAreaController<BouncerKeyguardMessageArea>
- @Mock
- private lateinit var mLockPatternView: LockPatternView
+ @Mock private lateinit var mLockPatternView: LockPatternView
- @Mock
- private lateinit var mPostureController: DevicePostureController
+ @Mock private lateinit var mPostureController: DevicePostureController
- private lateinit var mKeyguardPatternViewController: KeyguardPatternViewController
+ private lateinit var mKeyguardPatternViewController: KeyguardPatternViewController
- @Before
- fun setup() {
- MockitoAnnotations.initMocks(this)
- `when`(mKeyguardPatternView.isAttachedToWindow).thenReturn(true)
- `when`(mKeyguardPatternView
- .requireViewById<BouncerKeyguardMessageArea>(R.id.bouncer_message_area))
- .thenReturn(mKeyguardMessageArea)
- `when`(mKeyguardPatternView.findViewById<LockPatternView>(R.id.lockPatternView))
- .thenReturn(mLockPatternView)
- `when`(mKeyguardMessageAreaControllerFactory.create(mKeyguardMessageArea))
- .thenReturn(mKeyguardMessageAreaController)
- mKeyguardPatternViewController = KeyguardPatternViewController(
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ `when`(mKeyguardPatternView.isAttachedToWindow).thenReturn(true)
+ `when`(
+ mKeyguardPatternView.requireViewById<BouncerKeyguardMessageArea>(
+ R.id.bouncer_message_area))
+ .thenReturn(mKeyguardMessageArea)
+ `when`(mKeyguardPatternView.findViewById<LockPatternView>(R.id.lockPatternView))
+ .thenReturn(mLockPatternView)
+ `when`(mKeyguardMessageAreaControllerFactory.create(mKeyguardMessageArea))
+ .thenReturn(mKeyguardMessageAreaController)
+ `when`(mKeyguardPatternView.resources).thenReturn(context.resources)
+ mKeyguardPatternViewController =
+ KeyguardPatternViewController(
mKeyguardPatternView,
- mKeyguardUpdateMonitor, mSecurityMode, mLockPatternUtils, mKeyguardSecurityCallback,
- mLatencyTracker, mFalsingCollector, mEmergencyButtonController,
- mKeyguardMessageAreaControllerFactory, mPostureController
- )
- }
-
- @Test
- fun onPause_resetsText() {
- mKeyguardPatternViewController.init()
- mKeyguardPatternViewController.onPause()
- verify(mKeyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_pattern)
- }
-
-
- @Test
- fun startAppearAnimation() {
- mKeyguardPatternViewController.startAppearAnimation()
- verify(mKeyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_pattern)
- }
-
- @Test
- fun startAppearAnimation_withExistingMessage() {
- `when`(mKeyguardMessageAreaController.message).thenReturn("Unlock to continue.")
- mKeyguardPatternViewController.startAppearAnimation()
- verify(
- mKeyguardMessageAreaController,
- never()
- ).setMessage(R.string.keyguard_enter_your_password)
- }
+ mKeyguardUpdateMonitor,
+ mSecurityMode,
+ mLockPatternUtils,
+ mKeyguardSecurityCallback,
+ mLatencyTracker,
+ mFalsingCollector,
+ mEmergencyButtonController,
+ mKeyguardMessageAreaControllerFactory,
+ mPostureController)
+ }
+
+ @Test
+ fun onPause_resetsText() {
+ mKeyguardPatternViewController.init()
+ mKeyguardPatternViewController.onPause()
+ verify(mKeyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_pattern)
+ }
+
+ @Test
+ fun startAppearAnimation() {
+ mKeyguardPatternViewController.startAppearAnimation()
+ verify(mKeyguardMessageAreaController)
+ .setMessage(context.resources.getString(R.string.keyguard_enter_your_pattern), false)
+ }
+
+ @Test
+ fun startAppearAnimation_withExistingMessage() {
+ `when`(mKeyguardMessageAreaController.message).thenReturn("Unlock to continue.")
+ mKeyguardPatternViewController.startAppearAnimation()
+ verify(mKeyguardMessageAreaController, never()).setMessage(anyString(), anyBoolean())
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
index 8bcfe6f2b6f5..cdb7bbb9f823 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
@@ -31,10 +31,13 @@ import com.android.systemui.statusbar.policy.DevicePostureController
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.any
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@SmallTest
@@ -79,6 +82,7 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
keyguardMessageAreaControllerFactory.create(any(KeyguardMessageArea::class.java))
)
.thenReturn(keyguardMessageAreaController)
+ `when`(keyguardPinView.resources).thenReturn(context.resources)
pinViewController =
KeyguardPinViewController(
keyguardPinView,
@@ -98,14 +102,14 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
@Test
fun startAppearAnimation() {
pinViewController.startAppearAnimation()
- verify(keyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_pin)
+ verify(keyguardMessageAreaController)
+ .setMessage(context.resources.getString(R.string.keyguard_enter_your_pin), false)
}
@Test
fun startAppearAnimation_withExistingMessage() {
Mockito.`when`(keyguardMessageAreaController.message).thenReturn("Unlock to continue.")
pinViewController.startAppearAnimation()
- verify(keyguardMessageAreaController, Mockito.never())
- .setMessage(R.string.keyguard_enter_your_password)
+ verify(keyguardMessageAreaController, Mockito.never()).setMessage(anyString(), anyBoolean())
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 0e92a2904436..40542d25689d 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -30,6 +30,7 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STR
import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING_RESTARTING;
import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
+import static com.android.keyguard.KeyguardUpdateMonitor.HAL_POWER_PRESS_TIMEOUT;
import static com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser;
import static com.google.common.truth.Truth.assertThat;
@@ -855,12 +856,21 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
}
@Test
- public void testFingerprintPowerPressed_restartsFingerprintListeningStateImmediately() {
+ public void testFingerprintPowerPressed_restartsFingerprintListeningStateWithDelay() {
mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback
.onAuthenticationError(FingerprintManager.BIOMETRIC_ERROR_POWER_PRESSED, "");
- verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
- anyInt());
+ // THEN doesn't authenticate immediately
+ verify(mFingerprintManager, never()).authenticate(any(),
+ any(), any(), any(), anyInt(), anyInt(), anyInt());
+
+ // WHEN all messages (with delays) are processed
+ mTestableLooper.moveTimeForward(HAL_POWER_PRESS_TIMEOUT);
+ mTestableLooper.processAllMessages();
+
+ // THEN fingerprint manager attempts to authenticate again
+ verify(mFingerprintManager).authenticate(any(),
+ any(), any(), any(), anyInt(), anyInt(), anyInt());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index b267a5c23a49..a94f3427eebe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -110,6 +110,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
+import javax.inject.Provider;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper(setAsMainLooper = true)
@@ -261,6 +263,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
initUdfpsController(true /* hasAlternateTouchProvider */);
}
+
private void initUdfpsController(boolean hasAlternateTouchProvider) {
initUdfpsController(mOpticalProps, hasAlternateTouchProvider);
}
@@ -270,8 +273,10 @@ public class UdfpsControllerTest extends SysuiTestCase {
reset(mFingerprintManager);
reset(mScreenLifecycle);
- final Optional<AlternateUdfpsTouchProvider> alternateTouchProvider =
- hasAlternateTouchProvider ? Optional.of(mAlternateTouchProvider) : Optional.empty();
+ final Optional<Provider<AlternateUdfpsTouchProvider>> alternateTouchProvider =
+ hasAlternateTouchProvider ? Optional.of(
+ (Provider<AlternateUdfpsTouchProvider>) () -> mAlternateTouchProvider)
+ : Optional.empty();
mUdfpsController = new UdfpsController(mContext, new FakeExecution(), mLayoutInflater,
mFingerprintManager, mWindowManager, mStatusBarStateController, mFgExecutor,
@@ -1140,7 +1145,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
}
@Test
- public void onTouch_withNewTouchDetection_shouldCallOldFingerprintManagerPath()
+ public void onTouch_withNewTouchDetection_shouldCallNewFingerprintManagerPath()
throws RemoteException {
final NormalizedTouchData touchData = new NormalizedTouchData(0, 0f, 0f, 0f, 0f, 0f, 0L,
0L);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt
index 1d00d6b05568..16fb50c15af6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt
@@ -16,21 +16,19 @@
package com.android.systemui.controls.ui
-import android.content.Context
-import android.content.SharedPreferences
import android.test.suitebuilder.annotation.SmallTest
import android.testing.AndroidTestingRunner
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastSender
import com.android.systemui.controls.ControlsMetricsLogger
-import com.android.systemui.controls.FakeControlsSettingsRepository
+import com.android.systemui.controls.settings.ControlsSettingsDialogManager
+import com.android.systemui.controls.settings.FakeControlsSettingsRepository
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.settings.UserContextProvider
import com.android.systemui.statusbar.VibratorHelper
-import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.concurrency.DelayableExecutor
-import com.android.systemui.util.settings.SecureSettings
import com.android.wm.shell.TaskViewFactory
import org.junit.Before
import org.junit.Test
@@ -40,8 +38,8 @@ import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.`when`
import org.mockito.Mockito.anyBoolean
+import org.mockito.Mockito.doNothing
import org.mockito.Mockito.doReturn
-import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.spy
@@ -71,9 +69,9 @@ class ControlActionCoordinatorImplTest : SysuiTestCase() {
@Mock
private lateinit var metricsLogger: ControlsMetricsLogger
@Mock
- private lateinit var secureSettings: SecureSettings
+ private lateinit var featureFlags: FeatureFlags
@Mock
- private lateinit var userContextProvider: UserContextProvider
+ private lateinit var controlsSettingsDialogManager: ControlsSettingsDialogManager
companion object {
fun <T> any(): T = Mockito.any<T>()
@@ -103,23 +101,16 @@ class ControlActionCoordinatorImplTest : SysuiTestCase() {
taskViewFactory,
metricsLogger,
vibratorHelper,
- secureSettings,
- userContextProvider,
- controlsSettingsRepository
+ controlsSettingsRepository,
+ controlsSettingsDialogManager,
+ featureFlags
))
-
- val userContext = mock(Context::class.java)
- val pref = mock(SharedPreferences::class.java)
- `when`(userContextProvider.userContext).thenReturn(userContext)
- `when`(userContext.getSharedPreferences(
- DeviceControlsControllerImpl.PREFS_CONTROLS_FILE, Context.MODE_PRIVATE))
- .thenReturn(pref)
- // Just return 2 so we don't test any Dialog logic which requires a launched activity.
- `when`(pref.getInt(DeviceControlsControllerImpl.PREFS_SETTINGS_DIALOG_ATTEMPTS, 0))
- .thenReturn(2)
+ coordinator.activityContext = mContext
`when`(cvh.cws.ci.controlId).thenReturn(ID)
`when`(cvh.cws.control?.isAuthRequired()).thenReturn(true)
+ `when`(featureFlags.isEnabled(Flags.USE_APP_PANELS)).thenReturn(false)
+
action = spy(coordinator.Action(ID, {}, false, true))
doReturn(action).`when`(coordinator).createAction(any(), any(), anyBoolean(), anyBoolean())
}
@@ -160,15 +151,31 @@ class ControlActionCoordinatorImplTest : SysuiTestCase() {
doReturn(action).`when`(coordinator).createAction(any(), any(), anyBoolean(), anyBoolean())
`when`(keyguardStateController.isShowing()).thenReturn(true)
- `when`(keyguardStateController.isUnlocked()).thenReturn(false)
coordinator.toggle(cvh, "", true)
verify(coordinator).bouncerOrRun(action)
+ verify(controlsSettingsDialogManager).maybeShowDialog(any(), any())
verify(action).invoke()
}
@Test
+ fun testToggleWhenLockedDoesNotTriggerDialog_featureFlagEnabled() {
+ `when`(featureFlags.isEnabled(Flags.USE_APP_PANELS)).thenReturn(true)
+ action = spy(coordinator.Action(ID, {}, false, false))
+ doReturn(action).`when`(coordinator).createAction(any(), any(), anyBoolean(), anyBoolean())
+
+ `when`(keyguardStateController.isShowing()).thenReturn(true)
+ `when`(keyguardStateController.isUnlocked()).thenReturn(false)
+ doNothing().`when`(controlsSettingsDialogManager).maybeShowDialog(any(), any())
+
+ coordinator.toggle(cvh, "", true)
+
+ verify(coordinator).bouncerOrRun(action)
+ verify(controlsSettingsDialogManager, never()).maybeShowDialog(any(), any())
+ }
+
+ @Test
fun testToggleDoesNotRunsWhenLockedAndAuthRequired() {
action = spy(coordinator.Action(ID, {}, false, true))
doReturn(action).`when`(coordinator).createAction(any(), any(), anyBoolean(), anyBoolean())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
index 48fc46b7e730..9144b13c7f3e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
@@ -22,7 +22,7 @@ import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
import com.android.systemui.SysuiTestCase
-import com.android.systemui.controls.FakeControlsSettingsRepository
+import com.android.systemui.controls.settings.FakeControlsSettingsRepository
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.controls.controller.ControlsTileResourceConfiguration
import com.android.systemui.controls.management.ControlsListingController
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt
new file mode 100644
index 000000000000..0c9986d82447
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.controls.settings
+
+import android.content.DialogInterface
+import android.content.SharedPreferences
+import android.database.ContentObserver
+import android.provider.Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS
+import android.provider.Settings.Secure.LOCKSCREEN_SHOW_CONTROLS
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.controls.settings.ControlsSettingsDialogManager.Companion.PREFS_SETTINGS_DIALOG_ATTEMPTS
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.settings.UserFileManager
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl
+import com.android.systemui.util.FakeSharedPreferences
+import com.android.systemui.util.TestableAlertDialog
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.nullable
+import com.android.systemui.util.settings.FakeSettings
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.Mock
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class ControlsSettingsDialogManagerImplTest : SysuiTestCase() {
+
+ companion object {
+ private const val SETTING_SHOW = LOCKSCREEN_SHOW_CONTROLS
+ private const val SETTING_ACTION = LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS
+ private const val MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG = 2
+ }
+
+ @Mock private lateinit var userFileManager: UserFileManager
+ @Mock private lateinit var userTracker: UserTracker
+ @Mock private lateinit var activityStarter: ActivityStarter
+ @Mock private lateinit var completedRunnable: () -> Unit
+
+ private lateinit var controlsSettingsRepository: FakeControlsSettingsRepository
+ private lateinit var sharedPreferences: FakeSharedPreferences
+ private lateinit var secureSettings: FakeSettings
+
+ private lateinit var underTest: ControlsSettingsDialogManagerImpl
+
+ private var dialog: TestableAlertDialog? = null
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ controlsSettingsRepository = FakeControlsSettingsRepository()
+ sharedPreferences = FakeSharedPreferences()
+ secureSettings = FakeSettings()
+
+ `when`(userTracker.userId).thenReturn(0)
+ secureSettings.userId = userTracker.userId
+ `when`(
+ userFileManager.getSharedPreferences(
+ eq(DeviceControlsControllerImpl.PREFS_CONTROLS_FILE),
+ anyInt(),
+ anyInt()
+ )
+ )
+ .thenReturn(sharedPreferences)
+
+ `when`(activityStarter.dismissKeyguardThenExecute(any(), nullable(), anyBoolean()))
+ .thenAnswer { (it.arguments[0] as ActivityStarter.OnDismissAction).onDismiss() }
+
+ attachRepositoryToSettings()
+ underTest =
+ ControlsSettingsDialogManagerImpl(
+ secureSettings,
+ userFileManager,
+ controlsSettingsRepository,
+ userTracker,
+ activityStarter
+ ) { context, _ -> TestableAlertDialog(context).also { dialog = it } }
+ }
+
+ @After
+ fun tearDown() {
+ underTest.closeDialog()
+ }
+
+ @Test
+ fun dialogNotShownIfPrefsAtMaximum() {
+ sharedPreferences.putAttempts(MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG)
+
+ underTest.maybeShowDialog(context, completedRunnable)
+
+ assertThat(dialog?.isShowing ?: false).isFalse()
+ verify(completedRunnable).invoke()
+ }
+
+ @Test
+ fun dialogNotShownIfSettingsAreTrue() {
+ sharedPreferences.putAttempts(0)
+ secureSettings.putBool(SETTING_SHOW, true)
+ secureSettings.putBool(SETTING_ACTION, true)
+
+ underTest.maybeShowDialog(context, completedRunnable)
+
+ assertThat(dialog?.isShowing ?: false).isFalse()
+ verify(completedRunnable).invoke()
+ }
+
+ @Test
+ fun dialogShownIfAllowTrivialControlsFalse() {
+ sharedPreferences.putAttempts(0)
+ secureSettings.putBool(SETTING_SHOW, true)
+ secureSettings.putBool(SETTING_ACTION, false)
+
+ underTest.maybeShowDialog(context, completedRunnable)
+
+ assertThat(dialog?.isShowing ?: false).isTrue()
+ }
+
+ @Test
+ fun dialogDispossedAfterClosing() {
+ sharedPreferences.putAttempts(0)
+ secureSettings.putBool(SETTING_SHOW, true)
+ secureSettings.putBool(SETTING_ACTION, false)
+
+ underTest.maybeShowDialog(context, completedRunnable)
+ underTest.closeDialog()
+
+ assertThat(dialog?.isShowing ?: false).isFalse()
+ }
+
+ @Test
+ fun dialogNeutralButtonDoesntChangeSetting() {
+ sharedPreferences.putAttempts(0)
+ secureSettings.putBool(SETTING_SHOW, true)
+ secureSettings.putBool(SETTING_ACTION, false)
+
+ underTest.maybeShowDialog(context, completedRunnable)
+ clickButton(DialogInterface.BUTTON_NEUTRAL)
+
+ assertThat(secureSettings.getBool(SETTING_ACTION, false)).isFalse()
+ }
+
+ @Test
+ fun dialogNeutralButtonPutsMaxAttempts() {
+ sharedPreferences.putAttempts(0)
+ secureSettings.putBool(SETTING_SHOW, true)
+ secureSettings.putBool(SETTING_ACTION, false)
+
+ underTest.maybeShowDialog(context, completedRunnable)
+ clickButton(DialogInterface.BUTTON_NEUTRAL)
+
+ assertThat(sharedPreferences.getInt(PREFS_SETTINGS_DIALOG_ATTEMPTS, 0))
+ .isEqualTo(MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG)
+ }
+
+ @Test
+ fun dialogNeutralButtonCallsOnComplete() {
+ sharedPreferences.putAttempts(0)
+ secureSettings.putBool(SETTING_SHOW, true)
+ secureSettings.putBool(SETTING_ACTION, false)
+
+ underTest.maybeShowDialog(context, completedRunnable)
+ clickButton(DialogInterface.BUTTON_NEUTRAL)
+
+ verify(completedRunnable).invoke()
+ }
+
+ @Test
+ fun dialogPositiveButtonChangesSetting() {
+ sharedPreferences.putAttempts(0)
+ secureSettings.putBool(SETTING_SHOW, true)
+ secureSettings.putBool(SETTING_ACTION, false)
+
+ underTest.maybeShowDialog(context, completedRunnable)
+ clickButton(DialogInterface.BUTTON_POSITIVE)
+
+ assertThat(secureSettings.getBool(SETTING_ACTION, false)).isTrue()
+ }
+
+ @Test
+ fun dialogPositiveButtonPutsMaxAttempts() {
+ sharedPreferences.putAttempts(0)
+ secureSettings.putBool(SETTING_SHOW, true)
+ secureSettings.putBool(SETTING_ACTION, false)
+
+ underTest.maybeShowDialog(context, completedRunnable)
+ clickButton(DialogInterface.BUTTON_POSITIVE)
+
+ assertThat(sharedPreferences.getInt(PREFS_SETTINGS_DIALOG_ATTEMPTS, 0))
+ .isEqualTo(MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG)
+ }
+
+ @Test
+ fun dialogPositiveButtonCallsOnComplete() {
+ sharedPreferences.putAttempts(0)
+ secureSettings.putBool(SETTING_SHOW, true)
+ secureSettings.putBool(SETTING_ACTION, false)
+
+ underTest.maybeShowDialog(context, completedRunnable)
+ clickButton(DialogInterface.BUTTON_POSITIVE)
+
+ verify(completedRunnable).invoke()
+ }
+
+ @Test
+ fun dialogCancelDoesntChangeSetting() {
+ sharedPreferences.putAttempts(0)
+ secureSettings.putBool(SETTING_SHOW, true)
+ secureSettings.putBool(SETTING_ACTION, false)
+
+ underTest.maybeShowDialog(context, completedRunnable)
+ dialog?.cancel()
+
+ assertThat(secureSettings.getBool(SETTING_ACTION, false)).isFalse()
+ }
+
+ @Test
+ fun dialogCancelPutsOneExtraAttempt() {
+ val attempts = 0
+ sharedPreferences.putAttempts(attempts)
+ secureSettings.putBool(SETTING_SHOW, true)
+ secureSettings.putBool(SETTING_ACTION, false)
+
+ underTest.maybeShowDialog(context, completedRunnable)
+ dialog?.cancel()
+
+ assertThat(sharedPreferences.getInt(PREFS_SETTINGS_DIALOG_ATTEMPTS, 0))
+ .isEqualTo(attempts + 1)
+ }
+
+ @Test
+ fun dialogCancelCallsOnComplete() {
+ sharedPreferences.putAttempts(0)
+ secureSettings.putBool(SETTING_SHOW, true)
+ secureSettings.putBool(SETTING_ACTION, false)
+
+ underTest.maybeShowDialog(context, completedRunnable)
+ dialog?.cancel()
+
+ verify(completedRunnable).invoke()
+ }
+
+ @Test
+ fun closeDialogDoesNotCallOnComplete() {
+ sharedPreferences.putAttempts(0)
+ secureSettings.putBool(SETTING_SHOW, true)
+ secureSettings.putBool(SETTING_ACTION, false)
+
+ underTest.maybeShowDialog(context, completedRunnable)
+ underTest.closeDialog()
+
+ verify(completedRunnable, never()).invoke()
+ }
+
+ @Test
+ fun dialogPositiveWithBothSettingsFalseTogglesBothSettings() {
+ sharedPreferences.putAttempts(0)
+ secureSettings.putBool(SETTING_SHOW, false)
+ secureSettings.putBool(SETTING_ACTION, false)
+
+ underTest.maybeShowDialog(context, completedRunnable)
+ clickButton(DialogInterface.BUTTON_POSITIVE)
+
+ assertThat(secureSettings.getBool(SETTING_SHOW)).isTrue()
+ assertThat(secureSettings.getBool(SETTING_ACTION)).isTrue()
+ }
+
+ private fun clickButton(which: Int) {
+ dialog?.clickButton(which)
+ }
+
+ private fun attachRepositoryToSettings() {
+ secureSettings.registerContentObserver(
+ SETTING_SHOW,
+ object : ContentObserver(null) {
+ override fun onChange(selfChange: Boolean) {
+ controlsSettingsRepository.setCanShowControlsInLockscreen(
+ secureSettings.getBool(SETTING_SHOW, false)
+ )
+ }
+ }
+ )
+
+ secureSettings.registerContentObserver(
+ SETTING_ACTION,
+ object : ContentObserver(null) {
+ override fun onChange(selfChange: Boolean) {
+ controlsSettingsRepository.setAllowActionOnTrivialControlsInLockscreen(
+ secureSettings.getBool(SETTING_ACTION, false)
+ )
+ }
+ }
+ )
+ }
+
+ private fun SharedPreferences.putAttempts(value: Int) {
+ edit().putInt(PREFS_SETTINGS_DIALOG_ATTEMPTS, value).commit()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ControlsSettingsRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsRepositoryImplTest.kt
index 4b88b44c3f03..b904ac14e707 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/ControlsSettingsRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsRepositoryImplTest.kt
@@ -15,7 +15,7 @@
*
*/
-package com.android.systemui.controls
+package com.android.systemui.controls.settings
import android.content.pm.UserInfo
import android.provider.Settings
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/FakeControlsSettingsRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/settings/FakeControlsSettingsRepository.kt
index 8a1bed20e700..b6628db14235 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/FakeControlsSettingsRepository.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/settings/FakeControlsSettingsRepository.kt
@@ -15,7 +15,7 @@
*
*/
-package com.android.systemui.controls
+package com.android.systemui.controls.settings
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
index d965e337f47a..779788aa0075 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
@@ -35,10 +35,10 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.controls.ControlsMetricsLogger
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.CustomIconCache
-import com.android.systemui.controls.FakeControlsSettingsRepository
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.controls.controller.StructureInfo
import com.android.systemui.controls.management.ControlsListingController
+import com.android.systemui.controls.settings.FakeControlsSettingsRepository
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.settings.UserFileManager
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 d17e3744edc6..798839dcc1f6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.keyguard;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
import static android.view.WindowManagerPolicyConstants.OFF_BECAUSE_OF_USER;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
@@ -34,6 +35,7 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.IActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.os.PowerManager;
@@ -41,6 +43,11 @@ import android.os.PowerManager.WakeLock;
import android.telephony.TelephonyManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.view.IRemoteAnimationFinishedCallback;
+import android.view.RemoteAnimationTarget;
+import android.view.View;
+import android.view.ViewRootImpl;
+import android.view.WindowManager;
import androidx.test.filters.SmallTest;
@@ -52,21 +59,27 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.mediator.ScreenOnCoordinator;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.ActivityLaunchAnimator;
+import com.android.systemui.biometrics.AuthController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingCollectorFake;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.settings.UserTracker;
+import com.android.systemui.shade.NotificationShadeWindowControllerImpl;
import com.android.systemui.shade.ShadeController;
+import com.android.systemui.shade.ShadeExpansionStateManager;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.DeviceConfigProxy;
@@ -80,8 +93,6 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import dagger.Lazy;
-
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@SmallTest
@@ -96,11 +107,15 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
private @Mock BroadcastDispatcher mBroadcastDispatcher;
private @Mock DismissCallbackRegistry mDismissCallbackRegistry;
private @Mock DumpManager mDumpManager;
+ private @Mock WindowManager mWindowManager;
+ private @Mock IActivityManager mActivityManager;
+ private @Mock ConfigurationController mConfigurationController;
private @Mock PowerManager mPowerManager;
private @Mock TrustManager mTrustManager;
private @Mock UserSwitcherController mUserSwitcherController;
private @Mock NavigationModeController mNavigationModeController;
private @Mock KeyguardDisplayManager mKeyguardDisplayManager;
+ private @Mock KeyguardBypassController mKeyguardBypassController;
private @Mock DozeParameters mDozeParameters;
private @Mock SysuiStatusBarStateController mStatusBarStateController;
private @Mock KeyguardStateController mKeyguardStateController;
@@ -110,10 +125,13 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
private @Mock InteractionJankMonitor mInteractionJankMonitor;
private @Mock ScreenOnCoordinator mScreenOnCoordinator;
private @Mock ShadeController mShadeController;
- private @Mock Lazy<NotificationShadeWindowController> mNotificationShadeWindowControllerLazy;
+ private NotificationShadeWindowController mNotificationShadeWindowController;
private @Mock DreamOverlayStateController mDreamOverlayStateController;
private @Mock ActivityLaunchAnimator mActivityLaunchAnimator;
private @Mock ScrimController mScrimController;
+ private @Mock SysuiColorExtractor mColorExtractor;
+ private @Mock AuthController mAuthController;
+ private @Mock ShadeExpansionStateManager mShadeExpansionStateManager;
private DeviceConfigProxy mDeviceConfig = new DeviceConfigProxyFake();
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@@ -130,6 +148,14 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
when(mPowerManager.newWakeLock(anyInt(), any())).thenReturn(mock(WakeLock.class));
when(mInteractionJankMonitor.begin(any(), anyInt())).thenReturn(true);
when(mInteractionJankMonitor.end(anyInt())).thenReturn(true);
+ final ViewRootImpl testViewRoot = mock(ViewRootImpl.class);
+ when(testViewRoot.getView()).thenReturn(mock(View.class));
+ when(mStatusBarKeyguardViewManager.getViewRootImpl()).thenReturn(testViewRoot);
+ mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(mContext,
+ mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
+ mConfigurationController, mViewMediator, mKeyguardBypassController,
+ mColorExtractor, mDumpManager, mKeyguardStateController,
+ mScreenOffAnimationController, mAuthController, mShadeExpansionStateManager);
createAndStartViewMediator();
}
@@ -287,6 +313,23 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
verify(mCentralSurfaces).updateIsKeyguard();
}
+ @Test
+ @TestableLooper.RunWithLooper(setAsMainLooper = true)
+ public void testStartKeyguardExitAnimation_expectSurfaceBehindRemoteAnimation() {
+ RemoteAnimationTarget[] apps = new RemoteAnimationTarget[]{
+ mock(RemoteAnimationTarget.class)
+ };
+ RemoteAnimationTarget[] wallpapers = new RemoteAnimationTarget[]{
+ mock(RemoteAnimationTarget.class)
+ };
+ IRemoteAnimationFinishedCallback callback = mock(IRemoteAnimationFinishedCallback.class);
+
+ mViewMediator.startKeyguardExitAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY, apps, wallpapers,
+ null, callback);
+ TestableLooper.get(this).processAllMessages();
+ assertTrue(mViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind());
+ }
+
private void createAndStartViewMediator() {
mViewMediator = new KeyguardViewMediator(
mContext,
@@ -315,7 +358,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
mInteractionJankMonitor,
mDreamOverlayStateController,
() -> mShadeController,
- mNotificationShadeWindowControllerLazy,
+ () -> mNotificationShadeWindowController,
() -> mActivityLaunchAnimator,
() -> mScrimController);
mViewMediator.start();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
deleted file mode 100644
index 2ba8782c6d02..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
+++ /dev/null
@@ -1,440 +0,0 @@
-package com.android.systemui.qs
-
-import android.content.Intent
-import android.os.Handler
-import android.os.UserManager
-import android.provider.Settings
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import android.testing.ViewUtils
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.test.filters.SmallTest
-import com.android.internal.logging.MetricsLogger
-import com.android.internal.logging.UiEventLogger
-import com.android.internal.logging.testing.FakeMetricsLogger
-import com.android.systemui.R
-import com.android.systemui.animation.ActivityLaunchAnimator
-import com.android.systemui.classifier.FalsingManagerFake
-import com.android.systemui.globalactions.GlobalActionsDialogLite
-import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.settings.UserTracker
-import com.android.systemui.statusbar.phone.MultiUserSwitchController
-import com.android.systemui.statusbar.policy.DeviceProvisionedController
-import com.android.systemui.statusbar.policy.FakeConfigurationController
-import com.android.systemui.statusbar.policy.UserInfoController
-import com.android.systemui.util.mockito.capture
-import com.android.systemui.util.settings.FakeSettings
-import com.android.systemui.utils.leaks.LeakCheckedTest
-import com.google.common.truth.Expect
-import com.google.common.truth.Truth.assertThat
-import javax.inject.Provider
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentCaptor
-import org.mockito.ArgumentMatchers.any
-import org.mockito.ArgumentMatchers.anyBoolean
-import org.mockito.Captor
-import org.mockito.Mock
-import org.mockito.Mockito
-import org.mockito.Mockito.atLeastOnce
-import org.mockito.Mockito.clearInvocations
-import org.mockito.Mockito.never
-import org.mockito.Mockito.reset
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-@RunWith(AndroidTestingRunner::class)
-class FooterActionsControllerTest : LeakCheckedTest() {
-
- @get:Rule var expect: Expect = Expect.create()
-
- @Mock private lateinit var userManager: UserManager
- @Mock private lateinit var userTracker: UserTracker
- @Mock private lateinit var activityStarter: ActivityStarter
- @Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
- @Mock private lateinit var userInfoController: UserInfoController
- @Mock private lateinit var multiUserSwitchControllerFactory: MultiUserSwitchController.Factory
- @Mock private lateinit var multiUserSwitchController: MultiUserSwitchController
- @Mock private lateinit var globalActionsDialogProvider: Provider<GlobalActionsDialogLite>
- @Mock private lateinit var globalActionsDialog: GlobalActionsDialogLite
- @Mock private lateinit var uiEventLogger: UiEventLogger
- @Mock private lateinit var securityFooterController: QSSecurityFooter
- @Mock private lateinit var fgsManagerController: QSFgsManagerFooter
- @Captor
- private lateinit var visibilityChangedCaptor:
- ArgumentCaptor<VisibilityChangedDispatcher.OnVisibilityChangedListener>
-
- private lateinit var controller: FooterActionsController
-
- private val configurationController = FakeConfigurationController()
- private val metricsLogger: MetricsLogger = FakeMetricsLogger()
- private val falsingManager: FalsingManagerFake = FalsingManagerFake()
- private lateinit var view: FooterActionsView
- private lateinit var testableLooper: TestableLooper
- private lateinit var fakeSettings: FakeSettings
- private lateinit var securityFooter: View
- private lateinit var fgsFooter: View
-
- @Before
- fun setUp() {
- // We want to make sure testable resources are always used
- context.ensureTestableResources()
-
- MockitoAnnotations.initMocks(this)
- testableLooper = TestableLooper.get(this)
- fakeSettings = FakeSettings()
-
- whenever(multiUserSwitchControllerFactory.create(any()))
- .thenReturn(multiUserSwitchController)
- whenever(globalActionsDialogProvider.get()).thenReturn(globalActionsDialog)
-
- securityFooter = View(mContext)
- fgsFooter = View(mContext)
-
- whenever(securityFooterController.view).thenReturn(securityFooter)
- whenever(fgsManagerController.view).thenReturn(fgsFooter)
-
- view = inflateView()
-
- controller = constructFooterActionsController(view)
- controller.init()
- ViewUtils.attachView(view)
- // View looper is the testable looper associated with the test
- testableLooper.processAllMessages()
- }
-
- @After
- fun tearDown() {
- if (view.isAttachedToWindow) {
- ViewUtils.detachView(view)
- }
- }
-
- @Test
- fun testInitializesControllers() {
- verify(multiUserSwitchController).init()
- verify(fgsManagerController).init()
- verify(securityFooterController).init()
- }
-
- @Test
- fun testLogPowerMenuClick() {
- controller.visible = true
- falsingManager.setFalseTap(false)
-
- view.findViewById<View>(R.id.pm_lite).performClick()
- // Verify clicks are logged
- verify(uiEventLogger, Mockito.times(1))
- .log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS)
- }
-
- @Test
- fun testSettings() {
- val captor = ArgumentCaptor.forClass(Intent::class.java)
- whenever(deviceProvisionedController.isCurrentUserSetup).thenReturn(true)
- view.findViewById<View>(R.id.settings_button_container).performClick()
-
- verify(activityStarter)
- .startActivity(capture(captor), anyBoolean(), any<ActivityLaunchAnimator.Controller>())
-
- assertThat(captor.value.action).isEqualTo(Settings.ACTION_SETTINGS)
- }
-
- @Test
- fun testSettings_UserNotSetup() {
- whenever(deviceProvisionedController.isCurrentUserSetup).thenReturn(false)
- view.findViewById<View>(R.id.settings_button_container).performClick()
- // Verify Settings wasn't launched.
- verify(activityStarter, never())
- .startActivity(any(), anyBoolean(), any<ActivityLaunchAnimator.Controller>())
- }
-
- @Test
- fun testMultiUserSwitchUpdatedWhenExpansionStarts() {
- // When expansion starts, listening is set to true
- val multiUserSwitch = view.requireViewById<View>(R.id.multi_user_switch)
-
- assertThat(multiUserSwitch.visibility).isNotEqualTo(View.VISIBLE)
-
- whenever(multiUserSwitchController.isMultiUserEnabled).thenReturn(true)
-
- controller.setListening(true)
- testableLooper.processAllMessages()
-
- assertThat(multiUserSwitch.visibility).isEqualTo(View.VISIBLE)
- }
-
- @Test
- fun testMultiUserSwitchUpdatedWhenSettingChanged() {
- // Always listening to setting while View is attached
- testableLooper.processAllMessages()
-
- val multiUserSwitch = view.requireViewById<View>(R.id.multi_user_switch)
- assertThat(multiUserSwitch.visibility).isNotEqualTo(View.VISIBLE)
-
- // The setting is only used as an indicator for whether the view should refresh. The actual
- // value of the setting is ignored; isMultiUserEnabled is the source of truth
- whenever(multiUserSwitchController.isMultiUserEnabled).thenReturn(true)
-
- // Changing the value of USER_SWITCHER_ENABLED should cause the view to update
- fakeSettings.putIntForUser(Settings.Global.USER_SWITCHER_ENABLED, 1, userTracker.userId)
- testableLooper.processAllMessages()
-
- assertThat(multiUserSwitch.visibility).isEqualTo(View.VISIBLE)
- }
-
- @Test
- fun testMultiUserSettingNotListenedAfterDetach() {
- testableLooper.processAllMessages()
-
- val multiUserSwitch = view.requireViewById<View>(R.id.multi_user_switch)
- assertThat(multiUserSwitch.visibility).isNotEqualTo(View.VISIBLE)
-
- ViewUtils.detachView(view)
-
- // The setting is only used as an indicator for whether the view should refresh. The actual
- // value of the setting is ignored; isMultiUserEnabled is the source of truth
- whenever(multiUserSwitchController.isMultiUserEnabled).thenReturn(true)
-
- // Changing the value of USER_SWITCHER_ENABLED should cause the view to update
- fakeSettings.putIntForUser(Settings.Global.USER_SWITCHER_ENABLED, 1, userTracker.userId)
- testableLooper.processAllMessages()
-
- assertThat(multiUserSwitch.visibility).isNotEqualTo(View.VISIBLE)
- }
-
- @Test
- fun testCleanUpGAD() {
- reset(globalActionsDialogProvider)
- // We are creating a new controller, so detach the views from it
- (securityFooter.parent as ViewGroup).removeView(securityFooter)
- (fgsFooter.parent as ViewGroup).removeView(fgsFooter)
-
- whenever(globalActionsDialogProvider.get()).thenReturn(globalActionsDialog)
- val view = inflateView()
- controller = constructFooterActionsController(view)
- controller.init()
- verify(globalActionsDialogProvider, never()).get()
-
- // GAD is constructed during attachment
- ViewUtils.attachView(view)
- testableLooper.processAllMessages()
- verify(globalActionsDialogProvider).get()
-
- ViewUtils.detachView(view)
- testableLooper.processAllMessages()
- verify(globalActionsDialog).destroy()
- }
-
- @Test
- fun testSeparatorVisibility_noneVisible_gone() {
- verify(securityFooterController)
- .setOnVisibilityChangedListener(capture(visibilityChangedCaptor))
- val listener = visibilityChangedCaptor.value
- val separator = controller.securityFootersSeparator
-
- setVisibilities(securityFooterVisible = false, fgsFooterVisible = false, listener)
- assertThat(separator.visibility).isEqualTo(View.GONE)
- }
-
- @Test
- fun testSeparatorVisibility_onlySecurityFooterVisible_gone() {
- verify(securityFooterController)
- .setOnVisibilityChangedListener(capture(visibilityChangedCaptor))
- val listener = visibilityChangedCaptor.value
- val separator = controller.securityFootersSeparator
-
- setVisibilities(securityFooterVisible = true, fgsFooterVisible = false, listener)
- assertThat(separator.visibility).isEqualTo(View.GONE)
- }
-
- @Test
- fun testSeparatorVisibility_onlyFgsFooterVisible_gone() {
- verify(securityFooterController)
- .setOnVisibilityChangedListener(capture(visibilityChangedCaptor))
- val listener = visibilityChangedCaptor.value
- val separator = controller.securityFootersSeparator
-
- setVisibilities(securityFooterVisible = false, fgsFooterVisible = true, listener)
- assertThat(separator.visibility).isEqualTo(View.GONE)
- }
-
- @Test
- fun testSeparatorVisibility_bothVisible_visible() {
- verify(securityFooterController)
- .setOnVisibilityChangedListener(capture(visibilityChangedCaptor))
- val listener = visibilityChangedCaptor.value
- val separator = controller.securityFootersSeparator
-
- setVisibilities(securityFooterVisible = true, fgsFooterVisible = true, listener)
- assertThat(separator.visibility).isEqualTo(View.VISIBLE)
- }
-
- @Test
- fun testFgsFooterCollapsed() {
- verify(securityFooterController)
- .setOnVisibilityChangedListener(capture(visibilityChangedCaptor))
- val listener = visibilityChangedCaptor.value
-
- val booleanCaptor = ArgumentCaptor.forClass(Boolean::class.java)
-
- clearInvocations(fgsManagerController)
- setVisibilities(securityFooterVisible = false, fgsFooterVisible = true, listener)
- verify(fgsManagerController, atLeastOnce()).setCollapsed(capture(booleanCaptor))
- assertThat(booleanCaptor.allValues.last()).isFalse()
-
- clearInvocations(fgsManagerController)
- setVisibilities(securityFooterVisible = true, fgsFooterVisible = true, listener)
- verify(fgsManagerController, atLeastOnce()).setCollapsed(capture(booleanCaptor))
- assertThat(booleanCaptor.allValues.last()).isTrue()
- }
-
- @Test
- fun setExpansion_inSplitShade_alphaFollowsExpansion() {
- enableSplitShade()
-
- controller.setExpansion(0f)
- expect.that(view.alpha).isEqualTo(0f)
-
- controller.setExpansion(0.25f)
- expect.that(view.alpha).isEqualTo(0.25f)
-
- controller.setExpansion(0.5f)
- expect.that(view.alpha).isEqualTo(0.5f)
-
- controller.setExpansion(0.75f)
- expect.that(view.alpha).isEqualTo(0.75f)
-
- controller.setExpansion(1f)
- expect.that(view.alpha).isEqualTo(1f)
- }
-
- @Test
- fun setExpansion_inSplitShade_backgroundAlphaFollowsExpansion_with_0_9_delay() {
- enableSplitShade()
-
- controller.setExpansion(0f)
- expect.that(view.backgroundAlphaFraction).isEqualTo(0f)
-
- controller.setExpansion(0.5f)
- expect.that(view.backgroundAlphaFraction).isEqualTo(0f)
-
- controller.setExpansion(0.9f)
- expect.that(view.backgroundAlphaFraction).isEqualTo(0f)
-
- controller.setExpansion(0.91f)
- expect.that(view.backgroundAlphaFraction).isWithin(FLOAT_TOLERANCE).of(0.1f)
-
- controller.setExpansion(0.95f)
- expect.that(view.backgroundAlphaFraction).isWithin(FLOAT_TOLERANCE).of(0.5f)
-
- controller.setExpansion(1f)
- expect.that(view.backgroundAlphaFraction).isEqualTo(1f)
- }
-
- @Test
- fun setExpansion_inSingleShade_alphaFollowsExpansion_with_0_9_delay() {
- disableSplitShade()
-
- controller.setExpansion(0f)
- expect.that(view.alpha).isEqualTo(0f)
-
- controller.setExpansion(0.5f)
- expect.that(view.alpha).isEqualTo(0f)
-
- controller.setExpansion(0.9f)
- expect.that(view.alpha).isEqualTo(0f)
-
- controller.setExpansion(0.91f)
- expect.that(view.alpha).isWithin(FLOAT_TOLERANCE).of(0.1f)
-
- controller.setExpansion(0.95f)
- expect.that(view.alpha).isWithin(FLOAT_TOLERANCE).of(0.5f)
-
- controller.setExpansion(1f)
- expect.that(view.alpha).isEqualTo(1f)
- }
-
- @Test
- fun setExpansion_inSingleShade_backgroundAlphaAlways1() {
- disableSplitShade()
-
- controller.setExpansion(0f)
- expect.that(view.backgroundAlphaFraction).isEqualTo(1f)
-
- controller.setExpansion(0.5f)
- expect.that(view.backgroundAlphaFraction).isEqualTo(1f)
-
- controller.setExpansion(1f)
- expect.that(view.backgroundAlphaFraction).isEqualTo(1f)
- }
-
- private fun setVisibilities(
- securityFooterVisible: Boolean,
- fgsFooterVisible: Boolean,
- listener: VisibilityChangedDispatcher.OnVisibilityChangedListener
- ) {
- securityFooter.visibility = if (securityFooterVisible) View.VISIBLE else View.GONE
- listener.onVisibilityChanged(securityFooter.visibility)
- fgsFooter.visibility = if (fgsFooterVisible) View.VISIBLE else View.GONE
- listener.onVisibilityChanged(fgsFooter.visibility)
- }
-
- private fun inflateView(): FooterActionsView {
- return LayoutInflater.from(context).inflate(R.layout.footer_actions, null)
- as FooterActionsView
- }
-
- private fun constructFooterActionsController(view: FooterActionsView): FooterActionsController {
- return FooterActionsController(
- view,
- multiUserSwitchControllerFactory,
- activityStarter,
- userManager,
- userTracker,
- userInfoController,
- deviceProvisionedController,
- securityFooterController,
- fgsManagerController,
- falsingManager,
- metricsLogger,
- globalActionsDialogProvider,
- uiEventLogger,
- showPMLiteButton = true,
- fakeSettings,
- Handler(testableLooper.looper),
- configurationController)
- }
-
- private fun enableSplitShade() {
- setSplitShadeEnabled(true)
- }
-
- private fun disableSplitShade() {
- setSplitShadeEnabled(false)
- }
-
- private fun setSplitShadeEnabled(enabled: Boolean) {
- overrideResource(R.bool.config_use_split_notification_shade, enabled)
- configurationController.notifyConfigurationChanged()
- }
-}
-
-private const val FLOAT_TOLERANCE = 0.01f
-
-private val View.backgroundAlphaFraction: Float?
- get() {
- return if (background != null) {
- background.alpha / 255f
- } else {
- null
- }
- }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index aedb9354e6db..ffe918d36d6f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -25,6 +25,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
@@ -32,6 +33,7 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.annotation.Nullable;
import android.app.Fragment;
import android.content.Context;
import android.graphics.Rect;
@@ -42,6 +44,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import androidx.lifecycle.Lifecycle;
import androidx.test.filters.SmallTest;
import com.android.keyguard.BouncerPanelExpansionCalculator;
@@ -50,12 +53,12 @@ import com.android.systemui.SysuiBaseFragmentTest;
import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FakeFeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.media.controls.ui.MediaHost;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.dagger.QSFragmentComponent;
import com.android.systemui.qs.external.TileServiceRequestController;
+import com.android.systemui.qs.footer.ui.binder.FooterActionsViewBinder;
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarState;
@@ -99,6 +102,8 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
@Mock private QSAnimator mQSAnimator;
@Mock private SysuiStatusBarStateController mStatusBarStateController;
@Mock private QSSquishinessController mSquishinessController;
+ @Mock private FooterActionsViewModel mFooterActionsViewModel;
+ @Mock private FooterActionsViewModel.Factory mFooterActionsViewModelFactory;
private View mQsFragmentView;
public QSFragmentTest() {
@@ -245,7 +250,8 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
fragment.setQsExpansion(expansion, panelExpansionFraction, proposedTranslation,
squishinessFraction);
- verify(mQSFooterActionController).setExpansion(panelExpansionFraction);
+ verify(mFooterActionsViewModel).onQuickSettingsExpansionChanged(
+ panelExpansionFraction, /* isInSplitShade= */ true);
}
@Test
@@ -262,7 +268,8 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
fragment.setQsExpansion(expansion, panelExpansionFraction, proposedTranslation,
squishinessFraction);
- verify(mQSFooterActionController).setExpansion(expansion);
+ verify(mFooterActionsViewModel).onQuickSettingsExpansionChanged(
+ expansion, /* isInSplitShade= */ false);
}
@Test
@@ -379,6 +386,13 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
assertThat(mQsFragmentView.getTranslationY()).isEqualTo(0);
}
+ private Lifecycle.State getListeningAndVisibilityLifecycleState() {
+ return getFragment()
+ .getListeningAndVisibilityLifecycleOwner()
+ .getLifecycle()
+ .getCurrentState();
+ }
+
@Test
public void setListeningFalse_notVisible() {
QSFragment fragment = resumeAndGetFragment();
@@ -387,7 +401,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
fragment.setListening(false);
verify(mQSContainerImplController).setListening(false);
- verify(mQSFooterActionController).setListening(false);
+ assertThat(getListeningAndVisibilityLifecycleState()).isEqualTo(Lifecycle.State.CREATED);
verify(mQSPanelController).setListening(eq(false), anyBoolean());
}
@@ -399,7 +413,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
fragment.setListening(true);
verify(mQSContainerImplController).setListening(false);
- verify(mQSFooterActionController).setListening(false);
+ assertThat(getListeningAndVisibilityLifecycleState()).isEqualTo(Lifecycle.State.STARTED);
verify(mQSPanelController).setListening(eq(false), anyBoolean());
}
@@ -411,7 +425,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
fragment.setListening(false);
verify(mQSContainerImplController).setListening(false);
- verify(mQSFooterActionController).setListening(false);
+ assertThat(getListeningAndVisibilityLifecycleState()).isEqualTo(Lifecycle.State.CREATED);
verify(mQSPanelController).setListening(eq(false), anyBoolean());
}
@@ -423,7 +437,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
fragment.setListening(true);
verify(mQSContainerImplController).setListening(true);
- verify(mQSFooterActionController).setListening(true);
+ assertThat(getListeningAndVisibilityLifecycleState()).isEqualTo(Lifecycle.State.RESUMED);
verify(mQSPanelController).setListening(eq(true), anyBoolean());
}
@@ -480,7 +494,6 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
setUpOther();
FakeFeatureFlags featureFlags = new FakeFeatureFlags();
- featureFlags.set(Flags.NEW_FOOTER_ACTIONS, false);
return new QSFragment(
new RemoteInputQuickSettingsDisabler(
context, commandQueue, mock(ConfigurationController.class)),
@@ -495,8 +508,8 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
mFalsingManager,
mock(DumpManager.class),
featureFlags,
- mock(NewFooterActionsController.class),
- mock(FooterActionsViewModel.Factory.class));
+ mock(FooterActionsController.class),
+ mFooterActionsViewModelFactory);
}
private void setUpOther() {
@@ -505,6 +518,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
when(mQSContainerImplController.getView()).thenReturn(mContainer);
when(mQSPanelController.getTileLayout()).thenReturn(mQQsTileLayout);
when(mQuickQSPanelController.getTileLayout()).thenReturn(mQsTileLayout);
+ when(mFooterActionsViewModelFactory.create(any())).thenReturn(mFooterActionsViewModel);
}
private void setUpMedia() {
@@ -519,15 +533,40 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
.thenReturn(mQSPanelScrollView);
when(mQsFragmentView.findViewById(R.id.header)).thenReturn(mHeader);
when(mQsFragmentView.findViewById(android.R.id.edit)).thenReturn(new View(mContext));
+ when(mQsFragmentView.findViewById(R.id.qs_footer_actions)).thenAnswer(
+ invocation -> FooterActionsViewBinder.create(mContext));
}
private void setUpInflater() {
+ LayoutInflater realInflater = LayoutInflater.from(mContext);
+
when(mLayoutInflater.cloneInContext(any(Context.class))).thenReturn(mLayoutInflater);
- when(mLayoutInflater.inflate(anyInt(), any(ViewGroup.class), anyBoolean()))
- .thenReturn(mQsFragmentView);
+ when(mLayoutInflater.inflate(anyInt(), nullable(ViewGroup.class), anyBoolean()))
+ .thenAnswer((invocation) -> inflate(realInflater, (int) invocation.getArgument(0),
+ (ViewGroup) invocation.getArgument(1),
+ (boolean) invocation.getArgument(2)));
+ when(mLayoutInflater.inflate(anyInt(), nullable(ViewGroup.class)))
+ .thenAnswer((invocation) -> inflate(realInflater, (int) invocation.getArgument(0),
+ (ViewGroup) invocation.getArgument(1)));
mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE, mLayoutInflater);
}
+ private View inflate(LayoutInflater realInflater, int layoutRes, @Nullable ViewGroup root) {
+ return inflate(realInflater, layoutRes, root, root != null);
+ }
+
+ private View inflate(LayoutInflater realInflater, int layoutRes, @Nullable ViewGroup root,
+ boolean attachToRoot) {
+ if (layoutRes == R.layout.footer_actions
+ || layoutRes == R.layout.footer_actions_text_button
+ || layoutRes == R.layout.footer_actions_number_button
+ || layoutRes == R.layout.footer_actions_icon_button) {
+ return realInflater.inflate(layoutRes, root, attachToRoot);
+ }
+
+ return mQsFragmentView;
+ }
+
private void setupQsComponent() {
when(mQsComponentFactory.create(any(QSFragment.class))).thenReturn(mQsFragmentComponent);
when(mQsFragmentComponent.getQSPanelController()).thenReturn(mQSPanelController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
index 906c20b1d032..c656d6dd1a35 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
@@ -17,23 +17,24 @@ package com.android.systemui.qs;
import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;
import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
+import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.annotation.IdRes;
import android.app.AlertDialog;
import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.DialogInterface;
-import android.content.Intent;
import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.VectorDrawable;
@@ -42,27 +43,27 @@ import android.os.Looper;
import android.provider.Settings;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
-import android.testing.LayoutInflaterBuilder;
-import android.testing.TestableImageView;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
-import android.testing.ViewUtils;
import android.text.SpannableStringBuilder;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
import android.widget.TextView;
+import androidx.annotation.Nullable;
+
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.DialogLaunchAnimator;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.common.shared.model.Icon;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig;
+import com.android.systemui.security.data.model.SecurityModel;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.SecurityController;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -71,8 +72,6 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
-import java.util.concurrent.atomic.AtomicInteger;
-
/*
* Compile and run the whole SystemUI test suite:
runtest --path frameworks/base/packages/SystemUI/tests
@@ -96,11 +95,6 @@ public class QSSecurityFooterTest extends SysuiTestCase {
new ComponentName("TestDPC", "Test");
private static final int DEFAULT_ICON_ID = R.drawable.ic_info_outline;
- private ViewGroup mRootView;
- private ViewGroup mSecurityFooterView;
- private TextView mFooterText;
- private TestableImageView mPrimaryFooterIcon;
- private QSSecurityFooter mFooter;
private QSSecurityFooterUtils mFooterUtils;
@Mock
private SecurityController mSecurityController;
@@ -122,58 +116,53 @@ public class QSSecurityFooterTest extends SysuiTestCase {
Looper looper = mTestableLooper.getLooper();
Handler mainHandler = new Handler(looper);
when(mUserTracker.getUserInfo()).thenReturn(mock(UserInfo.class));
- mSecurityFooterView = (ViewGroup) new LayoutInflaterBuilder(mContext)
- .replace("ImageView", TestableImageView.class)
- .build().inflate(R.layout.quick_settings_security_footer, null, false);
mFooterUtils = new QSSecurityFooterUtils(getContext(),
getContext().getSystemService(DevicePolicyManager.class), mUserTracker,
mainHandler, mActivityStarter, mSecurityController, looper, mDialogLaunchAnimator);
- mFooter = new QSSecurityFooter(mSecurityFooterView, mainHandler, mSecurityController,
- looper, mBroadcastDispatcher, mFooterUtils);
- mFooterText = mSecurityFooterView.findViewById(R.id.footer_text);
- mPrimaryFooterIcon = mSecurityFooterView.findViewById(R.id.primary_footer_icon);
when(mSecurityController.getDeviceOwnerComponentOnAnyUser())
.thenReturn(DEVICE_OWNER_COMPONENT);
when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
.thenReturn(DEVICE_OWNER_TYPE_DEFAULT);
+ }
- // mSecurityFooterView must have a ViewGroup parent so that
- // DialogLaunchAnimator.Controller.fromView() does not return null.
- mRootView = new FrameLayout(mContext);
- mRootView.addView(mSecurityFooterView);
- ViewUtils.attachView(mRootView);
+ @Nullable
+ private SecurityButtonConfig getButtonConfig() {
+ SecurityModel securityModel = SecurityModel.create(mSecurityController);
+ return mFooterUtils.getButtonConfig(securityModel);
+ }
+
+ private void assertIsDefaultIcon(Icon icon) {
+ assertIsIconResource(icon, DEFAULT_ICON_ID);
+ }
- mFooter.init();
+ private void assertIsIconResource(Icon icon, @IdRes int res) {
+ assertThat(icon).isInstanceOf(Icon.Resource.class);
+ assertEquals(res, ((Icon.Resource) icon).getRes());
}
- @After
- public void tearDown() {
- ViewUtils.detachView(mRootView);
+ private void assertIsIconDrawable(Icon icon, Drawable drawable) {
+ assertThat(icon).isInstanceOf(Icon.Loaded.class);
+ assertEquals(drawable, ((Icon.Loaded) icon).getDrawable());
}
@Test
public void testUnmanaged() {
when(mSecurityController.isDeviceManaged()).thenReturn(false);
when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(false);
- mFooter.refreshState();
-
- TestableLooper.get(this).processAllMessages();
- assertEquals(View.GONE, mSecurityFooterView.getVisibility());
+ assertNull(getButtonConfig());
}
@Test
public void testManagedNoOwnerName() {
when(mSecurityController.isDeviceManaged()).thenReturn(true);
when(mSecurityController.getDeviceOwnerOrganizationName()).thenReturn(null);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
assertEquals(mContext.getString(R.string.quick_settings_disclosure_management),
- mFooterText.getText());
- assertEquals(View.VISIBLE, mSecurityFooterView.getVisibility());
- assertEquals(View.VISIBLE, mPrimaryFooterIcon.getVisibility());
- assertEquals(DEFAULT_ICON_ID, mPrimaryFooterIcon.getLastImageResource());
+ buttonConfig.getText());
+ assertIsDefaultIcon(buttonConfig.getIcon());
}
@Test
@@ -181,15 +170,13 @@ public class QSSecurityFooterTest extends SysuiTestCase {
when(mSecurityController.isDeviceManaged()).thenReturn(true);
when(mSecurityController.getDeviceOwnerOrganizationName())
.thenReturn(MANAGING_ORGANIZATION);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_management,
- MANAGING_ORGANIZATION),
- mFooterText.getText());
- assertEquals(View.VISIBLE, mSecurityFooterView.getVisibility());
- assertEquals(View.VISIBLE, mPrimaryFooterIcon.getVisibility());
- assertEquals(DEFAULT_ICON_ID, mPrimaryFooterIcon.getLastImageResource());
+ MANAGING_ORGANIZATION),
+ buttonConfig.getText());
+ assertIsDefaultIcon(buttonConfig.getIcon());
}
@Test
@@ -200,15 +187,13 @@ public class QSSecurityFooterTest extends SysuiTestCase {
when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
.thenReturn(DEVICE_OWNER_TYPE_FINANCED);
- mFooter.refreshState();
-
- TestableLooper.get(this).processAllMessages();
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
assertEquals(mContext.getString(
- R.string.quick_settings_financed_disclosure_named_management,
- MANAGING_ORGANIZATION), mFooterText.getText());
- assertEquals(View.VISIBLE, mSecurityFooterView.getVisibility());
- assertEquals(View.VISIBLE, mPrimaryFooterIcon.getVisibility());
- assertEquals(DEFAULT_ICON_ID, mPrimaryFooterIcon.getLastImageResource());
+ R.string.quick_settings_financed_disclosure_named_management,
+ MANAGING_ORGANIZATION),
+ buttonConfig.getText());
+ assertIsDefaultIcon(buttonConfig.getIcon());
}
@Test
@@ -220,21 +205,16 @@ public class QSSecurityFooterTest extends SysuiTestCase {
when(mUserTracker.getUserInfo()).thenReturn(mockUserInfo);
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_DEMO_MODE, 1);
- mFooter.refreshState();
-
- TestableLooper.get(this).processAllMessages();
- assertEquals(View.GONE, mSecurityFooterView.getVisibility());
+ assertNull(getButtonConfig());
}
@Test
public void testUntappableView_profileOwnerOfOrgOwnedDevice() {
when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
- mFooter.refreshState();
-
- TestableLooper.get(this).processAllMessages();
- assertFalse(mSecurityFooterView.isClickable());
- assertEquals(View.GONE, mSecurityFooterView.findViewById(R.id.footer_icon).getVisibility());
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
+ assertFalse(buttonConfig.isClickable());
}
@Test
@@ -244,12 +224,9 @@ public class QSSecurityFooterTest extends SysuiTestCase {
when(mSecurityController.isWorkProfileOn()).thenReturn(true);
when(mSecurityController.hasWorkProfile()).thenReturn(true);
- mFooter.refreshState();
-
- TestableLooper.get(this).processAllMessages();
- assertTrue(mSecurityFooterView.isClickable());
- assertEquals(View.VISIBLE,
- mSecurityFooterView.findViewById(R.id.footer_icon).getVisibility());
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
+ assertTrue(buttonConfig.isClickable());
}
@Test
@@ -258,35 +235,31 @@ public class QSSecurityFooterTest extends SysuiTestCase {
when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
when(mSecurityController.isWorkProfileOn()).thenReturn(false);
- mFooter.refreshState();
-
- TestableLooper.get(this).processAllMessages();
- assertFalse(mSecurityFooterView.isClickable());
- assertEquals(View.GONE, mSecurityFooterView.findViewById(R.id.footer_icon).getVisibility());
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
+ assertFalse(buttonConfig.isClickable());
}
@Test
public void testNetworkLoggingEnabled_deviceOwner() {
when(mSecurityController.isDeviceManaged()).thenReturn(true);
when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
- mFooterText.getText());
- assertEquals(View.VISIBLE, mPrimaryFooterIcon.getVisibility());
- assertEquals(DEFAULT_ICON_ID, mPrimaryFooterIcon.getLastImageResource());
+ buttonConfig.getText());
+ assertIsDefaultIcon(buttonConfig.getIcon());
// Same situation, but with organization name set
when(mSecurityController.getDeviceOwnerOrganizationName())
.thenReturn(MANAGING_ORGANIZATION);
- mFooter.refreshState();
-
- TestableLooper.get(this).processAllMessages();
+ buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
assertEquals(mContext.getString(
- R.string.quick_settings_disclosure_named_management_monitoring,
- MANAGING_ORGANIZATION),
- mFooterText.getText());
+ R.string.quick_settings_disclosure_named_management_monitoring,
+ MANAGING_ORGANIZATION),
+ buttonConfig.getText());
}
@Test
@@ -294,12 +267,12 @@ public class QSSecurityFooterTest extends SysuiTestCase {
when(mSecurityController.hasWorkProfile()).thenReturn(true);
when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
when(mSecurityController.isWorkProfileOn()).thenReturn(true);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
assertEquals(mContext.getString(
- R.string.quick_settings_disclosure_managed_profile_network_activity),
- mFooterText.getText());
+ R.string.quick_settings_disclosure_managed_profile_network_activity),
+ buttonConfig.getText());
}
@Test
@@ -307,21 +280,19 @@ public class QSSecurityFooterTest extends SysuiTestCase {
when(mSecurityController.hasWorkProfile()).thenReturn(true);
when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
when(mSecurityController.isWorkProfileOn()).thenReturn(false);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
- assertEquals("", mFooterText.getText());
+ assertNull(getButtonConfig());
}
@Test
public void testManagedCACertsInstalled() {
when(mSecurityController.isDeviceManaged()).thenReturn(true);
when(mSecurityController.hasCACertInCurrentUser()).thenReturn(true);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
- mFooterText.getText());
+ buttonConfig.getText());
}
@Test
@@ -329,25 +300,23 @@ public class QSSecurityFooterTest extends SysuiTestCase {
when(mSecurityController.isDeviceManaged()).thenReturn(true);
when(mSecurityController.isVpnEnabled()).thenReturn(true);
when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_named_vpn,
- VPN_PACKAGE),
- mFooterText.getText());
- assertEquals(View.VISIBLE, mPrimaryFooterIcon.getVisibility());
- assertEquals(R.drawable.stat_sys_vpn_ic, mPrimaryFooterIcon.getLastImageResource());
+ VPN_PACKAGE),
+ buttonConfig.getText());
+ assertIsIconResource(buttonConfig.getIcon(), R.drawable.stat_sys_vpn_ic);
// Same situation, but with organization name set
when(mSecurityController.getDeviceOwnerOrganizationName())
.thenReturn(MANAGING_ORGANIZATION);
- mFooter.refreshState();
-
- TestableLooper.get(this).processAllMessages();
+ buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
assertEquals(mContext.getString(
- R.string.quick_settings_disclosure_named_management_named_vpn,
- MANAGING_ORGANIZATION, VPN_PACKAGE),
- mFooterText.getText());
+ R.string.quick_settings_disclosure_named_management_named_vpn,
+ MANAGING_ORGANIZATION, VPN_PACKAGE),
+ buttonConfig.getText());
}
@Test
@@ -356,23 +325,21 @@ public class QSSecurityFooterTest extends SysuiTestCase {
when(mSecurityController.isVpnEnabled()).thenReturn(true);
when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_vpns),
- mFooterText.getText());
- assertEquals(View.VISIBLE, mPrimaryFooterIcon.getVisibility());
- assertEquals(R.drawable.stat_sys_vpn_ic, mPrimaryFooterIcon.getLastImageResource());
+ buttonConfig.getText());
+ assertIsIconResource(buttonConfig.getIcon(), R.drawable.stat_sys_vpn_ic);
// Same situation, but with organization name set
when(mSecurityController.getDeviceOwnerOrganizationName())
.thenReturn(MANAGING_ORGANIZATION);
- mFooter.refreshState();
-
- TestableLooper.get(this).processAllMessages();
+ buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_management_vpns,
MANAGING_ORGANIZATION),
- mFooterText.getText());
+ buttonConfig.getText());
}
@Test
@@ -381,13 +348,12 @@ public class QSSecurityFooterTest extends SysuiTestCase {
when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
when(mSecurityController.isVpnEnabled()).thenReturn(true);
when(mSecurityController.getPrimaryVpnName()).thenReturn("VPN Test App");
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
- assertEquals(View.VISIBLE, mPrimaryFooterIcon.getVisibility());
- assertEquals(R.drawable.stat_sys_vpn_ic, mPrimaryFooterIcon.getLastImageResource());
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
+ assertIsIconResource(buttonConfig.getIcon(), R.drawable.stat_sys_vpn_ic);
assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
- mFooterText.getText());
+ buttonConfig.getText());
}
@Test
@@ -395,24 +361,23 @@ public class QSSecurityFooterTest extends SysuiTestCase {
when(mSecurityController.isDeviceManaged()).thenReturn(false);
when(mSecurityController.hasCACertInWorkProfile()).thenReturn(true);
when(mSecurityController.isWorkProfileOn()).thenReturn(true);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
- assertEquals(DEFAULT_ICON_ID, mPrimaryFooterIcon.getLastImageResource());
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
+ assertIsDefaultIcon(buttonConfig.getIcon());
assertEquals(mContext.getString(
R.string.quick_settings_disclosure_managed_profile_monitoring),
- mFooterText.getText());
+ buttonConfig.getText());
// Same situation, but with organization name set
when(mSecurityController.getWorkProfileOrganizationName())
.thenReturn(MANAGING_ORGANIZATION);
- mFooter.refreshState();
-
- TestableLooper.get(this).processAllMessages();
+ buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
assertEquals(mContext.getString(
R.string.quick_settings_disclosure_named_managed_profile_monitoring,
MANAGING_ORGANIZATION),
- mFooterText.getText());
+ buttonConfig.getText());
}
@Test
@@ -420,22 +385,20 @@ public class QSSecurityFooterTest extends SysuiTestCase {
when(mSecurityController.isDeviceManaged()).thenReturn(false);
when(mSecurityController.hasCACertInWorkProfile()).thenReturn(true);
when(mSecurityController.isWorkProfileOn()).thenReturn(false);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
- assertEquals("", mFooterText.getText());
+ assertNull(getButtonConfig());
}
@Test
public void testCACertsInstalled() {
when(mSecurityController.isDeviceManaged()).thenReturn(false);
when(mSecurityController.hasCACertInCurrentUser()).thenReturn(true);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
- assertEquals(DEFAULT_ICON_ID, mPrimaryFooterIcon.getLastImageResource());
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
+ assertIsDefaultIcon(buttonConfig.getIcon());
assertEquals(mContext.getString(R.string.quick_settings_disclosure_monitoring),
- mFooterText.getText());
+ buttonConfig.getText());
}
@Test
@@ -443,12 +406,12 @@ public class QSSecurityFooterTest extends SysuiTestCase {
when(mSecurityController.isVpnEnabled()).thenReturn(true);
when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
- assertEquals(R.drawable.stat_sys_vpn_ic, mPrimaryFooterIcon.getLastImageResource());
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
+ assertIsIconResource(buttonConfig.getIcon(), R.drawable.stat_sys_vpn_ic);
assertEquals(mContext.getString(R.string.quick_settings_disclosure_vpns),
- mFooterText.getText());
+ buttonConfig.getText());
}
@Test
@@ -456,14 +419,14 @@ public class QSSecurityFooterTest extends SysuiTestCase {
when(mSecurityController.isVpnEnabled()).thenReturn(true);
when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
when(mSecurityController.isWorkProfileOn()).thenReturn(true);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
- assertEquals(R.drawable.stat_sys_vpn_ic, mPrimaryFooterIcon.getLastImageResource());
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
+ assertIsIconResource(buttonConfig.getIcon(), R.drawable.stat_sys_vpn_ic);
assertEquals(mContext.getString(
R.string.quick_settings_disclosure_managed_profile_named_vpn,
VPN_PACKAGE_2),
- mFooterText.getText());
+ buttonConfig.getText());
}
@Test
@@ -471,22 +434,19 @@ public class QSSecurityFooterTest extends SysuiTestCase {
when(mSecurityController.isVpnEnabled()).thenReturn(true);
when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
when(mSecurityController.isWorkProfileOn()).thenReturn(false);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
- assertEquals("", mFooterText.getText());
+ assertNull(getButtonConfig());
}
@Test
public void testProfileOwnerOfOrganizationOwnedDeviceNoName() {
when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
-
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
assertEquals(mContext.getString(
R.string.quick_settings_disclosure_management),
- mFooterText.getText());
+ buttonConfig.getText());
}
@Test
@@ -495,35 +455,33 @@ public class QSSecurityFooterTest extends SysuiTestCase {
when(mSecurityController.getWorkProfileOrganizationName())
.thenReturn(MANAGING_ORGANIZATION);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
-
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
assertEquals(mContext.getString(
R.string.quick_settings_disclosure_named_management,
MANAGING_ORGANIZATION),
- mFooterText.getText());
+ buttonConfig.getText());
}
@Test
public void testVpnEnabled() {
when(mSecurityController.isVpnEnabled()).thenReturn(true);
when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
- assertEquals(R.drawable.stat_sys_vpn_ic, mPrimaryFooterIcon.getLastImageResource());
+ SecurityButtonConfig buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
+ assertIsIconResource(buttonConfig.getIcon(), R.drawable.stat_sys_vpn_ic);
assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_vpn,
VPN_PACKAGE),
- mFooterText.getText());
+ buttonConfig.getText());
when(mSecurityController.hasWorkProfile()).thenReturn(true);
- mFooter.refreshState();
-
- TestableLooper.get(this).processAllMessages();
+ buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
assertEquals(mContext.getString(
R.string.quick_settings_disclosure_personal_profile_named_vpn,
VPN_PACKAGE),
- mFooterText.getText());
+ buttonConfig.getText());
}
@Test
@@ -687,19 +645,6 @@ public class QSSecurityFooterTest extends SysuiTestCase {
}
@Test
- public void testNoClickWhenGone() {
- mFooter.refreshState();
-
- TestableLooper.get(this).processAllMessages();
-
- assertFalse(mFooter.hasFooter());
- mFooter.onClick(mFooter.getView());
-
- // Proxy for dialog being created
- verify(mDialogLaunchAnimator, never()).showFromView(any(), any());
- }
-
- @Test
public void testParentalControls() {
// Make sure the security footer is visible, so that the images are updated.
when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
@@ -707,29 +652,26 @@ public class QSSecurityFooterTest extends SysuiTestCase {
// We use the default icon when there is no admin icon.
when(mSecurityController.getIcon(any())).thenReturn(null);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
+ SecurityButtonConfig buttonConfig = getButtonConfig();
assertEquals(mContext.getString(R.string.quick_settings_disclosure_parental_controls),
- mFooterText.getText());
- assertEquals(DEFAULT_ICON_ID, mPrimaryFooterIcon.getLastImageResource());
+ buttonConfig.getText());
+ assertIsDefaultIcon(buttonConfig.getIcon());
Drawable testDrawable = new VectorDrawable();
when(mSecurityController.getIcon(any())).thenReturn(testDrawable);
assertNotNull(mSecurityController.getIcon(null));
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
-
+ buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
assertEquals(mContext.getString(R.string.quick_settings_disclosure_parental_controls),
- mFooterText.getText());
- assertEquals(View.VISIBLE, mPrimaryFooterIcon.getVisibility());
- assertEquals(testDrawable, mPrimaryFooterIcon.getDrawable());
+ buttonConfig.getText());
+ assertIsIconDrawable(buttonConfig.getIcon(), testDrawable);
// Ensure the primary icon is back to default after parental controls are gone
when(mSecurityController.isParentalControlsEnabled()).thenReturn(false);
- mFooter.refreshState();
- TestableLooper.get(this).processAllMessages();
- assertEquals(DEFAULT_ICON_ID, mPrimaryFooterIcon.getLastImageResource());
+ buttonConfig = getButtonConfig();
+ assertNotNull(buttonConfig);
+ assertIsDefaultIcon(buttonConfig.getIcon());
}
@Test
@@ -743,16 +685,6 @@ public class QSSecurityFooterTest extends SysuiTestCase {
}
@Test
- public void testDialogUsesDialogLauncher() {
- when(mSecurityController.isDeviceManaged()).thenReturn(true);
- mFooter.onClick(mSecurityFooterView);
-
- mTestableLooper.processAllMessages();
-
- verify(mDialogLaunchAnimator).show(any(), any());
- }
-
- @Test
public void testCreateDialogViewForFinancedDevice() {
when(mSecurityController.isDeviceManaged()).thenReturn(true);
when(mSecurityController.getDeviceOwnerOrganizationName())
@@ -782,7 +714,10 @@ public class QSSecurityFooterTest extends SysuiTestCase {
when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
.thenReturn(DEVICE_OWNER_TYPE_FINANCED);
- mFooter.showDeviceMonitoringDialog();
+ Expandable expandable = mock(Expandable.class);
+ when(expandable.dialogLaunchController(any())).thenReturn(
+ mock(DialogLaunchAnimator.Controller.class));
+ mFooterUtils.showDeviceMonitoringDialog(getContext(), expandable);
ArgumentCaptor<AlertDialog> dialogCaptor = ArgumentCaptor.forClass(AlertDialog.class);
mTestableLooper.processAllMessages();
@@ -797,47 +732,6 @@ public class QSSecurityFooterTest extends SysuiTestCase {
dialog.dismiss();
}
- @Test
- public void testVisibilityListener() {
- final AtomicInteger lastVisibility = new AtomicInteger(-1);
- VisibilityChangedDispatcher.OnVisibilityChangedListener listener = lastVisibility::set;
-
- mFooter.setOnVisibilityChangedListener(listener);
-
- when(mSecurityController.isDeviceManaged()).thenReturn(true);
- mFooter.refreshState();
- mTestableLooper.processAllMessages();
- assertEquals(View.VISIBLE, lastVisibility.get());
-
- when(mSecurityController.isDeviceManaged()).thenReturn(false);
- mFooter.refreshState();
- mTestableLooper.processAllMessages();
- assertEquals(View.GONE, lastVisibility.get());
- }
-
- @Test
- public void testBroadcastShowsDialog() {
- // Setup dialog content
- when(mSecurityController.isDeviceManaged()).thenReturn(true);
- when(mSecurityController.getDeviceOwnerOrganizationName())
- .thenReturn(MANAGING_ORGANIZATION);
- when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
- .thenReturn(DEVICE_OWNER_TYPE_FINANCED);
-
- ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class);
- verify(mBroadcastDispatcher).registerReceiverWithHandler(captor.capture(), any(), any(),
- any());
-
- // Pretend view is not attached anymore.
- mRootView.removeView(mSecurityFooterView);
- captor.getValue().onReceive(mContext,
- new Intent(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG));
- mTestableLooper.processAllMessages();
-
- assertTrue(mFooterUtils.getDialog().isShowing());
- mFooterUtils.getDialog().dismiss();
- }
-
private CharSequence addLink(CharSequence description) {
final SpannableStringBuilder message = new SpannableStringBuilder();
message.append(description);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt
index 47afa70fa84b..01411c9e7f04 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt
@@ -385,4 +385,86 @@ class FooterActionsViewModelTest : SysuiTestCase() {
underTest.onVisibilityChangeRequested(visible = true)
assertThat(underTest.isVisible.value).isTrue()
}
+
+ @Test
+ fun alpha_inSplitShade_followsExpansion() {
+ val underTest = utils.footerActionsViewModel()
+
+ underTest.onQuickSettingsExpansionChanged(0f, isInSplitShade = true)
+ assertThat(underTest.alpha.value).isEqualTo(0f)
+
+ underTest.onQuickSettingsExpansionChanged(0.25f, isInSplitShade = true)
+ assertThat(underTest.alpha.value).isEqualTo(0.25f)
+
+ underTest.onQuickSettingsExpansionChanged(0.5f, isInSplitShade = true)
+ assertThat(underTest.alpha.value).isEqualTo(0.5f)
+
+ underTest.onQuickSettingsExpansionChanged(0.75f, isInSplitShade = true)
+ assertThat(underTest.alpha.value).isEqualTo(0.75f)
+
+ underTest.onQuickSettingsExpansionChanged(1f, isInSplitShade = true)
+ assertThat(underTest.alpha.value).isEqualTo(1f)
+ }
+
+ @Test
+ fun backgroundAlpha_inSplitShade_followsExpansion_with_0_99_delay() {
+ val underTest = utils.footerActionsViewModel()
+ val floatTolerance = 0.01f
+
+ underTest.onQuickSettingsExpansionChanged(0f, isInSplitShade = true)
+ assertThat(underTest.backgroundAlpha.value).isEqualTo(0f)
+
+ underTest.onQuickSettingsExpansionChanged(0.5f, isInSplitShade = true)
+ assertThat(underTest.backgroundAlpha.value).isEqualTo(0f)
+
+ underTest.onQuickSettingsExpansionChanged(0.9f, isInSplitShade = true)
+ assertThat(underTest.backgroundAlpha.value).isEqualTo(0f)
+
+ underTest.onQuickSettingsExpansionChanged(0.991f, isInSplitShade = true)
+ assertThat(underTest.backgroundAlpha.value).isWithin(floatTolerance).of(0.1f)
+
+ underTest.onQuickSettingsExpansionChanged(0.995f, isInSplitShade = true)
+ assertThat(underTest.backgroundAlpha.value).isWithin(floatTolerance).of(0.5f)
+
+ underTest.onQuickSettingsExpansionChanged(1f, isInSplitShade = true)
+ assertThat(underTest.backgroundAlpha.value).isEqualTo(1f)
+ }
+
+ @Test
+ fun alpha_inSingleShade_followsExpansion_with_0_9_delay() {
+ val underTest = utils.footerActionsViewModel()
+ val floatTolerance = 0.01f
+
+ underTest.onQuickSettingsExpansionChanged(0f, isInSplitShade = false)
+ assertThat(underTest.alpha.value).isEqualTo(0f)
+
+ underTest.onQuickSettingsExpansionChanged(0.5f, isInSplitShade = false)
+ assertThat(underTest.alpha.value).isEqualTo(0f)
+
+ underTest.onQuickSettingsExpansionChanged(0.9f, isInSplitShade = false)
+ assertThat(underTest.alpha.value).isEqualTo(0f)
+
+ underTest.onQuickSettingsExpansionChanged(0.91f, isInSplitShade = false)
+ assertThat(underTest.alpha.value).isWithin(floatTolerance).of(0.1f)
+
+ underTest.onQuickSettingsExpansionChanged(0.95f, isInSplitShade = false)
+ assertThat(underTest.alpha.value).isWithin(floatTolerance).of(0.5f)
+
+ underTest.onQuickSettingsExpansionChanged(1f, isInSplitShade = false)
+ assertThat(underTest.alpha.value).isEqualTo(1f)
+ }
+
+ @Test
+ fun backgroundAlpha_inSingleShade_always1() {
+ val underTest = utils.footerActionsViewModel()
+
+ underTest.onQuickSettingsExpansionChanged(0f, isInSplitShade = false)
+ assertThat(underTest.backgroundAlpha.value).isEqualTo(1f)
+
+ underTest.onQuickSettingsExpansionChanged(0.5f, isInSplitShade = false)
+ assertThat(underTest.backgroundAlpha.value).isEqualTo(1f)
+
+ underTest.onQuickSettingsExpansionChanged(1f, isInSplitShade = false)
+ assertThat(underTest.backgroundAlpha.value).isEqualTo(1f)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index 56a840cae267..0302dade0a8c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -173,6 +173,7 @@ import com.android.wm.shell.animation.FlingAnimationUtils;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -611,6 +612,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
}
@Test
+ @Ignore("b/261472011 - Test appears inconsistent across environments")
public void getVerticalSpaceForLockscreenNotifications_useLockIconBottomPadding_returnsSpaceAvailable() {
setBottomPadding(/* stackScrollLayoutBottom= */ 180,
/* lockIconPadding= */ 20,
@@ -622,6 +624,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
}
@Test
+ @Ignore("b/261472011 - Test appears inconsistent across environments")
public void getVerticalSpaceForLockscreenNotifications_useIndicationBottomPadding_returnsSpaceAvailable() {
setBottomPadding(/* stackScrollLayoutBottom= */ 180,
/* lockIconPadding= */ 0,
@@ -633,6 +636,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
}
@Test
+ @Ignore("b/261472011 - Test appears inconsistent across environments")
public void getVerticalSpaceForLockscreenNotifications_useAmbientBottomPadding_returnsSpaceAvailable() {
setBottomPadding(/* stackScrollLayoutBottom= */ 180,
/* lockIconPadding= */ 0,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java
index 17d81c8338cb..7693fee0a1c4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.util.condition;
+package com.android.systemui.shared.condition;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@@ -68,13 +68,15 @@ public class ConditionMonitorTest extends SysuiTestCase {
mConditionMonitor = new Monitor(mExecutor);
}
- public Monitor.Subscription.Builder getDefaultBuilder(Monitor.Callback callback) {
+ public Monitor.Subscription.Builder getDefaultBuilder(
+ Monitor.Callback callback) {
return new Monitor.Subscription.Builder(callback)
.addConditions(mConditions);
}
private Condition createMockCondition() {
- final Condition condition = Mockito.mock(Condition.class);
+ final Condition condition = Mockito.mock(
+ Condition.class);
when(condition.isConditionSet()).thenReturn(true);
return condition;
}
@@ -83,11 +85,14 @@ public class ConditionMonitorTest extends SysuiTestCase {
public void testOverridingCondition() {
final Condition overridingCondition = createMockCondition();
final Condition regularCondition = createMockCondition();
- final Monitor.Callback callback = Mockito.mock(Monitor.Callback.class);
+ final Monitor.Callback callback = Mockito.mock(
+ Monitor.Callback.class);
- final Monitor.Callback referenceCallback = Mockito.mock(Monitor.Callback.class);
+ final Monitor.Callback referenceCallback = Mockito.mock(
+ Monitor.Callback.class);
- final Monitor monitor = new Monitor(mExecutor);
+ final Monitor
+ monitor = new Monitor(mExecutor);
monitor.addSubscription(getDefaultBuilder(callback)
.addCondition(overridingCondition)
@@ -136,9 +141,11 @@ public class ConditionMonitorTest extends SysuiTestCase {
final Condition overridingCondition = createMockCondition();
final Condition overridingCondition2 = createMockCondition();
final Condition regularCondition = createMockCondition();
- final Monitor.Callback callback = Mockito.mock(Monitor.Callback.class);
+ final Monitor.Callback callback = Mockito.mock(
+ Monitor.Callback.class);
- final Monitor monitor = new Monitor(mExecutor);
+ final Monitor
+ monitor = new Monitor(mExecutor);
monitor.addSubscription(getDefaultBuilder(callback)
.addCondition(overridingCondition)
@@ -211,9 +218,11 @@ public class ConditionMonitorTest extends SysuiTestCase {
public void addCallback_addSecondCallback_reportWithExistingValue() {
final Monitor.Callback callback1 =
mock(Monitor.Callback.class);
- final Condition condition = mock(Condition.class);
+ final Condition condition = mock(
+ Condition.class);
when(condition.isConditionMet()).thenReturn(true);
- final Monitor monitor = new Monitor(mExecutor);
+ final Monitor
+ monitor = new Monitor(mExecutor);
monitor.addSubscription(new Monitor.Subscription.Builder(callback1)
.addCondition(condition)
.build());
@@ -229,8 +238,10 @@ public class ConditionMonitorTest extends SysuiTestCase {
@Test
public void addCallback_noConditions_reportAllConditionsMet() {
- final Monitor monitor = new Monitor(mExecutor);
- final Monitor.Callback callback = mock(Monitor.Callback.class);
+ final Monitor
+ monitor = new Monitor(mExecutor);
+ final Monitor.Callback callback = mock(
+ Monitor.Callback.class);
monitor.addSubscription(new Monitor.Subscription.Builder(callback).build());
mExecutor.runAllReady();
@@ -239,8 +250,10 @@ public class ConditionMonitorTest extends SysuiTestCase {
@Test
public void removeCallback_noFailureOnDoubleRemove() {
- final Condition condition = mock(Condition.class);
- final Monitor monitor = new Monitor(mExecutor);
+ final Condition condition = mock(
+ Condition.class);
+ final Monitor
+ monitor = new Monitor(mExecutor);
final Monitor.Callback callback =
mock(Monitor.Callback.class);
final Monitor.Subscription.Token token = monitor.addSubscription(
@@ -255,8 +268,10 @@ public class ConditionMonitorTest extends SysuiTestCase {
@Test
public void removeCallback_shouldNoLongerReceiveUpdate() {
- final Condition condition = mock(Condition.class);
- final Monitor monitor = new Monitor(mExecutor);
+ final Condition condition = mock(
+ Condition.class);
+ final Monitor
+ monitor = new Monitor(mExecutor);
final Monitor.Callback callback =
mock(Monitor.Callback.class);
final Monitor.Subscription.Token token = monitor.addSubscription(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionTest.java
index 28788647dd58..8443221e8b7a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.util.condition;
+package com.android.systemui.shared.condition;
import static com.google.common.truth.Truth.assertThat;
@@ -47,16 +47,20 @@ public class ConditionTest extends SysuiTestCase {
@Test
public void addCallback_addFirstCallback_triggerStart() {
- final Condition.Callback callback = mock(Condition.Callback.class);
+ final Condition.Callback callback = mock(
+ Condition.Callback.class);
mCondition.addCallback(callback);
verify(mCondition).start();
}
@Test
public void addCallback_addMultipleCallbacks_triggerStartOnlyOnce() {
- final Condition.Callback callback1 = mock(Condition.Callback.class);
- final Condition.Callback callback2 = mock(Condition.Callback.class);
- final Condition.Callback callback3 = mock(Condition.Callback.class);
+ final Condition.Callback callback1 = mock(
+ Condition.Callback.class);
+ final Condition.Callback callback2 = mock(
+ Condition.Callback.class);
+ final Condition.Callback callback3 = mock(
+ Condition.Callback.class);
mCondition.addCallback(callback1);
mCondition.addCallback(callback2);
@@ -67,12 +71,14 @@ public class ConditionTest extends SysuiTestCase {
@Test
public void addCallback_alreadyStarted_triggerUpdate() {
- final Condition.Callback callback1 = mock(Condition.Callback.class);
+ final Condition.Callback callback1 = mock(
+ Condition.Callback.class);
mCondition.addCallback(callback1);
mCondition.fakeUpdateCondition(true);
- final Condition.Callback callback2 = mock(Condition.Callback.class);
+ final Condition.Callback callback2 = mock(
+ Condition.Callback.class);
mCondition.addCallback(callback2);
verify(callback2).onConditionChanged(mCondition);
assertThat(mCondition.isConditionMet()).isTrue();
@@ -80,7 +86,8 @@ public class ConditionTest extends SysuiTestCase {
@Test
public void removeCallback_removeLastCallback_triggerStop() {
- final Condition.Callback callback = mock(Condition.Callback.class);
+ final Condition.Callback callback = mock(
+ Condition.Callback.class);
mCondition.addCallback(callback);
verify(mCondition, never()).stop();
@@ -92,7 +99,8 @@ public class ConditionTest extends SysuiTestCase {
public void updateCondition_falseToTrue_reportTrue() {
mCondition.fakeUpdateCondition(false);
- final Condition.Callback callback = mock(Condition.Callback.class);
+ final Condition.Callback callback = mock(
+ Condition.Callback.class);
mCondition.addCallback(callback);
mCondition.fakeUpdateCondition(true);
@@ -104,7 +112,8 @@ public class ConditionTest extends SysuiTestCase {
public void updateCondition_trueToFalse_reportFalse() {
mCondition.fakeUpdateCondition(true);
- final Condition.Callback callback = mock(Condition.Callback.class);
+ final Condition.Callback callback = mock(
+ Condition.Callback.class);
mCondition.addCallback(callback);
mCondition.fakeUpdateCondition(false);
@@ -116,7 +125,8 @@ public class ConditionTest extends SysuiTestCase {
public void updateCondition_trueToTrue_reportNothing() {
mCondition.fakeUpdateCondition(true);
- final Condition.Callback callback = mock(Condition.Callback.class);
+ final Condition.Callback callback = mock(
+ Condition.Callback.class);
mCondition.addCallback(callback);
mCondition.fakeUpdateCondition(true);
@@ -127,7 +137,8 @@ public class ConditionTest extends SysuiTestCase {
public void updateCondition_falseToFalse_reportNothing() {
mCondition.fakeUpdateCondition(false);
- final Condition.Callback callback = mock(Condition.Callback.class);
+ final Condition.Callback callback = mock(
+ Condition.Callback.class);
mCondition.addCallback(callback);
mCondition.fakeUpdateCondition(false);
@@ -149,7 +160,8 @@ public class ConditionTest extends SysuiTestCase {
final Condition combinedCondition = mCondition.or(
new FakeCondition(/* initialValue= */ false));
- final Condition.Callback callback = mock(Condition.Callback.class);
+ final Condition.Callback callback = mock(
+ Condition.Callback.class);
combinedCondition.addCallback(callback);
assertThat(combinedCondition.isConditionSet()).isTrue();
@@ -164,7 +176,8 @@ public class ConditionTest extends SysuiTestCase {
final Condition combinedCondition = mCondition.or(
new FakeCondition(/* initialValue= */ true));
- final Condition.Callback callback = mock(Condition.Callback.class);
+ final Condition.Callback callback = mock(
+ Condition.Callback.class);
combinedCondition.addCallback(callback);
assertThat(combinedCondition.isConditionSet()).isTrue();
@@ -179,7 +192,8 @@ public class ConditionTest extends SysuiTestCase {
final Condition combinedCondition = mCondition.or(
new FakeCondition(/* initialValue= */ true));
- final Condition.Callback callback = mock(Condition.Callback.class);
+ final Condition.Callback callback = mock(
+ Condition.Callback.class);
combinedCondition.addCallback(callback);
assertThat(combinedCondition.isConditionSet()).isTrue();
@@ -195,7 +209,8 @@ public class ConditionTest extends SysuiTestCase {
final Condition combinedCondition = mCondition.or(
new FakeCondition(/* initialValue= */ null));
- final Condition.Callback callback = mock(Condition.Callback.class);
+ final Condition.Callback callback = mock(
+ Condition.Callback.class);
combinedCondition.addCallback(callback);
assertThat(combinedCondition.isConditionSet()).isTrue();
@@ -211,7 +226,8 @@ public class ConditionTest extends SysuiTestCase {
final Condition combinedCondition = mCondition.or(
new FakeCondition(/* initialValue= */ null));
- final Condition.Callback callback = mock(Condition.Callback.class);
+ final Condition.Callback callback = mock(
+ Condition.Callback.class);
combinedCondition.addCallback(callback);
assertThat(combinedCondition.isConditionSet()).isFalse();
@@ -226,7 +242,8 @@ public class ConditionTest extends SysuiTestCase {
final Condition combinedCondition = mCondition.and(
new FakeCondition(/* initialValue= */ false));
- final Condition.Callback callback = mock(Condition.Callback.class);
+ final Condition.Callback callback = mock(
+ Condition.Callback.class);
combinedCondition.addCallback(callback);
assertThat(combinedCondition.isConditionSet()).isTrue();
@@ -241,7 +258,8 @@ public class ConditionTest extends SysuiTestCase {
final Condition combinedCondition = mCondition.and(
new FakeCondition(/* initialValue= */ true));
- final Condition.Callback callback = mock(Condition.Callback.class);
+ final Condition.Callback callback = mock(
+ Condition.Callback.class);
combinedCondition.addCallback(callback);
assertThat(combinedCondition.isConditionSet()).isTrue();
@@ -256,7 +274,8 @@ public class ConditionTest extends SysuiTestCase {
final Condition combinedCondition = mCondition.and(
new FakeCondition(/* initialValue= */ false));
- final Condition.Callback callback = mock(Condition.Callback.class);
+ final Condition.Callback callback = mock(
+ Condition.Callback.class);
combinedCondition.addCallback(callback);
assertThat(combinedCondition.isConditionSet()).isTrue();
@@ -272,7 +291,8 @@ public class ConditionTest extends SysuiTestCase {
final Condition combinedCondition = mCondition.and(
new FakeCondition(/* initialValue= */ null));
- final Condition.Callback callback = mock(Condition.Callback.class);
+ final Condition.Callback callback = mock(
+ Condition.Callback.class);
combinedCondition.addCallback(callback);
assertThat(combinedCondition.isConditionSet()).isFalse();
@@ -288,7 +308,8 @@ public class ConditionTest extends SysuiTestCase {
final Condition combinedCondition = mCondition.and(
new FakeCondition(/* initialValue= */ null));
- final Condition.Callback callback = mock(Condition.Callback.class);
+ final Condition.Callback callback = mock(
+ Condition.Callback.class);
combinedCondition.addCallback(callback);
assertThat(combinedCondition.isConditionSet()).isTrue();
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/condition/FakeCondition.java b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/FakeCondition.java
index 07ed1102e990..55a6d39d4644 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/util/condition/FakeCondition.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/FakeCondition.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.util.condition;
+package com.android.systemui.shared.condition;
/**
* Fake implementation of {@link Condition}, and provides a way for tests to update
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java
index 379bb28ae032..30dc0d20600f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java
@@ -108,7 +108,6 @@ public class ImageWallpaperTest extends SysuiTestCase {
private FeatureFlags mFeatureFlags;
FakeSystemClock mFakeSystemClock = new FakeSystemClock();
- FakeExecutor mFakeMainExecutor = new FakeExecutor(mFakeSystemClock);
FakeExecutor mFakeBackgroundExecutor = new FakeExecutor(mFakeSystemClock);
private CountDownLatch mEventCountdown;
@@ -163,7 +162,7 @@ public class ImageWallpaperTest extends SysuiTestCase {
}
private ImageWallpaper createImageWallpaper() {
- return new ImageWallpaper(mFeatureFlags, mFakeBackgroundExecutor, mFakeMainExecutor) {
+ return new ImageWallpaper(mFeatureFlags, mFakeBackgroundExecutor) {
@Override
public Engine onCreateEngine() {
return new GLEngine(mHandler) {
@@ -242,7 +241,7 @@ public class ImageWallpaperTest extends SysuiTestCase {
private ImageWallpaper createImageWallpaperCanvas() {
- return new ImageWallpaper(mFeatureFlags, mFakeBackgroundExecutor, mFakeMainExecutor) {
+ return new ImageWallpaper(mFeatureFlags, mFakeBackgroundExecutor) {
@Override
public Engine onCreateEngine() {
return new CanvasEngine() {
@@ -315,11 +314,10 @@ public class ImageWallpaperTest extends SysuiTestCase {
assertThat(mFakeBackgroundExecutor.numPending()).isAtLeast(1);
int n = 0;
- while (mFakeBackgroundExecutor.numPending() + mFakeMainExecutor.numPending() >= 1) {
+ while (mFakeBackgroundExecutor.numPending() >= 1) {
n++;
assertThat(n).isAtMost(10);
mFakeBackgroundExecutor.runNextReady();
- mFakeMainExecutor.runNextReady();
mFakeSystemClock.advanceTime(1000);
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt
index b31f119b7a7c..ced7955100f7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt
@@ -77,7 +77,5 @@ class FakeFgsManagerController(
dialogDismissedListeners.remove(listener)
}
- override fun shouldUpdateFooterVisibility(): Boolean = false
-
override fun visibleButtonsCount(): Int = 0
}
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
index b56818693124..52fb0a79a2bb 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
@@ -31,6 +31,7 @@ import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
import com.android.systemui.unfold.updates.FoldStateProvider
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdatesListener
+import com.android.systemui.unfold.updates.name
/** Maps fold updates to unfold transition progress using DynamicAnimation. */
class PhysicsBasedUnfoldTransitionProgressProvider(
@@ -117,7 +118,7 @@ class PhysicsBasedUnfoldTransitionProgressProvider(
}
if (DEBUG) {
- Log.d(TAG, "onFoldUpdate = $update")
+ Log.d(TAG, "onFoldUpdate = ${update.name()}")
Trace.traceCounter(Trace.TRACE_TAG_APP, "fold_update", update)
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index d2413f015003..55a4cc79abf0 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -726,7 +726,7 @@ class ActivityMetricsLogger {
// visible such as after the top task is finished.
for (int i = mTransitionInfoList.size() - 2; i >= 0; i--) {
final TransitionInfo prevInfo = mTransitionInfoList.get(i);
- if (prevInfo.mIsDrawn || !prevInfo.mLastLaunchedActivity.mVisibleRequested) {
+ if (prevInfo.mIsDrawn || !prevInfo.mLastLaunchedActivity.isVisibleRequested()) {
scheduleCheckActivityToBeDrawn(prevInfo.mLastLaunchedActivity, 0 /* delay */);
}
}
@@ -851,7 +851,7 @@ class ActivityMetricsLogger {
return;
}
if (DEBUG_METRICS) {
- Slog.i(TAG, "notifyVisibilityChanged " + r + " visible=" + r.mVisibleRequested
+ Slog.i(TAG, "notifyVisibilityChanged " + r + " visible=" + r.isVisibleRequested()
+ " state=" + r.getState() + " finishing=" + r.finishing);
}
if (r.isState(ActivityRecord.State.RESUMED) && r.mDisplayContent.isSleeping()) {
@@ -860,7 +860,7 @@ class ActivityMetricsLogger {
// the tracking of launch event.
return;
}
- if (!r.mVisibleRequested || r.finishing) {
+ if (!r.isVisibleRequested() || r.finishing) {
// Check if the tracker can be cancelled because the last launched activity may be
// no longer visible.
scheduleCheckActivityToBeDrawn(r, 0 /* delay */);
@@ -893,7 +893,7 @@ class ActivityMetricsLogger {
// activities in this task may be finished, invisible or drawn, so the transition event
// should be cancelled.
if (t != null && t.forAllActivities(
- a -> a.mVisibleRequested && !a.isReportedDrawn() && !a.finishing)) {
+ a -> a.isVisibleRequested() && !a.isReportedDrawn() && !a.finishing)) {
return;
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index e19e921852ff..313f5e205add 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -800,7 +800,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// it will sometimes be true a little earlier: when the activity record has
// been shown, but is still waiting for its app transition to execute
// before making its windows shown.
- boolean mVisibleRequested;
+ private boolean mVisibleRequested;
// Last visibility state we reported to the app token.
boolean reportedVisible;
@@ -3632,7 +3632,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// implied that the current finishing activity should be added into stopping list rather
// than destroy immediately.
final boolean isNextNotYetVisible = next != null
- && (!next.nowVisible || !next.mVisibleRequested);
+ && (!next.nowVisible || !next.isVisibleRequested());
// Clear last paused activity to ensure top activity can be resumed during sleeping.
if (isNextNotYetVisible && mDisplayContent.isSleeping()
@@ -4450,7 +4450,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
task.forAllActivities(fromActivity -> {
if (fromActivity == this) return true;
- return !fromActivity.mVisibleRequested && transferStartingWindow(fromActivity);
+ return !fromActivity.isVisibleRequested() && transferStartingWindow(fromActivity);
});
}
@@ -5115,7 +5115,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* This is the only place that writes {@link #mVisibleRequested} (except unit test). The caller
* outside of this class should use {@link #setVisibility}.
*/
- private void setVisibleRequested(boolean visible) {
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ void setVisibleRequested(boolean visible) {
if (visible == mVisibleRequested) {
return;
}
@@ -6561,7 +6562,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (associatedTask == null) {
removeStartingWindow();
} else if (associatedTask.getActivity(
- r -> r.mVisibleRequested && !r.firstWindowDrawn) == null) {
+ r -> r.isVisibleRequested() && !r.firstWindowDrawn) == null) {
// The last drawn activity may not be the one that owns the starting window.
final ActivityRecord r = associatedTask.topActivityContainsStartingWindow();
if (r != null) {
@@ -7940,8 +7941,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
@Override
- float getSizeCompatScale() {
- return hasSizeCompatBounds() ? mSizeCompatScale : super.getSizeCompatScale();
+ float getCompatScale() {
+ return hasSizeCompatBounds() ? mSizeCompatScale : super.getCompatScale();
}
@Override
diff --git a/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java b/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
index 30c7b232fcc8..0859d40c0fd1 100644
--- a/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
+++ b/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
@@ -92,7 +92,7 @@ public class ActivityServiceConnectionsHolder<T> {
public boolean isActivityVisible() {
synchronized (mService.mGlobalLock) {
- return mActivity.mVisibleRequested || mActivity.isState(RESUMED, PAUSING);
+ return mActivity.isVisibleRequested() || mActivity.isState(RESUMED, PAUSING);
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index e1c3cbf94bd4..4663662c5585 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -558,7 +558,7 @@ public class ActivityStartController {
if (rootTask == null) return false;
final RemoteTransition remote = options.getRemoteTransition();
final ActivityRecord r = rootTask.topRunningActivity();
- if (r == null || r.mVisibleRequested || !r.attachedToProcess() || remote == null
+ if (r == null || r.isVisibleRequested() || !r.attachedToProcess() || remote == null
|| !r.mActivityComponent.equals(intent.getComponent())
// Recents keeps invisible while device is locked.
|| r.mDisplayContent.isKeyguardLocked()) {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 27869c7cd44b..4fa7095b3282 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -2928,7 +2928,7 @@ class ActivityStarter {
// If the activity is visible in multi-windowing mode, it may already be on
// the top (visible to user but not the global top), then the result code
// should be START_DELIVERED_TO_TOP instead of START_TASK_TO_FRONT.
- final boolean wasTopOfVisibleRootTask = intentActivity.mVisibleRequested
+ final boolean wasTopOfVisibleRootTask = intentActivity.isVisibleRequested()
&& intentActivity.inMultiWindowMode()
&& intentActivity == mTargetRootTask.topRunningActivity();
// We only want to move to the front, if we aren't going to launch on a
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 028d4b3e0871..adb88060528a 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -319,7 +319,7 @@ class BackNavigationController {
// launch-behind to bump its visibility for the duration of the back gesture.
prevActivity = prevTask.getTopNonFinishingActivity();
if (prevActivity != null) {
- if (!prevActivity.mVisibleRequested) {
+ if (!prevActivity.isVisibleRequested()) {
prevActivity.setVisibility(true);
}
prevActivity.mLaunchTaskBehind = true;
@@ -492,7 +492,7 @@ class BackNavigationController {
private void prepareBackToHomeTransition(ActivityRecord currentActivity, Task homeTask) {
final DisplayContent dc = currentActivity.getDisplayContent();
final ActivityRecord homeActivity = homeTask.getTopNonFinishingActivity();
- if (!homeActivity.mVisibleRequested) {
+ if (!homeActivity.isVisibleRequested()) {
homeActivity.setVisibility(true);
}
homeActivity.mLaunchTaskBehind = true;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b33a83dac6e5..459949cffdf1 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -861,11 +861,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
final ActivityRecord activity = w.mActivityRecord;
if (gone) Slog.v(TAG, " GONE: mViewVisibility=" + w.mViewVisibility
+ " mRelayoutCalled=" + w.mRelayoutCalled + " visible=" + w.mToken.isVisible()
- + " visibleRequested=" + (activity != null && activity.mVisibleRequested)
+ + " visibleRequested=" + (activity != null && activity.isVisibleRequested())
+ " parentHidden=" + w.isParentWindowHidden());
else Slog.v(TAG, " VIS: mViewVisibility=" + w.mViewVisibility
+ " mRelayoutCalled=" + w.mRelayoutCalled + " visible=" + w.mToken.isVisible()
- + " visibleRequested=" + (activity != null && activity.mVisibleRequested)
+ + " visibleRequested=" + (activity != null && activity.isVisibleRequested())
+ " parentHidden=" + w.isParentWindowHidden());
}
@@ -1662,7 +1662,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
.notifyTaskRequestedOrientationChanged(task.mTaskId, orientation);
}
// The orientation source may not be the top if it uses SCREEN_ORIENTATION_BEHIND.
- final ActivityRecord topCandidate = !r.mVisibleRequested ? topRunningActivity() : r;
+ final ActivityRecord topCandidate = !r.isVisibleRequested() ? topRunningActivity() : r;
if (handleTopActivityLaunchingInDifferentOrientation(
topCandidate, r, true /* checkOpening */)) {
// Display orientation should be deferred until the top fixed rotation is finished.
@@ -2660,7 +2660,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
mWmService.mWindowsChanged = true;
// If the transition finished callback cannot match the token for some reason, make sure the
// rotated state is cleared if it is already invisible.
- if (mFixedRotationLaunchingApp != null && !mFixedRotationLaunchingApp.mVisibleRequested
+ if (mFixedRotationLaunchingApp != null && !mFixedRotationLaunchingApp.isVisibleRequested()
&& !mFixedRotationLaunchingApp.isVisible()
&& !mDisplayRotation.isRotatingSeamlessly()) {
clearFixedRotationLaunchingApp();
diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
index 7bb036d0b1e0..bd837940dfb2 100644
--- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
+++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
@@ -191,7 +191,7 @@ class EnsureActivitiesVisibleHelper {
if (!r.attachedToProcess()) {
makeVisibleAndRestartIfNeeded(mStarting, mConfigChanges, isTop,
resumeTopActivity && isTop, r);
- } else if (r.mVisibleRequested) {
+ } else if (r.isVisibleRequested()) {
// If this activity is already visible, then there is nothing to do here.
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Skipping: already visible at " + r);
@@ -244,7 +244,7 @@ class EnsureActivitiesVisibleHelper {
// invisible. If the app is already visible, it must have died while it was visible. In this
// case, we'll show the dead window but will not restart the app. Otherwise we could end up
// thrashing.
- if (!isTop && r.mVisibleRequested && !r.isState(INITIALIZING)) {
+ if (!isTop && r.isVisibleRequested() && !r.isState(INITIALIZING)) {
return;
}
@@ -256,7 +256,7 @@ class EnsureActivitiesVisibleHelper {
if (r != starting) {
r.startFreezingScreenLocked(configChanges);
}
- if (!r.mVisibleRequested || r.mLaunchTaskBehind) {
+ if (!r.isVisibleRequested() || r.mLaunchTaskBehind) {
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Starting and making visible: " + r);
}
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index 76ee733cbb27..bcea6f4db1dc 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -576,9 +576,8 @@ final class LetterboxUiController {
// Rounded corners should be displayed above the taskbar.
bounds.bottom =
Math.min(bounds.bottom, getTaskbarInsetsSource(mainWindow).getFrame().top);
- if (mActivityRecord.inSizeCompatMode()
- && mActivityRecord.getSizeCompatScale() < 1.0f) {
- bounds.scale(1.0f / mActivityRecord.getSizeCompatScale());
+ if (mActivityRecord.inSizeCompatMode() && mActivityRecord.getCompatScale() < 1.0f) {
+ bounds.scale(1.0f / mActivityRecord.getCompatScale());
}
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index ffe3374e6658..be9058840492 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -112,7 +112,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, OnRootTaskOrderChan
mTargetActivityType);
ActivityRecord targetActivity = getTargetActivity(targetRootTask);
if (targetActivity != null) {
- if (targetActivity.mVisibleRequested || targetActivity.isTopRunningActivity()) {
+ if (targetActivity.isVisibleRequested() || targetActivity.isTopRunningActivity()) {
// The activity is ready.
return;
}
@@ -195,7 +195,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, OnRootTaskOrderChan
// Send launch hint if we are actually launching the target. If it's already visible
// (shouldn't happen in general) we don't need to send it.
- if (targetActivity == null || !targetActivity.mVisibleRequested) {
+ if (targetActivity == null || !targetActivity.isVisibleRequested()) {
mService.mRootWindowContainer.startPowerModeLaunchIfNeeded(
true /* forceSend */, targetActivity);
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 6c6fbee885f2..2507a8d5af3a 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2626,7 +2626,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
final ArrayList<Task> addedTasks = new ArrayList<>();
forAllActivities((r) -> {
final Task task = r.getTask();
- if (r.mVisibleRequested && r.mStartingData == null && !addedTasks.contains(task)) {
+ if (r.isVisibleRequested() && r.mStartingData == null && !addedTasks.contains(task)) {
r.showStartingWindow(true /*taskSwitch*/);
addedTasks.add(task);
}
@@ -2651,7 +2651,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
forAllLeafTasks(task -> {
final int oldRank = task.mLayerRank;
final ActivityRecord r = task.topRunningActivityLocked();
- if (r != null && r.mVisibleRequested) {
+ if (r != null && r.isVisibleRequested()) {
task.mLayerRank = ++mTmpTaskLayerRank;
} else {
task.mLayerRank = Task.LAYER_RANK_INVISIBLE;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 51eec03855a5..c2604f1476c4 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1930,7 +1930,6 @@ class Task extends TaskFragment {
mTaskSupervisor.scheduleUpdateMultiWindowMode(this);
}
- final int newWinMode = getWindowingMode();
if (shouldStartChangeTransition(prevWinMode, mTmpPrevBounds)) {
initializeChangeTransition(mTmpPrevBounds);
}
@@ -1944,16 +1943,15 @@ class Task extends TaskFragment {
}
}
- if (pipChanging && wasInPictureInPicture) {
+ if (pipChanging && wasInPictureInPicture
+ && !mTransitionController.isShellTransitionsEnabled()) {
// If the top activity is changing from PiP to fullscreen with fixed rotation,
// clear the crop and rotation matrix of task because fixed rotation will handle
// the transformation on activity level. This also avoids flickering caused by the
// latency of fullscreen task organizer configuring the surface.
final ActivityRecord r = topRunningActivity();
if (r != null && mDisplayContent.isFixedRotationLaunchingApp(r)) {
- getSyncTransaction().setWindowCrop(mSurfaceControl, null)
- .setCornerRadius(mSurfaceControl, 0f)
- .setMatrix(mSurfaceControl, Matrix.IDENTITY_MATRIX, new float[9]);
+ resetSurfaceControlTransforms();
}
}
@@ -2474,7 +2472,7 @@ class Task extends TaskFragment {
final String myReason = reason + " adjustFocusToNextFocusableTask";
final ActivityRecord top = focusableTask.topRunningActivity();
- if (focusableTask.isActivityTypeHome() && (top == null || !top.mVisibleRequested)) {
+ if (focusableTask.isActivityTypeHome() && (top == null || !top.isVisibleRequested())) {
// If we will be focusing on the root home task next and its current top activity isn't
// visible, then use the move the root home task to top to make the activity visible.
focusableTask.getDisplayArea().moveHomeActivityToTop(myReason);
@@ -2786,7 +2784,7 @@ class Task extends TaskFragment {
*/
private static void getMaxVisibleBounds(ActivityRecord token, Rect out, boolean[] foundTop) {
// skip hidden (or about to hide) apps
- if (token.mIsExiting || !token.isClientVisible() || !token.mVisibleRequested) {
+ if (token.mIsExiting || !token.isClientVisible() || !token.isVisibleRequested()) {
return;
}
final WindowState win = token.findMainWindow();
@@ -3098,7 +3096,7 @@ class Task extends TaskFragment {
* this activity.
*/
ActivityRecord getTopVisibleActivity() {
- return getActivity((r) -> !r.mIsExiting && r.isClientVisible() && r.mVisibleRequested);
+ return getActivity((r) -> !r.mIsExiting && r.isClientVisible() && r.isVisibleRequested());
}
/**
@@ -5806,7 +5804,7 @@ class Task extends TaskFragment {
ActivityRecord r, ActivityRecord starting, String packageName) {
if (r.info.packageName.equals(packageName)) {
r.forceNewConfig = true;
- if (starting != null && r == starting && r.mVisibleRequested) {
+ if (starting != null && r == starting && r.isVisibleRequested()) {
r.startFreezingScreenLocked(CONFIG_SCREEN_LAYOUT);
}
}
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 454f338045d1..ae4f8947cc86 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -352,7 +352,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
}
void process(ActivityRecord start, boolean preserveWindow) {
- if (start == null || !start.mVisibleRequested) {
+ if (start == null || !start.isVisibleRequested()) {
return;
}
reset(preserveWindow);
@@ -1363,7 +1363,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
if (next.attachedToProcess()) {
if (DEBUG_SWITCH) {
Slog.v(TAG_SWITCH, "Resume running: " + next + " stopped=" + next.stopped
- + " visibleRequested=" + next.mVisibleRequested);
+ + " visibleRequested=" + next.isVisibleRequested());
}
// If the previous activity is translucent, force a visibility update of
@@ -1377,7 +1377,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|| mLastPausedActivity != null && !mLastPausedActivity.occludesParent();
// This activity is now becoming visible.
- if (!next.mVisibleRequested || next.stopped || lastActivityTranslucent) {
+ if (!next.isVisibleRequested() || next.stopped || lastActivityTranslucent) {
next.app.addToPendingTop();
next.setVisibility(true);
}
@@ -1428,7 +1428,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
// Do over!
mTaskSupervisor.scheduleResumeTopActivities();
}
- if (!next.mVisibleRequested || next.stopped) {
+ if (!next.isVisibleRequested() || next.stopped) {
next.setVisibility(true);
}
next.completeResumeLocked();
@@ -1739,7 +1739,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
} else if (prev.hasProcess()) {
ProtoLog.v(WM_DEBUG_STATES, "Enqueue pending stop if needed: %s "
+ "wasStopping=%b visibleRequested=%b", prev, wasStopping,
- prev.mVisibleRequested);
+ prev.isVisibleRequested());
if (prev.deferRelaunchUntilPaused) {
// Complete the deferred relaunch that was waiting for pause to complete.
ProtoLog.v(WM_DEBUG_STATES, "Re-launching after pause: %s", prev);
@@ -1749,7 +1749,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
// We can't clobber it, because the stop confirmation will not be handled.
// We don't need to schedule another stop, we only need to let it happen.
prev.setState(STOPPING, "completePausedLocked");
- } else if (!prev.mVisibleRequested || shouldSleepOrShutDownActivities()) {
+ } else if (!prev.isVisibleRequested() || shouldSleepOrShutDownActivities()) {
// Clear out any deferred client hide we might currently have.
prev.setDeferHidingClient(false);
// If we were visible then resumeTopActivities will release resources before
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 6b14dba6eb81..c874747b0b5a 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -643,7 +643,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
// No need to clip the display in case seeing the clipped content when during the
// display rotation. No need to clip activities because they rely on clipping on
// task layers.
- if (target.asDisplayContent() != null || target.asActivityRecord() != null) {
+ if (target.asTaskFragment() == null) {
t.setCrop(targetLeash, null /* crop */);
} else {
// Crop to the resolved override bounds.
@@ -993,7 +993,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
// show here in the same way that we manually hide in finishTransaction.
for (int i = mParticipants.size() - 1; i >= 0; --i) {
final ActivityRecord ar = mParticipants.valueAt(i).asActivityRecord();
- if (ar == null || !ar.mVisibleRequested) continue;
+ if (ar == null || !ar.isVisibleRequested()) continue;
transaction.show(ar.getSurfaceControl());
// Also manually show any non-reported parents. This is necessary in a few cases
@@ -1274,7 +1274,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
ArrayMap<WindowContainer, Integer> reasons = new ArrayMap<>();
for (int i = mParticipants.size() - 1; i >= 0; --i) {
ActivityRecord r = mParticipants.valueAt(i).asActivityRecord();
- if (r == null || !r.mVisibleRequested) continue;
+ if (r == null || !r.isVisibleRequested()) continue;
int transitionReason = APP_TRANSITION_WINDOWS_DRAWN;
// At this point, r is "ready", but if it's not "ALL ready" then it is probably only
// ready due to starting-window.
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 920b1bad48d1..1d25dbc0d533 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -726,9 +726,9 @@ class WallpaperController {
}
final boolean newTargetHidden = wallpaperTarget.mActivityRecord != null
- && !wallpaperTarget.mActivityRecord.mVisibleRequested;
+ && !wallpaperTarget.mActivityRecord.isVisibleRequested();
final boolean oldTargetHidden = prevWallpaperTarget.mActivityRecord != null
- && !prevWallpaperTarget.mActivityRecord.mVisibleRequested;
+ && !prevWallpaperTarget.mActivityRecord.isVisibleRequested();
ProtoLog.v(WM_DEBUG_WALLPAPER, "Animating wallpapers: "
+ "old: %s hidden=%b new: %s hidden=%b",
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index 8fdaec613ad5..bf6c4fb7220a 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -139,7 +139,7 @@ class WallpaperWindowToken extends WindowToken {
bac.linkFixedRotationTransformIfNeeded(this);
} else if ((wallpaperTarget.mActivityRecord == null
// Ignore invisible activity because it may be moving to background.
- || wallpaperTarget.mActivityRecord.mVisibleRequested)
+ || wallpaperTarget.mActivityRecord.isVisibleRequested())
&& wallpaperTarget.mToken.hasFixedRotationTransform()) {
// If the wallpaper target has a fixed rotation, we want the wallpaper to follow its
// rotation
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 68b853dd2695..b3a7754bc2d5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1883,7 +1883,7 @@ public class WindowManagerService extends IWindowManager.Stub
// Make this invalid which indicates a null attached frame.
outAttachedFrame.set(0, 0, -1, -1);
}
- outSizeCompatScale[0] = win.getSizeCompatScaleForClient();
+ outSizeCompatScale[0] = win.getCompatScaleForClient();
}
Binder.restoreCallingIdentity(origId);
@@ -8866,7 +8866,7 @@ public class WindowManagerService extends IWindowManager.Stub
outInsetsState.set(state, true /* copySources */);
if (WindowState.hasCompatScale(attrs, token, overrideScale)) {
final float compatScale = token != null && token.hasSizeCompatBounds()
- ? token.getSizeCompatScale() * overrideScale
+ ? token.getCompatScale() * overrideScale
: overrideScale;
outInsetsState.scale(1f / compatScale);
}
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index dc1d50c435b9..cd777092d438 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -1891,7 +1891,18 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
// actions.
taskFragment.setTaskFragmentOrganizer(creationParams.getOrganizer(),
ownerActivity.getUid(), ownerActivity.info.processName);
- ownerTask.addChild(taskFragment, POSITION_TOP);
+ final int position;
+ if (creationParams.getPairedPrimaryFragmentToken() != null) {
+ // When there is a paired primary TaskFragment, we want to place the new TaskFragment
+ // right above the paired one to make sure there is no other window in between.
+ final TaskFragment pairedPrimaryTaskFragment = getTaskFragment(
+ creationParams.getPairedPrimaryFragmentToken());
+ final int pairedPosition = ownerTask.mChildren.indexOf(pairedPrimaryTaskFragment);
+ position = pairedPosition != -1 ? pairedPosition + 1 : POSITION_TOP;
+ } else {
+ position = POSITION_TOP;
+ }
+ ownerTask.addChild(taskFragment, position);
taskFragment.setWindowingMode(creationParams.getWindowingMode());
taskFragment.setBounds(creationParams.getInitialBounds());
mLaunchTaskFragments.put(creationParams.getFragmentToken(), taskFragment);
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 202fe558f938..682918b1e7dd 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -751,7 +751,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
// - no longer visible OR
// - not focusable (in PiP mode for instance)
if (topDisplay == null
- || !mPreQTopResumedActivity.mVisibleRequested
+ || !mPreQTopResumedActivity.isVisibleRequested()
|| !mPreQTopResumedActivity.isFocusable()) {
canUpdate = true;
}
@@ -860,7 +860,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
// to those activities that are part of the package whose app-specific settings changed
if (packageName.equals(r.packageName)
&& r.applyAppSpecificConfig(nightMode, localesOverride)
- && r.mVisibleRequested) {
+ && r.isVisibleRequested()) {
r.ensureActivityConfiguration(0 /* globalChanges */, true /* preserveWindow */);
}
}
@@ -942,7 +942,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
}
// Don't consider any activities that are currently not in a state where they
// can be destroyed.
- if (r.mVisibleRequested || !r.stopped || !r.hasSavedState() || !r.isDestroyable()
+ if (r.isVisibleRequested() || !r.stopped || !r.hasSavedState() || !r.isDestroyable()
|| r.isState(STARTED, RESUMED, PAUSING, PAUSED, STOPPING)) {
if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Not releasing in-use activity: " + r);
continue;
@@ -988,7 +988,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
final int displayId = r.getDisplayId();
final Context c = root.getDisplayUiContext(displayId);
- if (c != null && r.mVisibleRequested && !displayContexts.contains(c)) {
+ if (c != null && r.isVisibleRequested() && !displayContexts.contains(c)) {
displayContexts.add(c);
}
}
@@ -1056,7 +1056,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
if (task != null && task.mLayerRank != Task.LAYER_RANK_INVISIBLE) {
stateFlags |= ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK;
}
- if (r.mVisibleRequested) {
+ if (r.isVisibleRequested()) {
if (r.isState(RESUMED)) {
stateFlags |= ACTIVITY_STATE_FLAG_HAS_RESUMED;
}
@@ -1268,7 +1268,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
}
for (int i = activities.size() - 1; i >= 0; i--) {
final ActivityRecord r = activities.get(i);
- if (r.mVisibleRequested || r.isVisible()) {
+ if (r.isVisibleRequested() || r.isVisible()) {
// While an activity launches a new activity, it's possible that the old activity
// is already requested to be hidden (mVisibleRequested=false), but this visibility
// is not yet committed, so isVisible()=true.
@@ -1489,7 +1489,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
Configuration overrideConfig = new Configuration(r.getRequestedOverrideConfiguration());
overrideConfig.assetsSeq = assetSeq;
r.onRequestedOverrideConfigurationChanged(overrideConfig);
- if (r.mVisibleRequested) {
+ if (r.isVisibleRequested()) {
r.ensureActivityConfiguration(0, true);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 45606f965858..2f55d1824c07 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -475,7 +475,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// Current transformation being applied.
float mGlobalScale = 1f;
float mInvGlobalScale = 1f;
- float mSizeCompatScale = 1f;
+ float mCompatScale = 1f;
final float mOverrideScale;
float mHScale = 1f, mVScale = 1f;
float mLastHScale = 1f, mLastVScale = 1f;
@@ -1254,21 +1254,21 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
void updateGlobalScale() {
if (hasCompatScale()) {
- mSizeCompatScale = (mOverrideScale == 1f || mToken.hasSizeCompatBounds())
- ? mToken.getSizeCompatScale()
+ mCompatScale = (mOverrideScale == 1f || mToken.hasSizeCompatBounds())
+ ? mToken.getCompatScale()
: 1f;
- mGlobalScale = mSizeCompatScale * mOverrideScale;
+ mGlobalScale = mCompatScale * mOverrideScale;
mInvGlobalScale = 1f / mGlobalScale;
return;
}
- mGlobalScale = mInvGlobalScale = mSizeCompatScale = 1f;
+ mGlobalScale = mInvGlobalScale = mCompatScale = 1f;
}
- float getSizeCompatScaleForClient() {
- // If the size compat scale is because of the size compat bounds, we only scale down its
- // coordinates at the server side without letting the client know.
- return mToken.hasSizeCompatBounds() ? 1f : mSizeCompatScale;
+ float getCompatScaleForClient() {
+ // If this window in the size compat mode. The scaling is fully controlled at the server
+ // side. The client doesn't need to take it into account.
+ return mToken.hasSizeCompatBounds() ? 1f : mCompatScale;
}
/**
@@ -1956,7 +1956,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
*/
// TODO: Can we consolidate this with #isVisible() or have a more appropriate name for this?
boolean isWinVisibleLw() {
- return (mActivityRecord == null || mActivityRecord.mVisibleRequested
+ return (mActivityRecord == null || mActivityRecord.isVisibleRequested()
|| mActivityRecord.isAnimating(TRANSITION | PARENTS)) && isVisible();
}
@@ -1993,7 +1993,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
final ActivityRecord atoken = mActivityRecord;
return (mHasSurface || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
&& isVisibleByPolicy() && !isParentWindowHidden()
- && (atoken == null || atoken.mVisibleRequested)
+ && (atoken == null || atoken.isVisibleRequested())
&& !mAnimatingExit && !mDestroying;
}
@@ -2100,7 +2100,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
boolean isDisplayed() {
final ActivityRecord atoken = mActivityRecord;
return isDrawn() && isVisibleByPolicy()
- && ((!isParentWindowHidden() && (atoken == null || atoken.mVisibleRequested))
+ && ((!isParentWindowHidden() && (atoken == null || atoken.isVisibleRequested()))
|| isAnimating(TRANSITION | PARENTS));
}
@@ -2122,7 +2122,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// a layout since they can request relayout when client visibility is false.
// TODO (b/157682066) investigate if we can clean up isVisible
|| (atoken == null && !(wouldBeVisibleIfPolicyIgnored() && isVisibleByPolicy()))
- || (atoken != null && !atoken.mVisibleRequested)
+ || (atoken != null && !atoken.isVisibleRequested())
|| isParentWindowGoneForLayout()
|| (mAnimatingExit && !isAnimatingLw())
|| mDestroying;
@@ -2169,7 +2169,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return;
}
if (mActivityRecord != null) {
- if (!mActivityRecord.mVisibleRequested) return;
+ if (!mActivityRecord.isVisibleRequested()) return;
if (mActivityRecord.allDrawn) {
// The allDrawn of activity is reset when the visibility is changed to visible, so
// the content should be ready if allDrawn is set.
@@ -2742,7 +2742,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
+ " exiting=" + mAnimatingExit + " destroying=" + mDestroying);
if (mActivityRecord != null) {
Slog.i(TAG_WM, " mActivityRecord.visibleRequested="
- + mActivityRecord.mVisibleRequested);
+ + mActivityRecord.isVisibleRequested());
}
}
}
@@ -3218,7 +3218,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
return !mActivityRecord.getTask().getRootTask().shouldIgnoreInput()
- && mActivityRecord.mVisibleRequested;
+ && mActivityRecord.isVisibleRequested();
}
/**
@@ -3867,14 +3867,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
}
- outFrames.sizeCompatScale = getSizeCompatScaleForClient();
+ outFrames.compatScale = getCompatScaleForClient();
// Note: in the cases where the window is tied to an activity, we should not send a
// configuration update when the window has requested to be hidden. Doing so can lead to
// the client erroneously accepting a configuration that would have otherwise caused an
// activity restart. We instead hand back the last reported {@link MergedConfiguration}.
if (useLatestConfig || (relayoutVisible && (mActivityRecord == null
- || mActivityRecord.mVisibleRequested))) {
+ || mActivityRecord.isVisibleRequested()))) {
final Configuration globalConfig = getProcessGlobalConfiguration();
final Configuration overrideConfig = getMergedOverrideConfiguration();
outMergedConfiguration.setConfiguration(globalConfig, overrideConfig);
@@ -4722,7 +4722,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
+ " during animation: policyVis=" + isVisibleByPolicy()
+ " parentHidden=" + isParentWindowHidden()
+ " tok.visibleRequested="
- + (mActivityRecord != null && mActivityRecord.mVisibleRequested)
+ + (mActivityRecord != null && mActivityRecord.isVisibleRequested())
+ " tok.visible=" + (mActivityRecord != null && mActivityRecord.isVisible())
+ " animating=" + isAnimating(TRANSITION | PARENTS)
+ " tok animating="
@@ -5195,7 +5195,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
+ " pv=" + isVisibleByPolicy()
+ " mDrawState=" + mWinAnimator.mDrawState
+ " ph=" + isParentWindowHidden()
- + " th=" + (mActivityRecord != null && mActivityRecord.mVisibleRequested)
+ + " th=" + (mActivityRecord != null && mActivityRecord.isVisibleRequested())
+ " a=" + isAnimating(TRANSITION | PARENTS));
}
}
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 805559035ef9..e6323315db4a 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -258,7 +258,7 @@ class WindowToken extends WindowContainer<WindowState> {
* @return The scale for applications running in compatibility mode. Multiply the size in the
* application by this scale will be the size in the screen.
*/
- float getSizeCompatScale() {
+ float getCompatScale() {
return mDisplayContent.mCompatibleScreenScale;
}
@@ -588,9 +588,7 @@ class WindowToken extends WindowContainer<WindowState> {
.setCallsite("WindowToken.getOrCreateFixedRotationLeash")
.build();
t.setPosition(leash, mLastSurfacePosition.x, mLastSurfacePosition.y);
- t.show(leash);
t.reparent(getSurfaceControl(), leash);
- t.setAlpha(getSurfaceControl(), 1.f);
mFixedRotationTransformLeash = leash;
updateSurfaceRotation(t, rotation, mFixedRotationTransformLeash);
return mFixedRotationTransformLeash;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index 5b909a343a59..14eeaa57ddd7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -99,7 +99,7 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase {
.setComponent(createRelative(DEFAULT_COMPONENT_PACKAGE_NAME, "TopActivity"))
.build();
// becomes invisible when covered by mTopActivity
- mTrampolineActivity.mVisibleRequested = false;
+ mTrampolineActivity.setVisibleRequested(false);
}
private <T> T verifyAsync(T mock) {
@@ -228,7 +228,7 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase {
public void testOnActivityLaunchCancelled_hasDrawn() {
onActivityLaunched(mTopActivity);
- mTopActivity.mVisibleRequested = true;
+ mTopActivity.setVisibleRequested(true);
doReturn(true).when(mTopActivity).isReportedDrawn();
// Cannot time already-visible activities.
@@ -251,7 +251,7 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase {
notifyActivityLaunching(noDrawnActivity.intent);
notifyAndVerifyActivityLaunched(noDrawnActivity);
- noDrawnActivity.mVisibleRequested = false;
+ noDrawnActivity.setVisibleRequested(false);
mActivityMetricsLogger.notifyVisibilityChanged(noDrawnActivity);
verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqLastStartedId(noDrawnActivity));
@@ -279,7 +279,7 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase {
clearInvocations(mLaunchObserver);
mLaunchTopByTrampoline = true;
- mTopActivity.mVisibleRequested = false;
+ mTopActivity.setVisibleRequested(false);
notifyActivityLaunching(mTopActivity.intent);
// It should schedule a message with UNKNOWN_VISIBILITY_CHECK_DELAY_MS to check whether
// the launch event is still valid.
@@ -307,7 +307,7 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase {
// Create an invisible event that should be cancelled after the next event starts.
final ActivityRecord prev = new ActivityBuilder(mAtm).setCreateTask(true).build();
onActivityLaunched(prev);
- prev.mVisibleRequested = false;
+ prev.setVisibleRequested(false);
mActivityOptions = ActivityOptions.makeBasic();
mActivityOptions.setSourceInfo(SourceInfo.TYPE_LAUNCHER, SystemClock.uptimeMillis() - 10);
@@ -540,7 +540,7 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase {
@Test
public void testConsecutiveLaunchWithDifferentWindowingMode() {
mTopActivity.setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW);
- mTrampolineActivity.mVisibleRequested = true;
+ mTrampolineActivity.setVisibleRequested(true);
onActivityLaunched(mTrampolineActivity);
mActivityMetricsLogger.notifyActivityLaunching(mTopActivity.intent,
mTrampolineActivity /* caller */, mTrampolineActivity.getUid());
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 53e0b2b7a615..17ec19d3e617 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -917,7 +917,7 @@ public class ActivityRecordTests extends WindowTestsBase {
// Prepare the activity record to be ready for immediate removal. It should be invisible and
// have no process. Otherwise, request to finish it will send a message to client first.
activity.setState(STOPPED, "test");
- activity.mVisibleRequested = false;
+ activity.setVisibleRequested(false);
activity.nowVisible = false;
// Set process to 'null' to allow immediate removal, but don't call mActivity.setProcess() -
// this will cause NPE when updating task's process.
@@ -927,7 +927,7 @@ public class ActivityRecordTests extends WindowTestsBase {
// next activity reports idle to destroy it.
final ActivityRecord topActivity = new ActivityBuilder(mAtm)
.setTask(activity.getTask()).build();
- topActivity.mVisibleRequested = true;
+ topActivity.setVisibleRequested(true);
topActivity.nowVisible = true;
topActivity.setState(RESUMED, "test");
@@ -1082,7 +1082,7 @@ public class ActivityRecordTests extends WindowTestsBase {
final ActivityRecord activity = createActivityWithTask();
clearInvocations(activity.mDisplayContent);
activity.finishing = false;
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
activity.setState(RESUMED, "test");
activity.finishIfPossible("test", false /* oomAdj */);
@@ -1099,7 +1099,7 @@ public class ActivityRecordTests extends WindowTestsBase {
final ActivityRecord activity = createActivityWithTask();
clearInvocations(activity.mDisplayContent);
activity.finishing = false;
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
activity.setState(PAUSED, "test");
activity.finishIfPossible("test", false /* oomAdj */);
@@ -1118,7 +1118,7 @@ public class ActivityRecordTests extends WindowTestsBase {
// Put an activity on top of test activity to make it invisible and prevent us from
// accidentally resuming the topmost one again.
new ActivityBuilder(mAtm).build();
- activity.mVisibleRequested = false;
+ activity.setVisibleRequested(false);
activity.setState(STOPPED, "test");
activity.finishIfPossible("test", false /* oomAdj */);
@@ -1136,7 +1136,7 @@ public class ActivityRecordTests extends WindowTestsBase {
final TestTransitionPlayer testPlayer = registerTestTransitionPlayer();
final ActivityRecord activity = createActivityWithTask();
activity.finishing = false;
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
activity.setState(RESUMED, "test");
activity.finishIfPossible("test", false /* oomAdj */);
@@ -1273,7 +1273,7 @@ public class ActivityRecordTests extends WindowTestsBase {
final ActivityRecord currentTop = createActivityWithTask();
final Task task = currentTop.getTask();
- currentTop.mVisibleRequested = currentTop.nowVisible = true;
+ currentTop.setVisibleRequested(currentTop.nowVisible = true);
// Simulates that {@code currentTop} starts an existing activity from background (so its
// state is stopped) and the starting flow just goes to place it at top.
@@ -1300,7 +1300,7 @@ public class ActivityRecordTests extends WindowTestsBase {
final ActivityRecord bottomActivity = createActivityWithTask();
final ActivityRecord topActivity = new ActivityBuilder(mAtm)
.setTask(bottomActivity.getTask()).build();
- topActivity.mVisibleRequested = true;
+ topActivity.setVisibleRequested(true);
// simulating bottomActivity as a trampoline activity.
bottomActivity.setState(RESUMED, "test");
bottomActivity.finishIfPossible("test", false);
@@ -1316,13 +1316,13 @@ public class ActivityRecordTests extends WindowTestsBase {
final ActivityRecord activity = createActivityWithTask();
final ActivityRecord topActivity = new ActivityBuilder(mAtm)
.setTask(activity.getTask()).build();
- topActivity.mVisibleRequested = true;
+ topActivity.setVisibleRequested(true);
topActivity.nowVisible = true;
topActivity.finishing = true;
topActivity.setState(PAUSED, "true");
// Mark the bottom activity as not visible, so that we will wait for it before removing
// the top one.
- activity.mVisibleRequested = false;
+ activity.setVisibleRequested(false);
activity.nowVisible = false;
activity.setState(STOPPED, "test");
@@ -1346,13 +1346,13 @@ public class ActivityRecordTests extends WindowTestsBase {
final ActivityRecord topActivity = createActivityWithTask();
mDisplayContent.setIsSleeping(true);
doReturn(true).when(activity).shouldBeVisible();
- topActivity.mVisibleRequested = false;
+ topActivity.setVisibleRequested(false);
topActivity.nowVisible = false;
topActivity.finishing = true;
topActivity.setState(STOPPED, "true");
// Mark the activity behind (on a separate task) as not visible
- activity.mVisibleRequested = false;
+ activity.setVisibleRequested(false);
activity.nowVisible = false;
activity.setState(STOPPED, "test");
@@ -1370,13 +1370,13 @@ public class ActivityRecordTests extends WindowTestsBase {
final ActivityRecord activity = createActivityWithTask();
final ActivityRecord topActivity = new ActivityBuilder(mAtm)
.setTask(activity.getTask()).build();
- topActivity.mVisibleRequested = false;
+ topActivity.setVisibleRequested(false);
topActivity.nowVisible = false;
topActivity.finishing = true;
topActivity.setState(STOPPED, "true");
// Mark the bottom activity as not visible, so that we would wait for it before removing
// the top one.
- activity.mVisibleRequested = false;
+ activity.setVisibleRequested(false);
activity.nowVisible = false;
activity.setState(STOPPED, "test");
@@ -1394,12 +1394,12 @@ public class ActivityRecordTests extends WindowTestsBase {
final ActivityRecord activity = createActivityWithTask();
final ActivityRecord topActivity = new ActivityBuilder(mAtm)
.setTask(activity.getTask()).build();
- topActivity.mVisibleRequested = true;
+ topActivity.setVisibleRequested(true);
topActivity.nowVisible = true;
topActivity.finishing = true;
topActivity.setState(PAUSED, "true");
// Mark the bottom activity as already visible, so that there is no need to wait for it.
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
activity.nowVisible = true;
activity.setState(RESUMED, "test");
@@ -1417,12 +1417,12 @@ public class ActivityRecordTests extends WindowTestsBase {
final ActivityRecord activity = createActivityWithTask();
final ActivityRecord topActivity = new ActivityBuilder(mAtm)
.setTask(activity.getTask()).build();
- topActivity.mVisibleRequested = false;
+ topActivity.setVisibleRequested(false);
topActivity.nowVisible = false;
topActivity.finishing = true;
topActivity.setState(STOPPED, "true");
// Mark the bottom activity as already visible, so that there is no need to wait for it.
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
activity.nowVisible = true;
activity.setState(RESUMED, "test");
@@ -1440,12 +1440,12 @@ public class ActivityRecordTests extends WindowTestsBase {
final ActivityRecord activity = createActivityWithTask();
final ActivityRecord topActivity = new ActivityBuilder(mAtm)
.setTask(activity.getTask()).build();
- topActivity.mVisibleRequested = true;
+ topActivity.setVisibleRequested(true);
topActivity.nowVisible = true;
topActivity.finishing = true;
topActivity.setState(PAUSED, "true");
// Mark the bottom activity as already visible, so that there is no need to wait for it.
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
activity.nowVisible = true;
activity.setState(RESUMED, "test");
@@ -1454,7 +1454,7 @@ public class ActivityRecordTests extends WindowTestsBase {
final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
final ActivityRecord focusedActivity = stack.getTopMostActivity();
focusedActivity.nowVisible = true;
- focusedActivity.mVisibleRequested = true;
+ focusedActivity.setVisibleRequested(true);
focusedActivity.setState(RESUMED, "test");
stack.setResumedActivity(focusedActivity, "test");
@@ -1476,7 +1476,7 @@ public class ActivityRecordTests extends WindowTestsBase {
int displayId = activity.getDisplayId();
doReturn(true).when(keyguardController).isKeyguardLocked(eq(displayId));
final ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task).build();
- topActivity.mVisibleRequested = true;
+ topActivity.setVisibleRequested(true);
topActivity.nowVisible = true;
topActivity.setState(RESUMED, "true");
doCallRealMethod().when(mRootWindowContainer).ensureActivitiesVisible(
@@ -1515,12 +1515,12 @@ public class ActivityRecordTests extends WindowTestsBase {
final ActivityRecord activity = createActivityWithTask();
final Task task = activity.getTask();
final ActivityRecord firstActivity = new ActivityBuilder(mAtm).setTask(task).build();
- firstActivity.mVisibleRequested = false;
+ firstActivity.setVisibleRequested(false);
firstActivity.nowVisible = false;
firstActivity.setState(STOPPED, "test");
final ActivityRecord secondActivity = new ActivityBuilder(mAtm).setTask(task).build();
- secondActivity.mVisibleRequested = true;
+ secondActivity.setVisibleRequested(true);
secondActivity.nowVisible = true;
secondActivity.setState(secondActivityState, "test");
@@ -1530,7 +1530,7 @@ public class ActivityRecordTests extends WindowTestsBase {
} else {
translucentActivity = new ActivityBuilder(mAtm).setTask(task).build();
}
- translucentActivity.mVisibleRequested = true;
+ translucentActivity.setVisibleRequested(true);
translucentActivity.nowVisible = true;
translucentActivity.setState(RESUMED, "test");
@@ -1546,7 +1546,7 @@ public class ActivityRecordTests extends WindowTestsBase {
// Finish the first activity
firstActivity.finishing = true;
- firstActivity.mVisibleRequested = true;
+ firstActivity.setVisibleRequested(true);
firstActivity.completeFinishing("test");
verify(firstActivity.mDisplayContent, times(2)).ensureActivitiesVisible(null /* starting */,
0 /* configChanges */ , false /* preserveWindows */,
@@ -1614,7 +1614,7 @@ public class ActivityRecordTests extends WindowTestsBase {
}, true /* traverseTopToBottom */);
activity.setState(STARTED, "test");
activity.finishing = true;
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
// Try to finish the last activity above the home stack.
activity.completeFinishing("test");
@@ -1909,7 +1909,7 @@ public class ActivityRecordTests extends WindowTestsBase {
// Simulate that the activity requests the same orientation as display.
activity.setOrientation(display.getConfiguration().orientation);
// Skip the real freezing.
- activity.mVisibleRequested = false;
+ activity.setVisibleRequested(false);
clearInvocations(activity);
activity.onCancelFixedRotationTransform(originalRotation);
// The implementation of cancellation must be executed.
@@ -2536,7 +2536,7 @@ public class ActivityRecordTests extends WindowTestsBase {
activity.setOccludesParent(true);
activity.setVisible(false);
- activity.mVisibleRequested = false;
+ activity.setVisibleRequested(false);
// Can not specify orientation if app isn't visible even though it occludes parent.
assertEquals(SCREEN_ORIENTATION_UNSET, activity.getOrientation());
// Can specify orientation if the current orientation candidate is orientation behind.
@@ -2913,7 +2913,7 @@ public class ActivityRecordTests extends WindowTestsBase {
task.addChild(taskFragment2, POSITION_TOP);
final ActivityRecord activity2 = new ActivityBuilder(mAtm)
.setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE).build();
- activity2.mVisibleRequested = true;
+ activity2.setVisibleRequested(true);
taskFragment2.addChild(activity2);
assertTrue(activity2.isResizeable());
activity1.reparent(taskFragment1, POSITION_TOP);
@@ -3059,7 +3059,7 @@ public class ActivityRecordTests extends WindowTestsBase {
.setCreateTask(true).build();
// By default, activity is visible.
assertTrue(activity.isVisible());
- assertTrue(activity.mVisibleRequested);
+ assertTrue(activity.isVisibleRequested());
assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
@@ -3068,7 +3068,7 @@ public class ActivityRecordTests extends WindowTestsBase {
// until we verify no logic relies on this behavior, we'll keep this as is.
activity.setVisibility(true);
assertTrue(activity.isVisible());
- assertTrue(activity.mVisibleRequested);
+ assertTrue(activity.isVisibleRequested());
assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
}
@@ -3079,7 +3079,7 @@ public class ActivityRecordTests extends WindowTestsBase {
.setCreateTask(true).build();
// By default, activity is visible.
assertTrue(activity.isVisible());
- assertTrue(activity.mVisibleRequested);
+ assertTrue(activity.isVisibleRequested());
assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
@@ -3087,7 +3087,7 @@ public class ActivityRecordTests extends WindowTestsBase {
// animation should be applied on this activity.
activity.setVisibility(false);
assertTrue(activity.isVisible());
- assertFalse(activity.mVisibleRequested);
+ assertFalse(activity.isVisibleRequested());
assertFalse(activity.mDisplayContent.mOpeningApps.contains(activity));
assertTrue(activity.mDisplayContent.mClosingApps.contains(activity));
}
@@ -3099,7 +3099,7 @@ public class ActivityRecordTests extends WindowTestsBase {
// Activiby is invisible. However ATMS requests it to become visible, since this is a top
// activity.
assertFalse(activity.isVisible());
- assertTrue(activity.mVisibleRequested);
+ assertTrue(activity.isVisibleRequested());
assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
@@ -3107,7 +3107,7 @@ public class ActivityRecordTests extends WindowTestsBase {
// animation should be applied on this activity.
activity.setVisibility(true);
assertFalse(activity.isVisible());
- assertTrue(activity.mVisibleRequested);
+ assertTrue(activity.isVisibleRequested());
assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
@@ -3130,7 +3130,7 @@ public class ActivityRecordTests extends WindowTestsBase {
// Activiby is invisible. However ATMS requests it to become visible, since this is a top
// activity.
assertFalse(activity.isVisible());
- assertTrue(activity.mVisibleRequested);
+ assertTrue(activity.isVisibleRequested());
assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
@@ -3138,7 +3138,7 @@ public class ActivityRecordTests extends WindowTestsBase {
// transition should be applied on this activity.
activity.setVisibility(false);
assertFalse(activity.isVisible());
- assertFalse(activity.mVisibleRequested);
+ assertFalse(activity.isVisibleRequested());
assertFalse(activity.mDisplayContent.mOpeningApps.contains(activity));
assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
}
@@ -3555,12 +3555,12 @@ public class ActivityRecordTests extends WindowTestsBase {
activity.reparent(taskFragment, POSITION_TOP);
// Ensure the activity visibility is updated even it is not shown to current user.
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
doReturn(false).when(activity).showToCurrentUser();
spyOn(taskFragment);
doReturn(false).when(taskFragment).shouldBeVisible(any());
display.ensureActivitiesVisible(null, 0, false, false);
- assertFalse(activity.mVisibleRequested);
+ assertFalse(activity.isVisibleRequested());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 6fe2d2cbe9d4..b4ffc2adbeea 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -505,7 +505,9 @@ public class ActivityStarterTests extends WindowTestsBase {
.setCreateActivity(true)
.build()
.getTopMostActivity();
- splitPrimaryActivity.mVisibleRequested = splitSecondActivity.mVisibleRequested = true;
+
+ splitPrimaryActivity.setVisibleRequested(true);
+ splitSecondActivity.setVisibleRequested(true);
assertEquals(splitOrg.mPrimary, splitPrimaryActivity.getRootTask());
assertEquals(splitOrg.mSecondary, splitSecondActivity.getRootTask());
@@ -518,7 +520,7 @@ public class ActivityStarterTests extends WindowTestsBase {
.setCreateActivity(true).build().getTopMostActivity();
final ActivityRecord translucentActivity = new TaskBuilder(mSupervisor)
.setCreateActivity(true).build().getTopMostActivity();
- assertTrue(activity.mVisibleRequested);
+ assertTrue(activity.isVisibleRequested());
final ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK,
false /* mockGetRootTask */);
@@ -919,7 +921,7 @@ public class ActivityStarterTests extends WindowTestsBase {
ACTIVITY_TYPE_STANDARD, false /* onTop */));
// Activity should start invisible since we are bringing it to front.
singleTaskActivity.setVisible(false);
- singleTaskActivity.mVisibleRequested = false;
+ singleTaskActivity.setVisibleRequested(false);
// Create another activity on top of the secondary display.
final Task topStack = secondaryTaskContainer.createRootTask(WINDOWING_MODE_FULLSCREEN,
@@ -1137,7 +1139,7 @@ public class ActivityStarterTests extends WindowTestsBase {
final ActivityStarter starter = prepareStarter(0 /* flags */);
final ActivityRecord target = new ActivityBuilder(mAtm).setCreateTask(true).build();
starter.mStartActivity = target;
- target.mVisibleRequested = false;
+ target.setVisibleRequested(false);
target.setTurnScreenOn(true);
// Assume the flag was consumed by relayout.
target.setCurrentLaunchCanTurnScreenOn(false);
@@ -1458,10 +1460,10 @@ public class ActivityStarterTests extends WindowTestsBase {
final ActivityRecord activityTop = new ActivityBuilder(mAtm).setTask(task).build();
activityBot.setVisible(false);
- activityBot.mVisibleRequested = false;
+ activityBot.setVisibleRequested(false);
assertTrue(activityTop.isVisible());
- assertTrue(activityTop.mVisibleRequested);
+ assertTrue(activityTop.isVisibleRequested());
final ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_REORDER_TO_FRONT
| FLAG_ACTIVITY_NEW_TASK, false /* mockGetRootTask */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 2fccd64bceca..368b750967c0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -344,7 +344,7 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
// Assume the activity is finishing and hidden because it was crashed.
activity.finishing = true;
- activity.mVisibleRequested = false;
+ activity.setVisibleRequested(false);
activity.setVisible(false);
activity.getTask().setPausingActivity(activity);
homeActivity.setState(PAUSED, "test");
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 43e79f9cbb15..f72933a697ae 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -122,7 +122,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
final ActivityRecord top = createActivityRecord(task);
top.setState(ActivityRecord.State.RESUMED, "test");
behind.setState(ActivityRecord.State.STARTED, "test");
- behind.mVisibleRequested = true;
+ behind.setVisibleRequested(true);
task.removeActivities("test", false /* excludingTaskOverlay */);
assertFalse(mDisplayContent.mAppTransition.isReady());
@@ -294,7 +294,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
final ActivityRecord activity2 = createActivityRecord(mDisplayContent);
activity2.setVisible(false);
- activity2.mVisibleRequested = false;
+ activity2.setVisibleRequested(false);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
@@ -319,12 +319,12 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// +- [Task2] - [ActivityRecord2] (opening, visible)
final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
activity1.setVisible(true);
- activity1.mVisibleRequested = true;
+ activity1.setVisibleRequested(true);
activity1.mRequestForceTransition = true;
final ActivityRecord activity2 = createActivityRecord(mDisplayContent);
activity2.setVisible(false);
- activity2.mVisibleRequested = false;
+ activity2.setVisibleRequested(false);
activity2.mRequestForceTransition = true;
final ArraySet<ActivityRecord> opening = new ArraySet<>();
@@ -391,7 +391,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
final ActivityRecord activity2 = createActivityRecord(mDisplayContent);
activity2.setVisible(false);
- activity2.mVisibleRequested = false;
+ activity2.setVisibleRequested(false);
attrs.setTitle("AppWindow2");
final TestWindowState appWindow2 = createWindowState(attrs, activity2);
appWindow2.mWillReplaceWindow = true;
@@ -424,17 +424,17 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// +- [ActivityRecord4] (invisible)
final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
activity1.setVisible(false);
- activity1.mVisibleRequested = true;
+ activity1.setVisibleRequested(true);
final ActivityRecord activity2 = createActivityRecord(mDisplayContent,
activity1.getTask());
activity2.setVisible(false);
- activity2.mVisibleRequested = false;
+ activity2.setVisibleRequested(false);
final ActivityRecord activity3 = createActivityRecord(mDisplayContent);
final ActivityRecord activity4 = createActivityRecord(mDisplayContent,
activity3.getTask());
activity4.setVisible(false);
- activity4.mVisibleRequested = false;
+ activity4.setVisibleRequested(false);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
@@ -459,7 +459,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// +- [ActivityRecord2] (closing, visible)
final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
activity1.setVisible(false);
- activity1.mVisibleRequested = true;
+ activity1.setVisibleRequested(true);
final ActivityRecord activity2 = createActivityRecord(mDisplayContent,
activity1.getTask());
@@ -490,7 +490,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
activity1.setVisible(false);
- activity1.mVisibleRequested = true;
+ activity1.setVisibleRequested(true);
activity1.setOccludesParent(false);
final ActivityRecord activity2 = createActivityRecord(mDisplayContent,
@@ -528,13 +528,13 @@ public class AppTransitionControllerTest extends WindowTestsBase {
final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
activity1.setVisible(false);
- activity1.mVisibleRequested = true;
+ activity1.setVisibleRequested(true);
activity1.setOccludesParent(false);
final ActivityRecord activity2 = createActivityRecord(mDisplayContent,
activity1.getTask());
activity2.setVisible(false);
- activity2.mVisibleRequested = true;
+ activity2.setVisibleRequested(true);
final ActivityRecord activity3 = createActivityRecord(mDisplayContent);
activity3.setOccludesParent(false);
@@ -567,7 +567,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
final Task parentTask = createTask(mDisplayContent);
final ActivityRecord activity1 = createActivityRecordWithParentTask(parentTask);
activity1.setVisible(false);
- activity1.mVisibleRequested = true;
+ activity1.setVisibleRequested(true);
final ActivityRecord activity2 = createActivityRecordWithParentTask(parentTask);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
@@ -600,10 +600,10 @@ public class AppTransitionControllerTest extends WindowTestsBase {
splitRoot1.setAdjacentTaskFragment(splitRoot2);
final ActivityRecord activity1 = createActivityRecordWithParentTask(splitRoot1);
activity1.setVisible(false);
- activity1.mVisibleRequested = true;
+ activity1.setVisibleRequested(true);
final ActivityRecord activity2 = createActivityRecordWithParentTask(splitRoot2);
activity2.setVisible(false);
- activity2.mVisibleRequested = true;
+ activity2.setVisibleRequested(true);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
@@ -626,13 +626,13 @@ public class AppTransitionControllerTest extends WindowTestsBase {
false /* createEmbeddedTask */);
final ActivityRecord activity1 = taskFragment1.getTopMostActivity();
activity1.setVisible(false);
- activity1.mVisibleRequested = true;
+ activity1.setVisibleRequested(true);
final TaskFragment taskFragment2 = createTaskFragmentWithParentTask(parentTask,
false /* createEmbeddedTask */);
final ActivityRecord activity2 = taskFragment2.getTopMostActivity();
activity2.setVisible(true);
- activity2.mVisibleRequested = false;
+ activity2.setVisibleRequested(false);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
@@ -657,13 +657,13 @@ public class AppTransitionControllerTest extends WindowTestsBase {
true /* createEmbeddedTask */);
final ActivityRecord activity1 = taskFragment1.getTopMostActivity();
activity1.setVisible(false);
- activity1.mVisibleRequested = true;
+ activity1.setVisibleRequested(true);
final TaskFragment taskFragment2 = createTaskFragmentWithParentTask(parentTask,
true /* createEmbeddedTask */);
final ActivityRecord activity2 = taskFragment2.getTopMostActivity();
activity2.setVisible(true);
- activity2.mVisibleRequested = false;
+ activity2.setVisibleRequested(false);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
@@ -688,11 +688,11 @@ public class AppTransitionControllerTest extends WindowTestsBase {
false /* createEmbeddedTask */);
final ActivityRecord activity1 = taskFragment1.getTopMostActivity();
activity1.setVisible(false);
- activity1.mVisibleRequested = true;
+ activity1.setVisibleRequested(true);
final ActivityRecord activity2 = createActivityRecord(mDisplayContent);
activity2.setVisible(true);
- activity2.mVisibleRequested = false;
+ activity2.setVisibleRequested(false);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
@@ -718,11 +718,11 @@ public class AppTransitionControllerTest extends WindowTestsBase {
false /* createEmbeddedTask */);
final ActivityRecord activity1 = taskFragment1.getTopMostActivity();
activity1.setVisible(true);
- activity1.mVisibleRequested = false;
+ activity1.setVisibleRequested(false);
final ActivityRecord activity2 = createActivityRecord(mDisplayContent);
activity2.setVisible(false);
- activity2.mVisibleRequested = true;
+ activity2.setVisibleRequested(true);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity2);
@@ -745,13 +745,13 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// +- [Task2] (embedded) - [ActivityRecord2] (opening, invisible)
final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
activity1.setVisible(false);
- activity1.mVisibleRequested = true;
+ activity1.setVisibleRequested(true);
final Task task2 = createTask(mDisplayContent);
task2.mRemoveWithTaskOrganizer = true;
final ActivityRecord activity2 = createActivityRecord(task2);
activity2.setVisible(false);
- activity2.mVisibleRequested = true;
+ activity2.setVisibleRequested(true);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
@@ -779,7 +779,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
final ActivityRecord activity1 = createActivityRecord(task);
activity1.setVisible(false);
- activity1.mVisibleRequested = true;
+ activity1.setVisibleRequested(true);
final ActivityRecord activity2 = createActivityRecord(task);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
@@ -1295,6 +1295,8 @@ public class AppTransitionControllerTest extends WindowTestsBase {
@Test
public void testTransitionGoodToGoForTaskFragments_detachedApp() {
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
+ final ITaskFragmentOrganizer iOrganizer = getITaskFragmentOrganizer(organizer);
+ mAtm.mTaskFragmentOrganizerController.registerOrganizer(iOrganizer);
final Task task = createTask(mDisplayContent);
final TaskFragment changeTaskFragment =
createTaskFragmentWithEmbeddedActivity(task, organizer);
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 8cfe503d61d7..32c3a49907be 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -420,11 +420,11 @@ public class AppTransitionTests extends WindowTestsBase {
// Simulate activity1 launches activity2.
final ActivityRecord activity1 = createActivityRecord(task);
activity1.setVisible(true);
- activity1.mVisibleRequested = false;
+ activity1.setVisibleRequested(false);
activity1.allDrawn = true;
final ActivityRecord activity2 = createActivityRecord(task);
activity2.setVisible(false);
- activity2.mVisibleRequested = true;
+ activity2.setVisibleRequested(true);
activity2.allDrawn = true;
dc.mClosingApps.add(activity1);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 63f4f5f5b9fb..98e68ca99720 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -588,7 +588,7 @@ public class DisplayContentTests extends WindowTestsBase {
assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
// Make sure top focused display not changed if there is a focused app.
- window1.mActivityRecord.mVisibleRequested = false;
+ window1.mActivityRecord.setVisibleRequested(false);
window1.getDisplayContent().setFocusedApp(window1.mActivityRecord);
updateFocusedWindow();
assertTrue(!window1.isFocused());
@@ -1104,7 +1104,7 @@ public class DisplayContentTests extends WindowTestsBase {
public void testOrientationBehind() {
final ActivityRecord prev = new ActivityBuilder(mAtm).setCreateTask(true)
.setScreenOrientation(getRotatedOrientation(mDisplayContent)).build();
- prev.mVisibleRequested = false;
+ prev.setVisibleRequested(false);
final ActivityRecord top = new ActivityBuilder(mAtm).setCreateTask(true)
.setScreenOrientation(SCREEN_ORIENTATION_BEHIND).build();
assertNotEquals(WindowConfiguration.ROTATION_UNDEFINED,
diff --git a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
index 2956c14155b9..3ab4495bd7ca 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
@@ -206,7 +206,7 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
assertThat(newTaskBounds).isEqualTo(newDagBounds);
// Activity config bounds is unchanged, size compat bounds is (860x[860x860/1200=616])
- assertThat(mFirstActivity.getSizeCompatScale()).isLessThan(1f);
+ assertThat(mFirstActivity.getCompatScale()).isLessThan(1f);
assertThat(activityConfigBounds.width()).isEqualTo(activityBounds.width());
assertThat(activityConfigBounds.height()).isEqualTo(activityBounds.height());
assertThat(activitySizeCompatBounds.height()).isEqualTo(newTaskBounds.height());
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 8546763aebec..48084743afde 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -172,12 +172,12 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
// executed.
final ActivityRecord activity1 = createActivityRecord(task);
activity1.setVisible(true);
- activity1.mVisibleRequested = false;
+ activity1.setVisibleRequested(false);
activity1.addWindow(createWindowState(new LayoutParams(TYPE_BASE_APPLICATION), activity1));
final ActivityRecord activity2 = createActivityRecord(task);
activity2.setVisible(false);
- activity2.mVisibleRequested = true;
+ activity2.setVisibleRequested(true);
mDefaultDisplay.getConfiguration().windowConfiguration.setRotation(
mDefaultDisplay.getRotation());
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index a1d6a5006fef..95623f0ab490 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -111,14 +111,14 @@ public class RecentsAnimationTest extends WindowTestsBase {
RecentsAnimationCallbacks recentsAnimation = startRecentsActivity(
mRecentsComponent, true /* getRecentsAnimation */);
// The launch-behind state should make the recents activity visible.
- assertTrue(recentActivity.mVisibleRequested);
+ assertTrue(recentActivity.isVisibleRequested());
assertEquals(ActivityTaskManagerService.DEMOTE_TOP_REASON_ANIMATING_RECENTS,
mAtm.mDemoteTopAppReasons);
// Simulate the animation is cancelled without changing the stack order.
recentsAnimation.onAnimationFinished(REORDER_KEEP_IN_PLACE, false /* sendUserLeaveHint */);
// The non-top recents activity should be invisible by the restored launch-behind state.
- assertFalse(recentActivity.mVisibleRequested);
+ assertFalse(recentActivity.isVisibleRequested());
assertEquals(0, mAtm.mDemoteTopAppReasons);
}
@@ -163,7 +163,7 @@ public class RecentsAnimationTest extends WindowTestsBase {
// The activity is started in background so it should be invisible and will be stopped.
assertThat(recentsActivity).isNotNull();
assertThat(mSupervisor.mStoppingActivities).contains(recentsActivity);
- assertFalse(recentsActivity.mVisibleRequested);
+ assertFalse(recentsActivity.isVisibleRequested());
// Assume it is stopped to test next use case.
recentsActivity.activityStopped(null /* newIcicle */, null /* newPersistentState */,
@@ -359,7 +359,7 @@ public class RecentsAnimationTest extends WindowTestsBase {
true);
// Ensure we find the task for the right user and it is made visible
- assertTrue(otherUserHomeActivity.mVisibleRequested);
+ assertTrue(otherUserHomeActivity.isVisibleRequested());
}
private void startRecentsActivity() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java b/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
index b46e90da3944..db26b272b635 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
@@ -1068,7 +1068,7 @@ public class RootTaskTests extends WindowTestsBase {
activity.app = null;
overlayActivity.app = null;
// Simulate the process is dead
- activity.mVisibleRequested = false;
+ activity.setVisibleRequested(false);
activity.setState(DESTROYED, "Test");
assertEquals(2, task.getChildCount());
@@ -1205,7 +1205,7 @@ public class RootTaskTests extends WindowTestsBase {
// There is still an activity1 in rootTask1 so the activity2 should be added to finishing
// list that will be destroyed until idle.
- rootTask2.getTopNonFinishingActivity().mVisibleRequested = true;
+ rootTask2.getTopNonFinishingActivity().setVisibleRequested(true);
final ActivityRecord activity2 = finishTopActivity(rootTask2);
assertEquals(STOPPING, activity2.getState());
assertThat(mSupervisor.mStoppingActivities).contains(activity2);
@@ -1410,7 +1410,7 @@ public class RootTaskTests extends WindowTestsBase {
new ActivityBuilder(mAtm).setTask(task).build();
// The scenario we are testing is when the app isn't visible yet.
nonTopVisibleActivity.setVisible(false);
- nonTopVisibleActivity.mVisibleRequested = false;
+ nonTopVisibleActivity.setVisibleRequested(false);
doReturn(false).when(nonTopVisibleActivity).attachedToProcess();
doReturn(true).when(nonTopVisibleActivity).shouldBeVisibleUnchecked();
doNothing().when(mSupervisor).startSpecificActivity(any(), anyBoolean(),
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 64c1e05da2cd..b89643cba116 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -172,7 +172,7 @@ public class RootWindowContainerTests extends WindowTestsBase {
public void testTaskLayerRank() {
final Task rootTask = new TaskBuilder(mSupervisor).build();
final Task task1 = new TaskBuilder(mSupervisor).setParentTaskFragment(rootTask).build();
- new ActivityBuilder(mAtm).setTask(task1).build().mVisibleRequested = true;
+ new ActivityBuilder(mAtm).setTask(task1).build().setVisibleRequested(true);
mWm.mRoot.rankTaskLayers();
assertEquals(1, task1.mLayerRank);
@@ -180,7 +180,7 @@ public class RootWindowContainerTests extends WindowTestsBase {
assertEquals(Task.LAYER_RANK_INVISIBLE, rootTask.mLayerRank);
final Task task2 = new TaskBuilder(mSupervisor).build();
- new ActivityBuilder(mAtm).setTask(task2).build().mVisibleRequested = true;
+ new ActivityBuilder(mAtm).setTask(task2).build().setVisibleRequested(true);
mWm.mRoot.rankTaskLayers();
// Note that ensureActivitiesVisible is disabled in SystemServicesTestRule, so both the
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 06eea298600c..babad4d4d744 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -167,7 +167,7 @@ public class SizeCompatTests extends WindowTestsBase {
public void testRestartProcessIfVisible() {
setUpDisplaySizeWithApp(1000, 2500);
doNothing().when(mSupervisor).scheduleRestartTimeout(mActivity);
- mActivity.mVisibleRequested = true;
+ mActivity.setVisibleRequested(true);
mActivity.setSavedState(null /* savedState */);
mActivity.setState(RESUMED, "testRestart");
prepareUnresizable(mActivity, 1.5f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED);
@@ -551,7 +551,7 @@ public class SizeCompatTests extends WindowTestsBase {
resizeDisplay(display, 900, 1800);
mActivity.setState(STOPPED, "testSizeCompatMode");
- mActivity.mVisibleRequested = false;
+ mActivity.setVisibleRequested(false);
mActivity.visibleIgnoringKeyguard = false;
mActivity.app.setReportedProcState(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY);
mActivity.app.computeProcessActivityState();
@@ -603,7 +603,7 @@ public class SizeCompatTests extends WindowTestsBase {
// Make the activity resizable again by restarting it
clearInvocations(mTask);
mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;
- mActivity.mVisibleRequested = true;
+ mActivity.setVisibleRequested(true);
mActivity.restartProcessIfVisible();
// The full lifecycle isn't hooked up so manually set state to resumed
mActivity.setState(RESUMED, "testHandleActivitySizeCompatModeChanged");
@@ -3185,7 +3185,7 @@ public class SizeCompatTests extends WindowTestsBase {
task.mResizeMode = activity.info.resizeMode;
task.getRootActivity().info.resizeMode = activity.info.resizeMode;
}
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
if (maxAspect >= 0) {
activity.info.setMaxAspectRatio(maxAspect);
}
@@ -3205,7 +3205,7 @@ public class SizeCompatTests extends WindowTestsBase {
/** Asserts that the size of activity is larger than its parent so it is scaling. */
private void assertScaled() {
assertTrue(mActivity.inSizeCompatMode());
- assertNotEquals(1f, mActivity.getSizeCompatScale(), 0.0001f /* delta */);
+ assertNotEquals(1f, mActivity.getCompatScale(), 0.0001f /* delta */);
}
/** Asserts that the activity is best fitted in the parent. */
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
index 7f09606d1c3a..e660db57fb69 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
@@ -398,7 +398,7 @@ public class TaskDisplayAreaTests extends WindowTestsBase {
.setParentTask(rootHomeTask).setCreateTask(true).build();
}
homeActivity.setVisible(false);
- homeActivity.mVisibleRequested = true;
+ homeActivity.setVisibleRequested(true);
assertFalse(rootHomeTask.isVisible());
assertEquals(defaultTaskDisplayArea.getOrientation(), rootHomeTask.getOrientation());
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index 2b493145f854..db65f49465bc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -370,7 +370,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
mController.onActivityReparentedToTask(activity);
mController.dispatchPendingEvents();
- assertTaskFragmentParentInfoChangedTransaction(task);
+ // There will not be TaskFragmentParentInfoChanged because Task visible request is changed
+ // before the organized TaskFragment is added to the Task.
assertActivityReparentedToTaskTransaction(task.mTaskId, activity.intent, activity.token);
}
@@ -552,10 +553,9 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
@Test
public void testApplyTransaction_enforceHierarchyChange_createTaskFragment() {
final ActivityRecord ownerActivity = createActivityRecord(mDisplayContent);
- final IBinder fragmentToken = new Binder();
// Allow organizer to create TaskFragment and start/reparent activity to TaskFragment.
- createTaskFragmentFromOrganizer(mTransaction, ownerActivity, fragmentToken);
+ createTaskFragmentFromOrganizer(mTransaction, ownerActivity, mFragmentToken);
mTransaction.startActivityInTaskFragment(
mFragmentToken, null /* callerToken */, new Intent(), null /* activityOptions */);
mTransaction.reparentActivityToTaskFragment(mFragmentToken, mock(IBinder.class));
@@ -564,7 +564,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
assertApplyTransactionAllowed(mTransaction);
// Successfully created a TaskFragment.
- final TaskFragment taskFragment = mWindowOrganizerController.getTaskFragment(fragmentToken);
+ final TaskFragment taskFragment = mWindowOrganizerController.getTaskFragment(
+ mFragmentToken);
assertNotNull(taskFragment);
assertEquals(ownerActivity.getTask(), taskFragment.getTask());
}
@@ -703,6 +704,40 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
}
@Test
+ public void testApplyTransaction_createTaskFragment_withPairedPrimaryFragmentToken() {
+ final Task task = createTask(mDisplayContent);
+ mTaskFragment = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .setFragmentToken(mFragmentToken)
+ .createActivityCount(1)
+ .build();
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
+ final ActivityRecord activityOnTop = createActivityRecord(task);
+ final int uid = Binder.getCallingUid();
+ activityOnTop.info.applicationInfo.uid = uid;
+ activityOnTop.getTask().effectiveUid = uid;
+ final IBinder fragmentToken1 = new Binder();
+ final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder(
+ mOrganizerToken, fragmentToken1, activityOnTop.token)
+ .setPairedPrimaryFragmentToken(mFragmentToken)
+ .build();
+ mTransaction.setTaskFragmentOrganizer(mIOrganizer);
+ mTransaction.createTaskFragment(params);
+ assertApplyTransactionAllowed(mTransaction);
+
+ // Successfully created a TaskFragment.
+ final TaskFragment taskFragment = mWindowOrganizerController.getTaskFragment(
+ fragmentToken1);
+ assertNotNull(taskFragment);
+ // The new TaskFragment should be positioned right above the paired TaskFragment.
+ assertEquals(task.mChildren.indexOf(mTaskFragment) + 1,
+ task.mChildren.indexOf(taskFragment));
+ // The top activity should remain on top.
+ assertEquals(task.mChildren.indexOf(taskFragment) + 1,
+ task.mChildren.indexOf(activityOnTop));
+ }
+
+ @Test
public void testApplyTransaction_enforceHierarchyChange_reparentChildren() {
doReturn(true).when(mTaskFragment).isAttached();
@@ -1159,6 +1194,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
doReturn(false).when(task).shouldBeVisible(any());
// Dispatch the initial event in the Task to update the Task visibility to the organizer.
+ clearInvocations(mOrganizer);
mController.onTaskFragmentAppeared(mIOrganizer, taskFragment);
mController.dispatchPendingEvents();
verify(mOrganizer).onTransactionReady(any());
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 999523f3ea19..3fd9dfe8f882 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -134,8 +134,8 @@ public class TransitionTests extends WindowTestsBase {
changes.put(closing, new Transition.ChangeInfo(true /* vis */, true /* exChg */));
fillChangeMap(changes, newTask);
// End states.
- closing.mVisibleRequested = false;
- opening.mVisibleRequested = true;
+ closing.setVisibleRequested(false);
+ opening.setVisibleRequested(true);
final int transit = transition.mType;
int flags = 0;
@@ -198,9 +198,9 @@ public class TransitionTests extends WindowTestsBase {
changes.put(closing, new Transition.ChangeInfo(true /* vis */, true /* exChg */));
fillChangeMap(changes, newTask);
// End states.
- closing.mVisibleRequested = false;
- opening.mVisibleRequested = true;
- opening2.mVisibleRequested = true;
+ closing.setVisibleRequested(false);
+ opening.setVisibleRequested(true);
+ opening2.setVisibleRequested(true);
final int transit = transition.mType;
int flags = 0;
@@ -247,8 +247,8 @@ public class TransitionTests extends WindowTestsBase {
fillChangeMap(changes, tda);
// End states.
- showing.mVisibleRequested = true;
- showing2.mVisibleRequested = true;
+ showing.setVisibleRequested(true);
+ showing2.setVisibleRequested(true);
final int transit = transition.mType;
int flags = 0;
@@ -283,16 +283,16 @@ public class TransitionTests extends WindowTestsBase {
final Task openTask = createTask(mDisplayContent);
final ActivityRecord opening = createActivityRecord(openTask);
- opening.mVisibleRequested = false; // starts invisible
+ opening.setVisibleRequested(false); // starts invisible
final Task closeTask = createTask(mDisplayContent);
final ActivityRecord closing = createActivityRecord(closeTask);
- closing.mVisibleRequested = true; // starts visible
+ closing.setVisibleRequested(true); // starts visible
transition.collectExistenceChange(openTask);
transition.collect(opening);
transition.collect(closing);
- opening.mVisibleRequested = true;
- closing.mVisibleRequested = false;
+ opening.setVisibleRequested(true);
+ closing.setVisibleRequested(false);
ArrayList<WindowContainer> targets = Transition.calculateTargets(
transition.mParticipants, transition.mChanges);
@@ -320,7 +320,7 @@ public class TransitionTests extends WindowTestsBase {
WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
final ActivityRecord act = createActivityRecord(tasks[i]);
// alternate so that the transition doesn't get promoted to the display area
- act.mVisibleRequested = (i % 2) == 0; // starts invisible
+ act.setVisibleRequested((i % 2) == 0); // starts invisible
}
// doesn't matter which order collected since participants is a set
@@ -328,7 +328,7 @@ public class TransitionTests extends WindowTestsBase {
transition.collectExistenceChange(tasks[i]);
final ActivityRecord act = tasks[i].getTopMostActivity();
transition.collect(act);
- tasks[i].getTopMostActivity().mVisibleRequested = (i % 2) != 0;
+ tasks[i].getTopMostActivity().setVisibleRequested((i % 2) != 0);
}
ArrayList<WindowContainer> targets = Transition.calculateTargets(
@@ -357,7 +357,7 @@ public class TransitionTests extends WindowTestsBase {
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
final ActivityRecord act = createActivityRecord(tasks[i]);
// alternate so that the transition doesn't get promoted to the display area
- act.mVisibleRequested = (i % 2) == 0; // starts invisible
+ act.setVisibleRequested((i % 2) == 0); // starts invisible
act.visibleIgnoringKeyguard = (i % 2) == 0;
if (i == showWallpaperTask) {
doReturn(true).when(act).showWallpaper();
@@ -378,7 +378,7 @@ public class TransitionTests extends WindowTestsBase {
transition.collectExistenceChange(tasks[i]);
final ActivityRecord act = tasks[i].getTopMostActivity();
transition.collect(act);
- tasks[i].getTopMostActivity().mVisibleRequested = (i % 2) != 0;
+ tasks[i].getTopMostActivity().setVisibleRequested((i % 2) != 0);
}
ArrayList<WindowContainer> targets = Transition.calculateTargets(
@@ -414,9 +414,9 @@ public class TransitionTests extends WindowTestsBase {
changes.put(closing, new Transition.ChangeInfo(true /* vis */, true /* exChg */));
fillChangeMap(changes, topTask);
// End states.
- showing.mVisibleRequested = true;
- closing.mVisibleRequested = false;
- hiding.mVisibleRequested = false;
+ showing.setVisibleRequested(true);
+ closing.setVisibleRequested(false);
+ hiding.setVisibleRequested(false);
participants.add(belowTask);
participants.add(hiding);
@@ -446,9 +446,9 @@ public class TransitionTests extends WindowTestsBase {
changes.put(closing, new Transition.ChangeInfo(true /* vis */, false /* exChg */));
fillChangeMap(changes, topTask);
// End states.
- showing.mVisibleRequested = true;
- opening.mVisibleRequested = true;
- closing.mVisibleRequested = false;
+ showing.setVisibleRequested(true);
+ opening.setVisibleRequested(true);
+ closing.setVisibleRequested(false);
participants.add(belowTask);
participants.add(showing);
@@ -528,19 +528,19 @@ public class TransitionTests extends WindowTestsBase {
@Test
public void testOpenActivityInTheSameTaskWithDisplayChange() {
final ActivityRecord closing = createActivityRecord(mDisplayContent);
- closing.mVisibleRequested = true;
+ closing.setVisibleRequested(true);
final Task task = closing.getTask();
makeTaskOrganized(task);
final ActivityRecord opening = createActivityRecord(task);
- opening.mVisibleRequested = false;
+ opening.setVisibleRequested(false);
makeDisplayAreaOrganized(mDisplayContent.getDefaultTaskDisplayArea(), mDisplayContent);
final WindowContainer<?>[] wcs = { closing, opening, task, mDisplayContent };
final Transition transition = createTestTransition(TRANSIT_OPEN);
for (WindowContainer<?> wc : wcs) {
transition.collect(wc);
}
- closing.mVisibleRequested = false;
- opening.mVisibleRequested = true;
+ closing.setVisibleRequested(false);
+ opening.setVisibleRequested(true);
final int newRotation = mDisplayContent.getWindowConfiguration().getRotation() + 1;
for (WindowContainer<?> wc : wcs) {
wc.getWindowConfiguration().setRotation(newRotation);
@@ -583,9 +583,9 @@ public class TransitionTests extends WindowTestsBase {
changes.put(changeInChange, new Transition.ChangeInfo(true /* vis */, false /* exChg */));
fillChangeMap(changes, openTask);
// End states.
- changeInChange.mVisibleRequested = true;
- openInOpen.mVisibleRequested = true;
- openInChange.mVisibleRequested = true;
+ changeInChange.setVisibleRequested(true);
+ openInOpen.setVisibleRequested(true);
+ openInChange.setVisibleRequested(true);
final int transit = transition.mType;
int flags = 0;
@@ -641,8 +641,8 @@ public class TransitionTests extends WindowTestsBase {
changes.put(closing, new Transition.ChangeInfo(true /* vis */, false /* exChg */));
fillChangeMap(changes, newTask);
// End states.
- closing.mVisibleRequested = true;
- opening.mVisibleRequested = true;
+ closing.setVisibleRequested(true);
+ opening.setVisibleRequested(true);
final int transit = transition.mType;
int flags = 0;
@@ -682,8 +682,8 @@ public class TransitionTests extends WindowTestsBase {
changes.put(closing, new Transition.ChangeInfo(true /* vis */, false /* exChg */));
fillChangeMap(changes, newTask);
// End states.
- closing.mVisibleRequested = true;
- opening.mVisibleRequested = true;
+ closing.setVisibleRequested(true);
+ opening.setVisibleRequested(true);
final int transit = transition.mType;
int flags = 0;
@@ -959,7 +959,7 @@ public class TransitionTests extends WindowTestsBase {
home.mTransitionController.requestStartTransition(transition, home.getTask(),
null /* remoteTransition */, null /* displayChange */);
transition.collectExistenceChange(home);
- home.mVisibleRequested = true;
+ home.setVisibleRequested(true);
mDisplayContent.setFixedRotationLaunchingAppUnchecked(home);
doReturn(true).when(home).hasFixedRotationTransform(any());
player.startTransition();
@@ -995,12 +995,12 @@ public class TransitionTests extends WindowTestsBase {
// Start out with task2 visible and set up a transition that closes task2 and opens task1
final Task task1 = createTask(mDisplayContent);
final ActivityRecord activity1 = createActivityRecord(task1);
- activity1.mVisibleRequested = false;
+ activity1.setVisibleRequested(false);
activity1.setVisible(false);
final Task task2 = createTask(mDisplayContent);
makeTaskOrganized(task1, task2);
final ActivityRecord activity2 = createActivityRecord(task1);
- activity2.mVisibleRequested = true;
+ activity2.setVisibleRequested(true);
activity2.setVisible(true);
openTransition.collectExistenceChange(task1);
@@ -1008,9 +1008,9 @@ public class TransitionTests extends WindowTestsBase {
openTransition.collectExistenceChange(task2);
openTransition.collectExistenceChange(activity2);
- activity1.mVisibleRequested = true;
+ activity1.setVisibleRequested(true);
activity1.setVisible(true);
- activity2.mVisibleRequested = false;
+ activity2.setVisibleRequested(false);
// Using abort to force-finish the sync (since we can't wait for drawing in unit test).
// We didn't call abort on the transition itself, so it will still run onTransactionReady
@@ -1026,8 +1026,8 @@ public class TransitionTests extends WindowTestsBase {
closeTransition.collectExistenceChange(task2);
closeTransition.collectExistenceChange(activity2);
- activity1.mVisibleRequested = false;
- activity2.mVisibleRequested = true;
+ activity1.setVisibleRequested(false);
+ activity2.setVisibleRequested(true);
openTransition.finishTransition();
@@ -1069,12 +1069,12 @@ public class TransitionTests extends WindowTestsBase {
// Start out with task2 visible and set up a transition that closes task2 and opens task1
final Task task1 = createTask(mDisplayContent);
final ActivityRecord activity1 = createActivityRecord(task1);
- activity1.mVisibleRequested = false;
+ activity1.setVisibleRequested(false);
activity1.setVisible(false);
final Task task2 = createTask(mDisplayContent);
makeTaskOrganized(task1, task2);
final ActivityRecord activity2 = createActivityRecord(task2);
- activity2.mVisibleRequested = true;
+ activity2.setVisibleRequested(true);
activity2.setVisible(true);
openTransition.collectExistenceChange(task1);
@@ -1082,9 +1082,9 @@ public class TransitionTests extends WindowTestsBase {
openTransition.collectExistenceChange(task2);
openTransition.collectExistenceChange(activity2);
- activity1.mVisibleRequested = true;
+ activity1.setVisibleRequested(true);
activity1.setVisible(true);
- activity2.mVisibleRequested = false;
+ activity2.setVisibleRequested(false);
// Using abort to force-finish the sync (since we can't wait for drawing in unit test).
// We didn't call abort on the transition itself, so it will still run onTransactionReady
@@ -1104,8 +1104,8 @@ public class TransitionTests extends WindowTestsBase {
closeTransition.collectExistenceChange(activity2);
closeTransition.setTransientLaunch(activity2, null /* restoreBelow */);
- activity1.mVisibleRequested = false;
- activity2.mVisibleRequested = true;
+ activity1.setVisibleRequested(false);
+ activity2.setVisibleRequested(true);
activity2.setVisible(true);
// Using abort to force-finish the sync (since we obviously can't wait for drawing).
@@ -1163,8 +1163,8 @@ public class TransitionTests extends WindowTestsBase {
changes.put(activity0, new Transition.ChangeInfo(true /* vis */, false /* exChg */));
changes.put(activity1, new Transition.ChangeInfo(false /* vis */, false /* exChg */));
// End states.
- activity0.mVisibleRequested = false;
- activity1.mVisibleRequested = true;
+ activity0.setVisibleRequested(false);
+ activity1.setVisibleRequested(true);
participants.add(activity0);
participants.add(activity1);
@@ -1207,9 +1207,9 @@ public class TransitionTests extends WindowTestsBase {
changes.put(nonEmbeddedActivity, new Transition.ChangeInfo(true /* vis */,
false /* exChg */));
// End states.
- closingActivity.mVisibleRequested = false;
- openingActivity.mVisibleRequested = true;
- nonEmbeddedActivity.mVisibleRequested = false;
+ closingActivity.setVisibleRequested(false);
+ openingActivity.setVisibleRequested(true);
+ nonEmbeddedActivity.setVisibleRequested(false);
participants.add(closingActivity);
participants.add(openingActivity);
@@ -1252,8 +1252,8 @@ public class TransitionTests extends WindowTestsBase {
false /* exChg */));
changes.put(embeddedTf, new Transition.ChangeInfo(false /* vis */, true /* exChg */));
// End states.
- nonEmbeddedActivity.mVisibleRequested = false;
- embeddedActivity.mVisibleRequested = true;
+ nonEmbeddedActivity.setVisibleRequested(false);
+ embeddedActivity.setVisibleRequested(true);
embeddedTf.setBounds(new Rect(0, 0, 500, 500));
participants.add(nonEmbeddedActivity);
@@ -1282,11 +1282,11 @@ public class TransitionTests extends WindowTestsBase {
final ActivityRecord activity = createActivityRecord(task);
// Start states: set bounds to make sure the start bounds is ignored if it is not visible.
activity.getConfiguration().windowConfiguration.setBounds(new Rect(0, 0, 250, 500));
- activity.mVisibleRequested = false;
+ activity.setVisibleRequested(false);
changes.put(activity, new Transition.ChangeInfo(activity));
// End states: reset bounds to fill Task.
activity.getConfiguration().windowConfiguration.setBounds(taskBounds);
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
participants.add(activity);
final ArrayList<WindowContainer> targets = Transition.calculateTargets(
@@ -1310,11 +1310,11 @@ public class TransitionTests extends WindowTestsBase {
task.getConfiguration().windowConfiguration.setBounds(taskBounds);
final ActivityRecord activity = createActivityRecord(task);
// Start states: fills Task without override.
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
changes.put(activity, new Transition.ChangeInfo(activity));
// End states: set bounds to make sure the start bounds is ignored if it is not visible.
activity.getConfiguration().windowConfiguration.setBounds(new Rect(0, 0, 250, 500));
- activity.mVisibleRequested = false;
+ activity.setVisibleRequested(false);
participants.add(activity);
final ArrayList<WindowContainer> targets = Transition.calculateTargets(
@@ -1337,12 +1337,12 @@ public class TransitionTests extends WindowTestsBase {
final Task lastParent = createTask(mDisplayContent);
final Task newParent = createTask(mDisplayContent);
final ActivityRecord activity = createActivityRecord(lastParent);
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
// Skip manipulate the SurfaceControl.
doNothing().when(activity).setDropInputMode(anyInt());
changes.put(activity, new Transition.ChangeInfo(activity));
activity.reparent(newParent, POSITION_TOP);
- activity.mVisibleRequested = false;
+ activity.setVisibleRequested(false);
participants.add(activity);
final ArrayList<WindowContainer> targets = Transition.calculateTargets(
@@ -1362,7 +1362,7 @@ public class TransitionTests extends WindowTestsBase {
final Task task = createTask(mDisplayContent);
task.setBounds(new Rect(0, 0, 2000, 1000));
final ActivityRecord activity = createActivityRecord(task);
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
// Skip manipulate the SurfaceControl.
doNothing().when(activity).setDropInputMode(anyInt());
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
@@ -1410,13 +1410,13 @@ public class TransitionTests extends WindowTestsBase {
task.setTaskDescription(taskDescription);
// Start states:
- embeddedActivity.mVisibleRequested = true;
- nonEmbeddedActivity.mVisibleRequested = false;
+ embeddedActivity.setVisibleRequested(true);
+ nonEmbeddedActivity.setVisibleRequested(false);
changes.put(embeddedTf, new Transition.ChangeInfo(embeddedTf));
changes.put(nonEmbeddedActivity, new Transition.ChangeInfo(nonEmbeddedActivity));
// End states:
- embeddedActivity.mVisibleRequested = false;
- nonEmbeddedActivity.mVisibleRequested = true;
+ embeddedActivity.setVisibleRequested(false);
+ nonEmbeddedActivity.setVisibleRequested(true);
participants.add(embeddedTf);
participants.add(nonEmbeddedActivity);
@@ -1529,7 +1529,7 @@ public class TransitionTests extends WindowTestsBase {
final ActivityRecord activity = createActivityRecord(lastParent);
doReturn(true).when(lastParent).shouldRemoveSelfOnLastChildRemoval();
doNothing().when(activity).setDropInputMode(anyInt());
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
final Transition transition = new Transition(TRANSIT_CHANGE, 0 /* flags */,
activity.mTransitionController, mWm.mSyncEngine);
diff --git a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index 45e114130420..2fccb88ad8de 100644
--- a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -95,7 +95,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
final ActivityRecord activity = createNonAttachedActivityRecord(mDisplayContent);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
activity.finishing = true;
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
activity.setVisibility(false, false);
assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
index aab70b5f9004..06a79f47de55 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -311,12 +311,12 @@ public class WallpaperControllerTests extends WindowTestsBase {
r.applyFixedRotationTransform(mDisplayContent.getDisplayInfo(),
mDisplayContent.mDisplayFrames, mDisplayContent.getConfiguration());
// Invisible requested activity should not share its rotation transform.
- r.mVisibleRequested = false;
+ r.setVisibleRequested(false);
mDisplayContent.mWallpaperController.adjustWallpaperWindows();
assertFalse(wallpaperToken.hasFixedRotationTransform());
// Wallpaper should link the transform of its target.
- r.mVisibleRequested = true;
+ r.setVisibleRequested(true);
mDisplayContent.mWallpaperController.adjustWallpaperWindows();
assertEquals(appWin, mDisplayContent.mWallpaperController.getWallpaperTarget());
assertTrue(r.hasFixedRotationTransform());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index b0d7ed660837..7ca358a12b36 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -191,7 +191,7 @@ public class WindowManagerServiceTests extends WindowTestsBase {
win.mViewVisibility = View.VISIBLE;
win.mHasSurface = true;
win.mActivityRecord.mAppStopped = true;
- win.mActivityRecord.mVisibleRequested = false;
+ win.mActivityRecord.setVisibleRequested(false);
win.mActivityRecord.setVisible(false);
mWm.mWindowMap.put(win.mClient.asBinder(), win);
final int w = 100;
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index 8deb2825c4f9..df3b306d6739 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -994,7 +994,7 @@ public class WindowOrganizerTests extends WindowTestsBase {
final Task task = createTask(rootTaskController1);
final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
- w.mActivityRecord.mVisibleRequested = true;
+ w.mActivityRecord.setVisibleRequested(true);
w.mActivityRecord.setVisible(true);
BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index 3abf7ce665ae..8bd414856394 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -324,7 +324,7 @@ public class WindowProcessControllerTests extends WindowTestsBase {
@Test
public void testComputeOomAdjFromActivities() {
final ActivityRecord activity = createActivityRecord(mWpc);
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
final int[] callbackResult = { 0 };
final int visible = 1;
final int paused = 2;
@@ -359,7 +359,7 @@ public class WindowProcessControllerTests extends WindowTestsBase {
assertEquals(visible, callbackResult[0]);
callbackResult[0] = 0;
- activity.mVisibleRequested = false;
+ activity.setVisibleRequested(false);
activity.setState(PAUSED, "test");
mWpc.computeOomAdjFromActivities(callback);
assertEquals(paused, callbackResult[0]);
@@ -380,7 +380,7 @@ public class WindowProcessControllerTests extends WindowTestsBase {
final VisibleActivityProcessTracker tracker = mAtm.mVisibleActivityProcessTracker;
spyOn(tracker);
final ActivityRecord activity = createActivityRecord(mWpc);
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
activity.setState(STARTED, "test");
verify(tracker).onAnyActivityVisible(mWpc);
@@ -398,7 +398,7 @@ public class WindowProcessControllerTests extends WindowTestsBase {
assertTrue(mWpc.hasForegroundActivities());
activity.setVisibility(false);
- activity.mVisibleRequested = false;
+ activity.setVisibleRequested(false);
activity.setState(STOPPED, "test");
verify(tracker).onAllActivitiesInvisible(mWpc);
@@ -413,7 +413,7 @@ public class WindowProcessControllerTests extends WindowTestsBase {
@Test
public void testTopActivityUiModeChangeScheduleConfigChange() {
final ActivityRecord activity = createActivityRecord(mWpc);
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
doReturn(true).when(activity).applyAppSpecificConfig(anyInt(), any());
mWpc.updateAppSpecificSettingsForAllActivitiesInPackage(DEFAULT_COMPONENT_PACKAGE_NAME,
Configuration.UI_MODE_NIGHT_YES, LocaleList.forLanguageTags("en-XA"));
@@ -423,7 +423,7 @@ public class WindowProcessControllerTests extends WindowTestsBase {
@Test
public void testTopActivityUiModeChangeForDifferentPackage_noScheduledConfigChange() {
final ActivityRecord activity = createActivityRecord(mWpc);
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
mWpc.updateAppSpecificSettingsForAllActivitiesInPackage("com.different.package",
Configuration.UI_MODE_NIGHT_YES, LocaleList.forLanguageTags("en-XA"));
verify(activity, never()).applyAppSpecificConfig(anyInt(), any());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 04d873453b2d..650286a8b111 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -263,7 +263,7 @@ public class WindowStateTests extends WindowTestsBase {
// Verify that app window can still be IME target as long as it is visible (even if
// it is going to become invisible).
- appWindow.mActivityRecord.mVisibleRequested = false;
+ appWindow.mActivityRecord.setVisibleRequested(false);
assertTrue(appWindow.canBeImeTarget());
// Make windows invisible
@@ -717,7 +717,7 @@ public class WindowStateTests extends WindowTestsBase {
// No need to wait for a window of invisible activity even if the window has surface.
final WindowState invisibleApp = mAppWindow;
- invisibleApp.mActivityRecord.mVisibleRequested = false;
+ invisibleApp.mActivityRecord.setVisibleRequested(false);
invisibleApp.mActivityRecord.allDrawn = false;
outWaitingForDrawn.clear();
invisibleApp.requestDrawIfNeeded(outWaitingForDrawn);
@@ -735,7 +735,7 @@ public class WindowStateTests extends WindowTestsBase {
assertFalse(startingApp.getOrientationChanging());
// Even if the display is frozen, invisible requested window should not be affected.
- startingApp.mActivityRecord.mVisibleRequested = false;
+ startingApp.mActivityRecord.setVisibleRequested(false);
mWm.startFreezingDisplay(0, 0, mDisplayContent);
doReturn(true).when(mWm.mPolicy).isScreenOn();
startingApp.getWindowFrames().setInsetsChanged(true);
@@ -810,7 +810,7 @@ public class WindowStateTests extends WindowTestsBase {
final WindowState win = createWindow(null /* parent */, TYPE_APPLICATION, embeddedActivity,
"App window");
doReturn(true).when(embeddedActivity).isVisible();
- embeddedActivity.mVisibleRequested = true;
+ embeddedActivity.setVisibleRequested(true);
makeWindowVisible(win);
win.mLayoutSeq = win.getDisplayContent().mLayoutSeq;
// Set the bounds twice:
@@ -835,7 +835,7 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testCantReceiveTouchWhenAppTokenHiddenRequested() {
final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
- win0.mActivityRecord.mVisibleRequested = false;
+ win0.mActivityRecord.setVisibleRequested(false);
assertFalse(win0.canReceiveTouchInput());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 894ba3e95261..268aa3e5f5b4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -715,7 +715,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
activity.onDisplayChanged(dc);
activity.setOccludesParent(true);
activity.setVisible(true);
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
}
static TaskFragment createTaskFragmentWithParentTask(@NonNull Task parentTask) {
@@ -1209,7 +1209,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
mTask.moveToFront("createActivity");
}
if (mVisible) {
- activity.mVisibleRequested = true;
+ activity.setVisibleRequested(true);
activity.setVisible(true);
}
}