summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/Notification.java46
-rw-r--r--core/java/android/app/Person.java14
-rw-r--r--core/java/android/app/ServiceStartArgs.java2
-rw-r--r--core/java/android/app/WallpaperInfo.java8
-rw-r--r--core/java/android/hardware/lights/Light.java30
-rw-r--r--core/java/android/view/SurfaceControl.java14
-rw-r--r--core/java/android/view/SurfaceControlViewHost.java3
-rw-r--r--core/java/android/view/WindowManager.java10
-rw-r--r--core/java/com/android/internal/jank/InteractionJankMonitor.java22
-rw-r--r--core/proto/android/input/keyboard_configured.proto50
-rw-r--r--core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java4
-rw-r--r--core/tests/coretests/src/android/view/SurfaceControlRegistryTests.java12
-rw-r--r--graphics/java/android/graphics/GraphicBuffer.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java20
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt21
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java61
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java64
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java13
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByDividerBenchmark.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByGoHomeBenchmark.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DragDividerToResizeBenchmark.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromAllAppsBenchmark.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromNotificationBenchmark.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromShortcutBenchmark.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromTaskbarBenchmark.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenFromOverviewBenchmark.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromAnotherAppBenchmark.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromHomeBenchmark.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromRecentBenchmark.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBetweenSplitPairsBenchmark.kt2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java4
-rw-r--r--media/jni/android_media_ImageReader.cpp1
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt31
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt11
-rw-r--r--packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt19
-rw-r--r--packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt5
-rw-r--r--packages/SystemUI/res/layout/screen_share_dialog.xml2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java13
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java15
-rw-r--r--packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java124
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java44
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java54
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt54
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceOnTouchListener.kt23
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java73
-rw-r--r--packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java6
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java12
-rw-r--r--services/core/java/com/android/server/am/UserController.java48
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java8
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java21
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java6
-rw-r--r--services/core/java/com/android/server/input/InputFeatureFlagProvider.java17
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java4
-rw-r--r--services/core/java/com/android/server/input/KeyboardBacklightController.java72
-rw-r--r--services/core/java/com/android/server/input/KeyboardLayoutManager.java2
-rw-r--r--services/core/java/com/android/server/input/KeyboardMetricsCollector.java121
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java8
-rw-r--r--services/core/java/com/android/server/policy/WindowManagerPolicy.java20
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java6
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java9
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java8
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java9
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java16
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotation.java1
-rw-r--r--services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java15
-rw-r--r--services/core/java/com/android/server/wm/KeyguardController.java40
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java5
-rw-r--r--services/core/java/com/android/server/wm/Transition.java8
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp16
-rw-r--r--services/tests/servicestests/src/com/android/server/am/UserControllerTest.java50
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt252
-rw-r--r--services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java20
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java21
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java7
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt2
98 files changed, 1488 insertions, 371 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 2eb6ca758970..8d2394b20438 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2833,12 +2833,14 @@ public class Notification implements Parcelable
}
/**
- * Note all {@link Uri} that are referenced internally, with the expectation
- * that Uri permission grants will need to be issued to ensure the recipient
- * of this object is able to render its contents.
- *
- * @hide
- */
+ * Note all {@link Uri} that are referenced internally, with the expectation that Uri permission
+ * grants will need to be issued to ensure the recipient of this object is able to render its
+ * contents.
+ * See b/281044385 for more context and examples about what happens when this isn't done
+ * correctly.
+ *
+ * @hide
+ */
public void visitUris(@NonNull Consumer<Uri> visitor) {
if (publicVersion != null) {
publicVersion.visitUris(visitor);
@@ -2882,13 +2884,13 @@ public class Notification implements Parcelable
ArrayList<Person> people = extras.getParcelableArrayList(EXTRA_PEOPLE_LIST, android.app.Person.class);
if (people != null && !people.isEmpty()) {
for (Person p : people) {
- visitor.accept(p.getIconUri());
+ p.visitUris(visitor);
}
}
final Person person = extras.getParcelable(EXTRA_MESSAGING_PERSON, Person.class);
if (person != null) {
- visitor.accept(person.getIconUri());
+ person.visitUris(visitor);
}
final RemoteInputHistoryItem[] history = extras.getParcelableArray(
@@ -2910,12 +2912,7 @@ public class Notification implements Parcelable
if (!ArrayUtils.isEmpty(messages)) {
for (MessagingStyle.Message message : MessagingStyle.Message
.getMessagesFromBundleArray(messages)) {
- visitor.accept(message.getDataUri());
-
- Person senderPerson = message.getSenderPerson();
- if (senderPerson != null) {
- visitor.accept(senderPerson.getIconUri());
- }
+ message.visitUris(visitor);
}
}
@@ -2924,12 +2921,7 @@ public class Notification implements Parcelable
if (!ArrayUtils.isEmpty(historic)) {
for (MessagingStyle.Message message : MessagingStyle.Message
.getMessagesFromBundleArray(historic)) {
- visitor.accept(message.getDataUri());
-
- Person senderPerson = message.getSenderPerson();
- if (senderPerson != null) {
- visitor.accept(senderPerson.getIconUri());
- }
+ message.visitUris(visitor);
}
}
@@ -2939,7 +2931,7 @@ public class Notification implements Parcelable
if (isStyle(CallStyle.class) & extras != null) {
Person callPerson = extras.getParcelable(EXTRA_CALL_PERSON, Person.class);
if (callPerson != null) {
- visitor.accept(callPerson.getIconUri());
+ callPerson.visitUris(visitor);
}
visitIconUri(visitor, extras.getParcelable(EXTRA_VERIFICATION_ICON, Icon.class));
}
@@ -8833,6 +8825,18 @@ public class Notification implements Parcelable
}
/**
+ * See {@link Notification#visitUris(Consumer)}.
+ *
+ * @hide
+ */
+ public void visitUris(@NonNull Consumer<Uri> visitor) {
+ visitor.accept(getDataUri());
+ if (mSender != null) {
+ mSender.visitUris(visitor);
+ }
+ }
+
+ /**
* Returns a list of messages read from the given bundle list, e.g.
* {@link #EXTRA_MESSAGES} or {@link #EXTRA_HISTORIC_MESSAGES}.
*/
diff --git a/core/java/android/app/Person.java b/core/java/android/app/Person.java
index 97a794d4e4ea..18fc0ce6af15 100644
--- a/core/java/android/app/Person.java
+++ b/core/java/android/app/Person.java
@@ -24,6 +24,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import java.util.Objects;
+import java.util.function.Consumer;
/**
* Provides an immutable reference to an entity that appears repeatedly on different surfaces of the
@@ -177,6 +178,19 @@ public final class Person implements Parcelable {
dest.writeBoolean(mIsBot);
}
+ /**
+ * Note all {@link Uri} that are referenced internally, with the expectation that Uri permission
+ * grants will need to be issued to ensure the recipient of this object is able to render its
+ * contents.
+ * See b/281044385 for more context and examples about what happens when this isn't done
+ * correctly.
+ *
+ * @hide
+ */
+ public void visitUris(@NonNull Consumer<Uri> visitor) {
+ visitor.accept(getIconUri());
+ }
+
/** Builder for the immutable {@link Person} class. */
public static class Builder {
@Nullable private CharSequence mName;
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/hardware/lights/Light.java b/core/java/android/hardware/lights/Light.java
index 1df9b75f0b09..18d0b09faa14 100644
--- a/core/java/android/hardware/lights/Light.java
+++ b/core/java/android/hardware/lights/Light.java
@@ -110,6 +110,8 @@ public final class Light implements Parcelable {
private final int mOrdinal;
private final int mType;
private final int mCapabilities;
+ @Nullable
+ private final int[] mPreferredBrightnessLevels;
/**
* Creates a new light with the given data.
@@ -117,7 +119,7 @@ public final class Light implements Parcelable {
* @hide
*/
public Light(int id, int ordinal, int type) {
- this(id, "Light", ordinal, type, 0);
+ this(id, "Light", ordinal, type, 0, null);
}
/**
@@ -126,11 +128,22 @@ public final class Light implements Parcelable {
* @hide
*/
public Light(int id, String name, int ordinal, int type, int capabilities) {
+ this(id, name, ordinal, type, capabilities, null);
+ }
+
+ /**
+ * Creates a new light with the given data.
+ *
+ * @hide
+ */
+ public Light(int id, String name, int ordinal, int type, int capabilities,
+ @Nullable int[] preferredBrightnessLevels) {
mId = id;
mName = name;
mOrdinal = ordinal;
mType = type;
mCapabilities = capabilities;
+ mPreferredBrightnessLevels = preferredBrightnessLevels;
}
private Light(@NonNull Parcel in) {
@@ -139,6 +152,7 @@ public final class Light implements Parcelable {
mOrdinal = in.readInt();
mType = in.readInt();
mCapabilities = in.readInt();
+ mPreferredBrightnessLevels = in.createIntArray();
}
/** Implement the Parcelable interface */
@@ -149,6 +163,7 @@ public final class Light implements Parcelable {
dest.writeInt(mOrdinal);
dest.writeInt(mType);
dest.writeInt(mCapabilities);
+ dest.writeIntArray(mPreferredBrightnessLevels);
}
/** Implement the Parcelable interface */
@@ -252,4 +267,17 @@ public final class Light implements Parcelable {
return (mCapabilities & LIGHT_CAPABILITY_COLOR_RGB) == LIGHT_CAPABILITY_COLOR_RGB;
}
+ /**
+ * Returns preferred brightness levels for the light which will be used when user
+ * increase/decrease brightness levels for the light (currently only used for Keyboard
+ * backlight control using backlight up/down keys).
+ *
+ * The values in the preferred brightness level array are in the range [0, 255].
+ *
+ * @hide
+ */
+ @Nullable
+ public int[] getPreferredBrightnessLevels() {
+ return mPreferredBrightnessLevels;
+ }
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index ddaa71c6b1b5..c11f4975149d 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -786,7 +786,11 @@ public final class SurfaceControl implements Parcelable {
mReleaseStack = null;
}
setUnreleasedWarningCallSite(callsite);
- addToRegistry();
+ if (nativeObject != 0) {
+ // Only add valid surface controls to the registry. This is called at the end of this
+ // method since its information is dumped if the process threshold is reached.
+ addToRegistry();
+ }
}
/**
@@ -893,6 +897,10 @@ public final class SurfaceControl implements Parcelable {
"Only buffer layers can set a valid buffer size.");
}
+ if (mName == null) {
+ Log.w(TAG, "Missing name for SurfaceControl", new Throwable());
+ }
+
if ((mFlags & FX_SURFACE_MASK) == FX_SURFACE_NORMAL) {
setBLASTLayer();
}
@@ -1254,6 +1262,9 @@ public final class SurfaceControl implements Parcelable {
}
/**
+ * Note: Most callers should use {@link SurfaceControl.Builder} or one of the other constructors
+ * to build an instance of a SurfaceControl. This constructor is mainly used for
+ * unparceling and passing into an AIDL call as an out parameter.
* @hide
*/
public SurfaceControl() {
@@ -2495,6 +2506,7 @@ public final class SurfaceControl implements Parcelable {
public static SurfaceControl mirrorSurface(SurfaceControl mirrorOf) {
long nativeObj = nativeMirrorSurface(mirrorOf.mNativeObject);
SurfaceControl sc = new SurfaceControl();
+ sc.mName = mirrorOf.mName + " (mirror)";
sc.assignNativeObject(nativeObj, "mirrorSurface");
return sc;
}
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index d9872174f9be..c8cf7d9a5194 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -171,8 +171,7 @@ public class SurfaceControlViewHost {
public SurfacePackage(@NonNull SurfacePackage other) {
SurfaceControl otherSurfaceControl = other.mSurfaceControl;
if (otherSurfaceControl != null && otherSurfaceControl.isValid()) {
- mSurfaceControl = new SurfaceControl();
- mSurfaceControl.copyFrom(otherSurfaceControl, "SurfacePackage");
+ mSurfaceControl = new SurfaceControl(otherSurfaceControl, "SurfacePackage");
}
mAccessibilityEmbeddedConnection = other.mAccessibilityEmbeddedConnection;
mInputToken = other.mInputToken;
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 0e72ea8622e2..d40c032eb21c 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/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index e530aec2119a..869b69611eba 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -28,6 +28,7 @@ import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_IN
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_ANIMATION;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_ALL_APPS_SCROLL;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_PIP;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_ICON;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_RECENTS;
@@ -258,8 +259,16 @@ public class InteractionJankMonitor {
public static final int CUJ_IME_INSETS_ANIMATION = 69;
public static final int CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION = 70;
public static final int CUJ_LAUNCHER_OPEN_SEARCH_RESULT = 71;
+ // 72 - 77 are reserved for b/281564325.
- private static final int LAST_CUJ = CUJ_LAUNCHER_OPEN_SEARCH_RESULT;
+ /**
+ * In some cases when we do not have any end-target, we play a simple slide-down animation.
+ * eg: Open an app from Overview/Task switcher such that there is no home-screen icon.
+ * eg: Exit the app using back gesture.
+ */
+ public static final int CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK = 78;
+
+ private static final int LAST_CUJ = CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK;
private static final int NO_STATSD_LOGGING = -1;
// Used to convert CujType to InteractionType enum value for statsd logging.
@@ -340,6 +349,14 @@ public class InteractionJankMonitor {
CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_IME_INSETS_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_ANIMATION;
CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_CLOCK_MOVE_ANIMATION;
CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_OPEN_SEARCH_RESULT] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_SEARCH_RESULT;
+ // 72 - 77 are reserved for b/281564325.
+ CUJ_TO_STATSD_INTERACTION_TYPE[72] = NO_STATSD_LOGGING;
+ CUJ_TO_STATSD_INTERACTION_TYPE[73] = NO_STATSD_LOGGING;
+ CUJ_TO_STATSD_INTERACTION_TYPE[74] = NO_STATSD_LOGGING;
+ CUJ_TO_STATSD_INTERACTION_TYPE[75] = NO_STATSD_LOGGING;
+ CUJ_TO_STATSD_INTERACTION_TYPE[76] = NO_STATSD_LOGGING;
+ CUJ_TO_STATSD_INTERACTION_TYPE[77] = NO_STATSD_LOGGING;
+ CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK;
}
private static class InstanceHolder {
@@ -439,6 +456,7 @@ public class InteractionJankMonitor {
CUJ_IME_INSETS_ANIMATION,
CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION,
CUJ_LAUNCHER_OPEN_SEARCH_RESULT,
+ CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK,
})
@Retention(RetentionPolicy.SOURCE)
public @interface CujType {
@@ -1050,6 +1068,8 @@ public class InteractionJankMonitor {
return "LOCKSCREEN_CLOCK_MOVE_ANIMATION";
case CUJ_LAUNCHER_OPEN_SEARCH_RESULT:
return "LAUNCHER_OPEN_SEARCH_RESULT";
+ case CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK:
+ return "LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK";
}
return "UNKNOWN";
}
diff --git a/core/proto/android/input/keyboard_configured.proto b/core/proto/android/input/keyboard_configured.proto
new file mode 100644
index 000000000000..16990087b319
--- /dev/null
+++ b/core/proto/android/input/keyboard_configured.proto
@@ -0,0 +1,50 @@
+/*
+ * Copyright 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.
+ */
+
+syntax = "proto2";
+
+package com.android.internal.os;
+
+option java_outer_classname = "KeyboardConfiguredProto";
+
+/**
+ * RepeatedKeyboardLayout proto from input_extension_atoms.proto,
+ * duplicated here so that it's accessible in the build.
+ * Must be kept in sync with the version in input_extension_atoms.proto.
+ */
+
+// Message containing the repeated field for KeyboardLayoutConfig
+message RepeatedKeyboardLayoutConfig {
+ repeated KeyboardLayoutConfig keyboard_layout_config = 1;
+}
+
+// Keyboard layout configured when the device is connected
+// used in KeyboardConfigured atom
+message KeyboardLayoutConfig {
+ // Keyboard configuration details
+ // Layout type mappings found at:
+ // frameworks/base/core/res/res/values/attrs.xml
+ optional int32 keyboard_layout_type = 1;
+ // PK language language tag (e.g. en-US, ru-Cyrl, etc). This will follow
+ // BCP-47 language tag standards.
+ optional string keyboard_language_tag = 2;
+ // Selected keyboard layout name (e.g. English(US), English(Dvorak), etc.)
+ optional string keyboard_layout_name = 3;
+ // Criteria for layout selection (such as user, device, virtual keyboard based)
+ // IntDef annotation at:
+ // services/core/java/com/android/server/input/KeyboardMetricsCollector.java
+ optional int32 layout_selection_criteria = 4;
+}
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/core/tests/coretests/src/android/view/SurfaceControlRegistryTests.java b/core/tests/coretests/src/android/view/SurfaceControlRegistryTests.java
index d10ba7ccbac4..e117051ba9de 100644
--- a/core/tests/coretests/src/android/view/SurfaceControlRegistryTests.java
+++ b/core/tests/coretests/src/android/view/SurfaceControlRegistryTests.java
@@ -104,6 +104,18 @@ public class SurfaceControlRegistryTests {
}
@Test
+ public void testInvalidSurfaceControlNotAddedToRegistry() {
+ int hash0 = SurfaceControlRegistry.getProcessInstance().hashCode();
+ // Verify no changes to the registry when dealing with invalid surface controls
+ SurfaceControl sc0 = new SurfaceControl();
+ SurfaceControl sc1 = new SurfaceControl(sc0, "test");
+ assertEquals(hash0, SurfaceControlRegistry.getProcessInstance().hashCode());
+ sc0.release();
+ sc1.release();
+ assertEquals(hash0, SurfaceControlRegistry.getProcessInstance().hashCode());
+ }
+
+ @Test
public void testThresholds() {
SurfaceControlRegistry registry = SurfaceControlRegistry.getProcessInstance();
TestReporter reporter = new TestReporter();
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/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index bc0b71c97346..2dbccaceeddc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -542,9 +542,12 @@ public abstract class WMShellModule {
Optional<PipTouchHandler> pipTouchHandlerOptional,
Optional<RecentsTransitionHandler> recentsTransitionHandler,
KeyguardTransitionHandler keyguardTransitionHandler,
+ Optional<DesktopModeController> desktopModeController,
+ Optional<DesktopTasksController> desktopTasksController,
Transitions transitions) {
return new DefaultMixedHandler(shellInit, transitions, splitScreenOptional,
- pipTouchHandlerOptional, recentsTransitionHandler, keyguardTransitionHandler);
+ pipTouchHandlerOptional, recentsTransitionHandler, keyguardTransitionHandler,
+ desktopModeController, desktopTasksController);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
index 1169af9306b0..705b35235193 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
@@ -33,6 +33,7 @@ import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DE
import android.app.ActivityManager.RunningTaskInfo;
import android.app.WindowConfiguration;
import android.content.Context;
+import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.graphics.Region;
import android.net.Uri;
@@ -414,6 +415,25 @@ public class DesktopModeController implements RemoteCallable<DesktopModeControll
}
/**
+ * Applies the proper surface states (rounded corners) to tasks when desktop mode is active.
+ * This is intended to be used when desktop mode is part of another animation but isn't, itself,
+ * animating.
+ */
+ public void syncSurfaceState(@NonNull TransitionInfo info,
+ SurfaceControl.Transaction finishTransaction) {
+ // Add rounded corners to freeform windows
+ final TypedArray ta = mContext.obtainStyledAttributes(
+ new int[]{android.R.attr.dialogCornerRadius});
+ final int cornerRadius = ta.getDimensionPixelSize(0, 0);
+ ta.recycle();
+ for (TransitionInfo.Change change: info.getChanges()) {
+ if (change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_FREEFORM) {
+ finishTransaction.setCornerRadius(change.getLeash(), cornerRadius);
+ }
+ }
+ }
+
+ /**
* A {@link ContentObserver} for listening to changes to {@link Settings.System#DESKTOP_MODE}
*/
private final class SettingsObserver extends ContentObserver {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index b551e6b9fb55..6ca9facc8110 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.desktopmode
+import android.R
import android.app.ActivityManager.RunningTaskInfo
import android.app.WindowConfiguration.ACTIVITY_TYPE_HOME
import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
@@ -24,6 +25,7 @@ import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED
import android.app.WindowConfiguration.WindowingMode
import android.content.Context
+import android.content.res.TypedArray
import android.graphics.Point
import android.graphics.Rect
import android.graphics.Region
@@ -460,6 +462,25 @@ class DesktopTasksController(
}
}
+ /**
+ * Applies the proper surface states (rounded corners) to tasks when desktop mode is active.
+ * This is intended to be used when desktop mode is part of another animation but isn't, itself,
+ * animating.
+ */
+ fun syncSurfaceState(
+ info: TransitionInfo,
+ finishTransaction: SurfaceControl.Transaction
+ ) {
+ // Add rounded corners to freeform windows
+ val ta: TypedArray = context.obtainStyledAttributes(
+ intArrayOf(R.attr.dialogCornerRadius))
+ val cornerRadius = ta.getDimensionPixelSize(0, 0).toFloat()
+ ta.recycle()
+ info.changes
+ .filter { it.taskInfo.windowingMode == WINDOWING_MODE_FREEFORM }
+ .forEach { finishTransaction.setCornerRadius(it.leash, cornerRadius) }
+ }
+
private fun handleFreeformTaskLaunch(task: RunningTaskInfo): WindowContainerTransaction? {
val activeTasks = desktopModeTaskRepository.getActiveTasks(task.displayId)
if (activeTasks.none { desktopModeTaskRepository.isVisibleTask(it) }) {
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..5ee5324f8758 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
@@ -40,6 +40,9 @@ import android.window.WindowContainerTransaction;
import android.window.WindowContainerTransactionCallback;
import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.desktopmode.DesktopModeController;
+import com.android.wm.shell.desktopmode.DesktopModeStatus;
+import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.keyguard.KeyguardTransitionHandler;
import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.pip.phone.PipTouchHandler;
@@ -65,6 +68,8 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
private RecentsTransitionHandler mRecentsHandler;
private StageCoordinator mSplitHandler;
private final KeyguardTransitionHandler mKeyguardHandler;
+ private DesktopModeController mDesktopModeController;
+ private DesktopTasksController mDesktopTasksController;
private static class MixedTransition {
static final int TYPE_ENTER_PIP_FROM_SPLIT = 1;
@@ -81,6 +86,9 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
/** Keyguard exit/occlude/unocclude transition. */
static final int TYPE_KEYGUARD = 5;
+ /** Recents Transition while in desktop mode. */
+ static final int TYPE_RECENTS_DURING_DESKTOP = 6;
+
/** The default animation for this mixed transition. */
static final int ANIM_TYPE_DEFAULT = 0;
@@ -132,7 +140,9 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
Optional<SplitScreenController> splitScreenControllerOptional,
Optional<PipTouchHandler> pipTouchHandlerOptional,
Optional<RecentsTransitionHandler> recentsHandlerOptional,
- KeyguardTransitionHandler keyguardHandler) {
+ KeyguardTransitionHandler keyguardHandler,
+ Optional<DesktopModeController> desktopModeControllerOptional,
+ Optional<DesktopTasksController> desktopTasksControllerOptional) {
mPlayer = player;
mKeyguardHandler = keyguardHandler;
if (Transitions.ENABLE_SHELL_TRANSITIONS && pipTouchHandlerOptional.isPresent()
@@ -149,6 +159,8 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
if (mRecentsHandler != null) {
mRecentsHandler.addMixer(this);
}
+ mDesktopModeController = desktopModeControllerOptional.orElse(null);
+ mDesktopTasksController = desktopTasksControllerOptional.orElse(null);
}, this);
}
}
@@ -218,7 +230,8 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
@Override
public Transitions.TransitionHandler handleRecentsRequest(WindowContainerTransaction outWCT) {
- if (mRecentsHandler != null && mSplitHandler.isSplitScreenVisible()) {
+ if (mRecentsHandler != null && (mSplitHandler.isSplitScreenVisible()
+ || DesktopModeStatus.isActive(mPlayer.getContext()))) {
return this;
}
return null;
@@ -233,6 +246,13 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
MixedTransition.TYPE_RECENTS_DURING_SPLIT, transition);
mixed.mLeftoversHandler = mRecentsHandler;
mActiveTransitions.add(mixed);
+ } else if (DesktopModeStatus.isActive(mPlayer.getContext())) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a recents request while "
+ + "desktop mode is active, so treat it as Mixed.");
+ final MixedTransition mixed = new MixedTransition(
+ MixedTransition.TYPE_RECENTS_DURING_DESKTOP, transition);
+ mixed.mLeftoversHandler = mRecentsHandler;
+ mActiveTransitions.add(mixed);
} else {
throw new IllegalStateException("Accepted a recents transition but don't know how to"
+ " handle it");
@@ -306,6 +326,9 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
} else if (mixed.mType == MixedTransition.TYPE_KEYGUARD) {
return animateKeyguard(mixed, info, startTransaction, finishTransaction,
finishCallback);
+ } else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_DESKTOP) {
+ return animateRecentsDuringDesktop(mixed, info, startTransaction, finishTransaction,
+ finishCallback);
} else {
mActiveTransitions.remove(mixed);
throw new IllegalStateException("Starting mixed animation without a known mixed type? "
@@ -540,9 +563,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 +578,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;
@@ -578,6 +605,30 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
return true;
}
+ private boolean animateRecentsDuringDesktop(@NonNull final MixedTransition mixed,
+ @NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction startTransaction,
+ @NonNull SurfaceControl.Transaction finishTransaction,
+ @NonNull Transitions.TransitionFinishCallback finishCallback) {
+ boolean consumed = mRecentsHandler.startAnimation(
+ mixed.mTransition, info, startTransaction, finishTransaction, finishCallback);
+ if (!consumed) {
+ return false;
+ }
+ //Sync desktop mode state (proto 1)
+ if (mDesktopModeController != null) {
+ mDesktopModeController.syncSurfaceState(info, finishTransaction);
+ return true;
+ }
+ //Sync desktop mode state (proto 2)
+ if (mDesktopTasksController != null) {
+ mDesktopTasksController.syncSurfaceState(info, finishTransaction);
+ return true;
+ }
+
+ return false;
+ }
+
@Override
public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
@@ -621,6 +672,9 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
finishCallback);
} else if (mixed.mType == MixedTransition.TYPE_KEYGUARD) {
mKeyguardHandler.mergeAnimation(transition, info, t, mergeTarget, finishCallback);
+ } else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_DESKTOP) {
+ mixed.mLeftoversHandler.mergeAnimation(transition, info, t, mergeTarget,
+ finishCallback);
} else {
throw new IllegalStateException("Playing a mixed transition with unknown type? "
+ mixed.mType);
@@ -646,6 +700,8 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
mixed.mLeftoversHandler.onTransitionConsumed(transition, aborted, finishT);
} else if (mixed.mType == MixedTransition.TYPE_KEYGUARD) {
mKeyguardHandler.onTransitionConsumed(transition, aborted, finishT);
+ } else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_DESKTOP) {
+ mixed.mLeftoversHandler.onTransitionConsumed(transition, aborted, finishT);
}
}
}
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/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 3b306e793640..e6d4603db10d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -16,9 +16,12 @@
package com.android.wm.shell.transition;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FIRST_CUSTOM;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_SLEEP;
import static android.view.WindowManager.TRANSIT_TO_BACK;
@@ -1081,6 +1084,16 @@ public class Transitions implements RemoteCallable<Transitions>,
}
}
}
+ if (request.getType() == TRANSIT_KEYGUARD_OCCLUDE && request.getTriggerTask() != null
+ && request.getTriggerTask().getWindowingMode() == WINDOWING_MODE_FREEFORM) {
+ // This freeform task is on top of keyguard, so its windowing mode should be changed to
+ // fullscreen.
+ if (wct == null) {
+ wct = new WindowContainerTransaction();
+ }
+ wct.setWindowingMode(request.getTriggerTask().token, WINDOWING_MODE_FULLSCREEN);
+ wct.setBounds(request.getTriggerTask().token, null);
+ }
mOrganizer.startTransition(transitionToken, wct != null && wct.isEmpty() ? null : wct);
active.mToken = transitionToken;
// Currently, WMCore only does one transition at a time. If it makes a requestStart, it
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/model/app/AppListRepository.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt
index 2b38b4cefe3e..8e0cf894bb28 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt
@@ -34,11 +34,11 @@ import kotlinx.coroutines.runBlocking
/**
* The repository to load the App List data.
*/
-internal interface AppListRepository {
+interface AppListRepository {
/** Loads the list of [ApplicationInfo]. */
suspend fun loadApps(
userId: Int,
- showInstantApps: Boolean = false,
+ loadInstantApps: Boolean = false,
matchAnyUserForAdmin: Boolean = false,
): List<ApplicationInfo>
@@ -50,6 +50,9 @@ internal interface AppListRepository {
/** Gets the system app package names. */
fun getSystemPackageNamesBlocking(userId: Int): Set<String>
+
+ /** Loads the list of [ApplicationInfo], and filter base on `isSystemApp`. */
+ suspend fun loadAndFilterApps(userId: Int, isSystemApp: Boolean): List<ApplicationInfo>
}
/**
@@ -62,13 +65,13 @@ object AppListRepositoryUtil {
AppListRepositoryImpl(context).getSystemPackageNamesBlocking(userId)
}
-internal class AppListRepositoryImpl(private val context: Context) : AppListRepository {
+class AppListRepositoryImpl(private val context: Context) : AppListRepository {
private val packageManager = context.packageManager
private val userManager = context.userManager
override suspend fun loadApps(
userId: Int,
- showInstantApps: Boolean,
+ loadInstantApps: Boolean,
matchAnyUserForAdmin: Boolean,
): List<ApplicationInfo> = coroutineScope {
val hiddenSystemModulesDeferred = async {
@@ -86,7 +89,7 @@ internal class AppListRepositoryImpl(private val context: Context) : AppListRepo
val hiddenSystemModules = hiddenSystemModulesDeferred.await()
val hideWhenDisabledPackages = hideWhenDisabledPackagesDeferred.await()
installedApplicationsAsUser.filter { app ->
- app.isInAppList(showInstantApps, hiddenSystemModules, hideWhenDisabledPackages)
+ app.isInAppList(loadInstantApps, hiddenSystemModules, hideWhenDisabledPackages)
}
}
@@ -136,17 +139,17 @@ internal class AppListRepositoryImpl(private val context: Context) : AppListRepo
): Flow<(app: ApplicationInfo) -> Boolean> =
userIdFlow.combine(showSystemFlow, ::showSystemPredicate)
- override fun getSystemPackageNamesBlocking(userId: Int) =
- runBlocking { getSystemPackageNames(userId) }
+ override fun getSystemPackageNamesBlocking(userId: Int) = runBlocking {
+ loadAndFilterApps(userId = userId, isSystemApp = true).map { it.packageName }.toSet()
+ }
- private suspend fun getSystemPackageNames(userId: Int): Set<String> =
- coroutineScope {
- val loadAppsDeferred = async { loadApps(userId) }
- val homeOrLauncherPackages = loadHomeOrLauncherPackages(userId)
- val showSystemPredicate =
- { app: ApplicationInfo -> isSystemApp(app, homeOrLauncherPackages) }
- loadAppsDeferred.await().filter(showSystemPredicate).map { it.packageName }.toSet()
+ override suspend fun loadAndFilterApps(userId: Int, isSystemApp: Boolean) = coroutineScope {
+ val loadAppsDeferred = async { loadApps(userId) }
+ val homeOrLauncherPackages = loadHomeOrLauncherPackages(userId)
+ loadAppsDeferred.await().filter { app ->
+ isSystemApp(app, homeOrLauncherPackages) == isSystemApp
}
+ }
private suspend fun showSystemPredicate(
userId: Int,
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/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt
index 302f78081626..375ed60e17cf 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt
@@ -108,7 +108,7 @@ class AppListRepositoryTest {
val appList = repository.loadApps(
userId = ADMIN_USER_ID,
- showInstantApps = false,
+ loadInstantApps = false,
)
assertThat(appList).containsExactly(NORMAL_APP)
@@ -120,7 +120,7 @@ class AppListRepositoryTest {
val appList = repository.loadApps(
userId = ADMIN_USER_ID,
- showInstantApps = true,
+ loadInstantApps = true,
)
assertThat(appList).containsExactly(NORMAL_APP, INSTANT_APP)
@@ -325,6 +325,21 @@ class AppListRepositoryTest {
assertThat(systemPackageNames).containsExactly(SYSTEM_APP.packageName)
}
+ @Test
+ fun loadAndFilterApps_loadNonSystemApp_returnExpectedValues() = runTest {
+ mockInstalledApplications(
+ apps = listOf(
+ NORMAL_APP, INSTANT_APP, SYSTEM_APP, UPDATED_SYSTEM_APP, HOME_APP, IN_LAUNCHER_APP
+ ),
+ userId = ADMIN_USER_ID,
+ )
+
+ val appList = repository.loadAndFilterApps(userId = ADMIN_USER_ID, isSystemApp = false)
+
+ assertThat(appList)
+ .containsExactly(NORMAL_APP, UPDATED_SYSTEM_APP, HOME_APP, IN_LAUNCHER_APP)
+ }
+
private suspend fun getShowSystemPredicate(showSystem: Boolean) =
repository.showSystemPredicate(
userIdFlow = flowOf(ADMIN_USER_ID),
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt
index 6889e5d21ac0..9b224976e080 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt
@@ -87,7 +87,7 @@ class AppListViewModelTest {
private object FakeAppListRepository : AppListRepository {
override suspend fun loadApps(
userId: Int,
- showInstantApps: Boolean,
+ loadInstantApps: Boolean,
matchAnyUserForAdmin: Boolean,
) = listOf(APP)
@@ -97,6 +97,9 @@ class AppListViewModelTest {
): Flow<(app: ApplicationInfo) -> Boolean> = flowOf { true }
override fun getSystemPackageNamesBlocking(userId: Int): Set<String> = emptySet()
+
+ override suspend fun loadAndFilterApps(userId: Int, isSystemApp: Boolean) =
+ emptyList<ApplicationInfo>()
}
private object FakeAppRepository : AppRepository {
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 0f0ebed01e82..894158c1b092 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;
@@ -1818,6 +1819,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)) {
@@ -2387,6 +2390,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();
@@ -2457,6 +2463,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);
@@ -3712,6 +3719,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/KeyguardLifecyclesDispatcher.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
index 757afb616fd1..67c85bd94bd7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
@@ -16,11 +16,19 @@
package com.android.systemui.keyguard;
+import android.annotation.IntDef;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
-import android.os.Trace;
+import android.os.TraceNameSupplier;
+
+import androidx.annotation.NonNull;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import javax.inject.Inject;
@@ -29,7 +37,6 @@ import javax.inject.Inject;
*/
@SysUISingleton
public class KeyguardLifecyclesDispatcher {
-
static final int SCREEN_TURNING_ON = 0;
static final int SCREEN_TURNED_ON = 1;
static final int SCREEN_TURNING_OFF = 2;
@@ -39,19 +46,46 @@ public class KeyguardLifecyclesDispatcher {
static final int FINISHED_WAKING_UP = 5;
static final int STARTED_GOING_TO_SLEEP = 6;
static final int FINISHED_GOING_TO_SLEEP = 7;
- private static final String TAG = "KeyguardLifecyclesDispatcher";
- private final ScreenLifecycle mScreenLifecycle;
- private final WakefulnessLifecycle mWakefulnessLifecycle;
+ @IntDef({
+ SCREEN_TURNING_ON,
+ SCREEN_TURNED_ON,
+ SCREEN_TURNING_OFF,
+ SCREEN_TURNED_OFF,
+ STARTED_WAKING_UP,
+ FINISHED_WAKING_UP,
+ STARTED_GOING_TO_SLEEP,
+ FINISHED_GOING_TO_SLEEP,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface KeyguardLifecycleMessageType {
+ }
+
+ private static String getNameOfMessage(@KeyguardLifecycleMessageType int what) {
+ return switch (what) {
+ case SCREEN_TURNING_ON -> "SCREEN_TURNING_ON";
+ case SCREEN_TURNED_ON -> "SCREEN_TURNED_ON";
+ case SCREEN_TURNING_OFF -> "SCREEN_TURNING_OFF";
+ case SCREEN_TURNED_OFF -> "SCREEN_TURNED_OFF";
+ case STARTED_WAKING_UP -> "STARTED_WAKING_UP";
+ case FINISHED_WAKING_UP -> "FINISHED_WAKING_UP";
+ case STARTED_GOING_TO_SLEEP -> "STARTED_GOING_TO_SLEEP";
+ case FINISHED_GOING_TO_SLEEP -> "FINISHED_GOING_TO_SLEEP";
+ default -> "UNKNOWN";
+ };
+ }
+
+ private final Handler mHandler;
@Inject
- public KeyguardLifecyclesDispatcher(ScreenLifecycle screenLifecycle,
+ public KeyguardLifecyclesDispatcher(
+ @Main Looper mainLooper,
+ ScreenLifecycle screenLifecycle,
WakefulnessLifecycle wakefulnessLifecycle) {
- mScreenLifecycle = screenLifecycle;
- mWakefulnessLifecycle = wakefulnessLifecycle;
+ mHandler = new KeyguardLifecycleHandler(mainLooper, screenLifecycle, wakefulnessLifecycle);
}
- void dispatch(int what) {
+ void dispatch(@KeyguardLifecycleMessageType int what) {
mHandler.obtainMessage(what).sendToTarget();
}
@@ -60,7 +94,7 @@ public class KeyguardLifecyclesDispatcher {
* @param pmReason Reason this message was triggered - this should be a value from either
* {@link PowerManager.WakeReason} or {@link PowerManager.GoToSleepReason}.
*/
- void dispatch(int what, int pmReason) {
+ void dispatch(@KeyguardLifecycleMessageType int what, int pmReason) {
final Message message = mHandler.obtainMessage(what);
message.arg1 = pmReason;
message.sendToTarget();
@@ -70,44 +104,48 @@ public class KeyguardLifecyclesDispatcher {
* @param what Message to send.
* @param object Object to send with the message
*/
- void dispatch(int what, Object object) {
+ void dispatch(@KeyguardLifecycleMessageType int what, Object object) {
mHandler.obtainMessage(what, object).sendToTarget();
}
- private Handler mHandler = new Handler() {
+ private static class KeyguardLifecycleHandler extends Handler {
+ private static final String TAG = "KeyguardLifecycleHandler";
+ private final ScreenLifecycle mScreenLifecycle;
+ private final WakefulnessLifecycle mWakefulnessLifecycle;
+
+ public KeyguardLifecycleHandler(Looper looper,
+ ScreenLifecycle screenLifecycle,
+ WakefulnessLifecycle wakefulnessLifecycle) {
+ super(looper);
+ mScreenLifecycle = screenLifecycle;
+ mWakefulnessLifecycle = wakefulnessLifecycle;
+ }
+
+ @NonNull
@Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case SCREEN_TURNING_ON:
- Trace.beginSection("KeyguardLifecyclesDispatcher#SCREEN_TURNING_ON");
- mScreenLifecycle.dispatchScreenTurningOn();
- Trace.endSection();
- break;
- case SCREEN_TURNED_ON:
- mScreenLifecycle.dispatchScreenTurnedOn();
- break;
- case SCREEN_TURNING_OFF:
- mScreenLifecycle.dispatchScreenTurningOff();
- break;
- case SCREEN_TURNED_OFF:
- mScreenLifecycle.dispatchScreenTurnedOff();
- break;
- case STARTED_WAKING_UP:
- mWakefulnessLifecycle.dispatchStartedWakingUp(msg.arg1 /* pmReason */);
- break;
- case FINISHED_WAKING_UP:
- mWakefulnessLifecycle.dispatchFinishedWakingUp();
- break;
- case STARTED_GOING_TO_SLEEP:
- mWakefulnessLifecycle.dispatchStartedGoingToSleep(msg.arg1 /* pmReason */);
- break;
- case FINISHED_GOING_TO_SLEEP:
- mWakefulnessLifecycle.dispatchFinishedGoingToSleep();
- break;
- default:
- throw new IllegalArgumentException("Unknown message: " + msg);
+ public String getTraceName(@NonNull Message msg) {
+ if (msg.getCallback() instanceof TraceNameSupplier || msg.getCallback() != null) {
+ return super.getTraceName(msg);
}
+ return TAG + "#" + getNameOfMessage(msg.what);
}
- };
+ @Override
+ public void handleMessage(@NonNull Message msg) {
+ switch (msg.what) {
+ case SCREEN_TURNING_ON -> mScreenLifecycle.dispatchScreenTurningOn();
+ case SCREEN_TURNED_ON -> mScreenLifecycle.dispatchScreenTurnedOn();
+ case SCREEN_TURNING_OFF -> mScreenLifecycle.dispatchScreenTurningOff();
+ case SCREEN_TURNED_OFF -> mScreenLifecycle.dispatchScreenTurnedOff();
+ case STARTED_WAKING_UP ->
+ mWakefulnessLifecycle.dispatchStartedWakingUp(msg.arg1 /* pmReason */);
+ case FINISHED_WAKING_UP -> mWakefulnessLifecycle.dispatchFinishedWakingUp();
+ case STARTED_GOING_TO_SLEEP ->
+ mWakefulnessLifecycle.dispatchStartedGoingToSleep(msg.arg1 /* pmReason */);
+ case FINISHED_GOING_TO_SLEEP ->
+ mWakefulnessLifecycle.dispatchFinishedGoingToSleep();
+ default -> throw new IllegalArgumentException("Unknown message: " + msg);
+ }
+ }
+ }
}
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 1a158c89dee7..29a7fe7d061a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -668,8 +668,24 @@ class KeyguardUnlockAnimationController @Inject constructor(
lockscreenSmartspace?.visibility = View.INVISIBLE
}
- // Start an animation for the wallpaper, which will finish keyguard exit when it completes.
- fadeInWallpaper()
+ // 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
+ }
+
+ if (wallpaperTargets != null) {
+ fadeInWallpaper()
+ } else {
+ keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
+ false /* cancelled */)
+ }
+ }, CANNED_UNLOCK_START_DELAY)
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 45e4623c7e27..81f325f53f1b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -17,6 +17,8 @@
package com.android.systemui.keyguard;
import static android.app.StatusBarManager.SESSION_KEYGUARD;
+import static android.provider.Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT;
+import static android.provider.Settings.System.LOCKSCREEN_SOUNDS_ENABLED;
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT;
@@ -70,7 +72,6 @@ import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
@@ -93,7 +94,6 @@ import android.view.WindowManager;
import android.view.WindowManagerPolicyConstants;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
-import android.window.IRemoteTransition;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -154,6 +154,9 @@ import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.DeviceConfigProxy;
+import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.util.settings.SystemSettings;
+import com.android.systemui.util.time.SystemClock;
import com.android.wm.shell.keyguard.KeyguardTransitions;
import dagger.Lazy;
@@ -161,7 +164,6 @@ import dagger.Lazy;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Optional;
import java.util.concurrent.Executor;
/**
@@ -215,7 +217,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
private final static String TAG = "KeyguardViewMediator";
- private static final String DELAYED_KEYGUARD_ACTION =
+ public static final String DELAYED_KEYGUARD_ACTION =
"com.android.internal.policy.impl.PhoneWindowManager.DELAYED_KEYGUARD";
private static final String DELAYED_LOCK_PROFILE_ACTION =
"com.android.internal.policy.impl.PhoneWindowManager.DELAYED_LOCK";
@@ -250,7 +252,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
* turning on the keyguard (i.e, the user has this much time to turn
* the screen back on without having to face the keyguard).
*/
- private static final int KEYGUARD_LOCK_AFTER_DELAY_DEFAULT = 5000;
+ public static final int KEYGUARD_LOCK_AFTER_DELAY_DEFAULT = 5000;
/**
* How long we'll wait for the {@link ViewMediatorCallback#keyguardDoneDrawing()}
@@ -306,6 +308,9 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
/** UserSwitcherController for creating guest user on boot complete */
private final UserSwitcherController mUserSwitcherController;
+ private final SecureSettings mSecureSettings;
+ private final SystemSettings mSystemSettings;
+ private final SystemClock mSystemClock;
/**
* Used to keep the device awake while to ensure the keyguard finishes opening before
@@ -1253,7 +1258,10 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
Lazy<NotificationShadeWindowController> notificationShadeWindowControllerLazy,
Lazy<ActivityLaunchAnimator> activityLaunchAnimator,
Lazy<ScrimController> scrimControllerLazy,
- FeatureFlags featureFlags) {
+ FeatureFlags featureFlags,
+ SecureSettings secureSettings,
+ SystemSettings systemSettings,
+ SystemClock systemClock) {
mContext = context;
mUserTracker = userTracker;
mFalsingCollector = falsingCollector;
@@ -1267,6 +1275,9 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
mPM = powerManager;
mTrustManager = trustManager;
mUserSwitcherController = userSwitcherController;
+ mSecureSettings = secureSettings;
+ mSystemSettings = systemSettings;
+ mSystemClock = systemClock;
mStatusBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
mKeyguardDisplayManager = keyguardDisplayManager;
@@ -1316,7 +1327,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
}
public void userActivity() {
- mPM.userActivity(SystemClock.uptimeMillis(), false);
+ mPM.userActivity(mSystemClock.uptimeMillis(), false);
}
private void setupLocked() {
@@ -1502,7 +1513,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
if (cameraGestureTriggered) {
// Just to make sure, make sure the device is awake.
- mContext.getSystemService(PowerManager.class).wakeUp(SystemClock.uptimeMillis(),
+ mContext.getSystemService(PowerManager.class).wakeUp(mSystemClock.uptimeMillis(),
PowerManager.WAKE_REASON_CAMERA_LAUNCH,
"com.android.systemui:CAMERA_GESTURE_PREVENT_LOCK");
setPendingLock(false);
@@ -1599,12 +1610,11 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
// to enable it a bit later (i.e, give the user a chance
// to turn the screen back on within a certain window without
// having to unlock the screen)
- final ContentResolver cr = mContext.getContentResolver();
// From SecuritySettings
- final long lockAfterTimeout = Settings.Secure.getInt(cr,
- Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
- KEYGUARD_LOCK_AFTER_DELAY_DEFAULT);
+ final long lockAfterTimeout = mSecureSettings.getIntForUser(LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
+ KEYGUARD_LOCK_AFTER_DELAY_DEFAULT,
+ userId);
// From DevicePolicyAdmin
final long policyTimeout = mLockPatternUtils.getDevicePolicyManager()
@@ -1616,8 +1626,9 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
timeout = lockAfterTimeout;
} else {
// From DisplaySettings
- long displayTimeout = Settings.System.getInt(cr, SCREEN_OFF_TIMEOUT,
- KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT);
+ long displayTimeout = mSystemSettings.getIntForUser(SCREEN_OFF_TIMEOUT,
+ KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT,
+ userId);
// policy in effect. Make sure we don't go beyond policy limit.
displayTimeout = Math.max(displayTimeout, 0); // ignore negative values
@@ -1638,7 +1649,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
private void doKeyguardLaterLocked(long timeout) {
// Lock in the future
- long when = SystemClock.elapsedRealtime() + timeout;
+ long when = mSystemClock.elapsedRealtime() + timeout;
Intent intent = new Intent(DELAYED_KEYGUARD_ACTION);
intent.setPackage(mContext.getPackageName());
intent.putExtra("seq", mDelayedShowingSequence);
@@ -1660,7 +1671,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
if (userTimeout == 0) {
doKeyguardForChildProfilesLocked();
} else {
- long userWhen = SystemClock.elapsedRealtime() + userTimeout;
+ long userWhen = mSystemClock.elapsedRealtime() + userTimeout;
Intent lockIntent = new Intent(DELAYED_LOCK_PROFILE_ACTION);
lockIntent.setPackage(mContext.getPackageName());
lockIntent.putExtra("seq", mDelayedProfileShowingSequence);
@@ -2468,8 +2479,9 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
private void playSound(int soundId) {
if (soundId == 0) return;
- final ContentResolver cr = mContext.getContentResolver();
- if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1) {
+ int lockscreenSoundsEnabled = mSystemSettings.getIntForUser(LOCKSCREEN_SOUNDS_ENABLED, 1,
+ KeyguardUpdateMonitor.getCurrentUser());
+ if (lockscreenSoundsEnabled == 1) {
mLockSounds.stop(mLockSoundStreamId);
// Init mAudioManager
@@ -2644,7 +2656,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
// It's possible that the device was unlocked (via BOUNCER) while dozing. It's time to
// wake up.
if (mAodShowing) {
- mPM.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
+ mPM.wakeUp(mSystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
"com.android.systemui:BOUNCER_DOZING");
}
@@ -2659,7 +2671,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
// TODO(bc-unlock): Fill parameters
mNotificationShadeWindowControllerLazy.get().batchApplyWindowLayoutParams(() -> {
handleStartKeyguardExitAnimation(
- SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(),
+ mSystemClock.uptimeMillis() + mHideAnimation.getStartOffset(),
mHideAnimation.getDuration(), null /* apps */, null /* wallpapers */,
null /* nonApps */, null /* finishedCallback */);
});
@@ -2668,7 +2680,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
// It's possible that the device was unlocked (via BOUNCER or Fingerprint) while
// dreaming. It's time to wake up.
if (mDreamOverlayShowing) {
- mPM.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
+ mPM.wakeUp(mSystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
"com.android.systemui:UNLOCK_DREAMING");
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index d7c039d9b519..1c5bb5f4efaf 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -64,6 +64,9 @@ import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.DeviceConfigProxy;
+import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.util.settings.SystemSettings;
+import com.android.systemui.util.time.SystemClock;
import com.android.wm.shell.keyguard.KeyguardTransitions;
import dagger.Lazy;
@@ -128,7 +131,10 @@ public class KeyguardModule {
Lazy<NotificationShadeWindowController> notificationShadeWindowController,
Lazy<ActivityLaunchAnimator> activityLaunchAnimator,
Lazy<ScrimController> scrimControllerLazy,
- FeatureFlags featureFlags) {
+ FeatureFlags featureFlags,
+ SecureSettings secureSettings,
+ SystemSettings systemSettings,
+ SystemClock systemClock) {
return new KeyguardViewMediator(
context,
uiEventLogger,
@@ -162,7 +168,10 @@ public class KeyguardModule {
notificationShadeWindowController,
activityLaunchAnimator,
scrimControllerLazy,
- featureFlags);
+ featureFlags,
+ secureSettings,
+ systemSettings,
+ systemClock);
}
/** */
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/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/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index f31ac00051f6..c4a0e7c6b7ab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -16,11 +16,16 @@
package com.android.systemui.keyguard;
+import static android.os.PowerManager.WAKE_REASON_WAKE_MOTION;
+import static android.provider.Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT;
import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManagerPolicyConstants.OFF_BECAUSE_OF_TIMEOUT;
import static android.view.WindowManagerPolicyConstants.OFF_BECAUSE_OF_USER;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT;
+import static com.android.systemui.keyguard.KeyguardViewMediator.DELAYED_KEYGUARD_ACTION;
+import static com.android.systemui.keyguard.KeyguardViewMediator.KEYGUARD_LOCK_AFTER_DELAY_DEFAULT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -35,9 +40,12 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.AlarmManager;
import android.app.IActivityManager;
+import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
+import android.content.Context;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.telephony.TelephonyManager;
@@ -94,9 +102,12 @@ import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.DeviceConfigProxyFake;
import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.util.settings.SystemSettings;
import com.android.systemui.util.time.FakeSystemClock;
import com.android.wm.shell.keyguard.KeyguardTransitions;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -156,18 +167,24 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
private @Mock CentralSurfaces mCentralSurfaces;
private @Mock UiEventLogger mUiEventLogger;
private @Mock SessionTracker mSessionTracker;
+ private @Mock SystemSettings mSystemSettings;
+ private @Mock SecureSettings mSecureSettings;
+ private @Mock AlarmManager mAlarmManager;
+ private FakeSystemClock mSystemClock;
private FakeFeatureFlags mFeatureFlags;
+ private int mInitialUserId;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mFalsingCollector = new FalsingCollectorFake();
-
+ mSystemClock = new FakeSystemClock();
when(mLockPatternUtils.getDevicePolicyManager()).thenReturn(mDevicePolicyManager);
when(mPowerManager.newWakeLock(anyInt(), any())).thenReturn(mock(WakeLock.class));
when(mInteractionJankMonitor.begin(any(), anyInt())).thenReturn(true);
when(mInteractionJankMonitor.end(anyInt())).thenReturn(true);
+ mContext.addMockSystemService(Context.ALARM_SERVICE, mAlarmManager);
final ViewRootImpl testViewRoot = mock(ViewRootImpl.class);
when(testViewRoot.getView()).thenReturn(mock(View.class));
when(mStatusBarKeyguardViewManager.getViewRootImpl()).thenReturn(testViewRoot);
@@ -183,6 +200,12 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
DejankUtils.setImmediate(true);
createAndStartViewMediator();
+ mInitialUserId = KeyguardUpdateMonitor.getCurrentUser();
+ }
+
+ @After
+ public void teardown() {
+ KeyguardUpdateMonitor.setCurrentUser(mInitialUserId);
}
@Test
@@ -369,6 +392,49 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
}
@Test
+ public void lockAfterScreenTimeoutUsesValueFromSettings() {
+ int currentUserId = 99;
+ int userSpecificTimeout = 5999;
+ KeyguardUpdateMonitor.setCurrentUser(currentUserId);
+
+ when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(false);
+ when(mDevicePolicyManager.getMaximumTimeToLock(null, currentUserId)).thenReturn(0L);
+ when(mSecureSettings.getIntForUser(LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
+ KEYGUARD_LOCK_AFTER_DELAY_DEFAULT, currentUserId)).thenReturn(userSpecificTimeout);
+ mSystemClock.setElapsedRealtime(0L);
+ ArgumentCaptor<PendingIntent> pendingIntent = ArgumentCaptor.forClass(PendingIntent.class);
+
+ mViewMediator.onStartedGoingToSleep(OFF_BECAUSE_OF_TIMEOUT);
+
+ verify(mAlarmManager).setExactAndAllowWhileIdle(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
+ eq(Long.valueOf(userSpecificTimeout)), pendingIntent.capture());
+ assertEquals(DELAYED_KEYGUARD_ACTION, pendingIntent.getValue().getIntent().getAction());
+ }
+
+ @Test
+ public void lockAfterSpecifiedAfterDreamStarted() {
+ int currentUserId = 99;
+ int userSpecificTimeout = 5999;
+ KeyguardUpdateMonitor.setCurrentUser(currentUserId);
+
+ // set mDeviceInteractive to true
+ mViewMediator.onStartedWakingUp(WAKE_REASON_WAKE_MOTION, false);
+ mFeatureFlags.set(Flags.LOCKSCREEN_WITHOUT_SECURE_LOCK_WHEN_DREAMING, false);
+ when(mLockPatternUtils.isSecure(currentUserId)).thenReturn(true);
+ when(mDevicePolicyManager.getMaximumTimeToLock(null, currentUserId)).thenReturn(0L);
+ when(mSecureSettings.getIntForUser(LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
+ KEYGUARD_LOCK_AFTER_DELAY_DEFAULT, currentUserId)).thenReturn(userSpecificTimeout);
+ mSystemClock.setElapsedRealtime(0L);
+ ArgumentCaptor<PendingIntent> pendingIntent = ArgumentCaptor.forClass(PendingIntent.class);
+
+ mViewMediator.onDreamingStarted();
+
+ verify(mAlarmManager).setExactAndAllowWhileIdle(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
+ eq(Long.valueOf(userSpecificTimeout)), pendingIntent.capture());
+ assertEquals(DELAYED_KEYGUARD_ACTION, pendingIntent.getValue().getIntent().getAction());
+ }
+
+ @Test
public void testHideSurfaceBehindKeyguardMarksKeyguardNotGoingAway() {
mViewMediator.hideSurfaceBehindKeyguard();
@@ -629,7 +695,10 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
() -> mNotificationShadeWindowController,
() -> mActivityLaunchAnimator,
() -> mScrimController,
- mFeatureFlags);
+ mFeatureFlags,
+ mSecureSettings,
+ mSystemSettings,
+ mSystemClock);
mViewMediator.start();
mViewMediator.registerCentralSurfaces(mCentralSurfaces, null, null, null, null, null);
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/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index d2d99b1a0a5e..44c50334649f 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -225,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;
@@ -3653,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);
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/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index 05ca6e4554fb..6ac163121d8c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -266,8 +266,12 @@ public abstract class AuthenticationClient<T, O extends AuthenticateOptions>
}
} else {
if (isBackgroundAuth) {
- Slog.e(TAG, "cancelling due to background auth");
- cancel();
+ Slog.e(TAG, "Sending cancel to client(Due to background auth)");
+ if (mTaskStackListener != null) {
+ mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
+ }
+ sendCancelOnly(getListener());
+ mCallback.onClientFinished(this, false);
} else {
// Allow system-defined limit of number of attempts before giving up
if (mShouldUseLockoutTracker) {
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/input/InputFeatureFlagProvider.java b/services/core/java/com/android/server/input/InputFeatureFlagProvider.java
index 3854adad9cd8..7c7f1513bd96 100644
--- a/services/core/java/com/android/server/input/InputFeatureFlagProvider.java
+++ b/services/core/java/com/android/server/input/InputFeatureFlagProvider.java
@@ -38,8 +38,15 @@ public final class InputFeatureFlagProvider {
private static final boolean KEYBOARD_BACKLIGHT_ANIMATION_ENABLED =
InputProperties.enable_keyboard_backlight_animation().orElse(false);
+ // To disable Custom keyboard backlight levels support via IDC files run:
+ // adb shell setprop persist.input.keyboard_backlight_custom_levels.enabled false (requires
+ // restart)
+ private static final boolean KEYBOARD_BACKLIGHT_CUSTOM_LEVELS_ENABLED =
+ InputProperties.enable_keyboard_backlight_custom_levels().orElse(true);
+
private static Optional<Boolean> sKeyboardBacklightControlOverride = Optional.empty();
private static Optional<Boolean> sKeyboardBacklightAnimationOverride = Optional.empty();
+ private static Optional<Boolean> sKeyboardBacklightCustomLevelsOverride = Optional.empty();
public static boolean isKeyboardBacklightControlEnabled() {
return sKeyboardBacklightControlOverride.orElse(KEYBOARD_BACKLIGHT_CONTROL_ENABLED);
@@ -49,6 +56,11 @@ public final class InputFeatureFlagProvider {
return sKeyboardBacklightAnimationOverride.orElse(KEYBOARD_BACKLIGHT_ANIMATION_ENABLED);
}
+ public static boolean isKeyboardBacklightCustomLevelsEnabled() {
+ return sKeyboardBacklightCustomLevelsOverride.orElse(
+ KEYBOARD_BACKLIGHT_CUSTOM_LEVELS_ENABLED);
+ }
+
public static void setKeyboardBacklightControlEnabled(boolean enabled) {
sKeyboardBacklightControlOverride = Optional.of(enabled);
}
@@ -57,11 +69,16 @@ public final class InputFeatureFlagProvider {
sKeyboardBacklightAnimationOverride = Optional.of(enabled);
}
+ public static void setKeyboardBacklightCustomLevelsEnabled(boolean enabled) {
+ sKeyboardBacklightCustomLevelsOverride = Optional.of(enabled);
+ }
+
/**
* Clears all input feature flag overrides.
*/
public static void clearOverrides() {
sKeyboardBacklightControlOverride = Optional.empty();
sKeyboardBacklightAnimationOverride = Optional.empty();
+ sKeyboardBacklightCustomLevelsOverride = Optional.empty();
}
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 9f3ab885bf16..c7b80af27d79 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -493,8 +493,6 @@ public class InputManagerService extends IInputManager.Stub
// Add ourselves to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
-
- mSettingsObserver.registerAndUpdate();
}
// TODO(BT) Pass in parameter for bluetooth system
@@ -505,6 +503,8 @@ public class InputManagerService extends IInputManager.Stub
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
+ mSettingsObserver.registerAndUpdate();
+
synchronized (mLidSwitchLock) {
mSystemReady = true;
diff --git a/services/core/java/com/android/server/input/KeyboardBacklightController.java b/services/core/java/com/android/server/input/KeyboardBacklightController.java
index 61ca0cbff7bf..36238a8cfd23 100644
--- a/services/core/java/com/android/server/input/KeyboardBacklightController.java
+++ b/services/core/java/com/android/server/input/KeyboardBacklightController.java
@@ -46,6 +46,7 @@ import java.time.Duration;
import java.util.Arrays;
import java.util.Objects;
import java.util.OptionalInt;
+import java.util.TreeSet;
/**
* A thread-safe component of {@link InputManagerService} responsible for managing the keyboard
@@ -70,7 +71,9 @@ final class KeyboardBacklightController implements
private static final int MSG_NOTIFY_USER_INACTIVITY = 5;
private static final int MSG_INTERACTIVE_STATE_CHANGED = 6;
private static final int MAX_BRIGHTNESS = 255;
- private static final int NUM_BRIGHTNESS_CHANGE_STEPS = 10;
+ private static final int DEFAULT_NUM_BRIGHTNESS_CHANGE_STEPS = 10;
+ @VisibleForTesting
+ static final int MAX_BRIGHTNESS_CHANGE_STEPS = 10;
private static final long TRANSITION_ANIMATION_DURATION_MILLIS =
Duration.ofSeconds(1).toMillis();
@@ -80,7 +83,8 @@ final class KeyboardBacklightController implements
static final long USER_INACTIVITY_THRESHOLD_MILLIS = Duration.ofSeconds(30).toMillis();
@VisibleForTesting
- static final int[] BRIGHTNESS_VALUE_FOR_LEVEL = new int[NUM_BRIGHTNESS_CHANGE_STEPS + 1];
+ static final int[] DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL =
+ new int[DEFAULT_NUM_BRIGHTNESS_CHANGE_STEPS + 1];
private final Context mContext;
private final NativeInputManagerService mNative;
@@ -104,10 +108,10 @@ final class KeyboardBacklightController implements
static {
// Fixed brightness levels to avoid issues when converting back and forth from the
// device brightness range to [0-255]
- // Levels are: 0, 25, 51, ..., 255
- for (int i = 0; i <= NUM_BRIGHTNESS_CHANGE_STEPS; i++) {
- BRIGHTNESS_VALUE_FOR_LEVEL[i] = (int) Math.floor(
- ((float) i * MAX_BRIGHTNESS) / NUM_BRIGHTNESS_CHANGE_STEPS);
+ // Levels are: 0, 51, ..., 255
+ for (int i = 0; i <= DEFAULT_NUM_BRIGHTNESS_CHANGE_STEPS; i++) {
+ DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL[i] = (int) Math.floor(
+ ((float) i * MAX_BRIGHTNESS) / DEFAULT_NUM_BRIGHTNESS_CHANGE_STEPS);
}
}
@@ -184,7 +188,8 @@ final class KeyboardBacklightController implements
final int currBrightnessLevel = state.mBrightnessLevel;
final int newBrightnessLevel;
if (direction == Direction.DIRECTION_UP) {
- newBrightnessLevel = Math.min(currBrightnessLevel + 1, NUM_BRIGHTNESS_CHANGE_STEPS);
+ newBrightnessLevel = Math.min(currBrightnessLevel + 1,
+ state.getNumBrightnessChangeSteps());
} else {
newBrightnessLevel = Math.max(currBrightnessLevel - 1, 0);
}
@@ -194,7 +199,7 @@ final class KeyboardBacklightController implements
try {
mDataStore.setKeyboardBacklightBrightness(inputDevice.getDescriptor(),
keyboardBacklight.getId(),
- BRIGHTNESS_VALUE_FOR_LEVEL[newBrightnessLevel]);
+ state.mBrightnessValueForLevel[newBrightnessLevel]);
} finally {
mDataStore.saveIfNeeded();
}
@@ -202,6 +207,7 @@ final class KeyboardBacklightController implements
}
private void restoreBacklightBrightness(InputDevice inputDevice, Light keyboardBacklight) {
+ KeyboardBacklightState state = mKeyboardBacklights.get(inputDevice.getId());
OptionalInt brightness;
synchronized (mDataStore) {
brightness = mDataStore.getKeyboardBacklightBrightness(
@@ -209,9 +215,9 @@ final class KeyboardBacklightController implements
}
if (brightness.isPresent()) {
int brightnessValue = Math.max(0, Math.min(MAX_BRIGHTNESS, brightness.getAsInt()));
- int index = Arrays.binarySearch(BRIGHTNESS_VALUE_FOR_LEVEL, brightnessValue);
+ int index = Arrays.binarySearch(state.mBrightnessValueForLevel, brightnessValue);
if (index < 0) {
- index = Math.min(NUM_BRIGHTNESS_CHANGE_STEPS, -(index + 1));
+ index = Math.min(state.getNumBrightnessChangeSteps(), -(index + 1));
}
updateBacklightState(inputDevice.getId(), index, false /* isTriggeredByKeyPress */);
if (DEBUG) {
@@ -386,7 +392,7 @@ final class KeyboardBacklightController implements
for (int i = 0; i < mKeyboardBacklightListenerRecords.size(); i++) {
IKeyboardBacklightState callbackState = new IKeyboardBacklightState();
callbackState.brightnessLevel = brightnessLevel;
- callbackState.maxBrightnessLevel = NUM_BRIGHTNESS_CHANGE_STEPS;
+ callbackState.maxBrightnessLevel = state.getNumBrightnessChangeSteps();
mKeyboardBacklightListenerRecords.valueAt(i).notifyKeyboardBacklightChanged(
deviceId, callbackState, isTriggeredByKeyPress);
}
@@ -443,10 +449,6 @@ final class KeyboardBacklightController implements
ipw.decreaseIndent();
}
- private static boolean isAnimationEnabled() {
- return InputFeatureFlagProvider.isKeyboardBacklightAnimationEnabled();
- }
-
// A record of a registered Keyboard backlight listener from one process.
private class KeyboardBacklightListenerRecord implements IBinder.DeathRecipient {
public final int mPid;
@@ -482,18 +484,52 @@ final class KeyboardBacklightController implements
private final Light mLight;
private int mBrightnessLevel;
private ValueAnimator mAnimator;
+ private final int[] mBrightnessValueForLevel;
KeyboardBacklightState(int deviceId, Light light) {
mDeviceId = deviceId;
mLight = light;
+ mBrightnessValueForLevel = setupBrightnessLevels();
+ }
+
+ private int[] setupBrightnessLevels() {
+ if (!InputFeatureFlagProvider.isKeyboardBacklightCustomLevelsEnabled()) {
+ return DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL;
+ }
+ int[] customLevels = mLight.getPreferredBrightnessLevels();
+ if (customLevels == null || customLevels.length == 0) {
+ return DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL;
+ }
+ TreeSet<Integer> brightnessLevels = new TreeSet<>();
+ brightnessLevels.add(0);
+ for (int level : customLevels) {
+ if (level > 0 && level < MAX_BRIGHTNESS) {
+ brightnessLevels.add(level);
+ }
+ }
+ brightnessLevels.add(MAX_BRIGHTNESS);
+ int brightnessChangeSteps = brightnessLevels.size() - 1;
+ if (brightnessChangeSteps > MAX_BRIGHTNESS_CHANGE_STEPS) {
+ return DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL;
+ }
+ int[] result = new int[brightnessLevels.size()];
+ int index = 0;
+ for (int val : brightnessLevels) {
+ result[index++] = val;
+ }
+ return result;
+ }
+
+ private int getNumBrightnessChangeSteps() {
+ return mBrightnessValueForLevel.length - 1;
}
private void onBacklightStateChanged() {
- setBacklightValue(mIsBacklightOn ? BRIGHTNESS_VALUE_FOR_LEVEL[mBrightnessLevel] : 0);
+ setBacklightValue(mIsBacklightOn ? mBrightnessValueForLevel[mBrightnessLevel] : 0);
}
private void setBrightnessLevel(int brightnessLevel) {
if (mIsBacklightOn) {
- setBacklightValue(BRIGHTNESS_VALUE_FOR_LEVEL[brightnessLevel]);
+ setBacklightValue(mBrightnessValueForLevel[brightnessLevel]);
}
mBrightnessLevel = brightnessLevel;
}
@@ -509,7 +545,7 @@ final class KeyboardBacklightController implements
if (fromValue == toValue) {
return;
}
- if (isAnimationEnabled()) {
+ if (InputFeatureFlagProvider.isKeyboardBacklightAnimationEnabled()) {
startAnimation(fromValue, toValue);
} else {
mNative.setLightColor(mDeviceId, mLight.getId(), Color.argb(toValue, 0, 0, 0));
diff --git a/services/core/java/com/android/server/input/KeyboardLayoutManager.java b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
index 6ec4022fe15a..611a61a2e272 100644
--- a/services/core/java/com/android/server/input/KeyboardLayoutManager.java
+++ b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
@@ -252,6 +252,8 @@ final class KeyboardLayoutManager implements InputManager.InputDeviceListener {
if (needToShowNotification) {
maybeUpdateNotification();
}
+ // TODO (b/280421650): Implement logging statements using KeyboardMetricsCollector
+ // for KeyboardConfigured atom
}
private String getDefaultKeyboardLayout(final InputDevice inputDevice) {
diff --git a/services/core/java/com/android/server/input/KeyboardMetricsCollector.java b/services/core/java/com/android/server/input/KeyboardMetricsCollector.java
index a9ae3121ce9f..b8f57f555c0e 100644
--- a/services/core/java/com/android/server/input/KeyboardMetricsCollector.java
+++ b/services/core/java/com/android/server/input/KeyboardMetricsCollector.java
@@ -16,10 +16,20 @@
package com.android.server.input;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
+import android.hardware.input.KeyboardLayout;
+import android.util.proto.ProtoOutputStream;
import android.view.InputDevice;
+import com.android.internal.os.KeyboardConfiguredProto.KeyboardLayoutConfig;
+import com.android.internal.os.KeyboardConfiguredProto.RepeatedKeyboardLayoutConfig;
import com.android.internal.util.FrameworkStatsLog;
+import java.lang.annotation.Retention;
+import java.util.List;
+
/**
* Collect Keyboard metrics
*/
@@ -38,4 +48,115 @@ public final class KeyboardMetricsCollector {
FrameworkStatsLog.write(FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED,
vendor_id, product_id, keyboardSystemEvent, keyCode, modifierState);
}
+
+ /**
+ * Function to log the KeyboardConfigured
+ * {@link com.android.os.input.KeyboardConfigured} atom
+ *
+ * @param inputDevice Input device
+ * @param keyboardLayoutConfigurations List of keyboard configurations
+ * @param isFirstTimeConfiguration Whether keyboard is configured for the first time
+ */
+ public static void logKeyboardConfiguredAtom(InputDevice inputDevice,
+ List<KeyboardLayoutConfiguration> keyboardLayoutConfigurations,
+ boolean isFirstTimeConfiguration) {
+ int vendor_id = inputDevice.getVendorId();
+ int product_id = inputDevice.getProductId();
+
+ // Creating proto to log nested field KeyboardLayoutConfig in atom
+ ProtoOutputStream proto = new ProtoOutputStream();
+
+ for (KeyboardLayoutConfiguration keyboardLayoutConfiguration :
+ keyboardLayoutConfigurations) {
+ addKeyboardLayoutConfigurationToProto(proto, keyboardLayoutConfiguration);
+ }
+ // Push the atom to Statsd
+ FrameworkStatsLog.write(FrameworkStatsLog.KEYBOARD_CONFIGURED,
+ isFirstTimeConfiguration, vendor_id, product_id, proto.getBytes());
+ }
+
+ /**
+ * Populate the KeyboardLayoutConfig proto which is a repeated proto
+ * in the RepeatedKeyboardLayoutConfig proto with values from the
+ * {@link KeyboardLayoutConfiguration} class
+ * The proto definitions can be found at:
+ * "frameworks/proto_logging/stats/atoms/input/input_extension_atoms.proto"
+ *
+ * @param proto Representing the nested proto RepeatedKeyboardLayoutConfig
+ * @param keyboardLayoutConfiguration Class containing the fields for populating the
+ * KeyboardLayoutConfig proto
+ */
+ private static void addKeyboardLayoutConfigurationToProto(ProtoOutputStream proto,
+ KeyboardLayoutConfiguration keyboardLayoutConfiguration) {
+ // Start a new KeyboardLayoutConfig proto.
+ long keyboardLayoutConfigToken = proto.start(
+ RepeatedKeyboardLayoutConfig.KEYBOARD_LAYOUT_CONFIG);
+ proto.write(KeyboardLayoutConfig.KEYBOARD_LANGUAGE_TAG,
+ keyboardLayoutConfiguration.getKeyboardLanguageTag());
+ proto.write(KeyboardLayoutConfig.KEYBOARD_LAYOUT_TYPE,
+ keyboardLayoutConfiguration.getKeyboardLayoutType());
+ proto.write(KeyboardLayoutConfig.KEYBOARD_LAYOUT_NAME,
+ keyboardLayoutConfiguration.getKeyboardLayoutName());
+ proto.write(KeyboardLayoutConfig.LAYOUT_SELECTION_CRITERIA,
+ keyboardLayoutConfiguration.getLayoutSelectionCriteria());
+ proto.end(keyboardLayoutConfigToken);
+ }
+
+ /**
+ * Java class representing the proto KeyboardLayoutConfig defined in
+ * "frameworks/proto_logging/stats/atoms/input/input_extension_atoms.proto"
+ *
+ * @see com.android.os.input.KeyboardConfigured
+ */
+ public static class KeyboardLayoutConfiguration {
+ // KeyboardLayoutType in "frameworks/base/core/res/res/values/attrs.xml"
+ // contains mapping for enums to int
+ int mKeyboardLayoutType;
+ String mKeyboardLanguageTag;
+ KeyboardLayout mKeyboardLayout;
+ @LayoutSelectionCriteria int mLayoutSelectionCriteria;
+
+ @Retention(SOURCE)
+ @IntDef(prefix = { "LAYOUT_SELECTION_CRITERIA_" }, value = {
+ LAYOUT_SELECTION_CRITERIA_USER,
+ LAYOUT_SELECTION_CRITERIA_DEVICE,
+ LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD
+ })
+ public @interface LayoutSelectionCriteria {}
+
+ /** Manual selection by user */
+ public static final int LAYOUT_SELECTION_CRITERIA_USER = 0;
+
+ /** Auto-detection based on device provided language tag and layout type */
+ public static final int LAYOUT_SELECTION_CRITERIA_DEVICE = 1;
+
+ /** Auto-detection based on IME provided language tag and layout type */
+ public static final int LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD = 2;
+
+ KeyboardLayoutConfiguration(int keyboardLayoutType,
+ String keyboardLanguageTag,
+ KeyboardLayout keyboardLayout,
+ @LayoutSelectionCriteria int layoutSelectionCriteria) {
+ mKeyboardLayoutType = keyboardLayoutType;
+ mKeyboardLanguageTag = keyboardLanguageTag;
+ mKeyboardLayout = keyboardLayout;
+ mLayoutSelectionCriteria = layoutSelectionCriteria;
+ }
+ int getKeyboardLayoutType() {
+ return mKeyboardLayoutType;
+ }
+
+ String getKeyboardLanguageTag() {
+ return mKeyboardLanguageTag;
+ }
+
+ String getKeyboardLayoutName() {
+ return mKeyboardLayout.getLabel();
+ }
+
+ @LayoutSelectionCriteria int getLayoutSelectionCriteria() {
+ return mLayoutSelectionCriteria;
+ }
+ }
}
+
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 952678408343..b1a289f046bd 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1095,6 +1095,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final DreamManagerInternal dreamManagerInternal = getDreamManagerInternal();
if (dreamManagerInternal == null || !dreamManagerInternal.canStartDreaming(isScreenOn)) {
+ Slog.d(TAG, "Can't start dreaming when attempting to dream from short power"
+ + " press (isScreenOn=" + isScreenOn + ")");
noDreamAction.run();
return;
}
@@ -6051,6 +6053,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/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 3e3eb570d0e3..7f9352b32ac5 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -2925,15 +2925,6 @@ class ActivityStarter {
}
}
- // If the matching task is already in the adjacent task of the launch target. Adjust to use
- // the adjacent task as its launch target. So the existing task will be launched into the
- // closer one and won't be reparent redundantly.
- final Task adjacentTargetTask = mTargetRootTask.getAdjacentTask();
- if (adjacentTargetTask != null && intentActivity.isDescendantOf(adjacentTargetTask)
- && intentTask.isOnTop()) {
- mTargetRootTask = adjacentTargetTask;
- }
-
// If the target task is not in the front, then we need to bring it to the front...
// except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
// the same behavior as if a new instance was being started, which means not bringing it
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 89862918744c..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;
@@ -5869,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/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e44d27911262..6aec96988a77 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -6511,6 +6511,22 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
.getKeyguardController().isDisplayOccluded(mDisplayId);
}
+ /**
+ * @return the task that is occluding the keyguard
+ */
+ @Nullable
+ Task getTaskOccludingKeyguard() {
+ final KeyguardController keyguardController = mRootWindowContainer.mTaskSupervisor
+ .getKeyguardController();
+ if (keyguardController.getTopOccludingActivity(mDisplayId) != null) {
+ return keyguardController.getTopOccludingActivity(mDisplayId).getRootTask();
+ }
+ if (keyguardController.getDismissKeyguardActivity(mDisplayId) != null) {
+ return keyguardController.getDismissKeyguardActivity(mDisplayId).getRootTask();
+ }
+ return null;
+ }
+
@VisibleForTesting
void removeAllTasks() {
forAllTasks((t) -> { t.getRootTask().removeChild(t, "removeAllTasks"); });
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 35e891ce8bbe..812d2a5d3217 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/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/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 5f6d66011768..99878a3d0ffe 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
@@ -411,19 +410,20 @@ class KeyguardController {
if (waitAppTransition) {
mService.deferWindowLayout();
try {
- mRootWindowContainer.getDefaultDisplay()
- .requestTransitionAndLegacyPrepare(
- isDisplayOccluded(DEFAULT_DISPLAY)
- ? TRANSIT_KEYGUARD_OCCLUDE
- : TRANSIT_KEYGUARD_UNOCCLUDE, 0 /* flags */);
+ if (isDisplayOccluded(DEFAULT_DISPLAY)) {
+ mRootWindowContainer.getDefaultDisplay().requestTransitionAndLegacyPrepare(
+ TRANSIT_KEYGUARD_OCCLUDE,
+ topActivity != null ? topActivity.getRootTask() : null);
+ } else {
+ mRootWindowContainer.getDefaultDisplay().requestTransitionAndLegacyPrepare(
+ TRANSIT_KEYGUARD_UNOCCLUDE, 0 /* flags */);
+ }
updateKeyguardSleepToken(DEFAULT_DISPLAY);
mWindowManager.executeAppTransition();
} finally {
mService.continueWindowLayout();
}
}
- dismissMultiWindowModeForTaskIfNeeded(displayId, topActivity != null
- ? topActivity.getRootTask() : null);
}
/**
@@ -473,6 +473,14 @@ class KeyguardController {
return getDisplayState(displayId).mOccluded;
}
+ ActivityRecord getTopOccludingActivity(int displayId) {
+ return getDisplayState(displayId).mTopOccludesActivity;
+ }
+
+ ActivityRecord getDismissKeyguardActivity(int displayId) {
+ return getDisplayState(displayId).mDismissingKeyguardActivity;
+ }
+
/**
* @return true if Keyguard can be currently dismissed without entering credentials.
*/
@@ -488,22 +496,6 @@ class KeyguardController {
return getDisplayState(DEFAULT_DISPLAY).mShowingDream;
}
- private void dismissMultiWindowModeForTaskIfNeeded(int displayId,
- @Nullable Task currentTaskControllingOcclusion) {
- // TODO(b/113840485): Handle docked stack for individual display.
- if (!getDisplayState(displayId).mKeyguardShowing || !isDisplayOccluded(DEFAULT_DISPLAY)) {
- return;
- }
-
- // Dismiss freeform windowing mode
- if (currentTaskControllingOcclusion == null) {
- return;
- }
- if (currentTaskControllingOcclusion.inFreeformWindowingMode()) {
- currentTaskControllingOcclusion.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- }
- }
-
private void updateKeyguardSleepToken() {
for (int displayNdx = mRootWindowContainer.getChildCount() - 1;
displayNdx >= 0; displayNdx--) {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 536915929e88..7e839596c59b 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2376,6 +2376,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
if (!displayShouldSleep && display.mTransitionController.isShellTransitionsEnabled()
&& !display.mTransitionController.isCollecting()) {
int transit = TRANSIT_NONE;
+ Task startTask = null;
if (!display.getDisplayPolicy().isAwake()) {
// Note that currently this only happens on default display because non-default
// display is always awake.
@@ -2383,12 +2384,12 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
} else if (display.isKeyguardOccluded()) {
// The display was awake so this is resuming activity for occluding keyguard.
transit = WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
+ startTask = display.getTaskOccludingKeyguard();
}
if (transit != TRANSIT_NONE) {
display.mTransitionController.requestStartTransition(
display.mTransitionController.createTransition(transit),
- null /* startTask */, null /* remoteTransition */,
- null /* displayChange */);
+ startTask, null /* remoteTransition */, null /* displayChange */);
}
}
// Set the sleeping state of the root tasks on the display.
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 663db861b79e..b938b9e4ec51 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();
@@ -2245,8 +2249,10 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
while (leashReference.getParent() != ancestor) {
leashReference = leashReference.getParent();
}
+
final SurfaceControl rootLeash = leashReference.makeAnimationLeash().setName(
"Transition Root: " + leashReference.getName()).build();
+ rootLeash.setUnreleasedWarningCallSite("Transition.calculateTransitionRoots");
startT.setLayer(rootLeash, leashReference.getLastLayer());
outInfo.addRootLeash(endDisplayId, rootLeash,
ancestor.getBounds().left, ancestor.getBounds().top);
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 2f1bf35a5ca8..8587270dd187 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -2214,13 +2214,25 @@ static jobject nativeGetLights(JNIEnv* env, jobject nativeImplObj, jint deviceId
jCapability |= env->GetStaticIntField(gLightClassInfo.clazz,
gLightClassInfo.lightCapabilityColorRgb);
}
+
+ ScopedLocalRef<jintArray> jPreferredBrightnessLevels{env};
+ if (!lightInfo.preferredBrightnessLevels.empty()) {
+ std::vector<int32_t> vec;
+ for (auto it : lightInfo.preferredBrightnessLevels) {
+ vec.push_back(ftl::to_underlying(it));
+ }
+ jPreferredBrightnessLevels.reset(env->NewIntArray(vec.size()));
+ env->SetIntArrayRegion(jPreferredBrightnessLevels.get(), 0, vec.size(), vec.data());
+ }
+
ScopedLocalRef<jobject> lightObj(env,
env->NewObject(gLightClassInfo.clazz,
gLightClassInfo.constructor,
static_cast<jint>(lightInfo.id),
env->NewStringUTF(lightInfo.name.c_str()),
static_cast<jint>(lightInfo.ordinal),
- jTypeId, jCapability));
+ jTypeId, jCapability,
+ jPreferredBrightnessLevels.get()));
// Add light object to list
env->CallBooleanMethod(jLights, gArrayListClassInfo.add, lightObj.get());
}
@@ -2846,7 +2858,7 @@ int register_android_server_InputManager(JNIEnv* env) {
FIND_CLASS(gLightClassInfo.clazz, "android/hardware/lights/Light");
gLightClassInfo.clazz = jclass(env->NewGlobalRef(gLightClassInfo.clazz));
GET_METHOD_ID(gLightClassInfo.constructor, gLightClassInfo.clazz, "<init>",
- "(ILjava/lang/String;III)V");
+ "(ILjava/lang/String;III[I)V");
gLightClassInfo.clazz = jclass(env->NewGlobalRef(gLightClassInfo.clazz));
gLightClassInfo.lightTypeInput =
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/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
index d5d06d3b4eb8..046b01c831b5 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
@@ -16,8 +16,10 @@
package com.android.server.biometrics.sensors.face.aidl;
+import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED;
import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT;
import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -205,7 +207,9 @@ public class FaceAuthenticationClientTest {
client.onAuthenticated(new Face("friendly", 1 /* faceId */, 2 /* deviceId */),
true /* authenticated */, new ArrayList<>());
- verify(mCancellationSignal).cancel();
+ verify(mCancellationSignal, never()).cancel();
+ verify(mClientMonitorCallbackConverter)
+ .onError(anyInt(), anyInt(), eq(BIOMETRIC_ERROR_CANCELED), anyInt());
}
private FaceAuthenticationClient createClient() throws RemoteException {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
index f8f40fe44457..c383a96d5de3 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
@@ -16,6 +16,8 @@
package com.android.server.biometrics.sensors.fingerprint.aidl;
+import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -399,7 +401,9 @@ public class FingerprintAuthenticationClientTest {
mLooper.moveTimeForward(10);
mLooper.dispatchAll();
- verify(mCancellationSignal).cancel();
+ verify(mCancellationSignal, never()).cancel();
+ verify(mClientMonitorCallbackConverter)
+ .onError(anyInt(), anyInt(), eq(BIOMETRIC_ERROR_CANCELED), anyInt());
}
private FingerprintAuthenticationClient createClient() throws RemoteException {
diff --git a/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt b/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt
index 272679280a62..ef15ccba4c74 100644
--- a/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt
+++ b/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt
@@ -32,7 +32,8 @@ import android.platform.test.annotations.Presubmit
import android.view.InputDevice
import androidx.test.annotation.UiThreadTest
import androidx.test.core.app.ApplicationProvider
-import com.android.server.input.KeyboardBacklightController.BRIGHTNESS_VALUE_FOR_LEVEL
+import com.android.server.input.KeyboardBacklightController.DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL
+import com.android.server.input.KeyboardBacklightController.MAX_BRIGHTNESS_CHANGE_STEPS
import com.android.server.input.KeyboardBacklightController.USER_INACTIVITY_THRESHOLD_MILLIS
import org.junit.After
import org.junit.Assert.assertEquals
@@ -65,12 +66,20 @@ private fun createKeyboard(deviceId: Int): InputDevice =
.build()
private fun createLight(lightId: Int, lightType: Int): Light =
+ createLight(
+ lightId,
+ lightType,
+ null
+ )
+
+private fun createLight(lightId: Int, lightType: Int, suggestedBrightnessLevels: IntArray?): Light =
Light(
lightId,
"Light $lightId",
1,
lightType,
- Light.LIGHT_CAPABILITY_BRIGHTNESS
+ Light.LIGHT_CAPABILITY_BRIGHTNESS,
+ suggestedBrightnessLevels
)
/**
* Tests for {@link KeyboardBacklightController}.
@@ -98,7 +107,6 @@ class KeyboardBacklightControllerTests {
private lateinit var context: Context
private lateinit var dataStore: PersistentDataStore
private lateinit var testLooper: TestLooper
- private val totalLevels = BRIGHTNESS_VALUE_FOR_LEVEL.size
private var lightColorMap: HashMap<Int, Int> = HashMap()
private var lastBacklightState: KeyboardBacklightState? = null
private var sysfsNodeChanges = 0
@@ -146,84 +154,21 @@ class KeyboardBacklightControllerTests {
@Test
fun testKeyboardBacklightIncrementDecrement() {
- BacklightAnimationFlag(false).use {
+ KeyboardBacklightFlags(animationEnabled = false, customLevelsEnabled = false).use {
val keyboardWithBacklight = createKeyboard(DEVICE_ID)
val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
`when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
- for (level in 1 until totalLevels) {
- incrementKeyboardBacklight(DEVICE_ID)
- assertEquals(
- "Light value for level $level mismatched",
- Color.argb(BRIGHTNESS_VALUE_FOR_LEVEL[level], 0, 0, 0),
- lightColorMap[LIGHT_ID]
- )
- assertEquals(
- "Light value for level $level must be correctly stored in the datastore",
- BRIGHTNESS_VALUE_FOR_LEVEL[level],
- dataStore.getKeyboardBacklightBrightness(
- keyboardWithBacklight.descriptor,
- LIGHT_ID
- ).asInt
- )
- }
-
- // Increment above max level
- incrementKeyboardBacklight(DEVICE_ID)
- assertEquals(
- "Light value for max level mismatched",
- Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
- lightColorMap[LIGHT_ID]
- )
- assertEquals(
- "Light value for max level must be correctly stored in the datastore",
- MAX_BRIGHTNESS,
- dataStore.getKeyboardBacklightBrightness(
- keyboardWithBacklight.descriptor,
- LIGHT_ID
- ).asInt
- )
-
- for (level in totalLevels - 2 downTo 0) {
- decrementKeyboardBacklight(DEVICE_ID)
- assertEquals(
- "Light value for level $level mismatched",
- Color.argb(BRIGHTNESS_VALUE_FOR_LEVEL[level], 0, 0, 0),
- lightColorMap[LIGHT_ID]
- )
- assertEquals(
- "Light value for level $level must be correctly stored in the datastore",
- BRIGHTNESS_VALUE_FOR_LEVEL[level],
- dataStore.getKeyboardBacklightBrightness(
- keyboardWithBacklight.descriptor,
- LIGHT_ID
- ).asInt
- )
- }
-
- // Decrement below min level
- decrementKeyboardBacklight(DEVICE_ID)
- assertEquals(
- "Light value for min level mismatched",
- Color.argb(0, 0, 0, 0),
- lightColorMap[LIGHT_ID]
- )
- assertEquals(
- "Light value for min level must be correctly stored in the datastore",
- 0,
- dataStore.getKeyboardBacklightBrightness(
- keyboardWithBacklight.descriptor,
- LIGHT_ID
- ).asInt
- )
+ assertIncrementDecrementForLevels(keyboardWithBacklight, keyboardBacklight,
+ DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL)
}
}
@Test
fun testKeyboardWithoutBacklight() {
- BacklightAnimationFlag(false).use {
+ KeyboardBacklightFlags(animationEnabled = false, customLevelsEnabled = false).use {
val keyboardWithoutBacklight = createKeyboard(DEVICE_ID)
val keyboardInputLight = createLight(LIGHT_ID, Light.LIGHT_TYPE_INPUT)
`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithoutBacklight)
@@ -237,7 +182,7 @@ class KeyboardBacklightControllerTests {
@Test
fun testKeyboardWithMultipleLight() {
- BacklightAnimationFlag(false).use {
+ KeyboardBacklightFlags(animationEnabled = false, customLevelsEnabled = false).use {
val keyboardWithBacklight = createKeyboard(DEVICE_ID)
val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
val keyboardInputLight = createLight(SECOND_LIGHT_ID, Light.LIGHT_TYPE_INPUT)
@@ -259,17 +204,17 @@ class KeyboardBacklightControllerTests {
@Test
fun testRestoreBacklightOnInputDeviceAdded() {
- BacklightAnimationFlag(false).use {
+ KeyboardBacklightFlags(animationEnabled = false, customLevelsEnabled = false).use {
val keyboardWithBacklight = createKeyboard(DEVICE_ID)
val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
`when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
- for (level in 1 until totalLevels) {
+ for (level in 1 until DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL.size) {
dataStore.setKeyboardBacklightBrightness(
keyboardWithBacklight.descriptor,
LIGHT_ID,
- BRIGHTNESS_VALUE_FOR_LEVEL[level] - 1
+ DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL[level] - 1
)
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
@@ -278,7 +223,7 @@ class KeyboardBacklightControllerTests {
assertEquals(
"Keyboard backlight level should be restored to the level saved in the " +
"data store",
- Color.argb(BRIGHTNESS_VALUE_FOR_LEVEL[level], 0, 0, 0),
+ Color.argb(DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL[level], 0, 0, 0),
lightColorMap[LIGHT_ID]
)
keyboardBacklightController.onInputDeviceRemoved(DEVICE_ID)
@@ -288,7 +233,7 @@ class KeyboardBacklightControllerTests {
@Test
fun testRestoreBacklightOnInputDeviceChanged() {
- BacklightAnimationFlag(false).use {
+ KeyboardBacklightFlags(animationEnabled = false, customLevelsEnabled = false).use {
val keyboardWithBacklight = createKeyboard(DEVICE_ID)
val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
@@ -320,9 +265,10 @@ class KeyboardBacklightControllerTests {
@Test
fun testKeyboardBacklight_registerUnregisterListener() {
- BacklightAnimationFlag(false).use {
+ KeyboardBacklightFlags(animationEnabled = false, customLevelsEnabled = false).use {
val keyboardWithBacklight = createKeyboard(DEVICE_ID)
val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
+ val maxLevel = DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL.size - 1
`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
`when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
@@ -341,13 +287,13 @@ class KeyboardBacklightControllerTests {
lastBacklightState!!.deviceId
)
assertEquals(
- "Backlight state brightnessLevel should be " + 1,
+ "Backlight state brightnessLevel should be 1",
1,
lastBacklightState!!.brightnessLevel
)
assertEquals(
- "Backlight state maxBrightnessLevel should be " + (totalLevels - 1),
- (totalLevels - 1),
+ "Backlight state maxBrightnessLevel should be $maxLevel",
+ maxLevel,
lastBacklightState!!.maxBrightnessLevel
)
assertEquals(
@@ -368,7 +314,7 @@ class KeyboardBacklightControllerTests {
@Test
fun testKeyboardBacklight_userActivity() {
- BacklightAnimationFlag(false).use {
+ KeyboardBacklightFlags(animationEnabled = false, customLevelsEnabled = false).use {
val keyboardWithBacklight = createKeyboard(DEVICE_ID)
val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
@@ -400,7 +346,7 @@ class KeyboardBacklightControllerTests {
@Test
fun testKeyboardBacklight_displayOnOff() {
- BacklightAnimationFlag(false).use {
+ KeyboardBacklightFlags(animationEnabled = false, customLevelsEnabled = false).use {
val keyboardWithBacklight = createKeyboard(DEVICE_ID)
val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
@@ -490,7 +436,7 @@ class KeyboardBacklightControllerTests {
@Test
@UiThreadTest
fun testKeyboardBacklightAnimation_onChangeLevels() {
- BacklightAnimationFlag(true).use {
+ KeyboardBacklightFlags(animationEnabled = true, customLevelsEnabled = false).use {
val keyboardWithBacklight = createKeyboard(DEVICE_ID)
val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
@@ -500,17 +446,145 @@ class KeyboardBacklightControllerTests {
incrementKeyboardBacklight(DEVICE_ID)
assertEquals(
"Should start animation from level 0",
- BRIGHTNESS_VALUE_FOR_LEVEL[0],
+ DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL[0],
lastAnimationValues[0]
)
assertEquals(
"Should start animation to level 1",
- BRIGHTNESS_VALUE_FOR_LEVEL[1],
+ DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL[1],
lastAnimationValues[1]
)
}
}
+ @Test
+ fun testKeyboardBacklightPreferredLevels() {
+ KeyboardBacklightFlags(animationEnabled = false, customLevelsEnabled = true).use {
+ val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+ val suggestedLevels = intArrayOf(0, 22, 63, 135, 196, 255)
+ val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT,
+ suggestedLevels)
+ `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+ `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+ keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+
+ assertIncrementDecrementForLevels(keyboardWithBacklight, keyboardBacklight,
+ suggestedLevels)
+ }
+ }
+
+ @Test
+ fun testKeyboardBacklightPreferredLevels_moreThanMax_shouldUseDefault() {
+ KeyboardBacklightFlags(animationEnabled = false, customLevelsEnabled = true).use {
+ val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+ val suggestedLevels = IntArray(MAX_BRIGHTNESS_CHANGE_STEPS + 1) { 10 * (it + 1) }
+ val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT,
+ suggestedLevels)
+ `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+ `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+ keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+
+ assertIncrementDecrementForLevels(keyboardWithBacklight, keyboardBacklight,
+ DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL)
+ }
+ }
+
+ @Test
+ fun testKeyboardBacklightPreferredLevels_mustHaveZeroAndMaxBrightnessAsBounds() {
+ KeyboardBacklightFlags(animationEnabled = false, customLevelsEnabled = true).use {
+ val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+ val suggestedLevels = intArrayOf(22, 63, 135, 196)
+ val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT,
+ suggestedLevels)
+ `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+ `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+ keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+
+ // Framework will add the lowest and maximum levels if not provided via config
+ assertIncrementDecrementForLevels(keyboardWithBacklight, keyboardBacklight,
+ intArrayOf(0, 22, 63, 135, 196, 255))
+ }
+ }
+
+ @Test
+ fun testKeyboardBacklightPreferredLevels_dropsOutOfBoundsLevels() {
+ KeyboardBacklightFlags(animationEnabled = false, customLevelsEnabled = true).use {
+ val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+ val suggestedLevels = intArrayOf(22, 63, 135, 400, 196, 1000)
+ val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT,
+ suggestedLevels)
+ `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+ `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+ keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+
+ // Framework will drop out of bound levels in the config
+ assertIncrementDecrementForLevels(keyboardWithBacklight, keyboardBacklight,
+ intArrayOf(0, 22, 63, 135, 196, 255))
+ }
+ }
+
+ private fun assertIncrementDecrementForLevels(
+ device: InputDevice,
+ light: Light,
+ expectedLevels: IntArray
+ ) {
+ val deviceId = device.id
+ val lightId = light.id
+ for (level in 1 until expectedLevels.size) {
+ incrementKeyboardBacklight(deviceId)
+ assertEquals(
+ "Light value for level $level mismatched",
+ Color.argb(expectedLevels[level], 0, 0, 0),
+ lightColorMap[lightId]
+ )
+ assertEquals(
+ "Light value for level $level must be correctly stored in the datastore",
+ expectedLevels[level],
+ dataStore.getKeyboardBacklightBrightness(device.descriptor, lightId).asInt
+ )
+ }
+
+ // Increment above max level
+ incrementKeyboardBacklight(deviceId)
+ assertEquals(
+ "Light value for max level mismatched",
+ Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
+ lightColorMap[lightId]
+ )
+ assertEquals(
+ "Light value for max level must be correctly stored in the datastore",
+ MAX_BRIGHTNESS,
+ dataStore.getKeyboardBacklightBrightness(device.descriptor, lightId).asInt
+ )
+
+ for (level in expectedLevels.size - 2 downTo 0) {
+ decrementKeyboardBacklight(deviceId)
+ assertEquals(
+ "Light value for level $level mismatched",
+ Color.argb(expectedLevels[level], 0, 0, 0),
+ lightColorMap[lightId]
+ )
+ assertEquals(
+ "Light value for level $level must be correctly stored in the datastore",
+ expectedLevels[level],
+ dataStore.getKeyboardBacklightBrightness(device.descriptor, lightId).asInt
+ )
+ }
+
+ // Decrement below min level
+ decrementKeyboardBacklight(deviceId)
+ assertEquals(
+ "Light value for min level mismatched",
+ Color.argb(0, 0, 0, 0),
+ lightColorMap[lightId]
+ )
+ assertEquals(
+ "Light value for min level must be correctly stored in the datastore",
+ 0,
+ dataStore.getKeyboardBacklightBrightness(device.descriptor, lightId).asInt
+ )
+ }
+
inner class KeyboardBacklightListener : IKeyboardBacklightListener.Stub() {
override fun onBrightnessChanged(
deviceId: Int,
@@ -545,9 +619,13 @@ class KeyboardBacklightControllerTests {
val isTriggeredByKeyPress: Boolean
)
- private inner class BacklightAnimationFlag constructor(enabled: Boolean) : AutoCloseable {
+ private inner class KeyboardBacklightFlags constructor(
+ animationEnabled: Boolean,
+ customLevelsEnabled: Boolean
+ ) : AutoCloseable {
init {
- InputFeatureFlagProvider.setKeyboardBacklightAnimationEnabled(enabled)
+ InputFeatureFlagProvider.setKeyboardBacklightAnimationEnabled(animationEnabled)
+ InputFeatureFlagProvider.setKeyboardBacklightCustomLevelsEnabled(customLevelsEnabled)
}
override fun close() {
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 866260757df9..114796d17ef1 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;
@@ -419,10 +421,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());
@@ -430,7 +432,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());
@@ -546,6 +550,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);
@@ -553,6 +558,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()