diff options
73 files changed, 979 insertions, 273 deletions
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java index b732da29b754..9ba94c8b9d11 100644 --- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java +++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java @@ -69,6 +69,8 @@ import java.io.IOException; import java.util.ArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicReference; /** * Perf tests for user life cycle events. @@ -101,7 +103,6 @@ public class UserLifecycleTests { private static final long TIMEOUT_MAX_TEST_TIME_MS = 24 * 60_000; private static final int TIMEOUT_IN_SECOND = 30; - private static final int CHECK_USER_REMOVED_INTERVAL_MS = 200; /** Name of users/profiles in the test. Users with this name may be freely removed. */ private static final String TEST_USER_NAME = "UserLifecycleTests_test_user"; @@ -1471,17 +1472,10 @@ public class UserLifecycleTests { private void removeUser(int userId) throws RemoteException { stopUserAfterWaitingForBroadcastIdle(userId, true); try { - mUm.removeUser(userId); - final long startTime = System.currentTimeMillis(); - final long timeoutInMs = TIMEOUT_IN_SECOND * 1000; - while (mUm.getUserInfo(userId) != null && - System.currentTimeMillis() - startTime < timeoutInMs) { - TimeUnit.MILLISECONDS.sleep(CHECK_USER_REMOVED_INTERVAL_MS); - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } catch (Exception e) { - // Ignore + runShellCommandWithTimeout("pm remove-user -w " + userId, TIMEOUT_IN_SECOND); + } catch (TimeoutException e) { + Log.e(TAG, String.format("Could not remove user %d in %d seconds", + userId, TIMEOUT_IN_SECOND), e); } if (mUm.getUserInfo(userId) != null) { mUsersToRemove.add(userId); @@ -1544,7 +1538,11 @@ public class UserLifecycleTests { } private void waitForBroadcastIdle() { - ShellHelper.runShellCommand("am wait-for-broadcast-idle"); + try { + runShellCommandWithTimeout("am wait-for-broadcast-idle", TIMEOUT_IN_SECOND); + } catch (TimeoutException e) { + Log.e(TAG, "Ending waitForBroadcastIdle because it is taking too long", e); + } } private void sleep(long ms) { @@ -1560,4 +1558,41 @@ public class UserLifecycleTests { waitForBroadcastIdle(); sleep(tenSeconds); } + + /** + * Runs a Shell command with a timeout, returning a trimmed response. + */ + private String runShellCommandWithTimeout(String command, long timeoutInSecond) + throws TimeoutException { + AtomicReference<Exception> exception = new AtomicReference<>(null); + AtomicReference<String> result = new AtomicReference<>(null); + + CountDownLatch latch = new CountDownLatch(1); + + new Thread(() -> { + try { + result.set(ShellHelper.runShellCommandRaw(command)); + } catch (Exception e) { + exception.set(e); + } finally { + latch.countDown(); + } + }).start(); + + try { + if (!latch.await(timeoutInSecond, TimeUnit.SECONDS)) { + throw new TimeoutException("Command: '" + command + "' could not run in " + + timeoutInSecond + " seconds"); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + + if (exception.get() != null) { + Log.e(TAG, "Command: '" + command + "' failed.", exception.get()); + throw new RuntimeException(exception.get()); + } + + return result.get(); + } } diff --git a/core/java/android/view/IRemoteAnimationRunner.aidl b/core/java/android/view/IRemoteAnimationRunner.aidl index 1981c9d66c8b..1f64fb8ca2ec 100644 --- a/core/java/android/view/IRemoteAnimationRunner.aidl +++ b/core/java/android/view/IRemoteAnimationRunner.aidl @@ -46,5 +46,5 @@ oneway interface IRemoteAnimationRunner { * won't have any effect anymore. */ @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) - void onAnimationCancelled(boolean isKeyguardOccluded); + void onAnimationCancelled(); } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java index b917ac80256c..d9b73a8290f5 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java @@ -83,10 +83,7 @@ class TaskFragmentAnimationRunner extends IRemoteAnimationRunner.Stub { } @Override - public void onAnimationCancelled(boolean isKeyguardOccluded) { - if (TaskFragmentAnimationController.DEBUG) { - Log.v(TAG, "onAnimationCancelled: isKeyguardOccluded=" + isKeyguardOccluded); - } + public void onAnimationCancelled() { mHandler.post(this::cancelAnimation); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java index 22c90153bb39..edefe9e3ab06 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java @@ -404,7 +404,7 @@ class CrossActivityAnimation { } @Override - public void onAnimationCancelled(boolean isKeyguardOccluded) { + public void onAnimationCancelled() { finishAnimation(); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java index f0c5d8b29b2f..2d6ec7547187 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java @@ -323,7 +323,7 @@ class CustomizeActivityAnimation { } @Override - public void onAnimationCancelled(boolean isKeyguardOccluded) { + public void onAnimationCancelled() { finishAnimation(); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java index f8f8897e41d5..2afe8ee83391 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java @@ -1007,6 +1007,7 @@ public class BubbleStackView extends FrameLayout updatePointerPosition(false /* forIme */); mExpandedAnimationController.expandFromStack(() -> { afterExpandedViewAnimation(); + mExpandedViewContainer.setVisibility(VISIBLE); showManageMenu(mShowingManage); } /* after */); PointF p = mPositioner.getExpandedBubbleXY(getBubbleIndex(mExpandedBubble), 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 d8e2f5c4a817..2f0f56cfdfb0 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 @@ -634,14 +634,8 @@ public abstract class WMShellModule { @WMSingleton @Provides - static UnfoldBackgroundController provideUnfoldBackgroundController( - RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, - Context context - ) { - return new UnfoldBackgroundController( - context, - rootTaskDisplayAreaOrganizer - ); + static UnfoldBackgroundController provideUnfoldBackgroundController(Context context) { + return new UnfoldBackgroundController(context); } // diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index 2f25511a1f4d..643245943916 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -460,7 +460,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } } @Override - public void onAnimationCancelled(boolean isKeyguardOccluded) { + public void onAnimationCancelled() { final WindowContainerTransaction evictWct = new WindowContainerTransaction(); mStageCoordinator.prepareEvictInvisibleChildTasks(evictWct); mSyncQueue.queue(evictWct); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 49e8227c98f1..4c903f500651 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -483,7 +483,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } } @Override - public void onAnimationCancelled(boolean isKeyguardOccluded) { + public void onAnimationCancelled() { if (isEnteringSplit) { mMainExecutor.execute(() -> exitSplitScreen( mSideStage.getChildCount() == 0 ? mMainStage : mSideStage, @@ -869,7 +869,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, onRemoteAnimationFinished(apps); t.apply(); try { - adapter.getRunner().onAnimationCancelled(mKeyguardShowing); + adapter.getRunner().onAnimationCancelled(); } catch (RemoteException e) { Slog.e(TAG, "Error starting remote animation", e); } @@ -1013,11 +1013,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } @Override - public void onAnimationCancelled(boolean isKeyguardOccluded) { + public void onAnimationCancelled() { onRemoteAnimationFinishedOrCancelled(evictWct); setDividerVisibility(true, null); try { - adapter.getRunner().onAnimationCancelled(isKeyguardOccluded); + adapter.getRunner().onAnimationCancelled(); } catch (RemoteException e) { Slog.e(TAG, "Error starting remote animation", e); } @@ -1038,7 +1038,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, onRemoteAnimationFinished(apps); t.apply(); try { - adapter.getRunner().onAnimationCancelled(mKeyguardShowing); + adapter.getRunner().onAnimationCancelled(); } catch (RemoteException e) { Slog.e(TAG, "Error starting remote animation", e); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/LegacyTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/LegacyTransitions.java index 61e92f355dc2..61e11e877b90 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/LegacyTransitions.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/LegacyTransitions.java @@ -107,7 +107,7 @@ public class LegacyTransitions { } @Override - public void onAnimationCancelled(boolean isKeyguardOccluded) throws RemoteException { + public void onAnimationCancelled() throws RemoteException { mCancelled = true; mApps = mWallpapers = mNonApps = null; checkApply(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldBackgroundController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldBackgroundController.java index fe0a3fb7b9dc..96657af22e37 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldBackgroundController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldBackgroundController.java @@ -19,14 +19,12 @@ package com.android.wm.shell.unfold; import static android.graphics.Color.blue; import static android.graphics.Color.green; import static android.graphics.Color.red; -import static android.view.Display.DEFAULT_DISPLAY; import android.annotation.NonNull; import android.content.Context; import android.view.SurfaceControl; import com.android.wm.shell.R; -import com.android.wm.shell.RootTaskDisplayAreaOrganizer; /** * Controls background color layer for the unfold animations @@ -34,15 +32,10 @@ import com.android.wm.shell.RootTaskDisplayAreaOrganizer; public class UnfoldBackgroundController { private static final int BACKGROUND_LAYER_Z_INDEX = -1; - - private final RootTaskDisplayAreaOrganizer mRootTaskDisplayAreaOrganizer; private final float[] mBackgroundColor; private SurfaceControl mBackgroundLayer; - public UnfoldBackgroundController( - @NonNull Context context, - @NonNull RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer) { - mRootTaskDisplayAreaOrganizer = rootTaskDisplayAreaOrganizer; + public UnfoldBackgroundController(@NonNull Context context) { mBackgroundColor = getBackgroundColor(context); } @@ -57,7 +50,6 @@ public class UnfoldBackgroundController { .setName("app-unfold-background") .setCallsite("AppUnfoldTransitionController") .setColorLayer(); - mRootTaskDisplayAreaOrganizer.attachToDisplayArea(DEFAULT_DISPLAY, colorLayerBuilder); mBackgroundLayer = colorLayerBuilder.build(); transaction diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index b95a149eb0cc..a5908a888449 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -252,9 +252,11 @@ filegroup { // domain "tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt", "tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt", + "tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt", "tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt", "tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt", "tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt", + "tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt", "tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt", // ui "tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt", @@ -263,6 +265,7 @@ filegroup { "tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt", "tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt", "tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt", + "tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt", // Keyguard helper "tests/src/com/android/systemui/keyguard/data/quickaffordance/FakeKeyguardQuickAffordanceConfig.kt", "tests/src/com/android/systemui/dump/LogBufferHelper.kt", diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt index 296c2ae5cf99..94b37403b232 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt @@ -436,8 +436,8 @@ class ActivityLaunchAnimator( } @BinderThread - override fun onAnimationCancelled(isKeyguardOccluded: Boolean) { - context.mainExecutor.execute { delegate.onAnimationCancelled(isKeyguardOccluded) } + override fun onAnimationCancelled() { + context.mainExecutor.execute { delegate.onAnimationCancelled() } } } @@ -744,7 +744,7 @@ class ActivityLaunchAnimator( } @UiThread - override fun onAnimationCancelled(isKeyguardOccluded: Boolean) { + override fun onAnimationCancelled() { if (timedOut) { return } @@ -754,7 +754,7 @@ class ActivityLaunchAnimator( removeTimeout() animation?.cancel() - controller.onLaunchAnimationCancelled(newKeyguardOccludedState = isKeyguardOccluded) + controller.onLaunchAnimationCancelled() } private fun IRemoteAnimationFinishedCallback.invoke() { diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationDelegate.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationDelegate.kt index 337408bb9c5d..d465962d6edf 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationDelegate.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationDelegate.kt @@ -26,5 +26,5 @@ interface RemoteAnimationDelegate<in T : IRemoteAnimationFinishedCallback> { ) /** Called on the UI thread when a signal is received to cancel the animation. */ - @UiThread fun onAnimationCancelled(isKeyguardOccluded: Boolean) + @UiThread fun onAnimationCancelled() } diff --git a/packages/SystemUI/res-keyguard/color/numpad_key_color_secondary.xml b/packages/SystemUI/res-keyguard/color/numpad_key_color_secondary.xml index 08c66a24348c..47641ee64ee1 100644 --- a/packages/SystemUI/res-keyguard/color/numpad_key_color_secondary.xml +++ b/packages/SystemUI/res-keyguard/color/numpad_key_color_secondary.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> - <item android:color="?androidprv:attr/colorAccentSecondaryVariant"/> + <item android:color="?androidprv:attr/materialColorSecondaryFixedDim"/> </selector>
\ No newline at end of file diff --git a/packages/SystemUI/res-keyguard/drawable/kg_emergency_button_background.xml b/packages/SystemUI/res-keyguard/drawable/kg_emergency_button_background.xml index 07642736869c..5e7cf3ee41fb 100644 --- a/packages/SystemUI/res-keyguard/drawable/kg_emergency_button_background.xml +++ b/packages/SystemUI/res-keyguard/drawable/kg_emergency_button_background.xml @@ -19,7 +19,7 @@ android:color="?attr/wallpaperTextColorSecondary"> <item android:id="@android:id/background"> <shape android:shape="rectangle"> - <solid android:color="?androidprv:attr/colorAccentTertiary"/> + <solid android:color="?androidprv:attr/materialColorTertiaryFixed"/> <corners android:radius="24dp"/> </shape> </item> diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml index 67fd5b9a78bd..83736e9d9473 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml @@ -19,6 +19,7 @@ <!-- This contains disable eSim buttons shared by sim_pin/sim_puk screens --> <com.android.keyguard.KeyguardEsimArea xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:id="@+id/keyguard_disable_esim" style="@style/Keyguard.TextView" android:layout_width="wrap_content" @@ -26,8 +27,8 @@ android:background="@drawable/kg_bouncer_secondary_button" android:drawablePadding="10dp" android:drawableStart="@drawable/ic_no_sim" - android:drawableTint="?android:attr/textColorPrimary" + android:drawableTint="?androidprv:attr/materialColorOnSurface" android:text="@string/disable_carrier_button_text" - android:textColor="?android:attr/textColorPrimary" + android:textColor="?androidprv:attr/materialColorOnSurface" android:textSize="@dimen/kg_status_line_font_size" android:visibility="gone" /> diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_security_container_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_security_container_view.xml index 426cfafb190e..751b07ae9a6e 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_security_container_view.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_security_container_view.xml @@ -19,13 +19,14 @@ <com.android.keyguard.KeyguardSecurityContainer xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:androidprv="http://schemas.android.com/apk/res-auto" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:id="@+id/keyguard_security_container" + android:background="?androidprv:attr/materialColorSurfaceContainer" android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false" - android:paddingTop="@dimen/keyguard_lock_padding" + android:paddingTop="@dimen/status_bar_height" android:importantForAccessibility="yes"> <!-- Needed because TYPE_WINDOW_STATE_CHANGED is sent from this view when bouncer is shown --> <com.android.keyguard.KeyguardSecurityViewFlipper diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml index 04dffb6e8c52..4fc411eaea9d 100644 --- a/packages/SystemUI/res-keyguard/values/styles.xml +++ b/packages/SystemUI/res-keyguard/values/styles.xml @@ -24,7 +24,7 @@ <item name="android:textSize">@dimen/kg_status_line_font_size</item> </style> <style name="Keyguard.TextView.EmergencyButton" parent="Theme.SystemUI"> - <item name="android:textColor">?androidprv:attr/textColorOnAccent</item> + <item name="android:textColor">?androidprv:attr/materialColorOnTertiaryFixed</item> <item name="android:textSize">16sp</item> <item name="android:background">@drawable/kg_emergency_button_background</item> <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item> diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml index fe9542b7aed6..d9fe949bb327 100644 --- a/packages/SystemUI/res/layout/super_notification_shade.xml +++ b/packages/SystemUI/res/layout/super_notification_shade.xml @@ -101,7 +101,6 @@ </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" diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index a2eba81155c7..0aa880fe6d88 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -808,6 +808,8 @@ <dimen name="keyguard_lock_height">42dp</dimen> <dimen name="keyguard_lock_padding">20dp</dimen> + <dimen name="keyguard_security_container_padding_top">20dp</dimen> + <dimen name="keyguard_indication_margin_bottom">32dp</dimen> <dimen name="lock_icon_margin_bottom">74dp</dimen> <dimen name="ambient_indication_margin_bottom">71dp</dimen> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java index 1b0dacc327c1..8dcd2aaac9ef 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java @@ -206,7 +206,7 @@ public abstract class RemoteAnimationRunnerCompat extends IRemoteAnimationRunner t.close(); info.releaseAllSurfaces(); if (finishRunnable == null) return; - onAnimationCancelled(false /* isKeyguardOccluded */); + onAnimationCancelled(); finishRunnable.run(); } }; diff --git a/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt b/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt index f59bf8e766fe..62f4f2282e66 100644 --- a/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt +++ b/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt @@ -28,6 +28,7 @@ import android.util.AttributeSet import android.view.View import com.android.settingslib.Utils import com.android.systemui.animation.Interpolators +import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.TITLE /** Displays security messages for the keyguard bouncer. */ open class BouncerKeyguardMessageArea(context: Context?, attrs: AttributeSet?) : @@ -56,8 +57,7 @@ open class BouncerKeyguardMessageArea(context: Context?, attrs: AttributeSet?) : } override fun onThemeChanged() { - val array: TypedArray = - mContext.obtainStyledAttributes(intArrayOf(android.R.attr.textColorPrimary)) + val array: TypedArray = mContext.obtainStyledAttributes(intArrayOf(TITLE)) val newTextColors: ColorStateList = ColorStateList.valueOf(array.getColor(0, Color.RED)) array.recycle() mDefaultColorState = newTextColors @@ -65,7 +65,7 @@ open class BouncerKeyguardMessageArea(context: Context?, attrs: AttributeSet?) : } override fun reloadColor() { - mDefaultColorState = Utils.getColorAttr(context, android.R.attr.textColorPrimary) + mDefaultColorState = Utils.getColorAttr(context, TITLE) super.reloadColor() } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index ba5a8c94dc23..b88d85c843e4 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -54,6 +54,7 @@ import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; import android.graphics.drawable.LayerDrawable; import android.os.UserManager; import android.provider.Settings; @@ -333,6 +334,11 @@ public class KeyguardSecurityContainer extends ConstraintLayout { mSpringAnimation = new SpringAnimation(this, DynamicAnimation.TRANSLATION_Y); mViewConfiguration = ViewConfiguration.get(context); mDoubleTapDetector = new GestureDetector(context, new DoubleTapListener()); + + // Add additional top padding. + setPadding(getPaddingLeft(), getPaddingTop() + getResources().getDimensionPixelSize( + R.dimen.keyguard_security_container_padding_top), getPaddingRight(), + getPaddingBottom()); } void onResume(SecurityMode securityMode, boolean faceAuthEnabled) { @@ -780,6 +786,8 @@ public class KeyguardSecurityContainer extends ConstraintLayout { void reloadColors() { mViewMode.reloadColors(); + setBackgroundColor(Utils.getColorAttrDefaultColor(getContext(), + com.android.internal.R.attr.materialColorSurface)); } /** Handles density or font scale changes. */ @@ -1022,11 +1030,15 @@ public class KeyguardSecurityContainer extends ConstraintLayout { mUserSwitcherController.removeUserSwitchCallback(mUserSwitchCallback); } - private Drawable findUserIcon(int userId) { + private Drawable findLargeUserIcon(int userId) { Bitmap userIcon = UserManager.get(mView.getContext()).getUserIcon(userId); if (userIcon != null) { - return CircleFramedDrawable.getInstance(mView.getContext(), - userIcon); + int iconSize = + mResources.getDimensionPixelSize(R.dimen.bouncer_user_switcher_icon_size); + return CircleFramedDrawable.getInstance( + mView.getContext(), + Icon.scaleDownIfNecessary(userIcon, iconSize, iconSize) + ); } return UserIcons.getDefaultUserIcon(mResources, userId, false); @@ -1085,7 +1097,7 @@ public class KeyguardSecurityContainer extends ConstraintLayout { return; } final String currentUserName = mUserSwitcherController.getCurrentUserName(); - Drawable userIcon = findUserIcon(currentUser.info.id); + Drawable userIcon = findLargeUserIcon(currentUser.info.id); ((ImageView) mView.findViewById(R.id.user_icon)).setImageDrawable(userIcon); mUserSwitcher.setText(currentUserName); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimInputView.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardSimInputView.kt index b4bfca1185f4..3fc39afe5d0f 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimInputView.kt +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimInputView.kt @@ -20,7 +20,9 @@ import android.content.Context import android.util.AttributeSet import android.widget.ImageView import androidx.core.graphics.drawable.DrawableCompat +import com.android.settingslib.Utils import com.android.systemui.R +import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.EMERGENCY_BUTTON abstract class KeyguardSimInputView(context: Context, attrs: AttributeSet) : KeyguardPinBasedInputView(context, attrs) { @@ -42,10 +44,7 @@ abstract class KeyguardSimInputView(context: Context, attrs: AttributeSet) : override fun reloadColors() { super.reloadColors() - val customAttrs = intArrayOf(android.R.attr.textColorSecondary) - val a = context.obtainStyledAttributes(customAttrs) - val imageColor = a.getColor(0, 0) - a.recycle() + val imageColor = Utils.getColorAttrDefaultColor(context, EMERGENCY_BUTTON) simImageView?.let { val wrappedDrawable = DrawableCompat.wrap(it.drawable) DrawableCompat.setTint(wrappedDrawable, imageColor) diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java index ad669099284f..c6c7113d7f9a 100644 --- a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java +++ b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java @@ -15,12 +15,19 @@ */ package com.android.keyguard; +import static com.android.settingslib.Utils.getColorAttrDefaultColor; +import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_BACKGROUND; +import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_BACKGROUND_PRESSED; +import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_BUTTON; +import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_KEY; +import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_PRESSED; import static com.android.systemui.util.ColorUtilKt.getPrivateAttrColorIfUnset; import android.animation.AnimatorSet; import android.animation.ArgbEvaluator; import android.animation.ValueAnimator; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; @@ -112,20 +119,18 @@ class NumPadAnimator { int[] customAttrs = {android.R.attr.colorControlNormal}; ContextThemeWrapper ctw = new ContextThemeWrapper(context, mStyle); - TypedArray a = ctw.obtainStyledAttributes(customAttrs); + @SuppressLint("ResourceType") TypedArray a = ctw.obtainStyledAttributes(customAttrs); mNormalBackgroundColor = getPrivateAttrColorIfUnset(ctw, a, 0, 0, - com.android.internal.R.attr.colorSurface); + NUM_PAD_BACKGROUND); a.recycle(); - mBackground.setColor(mNormalBackgroundColor); - mPressedBackgroundColor = context.getColor(android.R.color.system_accent1_200); + mPressedBackgroundColor = getColorAttrDefaultColor(context, NUM_PAD_BACKGROUND_PRESSED); + mTextColorPressed = getColorAttrDefaultColor(context, NUM_PAD_PRESSED); + + mBackground.setColor(mNormalBackgroundColor); mTextColorPrimary = isNumPadKey - ? com.android.settingslib.Utils - .getColorAttrDefaultColor(context, android.R.attr.textColorPrimary) - : com.android.settingslib.Utils - .getColorAttrDefaultColor(context, android.R.attr.textColorPrimaryInverse); - mTextColorPressed = com.android.settingslib.Utils - .getColorAttrDefaultColor(context, com.android.internal.R.attr.textColorOnAccent); + ? getColorAttrDefaultColor(context, NUM_PAD_KEY) + : getColorAttrDefaultColor(context, NUM_PAD_BUTTON); createAnimators(); } diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java index 11c329e9811d..6ae80a62891b 100644 --- a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java +++ b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java @@ -15,10 +15,12 @@ */ package com.android.keyguard; +import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_BUTTON; +import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_KEY; + import android.content.Context; import android.content.res.ColorStateList; import android.content.res.Configuration; -import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.VectorDrawable; @@ -27,6 +29,7 @@ import android.view.MotionEvent; import androidx.annotation.Nullable; +import com.android.settingslib.Utils; import com.android.systemui.R; /** @@ -95,12 +98,8 @@ public class NumPadButton extends AlphaOptimizedImageButton implements NumPadAni public void reloadColors() { if (mAnimator != null) mAnimator.reloadColors(getContext()); - int textColorResId = mIsTransparentMode ? android.R.attr.textColorPrimary - : android.R.attr.textColorPrimaryInverse; - int[] customAttrs = {textColorResId}; - TypedArray a = getContext().obtainStyledAttributes(customAttrs); - int imageColor = a.getColor(0, 0); - a.recycle(); + int textColorResId = mIsTransparentMode ? NUM_PAD_KEY : NUM_PAD_BUTTON; + int imageColor = Utils.getColorAttrDefaultColor(getContext(), textColorResId); ((VectorDrawable) getDrawable()).setTintList(ColorStateList.valueOf(imageColor)); } @@ -119,7 +118,7 @@ public class NumPadButton extends AlphaOptimizedImageButton implements NumPadAni public void setTransparentMode(boolean isTransparentMode) { mIsTransparentMode = isTransparentMode; if (isTransparentMode) { - setBackgroundColor(android.R.color.transparent); + setBackgroundColor(getResources().getColor(android.R.color.transparent)); } else { setBackground(getContext().getDrawable(R.drawable.num_pad_key_background)); } diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java index 7c7680afe368..e22fc300ede5 100644 --- a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java +++ b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java @@ -15,6 +15,8 @@ */ package com.android.keyguard; +import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_KEY; + import android.content.Context; import android.content.res.Configuration; import android.content.res.TypedArray; @@ -150,7 +152,7 @@ public class NumPadKey extends ViewGroup implements NumPadAnimationListener { * Reload colors from resources. **/ public void reloadColors() { - int textColor = Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary) + int textColor = Utils.getColorAttr(getContext(), NUM_PAD_KEY) .getDefaultColor(); int klondikeColor = Utils.getColorAttr(getContext(), android.R.attr.textColorSecondary) .getDefaultColor(); diff --git a/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java b/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java index fc5c254fdf29..32f06dcdbf20 100644 --- a/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java +++ b/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java @@ -16,6 +16,8 @@ package com.android.keyguard; +import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.PIN_SHAPES; + import android.content.Context; import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.Drawable; @@ -37,7 +39,7 @@ public class PinShapeHintingView extends LinearLayout implements PinShapeInput { private int mPinLength; private int mDotDiameter; - private int mColor = Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary) + private int mColor = Utils.getColorAttr(getContext(), PIN_SHAPES) .getDefaultColor(); private int mPosition = 0; private static final int DEFAULT_PIN_LENGTH = 6; diff --git a/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java b/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java index 14810d9baf02..4aeab970e2f7 100644 --- a/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java +++ b/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java @@ -16,6 +16,8 @@ package com.android.keyguard; +import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.PIN_SHAPES; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; @@ -45,8 +47,7 @@ import com.android.systemui.animation.Interpolators; */ public class PinShapeNonHintingView extends LinearLayout implements PinShapeInput { - private int mColor = Utils.getColorAttr(getContext(), - android.R.attr.textColorPrimary).getDefaultColor(); + private int mColor = Utils.getColorAttr(getContext(), PIN_SHAPES).getDefaultColor(); private int mPosition = 0; private final PinShapeAdapter mPinShapeAdapter; private ValueAnimator mValueAnimator = ValueAnimator.ofFloat(1f, 0f); diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt index 9a231814a813..025d7e40201e 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt @@ -41,6 +41,10 @@ class PanelTaskViewController( private val hide: () -> Unit = {} ) { + init { + taskView.alpha = 0f + } + private var detailTaskId = INVALID_TASK_ID private val fillInIntent = @@ -96,6 +100,7 @@ class PanelTaskViewController( override fun onTaskCreated(taskId: Int, name: ComponentName?) { detailTaskId = taskId + taskView.alpha = 1f } override fun onReleased() { diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamLogger.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamLogger.kt new file mode 100644 index 000000000000..eb7929095a4b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamLogger.kt @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.dreams + +import com.android.systemui.log.dagger.DreamLog +import com.android.systemui.plugins.log.LogBuffer +import com.android.systemui.plugins.log.LogLevel +import javax.inject.Inject + +/** Logs dream-related stuff to a {@link LogBuffer}. */ +class DreamLogger @Inject constructor(@DreamLog private val buffer: LogBuffer) { + /** Logs a debug message to the buffer. */ + fun d(tag: String, message: String) { + buffer.log(tag, LogLevel.DEBUG, { str1 = message }, { message }) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt index 5b56c04ae8aa..df46e07e0911 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt @@ -21,6 +21,7 @@ import android.animation.AnimatorSet import android.animation.ValueAnimator import android.view.View import android.view.animation.Interpolator +import androidx.core.animation.doOnCancel import androidx.core.animation.doOnEnd import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle @@ -65,7 +66,11 @@ constructor( private val mDreamInTranslationYDistance: Int, @Named(DreamOverlayModule.DREAM_IN_TRANSLATION_Y_DURATION) private val mDreamInTranslationYDurationMs: Long, + private val mLogger: DreamLogger, ) { + companion object { + private const val TAG = "DreamOverlayAnimationsController" + } private var mAnimator: Animator? = null private lateinit var view: View @@ -169,8 +174,11 @@ constructor( doOnEnd { mAnimator = null mOverlayStateController.setEntryAnimationsFinished(true) + mLogger.d(TAG, "Dream overlay entry animations finished.") } + doOnCancel { mLogger.d(TAG, "Dream overlay entry animations canceled.") } start() + mLogger.d(TAG, "Dream overlay entry animations started.") } } @@ -232,8 +240,11 @@ constructor( doOnEnd { mAnimator = null mOverlayStateController.setExitAnimationsRunning(false) + mLogger.d(TAG, "Dream overlay exit animations finished.") } + doOnCancel { mLogger.d(TAG, "Dream overlay exit animations canceled.") } start() + mLogger.d(TAG, "Dream overlay exit animations started.") } mOverlayStateController.setExitAnimationsRunning(true) return mAnimator as AnimatorSet diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index b29066f8e927..942730344f20 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -684,5 +684,6 @@ object Flags { // TODO(b/278761837): Tracking Bug @JvmField - val USE_NEW_ACTIVITY_STARTER = unreleasedFlag(2801, name = "use_new_activity_starter") + val USE_NEW_ACTIVITY_STARTER = unreleasedFlag(2801, name = "use_new_activity_starter", + teamfood = true) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java index 107e685c4482..8b6bd2486117 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java @@ -243,7 +243,7 @@ public class KeyguardService extends Service { Slog.e(TAG, "Called mergeAnimation, but finish callback is missing"); return; } - runner.onAnimationCancelled(false /* isKeyguardOccluded */); + runner.onAnimationCancelled(); currentFinishCB.onTransitionFinished(null /* wct */, null /* t */); } catch (RemoteException e) { // nothing, we'll just let it finish on its own I guess. @@ -418,7 +418,7 @@ public class KeyguardService extends Service { } @Override // Binder interface - public void onAnimationCancelled(boolean isKeyguardOccluded) { + public void onAnimationCancelled() { mKeyguardViewMediator.cancelKeyguardExitAnimation(); } }; diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 93ddfba5b6fc..1a126d72f9e9 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -959,20 +959,15 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, @Nullable private ValueAnimator mOccludeByDreamAnimator; @Override - public void onAnimationCancelled(boolean isKeyguardOccluded) { + public void onAnimationCancelled() { mContext.getMainExecutor().execute(() -> { if (mOccludeByDreamAnimator != null) { mOccludeByDreamAnimator.cancel(); } }); - // The value of isKeyguardOccluded here may come from mergeAnimation, which - // isn't reliable. In all cases, after running or cancelling this animation, - // keyguard should be occluded. + + Log.d(TAG, "OccludeByDreamAnimator#onAnimationCancelled. Set occluded = true"); setOccluded(true /* isOccluded */, false /* animate */); - if (DEBUG) { - Log.d(TAG, "Occlude by Dream animation cancelled. Occluded state is now: " - + mOccluded); - } } @Override @@ -984,6 +979,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, // Usually we rely on animation completion to synchronize occluded status, // but there was no animation to play, so just update it now. setOccluded(true /* isOccluded */, false /* animate */); + finishedCallback.onAnimationFinished(); } } @@ -991,11 +987,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException { if (apps == null || apps.length == 0 || apps[0] == null) { - if (DEBUG) { - Log.d(TAG, "No apps provided to the OccludeByDream runner; " - + "skipping occluding animation."); - } - finishedCallback.onAnimationFinished(); + Log.d(TAG, "No apps provided to the OccludeByDream runner; " + + "skipping occluding animation."); return false; } @@ -1005,7 +998,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, if (!isDream) { Log.w(TAG, "The occluding app isn't Dream; " + "finishing up. Please check that the config is correct."); - finishedCallback.onAnimationFinished(); return false; } @@ -1071,17 +1063,14 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, private final Matrix mUnoccludeMatrix = new Matrix(); @Override - public void onAnimationCancelled(boolean isKeyguardOccluded) { + public void onAnimationCancelled() { mContext.getMainExecutor().execute(() -> { if (mUnoccludeAnimator != null) { mUnoccludeAnimator.cancel(); } }); - setOccluded(isKeyguardOccluded /* isOccluded */, false /* animate */); - Log.d(TAG, "Unocclude animation cancelled. Occluded state is now: " - + mOccluded); - + Log.d(TAG, "Unocclude animation cancelled."); mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_OCCLUSION); } @@ -3404,9 +3393,9 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, } @Override - public void onAnimationCancelled(boolean isKeyguardOccluded) throws RemoteException { + public void onAnimationCancelled() throws RemoteException { if (mRunner != null) { - mRunner.onAnimationCancelled(isKeyguardOccluded); + mRunner.onAnimationCancelled(); } } @@ -3452,13 +3441,9 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, } @Override - public void onAnimationCancelled(boolean isKeyguardOccluded) throws RemoteException { - super.onAnimationCancelled(isKeyguardOccluded); - - Log.d(TAG, "Occlude animation cancelled by WM. " - + "Setting occluded state to: " + isKeyguardOccluded); - setOccluded(isKeyguardOccluded /* occluded */, false /* animate */); - + public void onAnimationCancelled() throws RemoteException { + super.onAnimationCancelled(); + Log.d(TAG, "Occlude animation cancelled by WM."); mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_OCCLUSION); } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt index 1fbfff95ab7e..c0d5abc04e5d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt @@ -48,6 +48,7 @@ constructor( listenForOccludedToDreaming() listenForOccludedToAodOrDozing() listenForOccludedToGone() + listenForOccludedToAlternateBouncer() } private fun listenForOccludedToDreaming() { @@ -167,6 +168,28 @@ constructor( } } + private fun listenForOccludedToAlternateBouncer() { + scope.launch { + keyguardInteractor.alternateBouncerShowing + .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair) + .collect { (isAlternateBouncerShowing, lastStartedTransitionStep) -> + if ( + isAlternateBouncerShowing && + lastStartedTransitionStep.to == KeyguardState.OCCLUDED + ) { + keyguardTransitionRepository.startTransition( + TransitionInfo( + ownerName = name, + from = KeyguardState.OCCLUDED, + to = KeyguardState.ALTERNATE_BOUNCER, + animator = getAnimator(), + ) + ) + } + } + } + } + private fun getAnimator(duration: Duration = DEFAULT_DURATION): ValueAnimator { return ValueAnimator().apply { setInterpolator(Interpolators.LINEAR) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt index 94961cbf4240..a681c43be19f 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt @@ -48,10 +48,51 @@ constructor( override fun start() { listenForPrimaryBouncerToGone() - listenForPrimaryBouncerToLockscreenAodOrDozing() + listenForPrimaryBouncerToAodOrDozing() + listenForPrimaryBouncerToLockscreenOrOccluded() } - private fun listenForPrimaryBouncerToLockscreenAodOrDozing() { + private fun listenForPrimaryBouncerToLockscreenOrOccluded() { + scope.launch { + keyguardInteractor.primaryBouncerShowing + .sample( + combine( + keyguardInteractor.wakefulnessModel, + keyguardTransitionInteractor.startedKeyguardTransitionStep, + keyguardInteractor.isKeyguardOccluded, + ::toTriple + ), + ::toQuad + ) + .collect { (isBouncerShowing, wakefulnessState, lastStartedTransitionStep, occluded) + -> + if ( + !isBouncerShowing && + lastStartedTransitionStep.to == KeyguardState.PRIMARY_BOUNCER && + (wakefulnessState.state == WakefulnessState.AWAKE || + wakefulnessState.state == WakefulnessState.STARTING_TO_WAKE) + ) { + val to = + if (occluded) { + KeyguardState.OCCLUDED + } else { + KeyguardState.LOCKSCREEN + } + + keyguardTransitionRepository.startTransition( + TransitionInfo( + ownerName = name, + from = KeyguardState.PRIMARY_BOUNCER, + to = to, + animator = getAnimator(), + ) + ) + } + } + } + } + + private fun listenForPrimaryBouncerToAodOrDozing() { scope.launch { keyguardInteractor.primaryBouncerShowing .sample( @@ -68,21 +109,17 @@ constructor( -> if ( !isBouncerShowing && - lastStartedTransitionStep.to == KeyguardState.PRIMARY_BOUNCER + lastStartedTransitionStep.to == KeyguardState.PRIMARY_BOUNCER && + (wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP || + wakefulnessState.state == WakefulnessState.ASLEEP) ) { val to = - if ( - wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP || - wakefulnessState.state == WakefulnessState.ASLEEP - ) { - if (isAodAvailable) { - KeyguardState.AOD - } else { - KeyguardState.DOZING - } + if (isAodAvailable) { + KeyguardState.AOD } else { - KeyguardState.LOCKSCREEN + KeyguardState.DOZING } + keyguardTransitionRepository.startTransition( TransitionInfo( ownerName = name, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/constants/KeyguardBouncerConstants.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/constants/KeyguardBouncerConstants.kt index 3b3ec39d0209..c45faf0ba961 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/constants/KeyguardBouncerConstants.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/constants/KeyguardBouncerConstants.kt @@ -32,4 +32,15 @@ object KeyguardBouncerConstants { * PIN hinting is enabled */ const val DEFAULT_PIN_LENGTH = 6 + + object ColorId { + const val TITLE = com.android.internal.R.attr.materialColorOnSurface + const val PIN_SHAPES = com.android.internal.R.attr.materialColorOnSurfaceVariant + const val NUM_PAD_BACKGROUND = com.android.internal.R.attr.materialColorSurfaceContainerHigh + const val NUM_PAD_BACKGROUND_PRESSED = com.android.internal.R.attr.materialColorPrimaryFixed + const val NUM_PAD_PRESSED = com.android.internal.R.attr.materialColorOnPrimaryFixed + const val NUM_PAD_KEY = com.android.internal.R.attr.materialColorOnSurface + const val NUM_PAD_BUTTON = com.android.internal.R.attr.materialColorOnSecondaryFixed + const val EMERGENCY_BUTTON = com.android.internal.R.attr.materialColorTertiaryFixed + } } diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/DreamLog.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/DreamLog.kt new file mode 100644 index 000000000000..cb9913abe99b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/DreamLog.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.log.dagger + +import javax.inject.Qualifier + +/** A [com.android.systemui.log.LogBuffer] for dream-related logging. */ +@Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class DreamLog diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java index 077ee027d764..658f6a087854 100644 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java @@ -440,4 +440,14 @@ public class LogModule { public static LogBuffer provideKeyguardLogBuffer(LogBufferFactory factory) { return factory.create("KeyguardLog", 250); } + + /** + * Provides a {@link LogBuffer} for dream-related logs. + */ + @Provides + @SysUISingleton + @DreamLog + public static LogBuffer provideDreamLogBuffer(LogBufferFactory factory) { + return factory.create("DreamLog", 250); + } } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt index 0aa434976ce7..1e9a466ccdce 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt @@ -67,6 +67,7 @@ import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.time.SystemClock import com.android.systemui.util.traceSection import java.io.PrintWriter +import java.util.Locale import java.util.TreeMap import javax.inject.Inject import javax.inject.Provider @@ -166,6 +167,8 @@ constructor( } } + private var carouselLocale: Locale? = null + /** Whether the media card currently has the "expanded" layout */ @VisibleForTesting var currentlyExpanded = true @@ -218,6 +221,15 @@ constructor( updatePlayers(recreateMedia = false) inflateSettingsButton() } + + override fun onLocaleListChanged() { + // Update players only if system primary language changes. + if (carouselLocale != context.resources.configuration.locales.get(0)) { + carouselLocale = context.resources.configuration.locales.get(0) + updatePlayers(recreateMedia = true) + inflateSettingsButton() + } + } } private val keyguardUpdateMonitorCallback = @@ -262,6 +274,7 @@ constructor( this::logSmartspaceImpression, logger ) + carouselLocale = context.resources.configuration.locales.get(0) isRtl = context.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL inflateSettingsButton() mediaContent = mediaCarousel.requireViewById(R.id.media_carousel) diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java index f16f0dcc5dba..ffe5489d656f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java @@ -458,13 +458,28 @@ public class InternetTile extends QSTileImpl<SignalState> { getTileSpec(), mLastTileState, arg == null ? "null" : arg.toString()); if (arg instanceof CellularCallbackInfo) { mLastTileState = LAST_STATE_CELLULAR; - handleUpdateCellularState(state, arg); + CellularCallbackInfo cb = (CellularCallbackInfo) arg; + CellularCallbackInfo cellularInfo = new CellularCallbackInfo(); + synchronized (cb) { + cb.copyTo(cellularInfo); + } + handleUpdateCellularState(state, cellularInfo); } else if (arg instanceof WifiCallbackInfo) { mLastTileState = LAST_STATE_WIFI; - handleUpdateWifiState(state, arg); + WifiCallbackInfo cb = (WifiCallbackInfo) arg; + WifiCallbackInfo wifiInfo = new WifiCallbackInfo(); + synchronized (cb) { + cb.copyTo(wifiInfo); + } + handleUpdateWifiState(state, wifiInfo); } else if (arg instanceof EthernetCallbackInfo) { mLastTileState = LAST_STATE_ETHERNET; - handleUpdateEthernetState(state, arg); + EthernetCallbackInfo cb = (EthernetCallbackInfo) arg; + EthernetCallbackInfo ethernetInfo = new EthernetCallbackInfo(); + synchronized (cb) { + cb.copyTo(ethernetInfo); + } + handleUpdateEthernetState(state, ethernetInfo); } else { // handleUpdateState will be triggered when user expands the QuickSetting panel with // arg = null, in this case the last updated CellularCallbackInfo or WifiCallbackInfo @@ -476,11 +491,11 @@ public class InternetTile extends QSTileImpl<SignalState> { } handleUpdateCellularState(state, cellularInfo); } else if (mLastTileState == LAST_STATE_WIFI) { - WifiCallbackInfo mifiInfo = new WifiCallbackInfo(); + WifiCallbackInfo wifiInfo = new WifiCallbackInfo(); synchronized (mSignalCallback.mWifiInfo) { - mSignalCallback.mWifiInfo.copyTo(mifiInfo); + mSignalCallback.mWifiInfo.copyTo(wifiInfo); } - handleUpdateWifiState(state, mifiInfo); + handleUpdateWifiState(state, wifiInfo); } else if (mLastTileState == LAST_STATE_ETHERNET) { EthernetCallbackInfo ethernetInfo = new EthernetCallbackInfo(); synchronized (mSignalCallback.mEthernetInfo) { @@ -667,11 +682,16 @@ public class InternetTile extends QSTileImpl<SignalState> { } @Override + @NonNull public Drawable getDrawable(Context context) { SignalDrawable d = new SignalDrawable(context); d.setLevel(getState()); return d; } + @Override + public String toString() { + return String.format("SignalIcon[mState=0x%08x]", mState); + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt index aa8e2c039684..187019a4851d 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt @@ -154,5 +154,5 @@ private val SCREENSHOT_REMOTE_RUNNER: IRemoteAnimationRunner.Stub = } } - override fun onAnimationCancelled(isKeyguardOccluded: Boolean) {} + override fun onAnimationCancelled() {} } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java index c9d1da38b196..77a65b22a7f4 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java @@ -150,7 +150,7 @@ public class ScreenshotController { } @Override - public void onAnimationCancelled(boolean isKeyguardOccluded) { + public void onAnimationCancelled() { } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java index a37b2a9e530a..58d705417632 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar; +import android.annotation.Nullable; import android.app.Notification; import android.app.RemoteInput; import android.content.Context; @@ -55,6 +56,13 @@ public class RemoteInputController { private final RemoteInputControllerLogger mLogger; + /** + * RemoteInput Active's last emitted value. It's added for debugging purpose to directly see + * its last emitted value. As RemoteInputController holds weak reference, isRemoteInputActive + * in dump may not reflect the last emitted value of Active. + */ + @Nullable private Boolean mLastAppliedRemoteInputActive = null; + public RemoteInputController(Delegate delegate, RemoteInputUriController remoteInputUriController, RemoteInputControllerLogger logger) { @@ -217,6 +225,7 @@ public class RemoteInputController { for (int i = 0; i < N; i++) { mCallbacks.get(i).onRemoteInputActive(remoteInputActive); } + mLastAppliedRemoteInputActive = remoteInputActive; } /** @@ -323,6 +332,8 @@ public class RemoteInputController { /** dump debug info; called by {@link NotificationRemoteInputManager} */ public void dump(@NonNull IndentingPrintWriter pw) { + pw.print("mLastAppliedRemoteInputActive: "); + pw.println((Object) mLastAppliedRemoteInputActive); pw.print("isRemoteInputActive: "); pw.println(isRemoteInputActive()); // Note that this prunes the mOpen list, printed later. pw.println("mOpen: " + mOpen.size()); diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt index 0ec1a214660c..c2922c4d6f34 100644 --- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt @@ -26,6 +26,7 @@ import android.content.IntentFilter import android.content.pm.UserInfo import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable +import android.graphics.drawable.Icon import android.os.RemoteException import android.os.UserHandle import android.os.UserManager @@ -762,8 +763,18 @@ constructor( } // TODO(b/246631653): cache the bitmaps to avoid the background work to fetch them. - // TODO(b/246631653): downscale the bitmaps to R.dimen.max_avatar_size if requested. - val userIcon = withContext(backgroundDispatcher) { manager.getUserIcon(userId) } + val userIcon = withContext(backgroundDispatcher) { + manager.getUserIcon(userId) + ?.let { bitmap -> + val iconSize = + applicationContext + .resources + .getDimensionPixelSize(R.dimen.bouncer_user_switcher_icon_size) + Icon.scaleDownIfNecessary(bitmap, iconSize, iconSize) + } + } + + if (userIcon != null) { return BitmapDrawable(userIcon) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt index 578e1d4d02ce..cc004363a049 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt @@ -159,22 +159,11 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() { @Test fun doesNotStartIfAnimationIsCancelled() { val runner = activityLaunchAnimator.createRunner(controller) - runner.onAnimationCancelled(false /* isKeyguardOccluded */) + runner.onAnimationCancelled() runner.onAnimationStart(0, emptyArray(), emptyArray(), emptyArray(), iCallback) waitForIdleSync() - verify(controller).onLaunchAnimationCancelled(false /* newKeyguardOccludedState */) - verify(controller, never()).onLaunchAnimationStart(anyBoolean()) - } - - @Test - fun passesOccludedStateToLaunchAnimationCancelled_ifTrue() { - val runner = activityLaunchAnimator.createRunner(controller) - runner.onAnimationCancelled(true /* isKeyguardOccluded */) - runner.onAnimationStart(0, emptyArray(), emptyArray(), emptyArray(), iCallback) - - waitForIdleSync() - verify(controller).onLaunchAnimationCancelled(true /* newKeyguardOccludedState */) + verify(controller).onLaunchAnimationCancelled() verify(controller, never()).onLaunchAnimationStart(anyBoolean()) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/PanelTaskViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/PanelTaskViewControllerTest.kt index f7c8ccaf731a..7840525b14aa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/PanelTaskViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/PanelTaskViewControllerTest.kt @@ -19,6 +19,7 @@ package com.android.systemui.controls.ui import android.app.ActivityOptions import android.app.PendingIntent +import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK @@ -90,6 +91,11 @@ class PanelTaskViewControllerTest : SysuiTestCase() { } @Test + fun testTaskViewStartsWithAlpha0() { + verify(taskView).alpha = 0f + } + + @Test fun testLaunchTaskViewAttachedListener() { underTest.launchTaskView() verify(taskView).setListener(eq(uiExecutor), any()) @@ -120,6 +126,16 @@ class PanelTaskViewControllerTest : SysuiTestCase() { } @Test + fun testOnTaskCreated_taskViewAlpha1() { + underTest.launchTaskView() + verify(taskView).setListener(any(), capture(listenerCaptor)) + + listenerCaptor.value.onTaskCreated(1, ComponentName("Test", "TEST")) + + verify(taskView).alpha = 1f + } + + @Test fun testHideRunnableCalledWhenBackOnRoot() { underTest.launchTaskView() verify(taskView).setListener(any(), capture(listenerCaptor)) diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt index b7c62463899f..039682c88498 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt @@ -24,6 +24,7 @@ import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Mock import org.mockito.Mockito.anyLong +import org.mockito.Mockito.atLeastOnce import org.mockito.Mockito.eq import org.mockito.Mockito.never import org.mockito.Mockito.times @@ -49,6 +50,7 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() { @Mock private lateinit var stateController: DreamOverlayStateController @Mock private lateinit var configController: ConfigurationController @Mock private lateinit var transitionViewModel: DreamingToLockscreenTransitionViewModel + @Mock private lateinit var logger: DreamLogger private lateinit var controller: DreamOverlayAnimationsController @Before @@ -67,6 +69,7 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() { DREAM_IN_COMPLICATIONS_ANIMATION_DURATION, DREAM_IN_TRANSLATION_Y_DISTANCE, DREAM_IN_TRANSLATION_Y_DURATION, + logger ) val mockView: View = mock() @@ -82,9 +85,9 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() { verify(stateController).setExitAnimationsRunning(true) val captor = argumentCaptor<Animator.AnimatorListener>() - verify(mockAnimator).addListener(captor.capture()) + verify(mockAnimator, atLeastOnce()).addListener(captor.capture()) - captor.value.onAnimationEnd(mockAnimator) + captor.allValues.forEach { it.onAnimationEnd(mockAnimator) } verify(stateController).setExitAnimationsRunning(false) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt index b46d996ddfcd..f8cb40885d21 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt @@ -19,7 +19,6 @@ package com.android.systemui.keyguard.data.quickaffordance import androidx.test.filters.SmallTest import com.android.systemui.R -import com.android.systemui.RoboPilotTest import com.android.systemui.SysuiTestCase import com.android.systemui.controls.ControlsServiceInfo import com.android.systemui.controls.controller.ControlsController @@ -46,7 +45,6 @@ import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest -@RoboPilotTest @RunWith(Parameterized::class) class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt index f4d28431a2e9..d0bfaa9bedc9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt @@ -23,7 +23,6 @@ import android.util.Log.TerribleFailureHandler import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.FlakyTest import androidx.test.filters.SmallTest -import com.android.systemui.RoboPilotTest import com.android.systemui.SysuiTestCase import com.android.systemui.animation.Interpolators import com.android.systemui.keyguard.shared.model.KeyguardState @@ -48,7 +47,6 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RoboPilotTest @RunWith(AndroidJUnit4::class) @FlakyTest(bugId = 270760395) class KeyguardTransitionRepositoryTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt index fe65236c699f..344df0acc409 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt @@ -180,7 +180,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun DREAMINGtoLOCKSCREEN() = + fun dreamingToLockscreen() = testScope.runTest { // GIVEN a device is dreaming keyguardRepository.setDreamingWithOverlay(true) @@ -215,7 +215,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun LOCKSCREENtoPRIMARY_BOUNCERviaBouncerShowingCall() = + fun lockscreenToPrimaryBouncerViaBouncerShowingCall() = testScope.runTest { // GIVEN a device that has at least woken up keyguardRepository.setWakefulnessModel(startingToWake()) @@ -242,7 +242,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun OCCLUDEDtoDOZING() = + fun occludedToDozing() = testScope.runTest { // GIVEN a device with AOD not available keyguardRepository.setAodAvailable(false) @@ -269,7 +269,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun OCCLUDEDtoAOD() = + fun occludedToAod() = testScope.runTest { // GIVEN a device with AOD available keyguardRepository.setAodAvailable(true) @@ -296,7 +296,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun LOCKSCREENtoDREAMING() = + fun lockscreenToDreaming() = testScope.runTest { // GIVEN a device that is not dreaming or dozing keyguardRepository.setDreamingWithOverlay(false) @@ -327,7 +327,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun LOCKSCREENtoDOZING() = + fun lockscreenToDozing() = testScope.runTest { // GIVEN a device with AOD not available keyguardRepository.setAodAvailable(false) @@ -354,7 +354,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun LOCKSCREENtoAOD() = + fun lockscreenToAod() = testScope.runTest { // GIVEN a device with AOD available keyguardRepository.setAodAvailable(true) @@ -381,7 +381,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun DOZINGtoLOCKSCREEN() = + fun dozingToLockscreen() = testScope.runTest { // GIVEN a prior transition has run to DOZING runTransition(KeyguardState.LOCKSCREEN, KeyguardState.DOZING) @@ -404,7 +404,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun DOZINGtoLOCKSCREENcannotBeInterrupedByDREAMING() = + fun dozingToLockscreenCannotBeInterruptedByDreaming() = testScope.runTest { // GIVEN a prior transition has started to LOCKSCREEN transitionRepository.sendTransitionStep( @@ -430,7 +430,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun DOZINGtoGONE() = + fun dozingToGone() = testScope.runTest { // GIVEN a prior transition has run to DOZING runTransition(KeyguardState.LOCKSCREEN, KeyguardState.DOZING) @@ -453,7 +453,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun GONEtoDOZING() = + fun goneToDozing() = testScope.runTest { // GIVEN a device with AOD not available keyguardRepository.setAodAvailable(false) @@ -480,7 +480,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun GONEtoAOD() = + fun goneToAod() = testScope.runTest { // GIVEN a device with AOD available keyguardRepository.setAodAvailable(true) @@ -507,7 +507,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun GONEtoLOCKSREEN() = + fun goneToLockscreen() = testScope.runTest { // GIVEN a prior transition has run to GONE runTransition(KeyguardState.LOCKSCREEN, KeyguardState.GONE) @@ -530,7 +530,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun GONEtoDREAMING() = + fun goneToDreaming() = testScope.runTest { // GIVEN a device that is not dreaming or dozing keyguardRepository.setDreamingWithOverlay(false) @@ -561,7 +561,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun ALTERNATE_BOUNCERtoPRIMARY_BOUNCER() = + fun alternateBouncerToPrimaryBouncer() = testScope.runTest { // GIVEN a prior transition has run to ALTERNATE_BOUNCER runTransition(KeyguardState.LOCKSCREEN, KeyguardState.ALTERNATE_BOUNCER) @@ -584,7 +584,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun ALTERNATE_BOUNCERtoAOD() = + fun alternateBoucnerToAod() = testScope.runTest { // GIVEN a prior transition has run to ALTERNATE_BOUNCER bouncerRepository.setAlternateVisible(true) @@ -613,7 +613,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun ALTERNATE_BOUNCERtoDOZING() = + fun alternateBouncerToDozing() = testScope.runTest { // GIVEN a prior transition has run to ALTERNATE_BOUNCER bouncerRepository.setAlternateVisible(true) @@ -643,7 +643,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun ALTERNATE_BOUNCERtoLOCKSCREEN() = + fun alternateBouncerToLockscreen() = testScope.runTest { // GIVEN a prior transition has run to ALTERNATE_BOUNCER bouncerRepository.setAlternateVisible(true) @@ -671,7 +671,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun PRIMARY_BOUNCERtoAOD() = + fun primaryBouncerToAod() = testScope.runTest { // GIVEN a prior transition has run to PRIMARY_BOUNCER bouncerRepository.setPrimaryShow(true) @@ -699,7 +699,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun PRIMARY_BOUNCERtoDOZING() = + fun primaryBouncerToDozing() = testScope.runTest { // GIVEN a prior transition has run to PRIMARY_BOUNCER bouncerRepository.setPrimaryShow(true) @@ -727,7 +727,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun PRIMARY_BOUNCERtoLOCKSCREEN() = + fun primaryBouncerToLockscreen() = testScope.runTest { // GIVEN a prior transition has run to PRIMARY_BOUNCER bouncerRepository.setPrimaryShow(true) @@ -754,7 +754,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun OCCLUDEDtoGONE() = + fun occludedToGone() = testScope.runTest { // GIVEN a device on lockscreen keyguardRepository.setKeyguardShowing(true) @@ -785,7 +785,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun OCCLUDEDtoLOCKSCREEN() = + fun occludedToLockscreen() = testScope.runTest { // GIVEN a device on lockscreen keyguardRepository.setKeyguardShowing(true) @@ -813,6 +813,61 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { coroutineContext.cancelChildren() } + @Test + fun occludedToAlternateBouncer() = + testScope.runTest { + + // GIVEN a prior transition has run to OCCLUDED + runTransition(KeyguardState.LOCKSCREEN, KeyguardState.OCCLUDED) + keyguardRepository.setKeyguardOccluded(true) + runCurrent() + + // WHEN alternate bouncer shows + bouncerRepository.setAlternateVisible(true) + runCurrent() + + val info = + withArgCaptor<TransitionInfo> { + verify(mockTransitionRepository).startTransition(capture(), anyBoolean()) + } + // THEN a transition to AlternateBouncer should occur + assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor") + assertThat(info.from).isEqualTo(KeyguardState.OCCLUDED) + assertThat(info.to).isEqualTo(KeyguardState.ALTERNATE_BOUNCER) + assertThat(info.animator).isNotNull() + + coroutineContext.cancelChildren() + } + + @Test + fun primaryBouncerToOccluded() = + testScope.runTest { + // GIVEN device not sleeping + keyguardRepository.setWakefulnessModel(startingToWake()) + + // GIVEN a prior transition has run to PRIMARY_BOUNCER + runTransition(KeyguardState.LOCKSCREEN, KeyguardState.PRIMARY_BOUNCER) + bouncerRepository.setPrimaryShow(true) + runCurrent() + + // WHEN the keyguard is occluded and primary bouncer stops showing + keyguardRepository.setKeyguardOccluded(true) + bouncerRepository.setPrimaryShow(false) + runCurrent() + + val info = + withArgCaptor<TransitionInfo> { + verify(mockTransitionRepository).startTransition(capture(), anyBoolean()) + } + // THEN a transition to AlternateBouncer should occur + assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor") + assertThat(info.from).isEqualTo(KeyguardState.PRIMARY_BOUNCER) + assertThat(info.to).isEqualTo(KeyguardState.OCCLUDED) + assertThat(info.animator).isNotNull() + + coroutineContext.cancelChildren() + } + private fun startingToWake() = WakefulnessModel( WakefulnessState.STARTING_TO_WAKE, diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt index 1a00ac2722fe..07f7c158fc4d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt @@ -17,7 +17,9 @@ package com.android.systemui.media.controls.ui import android.app.PendingIntent +import android.content.res.ColorStateList import android.content.res.Configuration +import android.os.LocaleList import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.util.MathUtils.abs @@ -26,6 +28,7 @@ import androidx.test.filters.SmallTest import com.android.internal.logging.InstanceId import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback +import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.classifier.FalsingCollector import com.android.systemui.dagger.qualifiers.Main @@ -50,9 +53,11 @@ import com.android.systemui.statusbar.notification.collection.provider.OnReorder import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.concurrency.DelayableExecutor +import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock +import java.util.Locale import javax.inject.Provider import junit.framework.Assert.assertEquals import junit.framework.Assert.assertFalse @@ -68,6 +73,7 @@ import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.floatThat import org.mockito.Mockito.mock +import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.times import org.mockito.Mockito.verify @@ -77,6 +83,8 @@ import org.mockito.MockitoAnnotations private val DATA = MediaTestUtils.emptyMediaData private val SMARTSPACE_KEY = "smartspace" +private const val PAUSED_LOCAL = "paused local" +private const val PLAYING_LOCAL = "playing local" @SmallTest @TestableLooper.RunWithLooper(setAsMainLooper = true) @@ -118,6 +126,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { @Before fun setup() { MockitoAnnotations.initMocks(this) + context.resources.configuration.locales = LocaleList(Locale.US, Locale.UK) transitionRepository = FakeKeyguardTransitionRepository() mediaCarouselController = MediaCarouselController( @@ -157,7 +166,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { // Test values: key, data, last active time val playingLocal = Triple( - "playing local", + PLAYING_LOCAL, DATA.copy( active = true, isPlaying = true, @@ -181,7 +190,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { val pausedLocal = Triple( - "paused local", + PAUSED_LOCAL, DATA.copy( active = true, isPlaying = false, @@ -384,8 +393,8 @@ class MediaCarouselControllerTest : SysuiTestCase() { testPlayerOrdering() // playing paused player listener.value.onMediaDataLoaded( - "paused local", - "paused local", + PAUSED_LOCAL, + PAUSED_LOCAL, DATA.copy( active = true, isPlaying = true, @@ -394,8 +403,8 @@ class MediaCarouselControllerTest : SysuiTestCase() { ) ) listener.value.onMediaDataLoaded( - "playing local", - "playing local", + PLAYING_LOCAL, + PLAYING_LOCAL, DATA.copy( active = true, isPlaying = false, @@ -405,7 +414,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { ) assertEquals( - MediaPlayerData.getMediaPlayerIndex("paused local"), + MediaPlayerData.getMediaPlayerIndex(PAUSED_LOCAL), mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex ) // paused player order should stays the same in visibleMediaPLayer map. @@ -486,7 +495,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { @Test fun testMediaLoaded_ScrollToActivePlayer() { listener.value.onMediaDataLoaded( - "playing local", + PLAYING_LOCAL, null, DATA.copy( active = true, @@ -496,7 +505,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { ) ) listener.value.onMediaDataLoaded( - "paused local", + PAUSED_LOCAL, null, DATA.copy( active = true, @@ -514,8 +523,8 @@ class MediaCarouselControllerTest : SysuiTestCase() { mediaCarouselController.shouldScrollToKey = true // switching between media players. listener.value.onMediaDataLoaded( - "playing local", - "playing local", + PLAYING_LOCAL, + PLAYING_LOCAL, DATA.copy( active = true, isPlaying = false, @@ -524,8 +533,8 @@ class MediaCarouselControllerTest : SysuiTestCase() { ) ) listener.value.onMediaDataLoaded( - "paused local", - "paused local", + PAUSED_LOCAL, + PAUSED_LOCAL, DATA.copy( active = true, isPlaying = true, @@ -535,7 +544,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { ) assertEquals( - MediaPlayerData.getMediaPlayerIndex("paused local"), + MediaPlayerData.getMediaPlayerIndex(PAUSED_LOCAL), mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex ) } @@ -548,7 +557,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { false ) listener.value.onMediaDataLoaded( - "playing local", + PLAYING_LOCAL, null, DATA.copy( active = true, @@ -558,7 +567,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { ) ) - var playerIndex = MediaPlayerData.getMediaPlayerIndex("playing local") + var playerIndex = MediaPlayerData.getMediaPlayerIndex(PLAYING_LOCAL) assertEquals( playerIndex, mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex @@ -569,7 +578,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { // And check that the card stays in its position. mediaCarouselController.shouldScrollToKey = true listener.value.onMediaDataLoaded( - "playing local", + PLAYING_LOCAL, null, DATA.copy( active = true, @@ -579,7 +588,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { packageName = "PACKAGE_NAME" ) ) - playerIndex = MediaPlayerData.getMediaPlayerIndex("playing local") + playerIndex = MediaPlayerData.getMediaPlayerIndex(PLAYING_LOCAL) assertEquals(playerIndex, 0) } @@ -676,36 +685,52 @@ class MediaCarouselControllerTest : SysuiTestCase() { @Test fun testOnConfigChanged_playersAreAddedBack() { - listener.value.onMediaDataLoaded( - "playing local", - null, - DATA.copy( - active = true, - isPlaying = true, - playbackLocation = MediaData.PLAYBACK_LOCAL, - resumption = false - ) - ) - listener.value.onMediaDataLoaded( - "paused local", - null, - DATA.copy( - active = true, - isPlaying = false, - playbackLocation = MediaData.PLAYBACK_LOCAL, - resumption = false - ) - ) + testConfigurationChange { configListener.value.onConfigChanged(Configuration()) } + } - val playersSize = MediaPlayerData.players().size + @Test + fun testOnUiModeChanged_playersAreAddedBack() { + testConfigurationChange(configListener.value::onUiModeChanged) - configListener.value.onConfigChanged(Configuration()) + verify(pageIndicator).tintList = + ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator)) + verify(pageIndicator, times(2)).setNumPages(any()) + } - assertEquals(playersSize, MediaPlayerData.players().size) - assertEquals( - MediaPlayerData.getMediaPlayerIndex("playing local"), - mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex - ) + @Test + fun testOnDensityOrFontScaleChanged_playersAreAddedBack() { + testConfigurationChange(configListener.value::onDensityOrFontScaleChanged) + + verify(pageIndicator).tintList = + ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator)) + // when recreateMedia is set to true, page indicator is updated on removal and addition. + verify(pageIndicator, times(4)).setNumPages(any()) + } + + @Test + fun testOnThemeChanged_playersAreAddedBack() { + testConfigurationChange(configListener.value::onThemeChanged) + + verify(pageIndicator).tintList = + ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator)) + verify(pageIndicator, times(2)).setNumPages(any()) + } + + @Test + fun testOnLocaleListChanged_playersAreAddedBack() { + context.resources.configuration.locales = LocaleList(Locale.US, Locale.UK, Locale.CANADA) + testConfigurationChange(configListener.value::onLocaleListChanged) + + verify(pageIndicator, never()).tintList = + ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator)) + + context.resources.configuration.locales = LocaleList(Locale.UK, Locale.US, Locale.CANADA) + testConfigurationChange(configListener.value::onLocaleListChanged) + + verify(pageIndicator).tintList = + ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator)) + // When recreateMedia is set to true, page indicator is updated on removal and addition. + verify(pageIndicator, times(4)).setNumPages(any()) } @Test @@ -846,4 +871,43 @@ class MediaCarouselControllerTest : SysuiTestCase() { // Then the carousel visibility is updated assertTrue(stateUpdated) } + + /** + * Helper method when a configuration change occurs. + * + * @param function called when a certain configuration change occurs. + */ + private fun testConfigurationChange(function: () -> Unit) { + mediaCarouselController.pageIndicator = pageIndicator + listener.value.onMediaDataLoaded( + PLAYING_LOCAL, + null, + DATA.copy( + active = true, + isPlaying = true, + playbackLocation = MediaData.PLAYBACK_LOCAL, + resumption = false + ) + ) + listener.value.onMediaDataLoaded( + PAUSED_LOCAL, + null, + DATA.copy( + active = true, + isPlaying = false, + playbackLocation = MediaData.PLAYBACK_LOCAL, + resumption = false + ) + ) + + val playersSize = MediaPlayerData.players().size + reset(pageIndicator) + function() + + assertEquals(playersSize, MediaPlayerData.players().size) + assertEquals( + MediaPlayerData.getMediaPlayerIndex(PLAYING_LOCAL), + mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex + ) + } } diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java index 7c32627dd1b1..55e805ab4ad0 100644 --- a/services/core/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -28,6 +28,7 @@ import static android.app.UiModeManager.MODE_NIGHT_YES; import static android.app.UiModeManager.PROJECTION_TYPE_AUTOMOTIVE; import static android.app.UiModeManager.PROJECTION_TYPE_NONE; import static android.os.UserHandle.USER_SYSTEM; +import static android.os.UserHandle.getCallingUserId; import static android.provider.Settings.Secure.CONTRAST_LEVEL; import static android.util.TimeUtils.isTimeBetween; @@ -199,8 +200,8 @@ final class UiModeManagerService extends SystemService { private PowerManagerInternal mLocalPowerManager; @GuardedBy("mLock") - private final RemoteCallbackList<IUiModeManagerCallback> mUiModeManagerCallbacks = - new RemoteCallbackList<IUiModeManagerCallback>(); + private final SparseArray<RemoteCallbackList<IUiModeManagerCallback>> mUiModeManagerCallbacks = + new SparseArray<>(); @GuardedBy("mLock") @Nullable @@ -371,8 +372,9 @@ final class UiModeManagerService extends SystemService { synchronized (mLock) { if (updateContrastLocked()) { float contrast = getContrastLocked(); - mUiModeManagerCallbacks.broadcast(ignoreRemoteException(callback -> - callback.notifyContrastChanged(contrast))); + mUiModeManagerCallbacks.get(mCurrentUser, new RemoteCallbackList<>()) + .broadcast(ignoreRemoteException( + callback -> callback.notifyContrastChanged(contrast))); } } } @@ -664,8 +666,12 @@ final class UiModeManagerService extends SystemService { private final IUiModeManager.Stub mService = new IUiModeManager.Stub() { @Override public void addCallback(IUiModeManagerCallback callback) { + int userId = getCallingUserId(); synchronized (mLock) { - mUiModeManagerCallbacks.register(callback); + if (!mUiModeManagerCallbacks.contains(userId)) { + mUiModeManagerCallbacks.put(userId, new RemoteCallbackList<>()); + } + mUiModeManagerCallbacks.get(userId).register(callback); } } diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 33f05525066e..0d89ba88c1cf 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -167,6 +167,51 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private static final int RINGBUFFER_MAX = 100; + private static final float[] BRIGHTNESS_RANGE_BOUNDARIES = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80, + 90, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1200, + 1400, 1600, 1800, 2000, 2250, 2500, 2750, 3000}; + private static final int[] BRIGHTNESS_RANGE_INDEX = { + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_UNKNOWN, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_0_1, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1_2, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2_3, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_3_4, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_4_5, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_5_6, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_6_7, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_7_8, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_8_9, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_9_10, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_10_20, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_20_30, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_30_40, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_40_50, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_50_60, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_60_70, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_70_80, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_80_90, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_90_100, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_100_200, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_200_300, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_300_400, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_400_500, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_500_600, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_600_700, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_700_800, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_800_900, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_900_1000, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1000_1200, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1200_1400, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1400_1600, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1600_1800, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1800_2000, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2000_2250, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2250_2500, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2500_2750, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2750_3000, + }; + private final String mTag; private final Object mLock = new Object(); @@ -1937,8 +1982,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call ? BrightnessEvent.FLAG_USER_SET : 0)); Slog.i(mTag, newEvent.toString(/* includeTime= */ false)); - if (userSetBrightnessChanged) { - logManualBrightnessEvent(newEvent); + if (userSetBrightnessChanged + || newEvent.getReason().getReason() != BrightnessReason.REASON_TEMPORARY) { + logBrightnessEvent(newEvent, unthrottledBrightnessState); } if (mBrightnessEventRingBuffer != null) { mBrightnessEventRingBuffer.append(newEvent); @@ -3091,7 +3137,63 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } } - private void logManualBrightnessEvent(BrightnessEvent event) { + // Return bucket index of range_[left]_[right] where + // left <= nits < right + private int nitsToRangeIndex(float nits) { + for (int i = 0; i < BRIGHTNESS_RANGE_BOUNDARIES.length; i++) { + if (nits < BRIGHTNESS_RANGE_BOUNDARIES[i]) { + return BRIGHTNESS_RANGE_INDEX[i]; + } + } + return FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_3000_INF; + } + + private int convertBrightnessReasonToStatsEnum(int brightnessReason) { + switch(brightnessReason) { + case BrightnessReason.REASON_UNKNOWN: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_UNKNOWN; + case BrightnessReason.REASON_MANUAL: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_MANUAL; + case BrightnessReason.REASON_DOZE: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_DOZE; + case BrightnessReason.REASON_DOZE_DEFAULT: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_DOZE_DEFAULT; + case BrightnessReason.REASON_AUTOMATIC: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_AUTOMATIC; + case BrightnessReason.REASON_SCREEN_OFF: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_SCREEN_OFF; + case BrightnessReason.REASON_OVERRIDE: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_OVERRIDE; + case BrightnessReason.REASON_TEMPORARY: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_TEMPORARY; + case BrightnessReason.REASON_BOOST: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_BOOST; + case BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_SCREEN_OFF_BRIGHTNESS_SENSOR; + case BrightnessReason.REASON_FOLLOWER: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_FOLLOWER; + } + return FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_UNKNOWN; + } + + private void logBrightnessEvent(BrightnessEvent event, float unmodifiedBrightness) { + int modifier = event.getReason().getModifier(); + int flags = event.getFlags(); + // It's easier to check if the brightness is at maximum level using the brightness + // value untouched by any modifiers + boolean brightnessIsMax = unmodifiedBrightness == event.getHbmMax(); + float brightnessInNits = convertToAdjustedNits(event.getBrightness()); float appliedLowPowerMode = event.isLowPowerModeSet() ? event.getPowerFactor() : -1f; int appliedRbcStrength = event.isRbcEnabled() ? event.getRbcStrength() : -1; float appliedHbmMaxNits = @@ -3105,7 +3207,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call if (mIsDisplayInternal) { FrameworkStatsLog.write(FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED, convertToAdjustedNits(event.getInitialBrightness()), - convertToAdjustedNits(event.getBrightness()), + brightnessInNits, event.getLux(), event.getPhysicalDisplayId(), event.wasShortTermModelActive(), @@ -3114,7 +3216,21 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call appliedHbmMaxNits, appliedThermalCapNits, event.isAutomaticBrightnessEnabled(), - FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__REASON__REASON_MANUAL); + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__REASON__REASON_MANUAL, + convertBrightnessReasonToStatsEnum(event.getReason().getReason()), + nitsToRangeIndex(brightnessInNits), + brightnessIsMax, + event.getHbmMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, + event.getHbmMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, + (modifier & BrightnessReason.MODIFIER_LOW_POWER) > 0, + mBrightnessThrottler.getBrightnessMaxReason(), + (modifier & BrightnessReason.MODIFIER_DIMMED) > 0, + event.isRbcEnabled(), + (flags & BrightnessEvent.FLAG_INVALID_LUX) > 0, + (flags & BrightnessEvent.FLAG_DOZE_SCALE) > 0, + (flags & BrightnessEvent.FLAG_USER_SET) > 0, + (flags & BrightnessEvent.FLAG_IDLE_CURVE) > 0, + (flags & BrightnessEvent.FLAG_LOW_POWER_MODE) > 0); } } diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java index f96b58e9ef2d..9e8c47f64926 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController2.java +++ b/services/core/java/com/android/server/display/DisplayPowerController2.java @@ -157,6 +157,51 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal private static final int RINGBUFFER_MAX = 100; + private static final float[] BRIGHTNESS_RANGE_BOUNDARIES = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80, + 90, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1200, + 1400, 1600, 1800, 2000, 2250, 2500, 2750, 3000}; + private static final int[] BRIGHTNESS_RANGE_INDEX = { + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_UNKNOWN, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_0_1, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1_2, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2_3, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_3_4, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_4_5, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_5_6, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_6_7, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_7_8, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_8_9, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_9_10, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_10_20, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_20_30, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_30_40, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_40_50, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_50_60, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_60_70, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_70_80, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_80_90, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_90_100, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_100_200, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_200_300, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_300_400, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_400_500, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_500_600, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_600_700, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_700_800, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_800_900, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_900_1000, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1000_1200, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1200_1400, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1400_1600, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1600_1800, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1800_2000, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2000_2250, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2250_2500, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2500_2750, + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2750_3000, + }; + private final String mTag; private final Object mLock = new Object(); @@ -1570,8 +1615,9 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal ? BrightnessEvent.FLAG_USER_SET : 0)); Slog.i(mTag, newEvent.toString(/* includeTime= */ false)); - if (userSetBrightnessChanged) { - logManualBrightnessEvent(newEvent); + if (userSetBrightnessChanged + || newEvent.getReason().getReason() != BrightnessReason.REASON_TEMPORARY) { + logBrightnessEvent(newEvent, unthrottledBrightnessState); } if (mBrightnessEventRingBuffer != null) { mBrightnessEventRingBuffer.append(newEvent); @@ -2448,7 +2494,64 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal } } - private void logManualBrightnessEvent(BrightnessEvent event) { + // Return bucket index of range_[left]_[right] where + // left <= nits < right + private int nitsToRangeIndex(float nits) { + for (int i = 0; i < BRIGHTNESS_RANGE_BOUNDARIES.length; i++) { + if (nits < BRIGHTNESS_RANGE_BOUNDARIES[i]) { + return BRIGHTNESS_RANGE_INDEX[i]; + } + } + return FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_3000_INF; + } + + private int convertBrightnessReasonToStatsEnum(int brightnessReason) { + switch(brightnessReason) { + case BrightnessReason.REASON_UNKNOWN: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_UNKNOWN; + case BrightnessReason.REASON_MANUAL: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_MANUAL; + case BrightnessReason.REASON_DOZE: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_DOZE; + case BrightnessReason.REASON_DOZE_DEFAULT: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_DOZE_DEFAULT; + case BrightnessReason.REASON_AUTOMATIC: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_AUTOMATIC; + case BrightnessReason.REASON_SCREEN_OFF: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_SCREEN_OFF; + case BrightnessReason.REASON_OVERRIDE: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_OVERRIDE; + case BrightnessReason.REASON_TEMPORARY: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_TEMPORARY; + case BrightnessReason.REASON_BOOST: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_BOOST; + case BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_SCREEN_OFF_BRIGHTNESS_SENSOR; + case BrightnessReason.REASON_FOLLOWER: + return FrameworkStatsLog + .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_FOLLOWER; + } + return FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_UNKNOWN; + } + + private void logBrightnessEvent(BrightnessEvent event, float unmodifiedBrightness) { + int modifier = event.getReason().getModifier(); + int flags = event.getFlags(); + // It's easier to check if the brightness is at maximum level using the brightness + // value untouched by any modifiers + boolean brightnessIsMax = unmodifiedBrightness == event.getHbmMax(); + float brightnessInNits = + mDisplayBrightnessController.convertToAdjustedNits(event.getBrightness()); float appliedLowPowerMode = event.isLowPowerModeSet() ? event.getPowerFactor() : -1f; int appliedRbcStrength = event.isRbcEnabled() ? event.getRbcStrength() : -1; float appliedHbmMaxNits = @@ -2462,7 +2565,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal FrameworkStatsLog.write(FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED, mDisplayBrightnessController .convertToAdjustedNits(event.getInitialBrightness()), - mDisplayBrightnessController.convertToAdjustedNits(event.getBrightness()), + brightnessInNits, event.getLux(), event.getPhysicalDisplayId(), event.wasShortTermModelActive(), @@ -2471,7 +2574,21 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal appliedHbmMaxNits, appliedThermalCapNits, event.isAutomaticBrightnessEnabled(), - FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__REASON__REASON_MANUAL); + FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__REASON__REASON_MANUAL, + convertBrightnessReasonToStatsEnum(event.getReason().getReason()), + nitsToRangeIndex(brightnessInNits), + brightnessIsMax, + event.getHbmMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, + event.getHbmMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, + (modifier & BrightnessReason.MODIFIER_LOW_POWER) > 0, + mBrightnessThrottler.getBrightnessMaxReason(), + (modifier & BrightnessReason.MODIFIER_DIMMED) > 0, + event.isRbcEnabled(), + (flags & BrightnessEvent.FLAG_INVALID_LUX) > 0, + (flags & BrightnessEvent.FLAG_DOZE_SCALE) > 0, + (flags & BrightnessEvent.FLAG_USER_SET) > 0, + (flags & BrightnessEvent.FLAG_IDLE_CURVE) > 0, + (flags & BrightnessEvent.FLAG_LOW_POWER_MODE) > 0); } } diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java index 7a51126eff2d..377b8cf1230e 100644 --- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java +++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java @@ -395,8 +395,8 @@ public final class MediaProjectionManagerService extends SystemService synchronized (mLock) { final boolean consentGranted = consentResult == RECORD_CONTENT_DISPLAY || consentResult == RECORD_CONTENT_TASK; - if (consentGranted && projection == null || !isCurrentProjection( - projection.asBinder())) { + if (consentGranted && !isCurrentProjection( + projection == null ? null : projection.asBinder())) { Slog.v(TAG, "Reusing token: Ignore consent result of " + consentResult + " for a " + "token that isn't current"); return; diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 8bfa4269af1c..ef38e8962599 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -2190,6 +2190,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } mWmService.mDisplayManagerInternal.performTraversal(transaction); + if (shellTransitions) { + // Before setDisplayProjection is applied by the start transaction of transition, + // set the transform hint to avoid using surface in old rotation. + getPendingTransaction().setFixedTransformHint(mSurfaceControl, rotation); + // The sync transaction should already contains setDisplayProjection, so unset the + // hint to restore the natural state when the transaction is applied. + transaction.unsetFixedTransformHint(mSurfaceControl); + } scheduleAnimation(); mWmService.mRotationWatcherController.dispatchDisplayRotationChange(mDisplayId, rotation); diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java index b879d1a8ec56..eb639b6f2033 100644 --- a/services/core/java/com/android/server/wm/RemoteAnimationController.java +++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java @@ -362,15 +362,8 @@ class RemoteAnimationController implements DeathRecipient { private void invokeAnimationCancelled(String reason) { ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "cancelAnimation(): reason=%s", reason); - final boolean isKeyguardOccluded = mDisplayContent.isKeyguardOccluded(); - try { - EventLogTags.writeWmSetKeyguardOccluded( - isKeyguardOccluded ? 1 : 0, - 0 /* animate */, - 0 /* transit */, - "onAnimationCancelled"); - mRemoteAnimationAdapter.getRunner().onAnimationCancelled(isKeyguardOccluded); + mRemoteAnimationAdapter.getRunner().onAnimationCancelled(); } catch (RemoteException e) { Slog.e(TAG, "Failed to notify cancel", e); } diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 54dfdd93b26c..abc9f8a48584 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -865,6 +865,13 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { if (c.getSnapshot() != null) { t.reparent(c.getSnapshot(), null); } + // The fixed transform hint was set in DisplayContent#applyRotation(). Make sure to + // clear the hint in case the start transaction is not applied. + if (c.hasFlags(FLAG_IS_DISPLAY) && c.getStartRotation() != c.getEndRotation() + && c.getContainer() != null) { + t.unsetFixedTransformHint(WindowContainer.fromBinder(c.getContainer().asBinder()) + .asDisplayContent().mSurfaceControl); + } } for (int i = info.getRootCount() - 1; i >= 0; --i) { final SurfaceControl leash = info.getRoot(i).getLeash(); diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java index 8af037be8d06..79726372ade7 100644 --- a/services/core/java/com/android/server/wm/TransitionController.java +++ b/services/core/java/com/android/server/wm/TransitionController.java @@ -823,6 +823,7 @@ class TransitionController { // Can reset track-count now that everything is idle. mTrackCount = 0; validateStates(); + mAtm.mWindowManager.onAnimationFinished(); } } @@ -963,6 +964,7 @@ class TransitionController { if (sync) { info.setFlags(info.getFlags() | TransitionInfo.FLAG_SYNC); } + transition.mAnimationTrack = track; info.setTrack(track); mTrackCount = Math.max(mTrackCount, track + 1); } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index b869ac421989..ebe7e0cbac06 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -20215,9 +20215,20 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } private boolean isLockTaskFeatureEnabled(int lockTaskFeature) throws RemoteException { - //TODO(b/175285301): Explicitly get the user's identity to check. - int lockTaskFeatures = - getUserData(getCurrentForegroundUserId()).mLockTaskFeatures; + int lockTaskFeatures = 0; + if (isPolicyEngineForFinanceFlagEnabled()) { + LockTaskPolicy policy = mDevicePolicyEngine.getResolvedPolicy( + PolicyDefinition.LOCK_TASK, getCurrentForegroundUserId()); + lockTaskFeatures = policy == null + // We default on the power button menu, in order to be consistent with pre-P + // behaviour. + ? DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS + : policy.getFlags(); + } else { + //TODO(b/175285301): Explicitly get the user's identity to check. + lockTaskFeatures = + getUserData(getCurrentForegroundUserId()).mLockTaskFeatures; + } return (lockTaskFeatures & lockTaskFeature) == lockTaskFeature; } diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java index 5751db0727e7..275533fb1c37 100644 --- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java @@ -446,6 +446,25 @@ public class MediaProjectionManagerServiceTest { } @Test + public void testSetUserReviewGrantedConsentResult_projectionNull_consentNotGranted() + throws Exception { + MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions(); + projection.start(mIMediaProjectionCallback); + assertThat(mService.isCurrentProjection(projection)).isTrue(); + doReturn(true).when(mWindowManagerInternal).setContentRecordingSession( + any(ContentRecordingSession.class)); + // Some other token. + final IMediaProjection otherProjection = null; + // Waiting for user to review consent. + mService.setContentRecordingSession(mWaitingDisplaySession); + mService.setUserReviewGrantedConsentResult(RECORD_CANCEL, otherProjection); + + // Display result is ignored; only the first session is set. + verify(mWindowManagerInternal, times(1)).setContentRecordingSession( + eq(mWaitingDisplaySession)); + } + + @Test public void testSetUserReviewGrantedConsentResult_noVirtualDisplay() throws Exception { MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions(); projection.start(mIMediaProjectionCallback); diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml index fe7cd4a5edd9..37e5da5f5eaf 100644 --- a/services/tests/wmtests/AndroidManifest.xml +++ b/services/tests/wmtests/AndroidManifest.xml @@ -79,6 +79,7 @@ android:turnScreenOn="true" android:showWhenLocked="true" /> <activity android:name="com.android.server.wm.ActivityOptionsTest$MainActivity" + android:configChanges="screenLayout|screenSize|smallestScreenSize|orientation" android:turnScreenOn="true" android:showWhenLocked="true" /> <activity android:name="com.android.server.wm.ScreenshotTests$ScreenshotActivity" 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 0033e3e368c6..47f32fec9f91 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -851,7 +851,7 @@ public class ActivityRecordTests extends WindowTestsBase { } @Override - public void onAnimationCancelled(boolean isKeyguardOccluded) { + public void onAnimationCancelled() { } }, 0, 0)); activity.updateOptionsLocked(opts); diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java index 6d1312458ce2..169968c75fc5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java @@ -87,7 +87,7 @@ public class AppChangeTransitionTests extends WindowTestsBase { } @Override - public void onAnimationCancelled(boolean isKeyguardOccluded) { + public void onAnimationCancelled() { } @Override 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 0ae579bab413..a11079be85ab 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java @@ -735,7 +735,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { } @Override - public void onAnimationCancelled(boolean isKeyguardOccluded) throws RemoteException { + public void onAnimationCancelled() throws RemoteException { mFinishedCallback = null; } 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 59cc4f5b0948..ba8c94dd9218 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java @@ -549,7 +549,7 @@ public class AppTransitionTests extends WindowTestsBase { } @Override - public void onAnimationCancelled(boolean isKeyguardOccluded) { + public void onAnimationCancelled() { mCancelled = true; } diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java index eb26415c2b21..11d9629cf25e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java @@ -211,7 +211,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN); adapter.onAnimationCancelled(mMockLeash); - verify(mMockRunner).onAnimationCancelled(anyBoolean()); + verify(mMockRunner).onAnimationCancelled(); } @Test @@ -227,7 +227,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { mClock.fastForward(10500); mHandler.timeAdvance(); - verify(mMockRunner).onAnimationCancelled(anyBoolean()); + verify(mMockRunner).onAnimationCancelled(); verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION), eq(adapter)); } @@ -248,12 +248,12 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { mClock.fastForward(10500); mHandler.timeAdvance(); - verify(mMockRunner, never()).onAnimationCancelled(anyBoolean()); + verify(mMockRunner, never()).onAnimationCancelled(); mClock.fastForward(52500); mHandler.timeAdvance(); - verify(mMockRunner).onAnimationCancelled(anyBoolean()); + verify(mMockRunner).onAnimationCancelled(); verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION), eq(adapter)); } finally { @@ -265,7 +265,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { public void testZeroAnimations() throws Exception { mController.goodToGo(TRANSIT_OLD_NONE); verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any()); - verify(mMockRunner).onAnimationCancelled(anyBoolean()); + verify(mMockRunner).onAnimationCancelled(); } @Test @@ -275,7 +275,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false); mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN); verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any()); - verify(mMockRunner).onAnimationCancelled(anyBoolean()); + verify(mMockRunner).onAnimationCancelled(); } @Test @@ -317,7 +317,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { win.mActivityRecord.removeImmediately(); mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN); verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any()); - verify(mMockRunner).onAnimationCancelled(anyBoolean()); + verify(mMockRunner).onAnimationCancelled(); verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION), eq(adapter)); } @@ -575,7 +575,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { // Cancel the wallpaper window animator and ensure the runner is not canceled wallpaperWindowToken.cancelAnimation(); - verify(mMockRunner, never()).onAnimationCancelled(anyBoolean()); + verify(mMockRunner, never()).onAnimationCancelled(); } finally { mDisplayContent.mOpeningApps.clear(); } diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceControlTests.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceControlTests.java index a27a5fd8a286..342ab83de6f0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SurfaceControlTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceControlTests.java @@ -16,19 +16,34 @@ package com.android.server.wm; +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; +import android.app.Activity; +import android.app.Instrumentation; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; import android.os.Parcel; import android.platform.test.annotations.Presubmit; +import android.util.Log; import android.view.SurfaceControl; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import androidx.annotation.NonNull; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.concurrent.atomic.AtomicInteger; + /** * Class for testing {@link SurfaceControl}. * @@ -106,6 +121,50 @@ public class SurfaceControlTests { } } + @Test + public void testSurfaceChangedOnRotation() { + final Instrumentation instrumentation = getInstrumentation(); + final Context context = instrumentation.getContext(); + final Activity activity = instrumentation.startActivitySync(new Intent().setComponent( + new ComponentName(context, ActivityOptionsTest.MainActivity.class)) + .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + final SurfaceView sv = new SurfaceView(activity); + final AtomicInteger surfaceChangedCount = new AtomicInteger(); + instrumentation.runOnMainSync(() -> activity.setContentView(sv)); + sv.getHolder().addCallback(new SurfaceHolder.Callback() { + @Override + public void surfaceCreated(@NonNull SurfaceHolder holder) { + } + @Override + public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, + int height) { + surfaceChangedCount.getAndIncrement(); + Log.i("surfaceChanged", "width=" + width + " height=" + height + + " getTransformHint=" + + sv.getViewRootImpl().getSurfaceControl().getTransformHint()); + } + @Override + public void surfaceDestroyed(@NonNull SurfaceHolder holder) { + } + }); + final int rotation = activity.getResources().getConfiguration() + .windowConfiguration.getRotation(); + activity.setRequestedOrientation(activity.getResources().getConfiguration().orientation + == Configuration.ORIENTATION_PORTRAIT + ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE + : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + instrumentation.getUiAutomation().syncInputTransactions(); + instrumentation.waitForIdleSync(); + final int newRotation = activity.getResources().getConfiguration() + .windowConfiguration.getRotation(); + final int count = surfaceChangedCount.get(); + activity.finishAndRemoveTask(); + // The first count is triggered from creation, so the target number is 2. + if (rotation != newRotation && count > 2) { + fail("More than once surfaceChanged for rotation change: " + count); + } + } + private SurfaceControl buildTestSurface() { return new SurfaceControl.Builder() .setContainerLayer() diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java index a1ddd5748002..ad606cb90841 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java @@ -1112,7 +1112,7 @@ public class WindowContainerTests extends WindowTestsBase { } @Override - public void onAnimationCancelled(boolean isKeyguardOccluded) { + public void onAnimationCancelled() { } }, 0, 0, false); adapter.setCallingPidUid(123, 456); diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java index 1ce85ba93d95..8be074d5e932 100644 --- a/telephony/java/android/telephony/data/ApnSetting.java +++ b/telephony/java/android/telephony/data/ApnSetting.java @@ -1337,6 +1337,14 @@ public class ApnSetting implements Parcelable { public ContentValues toContentValues() { ContentValues apnValue = new ContentValues(); apnValue.put(Telephony.Carriers.NUMERIC, nullToEmpty(mOperatorNumeric)); + // If the APN is editable, the user may be able to set an invalid numeric. The numeric must + // always be 5 or 6 characters (depending on the length of the MNC), so skip if it is + // potentially invalid. + if (!TextUtils.isEmpty(mOperatorNumeric) + && (mOperatorNumeric.length() == 5 || mOperatorNumeric.length() == 6)) { + apnValue.put(Telephony.Carriers.MCC, mOperatorNumeric.substring(0, 3)); + apnValue.put(Telephony.Carriers.MNC, mOperatorNumeric.substring(3)); + } apnValue.put(Telephony.Carriers.NAME, nullToEmpty(mEntryName)); apnValue.put(Telephony.Carriers.APN, nullToEmpty(mApnName)); apnValue.put(Telephony.Carriers.PROXY, nullToEmpty(mProxyAddress)); @@ -1356,6 +1364,7 @@ public class ApnSetting implements Parcelable { getProtocolStringFromInt(mRoamingProtocol)); apnValue.put(Telephony.Carriers.CARRIER_ENABLED, mCarrierEnabled); apnValue.put(Telephony.Carriers.MVNO_TYPE, getMvnoTypeStringFromInt(mMvnoType)); + apnValue.put(Telephony.Carriers.MVNO_MATCH_DATA, nullToEmpty(mMvnoMatchData)); apnValue.put(Telephony.Carriers.NETWORK_TYPE_BITMASK, mNetworkTypeBitmask); apnValue.put(Telephony.Carriers.LINGERING_NETWORK_TYPE_BITMASK, mLingeringNetworkTypeBitmask); |