diff options
21 files changed, 364 insertions, 417 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java index e8add56619c4..ac510f89b905 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java @@ -946,8 +946,7 @@ public abstract class WMShellModule { FocusTransitionObserver focusTransitionObserver, DesktopModeEventLogger desktopModeEventLogger, DesktopModeUiEventLogger desktopModeUiEventLogger, - WindowDecorTaskResourceLoader taskResourceLoader, - RecentsTransitionHandler recentsTransitionHandler + WindowDecorTaskResourceLoader taskResourceLoader ) { if (!DesktopModeStatus.canEnterDesktopModeOrShowAppHandle(context)) { return Optional.empty(); @@ -963,7 +962,7 @@ public abstract class WMShellModule { desktopTasksLimiter, appHandleEducationController, appToWebEducationController, windowDecorCaptionHandleRepository, activityOrientationChangeHandler, focusTransitionObserver, desktopModeEventLogger, desktopModeUiEventLogger, - taskResourceLoader, recentsTransitionHandler)); + taskResourceLoader)); } @WMSingleton diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentsAnimationRunner.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentsAnimationRunner.aidl index 8cdb8c4512a9..32c79a2d02de 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentsAnimationRunner.aidl +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentsAnimationRunner.aidl @@ -17,10 +17,9 @@ package com.android.wm.shell.recents; import android.graphics.Rect; -import android.os.Bundle; import android.view.RemoteAnimationTarget; import android.window.TaskSnapshot; -import android.window.TransitionInfo; +import android.os.Bundle; import com.android.wm.shell.recents.IRecentsAnimationController; @@ -58,8 +57,7 @@ oneway interface IRecentsAnimationRunner { */ void onAnimationStart(in IRecentsAnimationController controller, in RemoteAnimationTarget[] apps, in RemoteAnimationTarget[] wallpapers, - in Rect homeContentInsets, in Rect minimizedHomeBounds, in Bundle extras, - in TransitionInfo info) = 2; + in Rect homeContentInsets, in Rect minimizedHomeBounds, in Bundle extras) = 2; /** * Called when the task of an activity that has been started while the recents animation diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java index aeccd86e122c..db582aa30f6a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java @@ -587,8 +587,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler, mListener.onAnimationStart(this, apps.toArray(new RemoteAnimationTarget[apps.size()]), new RemoteAnimationTarget[0], - new Rect(0, 0, 0, 0), new Rect(), new Bundle(), - null); + new Rect(0, 0, 0, 0), new Rect(), new Bundle()); for (int i = 0; i < mStateListeners.size(); i++) { mStateListeners.get(i).onTransitionStateChanged(TRANSITION_STATE_ANIMATING); } @@ -819,7 +818,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler, mListener.onAnimationStart(this, apps.toArray(new RemoteAnimationTarget[apps.size()]), wallpapers.toArray(new RemoteAnimationTarget[wallpapers.size()]), - new Rect(0, 0, 0, 0), new Rect(), b, info); + new Rect(0, 0, 0, 0), new Rect(), b); for (int i = 0; i < mStateListeners.size(); i++) { mStateListeners.get(i).onTransitionStateChanged(TRANSITION_STATE_ANIMATING); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java index 429e0564dd2c..9fbda46bd2b7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java @@ -126,8 +126,6 @@ import com.android.wm.shell.desktopmode.common.ToggleTaskSizeUtilsKt; import com.android.wm.shell.desktopmode.education.AppHandleEducationController; import com.android.wm.shell.desktopmode.education.AppToWebEducationController; import com.android.wm.shell.freeform.FreeformTaskTransitionStarter; -import com.android.wm.shell.recents.RecentsTransitionHandler; -import com.android.wm.shell.recents.RecentsTransitionStateListener; import com.android.wm.shell.shared.FocusTransitionListener; import com.android.wm.shell.shared.annotations.ShellBackgroundThread; import com.android.wm.shell.shared.annotations.ShellMainThread; @@ -159,10 +157,8 @@ import kotlinx.coroutines.MainCoroutineDispatcher; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Optional; -import java.util.Set; import java.util.function.Supplier; /** @@ -251,7 +247,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, private final DesktopModeEventLogger mDesktopModeEventLogger; private final DesktopModeUiEventLogger mDesktopModeUiEventLogger; private final WindowDecorTaskResourceLoader mTaskResourceLoader; - private final RecentsTransitionHandler mRecentsTransitionHandler; public DesktopModeWindowDecorViewModel( Context context, @@ -287,8 +282,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, FocusTransitionObserver focusTransitionObserver, DesktopModeEventLogger desktopModeEventLogger, DesktopModeUiEventLogger desktopModeUiEventLogger, - WindowDecorTaskResourceLoader taskResourceLoader, - RecentsTransitionHandler recentsTransitionHandler) { + WindowDecorTaskResourceLoader taskResourceLoader) { this( context, shellExecutor, @@ -329,8 +323,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, focusTransitionObserver, desktopModeEventLogger, desktopModeUiEventLogger, - taskResourceLoader, - recentsTransitionHandler); + taskResourceLoader); } @VisibleForTesting @@ -374,8 +367,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, FocusTransitionObserver focusTransitionObserver, DesktopModeEventLogger desktopModeEventLogger, DesktopModeUiEventLogger desktopModeUiEventLogger, - WindowDecorTaskResourceLoader taskResourceLoader, - RecentsTransitionHandler recentsTransitionHandler) { + WindowDecorTaskResourceLoader taskResourceLoader) { mContext = context; mMainExecutor = shellExecutor; mMainHandler = mainHandler; @@ -444,7 +436,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, mDesktopModeEventLogger = desktopModeEventLogger; mDesktopModeUiEventLogger = desktopModeUiEventLogger; mTaskResourceLoader = taskResourceLoader; - mRecentsTransitionHandler = recentsTransitionHandler; shellInit.addInitCallback(this::onInit, this); } @@ -459,10 +450,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, new DesktopModeOnTaskResizeAnimationListener()); mDesktopTasksController.setOnTaskRepositionAnimationListener( new DesktopModeOnTaskRepositionAnimationListener()); - if (Flags.enableDesktopRecentsTransitionsCornersBugfix()) { - mRecentsTransitionHandler.addTransitionStateListener( - new DesktopModeRecentsTransitionStateListener()); - } mDisplayController.addDisplayChangingController(mOnDisplayChangingListener); try { mWindowManager.registerSystemGestureExclusionListener(mGestureExclusionListener, @@ -1872,38 +1859,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, } } - private class DesktopModeRecentsTransitionStateListener - implements RecentsTransitionStateListener { - final Set<Integer> mAnimatingTaskIds = new HashSet<>(); - - @Override - public void onTransitionStateChanged(int state) { - switch (state) { - case RecentsTransitionStateListener.TRANSITION_STATE_REQUESTED: - for (int n = 0; n < mWindowDecorByTaskId.size(); n++) { - int taskId = mWindowDecorByTaskId.keyAt(n); - mAnimatingTaskIds.add(taskId); - setIsRecentsTransitionRunningForTask(taskId, true); - } - return; - case RecentsTransitionStateListener.TRANSITION_STATE_NOT_RUNNING: - // No Recents transition running - clean up window decorations - for (int taskId : mAnimatingTaskIds) { - setIsRecentsTransitionRunningForTask(taskId, false); - } - mAnimatingTaskIds.clear(); - return; - default: - } - } - - private void setIsRecentsTransitionRunningForTask(int taskId, boolean isRecentsRunning) { - final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId); - if (decoration == null) return; - decoration.setIsRecentsTransitionRunning(isRecentsRunning); - } - } - private class DragEventListenerImpl implements DragPositioningCallbackUtility.DragEventListener { @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java index 39a989ce7c7f..4ac89546c9c7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java @@ -204,7 +204,6 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin private final MultiInstanceHelper mMultiInstanceHelper; private final WindowDecorCaptionHandleRepository mWindowDecorCaptionHandleRepository; private final DesktopUserRepositories mDesktopUserRepositories; - private boolean mIsRecentsTransitionRunning = false; private Runnable mLoadAppInfoRunnable; private Runnable mSetAppInfoRunnable; @@ -499,7 +498,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin applyStartTransactionOnDraw, shouldSetTaskVisibilityPositionAndCrop, mIsStatusBarVisible, mIsKeyguardVisibleAndOccluded, inFullImmersive, mDisplayController.getInsetsState(taskInfo.displayId), hasGlobalFocus, - displayExclusionRegion, mIsRecentsTransitionRunning); + displayExclusionRegion); final WindowDecorLinearLayout oldRootView = mResult.mRootView; final SurfaceControl oldDecorationSurface = mDecorationContainerSurface; @@ -870,8 +869,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin boolean inFullImmersiveMode, @NonNull InsetsState displayInsetsState, boolean hasGlobalFocus, - @NonNull Region displayExclusionRegion, - boolean shouldIgnoreCornerRadius) { + @NonNull Region displayExclusionRegion) { final int captionLayoutId = getDesktopModeWindowDecorLayoutId(taskInfo.getWindowingMode()); final boolean isAppHeader = captionLayoutId == R.layout.desktop_mode_app_header; @@ -1008,19 +1006,13 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin relayoutParams.mWindowDecorConfig = windowDecorConfig; if (DesktopModeStatus.useRoundedCorners()) { - relayoutParams.mCornerRadius = shouldIgnoreCornerRadius ? INVALID_CORNER_RADIUS : - getCornerRadius(context, relayoutParams.mLayoutResId); + relayoutParams.mCornerRadius = taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM + ? loadDimensionPixelSize(context.getResources(), + R.dimen.desktop_windowing_freeform_rounded_corner_radius) + : INVALID_CORNER_RADIUS; } } - private static int getCornerRadius(@NonNull Context context, int layoutResId) { - if (layoutResId == R.layout.desktop_mode_app_header) { - return loadDimensionPixelSize(context.getResources(), - R.dimen.desktop_windowing_freeform_rounded_corner_radius); - } - return INVALID_CORNER_RADIUS; - } - /** * If task has focused window decor, return the caption id of the fullscreen caption size * resource. Otherwise, return ID_NULL and caption width be set to task width. @@ -1748,17 +1740,6 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin } /** - * Declares whether a Recents transition is currently active. - * - * <p> When a Recents transition is active we allow that transition to take ownership of the - * corner radius of its task surfaces, so each window decoration should stop updating the corner - * radius of its task surface during that time. - */ - void setIsRecentsTransitionRunning(boolean isRecentsTransitionRunning) { - mIsRecentsTransitionRunning = isRecentsTransitionRunning; - } - - /** * Called when there is a {@link MotionEvent#ACTION_HOVER_EXIT} on the maximize window button. */ void onMaximizeButtonHoverExit() { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java index fa7183ad0fd8..5d1bedb85b5e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java @@ -967,4 +967,4 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> return Objects.hash(mToken, mOwner, mFrame, Arrays.hashCode(mBoundingRects), mFlags); } } -} +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java index ab43119b14c0..894d238b7e15 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java @@ -169,7 +169,7 @@ public class RecentsTransitionHandlerTest extends ShellTestCase { final IResultReceiver finishCallback = mock(IResultReceiver.class); final IBinder transition = startRecentsTransition(/* synthetic= */ true, runner); - verify(runner).onAnimationStart(any(), any(), any(), any(), any(), any(), any()); + verify(runner).onAnimationStart(any(), any(), any(), any(), any(), any()); // Finish and verify no transition remains and that the provided finish callback is called mRecentsTransitionHandler.findController(transition).finish(true /* toHome */, @@ -184,7 +184,7 @@ public class RecentsTransitionHandlerTest extends ShellTestCase { final IRecentsAnimationRunner runner = mock(IRecentsAnimationRunner.class); final IBinder transition = startRecentsTransition(/* synthetic= */ true, runner); - verify(runner).onAnimationStart(any(), any(), any(), any(), any(), any(), any()); + verify(runner).onAnimationStart(any(), any(), any(), any(), any(), any()); mRecentsTransitionHandler.findController(transition).cancel("test"); mMainExecutor.flushAll(); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt index 79e9b9c8cd77..ffe8e7135513 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt @@ -59,12 +59,11 @@ import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession import com.android.window.flags.Flags import com.android.wm.shell.R +import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction import com.android.wm.shell.desktopmode.DesktopImmersiveController import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.InputMethod import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition -import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction -import com.android.wm.shell.recents.RecentsTransitionStateListener import com.android.wm.shell.shared.desktopmode.DesktopModeStatus import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource import com.android.wm.shell.splitscreen.SplitScreenController @@ -540,8 +539,7 @@ class DesktopModeWindowDecorViewModelTests : DesktopModeWindowDecorViewModelTest onLeftSnapClickListenerCaptor.value.invoke() verify(mockDesktopTasksController, never()) - .snapToHalfScreen( - eq(decor.mTaskInfo), any(), eq(currentBounds), eq(SnapPosition.LEFT), + .snapToHalfScreen(eq(decor.mTaskInfo), any(), eq(currentBounds), eq(SnapPosition.LEFT), eq(ResizeTrigger.MAXIMIZE_BUTTON), eq(InputMethod.UNKNOWN_INPUT_METHOD), eq(decor), @@ -618,12 +616,11 @@ class DesktopModeWindowDecorViewModelTests : DesktopModeWindowDecorViewModelTest onRightSnapClickListenerCaptor.value.invoke() verify(mockDesktopTasksController, never()) - .snapToHalfScreen( - eq(decor.mTaskInfo), any(), eq(currentBounds), eq(SnapPosition.RIGHT), + .snapToHalfScreen(eq(decor.mTaskInfo), any(), eq(currentBounds), eq(SnapPosition.RIGHT), eq(ResizeTrigger.MAXIMIZE_BUTTON), eq(InputMethod.UNKNOWN_INPUT_METHOD), eq(decor), - ) + ) } @Test @@ -1226,49 +1223,6 @@ class DesktopModeWindowDecorViewModelTests : DesktopModeWindowDecorViewModelTest verify(task2, never()).onExclusionRegionChanged(newRegion) } - @Test - @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX) - fun testRecentsTransitionStateListener_requestedState_setsTransitionRunning() { - val task = createTask(windowingMode = WINDOWING_MODE_FREEFORM) - val decoration = setUpMockDecorationForTask(task) - onTaskOpening(task, SurfaceControl()) - - desktopModeRecentsTransitionStateListener.onTransitionStateChanged( - RecentsTransitionStateListener.TRANSITION_STATE_REQUESTED) - - verify(decoration).setIsRecentsTransitionRunning(true) - } - - @Test - @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX) - fun testRecentsTransitionStateListener_nonRunningState_setsTransitionNotRunning() { - val task = createTask(windowingMode = WINDOWING_MODE_FREEFORM) - val decoration = setUpMockDecorationForTask(task) - onTaskOpening(task, SurfaceControl()) - desktopModeRecentsTransitionStateListener.onTransitionStateChanged( - RecentsTransitionStateListener.TRANSITION_STATE_REQUESTED) - - desktopModeRecentsTransitionStateListener.onTransitionStateChanged( - RecentsTransitionStateListener.TRANSITION_STATE_NOT_RUNNING) - - verify(decoration).setIsRecentsTransitionRunning(false) - } - - @Test - @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX) - fun testRecentsTransitionStateListener_requestedAndAnimating_setsTransitionRunningOnce() { - val task = createTask(windowingMode = WINDOWING_MODE_FREEFORM) - val decoration = setUpMockDecorationForTask(task) - onTaskOpening(task, SurfaceControl()) - - desktopModeRecentsTransitionStateListener.onTransitionStateChanged( - RecentsTransitionStateListener.TRANSITION_STATE_REQUESTED) - desktopModeRecentsTransitionStateListener.onTransitionStateChanged( - RecentsTransitionStateListener.TRANSITION_STATE_ANIMATING) - - verify(decoration, times(1)).setIsRecentsTransitionRunning(true) - } - private fun createOpenTaskDecoration( @WindowingMode windowingMode: Int, taskSurface: SurfaceControl = SurfaceControl(), diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt index 8af8285d031c..b5e8cebc1277 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt @@ -40,7 +40,6 @@ import android.view.SurfaceControl import android.view.WindowInsets.Type.statusBars import com.android.dx.mockito.inline.extended.StaticMockitoSession import com.android.internal.jank.InteractionJankMonitor -import com.android.window.flags.Flags import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.ShellTestCase @@ -66,8 +65,6 @@ import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository import com.android.wm.shell.desktopmode.education.AppHandleEducationController import com.android.wm.shell.desktopmode.education.AppToWebEducationController import com.android.wm.shell.freeform.FreeformTaskTransitionStarter -import com.android.wm.shell.recents.RecentsTransitionHandler -import com.android.wm.shell.recents.RecentsTransitionStateListener import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.sysui.ShellCommandHandler import com.android.wm.shell.sysui.ShellController @@ -154,7 +151,6 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() { protected val mockFocusTransitionObserver = mock<FocusTransitionObserver>() protected val mockCaptionHandleRepository = mock<WindowDecorCaptionHandleRepository>() protected val mockDesktopRepository: DesktopRepository = mock<DesktopRepository>() - protected val mockRecentsTransitionHandler = mock<RecentsTransitionHandler>() protected val motionEvent = mock<MotionEvent>() val displayLayout = mock<DisplayLayout>() protected lateinit var spyContext: TestableContext @@ -168,7 +164,6 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() { protected lateinit var mockitoSession: StaticMockitoSession protected lateinit var shellInit: ShellInit internal lateinit var desktopModeOnInsetsChangedListener: DesktopModeOnInsetsChangedListener - protected lateinit var desktopModeRecentsTransitionStateListener: RecentsTransitionStateListener protected lateinit var displayChangingListener: DisplayChangeController.OnDisplayChangingListener internal lateinit var desktopModeOnKeyguardChangedListener: DesktopModeKeyguardChangeListener @@ -224,8 +219,7 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() { mockFocusTransitionObserver, desktopModeEventLogger, mock<DesktopModeUiEventLogger>(), - mock<WindowDecorTaskResourceLoader>(), - mockRecentsTransitionHandler, + mock<WindowDecorTaskResourceLoader>() ) desktopModeWindowDecorViewModel.setSplitScreenController(mockSplitScreenController) whenever(mockDisplayController.getDisplayLayout(any())).thenReturn(mockDisplayLayout) @@ -262,13 +256,6 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() { verify(displayInsetsController) .addGlobalInsetsChangedListener(insetsChangedCaptor.capture()) desktopModeOnInsetsChangedListener = insetsChangedCaptor.firstValue - val recentsTransitionStateListenerCaptor = argumentCaptor<RecentsTransitionStateListener>() - if (Flags.enableDesktopRecentsTransitionsCornersBugfix()) { - verify(mockRecentsTransitionHandler) - .addTransitionStateListener(recentsTransitionStateListenerCaptor.capture()) - desktopModeRecentsTransitionStateListener = - recentsTransitionStateListenerCaptor.firstValue - } val keyguardChangedCaptor = argumentCaptor<DesktopModeKeyguardChangeListener>() verify(mockShellController).addKeyguardChangeListener(keyguardChangedCaptor.capture()) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java index 9ea5fd6e1abe..6b02aeffd42a 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java @@ -169,7 +169,6 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { private static final boolean DEFAULT_IS_KEYGUARD_VISIBLE_AND_OCCLUDED = false; private static final boolean DEFAULT_IS_IN_FULL_IMMERSIVE_MODE = false; private static final boolean DEFAULT_HAS_GLOBAL_FOCUS = true; - private static final boolean DEFAULT_SHOULD_IGNORE_CORNER_RADIUS = false; @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT); @@ -397,31 +396,6 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { } @Test - public void updateRelayoutParams_shouldIgnoreCornerRadius_roundedCornersNotSet() { - final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); - taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM); - fillRoundedCornersResources(/* fillValue= */ 30); - RelayoutParams relayoutParams = new RelayoutParams(); - - DesktopModeWindowDecoration.updateRelayoutParams( - relayoutParams, - mTestableContext, - taskInfo, - mMockSplitScreenController, - DEFAULT_APPLY_START_TRANSACTION_ON_DRAW, - DEFAULT_SHOULD_SET_TASK_POSITIONING_AND_CROP, - DEFAULT_IS_STATUSBAR_VISIBLE, - DEFAULT_IS_KEYGUARD_VISIBLE_AND_OCCLUDED, - DEFAULT_IS_IN_FULL_IMMERSIVE_MODE, - new InsetsState(), - DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion, - /* shouldIgnoreCornerRadius= */ true); - - assertThat(relayoutParams.mCornerRadius).isEqualTo(INVALID_CORNER_RADIUS); - } - - @Test @EnableFlags(Flags.FLAG_ENABLE_APP_HEADER_WITH_TASK_DENSITY) public void updateRelayoutParams_appHeader_usesTaskDensity() { final int systemDensity = mTestableContext.getOrCreateTestableResources().getResources() @@ -660,8 +634,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { /* inFullImmersiveMode */ true, insetsState, DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion, - DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); + mExclusionRegion); // Takes status bar inset as padding, ignores caption bar inset. assertThat(relayoutParams.mCaptionTopPadding).isEqualTo(50); @@ -686,8 +659,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { /* inFullImmersiveMode */ true, new InsetsState(), DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion, - DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); + mExclusionRegion); assertThat(relayoutParams.mIsInsetSource).isFalse(); } @@ -711,8 +683,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_IS_IN_FULL_IMMERSIVE_MODE, new InsetsState(), DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion, - DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); + mExclusionRegion); // Header is always shown because it's assumed the status bar is always visible. assertThat(relayoutParams.mIsCaptionVisible).isTrue(); @@ -736,8 +707,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_IS_IN_FULL_IMMERSIVE_MODE, new InsetsState(), DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion, - DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); + mExclusionRegion); assertThat(relayoutParams.mIsCaptionVisible).isTrue(); } @@ -760,8 +730,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_IS_IN_FULL_IMMERSIVE_MODE, new InsetsState(), DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion, - DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); + mExclusionRegion); assertThat(relayoutParams.mIsCaptionVisible).isFalse(); } @@ -784,8 +753,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_IS_IN_FULL_IMMERSIVE_MODE, new InsetsState(), DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion, - DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); + mExclusionRegion); assertThat(relayoutParams.mIsCaptionVisible).isFalse(); } @@ -809,8 +777,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { /* inFullImmersiveMode */ true, new InsetsState(), DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion, - DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); + mExclusionRegion); assertThat(relayoutParams.mIsCaptionVisible).isTrue(); @@ -826,8 +793,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { /* inFullImmersiveMode */ true, new InsetsState(), DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion, - DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); + mExclusionRegion); assertThat(relayoutParams.mIsCaptionVisible).isFalse(); } @@ -851,8 +817,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { /* inFullImmersiveMode */ true, new InsetsState(), DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion, - DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); + mExclusionRegion); assertThat(relayoutParams.mIsCaptionVisible).isFalse(); } @@ -1515,8 +1480,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_IS_IN_FULL_IMMERSIVE_MODE, new InsetsState(), DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion, - DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); + mExclusionRegion); } private DesktopModeWindowDecoration createWindowDecoration( diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index ac9c7c8f7838..153f89284587 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -1919,3 +1919,13 @@ flag { description: "Special UI treatment for magic actions" bug: "383567383" } + +flag { + name: "show_audio_sharing_slider_in_volume_panel" + namespace: "cross_device_experiences" + description: "Show two sliders in volume panel when audio sharing." + bug: "336183611" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java index ff6bcdb150f8..51892aac606a 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java @@ -19,7 +19,6 @@ package com.android.systemui.shared.system; import android.graphics.Rect; import android.os.Bundle; import android.view.RemoteAnimationTarget; -import android.window.TransitionInfo; import com.android.systemui.shared.recents.model.ThumbnailData; @@ -31,7 +30,7 @@ public interface RecentsAnimationListener { */ void onAnimationStart(RecentsAnimationControllerCompat controller, RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, - Rect homeContentInsets, Rect minimizedHomeBounds, Bundle extras, TransitionInfo info); + Rect homeContentInsets, Rect minimizedHomeBounds, Bundle extras); /** * Called when the animation into Recents was canceled. This call is made on the binder thread. diff --git a/services/core/java/com/android/server/timezonedetector/Environment.java b/services/core/java/com/android/server/timezonedetector/Environment.java new file mode 100644 index 000000000000..795fb02373ff --- /dev/null +++ b/services/core/java/com/android/server/timezonedetector/Environment.java @@ -0,0 +1,80 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.timezonedetector; + +import android.annotation.CurrentTimeMillisLong; +import android.annotation.ElapsedRealtimeLong; +import android.annotation.NonNull; + +import com.android.server.SystemTimeZone; + +import java.io.PrintWriter; + +/** + * Used by the time zone detector code to interact with device state besides that available from + * {@link ServiceConfigAccessor}. It can be faked for testing. + */ +public interface Environment { + + /** + * Returns the device's currently configured time zone. May return an empty string. + */ + @NonNull + String getDeviceTimeZone(); + + /** + * Returns the confidence of the device's current time zone. + */ + @SystemTimeZone.TimeZoneConfidence + int getDeviceTimeZoneConfidence(); + + /** + * Sets the device's time zone, associated confidence, and records a debug log entry. + */ + void setDeviceTimeZoneAndConfidence( + @NonNull String zoneId, @SystemTimeZone.TimeZoneConfidence int confidence, + @NonNull String logInfo); + + /** + * Returns the time according to the elapsed realtime clock, the same as {@link + * android.os.SystemClock#elapsedRealtime()}. + */ + @ElapsedRealtimeLong + long elapsedRealtimeMillis(); + + /** + * Returns the current time in milliseconds, the same as + * {@link java.lang.System#currentTimeMillis()}. + */ + @CurrentTimeMillisLong + long currentTimeMillis(); + + /** + * Adds a standalone entry to the time zone debug log. + */ + void addDebugLogEntry(@NonNull String logMsg); + + /** + * Dumps the time zone debug log to the supplied {@link PrintWriter}. + */ + void dumpDebugLog(PrintWriter printWriter); + + /** + * Requests that the supplied runnable be invoked asynchronously. + */ + void runAsync(@NonNull Runnable runnable); +} diff --git a/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java b/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java index 449b41a09c51..8491b4818c2e 100644 --- a/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java +++ b/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java @@ -16,6 +16,7 @@ package com.android.server.timezonedetector; +import android.annotation.CurrentTimeMillisLong; import android.annotation.ElapsedRealtimeLong; import android.annotation.NonNull; import android.os.Handler; @@ -31,9 +32,9 @@ import java.io.PrintWriter; import java.util.Objects; /** - * The real implementation of {@link TimeZoneDetectorStrategyImpl.Environment}. + * The real implementation of {@link Environment}. */ -final class EnvironmentImpl implements TimeZoneDetectorStrategyImpl.Environment { +final class EnvironmentImpl implements Environment { private static final String TIMEZONE_PROPERTY = "persist.sys.timezone"; @@ -69,6 +70,11 @@ final class EnvironmentImpl implements TimeZoneDetectorStrategyImpl.Environment } @Override + public @CurrentTimeMillisLong long currentTimeMillis() { + return System.currentTimeMillis(); + } + + @Override public void addDebugLogEntry(@NonNull String logMsg) { SystemTimeZone.addDebugLogEntry(logMsg); } diff --git a/services/core/java/com/android/server/timezonedetector/NotifyingTimeZoneChangeListener.java b/services/core/java/com/android/server/timezonedetector/NotifyingTimeZoneChangeListener.java index 2e73829ca143..cf85a9a6a706 100644 --- a/services/core/java/com/android/server/timezonedetector/NotifyingTimeZoneChangeListener.java +++ b/services/core/java/com/android/server/timezonedetector/NotifyingTimeZoneChangeListener.java @@ -29,6 +29,7 @@ import static com.android.server.timezonedetector.TimeZoneDetectorStrategy.ORIGI import android.annotation.DurationMillisLong; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.UserIdInt; import android.app.ActivityManagerInternal; @@ -44,7 +45,6 @@ import android.icu.text.DateFormat; import android.icu.text.SimpleDateFormat; import android.icu.util.TimeZone; import android.os.Handler; -import android.os.SystemClock; import android.os.UserHandle; import android.util.IndentingPrintWriter; import android.util.Log; @@ -153,6 +153,9 @@ public class NotifyingTimeZoneChangeListener implements TimeZoneChangeListener { } }; + @NonNull + private final Environment mEnvironment; + private final Object mConfigurationLock = new Object(); @GuardedBy("mConfigurationLock") private ConfigurationInternal mConfigurationInternal; @@ -170,12 +173,14 @@ public class NotifyingTimeZoneChangeListener implements TimeZoneChangeListener { /** Create and initialise a new {@code TimeZoneChangeTrackerImpl} */ @RequiresPermission("android.permission.INTERACT_ACROSS_USERS_FULL") public static NotifyingTimeZoneChangeListener create(Handler handler, Context context, - ServiceConfigAccessor serviceConfigAccessor) { + ServiceConfigAccessor serviceConfigAccessor, + @NonNull Environment environment) { NotifyingTimeZoneChangeListener changeTracker = new NotifyingTimeZoneChangeListener(handler, context, serviceConfigAccessor, - context.getSystemService(NotificationManager.class)); + context.getSystemService(NotificationManager.class), + environment); // Pretend there was an update to initialize configuration. changeTracker.handleConfigurationUpdate(); @@ -184,9 +189,9 @@ public class NotifyingTimeZoneChangeListener implements TimeZoneChangeListener { } @VisibleForTesting - NotifyingTimeZoneChangeListener( - Handler handler, Context context, ServiceConfigAccessor serviceConfigAccessor, - NotificationManager notificationManager) { + NotifyingTimeZoneChangeListener(Handler handler, Context context, + ServiceConfigAccessor serviceConfigAccessor, NotificationManager notificationManager, + @NonNull Environment environment) { mHandler = Objects.requireNonNull(handler); mContext = Objects.requireNonNull(context); mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor); @@ -194,6 +199,7 @@ public class NotifyingTimeZoneChangeListener implements TimeZoneChangeListener { this::handleConfigurationUpdate); mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); mNotificationManager = notificationManager; + mEnvironment = Objects.requireNonNull(environment); } @RequiresPermission("android.permission.INTERACT_ACROSS_USERS_FULL") @@ -420,7 +426,7 @@ public class NotifyingTimeZoneChangeListener implements TimeZoneChangeListener { if (!changeEvent.getOldZoneId().equals(lastChangeEvent.getNewZoneId())) { int changeEventId = mNextChangeEventId.getAndIncrement(); TimeZoneChangeEvent syntheticChangeEvent = new TimeZoneChangeEvent( - SystemClock.elapsedRealtime(), System.currentTimeMillis(), + mEnvironment.elapsedRealtimeMillis(), mEnvironment.currentTimeMillis(), ORIGIN_UNKNOWN, UserHandle.USER_NULL, lastChangeEvent.getNewZoneId(), changeEvent.getOldZoneId(), 0, "Synthetic"); TimeZoneChangeRecord syntheticTrackedChangeEvent = diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java index b2b06b0af5fa..042d81ab6885 100644 --- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java +++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java @@ -25,7 +25,6 @@ import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_S import static com.android.server.SystemTimeZone.TIME_ZONE_CONFIDENCE_HIGH; import static com.android.server.SystemTimeZone.TIME_ZONE_CONFIDENCE_LOW; -import android.annotation.ElapsedRealtimeLong; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -54,7 +53,6 @@ import com.android.server.SystemTimeZone.TimeZoneConfidence; import com.android.server.flags.Flags; import com.android.server.timezonedetector.ConfigurationInternal.DetectionMode; -import java.io.PrintWriter; import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -67,55 +65,6 @@ import java.util.Objects; */ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrategy { - /** - * Used by {@link TimeZoneDetectorStrategyImpl} to interact with device state besides that - * available from {@link #mServiceConfigAccessor}. It can be faked for testing. - */ - @VisibleForTesting - public interface Environment { - - /** - * Returns the device's currently configured time zone. May return an empty string. - */ - @NonNull - String getDeviceTimeZone(); - - /** - * Returns the confidence of the device's current time zone. - */ - @TimeZoneConfidence - int getDeviceTimeZoneConfidence(); - - /** - * Sets the device's time zone, associated confidence, and records a debug log entry. - */ - void setDeviceTimeZoneAndConfidence( - @NonNull String zoneId, @TimeZoneConfidence int confidence, - @NonNull String logInfo); - - /** - * Returns the time according to the elapsed realtime clock, the same as {@link - * android.os.SystemClock#elapsedRealtime()}. - */ - @ElapsedRealtimeLong - long elapsedRealtimeMillis(); - - /** - * Adds a standalone entry to the time zone debug log. - */ - void addDebugLogEntry(@NonNull String logMsg); - - /** - * Dumps the time zone debug log to the supplied {@link PrintWriter}. - */ - void dumpDebugLog(PrintWriter printWriter); - - /** - * Requests that the supplied runnable be invoked asynchronously. - */ - void runAsync(@NonNull Runnable runnable); - } - private static final String LOG_TAG = TimeZoneDetectorService.TAG; private static final boolean DBG = TimeZoneDetectorService.DBG; @@ -263,10 +212,10 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat public static TimeZoneDetectorStrategyImpl create( @NonNull Context context, @NonNull Handler handler, @NonNull ServiceConfigAccessor serviceConfigAccessor) { - Environment environment = new EnvironmentImpl(handler); TimeZoneChangeListener changeEventTracker = - NotifyingTimeZoneChangeListener.create(handler, context, serviceConfigAccessor); + NotifyingTimeZoneChangeListener.create(handler, context, serviceConfigAccessor, + environment); return new TimeZoneDetectorStrategyImpl( serviceConfigAccessor, environment, changeEventTracker); } diff --git a/services/core/java/com/android/server/wm/LaunchParamsController.java b/services/core/java/com/android/server/wm/LaunchParamsController.java index d3c3d2834124..ba1401ab3978 100644 --- a/services/core/java/com/android/server/wm/LaunchParamsController.java +++ b/services/core/java/com/android/server/wm/LaunchParamsController.java @@ -79,7 +79,8 @@ class LaunchParamsController { * @param result The resulting params. */ void calculate(Task task, WindowLayout layout, ActivityRecord activity, ActivityRecord source, - ActivityOptions options, @Nullable Request request, int phase, LaunchParams result) { + ActivityOptions options, @Nullable Request request, + @LaunchParamsModifier.Phase int phase, LaunchParams result) { result.reset(); if (task != null || activity != null) { diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java index c39671d76929..e3a5b66b83fd 100644 --- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java +++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java @@ -96,9 +96,10 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { } @Override + @Result public int onCalculate(@Nullable Task task, @Nullable ActivityInfo.WindowLayout layout, @Nullable ActivityRecord activity, @Nullable ActivityRecord source, - @Nullable ActivityOptions options, @Nullable Request request, int phase, + @Nullable ActivityOptions options, @Nullable Request request, @Phase int phase, LaunchParams currentParams, LaunchParams outParams) { initLogBuilder(task, activity); final int result = calculate(task, layout, activity, source, options, request, phase, @@ -107,9 +108,10 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { return result; } + @Result private int calculate(@Nullable Task task, @Nullable ActivityInfo.WindowLayout layout, @Nullable ActivityRecord activity, @Nullable ActivityRecord source, - @Nullable ActivityOptions options, @Nullable Request request, int phase, + @Nullable ActivityOptions options, @Nullable Request request, @Phase int phase, LaunchParams currentParams, LaunchParams outParams) { final ActivityRecord root; if (task != null) { diff --git a/services/tests/timetests/src/com/android/server/timezonedetector/FakeEnvironment.java b/services/tests/timetests/src/com/android/server/timezonedetector/FakeEnvironment.java new file mode 100644 index 000000000000..5d181b81eb4c --- /dev/null +++ b/services/tests/timetests/src/com/android/server/timezonedetector/FakeEnvironment.java @@ -0,0 +1,141 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.timezonedetector; + +import static com.android.server.SystemTimeZone.TIME_ZONE_CONFIDENCE_LOW; + +import android.annotation.CurrentTimeMillisLong; +import android.annotation.ElapsedRealtimeLong; + +import com.android.server.SystemTimeZone; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + +/** + * A partially implemented, fake implementation of Environment for tests. + */ +public class FakeEnvironment implements Environment { + + private final TestState<String> mTimeZoneId = new TestState<>(); + private final TestState<Integer> mTimeZoneConfidence = new TestState<>(); + private final List<Runnable> mAsyncRunnables = new ArrayList<>(); + private @ElapsedRealtimeLong long mElapsedRealtimeMillis; + private @CurrentTimeMillisLong long mInitializationTimeMillis; + + FakeEnvironment() { + // Ensure the fake environment starts with the defaults a fresh device would. + initializeTimeZoneSetting("", TIME_ZONE_CONFIDENCE_LOW); + } + + void initializeClock(@CurrentTimeMillisLong long currentTimeMillis, + @ElapsedRealtimeLong long elapsedRealtimeMillis) { + mInitializationTimeMillis = currentTimeMillis - elapsedRealtimeMillis; + mElapsedRealtimeMillis = elapsedRealtimeMillis; + } + + void initializeTimeZoneSetting(String zoneId, + @SystemTimeZone.TimeZoneConfidence int timeZoneConfidence) { + mTimeZoneId.init(zoneId); + mTimeZoneConfidence.init(timeZoneConfidence); + } + + void incrementClock() { + mElapsedRealtimeMillis++; + } + + @Override + public String getDeviceTimeZone() { + return mTimeZoneId.getLatest(); + } + + @Override + public int getDeviceTimeZoneConfidence() { + return mTimeZoneConfidence.getLatest(); + } + + @Override + public void setDeviceTimeZoneAndConfidence( + String zoneId, @SystemTimeZone.TimeZoneConfidence int confidence, String logInfo) { + mTimeZoneId.set(zoneId); + mTimeZoneConfidence.set(confidence); + } + + void assertTimeZoneNotChanged() { + mTimeZoneId.assertHasNotBeenSet(); + mTimeZoneConfidence.assertHasNotBeenSet(); + } + + void assertTimeZoneChangedTo(String timeZoneId, + @SystemTimeZone.TimeZoneConfidence int confidence) { + mTimeZoneId.assertHasBeenSet(); + mTimeZoneId.assertChangeCount(1); + mTimeZoneId.assertLatestEquals(timeZoneId); + + mTimeZoneConfidence.assertHasBeenSet(); + mTimeZoneConfidence.assertChangeCount(1); + mTimeZoneConfidence.assertLatestEquals(confidence); + } + + void commitAllChanges() { + mTimeZoneId.commitLatest(); + mTimeZoneConfidence.commitLatest(); + } + + @Override + @ElapsedRealtimeLong + public long elapsedRealtimeMillis() { + return mElapsedRealtimeMillis; + } + + @Override + @CurrentTimeMillisLong + public long currentTimeMillis() { + return mInitializationTimeMillis + mElapsedRealtimeMillis; + } + + @Override + public void addDebugLogEntry(String logMsg) { + // No-op for tests + } + + @Override + public void dumpDebugLog(PrintWriter printWriter) { + // No-op for tests + } + + /** + * Adds the supplied runnable to a list but does not run them. To run all the runnables that + * have been supplied, call {@code #runAsyncRunnables}. + */ + @Override + public void runAsync(Runnable runnable) { + mAsyncRunnables.add(runnable); + } + + /** + * Requests that the runnable that have been supplied to {@code #runAsync} are invoked + * asynchronously and cleared. + */ + public void runAsyncRunnables() { + for (Runnable runnable : mAsyncRunnables) { + runnable.run(); + } + mAsyncRunnables.clear(); + } +} diff --git a/services/tests/timetests/src/com/android/server/timezonedetector/NotifyingTimeZoneChangeListenerTest.java b/services/tests/timetests/src/com/android/server/timezonedetector/NotifyingTimeZoneChangeListenerTest.java index 23c13bd04368..45cc891bff55 100644 --- a/services/tests/timetests/src/com/android/server/timezonedetector/NotifyingTimeZoneChangeListenerTest.java +++ b/services/tests/timetests/src/com/android/server/timezonedetector/NotifyingTimeZoneChangeListenerTest.java @@ -85,9 +85,6 @@ public class NotifyingTimeZoneChangeListenerTest { return List.of(ORIGIN_LOCATION, ORIGIN_TELEPHONY); } - private static final long ARBITRARY_ELAPSED_REALTIME_MILLIS = 1234; - /** A time zone used for initialization that does not occur elsewhere in tests. */ - private static final String ARBITRARY_TIME_ZONE_ID = "Etc/UTC"; private static final String INTERACT_ACROSS_USERS_FULL_PERMISSION = "android.permission.INTERACT_ACROSS_USERS_FULL"; @@ -99,6 +96,7 @@ public class NotifyingTimeZoneChangeListenerTest { private HandlerThread mHandlerThread; private TestHandler mHandler; private FakeServiceConfigAccessor mServiceConfigAccessor; + private FakeEnvironment mFakeEnvironment; private int mUid; private NotifyingTimeZoneChangeListener mTimeZoneChangeTracker; @@ -106,6 +104,9 @@ public class NotifyingTimeZoneChangeListenerTest { @Before public void setUp() { mUid = Process.myUid(); + mFakeEnvironment = new FakeEnvironment(); + mFakeEnvironment.initializeClock(1735689600L, 1234L); + // Create a thread + handler for processing the work that the service posts. mHandlerThread = new HandlerThread("TimeZoneDetectorInternalTest"); mHandlerThread.start(); @@ -138,7 +139,7 @@ public class NotifyingTimeZoneChangeListenerTest { mNotificationManager = new FakeNotificationManager(mContext, InstantSource.system()); mTimeZoneChangeTracker = new NotifyingTimeZoneChangeListener(mHandler, mContext, - mServiceConfigAccessor, mNotificationManager); + mServiceConfigAccessor, mNotificationManager, mFakeEnvironment); } @After @@ -151,7 +152,7 @@ public class NotifyingTimeZoneChangeListenerTest { public void process_autoDetectionOff_noManualTracking_shouldTrackWithoutNotifying() { enableTimeZoneNotifications(); - TimeZoneChangeRecord expectedChangeEvent = new TimeZoneChangeRecord( + TimeZoneChangeRecord expectedTimeZoneChangeRecord = new TimeZoneChangeRecord( /* id= */ 1, new TimeZoneChangeEvent( /* elapsedRealtimeMillis= */ 0, @@ -162,13 +163,14 @@ public class NotifyingTimeZoneChangeListenerTest { /* newZoneId= */ "Europe/London", /* newConfidence= */ 1, /* cause= */ "NO_REASON")); - expectedChangeEvent.setStatus(STATUS_UNTRACKED, SIGNAL_TYPE_NONE); + expectedTimeZoneChangeRecord.setStatus(STATUS_UNTRACKED, SIGNAL_TYPE_NONE); assertNull(mTimeZoneChangeTracker.getLastTimeZoneChangeRecord()); - mTimeZoneChangeTracker.process(expectedChangeEvent.getEvent()); + mTimeZoneChangeTracker.process(expectedTimeZoneChangeRecord.getEvent()); - assertEquals(expectedChangeEvent, mTimeZoneChangeTracker.getLastTimeZoneChangeRecord()); + assertEquals(expectedTimeZoneChangeRecord, + mTimeZoneChangeTracker.getLastTimeZoneChangeRecord()); assertEquals(0, mNotificationManager.getNotifications().size()); mHandler.assertTotalMessagesEnqueued(0); } @@ -177,7 +179,7 @@ public class NotifyingTimeZoneChangeListenerTest { public void process_autoDetectionOff_shouldTrackWithoutNotifying() { enableNotificationsWithManualChangeTracking(); - TimeZoneChangeRecord expectedChangeEvent = new TimeZoneChangeRecord( + TimeZoneChangeRecord expectedTimeZoneChangeRecord = new TimeZoneChangeRecord( /* id= */ 1, new TimeZoneChangeEvent( /* elapsedRealtimeMillis= */ 0, @@ -188,13 +190,14 @@ public class NotifyingTimeZoneChangeListenerTest { /* newZoneId= */ "Europe/London", /* newConfidence= */ 1, /* cause= */ "NO_REASON")); - expectedChangeEvent.setStatus(STATUS_UNTRACKED, SIGNAL_TYPE_NONE); + expectedTimeZoneChangeRecord.setStatus(STATUS_UNTRACKED, SIGNAL_TYPE_NONE); assertNull(mTimeZoneChangeTracker.getLastTimeZoneChangeRecord()); - mTimeZoneChangeTracker.process(expectedChangeEvent.getEvent()); + mTimeZoneChangeTracker.process(expectedTimeZoneChangeRecord.getEvent()); - assertEquals(expectedChangeEvent, mTimeZoneChangeTracker.getLastTimeZoneChangeRecord()); + assertEquals(expectedTimeZoneChangeRecord, + mTimeZoneChangeTracker.getLastTimeZoneChangeRecord()); assertEquals(0, mNotificationManager.getNotifications().size()); mHandler.assertTotalMessagesEnqueued(1); } @@ -214,7 +217,7 @@ public class NotifyingTimeZoneChangeListenerTest { enableNotificationsWithManualChangeTracking(); - TimeZoneChangeRecord expectedChangeEvent = new TimeZoneChangeRecord( + TimeZoneChangeRecord expectedTimeZoneChangeRecord = new TimeZoneChangeRecord( /* id= */ 1, new TimeZoneChangeEvent( /* elapsedRealtimeMillis= */ 0, @@ -225,19 +228,20 @@ public class NotifyingTimeZoneChangeListenerTest { /* newZoneId= */ "Europe/London", /* newConfidence= */ 1, /* cause= */ "NO_REASON")); - expectedChangeEvent.setStatus(STATUS_UNKNOWN, SIGNAL_TYPE_UNKNOWN); + expectedTimeZoneChangeRecord.setStatus(STATUS_UNKNOWN, SIGNAL_TYPE_UNKNOWN); assertNull(mTimeZoneChangeTracker.getLastTimeZoneChangeRecord()); // lastTrackedChangeEvent == null - mTimeZoneChangeTracker.process(expectedChangeEvent.getEvent()); - TimeZoneChangeRecord trackedEvent1 = mTimeZoneChangeTracker.getLastTimeZoneChangeRecord(); + mTimeZoneChangeTracker.process(expectedTimeZoneChangeRecord.getEvent()); + TimeZoneChangeRecord timeZoneChangeRecord1 = + mTimeZoneChangeTracker.getLastTimeZoneChangeRecord(); - assertEquals(expectedChangeEvent, trackedEvent1); + assertEquals(expectedTimeZoneChangeRecord, timeZoneChangeRecord1); assertEquals(1, mNotificationManager.getNotifications().size()); mHandler.assertTotalMessagesEnqueued(1); - expectedChangeEvent = new TimeZoneChangeRecord( + expectedTimeZoneChangeRecord = new TimeZoneChangeRecord( /* id= */ 2, new TimeZoneChangeEvent( /* elapsedRealtimeMillis= */ 1000L, @@ -248,14 +252,15 @@ public class NotifyingTimeZoneChangeListenerTest { /* newZoneId= */ "Europe/Paris", /* newConfidence= */ 1, /* cause= */ "NO_REASON")); - expectedChangeEvent.setStatus(STATUS_UNKNOWN, SIGNAL_TYPE_UNKNOWN); + expectedTimeZoneChangeRecord.setStatus(STATUS_UNKNOWN, SIGNAL_TYPE_UNKNOWN); // lastTrackedChangeEvent != null - mTimeZoneChangeTracker.process(expectedChangeEvent.getEvent()); - TimeZoneChangeRecord trackedEvent2 = mTimeZoneChangeTracker.getLastTimeZoneChangeRecord(); + mTimeZoneChangeTracker.process(expectedTimeZoneChangeRecord.getEvent()); + TimeZoneChangeRecord timeZoneChangeRecord2 = + mTimeZoneChangeTracker.getLastTimeZoneChangeRecord(); - assertEquals(STATUS_SUPERSEDED, trackedEvent1.getStatus()); - assertEquals(expectedChangeEvent, trackedEvent2); + assertEquals(STATUS_SUPERSEDED, timeZoneChangeRecord1.getStatus()); + assertEquals(expectedTimeZoneChangeRecord, timeZoneChangeRecord2); assertEquals(2, mNotificationManager.getNotifications().size()); mHandler.assertTotalMessagesEnqueued(2); @@ -263,7 +268,7 @@ public class NotifyingTimeZoneChangeListenerTest { // Test manual change within revert threshold { - expectedChangeEvent = new TimeZoneChangeRecord( + expectedTimeZoneChangeRecord = new TimeZoneChangeRecord( /* id= */ 3, new TimeZoneChangeEvent( /* elapsedRealtimeMillis= */ 999L + AUTO_REVERT_THRESHOLD, @@ -275,16 +280,16 @@ public class NotifyingTimeZoneChangeListenerTest { /* newZoneId= */ "Europe/London", /* newConfidence= */ 1, /* cause= */ "NO_REASON")); - expectedChangeEvent.setStatus(STATUS_UNTRACKED, SIGNAL_TYPE_NONE); + expectedTimeZoneChangeRecord.setStatus(STATUS_UNTRACKED, SIGNAL_TYPE_NONE); - mTimeZoneChangeTracker.process(expectedChangeEvent.getEvent()); - TimeZoneChangeRecord trackedEvent3 = + mTimeZoneChangeTracker.process(expectedTimeZoneChangeRecord.getEvent()); + TimeZoneChangeRecord timeZoneChangeRecord3 = mTimeZoneChangeTracker.getLastTimeZoneChangeRecord(); // The user manually changed the time zone within a short period of receiving the // notification, indicating that they rejected the automatic change of time zone - assertEquals(STATUS_REJECTED, trackedEvent2.getStatus()); - assertEquals(expectedChangeEvent, trackedEvent3); + assertEquals(STATUS_REJECTED, timeZoneChangeRecord2.getStatus()); + assertEquals(expectedTimeZoneChangeRecord, timeZoneChangeRecord3); assertEquals(2, mNotificationManager.getNotifications().size()); mHandler.assertTotalMessagesEnqueued(3); } @@ -293,12 +298,12 @@ public class NotifyingTimeZoneChangeListenerTest { { // [START] Reset previous event enableNotificationsWithManualChangeTracking(); - mTimeZoneChangeTracker.process(trackedEvent2.getEvent()); - trackedEvent2 = mTimeZoneChangeTracker.getLastTimeZoneChangeRecord(); + mTimeZoneChangeTracker.process(timeZoneChangeRecord2.getEvent()); + timeZoneChangeRecord2 = mTimeZoneChangeTracker.getLastTimeZoneChangeRecord(); disableTimeZoneAutoDetection(); // [END] Reset previous event - expectedChangeEvent = new TimeZoneChangeRecord( + expectedTimeZoneChangeRecord = new TimeZoneChangeRecord( /* id= */ 5, new TimeZoneChangeEvent( /* elapsedRealtimeMillis= */ 1001L + AUTO_REVERT_THRESHOLD, @@ -310,15 +315,15 @@ public class NotifyingTimeZoneChangeListenerTest { /* newZoneId= */ "Europe/London", /* newConfidence= */ 1, /* cause= */ "NO_REASON")); - expectedChangeEvent.setStatus(STATUS_UNTRACKED, SIGNAL_TYPE_NONE); + expectedTimeZoneChangeRecord.setStatus(STATUS_UNTRACKED, SIGNAL_TYPE_NONE); - mTimeZoneChangeTracker.process(expectedChangeEvent.getEvent()); - TimeZoneChangeRecord trackedEvent3 = + mTimeZoneChangeTracker.process(expectedTimeZoneChangeRecord.getEvent()); + TimeZoneChangeRecord timeZoneChangeRecord3 = mTimeZoneChangeTracker.getLastTimeZoneChangeRecord(); // The user manually changed the time zone outside of the period we consider as a revert - assertEquals(STATUS_SUPERSEDED, trackedEvent2.getStatus()); - assertEquals(expectedChangeEvent, trackedEvent3); + assertEquals(STATUS_SUPERSEDED, timeZoneChangeRecord2.getStatus()); + assertEquals(expectedTimeZoneChangeRecord, timeZoneChangeRecord3); assertEquals(3, mNotificationManager.getNotifications().size()); mHandler.assertTotalMessagesEnqueued(5); } @@ -339,7 +344,7 @@ public class NotifyingTimeZoneChangeListenerTest { enableNotificationsWithManualChangeTracking(); - TimeZoneChangeRecord expectedChangeEvent = new TimeZoneChangeRecord( + TimeZoneChangeRecord expectedTimeZoneChangeRecord = new TimeZoneChangeRecord( /* id= */ 1, new TimeZoneChangeEvent( /* elapsedRealtimeMillis= */ 0, @@ -350,19 +355,20 @@ public class NotifyingTimeZoneChangeListenerTest { /* newZoneId= */ "Europe/London", /* newConfidence= */ 1, /* cause= */ "NO_REASON")); - expectedChangeEvent.setStatus(STATUS_UNKNOWN, SIGNAL_TYPE_UNKNOWN); + expectedTimeZoneChangeRecord.setStatus(STATUS_UNKNOWN, SIGNAL_TYPE_UNKNOWN); assertNull(mTimeZoneChangeTracker.getLastTimeZoneChangeRecord()); // lastTrackedChangeEvent == null - mTimeZoneChangeTracker.process(expectedChangeEvent.getEvent()); - TimeZoneChangeRecord trackedEvent1 = mTimeZoneChangeTracker.getLastTimeZoneChangeRecord(); + mTimeZoneChangeTracker.process(expectedTimeZoneChangeRecord.getEvent()); + TimeZoneChangeRecord timeZoneChangeRecord1 = + mTimeZoneChangeTracker.getLastTimeZoneChangeRecord(); - assertEquals(expectedChangeEvent, trackedEvent1); + assertEquals(expectedTimeZoneChangeRecord, timeZoneChangeRecord1); assertEquals(1, mNotificationManager.getNotifications().size()); mHandler.assertTotalMessagesEnqueued(1); - expectedChangeEvent = new TimeZoneChangeRecord( + expectedTimeZoneChangeRecord = new TimeZoneChangeRecord( /* id= */ 3, new TimeZoneChangeEvent( /* elapsedRealtimeMillis= */ 1000L, @@ -373,14 +379,15 @@ public class NotifyingTimeZoneChangeListenerTest { /* newZoneId= */ "Europe/Paris", /* newConfidence= */ 1, /* cause= */ "NO_REASON")); - expectedChangeEvent.setStatus(STATUS_UNKNOWN, SIGNAL_TYPE_UNKNOWN); + expectedTimeZoneChangeRecord.setStatus(STATUS_UNKNOWN, SIGNAL_TYPE_UNKNOWN); // lastTrackedChangeEvent != null - mTimeZoneChangeTracker.process(expectedChangeEvent.getEvent()); - TimeZoneChangeRecord trackedEvent2 = mTimeZoneChangeTracker.getLastTimeZoneChangeRecord(); + mTimeZoneChangeTracker.process(expectedTimeZoneChangeRecord.getEvent()); + TimeZoneChangeRecord timeZoneChangeRecord2 = + mTimeZoneChangeTracker.getLastTimeZoneChangeRecord(); - assertEquals(STATUS_SUPERSEDED, trackedEvent1.getStatus()); - assertEquals(expectedChangeEvent, trackedEvent2); + assertEquals(STATUS_SUPERSEDED, timeZoneChangeRecord1.getStatus()); + assertEquals(expectedTimeZoneChangeRecord, timeZoneChangeRecord2); assertEquals(2, mNotificationManager.getNotifications().size()); mHandler.assertTotalMessagesEnqueued(2); } @@ -400,7 +407,7 @@ public class NotifyingTimeZoneChangeListenerTest { enableNotificationsWithManualChangeTracking(); - TimeZoneChangeRecord expectedChangeEvent = new TimeZoneChangeRecord( + TimeZoneChangeRecord expectedTimeZoneChangeRecord = new TimeZoneChangeRecord( /* id= */ 1, new TimeZoneChangeEvent( /* elapsedRealtimeMillis= */ 0, @@ -411,15 +418,16 @@ public class NotifyingTimeZoneChangeListenerTest { /* newZoneId= */ "Europe/Rome", /* newConfidence= */ 1, /* cause= */ "NO_REASON")); - expectedChangeEvent.setStatus(STATUS_UNKNOWN, SIGNAL_TYPE_UNKNOWN); + expectedTimeZoneChangeRecord.setStatus(STATUS_UNKNOWN, SIGNAL_TYPE_UNKNOWN); assertNull(mTimeZoneChangeTracker.getLastTimeZoneChangeRecord()); // lastTrackedChangeEvent == null - mTimeZoneChangeTracker.process(expectedChangeEvent.getEvent()); - TimeZoneChangeRecord trackedEvent1 = mTimeZoneChangeTracker.getLastTimeZoneChangeRecord(); + mTimeZoneChangeTracker.process(expectedTimeZoneChangeRecord.getEvent()); + TimeZoneChangeRecord timeZoneChangeRecord1 = + mTimeZoneChangeTracker.getLastTimeZoneChangeRecord(); - assertEquals(expectedChangeEvent, trackedEvent1); + assertEquals(expectedTimeZoneChangeRecord, timeZoneChangeRecord1); // No notification sent for the same UTC offset assertEquals(0, mNotificationManager.getNotifications().size()); mHandler.assertTotalMessagesEnqueued(1); diff --git a/services/tests/timetests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java b/services/tests/timetests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java index 9a01fa2eb966..44232e7ddfa2 100644 --- a/services/tests/timetests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java +++ b/services/tests/timetests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java @@ -63,7 +63,6 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import android.annotation.ElapsedRealtimeLong; import android.annotation.NonNull; import android.annotation.UserIdInt; import android.app.time.LocationTimeZoneAlgorithmStatus; @@ -94,7 +93,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -114,6 +112,7 @@ public class TimeZoneDetectorStrategyImplTest { @Rule public final SetFlagsRule mSetFlagsRule = mClassRule.createSetFlagsRule(); + private static final long ARBITRARY_CURRENT_TIME_MILLIS = 1735689600; // 2025-01-01 00:00:00 private static final long ARBITRARY_ELAPSED_REALTIME_MILLIS = 1234; /** A time zone used for initialization that does not occur elsewhere in tests. */ private static final String ARBITRARY_TIME_ZONE_ID = "Etc/UTC"; @@ -1220,7 +1219,7 @@ public class TimeZoneDetectorStrategyImplTest { .build(); Script script = new Script() - .initializeClock(ARBITRARY_ELAPSED_REALTIME_MILLIS) + .initializeClock(ARBITRARY_CURRENT_TIME_MILLIS, ARBITRARY_ELAPSED_REALTIME_MILLIS) .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID, TIME_ZONE_CONFIDENCE_LOW) .simulateConfigurationInternalChange(config) .resetConfigurationTracking(); @@ -1420,7 +1419,7 @@ public class TimeZoneDetectorStrategyImplTest { .build(); Script script = new Script() - .initializeClock(ARBITRARY_ELAPSED_REALTIME_MILLIS) + .initializeClock(ARBITRARY_CURRENT_TIME_MILLIS, ARBITRARY_ELAPSED_REALTIME_MILLIS) .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID, TIME_ZONE_CONFIDENCE_LOW) .simulateConfigurationInternalChange(config) .resetConfigurationTracking(); @@ -1591,7 +1590,7 @@ public class TimeZoneDetectorStrategyImplTest { .build(); Script script = new Script() - .initializeClock(ARBITRARY_ELAPSED_REALTIME_MILLIS) + .initializeClock(ARBITRARY_CURRENT_TIME_MILLIS, ARBITRARY_ELAPSED_REALTIME_MILLIS) .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID, TIME_ZONE_CONFIDENCE_LOW) .simulateConfigurationInternalChange(config) .resetConfigurationTracking(); @@ -1666,7 +1665,7 @@ public class TimeZoneDetectorStrategyImplTest { @Test public void testGetTimeZoneState() { Script script = new Script() - .initializeClock(ARBITRARY_ELAPSED_REALTIME_MILLIS) + .initializeClock(ARBITRARY_CURRENT_TIME_MILLIS, ARBITRARY_ELAPSED_REALTIME_MILLIS) .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID, TIME_ZONE_CONFIDENCE_LOW) .simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED_GEO_DISABLED) .resetConfigurationTracking(); @@ -1688,7 +1687,7 @@ public class TimeZoneDetectorStrategyImplTest { @Test public void testSetTimeZoneState() { Script script = new Script() - .initializeClock(ARBITRARY_ELAPSED_REALTIME_MILLIS) + .initializeClock(ARBITRARY_CURRENT_TIME_MILLIS, ARBITRARY_ELAPSED_REALTIME_MILLIS) .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID, TIME_ZONE_CONFIDENCE_LOW) .simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED_GEO_DISABLED) .resetConfigurationTracking(); @@ -1715,7 +1714,7 @@ public class TimeZoneDetectorStrategyImplTest { private void testConfirmTimeZone(ConfigurationInternal config) { String timeZoneId = "Europe/London"; Script script = new Script() - .initializeClock(ARBITRARY_ELAPSED_REALTIME_MILLIS) + .initializeClock(ARBITRARY_CURRENT_TIME_MILLIS, ARBITRARY_ELAPSED_REALTIME_MILLIS) .initializeTimeZoneSetting(timeZoneId, TIME_ZONE_CONFIDENCE_LOW) .simulateConfigurationInternalChange(config) .resetConfigurationTracking(); @@ -1902,97 +1901,6 @@ public class TimeZoneDetectorStrategyImplTest { mFakeEnvironment.elapsedRealtimeMillis(), Arrays.asList(zoneIds)); } - static class FakeEnvironment implements TimeZoneDetectorStrategyImpl.Environment { - - private final TestState<String> mTimeZoneId = new TestState<>(); - private final TestState<Integer> mTimeZoneConfidence = new TestState<>(); - private final List<Runnable> mAsyncRunnables = new ArrayList<>(); - private @ElapsedRealtimeLong long mElapsedRealtimeMillis; - - FakeEnvironment() { - // Ensure the fake environment starts with the defaults a fresh device would. - initializeTimeZoneSetting("", TIME_ZONE_CONFIDENCE_LOW); - } - - void initializeClock(@ElapsedRealtimeLong long elapsedRealtimeMillis) { - mElapsedRealtimeMillis = elapsedRealtimeMillis; - } - - void initializeTimeZoneSetting(String zoneId, @TimeZoneConfidence int timeZoneConfidence) { - mTimeZoneId.init(zoneId); - mTimeZoneConfidence.init(timeZoneConfidence); - } - - void incrementClock() { - mElapsedRealtimeMillis++; - } - - @Override - public String getDeviceTimeZone() { - return mTimeZoneId.getLatest(); - } - - @Override - public int getDeviceTimeZoneConfidence() { - return mTimeZoneConfidence.getLatest(); - } - - @Override - public void setDeviceTimeZoneAndConfidence( - String zoneId, @TimeZoneConfidence int confidence, String logInfo) { - mTimeZoneId.set(zoneId); - mTimeZoneConfidence.set(confidence); - } - - void assertTimeZoneNotChanged() { - mTimeZoneId.assertHasNotBeenSet(); - mTimeZoneConfidence.assertHasNotBeenSet(); - } - - void assertTimeZoneChangedTo(String timeZoneId, @TimeZoneConfidence int confidence) { - mTimeZoneId.assertHasBeenSet(); - mTimeZoneId.assertChangeCount(1); - mTimeZoneId.assertLatestEquals(timeZoneId); - - mTimeZoneConfidence.assertHasBeenSet(); - mTimeZoneConfidence.assertChangeCount(1); - mTimeZoneConfidence.assertLatestEquals(confidence); - } - - void commitAllChanges() { - mTimeZoneId.commitLatest(); - mTimeZoneConfidence.commitLatest(); - } - - @Override - @ElapsedRealtimeLong - public long elapsedRealtimeMillis() { - return mElapsedRealtimeMillis; - } - - @Override - public void addDebugLogEntry(String logMsg) { - // No-op for tests - } - - @Override - public void dumpDebugLog(PrintWriter printWriter) { - // No-op for tests - } - - @Override - public void runAsync(Runnable runnable) { - mAsyncRunnables.add(runnable); - } - - public void runAsyncRunnables() { - for (Runnable runnable : mAsyncRunnables) { - runnable.run(); - } - mAsyncRunnables.clear(); - } - } - private void assertStateChangeNotificationsSent( TestStateChangeListener stateChangeListener, int expectedCount) { // The fake environment needs to be told to run posted work. @@ -2013,8 +1921,8 @@ public class TimeZoneDetectorStrategyImplTest { return this; } - Script initializeClock(long elapsedRealtimeMillis) { - mFakeEnvironment.initializeClock(elapsedRealtimeMillis); + Script initializeClock(long currentTimeMillis, long elapsedRealtimeMillis) { + mFakeEnvironment.initializeClock(currentTimeMillis, elapsedRealtimeMillis); return this; } |