diff options
72 files changed, 753 insertions, 164 deletions
diff --git a/core/java/android/app/ServiceStartArgs.java b/core/java/android/app/ServiceStartArgs.java index 0b000af56400..9c52367392a5 100644 --- a/core/java/android/app/ServiceStartArgs.java +++ b/core/java/android/app/ServiceStartArgs.java @@ -49,7 +49,7 @@ public class ServiceStartArgs implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeInt(taskRemoved ? 1 : 0); out.writeInt(startId); - out.writeInt(flags); + out.writeInt(this.flags); if (args != null) { out.writeInt(1); args.writeToParcel(out, 0); diff --git a/core/java/android/app/WallpaperInfo.java b/core/java/android/app/WallpaperInfo.java index 99d406446dae..b29e73a717f4 100644 --- a/core/java/android/app/WallpaperInfo.java +++ b/core/java/android/app/WallpaperInfo.java @@ -292,12 +292,12 @@ public final class WallpaperInfo implements Parcelable { packageName = mService.serviceInfo.packageName; applicationInfo = mService.serviceInfo.applicationInfo; } - String contextUriString = pm.getText( - packageName, mContextUriResource, applicationInfo).toString(); - if (contextUriString == null) { + CharSequence contextUriCharSequence = pm.getText( + packageName, mContextUriResource, applicationInfo); + if (contextUriCharSequence == null) { return null; } - return Uri.parse(contextUriString); + return Uri.parse(contextUriCharSequence.toString()); } /** diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java index dacb25ca1628..bb5dd7f0cdfe 100644 --- a/core/java/android/speech/SpeechRecognizer.java +++ b/core/java/android/speech/SpeechRecognizer.java @@ -812,7 +812,7 @@ public class SpeechRecognizer { Intent recognizerIntent, Executor callbackExecutor, RecognitionSupportCallback recognitionSupportCallback) { - if (!maybeInitializeManagerService()) { + if (!maybeInitializeManagerService() || !checkOpenConnection()) { return; } try { @@ -831,7 +831,7 @@ public class SpeechRecognizer { Intent recognizerIntent, @Nullable Executor callbackExecutor, @Nullable ModelDownloadListener modelDownloadListener) { - if (!maybeInitializeManagerService()) { + if (!maybeInitializeManagerService() || !checkOpenConnection()) { return; } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index e95ba797a985..e40f8e78dafc 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -555,6 +555,13 @@ public interface WindowManager extends ViewManager { int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_LAUNCHER_CLEAR_SNAPSHOT = (1 << 9); // 0x200 /** + * Transition flag: The transition is prepared when nothing is visible on screen, e.g. screen + * is off. The animation handlers can decide whether to skip animations. + * @hide + */ + int TRANSIT_FLAG_INVISIBLE = (1 << 10); // 0x400 + + /** * @hide */ @IntDef(flag = true, prefix = { "TRANSIT_FLAG_" }, value = { @@ -567,7 +574,8 @@ public interface WindowManager extends ViewManager { TRANSIT_FLAG_KEYGUARD_LOCKED, TRANSIT_FLAG_IS_RECENTS, TRANSIT_FLAG_KEYGUARD_GOING_AWAY, - TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_LAUNCHER_CLEAR_SNAPSHOT + TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_LAUNCHER_CLEAR_SNAPSHOT, + TRANSIT_FLAG_INVISIBLE, }) @Retention(RetentionPolicy.SOURCE) @interface TransitionFlags {} diff --git a/core/java/com/android/internal/widget/ImageFloatingTextView.java b/core/java/com/android/internal/widget/ImageFloatingTextView.java index 2695b9c7651f..1ac5e1f12bfa 100644 --- a/core/java/com/android/internal/widget/ImageFloatingTextView.java +++ b/core/java/com/android/internal/widget/ImageFloatingTextView.java @@ -82,7 +82,7 @@ public class ImageFloatingTextView extends TextView { .setIncludePad(getIncludeFontPadding()) .setUseLineSpacingFromFallbacks(true) .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL); + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL_FAST); int maxLines; if (mMaxLinesForHeight > 0) { maxLines = mMaxLinesForHeight; diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java b/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java index 6e8e93a8c86b..b2e42ba90152 100644 --- a/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java +++ b/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java @@ -26,6 +26,7 @@ import android.app.Activity; import android.compat.testing.PlatformCompatChangeRule; import android.os.Bundle; import android.platform.test.annotations.IwTest; +import android.platform.test.annotations.PlatinumTest; import android.platform.test.annotations.Presubmit; import android.provider.Settings; import android.util.PollingCheck; @@ -72,6 +73,7 @@ public class FontScaleConverterActivityTest { restoreSystemFontScaleToDefault(); } + @PlatinumTest(focusArea = "accessibility") @IwTest(focusArea = "accessibility") @Test public void testFontsScaleNonLinearly() { @@ -103,6 +105,7 @@ public class FontScaleConverterActivityTest { ))); } + @PlatinumTest(focusArea = "accessibility") @IwTest(focusArea = "accessibility") @Test public void testOnConfigurationChanged_doesNotCrash() { @@ -117,6 +120,7 @@ public class FontScaleConverterActivityTest { }); } + @PlatinumTest(focusArea = "accessibility") @IwTest(focusArea = "accessibility") @Test public void testUpdateConfiguration_doesNotCrash() { diff --git a/graphics/java/android/graphics/GraphicBuffer.java b/graphics/java/android/graphics/GraphicBuffer.java index f9113a21405c..6705b25ab0ec 100644 --- a/graphics/java/android/graphics/GraphicBuffer.java +++ b/graphics/java/android/graphics/GraphicBuffer.java @@ -57,7 +57,7 @@ public class GraphicBuffer implements Parcelable { private final int mUsage; // Note: do not rename, this field is used by native code @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - private final long mNativeObject; + private long mNativeObject; // These two fields are only used by lock/unlockCanvas() private Canvas mCanvas; @@ -219,6 +219,7 @@ public class GraphicBuffer implements Parcelable { if (!mDestroyed) { mDestroyed = true; nDestroyGraphicBuffer(mNativeObject); + mNativeObject = 0; } } @@ -239,7 +240,7 @@ public class GraphicBuffer implements Parcelable { @Override protected void finalize() throws Throwable { try { - if (!mDestroyed) nDestroyGraphicBuffer(mNativeObject); + destroy(); } finally { super.finalize(); } 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 e0ffffffa727..256d48c5618c 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 @@ -192,6 +192,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, private final SplitScreenTransitions mSplitTransitions; private final SplitscreenEventLogger mLogger; private final ShellExecutor mMainExecutor; + // Cache live tile tasks while entering recents, evict them from stages in finish transaction + // if user is opening another task(s). + private final ArrayList<Integer> mPausingTasks = new ArrayList<>(); private final Optional<RecentTasksController> mRecentTasks; private final Rect mTempRect1 = new Rect(); @@ -658,6 +661,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, // Add task launch requests wct.startTask(mainTaskId, mainOptions); + // leave recents animation by re-start pausing tasks + if (mPausingTasks.contains(mainTaskId)) { + mPausingTasks.clear(); + } mSplitTransitions.startEnterTransition( TRANSIT_TO_FRONT, wct, remoteTransition, this, null, null, TRANSIT_SPLIT_SCREEN_PAIR_OPEN, false); @@ -1630,7 +1637,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } private void updateRecentTasksSplitPair() { - if (!mShouldUpdateRecents) { + // Preventing from single task update while processing recents. + if (!mShouldUpdateRecents || !mPausingTasks.isEmpty()) { return; } mRecentTasks.ifPresent(recentTasks -> { @@ -2582,6 +2590,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, final TransitionInfo.Change change = info.getChanges().get(iC); final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); if (taskInfo == null || !taskInfo.hasParentTask()) continue; + if (mPausingTasks.contains(taskInfo.taskId)) { + continue; + } final @StageType int stageType = getStageType(getStageOfTask(taskInfo)); if (stageType == STAGE_TYPE_MAIN && (isOpeningType(change.getMode()) || change.getMode() == TRANSIT_CHANGE)) { @@ -2654,6 +2665,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mShowDecorImmediately = true; mSplitLayout.flingDividerToCenter(); } + mPausingTasks.clear(); }); finishEnterSplitScreen(finishT); @@ -2811,12 +2823,33 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, /** Call this when starting the open-recents animation while split-screen is active. */ public void onRecentsInSplitAnimationStart(TransitionInfo info) { + if (isSplitScreenVisible()) { + // Cache tasks on live tile. + for (int i = 0; i < info.getChanges().size(); ++i) { + final TransitionInfo.Change change = info.getChanges().get(i); + if (TransitionUtil.isClosingType(change.getMode()) + && change.getTaskInfo() != null) { + final int taskId = change.getTaskInfo().taskId; + if (mMainStage.getTopVisibleChildTaskId() == taskId + || mSideStage.getTopVisibleChildTaskId() == taskId) { + mPausingTasks.add(taskId); + } + } + } + } + addDividerBarToTransition(info, false /* show */); } + /** Call this when the recents animation canceled during split-screen. */ + public void onRecentsInSplitAnimationCanceled() { + mPausingTasks.clear(); + } + /** Call this when the recents animation during split-screen finishes. */ public void onRecentsInSplitAnimationFinish(WindowContainerTransaction finishWct, - SurfaceControl.Transaction finishT, TransitionInfo info) { + SurfaceControl.Transaction finishT) { + mPausingTasks.clear(); // Check if the recent transition is finished by returning to the current // split, so we can restore the divider bar. for (int i = 0; i < finishWct.getHierarchyOps().size(); ++i) { @@ -2840,6 +2873,27 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, logExit(EXIT_REASON_UNKNOWN); } + /** Call this when the recents animation finishes by doing pair-to-pair switch. */ + public void onRecentsPairToPairAnimationFinish(WindowContainerTransaction finishWct) { + // Pair-to-pair switch happened so here should evict the live tile from its stage. + // Otherwise, the task will remain in stage, and occluding the new task when next time + // user entering recents. + for (int i = mPausingTasks.size() - 1; i >= 0; --i) { + final int taskId = mPausingTasks.get(i); + if (mMainStage.containsTask(taskId)) { + mMainStage.evictChildren(finishWct, taskId); + } else if (mSideStage.containsTask(taskId)) { + mSideStage.evictChildren(finishWct, taskId); + } + } + // If pending enter hasn't consumed, the mix handler will invoke start pending + // animation within following transition. + if (mSplitTransitions.mPendingEnter == null) { + mPausingTasks.clear(); + updateRecentTasksSplitPair(); + } + } + private void addDividerBarToTransition(@NonNull TransitionInfo info, boolean show) { final SurfaceControl leash = mSplitLayout.getDividerLeash(); if (leash == null || !leash.isValid()) { @@ -2892,6 +2946,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, pw.println(innerPrefix + "SplitLayout"); mSplitLayout.dump(pw, childPrefix); } + if (!mPausingTasks.isEmpty()) { + pw.println(childPrefix + "mPausingTasks=" + mPausingTasks); + } } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java index da7d18641a97..92ff5fed4584 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java @@ -377,6 +377,13 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { } } + void evictChildren(WindowContainerTransaction wct, int taskId) { + final ActivityManager.RunningTaskInfo taskInfo = mChildrenTaskInfo.get(taskId); + if (taskInfo != null) { + wct.reparent(taskInfo.token, null /* parent */, false /* onTop */); + } + } + void reparentTopTask(WindowContainerTransaction wct) { wct.reparentTasks(null /* currentParent */, mRootTaskInfo.token, CONTROLLED_WINDOWING_MODES, CONTROLLED_ACTIVITY_TYPES, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java index 863b5ab73a7d..64571e067a83 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java @@ -540,9 +540,12 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, mixed.mInFlightSubAnimations = 0; mActiveTransitions.remove(mixed); // If pair-to-pair switching, the post-recents clean-up isn't needed. + wct = wct != null ? wct : new WindowContainerTransaction(); if (mixed.mAnimType != MixedTransition.ANIM_TYPE_PAIR_TO_PAIR) { - wct = wct != null ? wct : new WindowContainerTransaction(); - mSplitHandler.onRecentsInSplitAnimationFinish(wct, finishTransaction, info); + mSplitHandler.onRecentsInSplitAnimationFinish(wct, finishTransaction); + } else { + // notify pair-to-pair recents animation finish + mSplitHandler.onRecentsPairToPairAnimationFinish(wct); } mSplitHandler.onTransitionAnimationComplete(); finishCallback.onTransitionFinished(wct, wctCB); @@ -552,6 +555,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, final boolean handled = mixed.mLeftoversHandler.startAnimation(mixed.mTransition, info, startTransaction, finishTransaction, finishCB); if (!handled) { + mSplitHandler.onRecentsInSplitAnimationCanceled(); mActiveTransitions.remove(mixed); } return handled; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java index 6a2468a7eaa2..dc8a25842969 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java @@ -299,7 +299,8 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { } // Early check if the transition doesn't warrant an animation. - if (Transitions.isAllNoAnimation(info) || Transitions.isAllOrderOnly(info)) { + if (Transitions.isAllNoAnimation(info) || Transitions.isAllOrderOnly(info) + || (info.getFlags() & WindowManager.TRANSIT_FLAG_INVISIBLE) != 0) { startTransaction.apply(); finishTransaction.apply(); finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java index 19d8384ace41..fc301b6993c0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java @@ -23,6 +23,7 @@ import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static android.view.WindowManager.transitTypeToString; +import static android.window.TransitionInfo.FLAGS_IS_NON_APP_WINDOW; import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT; import static android.window.TransitionInfo.FLAG_TRANSLUCENT; @@ -150,6 +151,10 @@ public class TransitionAnimationHelper { .loadAnimationAttr(options.getPackageName(), options.getAnimations(), animAttr, translucent); } + } else if (translucent && !isTask && ((changeFlags & FLAGS_IS_NON_APP_WINDOW) == 0)) { + // Un-styled translucent activities technically have undefined animations; however, + // as is always the case, some apps now rely on this being no-animation, so skip + // loading animations here. } else { a = transitionAnimation.loadDefaultAnimationAttr(animAttr, translucent); } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt index b7e73ad11c9f..72f25f36c9d9 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt @@ -18,6 +18,7 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.FlakyTest import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.traces.component.ComponentNameMatcher import android.tools.common.traces.component.EdgeExtensionComponentMatcher @@ -60,6 +61,7 @@ class CopyContentInSplit(override val flicker: FlickerTest) : thisTransition(this) } + @PlatinumTest(focusArea = "sysui") @IwTest(focusArea = "sysui") @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt index 0b0a3dad320b..ed3df9ced3b0 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt @@ -18,6 +18,7 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.FlakyTest import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder @@ -58,6 +59,7 @@ class DragDividerToResize(override val flicker: FlickerTest) : thisTransition(this) } + @PlatinumTest(focusArea = "sysui") @IwTest(focusArea = "sysui") @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt index 8cf871f88314..b4c6afd14a90 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit import android.tools.common.NavBar @@ -59,6 +60,7 @@ class SwitchAppByDoubleTapDivider(override val flicker: FlickerTest) : thisTransition(this) } + @PlatinumTest(focusArea = "sysui") @IwTest(focusArea = "sysui") @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt index 3b2da8dbcf9f..2cedc3570cfd 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt @@ -18,6 +18,7 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.FlakyTest import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder @@ -62,6 +63,7 @@ class SwitchBetweenSplitPairs(override val flicker: FlickerTest) : thisTransition(this) } + @PlatinumTest(focusArea = "sysui") @IwTest(focusArea = "sysui") @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt index a189a3f67eca..a5ad97d8ad65 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.splitscreen.benchmark import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -62,6 +63,7 @@ open class CopyContentInSplitBenchmark(override val flicker: FlickerTest) : thisTransition(this) } + @PlatinumTest(focusArea = "sysui") @IwTest(focusArea = "sysui") @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByDividerBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByDividerBenchmark.kt index 55ab7b3a30e4..fa6a4bfbcda6 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByDividerBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByDividerBenchmark.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.splitscreen.benchmark import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder @@ -68,6 +69,7 @@ open class DismissSplitScreenByDividerBenchmark(flicker: FlickerTest) : SplitScr thisTransition(this) } + @PlatinumTest(focusArea = "sysui") @IwTest(focusArea = "sysui") @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByGoHomeBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByGoHomeBenchmark.kt index c4cfd1add25c..d2beb678a4d5 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByGoHomeBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByGoHomeBenchmark.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.splitscreen.benchmark import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder @@ -55,6 +56,7 @@ open class DismissSplitScreenByGoHomeBenchmark(override val flicker: FlickerTest thisTransition(this) } + @PlatinumTest(focusArea = "sysui") @IwTest(focusArea = "sysui") @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DragDividerToResizeBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DragDividerToResizeBenchmark.kt index 146287c21c75..e95fd947ebde 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DragDividerToResizeBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DragDividerToResizeBenchmark.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.splitscreen.benchmark import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder @@ -58,6 +59,7 @@ open class DragDividerToResizeBenchmark(override val flicker: FlickerTest) : Assume.assumeTrue(tapl.isTablet || !flicker.scenario.isLandscapeOrSeascapeAtStart) } + @PlatinumTest(focusArea = "sysui") @IwTest(focusArea = "sysui") @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromAllAppsBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromAllAppsBenchmark.kt index cc715021adf4..63b74e29c39c 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromAllAppsBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromAllAppsBenchmark.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.splitscreen.benchmark import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.NavBar import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -70,6 +71,7 @@ open class EnterSplitScreenByDragFromAllAppsBenchmark(override val flicker: Flic Assume.assumeTrue(tapl.isTablet) } + @PlatinumTest(focusArea = "sysui") @IwTest(focusArea = "sysui") @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromNotificationBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromNotificationBenchmark.kt index de78f09d3ef4..e94da8713b43 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromNotificationBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromNotificationBenchmark.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.splitscreen.benchmark import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.NavBar import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -67,6 +68,7 @@ open class EnterSplitScreenByDragFromNotificationBenchmark(override val flicker: thisTransition(this) } + @PlatinumTest(focusArea = "sysui") @IwTest(focusArea = "sysui") @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromShortcutBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromShortcutBenchmark.kt index a29eb4085e54..f41117f0d54e 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromShortcutBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromShortcutBenchmark.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.splitscreen.benchmark import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.NavBar import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -70,6 +71,7 @@ open class EnterSplitScreenByDragFromShortcutBenchmark(flicker: FlickerTest) : thisTransition(this) } + @PlatinumTest(focusArea = "sysui") @IwTest(focusArea = "sysui") @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromTaskbarBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromTaskbarBenchmark.kt index b2395cafafc1..12f610b73e13 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromTaskbarBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromTaskbarBenchmark.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.splitscreen.benchmark import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.NavBar import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -65,6 +66,7 @@ open class EnterSplitScreenByDragFromTaskbarBenchmark(override val flicker: Flic thisTransition(this) } + @PlatinumTest(focusArea = "sysui") @IwTest(focusArea = "sysui") @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenFromOverviewBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenFromOverviewBenchmark.kt index e1d85d0a4371..77818d380053 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenFromOverviewBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenFromOverviewBenchmark.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.splitscreen.benchmark import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder @@ -64,6 +65,7 @@ open class EnterSplitScreenFromOverviewBenchmark(override val flicker: FlickerTe thisTransition(this) } + @PlatinumTest(focusArea = "sysui") @IwTest(focusArea = "sysui") @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt index ba8c46091808..6ff22902667c 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.splitscreen.benchmark import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.NavBar import android.tools.common.Rotation @@ -134,6 +135,7 @@ open class SwitchAppByDoubleTapDividerBenchmark(override val flicker: FlickerTes return displayBounds.width > displayBounds.height } + @PlatinumTest(focusArea = "sysui") @IwTest(focusArea = "sysui") @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromAnotherAppBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromAnotherAppBenchmark.kt index bbb2edc621e2..400adea8880d 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromAnotherAppBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromAnotherAppBenchmark.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.splitscreen.benchmark import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.NavBar import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -63,6 +64,7 @@ open class SwitchBackToSplitFromAnotherAppBenchmark(override val flicker: Flicke thisTransition(this) } + @PlatinumTest(focusArea = "sysui") @IwTest(focusArea = "sysui") @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromHomeBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromHomeBenchmark.kt index fa382932eb88..1ec43405ee44 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromHomeBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromHomeBenchmark.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.splitscreen.benchmark import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.NavBar import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -61,6 +62,7 @@ open class SwitchBackToSplitFromHomeBenchmark(override val flicker: FlickerTest) thisTransition(this) } + @PlatinumTest(focusArea = "sysui") @IwTest(focusArea = "sysui") @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromRecentBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromRecentBenchmark.kt index 1064bd93e3c1..9757153929ca 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromRecentBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromRecentBenchmark.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.splitscreen.benchmark import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.NavBar import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -61,6 +62,7 @@ open class SwitchBackToSplitFromRecentBenchmark(override val flicker: FlickerTes thisTransition(this) } + @PlatinumTest(focusArea = "sysui") @IwTest(focusArea = "sysui") @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBetweenSplitPairsBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBetweenSplitPairsBenchmark.kt index 8f4393f8d20d..c19a38dc9daf 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBetweenSplitPairsBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBetweenSplitPairsBenchmark.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.splitscreen.benchmark import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder @@ -64,6 +65,7 @@ open class SwitchBetweenSplitPairsBenchmark(override val flicker: FlickerTest) : thisTransition(this) } + @PlatinumTest(focusArea = "sysui") @IwTest(focusArea = "sysui") @Presubmit @Test open fun cujCompleted() {} companion object { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java index 60c0e5535568..5f705d743601 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java @@ -283,7 +283,7 @@ public class SplitTransitionTests extends ShellTestCase { // Make sure it cleans-up if recents doesn't restore WindowContainerTransaction commitWCT = new WindowContainerTransaction(); mStageCoordinator.onRecentsInSplitAnimationFinish(commitWCT, - mock(SurfaceControl.Transaction.class), mock(TransitionInfo.class)); + mock(SurfaceControl.Transaction.class)); assertFalse(mStageCoordinator.isSplitScreenVisible()); } @@ -322,7 +322,7 @@ public class SplitTransitionTests extends ShellTestCase { mMainStage.onTaskAppeared(mMainChild, mock(SurfaceControl.class)); mSideStage.onTaskAppeared(mSideChild, mock(SurfaceControl.class)); mStageCoordinator.onRecentsInSplitAnimationFinish(restoreWCT, - mock(SurfaceControl.Transaction.class), mock(TransitionInfo.class)); + mock(SurfaceControl.Transaction.class)); assertTrue(mStageCoordinator.isSplitScreenVisible()); } diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp index ca1bb3e97815..da2e56f5b6fa 100644 --- a/media/jni/android_media_ImageReader.cpp +++ b/media/jni/android_media_ImageReader.cpp @@ -768,6 +768,7 @@ static void ImageReader_unlockGraphicBuffer(JNIEnv* env, jobject /*thiz*/, android_graphics_GraphicBuffer_getNativeGraphicsBuffer(env, buffer); if (graphicBuffer.get() == NULL) { jniThrowRuntimeException(env, "Invalid graphic buffer!"); + return; } status_t res = graphicBuffer->unlock(); diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt index e3ea2e78756f..a0ff216875a2 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt @@ -76,7 +76,7 @@ class AppInfoProvider(private val packageInfo: PackageInfo) { private fun AppVersion() { if (packageInfo.versionName == null) return Spacer(modifier = Modifier.height(4.dp)) - SettingsBody(packageInfo.versionName) + SettingsBody(packageInfo.versionNameBidiWrapped) } @Composable @@ -84,10 +84,15 @@ class AppInfoProvider(private val packageInfo: PackageInfo) { if (packageInfo.versionName == null) return Divider() Box(modifier = Modifier.padding(SettingsDimension.itemPadding)) { - val versionName = BidiFormatter.getInstance().unicodeWrap(packageInfo.versionName) - SettingsBody(stringResource(R.string.version_text, versionName)) + SettingsBody(stringResource(R.string.version_text, packageInfo.versionNameBidiWrapped)) } } + + private companion object { + /** Wrapped the version name, so its directionality still keep same when RTL. */ + val PackageInfo.versionNameBidiWrapped: String + get() = BidiFormatter.getInstance().unicodeWrap(versionName) + } } @Composable diff --git a/packages/SystemUI/res/layout/screen_share_dialog.xml b/packages/SystemUI/res/layout/screen_share_dialog.xml index 0d86e0a40b6d..ab522a388735 100644 --- a/packages/SystemUI/res/layout/screen_share_dialog.xml +++ b/packages/SystemUI/res/layout/screen_share_dialog.xml @@ -36,7 +36,7 @@ android:layout_width="@dimen/screenrecord_logo_size" android:layout_height="@dimen/screenrecord_logo_size" android:src="@drawable/ic_media_projection_permission" - android:tint="?androidprv:attr/colorAccentPrimary" + android:tint="?androidprv:attr/colorAccentPrimaryVariant" android:importantForAccessibility="no"/> <TextView android:id="@+id/screen_share_dialog_title" diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java index afc25909ca91..99b5d52f8322 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java @@ -158,15 +158,18 @@ public class KeyguardPatternView extends KeyguardInputView public void startAppearAnimation() { enableClipping(false); - setAlpha(1f); + setAlpha(0f); setTranslationY(mAppearAnimationUtils.getStartTranslation()); AppearAnimationUtils.startTranslationYAnimation(this, 0 /* delay */, 500 /* duration */, 0, mAppearAnimationUtils.getInterpolator(), getAnimationListener(InteractionJankMonitor.CUJ_LOCKSCREEN_PATTERN_APPEAR)); - mAppearAnimationUtils.startAnimation2d( - mLockPatternView.getCellStates(), - () -> enableClipping(true), - this); + mLockPatternView.post(() -> { + setAlpha(1f); + mAppearAnimationUtils.startAnimation2d( + mLockPatternView.getCellStates(), + () -> enableClipping(true), + KeyguardPatternView.this); + }); if (!TextUtils.isEmpty(mSecurityMessageDisplay.getText())) { mAppearAnimationUtils.createAnimation(mSecurityMessageDisplay, 0, AppearAnimationUtils.DEFAULT_APPEAR_DURATION, diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index e8046dc07c02..1721891550a1 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -246,6 +246,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private static final int MSG_TIME_FORMAT_UPDATE = 344; private static final int MSG_REQUIRE_NFC_UNLOCK = 345; private static final int MSG_KEYGUARD_DISMISS_ANIMATION_FINISHED = 346; + private static final int MSG_SERVICE_PROVIDERS_UPDATED = 347; /** Biometric authentication state: Not listening. */ private static final int BIOMETRIC_STATE_STOPPED = 0; @@ -1826,6 +1827,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) { String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state)); + } else if (TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED.equals(action)) { + mHandler.obtainMessage(MSG_SERVICE_PROVIDERS_UPDATED, intent).sendToTarget(); } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) { mHandler.sendEmptyMessage(MSG_AIRPLANE_MODE_CHANGED); } else if (Intent.ACTION_SERVICE_STATE.equals(action)) { @@ -2402,6 +2405,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab case MSG_SERVICE_STATE_CHANGE: handleServiceStateChange(msg.arg1, (ServiceState) msg.obj); break; + case MSG_SERVICE_PROVIDERS_UPDATED: + handleServiceProvidersUpdated((Intent) msg.obj); + break; case MSG_SCREEN_TURNED_OFF: Trace.beginSection("KeyguardUpdateMonitor#handler MSG_SCREEN_TURNED_OFF"); handleScreenTurnedOff(); @@ -2472,6 +2478,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab filter.addAction(Intent.ACTION_SERVICE_STATE); filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); + filter.addAction(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED); filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); filter.addAction(UsbManager.ACTION_USB_PORT_COMPLIANCE_CHANGED); mBroadcastDispatcher.registerReceiverWithHandler(mBroadcastReceiver, filter, mHandler); @@ -3727,6 +3734,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } /** + * Handle {@link #MSG_SERVICE_PROVIDERS_UPDATED} + */ + private void handleServiceProvidersUpdated(Intent intent) { + mLogger.logServiceProvidersUpdated(intent); + callbacksRefreshCarrierInfo(); + } + + /** * Whether the keyguard is showing and not occluded. */ public boolean isKeyguardVisible() { diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt index 17cc23632d94..4923ab0fab18 100644 --- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt +++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt @@ -16,11 +16,15 @@ package com.android.keyguard.logging +import android.content.Intent import android.hardware.biometrics.BiometricConstants.LockoutMode import android.os.PowerManager import android.os.PowerManager.WakeReason import android.telephony.ServiceState import android.telephony.SubscriptionInfo +import android.telephony.SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX +import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID +import android.telephony.TelephonyManager import com.android.keyguard.ActiveUnlockConfig import com.android.keyguard.FaceAuthUiEvent import com.android.keyguard.KeyguardListenModel @@ -363,6 +367,21 @@ constructor(@KeyguardUpdateMonitorLog private val logBuffer: LogBuffer) { ) } + fun logServiceProvidersUpdated(intent: Intent) { + logBuffer.log( + TAG, + VERBOSE, + { + int1 = intent.getIntExtra(EXTRA_SUBSCRIPTION_INDEX, INVALID_SUBSCRIPTION_ID) + str1 = intent.getStringExtra(TelephonyManager.EXTRA_SPN) + str2 = intent.getStringExtra(TelephonyManager.EXTRA_PLMN) + }, + { + "action SERVICE_PROVIDERS_UPDATED subId=$int1 spn=$str1 plmn=$str2" + } + ) + } + fun logSimState(subId: Int, slotId: Int, state: Int) { logBuffer.log( TAG, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java index d2526dffcc52..a8d22c48e709 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java @@ -122,6 +122,10 @@ public class KeyguardService extends Service { } } + // Avoid wrapping non-task and non-wallpaper changes as they don't need to animate + // for keyguard unlock animation. + if (taskId < 0 && !wallpapers) continue; + final RemoteAnimationTarget target = TransitionUtil.newTarget(change, // wallpapers go into the "below" layer space info.getChanges().size() - i, @@ -303,46 +307,6 @@ public class KeyguardService extends Service { } } - final IRemoteTransition mOccludeAnimation = new IRemoteTransition.Stub() { - @Override - public void startAnimation(IBinder transition, TransitionInfo info, - SurfaceControl.Transaction t, IRemoteTransitionFinishedCallback finishCallback) - throws RemoteException { - t.apply(); - mBinder.setOccluded(true /* isOccluded */, true /* animate */); - finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */); - info.releaseAllSurfaces(); - } - - @Override - public void mergeAnimation(IBinder transition, TransitionInfo info, - SurfaceControl.Transaction t, IBinder mergeTarget, - IRemoteTransitionFinishedCallback finishCallback) { - t.close(); - info.releaseAllSurfaces(); - } - }; - - final IRemoteTransition mUnoccludeAnimation = new IRemoteTransition.Stub() { - @Override - public void startAnimation(IBinder transition, TransitionInfo info, - SurfaceControl.Transaction t, IRemoteTransitionFinishedCallback finishCallback) - throws RemoteException { - t.apply(); - mBinder.setOccluded(false /* isOccluded */, true /* animate */); - finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */); - info.releaseAllSurfaces(); - } - - @Override - public void mergeAnimation(IBinder transition, TransitionInfo info, - SurfaceControl.Transaction t, IBinder mergeTarget, - IRemoteTransitionFinishedCallback finishCallback) { - t.close(); - info.releaseAllSurfaces(); - } - }; - private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() { private static final String TRACK_NAME = "IKeyguardService"; diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt index 122e25975837..29a7fe7d061a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt @@ -637,7 +637,9 @@ class KeyguardUnlockAnimationController @Inject constructor( * Unlock to the launcher, using in-window animations, and the smartspace shared element * transition if possible. */ - private fun unlockToLauncherWithInWindowAnimations() { + + @VisibleForTesting + fun unlockToLauncherWithInWindowAnimations() { setSurfaceBehindAppearAmount(1f, wallpapers = false) try { @@ -662,10 +664,28 @@ class KeyguardUnlockAnimationController @Inject constructor( // Now that the Launcher surface (with its smartspace positioned identically to ours) is // visible, hide our smartspace. - lockscreenSmartspace?.visibility = View.INVISIBLE + if (lockscreenSmartspace?.visibility == View.VISIBLE) { + lockscreenSmartspace?.visibility = View.INVISIBLE + } + + // As soon as the shade has animated out of the way, start the canned unlock animation, + // which will finish keyguard exit when it completes. The in-window animations in the + // Launcher window will end on their own. + handler.postDelayed({ + if (keyguardViewMediator.get().isShowingAndNotOccluded && + !keyguardStateController.isKeyguardGoingAway) { + Log.e(TAG, "Finish keyguard exit animation delayed Runnable ran, but we are " + + "showing and not going away.") + return@postDelayed + } - // Start an animation for the wallpaper, which will finish keyguard exit when it completes. - fadeInWallpaper() + if (wallpaperTargets != null) { + fadeInWallpaper() + } else { + keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation( + false /* cancelled */) + } + }, CANNED_UNLOCK_START_DELAY) } /** @@ -914,7 +934,9 @@ class KeyguardUnlockAnimationController @Inject constructor( willUnlockWithSmartspaceTransition = false // The lockscreen surface is gone, so it is now safe to re-show the smartspace. - lockscreenSmartspace?.visibility = View.VISIBLE + if (lockscreenSmartspace?.visibility == View.INVISIBLE) { + lockscreenSmartspace?.visibility = View.VISIBLE + } listeners.forEach { it.onUnlockAnimationFinished() } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt index c8d37a165a0e..a8d662c96284 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt @@ -406,19 +406,21 @@ object KeyguardBottomAreaViewBinder { view.isClickable = viewModel.isClickable if (viewModel.isClickable) { if (viewModel.useLongPress) { - view.setOnTouchListener( - KeyguardQuickAffordanceOnTouchListener( - view, - viewModel, - messageDisplayer, - vibratorHelper, - falsingManager, - ) + val onTouchListener = KeyguardQuickAffordanceOnTouchListener( + view, + viewModel, + messageDisplayer, + vibratorHelper, + falsingManager, ) + view.setOnTouchListener(onTouchListener) + view.onLongClickListener = + OnLongClickListener(falsingManager, viewModel, vibratorHelper, onTouchListener) } else { view.setOnClickListener(OnClickListener(viewModel, checkNotNull(falsingManager))) } } else { + view.onLongClickListener = null view.setOnClickListener(null) view.setOnTouchListener(null) } @@ -454,6 +456,42 @@ object KeyguardBottomAreaViewBinder { .start() } + private class OnLongClickListener( + private val falsingManager: FalsingManager?, + private val viewModel: KeyguardQuickAffordanceViewModel, + private val vibratorHelper: VibratorHelper?, + private val onTouchListener: KeyguardQuickAffordanceOnTouchListener + ) : View.OnLongClickListener { + override fun onLongClick(view: View): Boolean { + if (falsingManager?.isFalseLongTap(FalsingManager.MODERATE_PENALTY) == true) { + return true + } + + if (viewModel.configKey != null) { + viewModel.onClicked( + KeyguardQuickAffordanceViewModel.OnClickedParameters( + configKey = viewModel.configKey, + expandable = Expandable.fromView(view), + slotId = viewModel.slotId, + ) + ) + vibratorHelper?.vibrate( + if (viewModel.isActivated) { + KeyguardBottomAreaVibrations.Activated + } else { + KeyguardBottomAreaVibrations.Deactivated + } + ) + } + + onTouchListener.cancel() + return true + } + + override fun onLongClickUseDefaultHapticFeedback(view: View?) = false + + } + private class OnClickListener( private val viewModel: KeyguardQuickAffordanceViewModel, private val falsingManager: FalsingManager, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceOnTouchListener.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceOnTouchListener.kt index 5745d6ae077e..7685345805f4 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceOnTouchListener.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceOnTouchListener.kt @@ -46,7 +46,7 @@ class KeyguardQuickAffordanceOnTouchListener( @SuppressLint("ClickableViewAccessibility") override fun onTouch(v: View, event: MotionEvent): Boolean { return when (event.actionMasked) { - MotionEvent.ACTION_DOWN -> + MotionEvent.ACTION_DOWN -> { if (viewModel.configKey != null) { downDisplayCoords.set(event.rawX, event.rawY) if (isUsingAccurateTool(event)) { @@ -62,21 +62,10 @@ class KeyguardQuickAffordanceOnTouchListener( .scaleX(PRESSED_SCALE) .scaleY(PRESSED_SCALE) .setDuration(longPressDurationMs) - .withEndAction { - if ( - falsingManager?.isFalseLongTap( - FalsingManager.MODERATE_PENALTY - ) == false - ) { - dispatchClick(viewModel.configKey) - } - cancel() - } } - true - } else { - false } + false + } MotionEvent.ACTION_MOVE -> { if (!isUsingAccurateTool(event)) { // Moving too far while performing a long-press gesture cancels that @@ -91,7 +80,7 @@ class KeyguardQuickAffordanceOnTouchListener( cancel() } } - true + false } MotionEvent.ACTION_UP -> { if (isUsingAccurateTool(event)) { @@ -146,7 +135,7 @@ class KeyguardQuickAffordanceOnTouchListener( } ) } - true + false } MotionEvent.ACTION_CANCEL -> { cancel() @@ -179,7 +168,7 @@ class KeyguardQuickAffordanceOnTouchListener( view.setOnClickListener(null) } - private fun cancel(onAnimationEnd: Runnable? = null) { + fun cancel(onAnimationEnd: Runnable? = null) { longPressAnimator?.cancel() longPressAnimator = null view.animate().scaleX(1f).scaleY(1f).withEndAction(onAnimationEnd) diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt index bce334610f28..6b993ce9e7bf 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt @@ -53,6 +53,7 @@ import android.text.TextUtils import android.util.Log import android.util.Pair as APair import androidx.media.utils.MediaConstants +import com.android.internal.annotations.Keep import com.android.internal.logging.InstanceId import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.Dumpable @@ -219,7 +220,7 @@ class MediaDataManager( private val mediaEntries: LinkedHashMap<String, MediaData> = LinkedHashMap() // There should ONLY be at most one Smartspace media recommendation. var smartspaceMediaData: SmartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA - private var smartspaceSession: SmartspaceSession? = null + @Keep private var smartspaceSession: SmartspaceSession? = null private var allowMediaRecommendations = allowMediaRecommendations(context) private val artworkWidth = @@ -381,6 +382,8 @@ class MediaDataManager( fun destroy() { smartspaceMediaDataProvider.unregisterListener(this) + smartspaceSession?.close() + smartspaceSession = null context.unregisterReceiver(appChangeReceiver) } diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt index 1fd11bd61700..77e2847cbe76 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt @@ -607,7 +607,7 @@ class BackPanelController internal constructor( ) } - private var previousPreThresholdWidthInterpolator = params.entryWidthTowardsEdgeInterpolator + private var previousPreThresholdWidthInterpolator = params.entryWidthInterpolator private fun preThresholdWidthStretchAmount(progress: Float): Float { val interpolator = run { val isPastSlop = totalTouchDeltaInactive > viewConfiguration.scaledTouchSlop diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt index 6d881d527ce4..9ddb78ae19ee 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt @@ -147,8 +147,21 @@ data class EdgePanelParams(private var resources: Resources) { val flungCommittedWidthSpring = createSpring(10000f, 1f) val flungCommittedHeightSpring = createSpring(10000f, 1f) - val entryIndicatorAlphaThreshold = .23f - val entryIndicatorAlphaFactor = 1.05f + val commonArrowDimensAlphaThreshold = .165f + val commonArrowDimensAlphaFactor = 1.05f + val commonArrowDimensAlphaSpring = Step( + threshold = commonArrowDimensAlphaThreshold, + factor = commonArrowDimensAlphaFactor, + postThreshold = createSpring(180f, 0.9f), + preThreshold = createSpring(2000f, 0.6f) + ) + val commonArrowDimensAlphaSpringInterpolator = Step( + threshold = commonArrowDimensAlphaThreshold, + factor = commonArrowDimensAlphaFactor, + postThreshold = 1f, + preThreshold = 0f + ) + entryIndicator = BackIndicatorDimens( horizontalTranslation = getDimen(R.dimen.navigation_edge_entry_margin), scale = getDimenFloat(R.dimen.navigation_edge_entry_scale), @@ -162,18 +175,8 @@ data class EdgePanelParams(private var resources: Resources) { alpha = 0f, lengthSpring = createSpring(600f, 0.4f), heightSpring = createSpring(600f, 0.4f), - alphaSpring = Step( - threshold = entryIndicatorAlphaThreshold, - factor = entryIndicatorAlphaFactor, - postThreshold = createSpring(200f, 1f), - preThreshold = createSpring(2000f, 0.6f) - ), - alphaInterpolator = Step( - threshold = entryIndicatorAlphaThreshold, - factor = entryIndicatorAlphaFactor, - postThreshold = 1f, - preThreshold = 0f - ) + alphaSpring = commonArrowDimensAlphaSpring, + alphaInterpolator = commonArrowDimensAlphaSpringInterpolator ), backgroundDimens = BackgroundDimens( alpha = 1f, @@ -188,20 +191,6 @@ data class EdgePanelParams(private var resources: Resources) { ) ) - val preThresholdAndActiveIndicatorAlphaThreshold = .355f - val preThresholdAndActiveIndicatorAlphaFactor = 1.05f - val preThresholdAndActiveAlphaSpring = Step( - threshold = preThresholdAndActiveIndicatorAlphaThreshold, - factor = preThresholdAndActiveIndicatorAlphaFactor, - postThreshold = createSpring(180f, 0.9f), - preThreshold = createSpring(2000f, 0.6f) - ) - val preThresholdAndActiveAlphaSpringInterpolator = Step( - threshold = preThresholdAndActiveIndicatorAlphaThreshold, - factor = preThresholdAndActiveIndicatorAlphaFactor, - postThreshold = 1f, - preThreshold = 0f - ) activeIndicator = BackIndicatorDimens( horizontalTranslation = getDimen(R.dimen.navigation_edge_active_margin), scale = getDimenFloat(R.dimen.navigation_edge_active_scale), @@ -214,8 +203,8 @@ data class EdgePanelParams(private var resources: Resources) { alpha = 1f, lengthSpring = activeCommittedArrowLengthSpring, heightSpring = activeCommittedArrowHeightSpring, - alphaSpring = preThresholdAndActiveAlphaSpring, - alphaInterpolator = preThresholdAndActiveAlphaSpringInterpolator + alphaSpring = commonArrowDimensAlphaSpring, + alphaInterpolator = commonArrowDimensAlphaSpringInterpolator ), backgroundDimens = BackgroundDimens( alpha = 1f, @@ -242,8 +231,8 @@ data class EdgePanelParams(private var resources: Resources) { alpha = 1f, lengthSpring = createSpring(100f, 0.6f), heightSpring = createSpring(100f, 0.6f), - alphaSpring = preThresholdAndActiveAlphaSpring, - alphaInterpolator = preThresholdAndActiveAlphaSpringInterpolator + alphaSpring = commonArrowDimensAlphaSpring, + alphaInterpolator = commonArrowDimensAlphaSpringInterpolator ), backgroundDimens = BackgroundDimens( alpha = 1f, diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 2f72cb95db98..419d045885a8 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -654,6 +654,24 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { } @Test + public void serviceProvidersUpdated_broadcastTriggersInfoRefresh() { + // The callback is invoked once on init + verify(mTestCallback, times(1)).onRefreshCarrierInfo(); + + // WHEN the SERVICE_PROVIDERS_UPDATED broadcast is sent + Intent intent = new Intent(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED); + intent.putExtra(TelephonyManager.EXTRA_SPN, "spn"); + intent.putExtra(TelephonyManager.EXTRA_PLMN, "plmn"); + mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(), + putPhoneInfo(intent, null, true)); + mTestableLooper.processAllMessages(); + + // THEN verify keyguardUpdateMonitorCallback receives a refresh callback + // Note that we have times(2) here because it's been called once already + verify(mTestCallback, times(2)).onRefreshCarrierInfo(); + } + + @Test public void testTriesToAuthenticateFingerprint_whenKeyguard() { mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */); mTestableLooper.processAllMessages(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt index 688c2db044e4..477e076669b7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt @@ -10,6 +10,7 @@ import android.testing.TestableLooper.RunWithLooper import android.view.RemoteAnimationTarget import android.view.SurfaceControl import android.view.SyncRtSurfaceTransactionApplier +import android.view.View import android.view.ViewRootImpl import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardViewController @@ -32,6 +33,7 @@ import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.atLeastOnce import org.mockito.Mockito.mock +import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions @@ -374,6 +376,83 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { verifyNoMoreInteractions(surfaceTransactionApplier) } + @Test + fun unlockToLauncherWithInWindowAnimations_ssViewIsVisible() { + val mockLockscreenSmartspaceView = mock(View::class.java) + whenever(mockLockscreenSmartspaceView.visibility).thenReturn(View.VISIBLE) + keyguardUnlockAnimationController.lockscreenSmartspace = mockLockscreenSmartspaceView + + keyguardUnlockAnimationController.unlockToLauncherWithInWindowAnimations() + + verify(mockLockscreenSmartspaceView).visibility = View.INVISIBLE + } + + @Test + fun unlockToLauncherWithInWindowAnimations_ssViewIsInvisible() { + val mockLockscreenSmartspaceView = mock(View::class.java) + whenever(mockLockscreenSmartspaceView.visibility).thenReturn(View.INVISIBLE) + keyguardUnlockAnimationController.lockscreenSmartspace = mockLockscreenSmartspaceView + + keyguardUnlockAnimationController.unlockToLauncherWithInWindowAnimations() + + verify(mockLockscreenSmartspaceView, never()).visibility = View.INVISIBLE + } + + @Test + fun unlockToLauncherWithInWindowAnimations_ssViewIsGone() { + val mockLockscreenSmartspaceView = mock(View::class.java) + whenever(mockLockscreenSmartspaceView.visibility).thenReturn(View.GONE) + keyguardUnlockAnimationController.lockscreenSmartspace = mockLockscreenSmartspaceView + + keyguardUnlockAnimationController.unlockToLauncherWithInWindowAnimations() + + verify(mockLockscreenSmartspaceView, never()).visibility = View.INVISIBLE + } + + @Test + fun notifyFinishedKeyguardExitAnimation_ssViewIsInvisibleAndCancelledIsTrue() { + val mockLockscreenSmartspaceView = mock(View::class.java) + whenever(mockLockscreenSmartspaceView.visibility).thenReturn(View.INVISIBLE) + keyguardUnlockAnimationController.lockscreenSmartspace = mockLockscreenSmartspaceView + + keyguardUnlockAnimationController.notifyFinishedKeyguardExitAnimation(true) + + verify(mockLockscreenSmartspaceView).visibility = View.VISIBLE + } + + @Test + fun notifyFinishedKeyguardExitAnimation_ssViewIsGoneAndCancelledIsTrue() { + val mockLockscreenSmartspaceView = mock(View::class.java) + whenever(mockLockscreenSmartspaceView.visibility).thenReturn(View.GONE) + keyguardUnlockAnimationController.lockscreenSmartspace = mockLockscreenSmartspaceView + + keyguardUnlockAnimationController.notifyFinishedKeyguardExitAnimation(true) + + verify(mockLockscreenSmartspaceView, never()).visibility = View.VISIBLE + } + + @Test + fun notifyFinishedKeyguardExitAnimation_ssViewIsInvisibleAndCancelledIsFalse() { + val mockLockscreenSmartspaceView = mock(View::class.java) + whenever(mockLockscreenSmartspaceView.visibility).thenReturn(View.INVISIBLE) + keyguardUnlockAnimationController.lockscreenSmartspace = mockLockscreenSmartspaceView + + keyguardUnlockAnimationController.notifyFinishedKeyguardExitAnimation(false) + + verify(mockLockscreenSmartspaceView).visibility = View.VISIBLE + } + + @Test + fun notifyFinishedKeyguardExitAnimation_ssViewIsGoneAndCancelledIsFalse() { + val mockLockscreenSmartspaceView = mock(View::class.java) + whenever(mockLockscreenSmartspaceView.visibility).thenReturn(View.GONE) + keyguardUnlockAnimationController.lockscreenSmartspace = mockLockscreenSmartspaceView + + keyguardUnlockAnimationController.notifyFinishedKeyguardExitAnimation(false) + + verify(mockLockscreenSmartspaceView, never()).visibility = View.VISIBLE + } + private class ArgThatCaptor<T> { private var allArgs: MutableList<T> = mutableListOf() diff --git a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java index f31ca8178eb6..c2ebddf00fb4 100644 --- a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java +++ b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java @@ -2057,7 +2057,11 @@ public class CameraExtensionsProxyService extends Service { mIsImageValid = false; if (mGraphicBuffer != null) { - ImageReader.unlockGraphicBuffer(mGraphicBuffer); + try { + ImageReader.unlockGraphicBuffer(mGraphicBuffer); + } catch (RuntimeException e) { + e.printStackTrace(); + } mGraphicBuffer.destroy(); mGraphicBuffer = null; } diff --git a/services/autofill/java/com/android/server/autofill/InlineSuggestionRendorInfoCallbackOnResultListener.java b/services/autofill/java/com/android/server/autofill/InlineSuggestionRendorInfoCallbackOnResultListener.java new file mode 100644 index 000000000000..7351ef59feca --- /dev/null +++ b/services/autofill/java/com/android/server/autofill/InlineSuggestionRendorInfoCallbackOnResultListener.java @@ -0,0 +1,65 @@ +/* + * 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.server.autofill; + +import android.annotation.Nullable; +import android.os.Bundle; +import android.os.RemoteCallback; +import android.util.Slog; +import android.view.autofill.AutofillId; +import android.view.inputmethod.InlineSuggestionsRequest; + +import java.lang.ref.WeakReference; +import java.util.function.Consumer; + +final class InlineSuggestionRendorInfoCallbackOnResultListener implements + RemoteCallback.OnResultListener{ + private static final String TAG = "InlineSuggestionRendorInfoCallbackOnResultListener"; + + private final int mRequestIdCopy; + private final AutofillId mFocusedId; + private final WeakReference<Session> mSessionWeakReference; + private final Consumer<InlineSuggestionsRequest> mInlineSuggestionsRequestConsumer; + + InlineSuggestionRendorInfoCallbackOnResultListener(WeakReference<Session> sessionWeakReference, + int requestIdCopy, + Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer, + AutofillId focusedId) { + this.mRequestIdCopy = requestIdCopy; + this.mInlineSuggestionsRequestConsumer = inlineSuggestionsRequestConsumer; + this.mSessionWeakReference = sessionWeakReference; + this.mFocusedId = focusedId; + } + public void onResult(@Nullable Bundle result) { + Session session = this.mSessionWeakReference.get(); + if (session == null) { + Slog.wtf(TAG, "Session is null before trying to call onResult"); + return; + } + synchronized (session.mLock) { + if (session.mDestroyed) { + Slog.wtf(TAG, "Session is destroyed before trying to call onResult"); + return; + } + session.mInlineSessionController.onCreateInlineSuggestionsRequestLocked( + this.mFocusedId, + session.inlineSuggestionsRequestCacheDecorator( + this.mInlineSuggestionsRequestConsumer, this.mRequestIdCopy), + result); + } + } +} diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 0a8f474fd4cc..44c50334649f 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -184,6 +184,7 @@ import com.android.server.wm.ActivityTaskManagerInternal; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -224,6 +225,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private static final String EXTRA_REQUEST_ID = "android.service.autofill.extra.REQUEST_ID"; private static final String PCC_HINTS_DELIMITER = ","; + public static final String EXTRA_KEY_DETECTIONS = "detections"; final Object mLock; @@ -321,7 +323,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState * Id of the View currently being displayed. */ @GuardedBy("mLock") - @Nullable private AutofillId mCurrentViewId; + @Nullable AutofillId mCurrentViewId; @GuardedBy("mLock") private IAutoFillManagerClient mClient; @@ -369,7 +371,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private Bundle mClientState; @GuardedBy("mLock") - private boolean mDestroyed; + boolean mDestroyed; /** * Helper used to handle state of Save UI when it must be hiding to show a custom description @@ -448,7 +450,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private ArrayList<AutofillId> mAugmentedAutofillableIds; @NonNull - private final AutofillInlineSessionController mInlineSessionController; + final AutofillInlineSessionController mInlineSessionController; /** * Receiver of assist data from the app's {@link Activity}. @@ -1224,24 +1226,30 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final RemoteInlineSuggestionRenderService remoteRenderService = mService.getRemoteInlineSuggestionRenderServiceLocked(); if (mSessionFlags.mInlineSupportedByService - && remoteRenderService != null - && (isViewFocusedLocked(flags) || isRequestSupportFillDialog(flags))) { + && remoteRenderService != null + && (isViewFocusedLocked(flags) || isRequestSupportFillDialog(flags))) { + Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer = mAssistReceiver.newAutofillRequestLocked(viewState, /* isInlineRequest= */ true); + if (inlineSuggestionsRequestConsumer != null) { - final AutofillId focusedId = mCurrentViewId; final int requestIdCopy = requestId; + final AutofillId focusedId = mCurrentViewId; + + WeakReference sessionWeakReference = new WeakReference<Session>(this); + InlineSuggestionRendorInfoCallbackOnResultListener + inlineSuggestionRendorInfoCallbackOnResultListener = + new InlineSuggestionRendorInfoCallbackOnResultListener( + sessionWeakReference, + requestIdCopy, + inlineSuggestionsRequestConsumer, + focusedId); + RemoteCallback inlineSuggestionRendorInfoCallback = new RemoteCallback( + inlineSuggestionRendorInfoCallbackOnResultListener, mHandler); + remoteRenderService.getInlineSuggestionsRendererInfo( - new RemoteCallback((extras) -> { - synchronized (mLock) { - mInlineSessionController.onCreateInlineSuggestionsRequestLocked( - focusedId, inlineSuggestionsRequestCacheDecorator( - inlineSuggestionsRequestConsumer, requestIdCopy), - extras); - } - }, mHandler) - ); + inlineSuggestionRendorInfoCallback); viewState.setState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST); } } else { @@ -3646,6 +3654,17 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final ArrayList<FillContext> contexts = mergePreviousSessionLocked( /* forSave= */ true); + FieldClassificationResponse fieldClassificationResponse = + mClassificationState.mLastFieldClassificationResponse; + if (mService.isPccClassificationEnabled() + && fieldClassificationResponse != null + && !fieldClassificationResponse.getClassifications().isEmpty()) { + if (mClientState == null) { + mClientState = new Bundle(); + } + mClientState.putParcelableArrayList(EXTRA_KEY_DETECTIONS, new ArrayList<>( + fieldClassificationResponse.getClassifications())); + } final SaveRequest saveRequest = new SaveRequest(contexts, mClientState, mSelectedDatasetIds); mRemoteFillService.onSaveRequest(saveRequest); @@ -5151,7 +5170,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } @NonNull - private Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestCacheDecorator( + Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestCacheDecorator( @NonNull Consumer<InlineSuggestionsRequest> consumer, int requestId) { return inlineSuggestionsRequest -> { consumer.accept(inlineSuggestionsRequest); diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 12bb5d23e4cf..76a994ec63e9 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -151,6 +151,8 @@ import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Objects; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; @@ -1707,7 +1709,8 @@ class UserController implements Handler.Callback { mInjector.getWindowManager().setSwitchingUser(true); // Only lock if the user has a secure keyguard PIN/Pattern/Pwd if (mInjector.getKeyguardManager().isDeviceSecure(userId)) { - mInjector.getWindowManager().lockNow(null); + // Make sure the device is locked before moving on with the user switch + mInjector.lockDeviceNowAndWaitForKeyguardShown(); } } @@ -3444,6 +3447,11 @@ class UserController implements Handler.Callback { WindowManagerService getWindowManager() { return mService.mWindowManager; } + + ActivityTaskManagerInternal getActivityTaskManagerInternal() { + return mService.mAtmInternal; + } + void activityManagerOnUserStopped(@UserIdInt int userId) { LocalServices.getService(ActivityTaskManagerInternal.class).onUserStopped(userId); } @@ -3667,5 +3675,43 @@ class UserController implements Handler.Callback { void onSystemUserVisibilityChanged(boolean visible) { getUserManagerInternal().onSystemUserVisibilityChanged(visible); } + + void lockDeviceNowAndWaitForKeyguardShown() { + if (getWindowManager().isKeyguardLocked()) { + return; + } + + final TimingsTraceAndSlog t = new TimingsTraceAndSlog(); + t.traceBegin("lockDeviceNowAndWaitForKeyguardShown"); + + final CountDownLatch latch = new CountDownLatch(1); + ActivityTaskManagerInternal.ScreenObserver screenObserver = + new ActivityTaskManagerInternal.ScreenObserver() { + @Override + public void onAwakeStateChanged(boolean isAwake) { + + } + + @Override + public void onKeyguardStateChanged(boolean isShowing) { + if (isShowing) { + latch.countDown(); + } + } + }; + + getActivityTaskManagerInternal().registerScreenObserver(screenObserver); + getWindowManager().lockDeviceNow(); + try { + if (!latch.await(20, TimeUnit.SECONDS)) { + throw new RuntimeException("Keyguard is not shown in 20 seconds"); + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } finally { + getActivityTaskManagerInternal().unregisterScreenObserver(screenObserver); + t.traceEnd(); + } + } } } diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 4208a12f91d4..d4bb445d66ac 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -3828,10 +3828,27 @@ public class Vpn { }, retryDelayMs, TimeUnit.MILLISECONDS); } + private boolean significantCapsChange(@Nullable final NetworkCapabilities left, + @Nullable final NetworkCapabilities right) { + if (left == right) return false; + return null == left + || null == right + || !Arrays.equals(left.getTransportTypes(), right.getTransportTypes()) + || !Arrays.equals(left.getCapabilities(), right.getCapabilities()) + || !Arrays.equals(left.getEnterpriseIds(), right.getEnterpriseIds()) + || !Objects.equals(left.getTransportInfo(), right.getTransportInfo()) + || !Objects.equals(left.getAllowedUids(), right.getAllowedUids()) + || !Objects.equals(left.getUnderlyingNetworks(), right.getUnderlyingNetworks()) + || !Objects.equals(left.getNetworkSpecifier(), right.getNetworkSpecifier()); + } + /** Called when the NetworkCapabilities of underlying network is changed */ public void onDefaultNetworkCapabilitiesChanged(@NonNull NetworkCapabilities nc) { - mEventChanges.log("[UnderlyingNW] Cap changed from " - + mUnderlyingNetworkCapabilities + " to " + nc); + if (significantCapsChange(mUnderlyingNetworkCapabilities, nc)) { + // TODO : make this log terser + mEventChanges.log("[UnderlyingNW] Cap changed from " + + mUnderlyingNetworkCapabilities + " to " + nc); + } final NetworkCapabilities oldNc = mUnderlyingNetworkCapabilities; mUnderlyingNetworkCapabilities = nc; if (oldNc == null || !nc.getSubscriptionIds().equals(oldNc.getSubscriptionIds())) { diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index be9df4aecf43..2c54e1cea3fa 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -4725,13 +4725,11 @@ public class HdmiControlService extends SystemService { Slog.w(TAG, "Tried to update eARC status on a port that doesn't support eARC."); return; } - // If eARC is disabled, the local device is null. In this case, the HAL shouldn't have - // reported connection state changes, but even if it did, it won't take effect. if (mEarcLocalDevice != null) { mEarcLocalDevice.handleEarcStateChange(status); } else if (status == HDMI_EARC_STATUS_ARC_PENDING) { - // If the local device is null we notify the Audio Service that eARC connection - // is disabled. + // If eARC is disabled, the local device is null. This is why we notify + // AudioService here that the eARC connection is terminated. notifyEarcStatusToAudioService(false, new ArrayList<>()); startArcAction(true, null); } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index d7eff52af9b4..a148de6848d0 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -6010,6 +6010,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @Override + @WindowManagerFuncs.LidState + public int getLidState() { + return mDefaultDisplayPolicy.getLidState(); + } + + @Override public void dumpDebug(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); proto.write(ROTATION_MODE, mDefaultDisplayRotation.getUserRotationMode()); diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index 887f9461bdce..3da78123016b 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -218,6 +218,14 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { * between it and the policy. */ public interface WindowManagerFuncs { + @IntDef(prefix = { "LID_" }, value = { + LID_ABSENT, + LID_CLOSED, + LID_OPEN, + }) + @Retention(RetentionPolicy.SOURCE) + @interface LidState{} + public static final int LID_ABSENT = -1; public static final int LID_CLOSED = 0; public static final int LID_OPEN = 1; @@ -231,8 +239,9 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { public static final int CAMERA_LENS_COVERED = 1; /** - * Returns a code that describes the current state of the lid switch. + * Returns a {@link LidState} that describes the current state of the lid switch. */ + @LidState public int getLidState(); /** @@ -282,7 +291,7 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { /** * Convert the lid state to a human readable format. */ - static String lidStateToString(int lid) { + static String lidStateToString(@LidState int lid) { switch (lid) { case LID_ABSENT: return "LID_ABSENT"; @@ -1241,4 +1250,11 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { * @return {@code true} if the key will be handled globally. */ boolean isGlobalKey(int keyCode); + + /** + * Returns a {@link WindowManagerFuncs.LidState} that describes the current state of + * the lid switch. + */ + @WindowManagerFuncs.LidState + int getLidState(); } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index b8c5b3f5524a..712be36e51c6 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -33,6 +33,7 @@ import static android.os.PowerManagerInternal.isInteractive; import static android.os.PowerManagerInternal.wakefulnessToString; import static com.android.internal.util.LatencyTracker.ACTION_TURN_ON_SCREEN; +import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED; import android.annotation.IntDef; import android.annotation.NonNull; @@ -5733,6 +5734,11 @@ public final class PowerManagerService extends SystemService @Override // Binder call public void wakeUp(long eventTime, @WakeReason int reason, String details, String opPackageName) { + if (mPolicy.getLidState() == LID_CLOSED) { + Slog.d(TAG, "Ignoring wake up call due to the lid being closed"); + return; + } + final long now = mClock.uptimeMillis(); if (eventTime > now) { Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now); diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java index e07c65426278..32f1f42aacb9 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java @@ -262,9 +262,17 @@ public abstract class ActivityTaskManagerInternal { */ public abstract void setVr2dDisplayId(int vr2dDisplayId); + /** + * Registers a {@link ScreenObserver}. + */ public abstract void registerScreenObserver(ScreenObserver observer); /** + * Unregisters the given {@link ScreenObserver}. + */ + public abstract void unregisterScreenObserver(ScreenObserver observer); + + /** * Returns is the caller has the same uid as the Recents component */ public abstract boolean isCallerRecents(int callingUid); diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 750ed986f567..4d4ffbafdcad 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -296,6 +296,7 @@ import java.text.DateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; @@ -652,7 +653,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { */ float mMinPercentageMultiWindowSupportWidth; - final List<ActivityTaskManagerInternal.ScreenObserver> mScreenObservers = new ArrayList<>(); + final List<ActivityTaskManagerInternal.ScreenObserver> mScreenObservers = + Collections.synchronizedList(new ArrayList<>()); // VR Vr2d Display Id. int mVr2dDisplayId = INVALID_DISPLAY; @@ -3649,6 +3651,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { Slog.e(TAG, "Skip enterPictureInPictureMode, destroyed " + r); return; } + EventLogTags.writeWmEnterPip(r.mUserId, System.identityHashCode(r), + r.shortComponentName, Boolean.toString(isAutoEnter)); r.setPictureInPictureParams(params); r.mAutoEnteringPip = isAutoEnter; mRootWindowContainer.moveActivityToPinnedRootTask(r, @@ -5867,6 +5871,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override + public void unregisterScreenObserver(ScreenObserver observer) { + mScreenObservers.remove(observer); + } + + @Override public boolean isCallerRecents(int callingUid) { return ActivityTaskManagerService.this.isCallerRecents(callingUid); } diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 77e70a25d497..46141f8e1b79 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -225,6 +225,7 @@ public class DisplayPolicy { /** Currently it can only be non-null when physical display switch happens. */ private DecorInsets.Cache mCachedDecorInsets; + @WindowManagerFuncs.LidState private volatile int mLidState = LID_ABSENT; private volatile int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED; private volatile boolean mHdmiPlugged; @@ -752,10 +753,11 @@ public class DisplayPolicy { return mNavigationBarCanMove; } - public void setLidState(int lidState) { + public void setLidState(@WindowManagerFuncs.LidState int lidState) { mLidState = lidState; } + @WindowManagerFuncs.LidState public int getLidState() { return mLidState; } diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 87de0f6e4aa0..bc1ddf8f66bc 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -513,6 +513,7 @@ public class DisplayRotation { } if (mDisplayContent.inTransition() + && mDisplayContent.getDisplayPolicy().isScreenOnFully() && !mDisplayContent.mTransitionController.useShellTransitionsRotation()) { // Rotation updates cannot be performed while the previous rotation change animation // is still in progress. Skip this update. We will try updating again after the diff --git a/services/core/java/com/android/server/wm/EventLogTags.logtags b/services/core/java/com/android/server/wm/EventLogTags.logtags index 244656ca68e6..d957591ab7f9 100644 --- a/services/core/java/com/android/server/wm/EventLogTags.logtags +++ b/services/core/java/com/android/server/wm/EventLogTags.logtags @@ -80,3 +80,6 @@ option java_package com.android.server.wm # Request surface flinger to show / hide the wallpaper surface. 33001 wm_wallpaper_surface (Display Id|1|5),(Visible|1),(Target|3) + +# Entering pip called +38000 wm_enter_pip (User|1|5),(Token|1|5),(Component Name|3),(is Auto Enter|3) diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java index ff2985c98421..e8a4c1c5c3d3 100644 --- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java @@ -91,6 +91,21 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider { } @Override + void setClientVisible(boolean clientVisible) { + final boolean wasClientVisible = isClientVisible(); + super.setClientVisible(clientVisible); + // The layer of ImePlaceholder needs to be updated on a higher z-order for + // non-activity window (For activity window, IME is already on top of it). + if (!wasClientVisible && isClientVisible()) { + final InsetsControlTarget imeControlTarget = getControlTarget(); + if (imeControlTarget != null && imeControlTarget.getWindow() != null + && imeControlTarget.getWindow().mActivityRecord == null) { + mDisplayContent.assignWindowLayers(false /* setLayoutNeeded */); + } + } + } + + @Override void setServerVisible(boolean serverVisible) { mServerVisible = serverVisible; if (!mFrozen) { diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 663db861b79e..d5a7ff582a58 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -687,7 +687,11 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { // All windows are synced already. return; } - if (!isInTransition(wc)) return; + if (wc.mDisplayContent == null || !isInTransition(wc)) return; + if (!wc.mDisplayContent.getDisplayPolicy().isScreenOnFully() + || wc.mDisplayContent.getDisplayInfo().state == Display.STATE_OFF) { + mFlags |= WindowManager.TRANSIT_FLAG_INVISIBLE; + } if (mContainerFreezer == null) { mContainerFreezer = new ScreenshotFreezer(); diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java index 317fd58e0c76..dccacb4d301a 100644 --- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java @@ -58,6 +58,7 @@ import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doCallRealMethod; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -103,11 +104,13 @@ import com.android.server.am.UserState.KeyEvictedCallback; import com.android.server.pm.UserJourneyLogger; import com.android.server.pm.UserManagerInternal; import com.android.server.pm.UserManagerService; +import com.android.server.wm.ActivityTaskManagerInternal; import com.android.server.wm.WindowManagerService; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentCaptor; import java.util.ArrayList; import java.util.Arrays; @@ -187,6 +190,7 @@ public class UserControllerTest { doNothing().when(mInjector).activityManagerOnUserStopped(anyInt()); doNothing().when(mInjector).clearBroadcastQueueForUser(anyInt()); doNothing().when(mInjector).taskSupervisorRemoveUser(anyInt()); + doNothing().when(mInjector).lockDeviceNowAndWaitForKeyguardShown(); mockIsUsersOnSecondaryDisplaysEnabled(false); // All UserController params are set to default. @@ -951,6 +955,45 @@ public class UserControllerTest { .systemServiceManagerOnUserCompletedEvent(eq(user2), eq(event2a)); } + @Test + public void testStallUserSwitchUntilTheKeyguardIsShown() throws Exception { + // enable user switch ui, because keyguard is only shown then + mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true, + /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false); + + // mock the device to be secure in order to expect the keyguard to be shown + when(mInjector.mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(true); + + // call real lockDeviceNowAndWaitForKeyguardShown method for this test + doCallRealMethod().when(mInjector).lockDeviceNowAndWaitForKeyguardShown(); + + // call startUser on a thread because we're expecting it to be blocked + Thread threadStartUser = new Thread(()-> { + mUserController.startUser(TEST_USER_ID, USER_START_MODE_FOREGROUND); + }); + threadStartUser.start(); + + // make sure the switch is stalled... + Thread.sleep(2000); + // by checking REPORT_USER_SWITCH_MSG is not sent yet + assertNull(mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG)); + // and the thread is still alive + assertTrue(threadStartUser.isAlive()); + + // mock send the keyguard shown event + ArgumentCaptor<ActivityTaskManagerInternal.ScreenObserver> captor = ArgumentCaptor.forClass( + ActivityTaskManagerInternal.ScreenObserver.class); + verify(mInjector.mActivityTaskManagerInternal).registerScreenObserver(captor.capture()); + captor.getValue().onKeyguardStateChanged(true); + + // verify the switch now moves on... + Thread.sleep(1000); + // by checking REPORT_USER_SWITCH_MSG is sent + assertNotNull(mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG)); + // and the thread is finished + assertFalse(threadStartUser.isAlive()); + } + private void setUpAndStartUserInBackground(int userId) throws Exception { setUpUser(userId, 0); mUserController.startUser(userId, USER_START_MODE_BACKGROUND); @@ -1092,6 +1135,7 @@ public class UserControllerTest { private final IStorageManager mStorageManagerMock; private final UserManagerInternal mUserManagerInternalMock; private final WindowManagerService mWindowManagerMock; + private final ActivityTaskManagerInternal mActivityTaskManagerInternal; private final KeyguardManager mKeyguardManagerMock; private final LockPatternUtils mLockPatternUtilsMock; @@ -1111,6 +1155,7 @@ public class UserControllerTest { mUserManagerMock = mock(UserManagerService.class); mUserManagerInternalMock = mock(UserManagerInternal.class); mWindowManagerMock = mock(WindowManagerService.class); + mActivityTaskManagerInternal = mock(ActivityTaskManagerInternal.class); mStorageManagerMock = mock(IStorageManager.class); mKeyguardManagerMock = mock(KeyguardManager.class); when(mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(true); @@ -1172,6 +1217,11 @@ public class UserControllerTest { } @Override + ActivityTaskManagerInternal getActivityTaskManagerInternal() { + return mActivityTaskManagerInternal; + } + + @Override KeyguardManager getKeyguardManager() { return mKeyguardManagerMock; } diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java index 933f00231313..7aec04568e0f 100644 --- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java @@ -26,6 +26,9 @@ import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE; import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING; import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING; +import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT; +import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED; + import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertFalse; @@ -145,6 +148,7 @@ public class PowerManagerServiceTest { @Mock private ActivityManagerInternal mActivityManagerInternalMock; @Mock private AttentionManagerInternal mAttentionManagerInternalMock; @Mock private DreamManagerInternal mDreamManagerInternalMock; + @Mock private WindowManagerPolicy mPolicyMock; @Mock private PowerManagerService.NativeWrapper mNativeWrapperMock; @Mock private Notifier mNotifierMock; @Mock private WirelessChargerDetector mWirelessChargerDetectorMock; @@ -205,6 +209,7 @@ public class PowerManagerServiceTest { .thenReturn(true); when(mSystemPropertiesMock.get(eq(SYSTEM_PROPERTY_QUIESCENT), anyString())).thenReturn(""); when(mAmbientDisplayConfigurationMock.ambientDisplayAvailable()).thenReturn(true); + when(mPolicyMock.getLidState()).thenReturn(LID_ABSENT); addLocalServiceMock(LightsManager.class, mLightsManagerMock); addLocalServiceMock(DisplayManagerInternal.class, mDisplayManagerInternalMock); @@ -212,6 +217,7 @@ public class PowerManagerServiceTest { addLocalServiceMock(ActivityManagerInternal.class, mActivityManagerInternalMock); addLocalServiceMock(AttentionManagerInternal.class, mAttentionManagerInternalMock); addLocalServiceMock(DreamManagerInternal.class, mDreamManagerInternalMock); + addLocalServiceMock(WindowManagerPolicy.class, mPolicyMock); mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext())); mResourcesSpy = spy(mContextSpy.getResources()); @@ -678,6 +684,20 @@ public class PowerManagerServiceTest { assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); } + @Test + public void testWakefulnessAwake_ShouldNotWakeUpWhenLidClosed() { + when(mPolicyMock.getLidState()).thenReturn(LID_CLOSED); + createService(); + startSystem(); + forceSleep(); + + mService.getBinderServiceInstance().wakeUp(mClock.now(), + PowerManager.WAKE_REASON_POWER_BUTTON, + "testing IPowerManager.wakeUp()", "pkg.name"); + + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + } + /** * Tests a series of variants that control whether a device wakes-up when it is plugged in * or docked. diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java index d1d83f62934d..d7e736df064b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java @@ -25,6 +25,7 @@ import static android.view.WindowInsets.Type.navigationBars; import static android.view.WindowInsets.Type.statusBars; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; +import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; @@ -38,6 +39,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.spy; @@ -420,10 +422,10 @@ public class InsetsStateControllerTest extends WindowTestsBase { @Test public void testUpdateAboveInsetsState_zOrderChanged() { - final WindowState ime = createTestWindow("ime"); - final WindowState app = createTestWindow("app"); - final WindowState statusBar = createTestWindow("statusBar"); - final WindowState navBar = createTestWindow("navBar"); + final WindowState ime = createNonAppWindow("ime"); + final WindowState app = createNonAppWindow("app"); + final WindowState statusBar = createNonAppWindow("statusBar"); + final WindowState navBar = createNonAppWindow("navBar"); final InsetsSourceProvider imeSourceProvider = getController().getOrCreateSourceProvider(ID_IME, ime()); @@ -431,7 +433,9 @@ public class InsetsStateControllerTest extends WindowTestsBase { waitUntilHandlersIdle(); clearInvocations(mDisplayContent); + imeSourceProvider.updateControlForTarget(app, false /* force */); imeSourceProvider.setClientVisible(true); + verify(mDisplayContent).assignWindowLayers(anyBoolean()); waitUntilHandlersIdle(); // The visibility change should trigger a traversal to notify the change. verify(mDisplayContent).notifyInsetsChanged(any()); @@ -547,6 +551,7 @@ public class InsetsStateControllerTest extends WindowTestsBase { control2.getInsetsHint().bottom); } + /** Creates a window which is associated with ActivityRecord. */ private WindowState createTestWindow(String name) { final WindowState win = createWindow(null, TYPE_APPLICATION, name); win.setHasSurface(true); @@ -554,6 +559,14 @@ public class InsetsStateControllerTest extends WindowTestsBase { return win; } + /** Creates a non-activity window. */ + private WindowState createNonAppWindow(String name) { + final WindowState win = createWindow(null, LAST_APPLICATION_WINDOW + 1, name); + win.setHasSurface(true); + spyOn(win); + return win; + } + private InsetsStateController getController() { return mDisplayContent.getInsetsStateController(); } diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java index adf3f3976f38..192632ce0277 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -18,6 +18,8 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; +import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT; + import android.annotation.Nullable; import android.content.Context; import android.content.res.Configuration; @@ -354,4 +356,9 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { public boolean isGlobalKey(int keyCode) { return false; } + + @Override + public int getLidState() { + return LID_ABSENT; + } } diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt index 7f496d828996..122a6cbbb98f 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt @@ -17,6 +17,7 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.Rotation import android.tools.common.traces.component.ComponentNameMatcher @@ -102,6 +103,7 @@ open class CloseImeOnGoHomeTest(flicker: FlickerTest) : BaseTest(flicker) { @Presubmit @Test + @PlatinumTest(focusArea = "ime") @IwTest(focusArea = "ime") override fun cujCompleted() { super.cujCompleted() diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt index c693ca759bdd..5aa43820e5cb 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt @@ -17,6 +17,7 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -103,6 +104,7 @@ open class CloseImeToAppOnPressBackTest(flicker: FlickerTest) : BaseTest(flicker @Presubmit @Test + @PlatinumTest(focusArea = "ime") @IwTest(focusArea = "ime") override fun cujCompleted() { super.cujCompleted() diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt index d5208e060883..6731089f8903 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt @@ -18,6 +18,7 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.FlakyTest import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.Rotation import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -71,6 +72,7 @@ open class CloseImeToHomeOnFinishActivityTest(flicker: FlickerTest) : BaseTest(f @Presubmit @Test + @PlatinumTest(focusArea = "ime") @IwTest(focusArea = "ime") override fun cujCompleted() { runAndIgnoreAssumptionViolation { entireScreenCovered() } diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt index d1335294f629..c70e3cb773d4 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt @@ -17,6 +17,7 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.Rotation import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -52,6 +53,7 @@ open class ShowImeWhenFocusingOnInputFieldTest(flicker: FlickerTest) : BaseTest( @Presubmit @Test + @PlatinumTest(focusArea = "ime") @IwTest(focusArea = "ime") override fun cujCompleted() { super.cujCompleted() diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt index 855ea3e38b3e..7fbcfec40121 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt @@ -17,6 +17,7 @@ package com.android.server.wm.flicker.rotation import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.traces.component.ComponentNameMatcher import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -129,6 +130,7 @@ open class ChangeAppRotationTest(flicker: FlickerTest) : RotationTransition(flic } @Test + @PlatinumTest(focusArea = "framework") @IwTest(focusArea = "framework") override fun cujCompleted() { super.cujCompleted() diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt index 0cbbb83b48ee..44ae14a8e4bb 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt @@ -17,6 +17,7 @@ package com.android.server.wm.flicker.rotation import android.platform.test.annotations.IwTest +import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.ScenarioBuilder import android.tools.common.traces.component.ComponentNameMatcher @@ -213,6 +214,7 @@ open class SeamlessAppRotationTest(flicker: FlickerTest) : RotationTransition(fl } @Test + @PlatinumTest(focusArea = "framework") @IwTest(focusArea = "framework") override fun cujCompleted() { appWindowFullScreen() |