summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apct-tests/perftests/core/src/android/text/VariableFontPerfTest.java28
-rw-r--r--core/java/android/app/ActivityOptions.java10
-rw-r--r--core/java/android/app/ContextImpl.java30
-rw-r--r--core/java/android/hardware/biometrics/BiometricConstants.java7
-rw-r--r--core/java/android/hardware/biometrics/BiometricManager.java18
-rw-r--r--core/java/android/hardware/input/IInputManager.aidl14
-rw-r--r--core/java/android/hardware/input/IKeyGestureEventListener.aidl (renamed from core/java/android/hardware/input/IKeyboardSystemShortcutListener.aidl)7
-rw-r--r--core/java/android/hardware/input/InputManager.java43
-rw-r--r--core/java/android/hardware/input/InputManagerGlobal.java94
-rw-r--r--core/java/android/hardware/input/KeyGestureEvent.java531
-rw-r--r--core/java/android/hardware/input/KeyboardSystemShortcut.java522
-rw-r--r--core/java/android/permission/flags.aconfig11
-rw-r--r--core/java/android/text/flags/flags.aconfig20
-rw-r--r--core/java/android/view/contentprotection/OWNERS6
-rw-r--r--core/java/android/window/flags/windowing_frontend.aconfig8
-rw-r--r--core/java/com/android/internal/protolog/LegacyProtoLogImpl.java9
-rw-r--r--core/jni/android_database_SQLiteRawStatement.cpp43
-rw-r--r--core/res/AndroidManifest.xml4
-rw-r--r--core/res/res/drawable-car/car_activity_resolver_list_background.xml20
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_animal_paw.xml25
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_apartment_building.xml25
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_book.xml26
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_child.xml25
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_classical_building.xml25
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_croissant.xml25
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_fork_and_knife.xml25
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_group_of_people.xml25
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_headphones.xml25
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_heart.xml25
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_house.xml25
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_lightbulb.xml25
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_palette.xml25
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_rabbit.xml25
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_running.xml26
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_shopping_cart.xml25
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_snowflake.xml25
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_speech_bubble.xml25
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_train.xml25
-rw-r--r--core/res/res/drawable/ic_zen_mode_icon_tv.xml25
-rw-r--r--core/res/res/layout-car/car_resolver_list.xml127
-rw-r--r--core/res/res/layout-car/car_resolver_list_with_default.xml159
-rw-r--r--core/res/res/values/config_telephony.xml7
-rw-r--r--core/tests/coretests/src/android/database/sqlite/SQLiteRawStatementTest.java27
-rw-r--r--core/tests/coretests/src/android/graphics/PaintFontVariationTest.java74
-rw-r--r--core/tests/coretests/src/android/graphics/PaintTest.java41
-rw-r--r--core/tests/coretests/src/android/view/contentprotection/OWNERS4
-rw-r--r--graphics/java/android/graphics/Typeface.java88
-rw-r--r--libs/WindowManager/Shell/res/values/dimen.xml13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java29
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java58
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt13
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java59
-rw-r--r--nfc/api/system-current.txt1
-rw-r--r--nfc/java/android/nfc/INfcAdapter.aidl1
-rw-r--r--nfc/java/android/nfc/NfcOemExtension.java15
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioSharingRepository.kt7
-rw-r--r--packages/SystemUI/aconfig/systemui.aconfig10
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt13
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractorTest.kt220
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt19
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt26
-rw-r--r--packages/SystemUI/res-keyguard/values-ar/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-ru/strings.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/SwipeHelper.java60
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractor.kt140
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/smartspace/SmartspaceInteractionHandler.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalAppWidgetHostViewBinder.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/util/InteractionHandlerDelegate.kt29
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt57
-rw-r--r--packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt23
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt36
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt110
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt70
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt108
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt71
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java23
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt87
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt49
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractorKosmos.kt37
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/plugins/DarkIconDispatcherKosmos.kt22
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/plugins/FakeDarkIconDispatcher.kt36
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/shared/system/TaskStackChangeListenersKosmos.kt22
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioSharingRepository.kt3
-rw-r--r--services/contentcapture/java/com/android/server/contentprotection/OWNERS4
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java16
-rw-r--r--services/core/java/com/android/server/biometrics/PreAuthInfo.java32
-rw-r--r--services/core/java/com/android/server/biometrics/Utils.java11
-rw-r--r--services/core/java/com/android/server/devicestate/DeviceStateManagerService.java10
-rw-r--r--services/core/java/com/android/server/input/InputManagerInternal.java20
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java59
-rw-r--r--services/core/java/com/android/server/input/KeyGestureController.java134
-rw-r--r--services/core/java/com/android/server/input/KeyboardMetricsCollector.java13
-rw-r--r--services/core/java/com/android/server/input/KeyboardShortcutCallbackHandler.java137
-rw-r--r--services/core/java/com/android/server/notification/NotificationAttentionHelper.java8
-rw-r--r--services/core/java/com/android/server/policy/ModifierShortcutManager.java86
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java244
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityController.java3
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java1
-rw-r--r--services/core/java/com/android/server/wm/Task.java9
-rw-r--r--services/tests/servicestests/Android.bp322
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java35
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java20
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java40
-rw-r--r--services/tests/servicestests/src/com/android/server/contentprotection/OWNERS5
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java19
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java (renamed from services/tests/wmtests/src/com/android/server/policy/KeyboardSystemShortcutTests.java)202
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java7
-rw-r--r--telephony/java/android/telephony/satellite/ISatelliteProvisionStateCallback.aidl12
-rw-r--r--telephony/java/android/telephony/satellite/SatelliteManager.java10
-rw-r--r--telephony/java/android/telephony/satellite/SatelliteProvisionStateCallback.java15
-rw-r--r--telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.aidl19
-rw-r--r--telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java174
-rw-r--r--tests/Input/src/android/hardware/input/KeyGestureEventListenerTest.kt (renamed from tests/Input/src/android/hardware/input/KeyboardSystemShortcutListenerTest.kt)94
-rw-r--r--tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt (renamed from tests/Input/src/com/android/server/input/KeyboardShortcutCallbackHandlerTests.kt)54
-rw-r--r--tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java7
-rw-r--r--tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostSyncTest.java1
-rw-r--r--tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java1
-rw-r--r--tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java1
141 files changed, 4082 insertions, 1927 deletions
diff --git a/apct-tests/perftests/core/src/android/text/VariableFontPerfTest.java b/apct-tests/perftests/core/src/android/text/VariableFontPerfTest.java
index fbe67a477f5d..c34936f930f9 100644
--- a/apct-tests/perftests/core/src/android/text/VariableFontPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/VariableFontPerfTest.java
@@ -19,6 +19,7 @@ package android.text;
import android.graphics.Paint;
import android.graphics.RecordingCanvas;
import android.graphics.RenderNode;
+import android.graphics.Typeface;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
@@ -120,13 +121,34 @@ public class VariableFontPerfTest {
public void testSetFontVariationSettings() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
final Paint paint = new Paint(PAINT);
- final Random random = new Random(0);
while (state.keepRunning()) {
state.pauseTiming();
- int weight = random.nextInt(1000);
+ paint.setTypeface(null);
+ paint.setFontVariationSettings(null);
+ Typeface.clearTypefaceCachesForTestingPurpose();
state.resumeTiming();
- paint.setFontVariationSettings("'wght' " + weight);
+ paint.setFontVariationSettings("'wght' 450");
+ }
+ Typeface.clearTypefaceCachesForTestingPurpose();
+ }
+
+ @Test
+ public void testSetFontVariationSettings_Cached() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final Paint paint = new Paint(PAINT);
+ Typeface.clearTypefaceCachesForTestingPurpose();
+
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ paint.setTypeface(null);
+ paint.setFontVariationSettings(null);
+ state.resumeTiming();
+
+ paint.setFontVariationSettings("'wght' 450");
}
+
+ Typeface.clearTypefaceCachesForTestingPurpose();
}
+
}
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 65acd49d44fa..91aa225039a4 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -1587,6 +1587,16 @@ public class ActivityOptions extends ComponentOptions {
}
}
+ /** @hide */
+ public static boolean hasLaunchTargetContainer(ActivityOptions options) {
+ return options.getLaunchDisplayId() != INVALID_DISPLAY
+ || options.getLaunchTaskDisplayArea() != null
+ || options.getLaunchTaskDisplayAreaFeatureId() != FEATURE_UNDEFINED
+ || options.getLaunchRootTask() != null
+ || options.getLaunchTaskId() != -1
+ || options.getLaunchTaskFragmentToken() != null;
+ }
+
/**
* Gets whether the activity is to be launched into LockTask mode.
* @return {@code true} if the activity is to be launched into LockTask mode.
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 7e2a580bec73..90fba2962a23 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1160,7 +1160,7 @@ class ContextImpl extends Context {
}
mMainThread.getInstrumentation().execStartActivity(
getOuterContext(), mMainThread.getApplicationThread(), null,
- (Activity) null, intent, -1, options);
+ (Activity) null, intent, -1, applyLaunchDisplayIfNeeded(options));
}
/** @hide */
@@ -1170,8 +1170,8 @@ class ContextImpl extends Context {
ActivityTaskManager.getService().startActivityAsUser(
mMainThread.getApplicationThread(), getOpPackageName(), getAttributionTag(),
intent, intent.resolveTypeIfNeeded(getContentResolver()),
- null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, options,
- user.getIdentifier());
+ null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null,
+ applyLaunchDisplayIfNeeded(options), user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1194,7 +1194,8 @@ class ContextImpl extends Context {
}
return mMainThread.getInstrumentation().execStartActivitiesAsUser(
getOuterContext(), mMainThread.getApplicationThread(), null,
- (Activity) null, intents, options, userHandle.getIdentifier());
+ (Activity) null, intents, applyLaunchDisplayIfNeeded(options),
+ userHandle.getIdentifier());
}
@Override
@@ -1208,7 +1209,26 @@ class ContextImpl extends Context {
}
mMainThread.getInstrumentation().execStartActivities(
getOuterContext(), mMainThread.getApplicationThread(), null,
- (Activity) null, intents, options);
+ (Activity) null, intents, applyLaunchDisplayIfNeeded(options));
+ }
+
+ private Bundle applyLaunchDisplayIfNeeded(@Nullable Bundle options) {
+ if (!isAssociatedWithDisplay()) {
+ // return if this Context has no associated display.
+ return options;
+ }
+
+ final ActivityOptions activityOptions;
+ if (options != null) {
+ activityOptions = ActivityOptions.fromBundle(options);
+ if (ActivityOptions.hasLaunchTargetContainer(activityOptions)) {
+ // return if the options already has launching target.
+ return options;
+ }
+ } else {
+ activityOptions = ActivityOptions.makeBasic();
+ }
+ return activityOptions.setLaunchDisplayId(getAssociatedDisplayId()).toBundle();
}
@Override
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index 61d87026b6e9..8975191b54c1 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -162,6 +162,13 @@ public interface BiometricConstants {
* @hide
*/
int BIOMETRIC_ERROR_POWER_PRESSED = 19;
+
+ /**
+ * Mandatory biometrics is not in effect.
+ * @hide
+ */
+ int BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE = 20;
+
/**
* This constant is only used by SystemUI. It notifies SystemUI that authentication was paused
* because the authentication attempt was unsuccessful.
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index de1cac47ff46..9bc46b9f382a 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -80,6 +80,20 @@ public class BiometricManager {
BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT;
/**
+ * Lockout error.
+ * @hide
+ */
+ public static final int BIOMETRIC_ERROR_LOCKOUT =
+ BiometricConstants.BIOMETRIC_ERROR_LOCKOUT;
+
+ /**
+ * Mandatory biometrics is not effective.
+ * @hide
+ */
+ public static final int BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE =
+ BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE;
+
+ /**
* A security vulnerability has been discovered and the sensor is unavailable until a
* security update has addressed this issue. This error can be received if for example,
* authentication was requested with {@link Authenticators#BIOMETRIC_STRONG}, but the
@@ -113,7 +127,9 @@ public class BiometricManager {
BIOMETRIC_ERROR_HW_UNAVAILABLE,
BIOMETRIC_ERROR_NONE_ENROLLED,
BIOMETRIC_ERROR_NO_HARDWARE,
- BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED})
+ BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED,
+ BIOMETRIC_ERROR_LOCKOUT,
+ BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE})
@Retention(RetentionPolicy.SOURCE)
public @interface BiometricError {}
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 98e11375f077..83f268517dab 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -25,7 +25,7 @@ import android.hardware.input.IInputDeviceBatteryListener;
import android.hardware.input.IInputDeviceBatteryState;
import android.hardware.input.IKeyboardBacklightListener;
import android.hardware.input.IKeyboardBacklightState;
-import android.hardware.input.IKeyboardSystemShortcutListener;
+import android.hardware.input.IKeyGestureEventListener;
import android.hardware.input.IStickyModifierStateListener;
import android.hardware.input.ITabletModeChangedListener;
import android.hardware.input.KeyboardLayoutSelectionResult;
@@ -241,13 +241,13 @@ interface IInputManager {
KeyGlyphMap getKeyGlyphMap(int deviceId);
- @EnforcePermission("MONITOR_KEYBOARD_SYSTEM_SHORTCUTS")
+ @EnforcePermission("MANAGE_KEY_GESTURES")
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
- + "android.Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS)")
- void registerKeyboardSystemShortcutListener(IKeyboardSystemShortcutListener listener);
+ + "android.Manifest.permission.MANAGE_KEY_GESTURES)")
+ void registerKeyGestureEventListener(IKeyGestureEventListener listener);
- @EnforcePermission("MONITOR_KEYBOARD_SYSTEM_SHORTCUTS")
+ @EnforcePermission("MANAGE_KEY_GESTURES")
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
- + "android.Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS)")
- void unregisterKeyboardSystemShortcutListener(IKeyboardSystemShortcutListener listener);
+ + "android.Manifest.permission.MANAGE_KEY_GESTURES)")
+ void unregisterKeyGestureEventListener(IKeyGestureEventListener listener);
}
diff --git a/core/java/android/hardware/input/IKeyboardSystemShortcutListener.aidl b/core/java/android/hardware/input/IKeyGestureEventListener.aidl
index 8d44917845f4..2c430f1a1c9d 100644
--- a/core/java/android/hardware/input/IKeyboardSystemShortcutListener.aidl
+++ b/core/java/android/hardware/input/IKeyGestureEventListener.aidl
@@ -17,11 +17,10 @@
package android.hardware.input;
/** @hide */
-oneway interface IKeyboardSystemShortcutListener {
+oneway interface IKeyGestureEventListener {
/**
- * Called when the keyboard system shortcut is triggered.
+ * Called when a key gesture event occurs.
*/
- void onKeyboardSystemShortcutTriggered(int deviceId, in int[] keycodes, int modifierState,
- int shortcut);
+ void onKeyGestureEvent(int deviceId, in int[] keycodes, int modifierState, int shortcut);
}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 6bc522b2b386..04cfcd880f52 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -1378,33 +1378,31 @@ public final class InputManager {
}
/**
- * Registers a keyboard system shortcut listener for {@link KeyboardSystemShortcut} being
- * triggered.
+ * Registers a key gesture event listener for {@link KeyGestureEvent} being triggered.
*
* @param executor an executor on which the callback will be called
- * @param listener the {@link KeyboardSystemShortcutListener}
+ * @param listener the {@link KeyGestureEventListener}
* @throws IllegalArgumentException if {@code listener} has already been registered previously.
* @throws NullPointerException if {@code listener} or {@code executor} is null.
* @hide
- * @see #unregisterKeyboardSystemShortcutListener(KeyboardSystemShortcutListener)
+ * @see #unregisterKeyGestureEventListener(KeyGestureEventListener)
*/
- @RequiresPermission(Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS)
- public void registerKeyboardSystemShortcutListener(@NonNull Executor executor,
- @NonNull KeyboardSystemShortcutListener listener) throws IllegalArgumentException {
- mGlobal.registerKeyboardSystemShortcutListener(executor, listener);
+ @RequiresPermission(Manifest.permission.MANAGE_KEY_GESTURES)
+ public void registerKeyGestureEventListener(@NonNull Executor executor,
+ @NonNull KeyGestureEventListener listener) throws IllegalArgumentException {
+ mGlobal.registerKeyGestureEventListener(executor, listener);
}
/**
- * Unregisters a previously added keyboard system shortcut listener.
+ * Unregisters a previously added key gesture event listener.
*
- * @param listener the {@link KeyboardSystemShortcutListener}
+ * @param listener the {@link KeyGestureEventListener}
* @hide
- * @see #registerKeyboardSystemShortcutListener(Executor, KeyboardSystemShortcutListener)
+ * @see #registerKeyGestureEventListener(Executor, KeyGestureEventListener)
*/
- @RequiresPermission(Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS)
- public void unregisterKeyboardSystemShortcutListener(
- @NonNull KeyboardSystemShortcutListener listener) {
- mGlobal.unregisterKeyboardSystemShortcutListener(listener);
+ @RequiresPermission(Manifest.permission.MANAGE_KEY_GESTURES)
+ public void unregisterKeyGestureEventListener(@NonNull KeyGestureEventListener listener) {
+ mGlobal.unregisterKeyGestureEventListener(listener);
}
/**
@@ -1510,19 +1508,18 @@ public final class InputManager {
}
/**
- * A callback used to be notified about keyboard system shortcuts being triggered.
+ * A callback used to notify about key gesture event on completion.
*
- * @see #registerKeyboardSystemShortcutListener(Executor, KeyboardSystemShortcutListener)
- * @see #unregisterKeyboardSystemShortcutListener(KeyboardSystemShortcutListener)
+ * @see #registerKeyGestureEventListener(Executor, KeyGestureEventListener)
+ * @see #unregisterKeyGestureEventListener(KeyGestureEventListener)
* @hide
*/
- public interface KeyboardSystemShortcutListener {
+ public interface KeyGestureEventListener {
/**
- * Called when a keyboard system shortcut is triggered.
+ * Called when a key gesture event occurs.
*
- * @param systemShortcut the shortcut info about the shortcut that was triggered.
+ * @param event the gesture event that occurred.
*/
- void onKeyboardSystemShortcutTriggered(int deviceId,
- @NonNull KeyboardSystemShortcut systemShortcut);
+ void onKeyGestureEvent(@NonNull KeyGestureEvent event);
}
}
diff --git a/core/java/android/hardware/input/InputManagerGlobal.java b/core/java/android/hardware/input/InputManagerGlobal.java
index f7fa5577a047..03cf7c5f926c 100644
--- a/core/java/android/hardware/input/InputManagerGlobal.java
+++ b/core/java/android/hardware/input/InputManagerGlobal.java
@@ -25,8 +25,8 @@ import android.hardware.BatteryState;
import android.hardware.SensorManager;
import android.hardware.input.InputManager.InputDeviceBatteryListener;
import android.hardware.input.InputManager.InputDeviceListener;
+import android.hardware.input.InputManager.KeyGestureEventListener;
import android.hardware.input.InputManager.KeyboardBacklightListener;
-import android.hardware.input.InputManager.KeyboardSystemShortcutListener;
import android.hardware.input.InputManager.OnTabletModeChangedListener;
import android.hardware.input.InputManager.StickyModifierStateListener;
import android.hardware.lights.Light;
@@ -111,13 +111,13 @@ public final class InputManagerGlobal {
@Nullable
private IStickyModifierStateListener mStickyModifierStateListener;
- private final Object mKeyboardSystemShortcutListenerLock = new Object();
- @GuardedBy("mKeyboardSystemShortcutListenerLock")
+ private final Object mKeyGestureEventListenerLock = new Object();
+ @GuardedBy("mKeyGestureEventListenerLock")
@Nullable
- private ArrayList<KeyboardSystemShortcutListenerDelegate> mKeyboardSystemShortcutListeners;
- @GuardedBy("mKeyboardSystemShortcutListenerLock")
+ private ArrayList<KeyGestureEventListenerDelegate> mKeyGestureEventListeners;
+ @GuardedBy("mKeyGestureEventListenerLock")
@Nullable
- private IKeyboardSystemShortcutListener mKeyboardSystemShortcutListener;
+ private IKeyGestureEventListener mKeyGestureEventListener;
// InputDeviceSensorManager gets notified synchronously from the binder thread when input
// devices change, so it must be synchronized with the input device listeners.
@@ -1064,94 +1064,92 @@ public final class InputManagerGlobal {
}
}
- private static final class KeyboardSystemShortcutListenerDelegate {
- final KeyboardSystemShortcutListener mListener;
+ private static final class KeyGestureEventListenerDelegate {
+ final KeyGestureEventListener mListener;
final Executor mExecutor;
- KeyboardSystemShortcutListenerDelegate(KeyboardSystemShortcutListener listener,
+ KeyGestureEventListenerDelegate(KeyGestureEventListener listener,
Executor executor) {
mListener = listener;
mExecutor = executor;
}
- void onKeyboardSystemShortcutTriggered(int deviceId,
- KeyboardSystemShortcut systemShortcut) {
- mExecutor.execute(() ->
- mListener.onKeyboardSystemShortcutTriggered(deviceId, systemShortcut));
+ void onKeyGestureEvent(KeyGestureEvent event) {
+ mExecutor.execute(() -> mListener.onKeyGestureEvent(event));
}
}
- private class LocalKeyboardSystemShortcutListener extends IKeyboardSystemShortcutListener.Stub {
+ private class LocalKeyGestureEventListener extends IKeyGestureEventListener.Stub {
@Override
- public void onKeyboardSystemShortcutTriggered(int deviceId, int[] keycodes,
- int modifierState, int shortcut) {
- synchronized (mKeyboardSystemShortcutListenerLock) {
- if (mKeyboardSystemShortcutListeners == null) return;
- final int numListeners = mKeyboardSystemShortcutListeners.size();
+ public void onKeyGestureEvent(int deviceId, int[] keycodes, int modifierState,
+ int gestureType) {
+ synchronized (mKeyGestureEventListenerLock) {
+ if (mKeyGestureEventListeners == null) return;
+ final int numListeners = mKeyGestureEventListeners.size();
for (int i = 0; i < numListeners; i++) {
- mKeyboardSystemShortcutListeners.get(i)
- .onKeyboardSystemShortcutTriggered(deviceId,
- new KeyboardSystemShortcut(keycodes, modifierState, shortcut));
+ mKeyGestureEventListeners.get(i)
+ .onKeyGestureEvent(
+ new KeyGestureEvent(deviceId, keycodes, modifierState,
+ gestureType));
}
}
}
}
/**
- * @see InputManager#registerKeyboardSystemShortcutListener(Executor,
- * KeyboardSystemShortcutListener)
+ * @see InputManager#registerKeyGestureEventListener(Executor,
+ * KeyGestureEventListener)
*/
- @RequiresPermission(Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS)
- void registerKeyboardSystemShortcutListener(@NonNull Executor executor,
- @NonNull KeyboardSystemShortcutListener listener) throws IllegalArgumentException {
+ @RequiresPermission(Manifest.permission.MANAGE_KEY_GESTURES)
+ void registerKeyGestureEventListener(@NonNull Executor executor,
+ @NonNull KeyGestureEventListener listener) throws IllegalArgumentException {
Objects.requireNonNull(executor, "executor should not be null");
Objects.requireNonNull(listener, "listener should not be null");
- synchronized (mKeyboardSystemShortcutListenerLock) {
- if (mKeyboardSystemShortcutListener == null) {
- mKeyboardSystemShortcutListeners = new ArrayList<>();
- mKeyboardSystemShortcutListener = new LocalKeyboardSystemShortcutListener();
+ synchronized (mKeyGestureEventListenerLock) {
+ if (mKeyGestureEventListener == null) {
+ mKeyGestureEventListeners = new ArrayList<>();
+ mKeyGestureEventListener = new LocalKeyGestureEventListener();
try {
- mIm.registerKeyboardSystemShortcutListener(mKeyboardSystemShortcutListener);
+ mIm.registerKeyGestureEventListener(mKeyGestureEventListener);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
- final int numListeners = mKeyboardSystemShortcutListeners.size();
+ final int numListeners = mKeyGestureEventListeners.size();
for (int i = 0; i < numListeners; i++) {
- if (mKeyboardSystemShortcutListeners.get(i).mListener == listener) {
+ if (mKeyGestureEventListeners.get(i).mListener == listener) {
throw new IllegalArgumentException("Listener has already been registered!");
}
}
- KeyboardSystemShortcutListenerDelegate delegate =
- new KeyboardSystemShortcutListenerDelegate(listener, executor);
- mKeyboardSystemShortcutListeners.add(delegate);
+ KeyGestureEventListenerDelegate delegate =
+ new KeyGestureEventListenerDelegate(listener, executor);
+ mKeyGestureEventListeners.add(delegate);
}
}
/**
- * @see InputManager#unregisterKeyboardSystemShortcutListener(KeyboardSystemShortcutListener)
+ * @see InputManager#unregisterKeyGestureEventListener(KeyGestureEventListener)
*/
- @RequiresPermission(Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS)
- void unregisterKeyboardSystemShortcutListener(
- @NonNull KeyboardSystemShortcutListener listener) {
+ @RequiresPermission(Manifest.permission.MANAGE_KEY_GESTURES)
+ void unregisterKeyGestureEventListener(@NonNull KeyGestureEventListener listener) {
Objects.requireNonNull(listener, "listener should not be null");
- synchronized (mKeyboardSystemShortcutListenerLock) {
- if (mKeyboardSystemShortcutListeners == null) {
+ synchronized (mKeyGestureEventListenerLock) {
+ if (mKeyGestureEventListeners == null) {
return;
}
- mKeyboardSystemShortcutListeners.removeIf((delegate) -> delegate.mListener == listener);
- if (mKeyboardSystemShortcutListeners.isEmpty()) {
+ mKeyGestureEventListeners.removeIf((delegate) -> delegate.mListener == listener);
+ if (mKeyGestureEventListeners.isEmpty()) {
try {
- mIm.unregisterKeyboardSystemShortcutListener(mKeyboardSystemShortcutListener);
+ mIm.unregisterKeyGestureEventListener(mKeyGestureEventListener);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
- mKeyboardSystemShortcutListeners = null;
- mKeyboardSystemShortcutListener = null;
+ mKeyGestureEventListeners = null;
+ mKeyGestureEventListener = null;
}
}
}
diff --git a/core/java/android/hardware/input/KeyGestureEvent.java b/core/java/android/hardware/input/KeyGestureEvent.java
new file mode 100644
index 000000000000..7a8dd3395d21
--- /dev/null
+++ b/core/java/android/hardware/input/KeyGestureEvent.java
@@ -0,0 +1,531 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.util.FrameworkStatsLog;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Provides information about the keyboard gesture event being triggered by an external keyboard.
+ *
+ * @hide
+ */
+@DataClass(genToString = true, genEqualsHashCode = true)
+public class KeyGestureEvent {
+
+ private final int mDeviceId;
+ @NonNull
+ private final int[] mKeycodes;
+ private final int mModifierState;
+ @KeyGestureType
+ private final int mKeyGestureType;
+
+
+ public static final int KEY_GESTURE_TYPE_UNSPECIFIED =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__UNSPECIFIED;
+ public static final int KEY_GESTURE_TYPE_HOME =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__HOME;
+ public static final int KEY_GESTURE_TYPE_RECENT_APPS =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__RECENT_APPS;
+ public static final int KEY_GESTURE_TYPE_BACK =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__BACK;
+ public static final int KEY_GESTURE_TYPE_APP_SWITCH =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__APP_SWITCH;
+ public static final int KEY_GESTURE_TYPE_LAUNCH_ASSISTANT =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_ASSISTANT;
+ public static final int KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_VOICE_ASSISTANT;
+ public static final int KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_SYSTEM_SETTINGS;
+ public static final int KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_NOTIFICATION_PANEL;
+ public static final int KEY_GESTURE_TYPE_TOGGLE_TASKBAR =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_TASKBAR;
+ public static final int KEY_GESTURE_TYPE_TAKE_SCREENSHOT =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TAKE_SCREENSHOT;
+ public static final int KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__OPEN_SHORTCUT_HELPER;
+ public static final int KEY_GESTURE_TYPE_BRIGHTNESS_UP =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__BRIGHTNESS_UP;
+ public static final int KEY_GESTURE_TYPE_BRIGHTNESS_DOWN =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__BRIGHTNESS_DOWN;
+ public static final int KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__KEYBOARD_BACKLIGHT_UP;
+ public static final int KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__KEYBOARD_BACKLIGHT_DOWN;
+ public static final int KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__KEYBOARD_BACKLIGHT_TOGGLE;
+ public static final int KEY_GESTURE_TYPE_VOLUME_UP =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__VOLUME_UP;
+ public static final int KEY_GESTURE_TYPE_VOLUME_DOWN =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__VOLUME_DOWN;
+ public static final int KEY_GESTURE_TYPE_VOLUME_MUTE =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__VOLUME_MUTE;
+ public static final int KEY_GESTURE_TYPE_ALL_APPS =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__ALL_APPS;
+ public static final int KEY_GESTURE_TYPE_LAUNCH_SEARCH =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_SEARCH;
+ public static final int KEY_GESTURE_TYPE_LANGUAGE_SWITCH =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LANGUAGE_SWITCH;
+ public static final int KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__ACCESSIBILITY_ALL_APPS;
+ public static final int KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_CAPS_LOCK;
+ public static final int KEY_GESTURE_TYPE_SYSTEM_MUTE =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SYSTEM_MUTE;
+ public static final int KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SPLIT_SCREEN_NAVIGATION;
+ public static final int KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__CHANGE_SPLITSCREEN_FOCUS;
+ public static final int KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TRIGGER_BUG_REPORT;
+ public static final int KEY_GESTURE_TYPE_LOCK_SCREEN =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LOCK_SCREEN;
+ public static final int KEY_GESTURE_TYPE_OPEN_NOTES =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__OPEN_NOTES;
+ public static final int KEY_GESTURE_TYPE_TOGGLE_POWER =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_POWER;
+ public static final int KEY_GESTURE_TYPE_SYSTEM_NAVIGATION =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SYSTEM_NAVIGATION;
+ public static final int KEY_GESTURE_TYPE_SLEEP =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SLEEP;
+ public static final int KEY_GESTURE_TYPE_WAKEUP =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__WAKEUP;
+ public static final int KEY_GESTURE_TYPE_MEDIA_KEY =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__MEDIA_KEY;
+ public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_BROWSER;
+ public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_EMAIL;
+ public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_CONTACTS;
+ public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_CALENDAR;
+ public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_CALCULATOR;
+ public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_MUSIC;
+ public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_MAPS;
+ public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_MESSAGING;
+ public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_GALLERY =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_GALLERY;
+ public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FILES =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_FILES;
+ public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_WEATHER =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_WEATHER;
+ public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FITNESS =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_FITNESS;
+ public static final int KEY_GESTURE_TYPE_LAUNCH_APPLICATION_BY_PACKAGE_NAME =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_APPLICATION_BY_PACKAGE_NAME;
+ public static final int KEY_GESTURE_TYPE_DESKTOP_MODE =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__DESKTOP_MODE;
+ public static final int KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION =
+ FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__MULTI_WINDOW_NAVIGATION;
+
+
+
+ // Code below generated by codegen v1.0.23.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/input/KeyGestureEvent.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @IntDef(prefix = "KEY_GESTURE_TYPE_", value = {
+ KEY_GESTURE_TYPE_UNSPECIFIED,
+ KEY_GESTURE_TYPE_HOME,
+ KEY_GESTURE_TYPE_RECENT_APPS,
+ KEY_GESTURE_TYPE_BACK,
+ KEY_GESTURE_TYPE_APP_SWITCH,
+ KEY_GESTURE_TYPE_LAUNCH_ASSISTANT,
+ KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT,
+ KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS,
+ KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL,
+ KEY_GESTURE_TYPE_TOGGLE_TASKBAR,
+ KEY_GESTURE_TYPE_TAKE_SCREENSHOT,
+ KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER,
+ KEY_GESTURE_TYPE_BRIGHTNESS_UP,
+ KEY_GESTURE_TYPE_BRIGHTNESS_DOWN,
+ KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP,
+ KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN,
+ KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE,
+ KEY_GESTURE_TYPE_VOLUME_UP,
+ KEY_GESTURE_TYPE_VOLUME_DOWN,
+ KEY_GESTURE_TYPE_VOLUME_MUTE,
+ KEY_GESTURE_TYPE_ALL_APPS,
+ KEY_GESTURE_TYPE_LAUNCH_SEARCH,
+ KEY_GESTURE_TYPE_LANGUAGE_SWITCH,
+ KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS,
+ KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK,
+ KEY_GESTURE_TYPE_SYSTEM_MUTE,
+ KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION,
+ KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS,
+ KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT,
+ KEY_GESTURE_TYPE_LOCK_SCREEN,
+ KEY_GESTURE_TYPE_OPEN_NOTES,
+ KEY_GESTURE_TYPE_TOGGLE_POWER,
+ KEY_GESTURE_TYPE_SYSTEM_NAVIGATION,
+ KEY_GESTURE_TYPE_SLEEP,
+ KEY_GESTURE_TYPE_WAKEUP,
+ KEY_GESTURE_TYPE_MEDIA_KEY,
+ KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER,
+ KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL,
+ KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS,
+ KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR,
+ KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR,
+ KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC,
+ KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS,
+ KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING,
+ KEY_GESTURE_TYPE_LAUNCH_DEFAULT_GALLERY,
+ KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FILES,
+ KEY_GESTURE_TYPE_LAUNCH_DEFAULT_WEATHER,
+ KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FITNESS,
+ KEY_GESTURE_TYPE_LAUNCH_APPLICATION_BY_PACKAGE_NAME,
+ KEY_GESTURE_TYPE_DESKTOP_MODE,
+ KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @DataClass.Generated.Member
+ public @interface KeyGestureType {}
+
+ @DataClass.Generated.Member
+ public static String keyGestureTypeToString(@KeyGestureType int value) {
+ switch (value) {
+ case KEY_GESTURE_TYPE_UNSPECIFIED:
+ return "KEY_GESTURE_TYPE_UNSPECIFIED";
+ case KEY_GESTURE_TYPE_HOME:
+ return "KEY_GESTURE_TYPE_HOME";
+ case KEY_GESTURE_TYPE_RECENT_APPS:
+ return "KEY_GESTURE_TYPE_RECENT_APPS";
+ case KEY_GESTURE_TYPE_BACK:
+ return "KEY_GESTURE_TYPE_BACK";
+ case KEY_GESTURE_TYPE_APP_SWITCH:
+ return "KEY_GESTURE_TYPE_APP_SWITCH";
+ case KEY_GESTURE_TYPE_LAUNCH_ASSISTANT:
+ return "KEY_GESTURE_TYPE_LAUNCH_ASSISTANT";
+ case KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT:
+ return "KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT";
+ case KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS:
+ return "KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS";
+ case KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL:
+ return "KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL";
+ case KEY_GESTURE_TYPE_TOGGLE_TASKBAR:
+ return "KEY_GESTURE_TYPE_TOGGLE_TASKBAR";
+ case KEY_GESTURE_TYPE_TAKE_SCREENSHOT:
+ return "KEY_GESTURE_TYPE_TAKE_SCREENSHOT";
+ case KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER:
+ return "KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER";
+ case KEY_GESTURE_TYPE_BRIGHTNESS_UP:
+ return "KEY_GESTURE_TYPE_BRIGHTNESS_UP";
+ case KEY_GESTURE_TYPE_BRIGHTNESS_DOWN:
+ return "KEY_GESTURE_TYPE_BRIGHTNESS_DOWN";
+ case KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP:
+ return "KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP";
+ case KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN:
+ return "KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN";
+ case KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE:
+ return "KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE";
+ case KEY_GESTURE_TYPE_VOLUME_UP:
+ return "KEY_GESTURE_TYPE_VOLUME_UP";
+ case KEY_GESTURE_TYPE_VOLUME_DOWN:
+ return "KEY_GESTURE_TYPE_VOLUME_DOWN";
+ case KEY_GESTURE_TYPE_VOLUME_MUTE:
+ return "KEY_GESTURE_TYPE_VOLUME_MUTE";
+ case KEY_GESTURE_TYPE_ALL_APPS:
+ return "KEY_GESTURE_TYPE_ALL_APPS";
+ case KEY_GESTURE_TYPE_LAUNCH_SEARCH:
+ return "KEY_GESTURE_TYPE_LAUNCH_SEARCH";
+ case KEY_GESTURE_TYPE_LANGUAGE_SWITCH:
+ return "KEY_GESTURE_TYPE_LANGUAGE_SWITCH";
+ case KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS:
+ return "KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS";
+ case KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK:
+ return "KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK";
+ case KEY_GESTURE_TYPE_SYSTEM_MUTE:
+ return "KEY_GESTURE_TYPE_SYSTEM_MUTE";
+ case KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION:
+ return "KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION";
+ case KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS:
+ return "KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS";
+ case KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT:
+ return "KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT";
+ case KEY_GESTURE_TYPE_LOCK_SCREEN:
+ return "KEY_GESTURE_TYPE_LOCK_SCREEN";
+ case KEY_GESTURE_TYPE_OPEN_NOTES:
+ return "KEY_GESTURE_TYPE_OPEN_NOTES";
+ case KEY_GESTURE_TYPE_TOGGLE_POWER:
+ return "KEY_GESTURE_TYPE_TOGGLE_POWER";
+ case KEY_GESTURE_TYPE_SYSTEM_NAVIGATION:
+ return "KEY_GESTURE_TYPE_SYSTEM_NAVIGATION";
+ case KEY_GESTURE_TYPE_SLEEP:
+ return "KEY_GESTURE_TYPE_SLEEP";
+ case KEY_GESTURE_TYPE_WAKEUP:
+ return "KEY_GESTURE_TYPE_WAKEUP";
+ case KEY_GESTURE_TYPE_MEDIA_KEY:
+ return "KEY_GESTURE_TYPE_MEDIA_KEY";
+ case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER:
+ return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER";
+ case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL:
+ return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL";
+ case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS:
+ return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS";
+ case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR:
+ return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR";
+ case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR:
+ return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR";
+ case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC:
+ return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC";
+ case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS:
+ return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS";
+ case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING:
+ return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING";
+ case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_GALLERY:
+ return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_GALLERY";
+ case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FILES:
+ return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FILES";
+ case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_WEATHER:
+ return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_WEATHER";
+ case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FITNESS:
+ return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FITNESS";
+ case KEY_GESTURE_TYPE_LAUNCH_APPLICATION_BY_PACKAGE_NAME:
+ return "KEY_GESTURE_TYPE_LAUNCH_APPLICATION_BY_PACKAGE_NAME";
+ case KEY_GESTURE_TYPE_DESKTOP_MODE:
+ return "KEY_GESTURE_TYPE_DESKTOP_MODE";
+ case KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION:
+ return "KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION";
+ default: return Integer.toHexString(value);
+ }
+ }
+
+ @DataClass.Generated.Member
+ public KeyGestureEvent(
+ int deviceId,
+ @NonNull int[] keycodes,
+ int modifierState,
+ @KeyGestureType int keyGestureType) {
+ this.mDeviceId = deviceId;
+ this.mKeycodes = keycodes;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mKeycodes);
+ this.mModifierState = modifierState;
+ this.mKeyGestureType = keyGestureType;
+
+ if (!(mKeyGestureType == KEY_GESTURE_TYPE_UNSPECIFIED)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_HOME)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_RECENT_APPS)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_BACK)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_APP_SWITCH)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_ASSISTANT)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_TOGGLE_TASKBAR)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_TAKE_SCREENSHOT)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_BRIGHTNESS_UP)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_BRIGHTNESS_DOWN)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_VOLUME_UP)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_VOLUME_DOWN)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_VOLUME_MUTE)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_ALL_APPS)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_SEARCH)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LANGUAGE_SWITCH)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_SYSTEM_MUTE)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LOCK_SCREEN)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_OPEN_NOTES)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_TOGGLE_POWER)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_SYSTEM_NAVIGATION)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_SLEEP)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_WAKEUP)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_MEDIA_KEY)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_GALLERY)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FILES)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_WEATHER)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FITNESS)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_APPLICATION_BY_PACKAGE_NAME)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_DESKTOP_MODE)
+ && !(mKeyGestureType == KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION)) {
+ throw new java.lang.IllegalArgumentException(
+ "keyGestureType was " + mKeyGestureType + " but must be one of: "
+ + "KEY_GESTURE_TYPE_UNSPECIFIED(" + KEY_GESTURE_TYPE_UNSPECIFIED + "), "
+ + "KEY_GESTURE_TYPE_HOME(" + KEY_GESTURE_TYPE_HOME + "), "
+ + "KEY_GESTURE_TYPE_RECENT_APPS(" + KEY_GESTURE_TYPE_RECENT_APPS + "), "
+ + "KEY_GESTURE_TYPE_BACK(" + KEY_GESTURE_TYPE_BACK + "), "
+ + "KEY_GESTURE_TYPE_APP_SWITCH(" + KEY_GESTURE_TYPE_APP_SWITCH + "), "
+ + "KEY_GESTURE_TYPE_LAUNCH_ASSISTANT(" + KEY_GESTURE_TYPE_LAUNCH_ASSISTANT + "), "
+ + "KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT(" + KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT + "), "
+ + "KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS(" + KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS + "), "
+ + "KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL(" + KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL + "), "
+ + "KEY_GESTURE_TYPE_TOGGLE_TASKBAR(" + KEY_GESTURE_TYPE_TOGGLE_TASKBAR + "), "
+ + "KEY_GESTURE_TYPE_TAKE_SCREENSHOT(" + KEY_GESTURE_TYPE_TAKE_SCREENSHOT + "), "
+ + "KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER(" + KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER + "), "
+ + "KEY_GESTURE_TYPE_BRIGHTNESS_UP(" + KEY_GESTURE_TYPE_BRIGHTNESS_UP + "), "
+ + "KEY_GESTURE_TYPE_BRIGHTNESS_DOWN(" + KEY_GESTURE_TYPE_BRIGHTNESS_DOWN + "), "
+ + "KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP(" + KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP + "), "
+ + "KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN(" + KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN + "), "
+ + "KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE(" + KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE + "), "
+ + "KEY_GESTURE_TYPE_VOLUME_UP(" + KEY_GESTURE_TYPE_VOLUME_UP + "), "
+ + "KEY_GESTURE_TYPE_VOLUME_DOWN(" + KEY_GESTURE_TYPE_VOLUME_DOWN + "), "
+ + "KEY_GESTURE_TYPE_VOLUME_MUTE(" + KEY_GESTURE_TYPE_VOLUME_MUTE + "), "
+ + "KEY_GESTURE_TYPE_ALL_APPS(" + KEY_GESTURE_TYPE_ALL_APPS + "), "
+ + "KEY_GESTURE_TYPE_LAUNCH_SEARCH(" + KEY_GESTURE_TYPE_LAUNCH_SEARCH + "), "
+ + "KEY_GESTURE_TYPE_LANGUAGE_SWITCH(" + KEY_GESTURE_TYPE_LANGUAGE_SWITCH + "), "
+ + "KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS(" + KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS + "), "
+ + "KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK(" + KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK + "), "
+ + "KEY_GESTURE_TYPE_SYSTEM_MUTE(" + KEY_GESTURE_TYPE_SYSTEM_MUTE + "), "
+ + "KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION(" + KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION + "), "
+ + "KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS(" + KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS + "), "
+ + "KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT(" + KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT + "), "
+ + "KEY_GESTURE_TYPE_LOCK_SCREEN(" + KEY_GESTURE_TYPE_LOCK_SCREEN + "), "
+ + "KEY_GESTURE_TYPE_OPEN_NOTES(" + KEY_GESTURE_TYPE_OPEN_NOTES + "), "
+ + "KEY_GESTURE_TYPE_TOGGLE_POWER(" + KEY_GESTURE_TYPE_TOGGLE_POWER + "), "
+ + "KEY_GESTURE_TYPE_SYSTEM_NAVIGATION(" + KEY_GESTURE_TYPE_SYSTEM_NAVIGATION + "), "
+ + "KEY_GESTURE_TYPE_SLEEP(" + KEY_GESTURE_TYPE_SLEEP + "), "
+ + "KEY_GESTURE_TYPE_WAKEUP(" + KEY_GESTURE_TYPE_WAKEUP + "), "
+ + "KEY_GESTURE_TYPE_MEDIA_KEY(" + KEY_GESTURE_TYPE_MEDIA_KEY + "), "
+ + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER + "), "
+ + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL + "), "
+ + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS + "), "
+ + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR + "), "
+ + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR + "), "
+ + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC + "), "
+ + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS + "), "
+ + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING + "), "
+ + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_GALLERY(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_GALLERY + "), "
+ + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FILES(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FILES + "), "
+ + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_WEATHER(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_WEATHER + "), "
+ + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FITNESS(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FITNESS + "), "
+ + "KEY_GESTURE_TYPE_LAUNCH_APPLICATION_BY_PACKAGE_NAME(" + KEY_GESTURE_TYPE_LAUNCH_APPLICATION_BY_PACKAGE_NAME + "), "
+ + "KEY_GESTURE_TYPE_DESKTOP_MODE(" + KEY_GESTURE_TYPE_DESKTOP_MODE + "), "
+ + "KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION(" + KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION + ")");
+ }
+
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public int getDeviceId() {
+ return mDeviceId;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull int[] getKeycodes() {
+ return mKeycodes;
+ }
+
+ @DataClass.Generated.Member
+ public int getModifierState() {
+ return mModifierState;
+ }
+
+ @DataClass.Generated.Member
+ public @KeyGestureType int getKeyGestureType() {
+ return mKeyGestureType;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "KeyGestureEvent { " +
+ "deviceId = " + mDeviceId + ", " +
+ "keycodes = " + java.util.Arrays.toString(mKeycodes) + ", " +
+ "modifierState = " + mModifierState + ", " +
+ "keyGestureType = " + keyGestureTypeToString(mKeyGestureType) +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(KeyGestureEvent other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ KeyGestureEvent that = (KeyGestureEvent) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && mDeviceId == that.mDeviceId
+ && java.util.Arrays.equals(mKeycodes, that.mKeycodes)
+ && mModifierState == that.mModifierState
+ && mKeyGestureType == that.mKeyGestureType;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + mDeviceId;
+ _hash = 31 * _hash + java.util.Arrays.hashCode(mKeycodes);
+ _hash = 31 * _hash + mModifierState;
+ _hash = 31 * _hash + mKeyGestureType;
+ return _hash;
+ }
+
+ @DataClass.Generated(
+ time = 1723409092192L,
+ codegenVersion = "1.0.23",
+ sourceFile = "frameworks/base/core/java/android/hardware/input/KeyGestureEvent.java",
+ inputSignatures = "private final int mDeviceId\nprivate final @android.annotation.NonNull int[] mKeycodes\nprivate final int mModifierState\nprivate final @android.hardware.input.KeyGestureEvent.KeyGestureType int mKeyGestureType\npublic static final int KEY_GESTURE_TYPE_UNSPECIFIED\npublic static final int KEY_GESTURE_TYPE_HOME\npublic static final int KEY_GESTURE_TYPE_RECENT_APPS\npublic static final int KEY_GESTURE_TYPE_BACK\npublic static final int KEY_GESTURE_TYPE_APP_SWITCH\npublic static final int KEY_GESTURE_TYPE_LAUNCH_ASSISTANT\npublic static final int KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT\npublic static final int KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS\npublic static final int KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL\npublic static final int KEY_GESTURE_TYPE_TOGGLE_TASKBAR\npublic static final int KEY_GESTURE_TYPE_TAKE_SCREENSHOT\npublic static final int KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER\npublic static final int KEY_GESTURE_TYPE_BRIGHTNESS_UP\npublic static final int KEY_GESTURE_TYPE_BRIGHTNESS_DOWN\npublic static final int KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP\npublic static final int KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN\npublic static final int KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE\npublic static final int KEY_GESTURE_TYPE_VOLUME_UP\npublic static final int KEY_GESTURE_TYPE_VOLUME_DOWN\npublic static final int KEY_GESTURE_TYPE_VOLUME_MUTE\npublic static final int KEY_GESTURE_TYPE_ALL_APPS\npublic static final int KEY_GESTURE_TYPE_LAUNCH_SEARCH\npublic static final int KEY_GESTURE_TYPE_LANGUAGE_SWITCH\npublic static final int KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS\npublic static final int KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK\npublic static final int KEY_GESTURE_TYPE_SYSTEM_MUTE\npublic static final int KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION\npublic static final int KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS\npublic static final int KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT\npublic static final int KEY_GESTURE_TYPE_LOCK_SCREEN\npublic static final int KEY_GESTURE_TYPE_OPEN_NOTES\npublic static final int KEY_GESTURE_TYPE_TOGGLE_POWER\npublic static final int KEY_GESTURE_TYPE_SYSTEM_NAVIGATION\npublic static final int KEY_GESTURE_TYPE_SLEEP\npublic static final int KEY_GESTURE_TYPE_WAKEUP\npublic static final int KEY_GESTURE_TYPE_MEDIA_KEY\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_GALLERY\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FILES\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_WEATHER\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FITNESS\npublic static final int KEY_GESTURE_TYPE_LAUNCH_APPLICATION_BY_PACKAGE_NAME\npublic static final int KEY_GESTURE_TYPE_DESKTOP_MODE\npublic static final int KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION\nclass KeyGestureEvent extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genToString=true, genEqualsHashCode=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/hardware/input/KeyboardSystemShortcut.java b/core/java/android/hardware/input/KeyboardSystemShortcut.java
deleted file mode 100644
index 89cf877c3aa8..000000000000
--- a/core/java/android/hardware/input/KeyboardSystemShortcut.java
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.input;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-import com.android.internal.util.DataClass;
-import com.android.internal.util.FrameworkStatsLog;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Provides information about the keyboard shortcut being triggered by an external keyboard.
- *
- * @hide
- */
-@DataClass(genToString = true, genEqualsHashCode = true)
-public class KeyboardSystemShortcut {
-
- private static final String TAG = "KeyboardSystemShortcut";
-
- @NonNull
- private final int[] mKeycodes;
- private final int mModifierState;
- @SystemShortcut
- private final int mSystemShortcut;
-
-
- public static final int SYSTEM_SHORTCUT_UNSPECIFIED =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__UNSPECIFIED;
- public static final int SYSTEM_SHORTCUT_HOME =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__HOME;
- public static final int SYSTEM_SHORTCUT_RECENT_APPS =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__RECENT_APPS;
- public static final int SYSTEM_SHORTCUT_BACK =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__BACK;
- public static final int SYSTEM_SHORTCUT_APP_SWITCH =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__APP_SWITCH;
- public static final int SYSTEM_SHORTCUT_LAUNCH_ASSISTANT =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_ASSISTANT;
- public static final int SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_VOICE_ASSISTANT;
- public static final int SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_SYSTEM_SETTINGS;
- public static final int SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_NOTIFICATION_PANEL;
- public static final int SYSTEM_SHORTCUT_TOGGLE_TASKBAR =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_TASKBAR;
- public static final int SYSTEM_SHORTCUT_TAKE_SCREENSHOT =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TAKE_SCREENSHOT;
- public static final int SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__OPEN_SHORTCUT_HELPER;
- public static final int SYSTEM_SHORTCUT_BRIGHTNESS_UP =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__BRIGHTNESS_UP;
- public static final int SYSTEM_SHORTCUT_BRIGHTNESS_DOWN =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__BRIGHTNESS_DOWN;
- public static final int SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__KEYBOARD_BACKLIGHT_UP;
- public static final int SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__KEYBOARD_BACKLIGHT_DOWN;
- public static final int SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__KEYBOARD_BACKLIGHT_TOGGLE;
- public static final int SYSTEM_SHORTCUT_VOLUME_UP =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__VOLUME_UP;
- public static final int SYSTEM_SHORTCUT_VOLUME_DOWN =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__VOLUME_DOWN;
- public static final int SYSTEM_SHORTCUT_VOLUME_MUTE =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__VOLUME_MUTE;
- public static final int SYSTEM_SHORTCUT_ALL_APPS =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__ALL_APPS;
- public static final int SYSTEM_SHORTCUT_LAUNCH_SEARCH =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_SEARCH;
- public static final int SYSTEM_SHORTCUT_LANGUAGE_SWITCH =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LANGUAGE_SWITCH;
- public static final int SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__ACCESSIBILITY_ALL_APPS;
- public static final int SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_CAPS_LOCK;
- public static final int SYSTEM_SHORTCUT_SYSTEM_MUTE =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SYSTEM_MUTE;
- public static final int SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SPLIT_SCREEN_NAVIGATION;
- public static final int SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__CHANGE_SPLITSCREEN_FOCUS;
- public static final int SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TRIGGER_BUG_REPORT;
- public static final int SYSTEM_SHORTCUT_LOCK_SCREEN =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LOCK_SCREEN;
- public static final int SYSTEM_SHORTCUT_OPEN_NOTES =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__OPEN_NOTES;
- public static final int SYSTEM_SHORTCUT_TOGGLE_POWER =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_POWER;
- public static final int SYSTEM_SHORTCUT_SYSTEM_NAVIGATION =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SYSTEM_NAVIGATION;
- public static final int SYSTEM_SHORTCUT_SLEEP =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SLEEP;
- public static final int SYSTEM_SHORTCUT_WAKEUP =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__WAKEUP;
- public static final int SYSTEM_SHORTCUT_MEDIA_KEY =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__MEDIA_KEY;
- public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_BROWSER;
- public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_EMAIL;
- public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_CONTACTS;
- public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_CALENDAR;
- public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_CALCULATOR;
- public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_MUSIC;
- public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_MAPS;
- public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_MESSAGING;
- public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_GALLERY;
- public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_FILES;
- public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_WEATHER;
- public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_FITNESS;
- public static final int SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_APPLICATION_BY_PACKAGE_NAME;
- public static final int SYSTEM_SHORTCUT_DESKTOP_MODE =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__DESKTOP_MODE;
- public static final int SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION =
- FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__MULTI_WINDOW_NAVIGATION;
-
-
-
- // Code below generated by codegen v1.0.23.
- //
- // DO NOT MODIFY!
- // CHECKSTYLE:OFF Generated code
- //
- // To regenerate run:
- // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/input/KeyboardSystemShortcut.java
- //
- // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
- // Settings > Editor > Code Style > Formatter Control
- //@formatter:off
-
-
- @IntDef(prefix = "SYSTEM_SHORTCUT_", value = {
- SYSTEM_SHORTCUT_UNSPECIFIED,
- SYSTEM_SHORTCUT_HOME,
- SYSTEM_SHORTCUT_RECENT_APPS,
- SYSTEM_SHORTCUT_BACK,
- SYSTEM_SHORTCUT_APP_SWITCH,
- SYSTEM_SHORTCUT_LAUNCH_ASSISTANT,
- SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT,
- SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS,
- SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL,
- SYSTEM_SHORTCUT_TOGGLE_TASKBAR,
- SYSTEM_SHORTCUT_TAKE_SCREENSHOT,
- SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER,
- SYSTEM_SHORTCUT_BRIGHTNESS_UP,
- SYSTEM_SHORTCUT_BRIGHTNESS_DOWN,
- SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP,
- SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN,
- SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE,
- SYSTEM_SHORTCUT_VOLUME_UP,
- SYSTEM_SHORTCUT_VOLUME_DOWN,
- SYSTEM_SHORTCUT_VOLUME_MUTE,
- SYSTEM_SHORTCUT_ALL_APPS,
- SYSTEM_SHORTCUT_LAUNCH_SEARCH,
- SYSTEM_SHORTCUT_LANGUAGE_SWITCH,
- SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS,
- SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK,
- SYSTEM_SHORTCUT_SYSTEM_MUTE,
- SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION,
- SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS,
- SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT,
- SYSTEM_SHORTCUT_LOCK_SCREEN,
- SYSTEM_SHORTCUT_OPEN_NOTES,
- SYSTEM_SHORTCUT_TOGGLE_POWER,
- SYSTEM_SHORTCUT_SYSTEM_NAVIGATION,
- SYSTEM_SHORTCUT_SLEEP,
- SYSTEM_SHORTCUT_WAKEUP,
- SYSTEM_SHORTCUT_MEDIA_KEY,
- SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER,
- SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL,
- SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS,
- SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR,
- SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR,
- SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC,
- SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS,
- SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING,
- SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY,
- SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES,
- SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER,
- SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS,
- SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME,
- SYSTEM_SHORTCUT_DESKTOP_MODE,
- SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION
- })
- @Retention(RetentionPolicy.SOURCE)
- @DataClass.Generated.Member
- public @interface SystemShortcut {}
-
- @DataClass.Generated.Member
- public static String systemShortcutToString(@SystemShortcut int value) {
- switch (value) {
- case SYSTEM_SHORTCUT_UNSPECIFIED:
- return "SYSTEM_SHORTCUT_UNSPECIFIED";
- case SYSTEM_SHORTCUT_HOME:
- return "SYSTEM_SHORTCUT_HOME";
- case SYSTEM_SHORTCUT_RECENT_APPS:
- return "SYSTEM_SHORTCUT_RECENT_APPS";
- case SYSTEM_SHORTCUT_BACK:
- return "SYSTEM_SHORTCUT_BACK";
- case SYSTEM_SHORTCUT_APP_SWITCH:
- return "SYSTEM_SHORTCUT_APP_SWITCH";
- case SYSTEM_SHORTCUT_LAUNCH_ASSISTANT:
- return "SYSTEM_SHORTCUT_LAUNCH_ASSISTANT";
- case SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT:
- return "SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT";
- case SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS:
- return "SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS";
- case SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL:
- return "SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL";
- case SYSTEM_SHORTCUT_TOGGLE_TASKBAR:
- return "SYSTEM_SHORTCUT_TOGGLE_TASKBAR";
- case SYSTEM_SHORTCUT_TAKE_SCREENSHOT:
- return "SYSTEM_SHORTCUT_TAKE_SCREENSHOT";
- case SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER:
- return "SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER";
- case SYSTEM_SHORTCUT_BRIGHTNESS_UP:
- return "SYSTEM_SHORTCUT_BRIGHTNESS_UP";
- case SYSTEM_SHORTCUT_BRIGHTNESS_DOWN:
- return "SYSTEM_SHORTCUT_BRIGHTNESS_DOWN";
- case SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP:
- return "SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP";
- case SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN:
- return "SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN";
- case SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE:
- return "SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE";
- case SYSTEM_SHORTCUT_VOLUME_UP:
- return "SYSTEM_SHORTCUT_VOLUME_UP";
- case SYSTEM_SHORTCUT_VOLUME_DOWN:
- return "SYSTEM_SHORTCUT_VOLUME_DOWN";
- case SYSTEM_SHORTCUT_VOLUME_MUTE:
- return "SYSTEM_SHORTCUT_VOLUME_MUTE";
- case SYSTEM_SHORTCUT_ALL_APPS:
- return "SYSTEM_SHORTCUT_ALL_APPS";
- case SYSTEM_SHORTCUT_LAUNCH_SEARCH:
- return "SYSTEM_SHORTCUT_LAUNCH_SEARCH";
- case SYSTEM_SHORTCUT_LANGUAGE_SWITCH:
- return "SYSTEM_SHORTCUT_LANGUAGE_SWITCH";
- case SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS:
- return "SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS";
- case SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK:
- return "SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK";
- case SYSTEM_SHORTCUT_SYSTEM_MUTE:
- return "SYSTEM_SHORTCUT_SYSTEM_MUTE";
- case SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION:
- return "SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION";
- case SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS:
- return "SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS";
- case SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT:
- return "SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT";
- case SYSTEM_SHORTCUT_LOCK_SCREEN:
- return "SYSTEM_SHORTCUT_LOCK_SCREEN";
- case SYSTEM_SHORTCUT_OPEN_NOTES:
- return "SYSTEM_SHORTCUT_OPEN_NOTES";
- case SYSTEM_SHORTCUT_TOGGLE_POWER:
- return "SYSTEM_SHORTCUT_TOGGLE_POWER";
- case SYSTEM_SHORTCUT_SYSTEM_NAVIGATION:
- return "SYSTEM_SHORTCUT_SYSTEM_NAVIGATION";
- case SYSTEM_SHORTCUT_SLEEP:
- return "SYSTEM_SHORTCUT_SLEEP";
- case SYSTEM_SHORTCUT_WAKEUP:
- return "SYSTEM_SHORTCUT_WAKEUP";
- case SYSTEM_SHORTCUT_MEDIA_KEY:
- return "SYSTEM_SHORTCUT_MEDIA_KEY";
- case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER:
- return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER";
- case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL:
- return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL";
- case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS:
- return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS";
- case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR:
- return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR";
- case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR:
- return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR";
- case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC:
- return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC";
- case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS:
- return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS";
- case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING:
- return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING";
- case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY:
- return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY";
- case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES:
- return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES";
- case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER:
- return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER";
- case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS:
- return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS";
- case SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME:
- return "SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME";
- case SYSTEM_SHORTCUT_DESKTOP_MODE:
- return "SYSTEM_SHORTCUT_DESKTOP_MODE";
- case SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION:
- return "SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION";
- default: return Integer.toHexString(value);
- }
- }
-
- @DataClass.Generated.Member
- public KeyboardSystemShortcut(
- @NonNull int[] keycodes,
- int modifierState,
- @SystemShortcut int systemShortcut) {
- this.mKeycodes = keycodes;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mKeycodes);
- this.mModifierState = modifierState;
- this.mSystemShortcut = systemShortcut;
-
- if (!(mSystemShortcut == SYSTEM_SHORTCUT_UNSPECIFIED)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_HOME)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_RECENT_APPS)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_BACK)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_APP_SWITCH)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_ASSISTANT)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_TOGGLE_TASKBAR)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_TAKE_SCREENSHOT)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_BRIGHTNESS_UP)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_BRIGHTNESS_DOWN)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_VOLUME_UP)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_VOLUME_DOWN)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_VOLUME_MUTE)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_ALL_APPS)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_SEARCH)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LANGUAGE_SWITCH)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_SYSTEM_MUTE)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LOCK_SCREEN)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_OPEN_NOTES)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_TOGGLE_POWER)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_SYSTEM_NAVIGATION)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_SLEEP)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_WAKEUP)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_MEDIA_KEY)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_DESKTOP_MODE)
- && !(mSystemShortcut == SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION)) {
- throw new java.lang.IllegalArgumentException(
- "systemShortcut was " + mSystemShortcut + " but must be one of: "
- + "SYSTEM_SHORTCUT_UNSPECIFIED(" + SYSTEM_SHORTCUT_UNSPECIFIED + "), "
- + "SYSTEM_SHORTCUT_HOME(" + SYSTEM_SHORTCUT_HOME + "), "
- + "SYSTEM_SHORTCUT_RECENT_APPS(" + SYSTEM_SHORTCUT_RECENT_APPS + "), "
- + "SYSTEM_SHORTCUT_BACK(" + SYSTEM_SHORTCUT_BACK + "), "
- + "SYSTEM_SHORTCUT_APP_SWITCH(" + SYSTEM_SHORTCUT_APP_SWITCH + "), "
- + "SYSTEM_SHORTCUT_LAUNCH_ASSISTANT(" + SYSTEM_SHORTCUT_LAUNCH_ASSISTANT + "), "
- + "SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT(" + SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT + "), "
- + "SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS(" + SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS + "), "
- + "SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL(" + SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL + "), "
- + "SYSTEM_SHORTCUT_TOGGLE_TASKBAR(" + SYSTEM_SHORTCUT_TOGGLE_TASKBAR + "), "
- + "SYSTEM_SHORTCUT_TAKE_SCREENSHOT(" + SYSTEM_SHORTCUT_TAKE_SCREENSHOT + "), "
- + "SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER(" + SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER + "), "
- + "SYSTEM_SHORTCUT_BRIGHTNESS_UP(" + SYSTEM_SHORTCUT_BRIGHTNESS_UP + "), "
- + "SYSTEM_SHORTCUT_BRIGHTNESS_DOWN(" + SYSTEM_SHORTCUT_BRIGHTNESS_DOWN + "), "
- + "SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP(" + SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP + "), "
- + "SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN(" + SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN + "), "
- + "SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE(" + SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE + "), "
- + "SYSTEM_SHORTCUT_VOLUME_UP(" + SYSTEM_SHORTCUT_VOLUME_UP + "), "
- + "SYSTEM_SHORTCUT_VOLUME_DOWN(" + SYSTEM_SHORTCUT_VOLUME_DOWN + "), "
- + "SYSTEM_SHORTCUT_VOLUME_MUTE(" + SYSTEM_SHORTCUT_VOLUME_MUTE + "), "
- + "SYSTEM_SHORTCUT_ALL_APPS(" + SYSTEM_SHORTCUT_ALL_APPS + "), "
- + "SYSTEM_SHORTCUT_LAUNCH_SEARCH(" + SYSTEM_SHORTCUT_LAUNCH_SEARCH + "), "
- + "SYSTEM_SHORTCUT_LANGUAGE_SWITCH(" + SYSTEM_SHORTCUT_LANGUAGE_SWITCH + "), "
- + "SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS(" + SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS + "), "
- + "SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK(" + SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK + "), "
- + "SYSTEM_SHORTCUT_SYSTEM_MUTE(" + SYSTEM_SHORTCUT_SYSTEM_MUTE + "), "
- + "SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION(" + SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION + "), "
- + "SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS(" + SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS + "), "
- + "SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT(" + SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT + "), "
- + "SYSTEM_SHORTCUT_LOCK_SCREEN(" + SYSTEM_SHORTCUT_LOCK_SCREEN + "), "
- + "SYSTEM_SHORTCUT_OPEN_NOTES(" + SYSTEM_SHORTCUT_OPEN_NOTES + "), "
- + "SYSTEM_SHORTCUT_TOGGLE_POWER(" + SYSTEM_SHORTCUT_TOGGLE_POWER + "), "
- + "SYSTEM_SHORTCUT_SYSTEM_NAVIGATION(" + SYSTEM_SHORTCUT_SYSTEM_NAVIGATION + "), "
- + "SYSTEM_SHORTCUT_SLEEP(" + SYSTEM_SHORTCUT_SLEEP + "), "
- + "SYSTEM_SHORTCUT_WAKEUP(" + SYSTEM_SHORTCUT_WAKEUP + "), "
- + "SYSTEM_SHORTCUT_MEDIA_KEY(" + SYSTEM_SHORTCUT_MEDIA_KEY + "), "
- + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER + "), "
- + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL + "), "
- + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS + "), "
- + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR + "), "
- + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR + "), "
- + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC + "), "
- + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS + "), "
- + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING + "), "
- + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY + "), "
- + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES + "), "
- + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER + "), "
- + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS + "), "
- + "SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME(" + SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME + "), "
- + "SYSTEM_SHORTCUT_DESKTOP_MODE(" + SYSTEM_SHORTCUT_DESKTOP_MODE + "), "
- + "SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION(" + SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION + ")");
- }
-
-
- // onConstructed(); // You can define this method to get a callback
- }
-
- @DataClass.Generated.Member
- public @NonNull int[] getKeycodes() {
- return mKeycodes;
- }
-
- @DataClass.Generated.Member
- public int getModifierState() {
- return mModifierState;
- }
-
- @DataClass.Generated.Member
- public @SystemShortcut int getSystemShortcut() {
- return mSystemShortcut;
- }
-
- @Override
- @DataClass.Generated.Member
- public String toString() {
- // You can override field toString logic by defining methods like:
- // String fieldNameToString() { ... }
-
- return "KeyboardSystemShortcut { " +
- "keycodes = " + java.util.Arrays.toString(mKeycodes) + ", " +
- "modifierState = " + mModifierState + ", " +
- "systemShortcut = " + systemShortcutToString(mSystemShortcut) +
- " }";
- }
-
- @Override
- @DataClass.Generated.Member
- public boolean equals(@Nullable Object o) {
- // You can override field equality logic by defining either of the methods like:
- // boolean fieldNameEquals(KeyboardSystemShortcut other) { ... }
- // boolean fieldNameEquals(FieldType otherValue) { ... }
-
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- @SuppressWarnings("unchecked")
- KeyboardSystemShortcut that = (KeyboardSystemShortcut) o;
- //noinspection PointlessBooleanExpression
- return true
- && java.util.Arrays.equals(mKeycodes, that.mKeycodes)
- && mModifierState == that.mModifierState
- && mSystemShortcut == that.mSystemShortcut;
- }
-
- @Override
- @DataClass.Generated.Member
- public int hashCode() {
- // You can override field hashCode logic by defining methods like:
- // int fieldNameHashCode() { ... }
-
- int _hash = 1;
- _hash = 31 * _hash + java.util.Arrays.hashCode(mKeycodes);
- _hash = 31 * _hash + mModifierState;
- _hash = 31 * _hash + mSystemShortcut;
- return _hash;
- }
-
- @DataClass.Generated(
- time = 1722890917041L,
- codegenVersion = "1.0.23",
- sourceFile = "frameworks/base/core/java/android/hardware/input/KeyboardSystemShortcut.java",
- inputSignatures = "private static final java.lang.String TAG\nprivate final @android.annotation.NonNull int[] mKeycodes\nprivate final int mModifierState\nprivate final @android.hardware.input.KeyboardSystemShortcut.SystemShortcut int mSystemShortcut\npublic static final int SYSTEM_SHORTCUT_UNSPECIFIED\npublic static final int SYSTEM_SHORTCUT_HOME\npublic static final int SYSTEM_SHORTCUT_RECENT_APPS\npublic static final int SYSTEM_SHORTCUT_BACK\npublic static final int SYSTEM_SHORTCUT_APP_SWITCH\npublic static final int SYSTEM_SHORTCUT_LAUNCH_ASSISTANT\npublic static final int SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT\npublic static final int SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS\npublic static final int SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL\npublic static final int SYSTEM_SHORTCUT_TOGGLE_TASKBAR\npublic static final int SYSTEM_SHORTCUT_TAKE_SCREENSHOT\npublic static final int SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER\npublic static final int SYSTEM_SHORTCUT_BRIGHTNESS_UP\npublic static final int SYSTEM_SHORTCUT_BRIGHTNESS_DOWN\npublic static final int SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP\npublic static final int SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN\npublic static final int SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE\npublic static final int SYSTEM_SHORTCUT_VOLUME_UP\npublic static final int SYSTEM_SHORTCUT_VOLUME_DOWN\npublic static final int SYSTEM_SHORTCUT_VOLUME_MUTE\npublic static final int SYSTEM_SHORTCUT_ALL_APPS\npublic static final int SYSTEM_SHORTCUT_LAUNCH_SEARCH\npublic static final int SYSTEM_SHORTCUT_LANGUAGE_SWITCH\npublic static final int SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS\npublic static final int SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK\npublic static final int SYSTEM_SHORTCUT_SYSTEM_MUTE\npublic static final int SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION\npublic static final int SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS\npublic static final int SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT\npublic static final int SYSTEM_SHORTCUT_LOCK_SCREEN\npublic static final int SYSTEM_SHORTCUT_OPEN_NOTES\npublic static final int SYSTEM_SHORTCUT_TOGGLE_POWER\npublic static final int SYSTEM_SHORTCUT_SYSTEM_NAVIGATION\npublic static final int SYSTEM_SHORTCUT_SLEEP\npublic static final int SYSTEM_SHORTCUT_WAKEUP\npublic static final int SYSTEM_SHORTCUT_MEDIA_KEY\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS\npublic static final int SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME\npublic static final int SYSTEM_SHORTCUT_DESKTOP_MODE\npublic static final int SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION\nclass KeyboardSystemShortcut extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genToString=true, genEqualsHashCode=true)")
- @Deprecated
- private void __metadata() {}
-
-
- //@formatter:on
- // End of generated code
-
-}
diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig
index 3fe063df0e1b..4c4aa6cc4e68 100644
--- a/core/java/android/permission/flags.aconfig
+++ b/core/java/android/permission/flags.aconfig
@@ -223,3 +223,14 @@ flag {
description: "Show access entry of location bypass permission in the Privacy Dashboard"
bug: "325536053"
}
+
+flag {
+ name: "dont_remove_existing_uid_states"
+ is_fixed_read_only: true
+ namespace: "permissions"
+ description: "Double check if the uid still exists before attempting to remove its appops state"
+ bug: "353474742"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/core/java/android/text/flags/flags.aconfig b/core/java/android/text/flags/flags.aconfig
index 3d190fe43626..1c3d73824e7e 100644
--- a/core/java/android/text/flags/flags.aconfig
+++ b/core/java/android/text/flags/flags.aconfig
@@ -267,3 +267,23 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "typeface_cache_for_var_settings"
+ namespace: "text"
+ description: "Cache Typeface instance for font variation settings."
+ bug: "355462362"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "context_menu_hide_unavailable_items"
+ namespace: "text"
+ description: "Hide rather than disable unavailable Editor context menu items."
+ bug: "345709107"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/core/java/android/view/contentprotection/OWNERS b/core/java/android/view/contentprotection/OWNERS
index b3583a7f6ab1..48052c640560 100644
--- a/core/java/android/view/contentprotection/OWNERS
+++ b/core/java/android/view/contentprotection/OWNERS
@@ -1,4 +1,6 @@
-# Bug component: 544200
+# Bug component: 1040349
-include /core/java/android/view/contentcapture/OWNERS
+njagar@google.com
+williamluh@google.com
+aaronjosephs@google.com
diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig
index 0cb96df2878b..61ee13a2693c 100644
--- a/core/java/android/window/flags/windowing_frontend.aconfig
+++ b/core/java/android/window/flags/windowing_frontend.aconfig
@@ -91,6 +91,14 @@ flag {
}
flag {
+ name: "transit_tracker_plumbing"
+ namespace: "windowing_frontend"
+ description: "Plumb and collect on transition tracking object instead of singleton"
+ bug: "325114242"
+ is_fixed_read_only: true
+}
+
+flag {
name: "transit_ready_tracking"
namespace: "windowing_frontend"
description: "Enable accurate transition readiness tracking"
diff --git a/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java b/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java
index 572a599dc8f5..fcc302331dae 100644
--- a/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java
@@ -48,6 +48,7 @@ import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
@@ -423,6 +424,14 @@ public class LegacyProtoLogImpl implements IProtoLog {
for (IProtoLogGroup group : protoLogGroups) {
mLogGroups.put(group.name(), group);
}
+
+ final var hasGroupsLoggingToLogcat = Arrays.stream(protoLogGroups)
+ .anyMatch(IProtoLogGroup::isLogToLogcat);
+
+ final ILogger logger = (msg) -> Slog.i(TAG, msg);
+ if (hasGroupsLoggingToLogcat) {
+ mViewerConfig.loadViewerConfig(logger, mLegacyViewerConfigFilename);
+ }
}
}
diff --git a/core/jni/android_database_SQLiteRawStatement.cpp b/core/jni/android_database_SQLiteRawStatement.cpp
index 961486474821..85a6bdf95928 100644
--- a/core/jni/android_database_SQLiteRawStatement.cpp
+++ b/core/jni/android_database_SQLiteRawStatement.cpp
@@ -72,14 +72,17 @@ static void throwInvalidParameter(JNIEnv *env, jlong stmtPtr, jint index) {
// This throws a SQLiteBindOrColumnIndexOutOfRangeException if the column index is out
-// of bounds.
-static void throwIfInvalidColumn(JNIEnv *env, jlong stmtPtr, jint col) {
+// of bounds. It returns true if an exception was thrown.
+static bool throwIfInvalidColumn(JNIEnv *env, jlong stmtPtr, jint col) {
if (col < 0 || col >= sqlite3_data_count(stmt(stmtPtr))) {
int count = sqlite3_data_count(stmt(stmtPtr));
std::string message = android::base::StringPrintf(
"column index %d out of bounds [0,%d]", col, count - 1);
char const * errmsg = sqlite3_errstr(SQLITE_RANGE);
throw_sqlite3_exception(env, SQLITE_RANGE, errmsg, message.c_str());
+ return true;
+ } else {
+ return false;
}
}
@@ -216,12 +219,16 @@ static void bindText(JNIEnv* env, jclass, jlong stmtPtr, jint index, jstring val
static jint columnType(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
- throwIfInvalidColumn(env, stmtPtr, col);
+ if (throwIfInvalidColumn(env, stmtPtr, col)) {
+ return 0;
+ }
return sqlite3_column_type(stmt(stmtPtr), col);
}
static jstring columnName(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
- throwIfInvalidColumn(env, stmtPtr, col);
+ if (throwIfInvalidColumn(env, stmtPtr, col)) {
+ return nullptr;
+ }
const jchar* name = static_cast<const jchar*>(sqlite3_column_name16(stmt(stmtPtr), col));
if (name == nullptr) {
throw_sqlite3_exception(env, db(stmtPtr), "error fetching columnName()");
@@ -232,14 +239,18 @@ static jstring columnName(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
}
static jint columnBytes(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
- throwIfInvalidColumn(env, stmtPtr, col);
+ if (throwIfInvalidColumn(env, stmtPtr, col)) {
+ return 0;
+ }
int r = sqlite3_column_bytes16(stmt(stmtPtr), col);
throwIfError(env, stmtPtr);
return r;
}
static jbyteArray columnBlob(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
- throwIfInvalidColumn(env, stmtPtr, col);
+ if (throwIfInvalidColumn(env, stmtPtr, col)) {
+ return nullptr;
+ }
const void* blob = sqlite3_column_blob(stmt(stmtPtr), col);
if (blob == nullptr) {
if (throwIfError(env, stmtPtr)) {
@@ -262,7 +273,9 @@ static jbyteArray columnBlob(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
static int columnBuffer(JNIEnv* env, jclass, jlong stmtPtr, jint col,
jbyteArray buffer, jint offset, jint length, jint srcOffset) {
- throwIfInvalidColumn(env, stmtPtr, col);
+ if (throwIfInvalidColumn(env, stmtPtr, col)) {
+ return 0;
+ }
const void* blob = sqlite3_column_blob(stmt(stmtPtr), col);
if (blob == nullptr) {
throwIfError(env, stmtPtr);
@@ -281,22 +294,30 @@ static int columnBuffer(JNIEnv* env, jclass, jlong stmtPtr, jint col,
}
static jdouble columnDouble(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
- throwIfInvalidColumn(env, stmtPtr, col);
+ if (throwIfInvalidColumn(env, stmtPtr, col)) {
+ return 0;
+ }
return sqlite3_column_double(stmt(stmtPtr), col);
}
static jint columnInt(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
- throwIfInvalidColumn(env, stmtPtr, col);
+ if (throwIfInvalidColumn(env, stmtPtr, col)) {
+ return 0;
+ }
return sqlite3_column_int(stmt(stmtPtr), col);
}
static jlong columnLong(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
- throwIfInvalidColumn(env, stmtPtr, col);
+ if (throwIfInvalidColumn(env, stmtPtr, col)) {
+ return 0;
+ }
return sqlite3_column_int64(stmt(stmtPtr), col);
}
static jstring columnText(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
- throwIfInvalidColumn(env, stmtPtr, col);
+ if (throwIfInvalidColumn(env, stmtPtr, col)) {
+ return nullptr;
+ }
const jchar* text = static_cast<const jchar*>(sqlite3_column_text16(stmt(stmtPtr), col));
if (text == nullptr) {
throwIfError(env, stmtPtr);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7aeabeed2a08..117041ab353e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -8132,10 +8132,10 @@
<permission android:name="android.permission.MONITOR_STICKY_MODIFIER_STATE"
android:protectionLevel="signature" />
- <!-- Allows low-level access to monitor keyboard system shortcuts
+ <!-- Allows low-level access to manage key gestures.
<p>Not for use by third-party applications.
@hide -->
- <permission android:name="android.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS"
+ <permission android:name="android.permission.MANAGE_KEY_GESTURES"
android:protectionLevel="signature" />
<uses-permission android:name="android.permission.HANDLE_QUERY_PACKAGE_RESTART" />
diff --git a/core/res/res/drawable-car/car_activity_resolver_list_background.xml b/core/res/res/drawable-car/car_activity_resolver_list_background.xml
deleted file mode 100644
index dbbadd83d9a8..000000000000
--- a/core/res/res/drawable-car/car_activity_resolver_list_background.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2024 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.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="?attr/colorBackgroundFloating" />
- <corners android:radius="@dimen/car_activity_resolver_corner_radius" />
-</shape> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_animal_paw.xml b/core/res/res/drawable/ic_zen_mode_icon_animal_paw.xml
new file mode 100644
index 000000000000..31004ecd0e72
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_animal_paw.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M180,485Q138,485 109,456Q80,427 80,385Q80,343 109,314Q138,285 180,285Q222,285 251,314Q280,343 280,385Q280,427 251,456Q222,485 180,485ZM360,325Q318,325 289,296Q260,267 260,225Q260,183 289,154Q318,125 360,125Q402,125 431,154Q460,183 460,225Q460,267 431,296Q402,325 360,325ZM600,325Q558,325 529,296Q500,267 500,225Q500,183 529,154Q558,125 600,125Q642,125 671,154Q700,183 700,225Q700,267 671,296Q642,325 600,325ZM780,485Q738,485 709,456Q680,427 680,385Q680,343 709,314Q738,285 780,285Q822,285 851,314Q880,343 880,385Q880,427 851,456Q822,485 780,485ZM266,885Q221,885 190.5,850.5Q160,816 160,769Q160,717 195.5,678Q231,639 266,601Q295,570 316,533.5Q337,497 366,465Q388,439 417,422Q446,405 480,405Q514,405 543,421Q572,437 594,463Q622,495 643.5,532Q665,569 694,601Q729,639 764.5,678Q800,717 800,769Q800,816 769.5,850.5Q739,885 694,885Q640,885 587,876Q534,867 480,867Q426,867 373,876Q320,885 266,885Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_apartment_building.xml b/core/res/res/drawable/ic_zen_mode_icon_apartment_building.xml
new file mode 100644
index 000000000000..30f01fa9d3b6
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_apartment_building.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M120,840L120,280L280,280L280,120L680,120L680,440L840,440L840,840L520,840L520,680L440,680L440,840L120,840ZM200,760L280,760L280,680L200,680L200,760ZM200,600L280,600L280,520L200,520L200,600ZM200,440L280,440L280,360L200,360L200,440ZM360,600L440,600L440,520L360,520L360,600ZM360,440L440,440L440,360L360,360L360,440ZM360,280L440,280L440,200L360,200L360,280ZM520,600L600,600L600,520L520,520L520,600ZM520,440L600,440L600,360L520,360L520,440ZM520,280L600,280L600,200L520,200L520,280ZM680,760L760,760L760,680L680,680L680,760ZM680,600L760,600L760,520L680,520L680,600Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_book.xml b/core/res/res/drawable/ic_zen_mode_icon_book.xml
new file mode 100644
index 000000000000..c30d222da7c1
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_book.xml
@@ -0,0 +1,26 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960"
+ android:autoMirrored="true">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M560,396L560,328Q593,314 627.5,307Q662,300 700,300Q726,300 751,304Q776,308 800,314L800,378Q776,369 751.5,364.5Q727,360 700,360Q662,360 627,369.5Q592,379 560,396ZM560,616L560,548Q593,534 627.5,527Q662,520 700,520Q726,520 751,524Q776,528 800,534L800,598Q776,589 751.5,584.5Q727,580 700,580Q662,580 627,589Q592,598 560,616ZM560,506L560,438Q593,424 627.5,417Q662,410 700,410Q726,410 751,414Q776,418 800,424L800,488Q776,479 751.5,474.5Q727,470 700,470Q662,470 627,479.5Q592,489 560,506ZM260,640Q307,640 351.5,650.5Q396,661 440,682L440,288Q399,264 353,252Q307,240 260,240Q224,240 188.5,247Q153,254 120,268Q120,268 120,268Q120,268 120,268L120,664Q120,664 120,664Q120,664 120,664Q155,652 189.5,646Q224,640 260,640ZM520,682Q564,661 608.5,650.5Q653,640 700,640Q736,640 770.5,646Q805,652 840,664Q840,664 840,664Q840,664 840,664L840,268Q840,268 840,268Q840,268 840,268Q807,254 771.5,247Q736,240 700,240Q653,240 607,252Q561,264 520,288L520,682ZM480,800Q432,762 376,741Q320,720 260,720Q218,720 177.5,731Q137,742 100,762Q79,773 59.5,761Q40,749 40,726L40,244Q40,233 45.5,223Q51,213 62,208Q108,184 158,172Q208,160 260,160Q318,160 373.5,175Q429,190 480,220Q531,190 586.5,175Q642,160 700,160Q752,160 802,172Q852,184 898,208Q909,213 914.5,223Q920,233 920,244L920,726Q920,749 900.5,761Q881,773 860,762Q823,742 782.5,731Q742,720 700,720Q640,720 584,741Q528,762 480,800ZM280,466Q280,466 280,466Q280,466 280,466L280,466Q280,466 280,466Q280,466 280,466Q280,466 280,466Q280,466 280,466Q280,466 280,466Q280,466 280,466L280,466Q280,466 280,466Q280,466 280,466Q280,466 280,466Q280,466 280,466Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_child.xml b/core/res/res/drawable/ic_zen_mode_icon_child.xml
new file mode 100644
index 000000000000..d11772ac1db6
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_child.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M580,470Q559,470 544.5,455.5Q530,441 530,420Q530,399 544.5,384.5Q559,370 580,370Q601,370 615.5,384.5Q630,399 630,420Q630,441 615.5,455.5Q601,470 580,470ZM380,470Q359,470 344.5,455.5Q330,441 330,420Q330,399 344.5,384.5Q359,370 380,370Q401,370 415.5,384.5Q430,399 430,420Q430,441 415.5,455.5Q401,470 380,470ZM480,680Q420,680 371.5,647Q323,614 300,560L660,560Q637,614 588.5,647Q540,680 480,680ZM480,840Q405,840 339.5,811.5Q274,783 225.5,734.5Q177,686 148.5,620.5Q120,555 120,480Q120,405 148.5,339.5Q177,274 225.5,225.5Q274,177 339.5,148.5Q405,120 480,120Q555,120 620.5,148.5Q686,177 734.5,225.5Q783,274 811.5,339.5Q840,405 840,480Q840,555 811.5,620.5Q783,686 734.5,734.5Q686,783 620.5,811.5Q555,840 480,840ZM480,760Q596,760 678,678Q760,596 760,480Q760,364 678,282Q596,200 480,200Q474,200 468,200Q462,200 456,202Q450,208 448,215Q446,222 446,230Q446,251 460.5,265.5Q475,280 496,280Q505,280 512.5,277Q520,274 528,274Q540,274 548,283Q556,292 556,304Q556,327 534.5,333.5Q513,340 496,340Q451,340 418.5,307.5Q386,275 386,230Q386,227 386,224Q386,221 387,216Q304,246 252,317Q200,388 200,480Q200,596 282,678Q364,760 480,760ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_classical_building.xml b/core/res/res/drawable/ic_zen_mode_icon_classical_building.xml
new file mode 100644
index 000000000000..26751262c673
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_classical_building.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M200,680L200,400L280,400L280,680L200,680ZM440,680L440,400L520,400L520,680L440,680ZM80,840L80,760L880,760L880,840L80,840ZM680,680L680,400L760,400L760,680L680,680ZM80,320L80,240L480,40L880,240L880,320L80,320ZM258,240L480,240L702,240L258,240ZM258,240L702,240L480,130L258,240Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_croissant.xml b/core/res/res/drawable/ic_zen_mode_icon_croissant.xml
new file mode 100644
index 000000000000..199343d0e502
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_croissant.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M804,678Q821,687 834,674Q847,661 838,644L780,536L738,644L804,678ZM604,640L652,640L748,402Q751,394 746.5,388.5Q742,383 736,380L656,348Q647,345 638.5,350Q630,355 628,364L604,640ZM308,640L356,640L332,364Q330,353 321.5,349Q313,345 304,348L224,380Q216,383 212.5,388.5Q209,394 212,402L308,640ZM156,678L222,644L180,536L122,644Q113,661 126,674Q139,687 156,678ZM436,640L524,640L554,302Q556,293 549.5,286.5Q543,280 534,280L426,280Q418,280 411.5,286.5Q405,293 406,302L436,640ZM138,760Q96,760 68,728.5Q40,697 40,654Q40,642 43.5,630.5Q47,619 52,608L140,440Q126,400 141,361Q156,322 194,306L274,274Q288,269 302,267Q316,265 330,268Q344,239 369,219.5Q394,200 426,200L534,200Q566,200 591,219.5Q616,239 630,268Q644,266 658,267.5Q672,269 686,274L766,306Q806,322 822,361Q838,400 820,438L908,606Q914,617 917,629Q920,641 920,654Q920,699 889.5,729.5Q859,760 814,760Q803,760 792,757.5Q781,755 770,750L708,720L250,720L194,750Q181,757 166.5,758.5Q152,760 138,760ZM480,480Q480,480 480,480Q480,480 480,480L480,480L480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_fork_and_knife.xml b/core/res/res/drawable/ic_zen_mode_icon_fork_and_knife.xml
new file mode 100644
index 000000000000..1fa73794eb32
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_fork_and_knife.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M280,880L280,514Q229,500 194.5,458Q160,416 160,360L160,80L240,80L240,360L280,360L280,80L360,80L360,360L400,360L400,80L480,80L480,360Q480,416 445.5,458Q411,500 360,514L360,880L280,880ZM680,880L680,560L560,560L560,280Q560,197 618.5,138.5Q677,80 760,80L760,880L680,880Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_group_of_people.xml b/core/res/res/drawable/ic_zen_mode_icon_group_of_people.xml
new file mode 100644
index 000000000000..c6194d529117
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_group_of_people.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M0,720L0,657Q0,614 44,587Q88,560 160,560Q173,560 185,560.5Q197,561 208,563Q194,584 187,607Q180,630 180,655L180,720L0,720ZM240,720L240,655Q240,623 257.5,596.5Q275,570 307,550Q339,530 383.5,520Q428,510 480,510Q533,510 577.5,520Q622,530 654,550Q686,570 703,596.5Q720,623 720,655L720,720L240,720ZM780,720L780,655Q780,629 773.5,606Q767,583 754,563Q765,561 776.5,560.5Q788,560 800,560Q872,560 916,586.5Q960,613 960,657L960,720L780,720ZM325,640L636,640L636,640Q626,620 580.5,605Q535,590 480,590Q425,590 379.5,605Q334,620 325,640ZM160,520Q127,520 103.5,496.5Q80,473 80,440Q80,406 103.5,383Q127,360 160,360Q194,360 217,383Q240,406 240,440Q240,473 217,496.5Q194,520 160,520ZM800,520Q767,520 743.5,496.5Q720,473 720,440Q720,406 743.5,383Q767,360 800,360Q834,360 857,383Q880,406 880,440Q880,473 857,496.5Q834,520 800,520ZM480,480Q430,480 395,445Q360,410 360,360Q360,309 395,274.5Q430,240 480,240Q531,240 565.5,274.5Q600,309 600,360Q600,410 565.5,445Q531,480 480,480ZM480,400Q497,400 508.5,388.5Q520,377 520,360Q520,343 508.5,331.5Q497,320 480,320Q463,320 451.5,331.5Q440,343 440,360Q440,377 451.5,388.5Q463,400 480,400ZM481,640L481,640Q481,640 481,640Q481,640 481,640Q481,640 481,640Q481,640 481,640L481,640ZM480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_headphones.xml b/core/res/res/drawable/ic_zen_mode_icon_headphones.xml
new file mode 100644
index 000000000000..f0bc7a211ca5
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_headphones.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M360,840L200,840Q167,840 143.5,816.5Q120,793 120,760L120,480Q120,405 148.5,339.5Q177,274 225.5,225.5Q274,177 339.5,148.5Q405,120 480,120Q555,120 620.5,148.5Q686,177 734.5,225.5Q783,274 811.5,339.5Q840,405 840,480L840,760Q840,793 816.5,816.5Q793,840 760,840L600,840L600,520L760,520L760,480Q760,363 678.5,281.5Q597,200 480,200Q363,200 281.5,281.5Q200,363 200,480L200,520L360,520L360,840ZM280,600L200,600L200,760Q200,760 200,760Q200,760 200,760L280,760L280,600ZM680,600L680,760L760,760Q760,760 760,760Q760,760 760,760L760,600L680,600ZM280,600L280,600L200,600Q200,600 200,600Q200,600 200,600L200,600L280,600ZM680,600L760,600L760,600Q760,600 760,600Q760,600 760,600L680,600Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_heart.xml b/core/res/res/drawable/ic_zen_mode_icon_heart.xml
new file mode 100644
index 000000000000..c9b1577d57f4
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_heart.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M480,840L422,788Q321,697 255,631Q189,565 150,512.5Q111,460 95.5,416Q80,372 80,326Q80,232 143,169Q206,106 300,106Q352,106 399,128Q446,150 480,190Q514,150 561,128Q608,106 660,106Q754,106 817,169Q880,232 880,326Q880,372 864.5,416Q849,460 810,512.5Q771,565 705,631Q639,697 538,788L480,840ZM480,732Q576,646 638,584.5Q700,523 736,477.5Q772,432 786,396.5Q800,361 800,326Q800,266 760,226Q720,186 660,186Q613,186 573,212.5Q533,239 518,280L518,280L442,280L442,280Q427,239 387,212.5Q347,186 300,186Q240,186 200,226Q160,266 160,326Q160,361 174,396.5Q188,432 224,477.5Q260,523 322,584.5Q384,646 480,732ZM480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459L480,459L480,459L480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_house.xml b/core/res/res/drawable/ic_zen_mode_icon_house.xml
new file mode 100644
index 000000000000..e25d194eb8d0
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_house.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M160,840L160,465L88,520L40,456L160,364L160,240L240,240L240,303L480,120L920,456L872,519L800,465L800,840L160,840ZM240,760L440,760L440,600L520,600L520,760L720,760L720,404L480,221L240,404L240,760ZM160,200Q160,150 195,115Q230,80 280,80Q297,80 308.5,68.5Q320,57 320,40L400,40Q400,90 365,125Q330,160 280,160Q263,160 251.5,171.5Q240,183 240,200L160,200ZM240,760L440,760L440,760L520,760L520,760L720,760L720,760L480,760L240,760Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_lightbulb.xml b/core/res/res/drawable/ic_zen_mode_icon_lightbulb.xml
new file mode 100644
index 000000000000..602e60d0824a
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_lightbulb.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M480,880Q454,880 433,867.5Q412,855 400,834L400,834Q367,834 343.5,810.5Q320,787 320,754L320,612Q261,573 225.5,509Q190,445 190,370Q190,249 274.5,164.5Q359,80 480,80Q601,80 685.5,164.5Q770,249 770,370Q770,447 734.5,510Q699,573 640,612L640,754Q640,787 616.5,810.5Q593,834 560,834L560,834Q548,855 527,867.5Q506,880 480,880ZM400,754L560,754L560,718L400,718L400,754ZM400,678L560,678L560,640L400,640L400,678ZM392,560L450,560L450,452L362,364L404,322L480,398L556,322L598,364L510,452L510,560L568,560Q622,534 656,483.5Q690,433 690,370Q690,282 629,221Q568,160 480,160Q392,160 331,221Q270,282 270,370Q270,433 304,483.5Q338,534 392,560ZM480,398L480,398L480,398L480,398L480,398L480,398L480,398L480,398L480,398ZM480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360L480,360L480,360L480,360L480,360L480,360L480,360L480,360L480,360L480,360Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_palette.xml b/core/res/res/drawable/ic_zen_mode_icon_palette.xml
new file mode 100644
index 000000000000..f31704de1498
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_palette.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M480,880Q398,880 325,848.5Q252,817 197.5,762.5Q143,708 111.5,635Q80,562 80,480Q80,397 112.5,324Q145,251 200.5,197Q256,143 330,111.5Q404,80 488,80Q568,80 639,107.5Q710,135 763.5,183.5Q817,232 848.5,298.5Q880,365 880,442Q880,557 810,618.5Q740,680 640,680L566,680Q557,680 553.5,685Q550,690 550,696Q550,708 565,730.5Q580,753 580,782Q580,832 552.5,856Q525,880 480,880ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480ZM260,520Q286,520 303,503Q320,486 320,460Q320,434 303,417Q286,400 260,400Q234,400 217,417Q200,434 200,460Q200,486 217,503Q234,520 260,520ZM380,360Q406,360 423,343Q440,326 440,300Q440,274 423,257Q406,240 380,240Q354,240 337,257Q320,274 320,300Q320,326 337,343Q354,360 380,360ZM580,360Q606,360 623,343Q640,326 640,300Q640,274 623,257Q606,240 580,240Q554,240 537,257Q520,274 520,300Q520,326 537,343Q554,360 580,360ZM700,520Q726,520 743,503Q760,486 760,460Q760,434 743,417Q726,400 700,400Q674,400 657,417Q640,434 640,460Q640,486 657,503Q674,520 700,520ZM480,800Q489,800 494.5,795Q500,790 500,782Q500,768 485,749Q470,730 470,692Q470,650 499,625Q528,600 570,600L640,600Q706,600 753,561.5Q800,523 800,442Q800,321 707.5,240.5Q615,160 488,160Q352,160 256,253Q160,346 160,480Q160,613 253.5,706.5Q347,800 480,800Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_rabbit.xml b/core/res/res/drawable/ic_zen_mode_icon_rabbit.xml
new file mode 100644
index 000000000000..190d0cb319ec
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_rabbit.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M380,880Q305,880 252.5,827.5Q200,775 200,700Q200,665 217,635.5Q234,606 280,560Q286,554 291.5,547.5Q297,541 306,530Q255,452 227.5,366.5Q200,281 200,200Q200,142 221,111Q242,80 280,80Q337,80 382,135Q427,190 450,236Q459,256 466.5,276.5Q474,297 480,319Q486,297 493.5,276.5Q501,256 511,236Q533,190 578,135Q623,80 680,80Q718,80 739,111Q760,142 760,200Q760,281 732.5,366.5Q705,452 654,530Q663,541 668.5,547.5Q674,554 680,560Q726,606 743,635.5Q760,665 760,700Q760,775 707.5,827.5Q655,880 580,880Q535,880 507.5,870Q480,860 480,860Q480,860 452.5,870Q425,880 380,880ZM380,800Q403,800 426,794.5Q449,789 469,778Q458,773 449,761Q440,749 440,740Q440,732 451.5,726Q463,720 480,720Q497,720 508.5,726Q520,732 520,740Q520,749 511,761Q502,773 491,778Q511,789 534,794.5Q557,800 580,800Q622,800 651,771Q680,742 680,700Q680,682 670,665Q660,648 640,631Q626,619 617,610Q608,601 588,576Q559,541 540,530.5Q521,520 480,520Q439,520 419.5,530.5Q400,541 372,576Q352,601 343,610Q334,619 320,631Q300,648 290,665Q280,682 280,700Q280,742 309,771Q338,800 380,800ZM420,670Q412,670 406,661Q400,652 400,640Q400,628 406,619Q412,610 420,610Q428,610 434,619Q440,628 440,640Q440,652 434,661Q428,670 420,670ZM540,670Q532,670 526,661Q520,652 520,640Q520,628 526,619Q532,610 540,610Q548,610 554,619Q560,628 560,640Q560,652 554,661Q548,670 540,670ZM363,471Q374,463 388,457Q402,451 419,446Q417,398 404.5,350.5Q392,303 373,264Q354,224 331,196.5Q308,169 285,161Q283,167 281.5,176.5Q280,186 280,200Q280,268 301.5,338Q323,408 363,471ZM597,471Q637,408 658.5,338Q680,268 680,200Q680,186 678.5,176.5Q677,167 675,161Q652,169 629,196.5Q606,224 587,264Q569,303 556.5,350.5Q544,398 541,446Q556,450 570,456.5Q584,463 597,471Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_running.xml b/core/res/res/drawable/ic_zen_mode_icon_running.xml
new file mode 100644
index 000000000000..472b04e24bc0
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_running.xml
@@ -0,0 +1,26 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960"
+ android:autoMirrored="true">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M520,920L520,680L436,600L396,776L120,720L136,640L328,680L392,356L320,384L320,520L240,520L240,332L398,264Q433,249 449.5,244.5Q466,240 480,240Q501,240 519,251Q537,262 548,280L588,344Q614,386 658.5,413Q703,440 760,440L760,520Q694,520 636.5,492.5Q579,465 540,420L516,540L600,620L600,920L520,920ZM540,220Q507,220 483.5,196.5Q460,173 460,140Q460,107 483.5,83.5Q507,60 540,60Q573,60 596.5,83.5Q620,107 620,140Q620,173 596.5,196.5Q573,220 540,220Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_shopping_cart.xml b/core/res/res/drawable/ic_zen_mode_icon_shopping_cart.xml
new file mode 100644
index 000000000000..92cec4dde7b7
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_shopping_cart.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M280,880Q247,880 223.5,856.5Q200,833 200,800Q200,767 223.5,743.5Q247,720 280,720Q313,720 336.5,743.5Q360,767 360,800Q360,833 336.5,856.5Q313,880 280,880ZM680,880Q647,880 623.5,856.5Q600,833 600,800Q600,767 623.5,743.5Q647,720 680,720Q713,720 736.5,743.5Q760,767 760,800Q760,833 736.5,856.5Q713,880 680,880ZM246,240L342,440L622,440Q622,440 622,440Q622,440 622,440L732,240Q732,240 732,240Q732,240 732,240L246,240ZM208,160L798,160Q821,160 833,180.5Q845,201 834,222L692,478Q681,498 662.5,509Q644,520 622,520L324,520L280,600Q280,600 280,600Q280,600 280,600L760,600L760,680L280,680Q235,680 212,640.5Q189,601 210,562L264,464L120,160L40,160L40,80L170,80L208,160ZM342,440L342,440L622,440Q622,440 622,440Q622,440 622,440L622,440L342,440Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_snowflake.xml b/core/res/res/drawable/ic_zen_mode_icon_snowflake.xml
new file mode 100644
index 000000000000..1746e20a6aae
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_snowflake.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M440,880L440,714L310,842L254,786L440,600L440,520L360,520L174,706L118,650L246,520L80,520L80,440L246,440L118,310L174,254L360,440L440,440L440,360L254,174L310,118L440,246L440,80L520,80L520,246L650,118L706,174L520,360L520,440L600,440L786,254L842,310L714,440L880,440L880,520L714,520L842,650L786,706L600,520L520,520L520,600L706,786L650,842L520,714L520,880L440,880Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_speech_bubble.xml b/core/res/res/drawable/ic_zen_mode_icon_speech_bubble.xml
new file mode 100644
index 000000000000..4be98abd9369
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_speech_bubble.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M80,880L80,160Q80,127 103.5,103.5Q127,80 160,80L800,80Q833,80 856.5,103.5Q880,127 880,160L880,640Q880,673 856.5,696.5Q833,720 800,720L240,720L80,880ZM206,640L800,640Q800,640 800,640Q800,640 800,640L800,160Q800,160 800,160Q800,160 800,160L160,160Q160,160 160,160Q160,160 160,160L160,685L206,640ZM160,640L160,640L160,160Q160,160 160,160Q160,160 160,160L160,160Q160,160 160,160Q160,160 160,160L160,640Q160,640 160,640Q160,640 160,640Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_train.xml b/core/res/res/drawable/ic_zen_mode_icon_train.xml
new file mode 100644
index 000000000000..b6f3445468a5
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_train.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M160,620L160,240Q160,187 187.5,155.5Q215,124 260,107.5Q305,91 362.5,85.5Q420,80 480,80Q546,80 604.5,85.5Q663,91 706.5,107.5Q750,124 775,155.5Q800,187 800,240L800,620Q800,679 759.5,719.5Q719,760 660,760L720,820L720,840L640,840L560,760L400,760L320,840L240,840L240,820L300,760Q241,760 200.5,719.5Q160,679 160,620ZM480,160Q374,160 325,172.5Q276,185 258,200L706,200Q691,183 641.5,171.5Q592,160 480,160ZM240,400L440,400L440,280L240,280L240,400ZM660,480L300,480Q274,480 257,480Q240,480 240,480L240,480L720,480L720,480Q720,480 703,480Q686,480 660,480ZM520,400L720,400L720,280L520,280L520,400ZM340,640Q366,640 383,623Q400,606 400,580Q400,554 383,537Q366,520 340,520Q314,520 297,537Q280,554 280,580Q280,606 297,623Q314,640 340,640ZM620,640Q646,640 663,623Q680,606 680,580Q680,554 663,537Q646,520 620,520Q594,520 577,537Q560,554 560,580Q560,606 577,623Q594,640 620,640ZM300,680L660,680Q686,680 703,663Q720,646 720,620L720,480L240,480L240,620Q240,646 257,663Q274,680 300,680ZM480,200Q592,200 641.5,200Q691,200 706,200L258,200Q276,200 325,200Q374,200 480,200Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_zen_mode_icon_tv.xml b/core/res/res/drawable/ic_zen_mode_icon_tv.xml
new file mode 100644
index 000000000000..eaa920aa37cc
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_mode_icon_tv.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M320,840L320,760L160,760Q127,760 103.5,736.5Q80,713 80,680L80,200Q80,167 103.5,143.5Q127,120 160,120L800,120Q833,120 856.5,143.5Q880,167 880,200L880,680Q880,713 856.5,736.5Q833,760 800,760L640,760L640,840L320,840ZM160,680L800,680Q800,680 800,680Q800,680 800,680L800,200Q800,200 800,200Q800,200 800,200L160,200Q160,200 160,200Q160,200 160,200L160,680Q160,680 160,680Q160,680 160,680ZM160,680Q160,680 160,680Q160,680 160,680L160,200Q160,200 160,200Q160,200 160,200L160,200Q160,200 160,200Q160,200 160,200L160,680Q160,680 160,680Q160,680 160,680Z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/layout-car/car_resolver_list.xml b/core/res/res/layout-car/car_resolver_list.xml
deleted file mode 100644
index 08c98615087b..000000000000
--- a/core/res/res/layout-car/car_resolver_list.xml
+++ /dev/null
@@ -1,127 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-* Copyright 2019, 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.
-*/
--->
-<com.android.internal.widget.ResolverDrawerLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="@dimen/car_activity_resolver_width"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:id="@id/contentPanel">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:background="@drawable/car_activity_resolver_list_background">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@drawable/car_activity_resolver_list_background"
- android:orientation="horizontal"
- android:paddingVertical="@dimen/car_padding_4"
- android:paddingHorizontal="@dimen/car_padding_4" >
- <TextView
- android:id="@+id/profile_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:visibility="gone" />
-
- <TextView
- android:id="@+id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="start"
- android:textAppearance="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle" />
- </LinearLayout>
-
- <FrameLayout
- android:id="@+id/stub"
- android:visibility="gone"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
-
- <TabHost
- android:id="@+id/profile_tabhost"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_centerHorizontal="true"
- android:background="?android:attr/colorBackgroundFloating">
- <LinearLayout
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <TabWidget
- android:id="@android:id/tabs"
- android:visibility="gone"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- </TabWidget>
- <View
- android:id="@+id/resolver_tab_divider"
- android:visibility="gone"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
- <FrameLayout
- android:id="@android:id/tabcontent"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <com.android.internal.app.ResolverViewPager
- android:id="@+id/profile_pager"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
- </FrameLayout>
- </LinearLayout>
- </TabHost>
-
- <LinearLayout
- android:id="@+id/button_bar"
- android:visibility="gone"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginVertical="@dimen/car_padding_4"
- android:layout_marginHorizontal="@dimen/car_padding_4"
- android:padding="0dp"
- android:gravity="center"
- android:background="@drawable/car_activity_resolver_list_background"
- android:orientation="vertical">
-
- <Button
- android:id="@+id/button_once"
- android:layout_width="match_parent"
- android:layout_height="@dimen/car_button_height"
- android:enabled="false"
- android:layout_gravity="center"
- android:layout_marginBottom="@dimen/car_padding_2"
- android:text="@string/activity_resolver_use_once"
- android:onClick="onButtonClick"/>
-
- <Button
- android:id="@+id/button_always"
- android:layout_width="match_parent"
- android:layout_height="@dimen/car_button_height"
- android:enabled="false"
- android:layout_gravity="center"
- android:text="@string/activity_resolver_use_always"
- android:onClick="onButtonClick"/>
- </LinearLayout>
-
- </LinearLayout>
-
-</com.android.internal.widget.ResolverDrawerLayout> \ No newline at end of file
diff --git a/core/res/res/layout-car/car_resolver_list_with_default.xml b/core/res/res/layout-car/car_resolver_list_with_default.xml
deleted file mode 100644
index 08cc7ff3021f..000000000000
--- a/core/res/res/layout-car/car_resolver_list_with_default.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-* Copyright 2019, 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.
-*/
--->
-<com.android.internal.widget.ResolverDrawerLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="@dimen/car_activity_resolver_width"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:id="@id/contentPanel">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_gravity="center"
- android:background="@drawable/car_activity_resolver_list_background">
-
- <FrameLayout
- android:id="@+id/stub"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@drawable/car_activity_resolver_list_background"/>
-
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="@dimen/car_activity_resolver_list_item_height"
- android:orientation="horizontal">
-
- <RadioButton
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:focusable="false"
- android:clickable="false"
- android:layout_marginStart="?attr/listPreferredItemPaddingStart"
- android:layout_gravity="start|center_vertical"
- android:checked="true"/>
-
- <ImageView
- android:id="@+id/icon"
- android:layout_width="@dimen/car_icon_size"
- android:layout_height="@dimen/car_icon_size"
- android:layout_gravity="start|center_vertical"
- android:layout_marginStart="@dimen/car_padding_4"
- android:src="@drawable/resolver_icon_placeholder"
- android:scaleType="fitCenter"/>
-
- <TextView
- android:id="@+id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginHorizontal="?attr/listPreferredItemPaddingStart"
- style="?android:attr/textAppearanceListItem"
- android:layout_gravity="start|center_vertical" />
-
- <LinearLayout
- android:id="@+id/profile_button"
- android:visibility="gone"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
-
- <ImageView
- android:id="@+id/icon"
- android:visibility="gone"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <TextView
- android:id="@id/text1"
- android:visibility="gone"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- </LinearLayout>
- </LinearLayout>
-
- <TabHost
- android:id="@+id/profile_tabhost"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_centerHorizontal="true"
- android:background="?attr/colorBackgroundFloating">
- <LinearLayout
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <TabWidget
- android:id="@android:id/tabs"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone">
- </TabWidget>
- <View
- android:id="@+id/resolver_tab_divider"
- android:visibility="gone"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
- <FrameLayout
- android:id="@android:id/tabcontent"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <com.android.internal.app.ResolverViewPager
- android:id="@+id/profile_pager"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- </com.android.internal.app.ResolverViewPager>
- </FrameLayout>
- </LinearLayout>
- </TabHost>
-
- <LinearLayout
- android:id="@+id/button_bar"
- android:visibility="gone"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginVertical="@dimen/car_padding_4"
- android:layout_marginHorizontal="@dimen/car_padding_4"
- android:gravity="center"
- android:background="@drawable/car_activity_resolver_list_background"
- android:orientation="vertical">
-
- <Button
- android:id="@+id/button_once"
- android:layout_width="match_parent"
- android:layout_height="@dimen/car_button_height"
- android:enabled="false"
- android:layout_gravity="center"
- android:layout_marginBottom="@dimen/car_padding_2"
- android:text="@string/activity_resolver_use_once"
- android:onClick="onButtonClick"/>
-
- <Button
- android:id="@+id/button_always"
- android:layout_width="match_parent"
- android:layout_height="@dimen/car_button_height"
- android:enabled="false"
- android:layout_gravity="center"
- android:text="@string/activity_resolver_use_always"
- android:onClick="onButtonClick"/>
- </LinearLayout>
- </LinearLayout>
-
-</com.android.internal.widget.ResolverDrawerLayout>
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index 61c7a8cde7d5..383033d9ae5d 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -237,6 +237,13 @@
<integer name="config_emergency_call_wait_for_connection_timeout_millis">20000</integer>
<java-symbol type="integer" name="config_emergency_call_wait_for_connection_timeout_millis" />
+ <!-- The time duration in millis after which Telephony will stop waiting for the OFF state
+ from cellular modem, consider the request to power off cellular modem as failed, and thus
+ treat the cellular modem state as ON.
+ -->
+ <integer name="config_satellite_wait_for_cellular_modem_off_timeout_millis">120000</integer>
+ <java-symbol type="integer" name="config_satellite_wait_for_cellular_modem_off_timeout_millis" />
+
<!-- Indicates the data limit in bytes that can be used for bootstrap sim until factory reset.
-1 means unlimited. -->
<integer name="config_esim_bootstrap_data_limit_bytes">-1</integer>
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteRawStatementTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteRawStatementTest.java
index 832ebe534c67..6dad3b7b2ac4 100644
--- a/core/tests/coretests/src/android/database/sqlite/SQLiteRawStatementTest.java
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteRawStatementTest.java
@@ -999,4 +999,31 @@ public class SQLiteRawStatementTest {
mDatabase.endTransaction();
}
}
+
+ /**
+ * This test verifies that the JNI exception thrown because of a bad column is actually thrown
+ * and does not crash the VM.
+ */
+ @Test
+ public void testJniExceptions() {
+ // Create the t1 table.
+ mDatabase.beginTransaction();
+ try {
+ mDatabase.execSQL("CREATE TABLE t1 (i int, j int);");
+ mDatabase.setTransactionSuccessful();
+ } finally {
+ mDatabase.endTransaction();
+ }
+
+ mDatabase.beginTransactionReadOnly();
+ try (SQLiteRawStatement s = mDatabase.createRawStatement("SELECT * from t1")) {
+ s.step();
+ s.getColumnText(5); // out-of-range column
+ fail("JNI exception not thrown");
+ } catch (SQLiteBindOrColumnIndexOutOfRangeException e) {
+ // Passing case.
+ } finally {
+ mDatabase.endTransaction();
+ }
+ }
}
diff --git a/core/tests/coretests/src/android/graphics/PaintFontVariationTest.java b/core/tests/coretests/src/android/graphics/PaintFontVariationTest.java
new file mode 100644
index 000000000000..8a54e5b998e7
--- /dev/null
+++ b/core/tests/coretests/src/android/graphics/PaintFontVariationTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.test.InstrumentationTestCase;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.text.flags.Flags;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * PaintTest tests {@link Paint}.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PaintFontVariationTest extends InstrumentationTestCase {
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
+ @RequiresFlagsEnabled(Flags.FLAG_TYPEFACE_CACHE_FOR_VAR_SETTINGS)
+ @Test
+ public void testDerivedFromSameTypeface() {
+ final Paint p = new Paint();
+
+ p.setTypeface(Typeface.SANS_SERIF);
+ assertThat(p.setFontVariationSettings("'wght' 450")).isTrue();
+ Typeface first = p.getTypeface();
+
+ p.setTypeface(Typeface.SANS_SERIF);
+ assertThat(p.setFontVariationSettings("'wght' 480")).isTrue();
+ Typeface second = p.getTypeface();
+
+ assertThat(first.getDerivedFrom()).isSameInstanceAs(second.getDerivedFrom());
+ }
+
+ @RequiresFlagsEnabled(Flags.FLAG_TYPEFACE_CACHE_FOR_VAR_SETTINGS)
+ @Test
+ public void testDerivedFromChained() {
+ final Paint p = new Paint();
+
+ p.setTypeface(Typeface.SANS_SERIF);
+ assertThat(p.setFontVariationSettings("'wght' 450")).isTrue();
+ Typeface first = p.getTypeface();
+
+ assertThat(p.setFontVariationSettings("'wght' 480")).isTrue();
+ Typeface second = p.getTypeface();
+
+ assertThat(first.getDerivedFrom()).isSameInstanceAs(second.getDerivedFrom());
+ }
+}
diff --git a/core/tests/coretests/src/android/graphics/PaintTest.java b/core/tests/coretests/src/android/graphics/PaintTest.java
index 0dec756d7611..878ba703c8fe 100644
--- a/core/tests/coretests/src/android/graphics/PaintTest.java
+++ b/core/tests/coretests/src/android/graphics/PaintTest.java
@@ -16,13 +16,22 @@
package android.graphics;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertNotEquals;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.test.InstrumentationTestCase;
import android.text.TextUtils;
import androidx.test.filters.SmallTest;
+import com.android.text.flags.Flags;
+
+import org.junit.Rule;
+
import java.util.Arrays;
import java.util.HashSet;
@@ -30,6 +39,9 @@ import java.util.HashSet;
* PaintTest tests {@link Paint}.
*/
public class PaintTest extends InstrumentationTestCase {
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
private static final String FONT_PATH = "fonts/HintedAdvanceWidthTest-Regular.ttf";
static void assertEquals(String message, float[] expected, float[] actual) {
@@ -403,4 +415,33 @@ public class PaintTest extends InstrumentationTestCase {
assertEquals(6, getClusterCount(p, rtlStr + ltrStr));
assertEquals(9, getClusterCount(p, ltrStr + rtlStr + ltrStr));
}
+
+ @RequiresFlagsEnabled(Flags.FLAG_TYPEFACE_CACHE_FOR_VAR_SETTINGS)
+ public void testDerivedFromSameTypeface() {
+ final Paint p = new Paint();
+
+ p.setTypeface(Typeface.SANS_SERIF);
+ assertThat(p.setFontVariationSettings("'wght' 450")).isTrue();
+ Typeface first = p.getTypeface();
+
+ p.setTypeface(Typeface.SANS_SERIF);
+ assertThat(p.setFontVariationSettings("'wght' 480")).isTrue();
+ Typeface second = p.getTypeface();
+
+ assertThat(first.getDerivedFrom()).isSameInstanceAs(second.getDerivedFrom());
+ }
+
+ @RequiresFlagsEnabled(Flags.FLAG_TYPEFACE_CACHE_FOR_VAR_SETTINGS)
+ public void testDerivedFromChained() {
+ final Paint p = new Paint();
+
+ p.setTypeface(Typeface.SANS_SERIF);
+ assertThat(p.setFontVariationSettings("'wght' 450")).isTrue();
+ Typeface first = p.getTypeface();
+
+ assertThat(p.setFontVariationSettings("'wght' 480")).isTrue();
+ Typeface second = p.getTypeface();
+
+ assertThat(first.getDerivedFrom()).isSameInstanceAs(second.getDerivedFrom());
+ }
}
diff --git a/core/tests/coretests/src/android/view/contentprotection/OWNERS b/core/tests/coretests/src/android/view/contentprotection/OWNERS
index b3583a7f6ab1..3d09da303b0f 100644
--- a/core/tests/coretests/src/android/view/contentprotection/OWNERS
+++ b/core/tests/coretests/src/android/view/contentprotection/OWNERS
@@ -1,4 +1,4 @@
-# Bug component: 544200
+# Bug component: 1040349
-include /core/java/android/view/contentcapture/OWNERS
+include /core/java/android/view/contentprotection/OWNERS
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index fd788167a0d8..889a778556b7 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -56,6 +56,7 @@ import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
+import com.android.text.flags.Flags;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
@@ -74,6 +75,7 @@ import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -143,6 +145,23 @@ public class Typeface {
private static final LruCache<String, Typeface> sDynamicTypefaceCache = new LruCache<>(16);
private static final Object sDynamicCacheLock = new Object();
+ private static final LruCache<Long, LruCache<String, Typeface>> sVariableCache =
+ new LruCache<>(16);
+ private static final Object sVariableCacheLock = new Object();
+
+ /** @hide */
+ @VisibleForTesting
+ public static void clearTypefaceCachesForTestingPurpose() {
+ synchronized (sWeightCacheLock) {
+ sWeightTypefaceCache.clear();
+ }
+ synchronized (sDynamicCacheLock) {
+ sDynamicTypefaceCache.evictAll();
+ }
+ synchronized (sVariableCacheLock) {
+ sVariableCache.evictAll();
+ }
+ }
@GuardedBy("SYSTEM_FONT_MAP_LOCK")
static Typeface sDefaultTypeface;
@@ -195,6 +214,8 @@ public class Typeface {
@UnsupportedAppUsage
public final long native_instance;
+ private final Typeface mDerivedFrom;
+
private final String mSystemFontFamilyName;
private final Runnable mCleaner;
@@ -274,6 +295,18 @@ public class Typeface {
}
/**
+ * Returns the Typeface used for creating this Typeface.
+ *
+ * Maybe null if this is not derived from other Typeface.
+ * TODO(b/357707916): Make this public API.
+ * @hide
+ */
+ @VisibleForTesting
+ public final @Nullable Typeface getDerivedFrom() {
+ return mDerivedFrom;
+ }
+
+ /**
* Returns the system font family name if the typeface was created from a system font family,
* otherwise returns null.
*/
@@ -1021,9 +1054,51 @@ public class Typeface {
return typeface;
}
- /** @hide */
+ private static String axesToVarKey(@NonNull List<FontVariationAxis> axes) {
+ // The given list can be mutated because it is allocated in Paint#setFontVariationSettings.
+ // Currently, Paint#setFontVariationSettings is the only code path reaches this method.
+ axes.sort(Comparator.comparingInt(FontVariationAxis::getOpenTypeTagValue));
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < axes.size(); ++i) {
+ final FontVariationAxis fva = axes.get(i);
+ sb.append(fva.getTag());
+ sb.append(fva.getStyleValue());
+ }
+ return sb.toString();
+ }
+
+ /**
+ * TODO(b/357707916): Make this public API.
+ * @hide
+ */
public static Typeface createFromTypefaceWithVariation(@Nullable Typeface family,
@NonNull List<FontVariationAxis> axes) {
+ if (Flags.typefaceCacheForVarSettings()) {
+ final Typeface target = (family == null) ? Typeface.DEFAULT : family;
+ final Typeface base = (target.mDerivedFrom == null) ? target : target.mDerivedFrom;
+
+ final String key = axesToVarKey(axes);
+
+ synchronized (sVariableCacheLock) {
+ LruCache<String, Typeface> innerCache = sVariableCache.get(base.native_instance);
+ if (innerCache == null) {
+ // Cache up to 16 var instance per root Typeface
+ innerCache = new LruCache<>(16);
+ sVariableCache.put(base.native_instance, innerCache);
+ } else {
+ Typeface cached = innerCache.get(key);
+ if (cached != null) {
+ return cached;
+ }
+ }
+ Typeface typeface = new Typeface(
+ nativeCreateFromTypefaceWithVariation(base.native_instance, axes),
+ base.getSystemFontFamilyName(), base);
+ innerCache.put(key, typeface);
+ return typeface;
+ }
+ }
+
final Typeface base = family == null ? Typeface.DEFAULT : family;
Typeface typeface = new Typeface(
nativeCreateFromTypefaceWithVariation(base.native_instance, axes),
@@ -1184,11 +1259,19 @@ public class Typeface {
// don't allow clients to call this directly
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private Typeface(long ni) {
- this(ni, null);
+ this(ni, null, null);
}
+
// don't allow clients to call this directly
+ // This is kept for robolectric.
private Typeface(long ni, @Nullable String systemFontFamilyName) {
+ this(ni, systemFontFamilyName, null);
+ }
+
+ // don't allow clients to call this directly
+ private Typeface(long ni, @Nullable String systemFontFamilyName,
+ @Nullable Typeface derivedFrom) {
if (ni == 0) {
throw new RuntimeException("native typeface cannot be made");
}
@@ -1198,6 +1281,7 @@ public class Typeface {
mStyle = nativeGetStyle(ni);
mWeight = nativeGetWeight(ni);
mSystemFontFamilyName = systemFontFamilyName;
+ mDerivedFrom = derivedFrom;
}
/**
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 8627c0b920e5..53ab2d56f6e6 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -539,20 +539,23 @@
<!-- The size of the icon shown in the resize veil. -->
<dimen name="desktop_mode_resize_veil_icon_size">96dp</dimen>
- <!-- The with of the border around the app task for edge resizing, when
+ <!-- The width of the border outside the app task eligible for edge resizing, when
enable_windowing_edge_drag_resize is enabled. -->
- <dimen name="desktop_mode_edge_handle">12dp</dimen>
+ <dimen name="freeform_edge_handle_outset">10dp</dimen>
+
+ <!-- The size of the border inside the app task eligible for edge resizing, when
+ enable_windowing_edge_drag_resize is enabled. -->
+ <dimen name="freeform_edge_handle_inset">2dp</dimen>
<!-- The original width of the border around the app task for edge resizing, when
enable_windowing_edge_drag_resize is disabled. -->
<dimen name="freeform_resize_handle">15dp</dimen>
<!-- The size of the corner region for drag resizing with touch, when a larger touch region is
- appropriate. Applied when enable_windowing_edge_drag_resize is enabled. -->
+ appropriate. -->
<dimen name="desktop_mode_corner_resize_large">48dp</dimen>
- <!-- The original size of the corner region for darg resizing, when
- enable_windowing_edge_drag_resize is disabled. -->
+ <!-- The size of the corner region for drag resizing with a cursor or a stylus. -->
<dimen name="freeform_resize_corner">44dp</dimen>
<!-- The thickness in dp for all desktop drag transition regions. -->
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 221416341dca..cfe3cfad123f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -1997,10 +1997,15 @@ public class BubbleController implements ConfigurationChangeListener,
@Override
public void expansionChanged(boolean isExpanded) {
- // in bubble bar mode, let the request to show the expanded view come from launcher.
- // only collapse here if we're collapsing.
- if (mLayerView != null && !isExpanded) {
- mLayerView.collapse();
+ if (mLayerView != null) {
+ if (!isExpanded) {
+ mLayerView.collapse();
+ } else {
+ BubbleViewProvider selectedBubble = mBubbleData.getSelectedBubble();
+ if (selectedBubble != null) {
+ mLayerView.showExpandedView(selectedBubble);
+ }
+ }
}
}
@@ -2146,13 +2151,6 @@ public class BubbleController implements ConfigurationChangeListener,
}
};
- private void showExpandedViewForBubbleBar() {
- BubbleViewProvider selectedBubble = mBubbleData.getSelectedBubble();
- if (selectedBubble != null) {
- mLayerView.showExpandedView(selectedBubble);
- }
- }
-
private void updateOverflowButtonDot() {
BubbleOverflow overflow = mBubbleData.getOverflow();
if (overflow == null) return;
@@ -2535,15 +2533,6 @@ public class BubbleController implements ConfigurationChangeListener,
if (mLayerView != null) mLayerView.updateExpandedView();
});
}
-
- @Override
- public void showExpandedView() {
- mMainExecutor.execute(() -> {
- if (mLayerView != null) {
- showExpandedViewForBubbleBar();
- }
- });
- }
}
private class BubblesImpl implements Bubbles {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
index 5779a8f7bcc4..5c789749412c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
@@ -53,6 +53,4 @@ interface IBubbles {
oneway void showShortcutBubble(in ShortcutInfo info) = 12;
oneway void showAppBubble(in Intent intent) = 13;
-
- oneway void showExpandedView() = 14;
} \ No newline at end of file
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 456d92ae2396..544c2dd5c484 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
@@ -1108,16 +1108,21 @@ class DesktopTasksController(
/** Handle task closing by removing wallpaper activity if it's the last active task */
private fun handleTaskClosing(task: RunningTaskInfo): WindowContainerTransaction? {
logV("handleTaskClosing")
+ if (!isDesktopModeShowing(task.displayId))
+ return null
+
val wct = WindowContainerTransaction()
if (taskRepository.isOnlyVisibleNonClosingTask(task.taskId)
- && taskRepository.wallpaperActivityToken != null) {
+ && taskRepository.wallpaperActivityToken != null
+ ) {
// Remove wallpaper activity when the last active task is removed
removeWallpaperActivity(wct)
}
taskRepository.addClosingTask(task.displayId, task.taskId)
// If a CLOSE or TO_BACK is triggered on a desktop task, remove the task.
if (DesktopModeFlags.BACK_NAVIGATION.isEnabled(context) &&
- taskRepository.isVisibleTask(task.taskId)) {
+ taskRepository.isVisibleTask(task.taskId)
+ ) {
wct.removeTask(task.token)
}
return if (wct.isEmpty) null else wct
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
index 401b78df026a..39260f64c9f4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -19,6 +19,7 @@ package com.android.wm.shell.windowdecor;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getFineResizeCornerSize;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getLargeResizeCornerSize;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getResizeEdgeHandleSize;
+import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getResizeHandleEdgeInset;
import android.annotation.NonNull;
import android.annotation.SuppressLint;
@@ -286,7 +287,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
final Resources res = mResult.mRootView.getResources();
mDragResizeListener.setGeometry(new DragResizeWindowGeometry(0 /* taskCornerRadius */,
new Size(mResult.mWidth, mResult.mHeight), getResizeEdgeHandleSize(mContext, res),
- getFineResizeCornerSize(res), getLargeResizeCornerSize(res)), touchSlop);
+ getResizeHandleEdgeInset(res), getFineResizeCornerSize(res),
+ getLargeResizeCornerSize(res)), touchSlop);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 538d0fb9cbf6..b5f5bb931c02 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -31,6 +31,7 @@ import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSIT
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getFineResizeCornerSize;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getLargeResizeCornerSize;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getResizeEdgeHandleSize;
+import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getResizeHandleEdgeInset;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -515,8 +516,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
if (mDragResizeListener.setGeometry(
new DragResizeWindowGeometry(mRelayoutParams.mCornerRadius,
new Size(mResult.mWidth, mResult.mHeight),
- getResizeEdgeHandleSize(mContext, res), getFineResizeCornerSize(res),
- getLargeResizeCornerSize(res)), touchSlop)
+ getResizeEdgeHandleSize(mContext, res), getResizeHandleEdgeInset(res),
+ getFineResizeCornerSize(res), getLargeResizeCornerSize(res)), touchSlop)
|| !mTaskInfo.positionInParent.equals(mPositionInParent)) {
updateExclusionRegion();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
index 014d61d00b9e..fd7bed7c60de 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
@@ -44,27 +44,32 @@ import java.util.Objects;
final class DragResizeWindowGeometry {
private final int mTaskCornerRadius;
private final Size mTaskSize;
- // The size of the handle applied to the edges of the window, for the user to drag resize.
- private final int mResizeHandleThickness;
+ // The size of the handle outside the task window applied to the edges of the window, for the
+ // user to drag resize.
+ private final int mResizeHandleEdgeOutset;
+ // The size of the handle inside the task window applied to the edges of the window, for the
+ // user to drag resize.
+ private final int mResizeHandleEdgeInset;
// The task corners to permit drag resizing with a course input, such as touch.
-
private final @NonNull TaskCorners mLargeTaskCorners;
// The task corners to permit drag resizing with a fine input, such as stylus or cursor.
private final @NonNull TaskCorners mFineTaskCorners;
// The bounds for each edge drag region, which can resize the task in one direction.
- private final @NonNull TaskEdges mTaskEdges;
+ final @NonNull TaskEdges mTaskEdges;
DragResizeWindowGeometry(int taskCornerRadius, @NonNull Size taskSize,
- int resizeHandleThickness, int fineCornerSize, int largeCornerSize) {
+ int resizeHandleEdgeOutset, int resizeHandleEdgeInset, int fineCornerSize,
+ int largeCornerSize) {
mTaskCornerRadius = taskCornerRadius;
mTaskSize = taskSize;
- mResizeHandleThickness = resizeHandleThickness;
+ mResizeHandleEdgeOutset = resizeHandleEdgeOutset;
+ mResizeHandleEdgeInset = resizeHandleEdgeInset;
mLargeTaskCorners = new TaskCorners(mTaskSize, largeCornerSize);
mFineTaskCorners = new TaskCorners(mTaskSize, fineCornerSize);
// Save touch areas for each edge.
- mTaskEdges = new TaskEdges(mTaskSize, mResizeHandleThickness);
+ mTaskEdges = new TaskEdges(mTaskSize, mResizeHandleEdgeOutset, mResizeHandleEdgeInset);
}
/**
@@ -72,11 +77,18 @@ final class DragResizeWindowGeometry {
*/
static int getResizeEdgeHandleSize(@NonNull Context context, @NonNull Resources res) {
return EDGE_DRAG_RESIZE.isEnabled(context)
- ? res.getDimensionPixelSize(R.dimen.desktop_mode_edge_handle)
+ ? res.getDimensionPixelSize(R.dimen.freeform_edge_handle_outset)
: res.getDimensionPixelSize(R.dimen.freeform_resize_handle);
}
/**
+ * Returns the resource value to use for the edge resize handle inside the task bounds.
+ */
+ static int getResizeHandleEdgeInset(@NonNull Resources res) {
+ return res.getDimensionPixelSize(R.dimen.freeform_edge_handle_inset);
+ }
+
+ /**
* Returns the resource value to use for course input, such as touch, that benefits from a large
* square on each of the window's corners.
*/
@@ -95,7 +107,8 @@ final class DragResizeWindowGeometry {
/**
* Returns the size of the task this geometry is calculated for.
*/
- @NonNull Size getTaskSize() {
+ @NonNull
+ Size getTaskSize() {
// Safe to return directly since size is immutable.
return mTaskSize;
}
@@ -217,13 +230,15 @@ final class DragResizeWindowGeometry {
ctrlType |= CTRL_TYPE_BOTTOM;
}
// If the touch is within one of the four corners, check if it is within the bounds of the
- // // handle.
+ // handle.
if ((ctrlType & (CTRL_TYPE_LEFT | CTRL_TYPE_RIGHT)) != 0
&& (ctrlType & (CTRL_TYPE_TOP | CTRL_TYPE_BOTTOM)) != 0) {
return checkDistanceFromCenter(ctrlType, x, y);
}
- // Otherwise, we should make sure we don't resize tasks inside task bounds.
- return (x < 0 || y < 0 || x >= mTaskSize.getWidth() || y >= mTaskSize.getHeight())
+ // Allow a small resize handle inside the task bounds defined by the edge inset.
+ return (x <= mResizeHandleEdgeInset || y <= mResizeHandleEdgeInset
+ || x >= mTaskSize.getWidth() - mResizeHandleEdgeInset
+ || y >= mTaskSize.getHeight() - mResizeHandleEdgeInset)
? ctrlType : CTRL_TYPE_UNDEFINED;
}
@@ -237,7 +252,7 @@ final class DragResizeWindowGeometry {
final Point cornerRadiusCenter = calculateCenterForCornerRadius(ctrlType);
double distanceFromCenter = Math.hypot(x - cornerRadiusCenter.x, y - cornerRadiusCenter.y);
- if (distanceFromCenter < mTaskCornerRadius + mResizeHandleThickness
+ if (distanceFromCenter < mTaskCornerRadius + mResizeHandleEdgeOutset
&& distanceFromCenter >= mTaskCornerRadius) {
return ctrlType;
}
@@ -288,7 +303,8 @@ final class DragResizeWindowGeometry {
return this.mTaskCornerRadius == other.mTaskCornerRadius
&& this.mTaskSize.equals(other.mTaskSize)
- && this.mResizeHandleThickness == other.mResizeHandleThickness
+ && this.mResizeHandleEdgeOutset == other.mResizeHandleEdgeOutset
+ && this.mResizeHandleEdgeInset == other.mResizeHandleEdgeInset
&& this.mFineTaskCorners.equals(other.mFineTaskCorners)
&& this.mLargeTaskCorners.equals(other.mLargeTaskCorners)
&& this.mTaskEdges.equals(other.mTaskEdges);
@@ -299,7 +315,8 @@ final class DragResizeWindowGeometry {
return Objects.hash(
mTaskCornerRadius,
mTaskSize,
- mResizeHandleThickness,
+ mResizeHandleEdgeOutset,
+ mResizeHandleEdgeInset,
mFineTaskCorners,
mLargeTaskCorners,
mTaskEdges);
@@ -421,26 +438,27 @@ final class DragResizeWindowGeometry {
private final @NonNull Rect mBottomEdgeBounds;
private final @NonNull Region mRegion;
- private TaskEdges(@NonNull Size taskSize, int resizeHandleThickness) {
+ private TaskEdges(@NonNull Size taskSize, int resizeHandleThickness,
+ int resizeHandleEdgeInset) {
// Save touch areas for each edge.
mTopEdgeBounds = new Rect(
-resizeHandleThickness,
-resizeHandleThickness,
taskSize.getWidth() + resizeHandleThickness,
- 0);
+ resizeHandleThickness);
mLeftEdgeBounds = new Rect(
-resizeHandleThickness,
0,
- 0,
+ resizeHandleEdgeInset,
taskSize.getHeight());
mRightEdgeBounds = new Rect(
- taskSize.getWidth(),
+ taskSize.getWidth() - resizeHandleEdgeInset,
0,
taskSize.getWidth() + resizeHandleThickness,
taskSize.getHeight());
mBottomEdgeBounds = new Rect(
-resizeHandleThickness,
- taskSize.getHeight(),
+ taskSize.getHeight() - resizeHandleEdgeInset,
taskSize.getWidth() + resizeHandleThickness,
taskSize.getHeight() + resizeHandleThickness);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index 18c62282f035..a630cef99474 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -1819,6 +1819,19 @@ class DesktopTasksControllerTest : ShellTestCase() {
}
@Test
+ @EnableFlags(
+ Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
+ )
+ fun handleRequest_backTransition_singleTaskNoToken_withWallpaper_notInDesktop_doesNotHandle() {
+ val task = setUpFreeformTask()
+ markTaskHidden(task)
+
+ val result = controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK))
+
+ assertNull(result, "Should not handle request")
+ }
+
+ @Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
@DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION)
fun handleRequest_backTransition_singleTaskNoToken_noBackNav_doesNotHandle() {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java
index d8f395d76b39..1691f077a030 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java
@@ -45,6 +45,9 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Arrays;
+import java.util.List;
+
/**
* Tests for {@link DragResizeWindowGeometry}.
*
@@ -57,11 +60,12 @@ public class DragResizeWindowGeometryTests extends ShellTestCase {
private static final Size TASK_SIZE = new Size(500, 1000);
private static final int TASK_CORNER_RADIUS = 10;
private static final int EDGE_RESIZE_THICKNESS = 12;
+ private static final int EDGE_RESIZE_HANDLE_INSET = 4;
private static final int FINE_CORNER_SIZE = EDGE_RESIZE_THICKNESS * 2 + 10;
private static final int LARGE_CORNER_SIZE = FINE_CORNER_SIZE + 10;
private static final DragResizeWindowGeometry GEOMETRY = new DragResizeWindowGeometry(
- TASK_CORNER_RADIUS, TASK_SIZE, EDGE_RESIZE_THICKNESS, FINE_CORNER_SIZE,
- LARGE_CORNER_SIZE);
+ TASK_CORNER_RADIUS, TASK_SIZE, EDGE_RESIZE_THICKNESS, EDGE_RESIZE_HANDLE_INSET,
+ FINE_CORNER_SIZE, LARGE_CORNER_SIZE);
// Points in the edge resize handle. Note that coordinates start from the top left.
private static final Point TOP_EDGE_POINT = new Point(TASK_SIZE.getWidth() / 2,
-EDGE_RESIZE_THICKNESS / 2);
@@ -71,6 +75,16 @@ public class DragResizeWindowGeometryTests extends ShellTestCase {
TASK_SIZE.getWidth() + EDGE_RESIZE_THICKNESS / 2, TASK_SIZE.getHeight() / 2);
private static final Point BOTTOM_EDGE_POINT = new Point(TASK_SIZE.getWidth() / 2,
TASK_SIZE.getHeight() + EDGE_RESIZE_THICKNESS / 2);
+ // Points in the inset of the task bounds still within the edge resize handle.
+ // Note that coordinates start from the top left.
+ private static final Point TOP_INSET_POINT = new Point(TASK_SIZE.getWidth() / 2,
+ EDGE_RESIZE_HANDLE_INSET / 2);
+ private static final Point LEFT_INSET_POINT = new Point(EDGE_RESIZE_HANDLE_INSET / 2,
+ TASK_SIZE.getHeight() / 2);
+ private static final Point RIGHT_INSET_POINT = new Point(
+ TASK_SIZE.getWidth() - EDGE_RESIZE_HANDLE_INSET / 2, TASK_SIZE.getHeight() / 2);
+ private static final Point BOTTOM_INSET_POINT = new Point(TASK_SIZE.getWidth() / 2,
+ TASK_SIZE.getHeight() - EDGE_RESIZE_HANDLE_INSET / 2);
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@@ -85,18 +99,23 @@ public class DragResizeWindowGeometryTests extends ShellTestCase {
.addEqualityGroup(
GEOMETRY,
new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE,
- EDGE_RESIZE_THICKNESS, FINE_CORNER_SIZE, LARGE_CORNER_SIZE))
+ EDGE_RESIZE_THICKNESS, EDGE_RESIZE_HANDLE_INSET, FINE_CORNER_SIZE,
+ LARGE_CORNER_SIZE))
.addEqualityGroup(
new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE,
- EDGE_RESIZE_THICKNESS + 10, FINE_CORNER_SIZE, LARGE_CORNER_SIZE),
+ EDGE_RESIZE_THICKNESS + 10, EDGE_RESIZE_HANDLE_INSET,
+ FINE_CORNER_SIZE, LARGE_CORNER_SIZE),
new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE,
- EDGE_RESIZE_THICKNESS + 10, FINE_CORNER_SIZE, LARGE_CORNER_SIZE))
+ EDGE_RESIZE_THICKNESS + 10, EDGE_RESIZE_HANDLE_INSET,
+ FINE_CORNER_SIZE, LARGE_CORNER_SIZE))
.addEqualityGroup(
new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE,
- EDGE_RESIZE_THICKNESS + 10, FINE_CORNER_SIZE,
+ EDGE_RESIZE_THICKNESS + 10, EDGE_RESIZE_HANDLE_INSET,
+ FINE_CORNER_SIZE,
LARGE_CORNER_SIZE + 5),
new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE,
- EDGE_RESIZE_THICKNESS + 10, FINE_CORNER_SIZE,
+ EDGE_RESIZE_THICKNESS + 10, EDGE_RESIZE_HANDLE_INSET,
+ FINE_CORNER_SIZE,
LARGE_CORNER_SIZE + 5))
.testEquals();
}
@@ -127,7 +146,7 @@ public class DragResizeWindowGeometryTests extends ShellTestCase {
assertThat(region.contains(point.x - EDGE_RESIZE_THICKNESS, point.y)).isTrue();
// Vertically along the edge is not contained.
assertThat(region.contains(point.x, point.y - EDGE_RESIZE_THICKNESS)).isFalse();
- assertThat(region.contains(point.x, point.y + EDGE_RESIZE_THICKNESS)).isFalse();
+ assertThat(region.contains(point.x, point.y + EDGE_RESIZE_THICKNESS + 10)).isFalse();
}
private static void verifyVerticalEdge(@NonNull Region region, @NonNull Point point) {
@@ -188,18 +207,18 @@ public class DragResizeWindowGeometryTests extends ShellTestCase {
}
private void validateCtrlTypeForEdges(boolean isTouchscreen, boolean isEdgeResizePermitted) {
- assertThat(GEOMETRY.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted,
- LEFT_EDGE_POINT.x, LEFT_EDGE_POINT.y)).isEqualTo(
- isEdgeResizePermitted ? CTRL_TYPE_LEFT : CTRL_TYPE_UNDEFINED);
- assertThat(GEOMETRY.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted,
- TOP_EDGE_POINT.x, TOP_EDGE_POINT.y)).isEqualTo(
- isEdgeResizePermitted ? CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED);
- assertThat(GEOMETRY.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted,
- RIGHT_EDGE_POINT.x, RIGHT_EDGE_POINT.y)).isEqualTo(
- isEdgeResizePermitted ? CTRL_TYPE_RIGHT : CTRL_TYPE_UNDEFINED);
- assertThat(GEOMETRY.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted,
- BOTTOM_EDGE_POINT.x, BOTTOM_EDGE_POINT.y)).isEqualTo(
- isEdgeResizePermitted ? CTRL_TYPE_BOTTOM : CTRL_TYPE_UNDEFINED);
+ List<Point> points = Arrays.asList(LEFT_EDGE_POINT, TOP_EDGE_POINT, RIGHT_EDGE_POINT,
+ BOTTOM_EDGE_POINT, LEFT_INSET_POINT, TOP_INSET_POINT, RIGHT_INSET_POINT,
+ BOTTOM_INSET_POINT);
+ List<Integer> expectedCtrlType = Arrays.asList(CTRL_TYPE_LEFT, CTRL_TYPE_TOP,
+ CTRL_TYPE_RIGHT, CTRL_TYPE_BOTTOM, CTRL_TYPE_LEFT, CTRL_TYPE_TOP, CTRL_TYPE_RIGHT,
+ CTRL_TYPE_BOTTOM);
+
+ for (int i = 0; i < points.size(); i++) {
+ assertThat(GEOMETRY.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted,
+ points.get(i).x, points.get(i).y)).isEqualTo(
+ isEdgeResizePermitted ? expectedCtrlType.get(i) : CTRL_TYPE_UNDEFINED);
+ }
}
@Test
diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt
index 3375e18c001d..ae63e1939c00 100644
--- a/nfc/api/system-current.txt
+++ b/nfc/api/system-current.txt
@@ -57,6 +57,7 @@ package android.nfc {
@FlaggedApi("android.nfc.nfc_oem_extension") public final class NfcOemExtension {
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void clearPreference();
+ method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull public java.util.List<java.lang.String> getActiveNfceeList();
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void maybeTriggerFirmwareUpdate();
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcOemExtension.Callback);
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void synchronizeScreenState();
diff --git a/nfc/java/android/nfc/INfcAdapter.aidl b/nfc/java/android/nfc/INfcAdapter.aidl
index c5b82ed0f8f2..6c0f93354683 100644
--- a/nfc/java/android/nfc/INfcAdapter.aidl
+++ b/nfc/java/android/nfc/INfcAdapter.aidl
@@ -113,4 +113,5 @@ interface INfcAdapter
void clearPreference();
void setScreenState();
void checkFirmware();
+ List<String> fetchActiveNfceeList();
}
diff --git a/nfc/java/android/nfc/NfcOemExtension.java b/nfc/java/android/nfc/NfcOemExtension.java
index 2ec819cdc1a9..204ba9fbefad 100644
--- a/nfc/java/android/nfc/NfcOemExtension.java
+++ b/nfc/java/android/nfc/NfcOemExtension.java
@@ -26,6 +26,8 @@ import android.os.Binder;
import android.os.RemoteException;
import android.util.Log;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.Executor;
/**
@@ -153,6 +155,19 @@ public final class NfcOemExtension {
NfcAdapter.callService(() -> NfcAdapter.sService.checkFirmware());
}
+ /**
+ * Get the Active NFCEE (NFC Execution Environment) List
+ *
+ * @return List of activated secure elements on success
+ * which can contain "eSE" and "UICC", otherwise empty list.
+ */
+ @NonNull
+ @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
+ public List<String> getActiveNfceeList() {
+ return NfcAdapter.callServiceReturn(() ->
+ NfcAdapter.sService.fetchActiveNfceeList(), new ArrayList<String>());
+ }
+
private final class NfcOemExtensionCallback extends INfcOemExtensionCallback.Stub {
@Override
public void onTagConnected(boolean connected, Tag tag) throws RemoteException {
diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioSharingRepository.kt b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioSharingRepository.kt
index ebba7f152b90..2f8105ae461d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioSharingRepository.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioSharingRepository.kt
@@ -63,7 +63,7 @@ typealias GroupIdToVolumes = Map<Int, Int>
/** Provides audio sharing functionality. */
interface AudioSharingRepository {
/** Whether the device is in audio sharing. */
- val inAudioSharing: Flow<Boolean>
+ val inAudioSharing: StateFlow<Boolean>
/** The primary headset groupId in audio sharing. */
val primaryGroupId: StateFlow<Int>
@@ -101,7 +101,7 @@ class AudioSharingRepositoryImpl(
.flowOn(backgroundCoroutineContext)
.stateIn(coroutineScope, SharingStarted.WhileSubscribed(), false)
- override val inAudioSharing: Flow<Boolean> =
+ override val inAudioSharing: StateFlow<Boolean> =
isAudioSharingProfilesReady.flatMapLatest { ready ->
if (ready) {
btManager.profileManager.leAudioBroadcastProfile.onBroadcastStartedOrStopped
@@ -113,6 +113,7 @@ class AudioSharingRepositoryImpl(
flowOf(false)
}
}
+ .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), false)
private val primaryChange: Flow<Unit> = callbackFlow {
val callback =
@@ -254,7 +255,7 @@ class AudioSharingRepositoryImpl(
}
class AudioSharingRepositoryEmptyImpl : AudioSharingRepository {
- override val inAudioSharing: Flow<Boolean> = flowOf(false)
+ override val inAudioSharing: StateFlow<Boolean> = MutableStateFlow(false)
override val primaryGroupId: StateFlow<Int> =
MutableStateFlow(BluetoothCsipSetCoordinator.GROUP_ID_INVALID)
override val secondaryGroupId: StateFlow<Int> =
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 66b9e5c6bf00..5632e300da35 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -991,6 +991,16 @@ flag {
}
flag {
+ name: "communal_widget_trampoline_fix"
+ namespace: "systemui"
+ description: "fixes activity starts caused by non-activity trampolines from widgets."
+ bug: "350468769"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "app_clips_backlinks"
namespace: "systemui"
description: "Enables Backlinks improvement feature in App Clips"
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
index 7920e74eff01..7dc53eaf53ac 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
@@ -56,6 +56,7 @@ import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInteropFilter
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.layoutId
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.colorResource
@@ -88,6 +89,8 @@ import com.android.systemui.media.controls.ui.controller.MediaCarouselController
import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager
import com.android.systemui.media.controls.ui.view.MediaHost
import com.android.systemui.media.controls.ui.view.MediaHostState
+import com.android.systemui.media.controls.ui.view.MediaHostState.Companion.COLLAPSED
+import com.android.systemui.media.controls.ui.view.MediaHostState.Companion.EXPANDED
import com.android.systemui.media.dagger.MediaModule.QS_PANEL
import com.android.systemui.media.dagger.MediaModule.QUICK_QS_PANEL
import com.android.systemui.notifications.ui.composable.NotificationScrollingStack
@@ -110,6 +113,7 @@ import com.android.systemui.statusbar.notification.stack.ui.viewmodel.Notificati
import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.phone.ui.StatusBarIconController
import com.android.systemui.statusbar.phone.ui.TintedIconManager
+import com.android.systemui.util.Utils
import dagger.Lazy
import javax.inject.Inject
import javax.inject.Named
@@ -260,6 +264,11 @@ private fun SceneScope.SingleShade(
shadeSession: SaveableSession,
) {
val cutoutLocation = LocalDisplayCutout.current.location
+ val isLandscape = LocalWindowSizeClass.current.heightSizeClass == WindowHeightSizeClass.Compact
+ val usingCollapsedLandscapeMedia =
+ Utils.useCollapsedMediaInLandscape(LocalContext.current.resources)
+ val isExpanded = !usingCollapsedLandscapeMedia || !isLandscape
+ mediaHost.expansion = if (isExpanded) EXPANDED else COLLAPSED
val maxNotifScrimTop = remember { mutableStateOf(0f) }
val tileSquishiness by
@@ -275,9 +284,7 @@ private fun SceneScope.SingleShade(
layoutState.isTransitioningBetween(Scenes.Gone, Scenes.Shade) ||
layoutState.isTransitioningBetween(Scenes.Lockscreen, Scenes.Shade)
// Media is visible and we are in landscape on a small height screen
- val mediaInRow =
- isMediaVisible &&
- LocalWindowSizeClass.current.heightSizeClass == WindowHeightSizeClass.Compact
+ val mediaInRow = isMediaVisible && isLandscape
val mediaOffset by
animateSceneDpAsState(value = InQQS, key = MediaLandscapeTopOffset, canOverflow = false)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractorTest.kt
new file mode 100644
index 000000000000..b3ffc7159f7c
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractorTest.kt
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.domain.interactor
+
+import android.app.ActivityManager.RunningTaskInfo
+import android.app.usage.UsageEvents
+import android.content.pm.UserInfo
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.usagestats.data.repository.fakeUsageStatsRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.plugins.activityStarter
+import com.android.systemui.settings.fakeUserTracker
+import com.android.systemui.shared.system.taskStackChangeListeners
+import com.android.systemui.testKosmos
+import com.android.systemui.util.time.fakeSystemClock
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.milliseconds
+import kotlin.time.Duration.Companion.seconds
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.currentTime
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.anyOrNull
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.never
+import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class WidgetTrampolineInteractorTest : SysuiTestCase() {
+
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+
+ private val activityStarter = kosmos.activityStarter
+ private val usageStatsRepository = kosmos.fakeUsageStatsRepository
+ private val taskStackChangeListeners = kosmos.taskStackChangeListeners
+ private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
+ private val userTracker = kosmos.fakeUserTracker
+ private val systemClock = kosmos.fakeSystemClock
+
+ private val underTest = kosmos.widgetTrampolineInteractor
+
+ @Before
+ fun setUp() {
+ userTracker.set(listOf(MAIN_USER), 0)
+ systemClock.setCurrentTimeMillis(testScope.currentTime)
+ }
+
+ @Test
+ fun testNewTaskStartsWhileOnHub_triggersUnlock() =
+ testScope.runTest {
+ transition(from = KeyguardState.LOCKSCREEN, to = KeyguardState.GLANCEABLE_HUB)
+ backgroundScope.launch { underTest.waitForActivityStartAndDismissKeyguard() }
+ runCurrent()
+
+ verify(activityStarter, never()).dismissKeyguardThenExecute(any(), anyOrNull(), any())
+ moveTaskToFront()
+
+ verify(activityStarter).dismissKeyguardThenExecute(any(), anyOrNull(), any())
+ }
+
+ @Test
+ fun testNewTaskStartsAfterExitingHub_doesNotTriggerUnlock() =
+ testScope.runTest {
+ transition(from = KeyguardState.LOCKSCREEN, to = KeyguardState.GLANCEABLE_HUB)
+ backgroundScope.launch { underTest.waitForActivityStartAndDismissKeyguard() }
+ runCurrent()
+
+ transition(from = KeyguardState.GLANCEABLE_HUB, to = KeyguardState.LOCKSCREEN)
+ moveTaskToFront()
+
+ verify(activityStarter, never()).dismissKeyguardThenExecute(any(), anyOrNull(), any())
+ }
+
+ @Test
+ fun testNewTaskStartsAfterTimeout_doesNotTriggerUnlock() =
+ testScope.runTest {
+ transition(from = KeyguardState.LOCKSCREEN, to = KeyguardState.GLANCEABLE_HUB)
+ backgroundScope.launch { underTest.waitForActivityStartAndDismissKeyguard() }
+ runCurrent()
+
+ advanceTime(2.seconds)
+ moveTaskToFront()
+
+ verify(activityStarter, never()).dismissKeyguardThenExecute(any(), anyOrNull(), any())
+ }
+
+ @Test
+ fun testActivityResumedWhileOnHub_triggersUnlock() =
+ testScope.runTest {
+ transition(from = KeyguardState.LOCKSCREEN, to = KeyguardState.GLANCEABLE_HUB)
+ backgroundScope.launch { underTest.waitForActivityStartAndDismissKeyguard() }
+ runCurrent()
+
+ addActivityEvent(UsageEvents.Event.ACTIVITY_RESUMED)
+ advanceTime(1.seconds)
+
+ verify(activityStarter).dismissKeyguardThenExecute(any(), anyOrNull(), any())
+ }
+
+ @Test
+ fun testActivityResumedAfterExitingHub_doesNotTriggerUnlock() =
+ testScope.runTest {
+ transition(from = KeyguardState.LOCKSCREEN, to = KeyguardState.GLANCEABLE_HUB)
+ backgroundScope.launch { underTest.waitForActivityStartAndDismissKeyguard() }
+ runCurrent()
+
+ transition(from = KeyguardState.GLANCEABLE_HUB, to = KeyguardState.LOCKSCREEN)
+ addActivityEvent(UsageEvents.Event.ACTIVITY_RESUMED)
+ advanceTime(1.seconds)
+
+ verify(activityStarter, never()).dismissKeyguardThenExecute(any(), anyOrNull(), any())
+ }
+
+ @Test
+ fun testActivityDestroyed_doesNotTriggerUnlock() =
+ testScope.runTest {
+ transition(from = KeyguardState.LOCKSCREEN, to = KeyguardState.GLANCEABLE_HUB)
+ backgroundScope.launch { underTest.waitForActivityStartAndDismissKeyguard() }
+ runCurrent()
+
+ addActivityEvent(UsageEvents.Event.ACTIVITY_DESTROYED)
+ advanceTime(1.seconds)
+
+ verify(activityStarter, never()).dismissKeyguardThenExecute(any(), anyOrNull(), any())
+ }
+
+ @Test
+ fun testMultipleActivityEvents_triggersUnlockOnlyOnce() =
+ testScope.runTest {
+ transition(from = KeyguardState.LOCKSCREEN, to = KeyguardState.GLANCEABLE_HUB)
+ backgroundScope.launch { underTest.waitForActivityStartAndDismissKeyguard() }
+ runCurrent()
+
+ addActivityEvent(UsageEvents.Event.ACTIVITY_RESUMED)
+ advanceTime(10.milliseconds)
+ addActivityEvent(UsageEvents.Event.ACTIVITY_RESUMED)
+ advanceTime(1.seconds)
+
+ verify(activityStarter, times(1)).dismissKeyguardThenExecute(any(), anyOrNull(), any())
+ }
+
+ private fun TestScope.advanceTime(duration: Duration) {
+ systemClock.advanceTime(duration.inWholeMilliseconds)
+ advanceTimeBy(duration)
+ }
+
+ private fun TestScope.addActivityEvent(type: Int) {
+ usageStatsRepository.addEvent(
+ instanceId = 1,
+ user = MAIN_USER.userHandle,
+ packageName = "pkg.test",
+ timestamp = systemClock.currentTimeMillis(),
+ type = type,
+ )
+ runCurrent()
+ }
+
+ private fun TestScope.moveTaskToFront() {
+ taskStackChangeListeners.listenerImpl.onTaskMovedToFront(mock<RunningTaskInfo>())
+ runCurrent()
+ }
+
+ private suspend fun TestScope.transition(from: KeyguardState, to: KeyguardState) {
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ TransitionStep(
+ from = from,
+ to = to,
+ value = 0.1f,
+ transitionState = TransitionState.STARTED,
+ ownerName = "test",
+ ),
+ TransitionStep(
+ from = from,
+ to = to,
+ value = 1f,
+ transitionState = TransitionState.FINISHED,
+ ownerName = "test",
+ ),
+ ),
+ testScope
+ )
+ runCurrent()
+ }
+
+ private companion object {
+ val MAIN_USER: UserInfo = UserInfo(0, "primary", UserInfo.FLAG_MAIN)
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt
index 023de52b2460..400f736ba882 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt
@@ -27,7 +27,9 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.domain.interactor.communalSceneInteractor
+import com.android.systemui.communal.domain.interactor.widgetTrampolineInteractor
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.kosmos.testScope
import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.plugins.ActivityStarter
@@ -67,9 +69,11 @@ class WidgetInteractionHandlerTest : SysuiTestCase() {
with(kosmos) {
underTest =
WidgetInteractionHandler(
+ applicationScope = applicationCoroutineScope,
activityStarter = activityStarter,
communalSceneInteractor = communalSceneInteractor,
logBuffer = logcatLogBuffer(),
+ widgetTrampolineInteractor = widgetTrampolineInteractor,
)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt
index 409c55144c6a..5ec566bab6d5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt
@@ -28,6 +28,7 @@ import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
+import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
@@ -49,6 +50,24 @@ class PrimaryBouncerToLockscreenTransitionViewModelTest : SysuiTestCase() {
val underTest = kosmos.primaryBouncerToLockscreenTransitionViewModel
@Test
+ fun lockscreenAlphaStartsFromViewStateAccessorAlpha() =
+ testScope.runTest {
+ val viewState = ViewStateAccessor(alpha = { 0.5f })
+ val alpha by collectLastValue(underTest.lockscreenAlpha(viewState))
+
+ keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED))
+
+ keyguardTransitionRepository.sendTransitionStep(step(0f))
+ assertThat(alpha).isEqualTo(0.5f)
+
+ keyguardTransitionRepository.sendTransitionStep(step(0.5f))
+ assertThat(alpha).isIn(Range.open(0.5f, 1f))
+
+ keyguardTransitionRepository.sendTransitionStep(step(1f))
+ assertThat(alpha).isEqualTo(1f)
+ }
+
+ @Test
fun deviceEntryParentViewAlpha() =
testScope.runTest {
val deviceEntryParentViewAlpha by collectLastValue(underTest.deviceEntryParentViewAlpha)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index cd84abc50802..aee3ce052d78 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -133,6 +133,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
sceneInteractor = sceneInteractor,
falsingInteractor = kosmos.falsingInteractor,
powerInteractor = kosmos.powerInteractor,
+ motionEventHandlerReceiver = {},
)
.apply { setTransitionState(transitionState) }
}
@@ -199,6 +200,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
shadeSceneContentViewModel.activateIn(testScope)
shadeSceneActionsViewModel.activateIn(testScope)
bouncerSceneContentViewModel.activateIn(testScope)
+ sceneContainerViewModel.activateIn(testScope)
assertWithMessage("Initial scene key mismatch!")
.that(sceneContainerViewModel.currentScene.value)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
index ea95aab4a1c4..f85823ad7c33 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
package com.android.systemui.scene.ui.viewmodel
import android.view.MotionEvent
@@ -25,6 +27,7 @@ import com.android.systemui.classifier.fakeFalsingManager
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.kosmos.testScope
+import com.android.systemui.lifecycle.activateIn
import com.android.systemui.power.data.repository.fakePowerRepository
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
@@ -37,6 +40,8 @@ import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -57,6 +62,9 @@ class SceneContainerViewModelTest : SysuiTestCase() {
private lateinit var underTest: SceneContainerViewModel
+ private lateinit var activationJob: Job
+ private var motionEventHandler: SceneContainerViewModel.MotionEventHandler? = null
+
@Before
fun setUp() {
underTest =
@@ -64,10 +72,28 @@ class SceneContainerViewModelTest : SysuiTestCase() {
sceneInteractor = sceneInteractor,
falsingInteractor = kosmos.falsingInteractor,
powerInteractor = kosmos.powerInteractor,
+ motionEventHandlerReceiver = { motionEventHandler ->
+ this@SceneContainerViewModelTest.motionEventHandler = motionEventHandler
+ },
)
+ activationJob = Job()
+ underTest.activateIn(testScope, activationJob)
}
@Test
+ fun activate_setsMotionEventHandler() =
+ testScope.runTest { assertThat(motionEventHandler).isNotNull() }
+
+ @Test
+ fun deactivate_clearsMotionEventHandler() =
+ testScope.runTest {
+ activationJob.cancel()
+ runCurrent()
+
+ assertThat(motionEventHandler).isNull()
+ }
+
+ @Test
fun isVisible() =
testScope.runTest {
val isVisible by collectLastValue(underTest.isVisible)
diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml
index 57fd9ea8319f..d069c0181218 100644
--- a/packages/SystemUI/res-keyguard/values-ar/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml
@@ -71,7 +71,7 @@
<string name="kg_prompt_after_dpm_lock" msgid="6002804765868345917">"لمزيد من الأمان، تم قفل الجهاز وفقًا لسياسة العمل."</string>
<string name="kg_prompt_after_user_lockdown_pin" msgid="5374732179740050373">"يجب إدخال رقم التعريف الشخصي بعد إلغاء الفتح الذكي."</string>
<string name="kg_prompt_after_user_lockdown_password" msgid="9097968458291129795">"يجب إدخال كلمة المرور بعد إلغاء الفتح الذكي."</string>
- <string name="kg_prompt_after_user_lockdown_pattern" msgid="215072203613597906">"يجب رسم النقش بعد إلغاء التأمين."</string>
+ <string name="kg_prompt_after_user_lockdown_pattern" msgid="215072203613597906">"يجب رسم النقش بعد إلغاء الفتح الذكي."</string>
<string name="kg_prompt_unattended_update" msgid="4366635751738712452">"سيتم تثبيت التحديث عندما لا يكون الجهاز قيد الاستخدام."</string>
<string name="kg_prompt_pin_auth_timeout" msgid="5868644725126275245">"‏يجب تعزيز الأمان. لم يُستخدَم رقم PIN لبعض الوقت."</string>
<string name="kg_prompt_password_auth_timeout" msgid="5809110458491920871">"يجب تعزيز الأمان. لم تستخدَم كلمة المرور لبعض الوقت."</string>
diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml
index fd90d08caf9e..cf2057cafb8b 100644
--- a/packages/SystemUI/res-keyguard/values-ru/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml
@@ -57,7 +57,7 @@
<string name="kg_wrong_pin" msgid="4160978845968732624">"Неверный PIN-код"</string>
<string name="kg_wrong_pin_try_again" msgid="3129729383303430190">"Неверный PIN-код."</string>
<string name="kg_wrong_input_try_fp_suggestion" msgid="3143861542242024833">"Повторите попытку или используйте отпечаток пальца."</string>
- <string name="kg_fp_not_recognized" msgid="5183108260932029241">"Отпечаток не распознан."</string>
+ <string name="kg_fp_not_recognized" msgid="5183108260932029241">"Отпечаток не распознан"</string>
<string name="bouncer_face_not_recognized" msgid="1666128054475597485">"Лицо не распознано."</string>
<string name="kg_bio_try_again_or_pin" msgid="4752168242723808390">"Повторите попытку или введите PIN-код."</string>
<string name="kg_bio_try_again_or_password" msgid="1473132729225398039">"Повторите попытку или введите пароль."</string>
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 63ad41a808dc..13cd2c538f3f 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -53,6 +53,7 @@ import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.res.R;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.shared.NotificationContentAlphaOptimization;
import com.android.wm.shell.animation.FlingAnimationUtils;
import com.android.wm.shell.shared.animation.PhysicsAnimator;
import com.android.wm.shell.shared.animation.PhysicsAnimator.SpringConfig;
@@ -63,13 +64,6 @@ import java.util.function.Consumer;
public class SwipeHelper implements Gefingerpoken, Dumpable {
static final String TAG = "com.android.systemui.SwipeHelper";
private static final boolean DEBUG_INVALIDATE = false;
- private static final boolean CONSTRAIN_SWIPE = true;
- private static final boolean FADE_OUT_DURING_SWIPE = true;
- private static final boolean DISMISS_IF_SWIPED_FAR_ENOUGH = true;
-
- public static final int X = 0;
- public static final int Y = 1;
-
private static final float SWIPE_ESCAPE_VELOCITY = 500f; // dp/sec
private static final int DEFAULT_ESCAPE_ANIMATION_DURATION = 200; // ms
private static final int MAX_ESCAPE_ANIMATION_DURATION = 400; // ms
@@ -171,10 +165,6 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
mPagingTouchSlop = pagingTouchSlop;
}
- public void setDisableHardwareLayers(boolean disableHwLayers) {
- mDisableHwLayers = disableHwLayers;
- }
-
private float getPos(MotionEvent ev) {
return ev.getX();
}
@@ -253,13 +243,14 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
float translation) {
float swipeProgress = getSwipeProgressForOffset(animView, translation);
if (!mCallback.updateSwipeProgress(animView, dismissable, swipeProgress)) {
- if (FADE_OUT_DURING_SWIPE && dismissable) {
- if (!mDisableHwLayers) {
- if (swipeProgress != 0f && swipeProgress != 1f) {
- animView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- } else {
- animView.setLayerType(View.LAYER_TYPE_NONE, null);
- }
+ if (dismissable
+ || (NotificationContentAlphaOptimization.isEnabled() && translation == 0)) {
+ // We need to reset the content alpha even when the view is not dismissible (eg.
+ // when Guts is visible)
+ if (swipeProgress != 0f && swipeProgress != 1f) {
+ animView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ } else {
+ animView.setLayerType(View.LAYER_TYPE_NONE, null);
}
updateSwipeProgressAlpha(animView, getSwipeAlpha(swipeProgress));
}
@@ -436,9 +427,7 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
duration = fixedDuration;
}
- if (!mDisableHwLayers) {
- animView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- }
+ animView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
@@ -493,9 +482,7 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
if (endAction != null) {
endAction.accept(mCancelled);
}
- if (!mDisableHwLayers) {
- animView.setLayerType(View.LAYER_TYPE_NONE, null);
- }
+ animView.setLayerType(View.LAYER_TYPE_NONE, null);
onDismissChildWithAnimationFinished();
}
});
@@ -612,7 +599,11 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
* view is being animated to dismiss or snap.
*/
public void onTranslationUpdate(View animView, float value, boolean canBeDismissed) {
- updateSwipeProgressFromOffset(animView, canBeDismissed, value);
+ updateSwipeProgressFromOffset(
+ animView,
+ /* dismissable= */ canBeDismissed,
+ /* translation= */ value
+ );
}
private void snapChildInstantly(final View view) {
@@ -689,7 +680,7 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
} else {
// don't let items that can't be dismissed be dragged more than
// maxScrollDistance
- if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissedInDirection(
+ if (!mCallback.canChildBeDismissedInDirection(
mTouchedView,
delta > 0)) {
float size = getSize(mTouchedView);
@@ -761,8 +752,7 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
protected boolean swipedFarEnough() {
float translation = getTranslation(mTouchedView);
- return DISMISS_IF_SWIPED_FAR_ENOUGH
- && Math.abs(translation) > SWIPED_FAR_ENOUGH_SIZE_FRACTION * getSize(
+ return Math.abs(translation) > SWIPED_FAR_ENOUGH_SIZE_FRACTION * getSize(
mTouchedView);
}
@@ -822,9 +812,18 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
}
public void forceResetSwipeState(@NonNull View view) {
- if (view.getTranslationX() == 0) return;
+ if (view.getTranslationX() == 0
+ && (!NotificationContentAlphaOptimization.isEnabled() || view.getAlpha() == 1f)
+ ) {
+ // Don't do anything when translation is 0 and alpha is 1
+ return;
+ }
setTranslation(view, 0);
- updateSwipeProgressFromOffset(view, /* dismissable= */ true, 0);
+ updateSwipeProgressFromOffset(
+ view,
+ /* dismissable= */ true,
+ /* translation= */ 0
+ );
}
/** This method resets the swipe state, and if `resetAll` is true, also resets the snap state */
@@ -893,7 +892,6 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
pw.append("mTranslation=").println(mTranslation);
pw.append("mCanCurrViewBeDimissed=").println(mCanCurrViewBeDimissed);
pw.append("mMenuRowIntercepting=").println(mMenuRowIntercepting);
- pw.append("mDisableHwLayers=").println(mDisableHwLayers);
pw.append("mDismissPendingMap: ").println(mDismissPendingMap.size());
if (!mDismissPendingMap.isEmpty()) {
mDismissPendingMap.forEach((view, animator) -> {
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractor.kt
new file mode 100644
index 000000000000..7453368d0ee7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractor.kt
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.domain.interactor
+
+import android.app.ActivityManager
+import com.android.systemui.common.usagestats.domain.UsageStatsInteractor
+import com.android.systemui.common.usagestats.shared.model.ActivityEventModel
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.Logger
+import com.android.systemui.log.dagger.CommunalLog
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.shared.system.TaskStackChangeListener
+import com.android.systemui.shared.system.TaskStackChangeListeners
+import com.android.systemui.util.kotlin.race
+import com.android.systemui.util.time.SystemClock
+import javax.inject.Inject
+import kotlin.time.Duration.Companion.milliseconds
+import kotlin.time.Duration.Companion.seconds
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.TimeoutCancellationException
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.takeWhile
+import kotlinx.coroutines.suspendCancellableCoroutine
+import kotlinx.coroutines.withTimeout
+
+/**
+ * Detects activity starts that occur while the communal hub is showing, within a short delay of a
+ * widget interaction occurring. Used for detecting non-activity trampolines which otherwise would
+ * not prompt the user for authentication.
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+@SysUISingleton
+class WidgetTrampolineInteractor
+@Inject
+constructor(
+ private val activityStarter: ActivityStarter,
+ private val systemClock: SystemClock,
+ private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
+ private val taskStackChangeListeners: TaskStackChangeListeners,
+ private val usageStatsInteractor: UsageStatsInteractor,
+ @CommunalLog logBuffer: LogBuffer,
+) {
+ private companion object {
+ const val TAG = "WidgetTrampolineInteractor"
+ }
+
+ private val logger = Logger(logBuffer, TAG)
+
+ /** Waits for a new task to be moved to the foreground. */
+ private suspend fun waitForNewForegroundTask() = suspendCancellableCoroutine { cont ->
+ val listener =
+ object : TaskStackChangeListener {
+ override fun onTaskMovedToFront(taskInfo: ActivityManager.RunningTaskInfo) {
+ if (!cont.isCompleted) {
+ cont.resume(Unit, null)
+ }
+ }
+ }
+ taskStackChangeListeners.registerTaskStackListener(listener)
+ cont.invokeOnCancellation { taskStackChangeListeners.unregisterTaskStackListener(listener) }
+ }
+
+ /**
+ * Waits for an activity to enter a [ActivityEventModel.Lifecycle.RESUMED] state by periodically
+ * polling the system to see if any activities have started.
+ */
+ private suspend fun waitForActivityStartByPolling(startTime: Long): Boolean {
+ while (true) {
+ val events = usageStatsInteractor.queryActivityEvents(startTime = startTime)
+ if (events.any { event -> event.lifecycle == ActivityEventModel.Lifecycle.RESUMED }) {
+ return true
+ } else {
+ // Poll again in the future to check if an activity started.
+ delay(200.milliseconds)
+ }
+ }
+ }
+
+ /** Waits for a transition away from the hub to occur. */
+ private suspend fun waitForTransitionAwayFromHub() {
+ keyguardTransitionInteractor
+ .isFinishedIn(Scenes.Communal, KeyguardState.GLANCEABLE_HUB)
+ .takeWhile { it }
+ .collect {}
+ }
+
+ private suspend fun waitForActivityStartWhileOnHub(): Boolean {
+ val startTime = systemClock.currentTimeMillis()
+ return try {
+ return withTimeout(1.seconds) {
+ race(
+ {
+ waitForNewForegroundTask()
+ true
+ },
+ { waitForActivityStartByPolling(startTime) },
+ {
+ waitForTransitionAwayFromHub()
+ false
+ },
+ )
+ }
+ } catch (e: TimeoutCancellationException) {
+ false
+ }
+ }
+
+ /**
+ * Checks if an activity starts while on the glanceable hub and dismisses the keyguard if it
+ * does. This can detect activities started due to broadcast trampolines from widgets.
+ */
+ suspend fun waitForActivityStartAndDismissKeyguard() {
+ if (waitForActivityStartWhileOnHub()) {
+ logger.d("Detected trampoline, requesting unlock")
+ activityStarter.dismissKeyguardThenExecute(
+ /* action= */ { false },
+ /* cancel= */ null,
+ /* afterKeyguardGone= */ false
+ )
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/smartspace/SmartspaceInteractionHandler.kt b/packages/SystemUI/src/com/android/systemui/communal/smartspace/SmartspaceInteractionHandler.kt
index c4edcac1a2a1..99e3232a70c2 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/smartspace/SmartspaceInteractionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/smartspace/SmartspaceInteractionHandler.kt
@@ -48,7 +48,17 @@ constructor(
InteractionHandlerDelegate(
communalSceneInteractor,
findViewToAnimate = { view -> view is SmartspaceAppWidgetHostView },
- intentStarter = this::startIntent,
+ intentStarter =
+ object : InteractionHandlerDelegate.IntentStarter {
+ override fun startActivity(
+ intent: PendingIntent,
+ fillInIntent: Intent,
+ activityOptions: ActivityOptions,
+ controller: ActivityTransitionAnimator.Controller?
+ ): Boolean {
+ return startIntent(intent, fillInIntent, activityOptions, controller)
+ }
+ },
logger = Logger(logBuffer, TAG),
)
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalAppWidgetHostViewBinder.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalAppWidgetHostViewBinder.kt
index 7a0567190bd0..5f421fd19550 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalAppWidgetHostViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalAppWidgetHostViewBinder.kt
@@ -21,10 +21,13 @@ import android.util.SizeF
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
+import androidx.core.view.doOnLayout
import com.android.app.tracing.coroutines.launch
import com.android.systemui.communal.domain.model.CommunalContentModel
import com.android.systemui.communal.util.WidgetViewFactory
import com.android.systemui.util.kotlin.DisposableHandles
+import kotlin.coroutines.resume
+import kotlin.coroutines.suspendCoroutine
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DisposableHandle
@@ -44,13 +47,8 @@ object CommunalAppWidgetHostViewBinder {
val loadingJob =
applicationScope.launch("$TAG#createWidgetView") {
val widget = factory.createWidget(context, model, size)
- // TODO(b/358662507): Remove this workaround
- (container.parent as? ViewGroup)?.let { parent ->
- val index = parent.indexOfChild(container)
- parent.removeView(container)
- parent.addView(container, index)
- }
- container.setView(widget)
+ waitForLayout(container)
+ container.post { container.setView(widget) }
}
disposables += DisposableHandle { loadingJob.cancel() }
@@ -58,6 +56,10 @@ object CommunalAppWidgetHostViewBinder {
return disposables
}
+
+ private suspend fun waitForLayout(container: FrameLayout) = suspendCoroutine { cont ->
+ container.doOnLayout { cont.resume(Unit) }
+ }
}
private fun ViewGroup.setView(view: View) {
diff --git a/packages/SystemUI/src/com/android/systemui/communal/util/InteractionHandlerDelegate.kt b/packages/SystemUI/src/com/android/systemui/communal/util/InteractionHandlerDelegate.kt
index d2029d50bf63..5e21afacf9f3 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/util/InteractionHandlerDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/util/InteractionHandlerDelegate.kt
@@ -19,6 +19,7 @@ package com.android.systemui.communal.util
import android.app.ActivityOptions
import android.app.PendingIntent
import android.content.Intent
+import android.util.Pair as UtilPair
import android.view.View
import android.widget.RemoteViews
import androidx.core.util.component1
@@ -36,14 +37,28 @@ class InteractionHandlerDelegate(
private val logger: Logger,
) : RemoteViews.InteractionHandler {
- /** Responsible for starting the pending intent for launching activities. */
- fun interface IntentStarter {
- fun startPendingIntent(
+ interface IntentStarter {
+ /** Responsible for starting the pending intent for launching activities. */
+ fun startActivity(
intent: PendingIntent,
fillInIntent: Intent,
activityOptions: ActivityOptions,
controller: ActivityTransitionAnimator.Controller?,
): Boolean
+
+ /** Responsible for starting the pending intent for non-activity launches. */
+ fun startPendingIntent(
+ view: View,
+ pendingIntent: PendingIntent,
+ fillInIntent: Intent,
+ activityOptions: ActivityOptions,
+ ): Boolean {
+ return RemoteViews.startPendingIntent(
+ view,
+ pendingIntent,
+ UtilPair(fillInIntent, activityOptions),
+ )
+ }
}
override fun onInteraction(
@@ -55,7 +70,7 @@ class InteractionHandlerDelegate(
str1 = pendingIntent.toLoggingString()
str2 = pendingIntent.creatorPackage
}
- val launchOptions = response.getLaunchOptions(view)
+ val (fillInIntent, activityOptions) = response.getLaunchOptions(view)
return when {
pendingIntent.isActivity -> {
// Forward the fill-in intent and activity options retrieved from the response
@@ -67,15 +82,15 @@ class InteractionHandlerDelegate(
communalSceneInteractor.setIsLaunchingWidget(true)
CommunalTransitionAnimatorController(it, communalSceneInteractor)
}
- val (fillInIntent, activityOptions) = launchOptions
- intentStarter.startPendingIntent(
+ intentStarter.startActivity(
pendingIntent,
fillInIntent,
activityOptions,
animationController
)
}
- else -> RemoteViews.startPendingIntent(view, pendingIntent, launchOptions)
+ else ->
+ intentStarter.startPendingIntent(view, pendingIntent, fillInIntent, activityOptions)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt
index 0eeb506ccc09..121b4a304c3a 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt
@@ -21,22 +21,30 @@ import android.app.PendingIntent
import android.content.Intent
import android.view.View
import android.widget.RemoteViews
+import com.android.app.tracing.coroutines.launch
+import com.android.systemui.Flags.communalWidgetTrampolineFix
import com.android.systemui.animation.ActivityTransitionAnimator
import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor
+import com.android.systemui.communal.domain.interactor.WidgetTrampolineInteractor
import com.android.systemui.communal.util.InteractionHandlerDelegate
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.Logger
import com.android.systemui.log.dagger.CommunalLog
import com.android.systemui.plugins.ActivityStarter
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
@SysUISingleton
class WidgetInteractionHandler
@Inject
constructor(
+ @Application applicationScope: CoroutineScope,
private val activityStarter: ActivityStarter,
communalSceneInteractor: CommunalSceneInteractor,
+ private val widgetTrampolineInteractor: WidgetTrampolineInteractor,
@CommunalLog val logBuffer: LogBuffer,
) : RemoteViews.InteractionHandler {
@@ -48,7 +56,52 @@ constructor(
InteractionHandlerDelegate(
communalSceneInteractor,
findViewToAnimate = { view -> view is CommunalAppWidgetHostView },
- intentStarter = this::startIntent,
+ intentStarter =
+ object : InteractionHandlerDelegate.IntentStarter {
+ private var job: Job? = null
+
+ override fun startActivity(
+ intent: PendingIntent,
+ fillInIntent: Intent,
+ activityOptions: ActivityOptions,
+ controller: ActivityTransitionAnimator.Controller?
+ ): Boolean {
+ cancelTrampolineMonitoring()
+ return startActivityIntent(
+ intent,
+ fillInIntent,
+ activityOptions,
+ controller
+ )
+ }
+
+ override fun startPendingIntent(
+ view: View,
+ pendingIntent: PendingIntent,
+ fillInIntent: Intent,
+ activityOptions: ActivityOptions
+ ): Boolean {
+ cancelTrampolineMonitoring()
+ if (communalWidgetTrampolineFix()) {
+ job =
+ applicationScope.launch("$TAG#monitorForActivityStart") {
+ widgetTrampolineInteractor
+ .waitForActivityStartAndDismissKeyguard()
+ }
+ }
+ return super.startPendingIntent(
+ view,
+ pendingIntent,
+ fillInIntent,
+ activityOptions
+ )
+ }
+
+ private fun cancelTrampolineMonitoring() {
+ job?.cancel()
+ job = null
+ }
+ },
logger = Logger(logBuffer, TAG),
)
@@ -58,7 +111,7 @@ constructor(
response: RemoteViews.RemoteResponse
): Boolean = delegate.onInteraction(view, pendingIntent, response)
- private fun startIntent(
+ private fun startActivityIntent(
pendingIntent: PendingIntent,
fillInIntent: Intent,
extraOptions: ActivityOptions,
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt
index b9b38954784e..36b9ac70d290 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt
@@ -17,6 +17,7 @@
package com.android.systemui.inputdevice.tutorial.data.repository
import android.content.Context
+import androidx.annotation.VisibleForTesting
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
@@ -33,15 +34,19 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
@SysUISingleton
-class TutorialSchedulerRepository
-@Inject
-constructor(
- @Application private val applicationContext: Context,
- @Background private val backgroundScope: CoroutineScope
+class TutorialSchedulerRepository(
+ private val applicationContext: Context,
+ backgroundScope: CoroutineScope,
+ dataStoreName: String
) {
+ @Inject
+ constructor(
+ @Application applicationContext: Context,
+ @Background backgroundScope: CoroutineScope
+ ) : this(applicationContext, backgroundScope, dataStoreName = "TutorialScheduler")
private val Context.dataStore: DataStore<Preferences> by
- preferencesDataStore(name = DATASTORE_NAME, scope = backgroundScope)
+ preferencesDataStore(name = dataStoreName, scope = backgroundScope)
suspend fun isLaunched(deviceType: DeviceType): Boolean = loadData()[deviceType]!!.isLaunched
@@ -81,8 +86,12 @@ constructor(
private fun getConnectKey(device: DeviceType) =
longPreferencesKey(device.name + CONNECT_TIME_SUFFIX)
+ @VisibleForTesting
+ suspend fun clearDataStore() {
+ applicationContext.dataStore.edit { it.clear() }
+ }
+
companion object {
- const val DATASTORE_NAME = "TutorialScheduler"
const val IS_LAUNCHED_SUFFIX = "_IS_LAUNCHED"
const val CONNECT_TIME_SUFFIX = "_CONNECTED_TIME"
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index 81b0064f0f03..49303e089036 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -91,11 +91,11 @@ interface KeyguardRepository {
* the z-order (which is not really above the system UI window, but rather - the lock-screen
* becomes invisible to reveal the "occluding activity").
*/
- val isKeyguardShowing: Flow<Boolean>
+ val isKeyguardShowing: StateFlow<Boolean>
/** Is an activity showing over the keyguard? */
@Deprecated("Use KeyguardTransitionInteractor + KeyguardState.OCCLUDED")
- val isKeyguardOccluded: Flow<Boolean>
+ val isKeyguardOccluded: StateFlow<Boolean>
/**
* Whether the device is locked or unlocked right now. This is true when keyguard has been
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
index 2a8bb471c217..13d54bac8339 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
@@ -36,8 +36,6 @@ import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
@SysUISingleton
@@ -73,15 +71,11 @@ constructor(
listenForTransitionToCamera(scope, keyguardInteractor)
}
- private val canDismissLockscreen: Flow<Boolean> =
- combine(
- keyguardInteractor.isKeyguardShowing,
- keyguardInteractor.isKeyguardDismissible,
- keyguardInteractor.biometricUnlockState,
- ) { isKeyguardShowing, isKeyguardDismissible, biometricUnlockState ->
- (isWakeAndUnlock(biometricUnlockState.mode) ||
- (!isKeyguardShowing && isKeyguardDismissible))
- }
+ private fun canDismissLockscreen(): Boolean {
+ return isWakeAndUnlock(keyguardInteractor.biometricUnlockState.value.mode) ||
+ (!keyguardInteractor.isKeyguardShowing.value &&
+ keyguardInteractor.isKeyguardDismissible.value)
+ }
/**
* Listen for the signal that we're waking up and figure what state we need to transition to.
@@ -96,22 +90,18 @@ constructor(
.debounce(50L)
.sample(
startedKeyguardTransitionStep,
- keyguardInteractor.biometricUnlockState,
- keyguardInteractor.primaryBouncerShowing,
- keyguardInteractor.isKeyguardOccluded,
- canDismissLockscreen,
wakeToGoneInteractor.canWakeDirectlyToGone,
)
.collect {
(
_,
startedStep,
- biometricUnlockState,
- primaryBouncerShowing,
- isKeyguardOccludedLegacy,
- canDismissLockscreen,
canWakeDirectlyToGone,
) ->
+ val isKeyguardOccludedLegacy = keyguardInteractor.isKeyguardOccluded.value
+ val biometricUnlockMode = keyguardInteractor.biometricUnlockState.value.mode
+ val primaryBouncerShowing = keyguardInteractor.primaryBouncerShowing.value
+
if (!maybeHandleInsecurePowerGesture()) {
val shouldTransitionToLockscreen =
if (KeyguardWmStateRefactor.isEnabled) {
@@ -121,12 +111,10 @@ constructor(
// completes.
!maybeStartTransitionToOccludedOrInsecureCamera { state, reason ->
startTransitionTo(state, ownerReason = reason)
- } &&
- !isWakeAndUnlock(biometricUnlockState.mode) &&
- !primaryBouncerShowing
+ } && !isWakeAndUnlock(biometricUnlockMode) && !primaryBouncerShowing
} else {
!isKeyguardOccludedLegacy &&
- !isWakeAndUnlock(biometricUnlockState.mode) &&
+ !isWakeAndUnlock(biometricUnlockMode) &&
!primaryBouncerShowing
}
@@ -136,7 +124,7 @@ constructor(
!KeyguardWmStateRefactor.isEnabled && isKeyguardOccludedLegacy
val shouldTransitionToGone =
- (!KeyguardWmStateRefactor.isEnabled && canDismissLockscreen) ||
+ (!KeyguardWmStateRefactor.isEnabled && canDismissLockscreen()) ||
(KeyguardWmStateRefactor.isEnabled && canWakeDirectlyToGone)
if (shouldTransitionToGone) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
index 61446c19605c..0c12f8cee943 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
@@ -42,8 +42,6 @@ import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.launch
@@ -83,13 +81,10 @@ constructor(
listenForTransitionToCamera(scope, keyguardInteractor)
}
- private val canTransitionToGoneOnWake: Flow<Boolean> =
- combine(
- keyguardInteractor.isKeyguardShowing,
- keyguardInteractor.isKeyguardDismissible,
- ) { isKeyguardShowing, isKeyguardDismissible ->
- isKeyguardDismissible && !isKeyguardShowing
- }
+ private fun canDismissLockscreen(): Boolean {
+ return !keyguardInteractor.isKeyguardShowing.value &&
+ keyguardInteractor.isKeyguardDismissible.value
+ }
private fun listenForDozingToGoneViaBiometrics() {
if (KeyguardWmStateRefactor.isEnabled) {
@@ -135,27 +130,20 @@ constructor(
.debounce(50L)
.filterRelevantKeyguardStateAnd { isAwake -> isAwake }
.sample(
- keyguardInteractor.isKeyguardOccluded,
communalInteractor.isCommunalAvailable,
communalSceneInteractor.isIdleOnCommunal,
- canTransitionToGoneOnWake,
- keyguardInteractor.primaryBouncerShowing,
)
- .collect {
- (
- _,
- occluded,
- isCommunalAvailable,
- isIdleOnCommunal,
- canTransitionToGoneOnWake,
- primaryBouncerShowing) ->
+ .collect { (_, isCommunalAvailable, isIdleOnCommunal) ->
+ val isKeyguardOccludedLegacy = keyguardInteractor.isKeyguardOccluded.value
+ val primaryBouncerShowing = keyguardInteractor.primaryBouncerShowing.value
+
if (!deviceEntryInteractor.isLockscreenEnabled()) {
if (SceneContainerFlag.isEnabled) {
// TODO(b/336576536): Check if adaptation for scene framework is needed
} else {
startTransitionTo(KeyguardState.GONE)
}
- } else if (canTransitionToGoneOnWake) {
+ } else if (canDismissLockscreen()) {
if (SceneContainerFlag.isEnabled) {
// TODO(b/336576536): Check if adaptation for scene framework is needed
} else {
@@ -167,7 +155,7 @@ constructor(
} else {
startTransitionTo(KeyguardState.PRIMARY_BOUNCER)
}
- } else if (occluded) {
+ } else if (isKeyguardOccludedLegacy) {
startTransitionTo(KeyguardState.OCCLUDED)
} else if (isIdleOnCommunal && !communalSceneKtfRefactor()) {
if (SceneContainerFlag.isEnabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
index 17c1e823a1ca..7bf9c2f1dc7a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
@@ -32,7 +32,6 @@ import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.scene.shared.flag.SceneContainerFlag
-import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
@@ -208,15 +207,15 @@ constructor(
scope.launch {
keyguardInteractor.isAbleToDream
- .sampleCombine(
- keyguardInteractor.isKeyguardShowing,
- keyguardInteractor.isKeyguardDismissible,
- )
- .filterRelevantKeyguardStateAnd {
- (isDreaming, isKeyguardShowing, isKeyguardDismissible) ->
- !isDreaming && isKeyguardDismissible && !isKeyguardShowing
+ .filterRelevantKeyguardStateAnd { isDreaming -> !isDreaming }
+ .collect {
+ if (
+ keyguardInteractor.isKeyguardDismissible.value &&
+ !keyguardInteractor.isKeyguardShowing.value
+ ) {
+ startTransitionTo(KeyguardState.GONE)
+ }
}
- .collect { startTransitionTo(KeyguardState.GONE) }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index 0df989e9353f..4cab2bb5dba8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -216,14 +216,14 @@ constructor(
/** Whether the keyguard is showing or not. */
@Deprecated("Use KeyguardTransitionInteractor + KeyguardState")
- val isKeyguardShowing: Flow<Boolean> = repository.isKeyguardShowing
+ val isKeyguardShowing: StateFlow<Boolean> = repository.isKeyguardShowing
/** Whether the keyguard is dismissible or not. */
val isKeyguardDismissible: StateFlow<Boolean> = repository.isKeyguardDismissible
/** Whether the keyguard is occluded (covered by an activity). */
@Deprecated("Use KeyguardTransitionInteractor + KeyguardState.OCCLUDED")
- val isKeyguardOccluded: Flow<Boolean> = repository.isKeyguardOccluded
+ val isKeyguardOccluded: StateFlow<Boolean> = repository.isKeyguardOccluded
/** Whether the keyguard is going away. */
@Deprecated("Use KeyguardTransitionInteractor + KeyguardState.GONE")
@@ -253,7 +253,7 @@ constructor(
val ambientIndicationVisible: Flow<Boolean> = repository.ambientIndicationVisible.asStateFlow()
/** Whether the primary bouncer is showing or not. */
- @JvmField val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerShow
+ @JvmField val primaryBouncerShowing: StateFlow<Boolean> = bouncerRepository.primaryBouncerShow
/** Whether the alternate bouncer is showing or not. */
val alternateBouncerShowing: Flow<Boolean> =
@@ -274,7 +274,7 @@ constructor(
val statusBarState: Flow<StatusBarState> = repository.statusBarState
/** Observable for [BiometricUnlockModel] when biometrics are used to unlock the device. */
- val biometricUnlockState: Flow<BiometricUnlockModel> = repository.biometricUnlockState
+ val biometricUnlockState: StateFlow<BiometricUnlockModel> = repository.biometricUnlockState
/** Keyguard is present and is not occluded. */
val isKeyguardVisible: Flow<Boolean> =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
index 15e6b1d78ea0..d119ed4f6580 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
@@ -92,8 +92,8 @@ constructor(
val button = view as ImageView
val configurationBasedDimensions = MutableStateFlow(loadFromResources(view))
val disposableHandle =
- view.repeatWhenAttached(mainImmediateDispatcher) {
- repeatOnLifecycle(Lifecycle.State.STARTED) {
+ view.repeatWhenAttached {
+ repeatOnLifecycle(Lifecycle.State.CREATED) {
launch("$TAG#viewModel") {
viewModel.collect { buttonModel ->
updateButton(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
index aab5b9b29680..89851dbec7bc 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
@@ -152,6 +152,62 @@ object KeyguardRootViewBinder {
}
}
}
+
+ if (
+ KeyguardBottomAreaRefactor.isEnabled || DeviceEntryUdfpsRefactor.isEnabled
+ ) {
+ launch("$TAG#alpha") {
+ viewModel.alpha(viewState).collect { alpha ->
+ view.alpha = alpha
+ if (KeyguardBottomAreaRefactor.isEnabled) {
+ childViews[statusViewId]?.alpha = alpha
+ childViews[burnInLayerId]?.alpha = alpha
+ }
+ }
+ }
+ }
+
+ if (MigrateClocksToBlueprint.isEnabled) {
+ launch("$TAG#translationY") {
+ // When translation happens in burnInLayer, it won't be weather clock
+ // large clock isn't added to burnInLayer due to its scale transition
+ // so we also need to add translation to it here
+ // same as translationX
+ viewModel.translationY.collect { y ->
+ childViews[burnInLayerId]?.translationY = y
+ childViews[largeClockId]?.translationY = y
+ childViews[aodNotificationIconContainerId]?.translationY = y
+ }
+ }
+
+ launch("$TAG#translationX") {
+ viewModel.translationX.collect { state ->
+ val px = state.value ?: return@collect
+ when {
+ state.isToOrFrom(KeyguardState.AOD) -> {
+ // Large Clock is not translated in the x direction
+ childViews[burnInLayerId]?.translationX = px
+ childViews[aodNotificationIconContainerId]?.translationX =
+ px
+ }
+ state.isToOrFrom(KeyguardState.GLANCEABLE_HUB) -> {
+ for ((key, childView) in childViews.entries) {
+ when (key) {
+ indicationArea,
+ startButton,
+ endButton,
+ lockIcon,
+ deviceEntryIcon -> {
+ // Do not move these views
+ }
+ else -> childView.translationX = px
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
}
disposables +=
@@ -188,20 +244,6 @@ object KeyguardRootViewBinder {
}
}
- if (
- KeyguardBottomAreaRefactor.isEnabled || DeviceEntryUdfpsRefactor.isEnabled
- ) {
- launch {
- viewModel.alpha(viewState).collect { alpha ->
- view.alpha = alpha
- if (KeyguardBottomAreaRefactor.isEnabled) {
- childViews[statusViewId]?.alpha = alpha
- childViews[burnInLayerId]?.alpha = alpha
- }
- }
- }
- }
-
if (MigrateClocksToBlueprint.isEnabled) {
launch {
viewModel.burnInLayerVisibility.collect { visibility ->
@@ -222,46 +264,6 @@ object KeyguardRootViewBinder {
}
launch {
- // When translation happens in burnInLayer, it won't be weather clock
- // large clock isn't added to burnInLayer due to its scale transition
- // so we also need to add translation to it here
- // same as translationX
- viewModel.translationY.collect { y ->
- childViews[burnInLayerId]?.translationY = y
- childViews[largeClockId]?.translationY = y
- childViews[aodNotificationIconContainerId]?.translationY = y
- }
- }
-
- launch {
- viewModel.translationX.collect { state ->
- val px = state.value ?: return@collect
- when {
- state.isToOrFrom(KeyguardState.AOD) -> {
- // Large Clock is not translated in the x direction
- childViews[burnInLayerId]?.translationX = px
- childViews[aodNotificationIconContainerId]?.translationX =
- px
- }
- state.isToOrFrom(KeyguardState.GLANCEABLE_HUB) -> {
- for ((key, childView) in childViews.entries) {
- when (key) {
- indicationArea,
- startButton,
- endButton,
- lockIcon,
- deviceEntryIcon -> {
- // Do not move these views
- }
- else -> childView.translationX = px
- }
- }
- }
- }
- }
- }
-
- launch {
viewModel.scale.collect { scaleViewModel ->
if (scaleViewModel.scaleClockOnly) {
// For clocks except weather clock, we have scale transition
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
index 050ef6f94f0a..06f77bfe54c6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
@@ -270,7 +270,7 @@ constructor(
occludedToLockscreenTransitionViewModel.lockscreenAlpha,
primaryBouncerToAodTransitionViewModel.lockscreenAlpha,
primaryBouncerToGoneTransitionViewModel.lockscreenAlpha,
- primaryBouncerToLockscreenTransitionViewModel.lockscreenAlpha,
+ primaryBouncerToLockscreenTransitionViewModel.lockscreenAlpha(viewState),
)
.onStart { emit(1f) }
) { hideKeyguard, alpha ->
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt
index 7511101bf04e..d29f5129bd59 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt
@@ -16,6 +16,7 @@
package com.android.systemui.keyguard.ui.viewmodel
+import android.util.MathUtils
import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor
@@ -58,7 +59,14 @@ constructor(
onStep = { it }
)
- val lockscreenAlpha: Flow<Float> = shortcutsAlpha
+ fun lockscreenAlpha(viewState: ViewStateAccessor): Flow<Float> {
+ var currentAlpha = 0f
+ return transitionAnimation.sharedFlow(
+ duration = 250.milliseconds,
+ onStart = { currentAlpha = viewState.alpha() },
+ onStep = { MathUtils.lerp(currentAlpha, 1f, it) },
+ )
+ }
val deviceEntryBackgroundViewAlpha: Flow<Float> =
transitionAnimation.immediatelyTransitionTo(1f)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
index 62a72184190d..c21301c62c8d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
@@ -223,7 +223,7 @@ constructor(
if (!mediaFlags.isSceneContainerEnabled()) {
MediaPlayerData.players().forEach { it.updateAnimatorDurationScale() }
} else {
- controllerByViewModel.values.forEach { it.updateAnimatorDurationScale() }
+ controllerById.values.forEach { it.updateAnimatorDurationScale() }
}
}
}
@@ -324,7 +324,7 @@ constructor(
private var widthInSceneContainerPx = 0
private var heightInSceneContainerPx = 0
- private val controllerByViewModel = mutableMapOf<MediaCommonViewModel, MediaViewController>()
+ private val controllerById = mutableMapOf<String, MediaViewController>()
private val commonViewModels = mutableListOf<MediaCommonViewModel>()
init {
@@ -738,7 +738,7 @@ constructor(
viewController.heightInSceneContainerPx = heightInSceneContainerPx
}
viewController.attachPlayer(viewHolder)
- viewController.mediaViewHolder.player.layoutParams = lp
+ viewController.mediaViewHolder?.player?.layoutParams = lp
MediaControlViewBinder.bind(
viewHolder,
commonViewModel.controlViewModel,
@@ -749,12 +749,13 @@ constructor(
mediaFlags
)
mediaContent.addView(viewHolder.player, position)
+ controllerById[commonViewModel.instanceId.toString()] = viewController
}
is MediaCommonViewModel.MediaRecommendations -> {
val viewHolder =
RecommendationViewHolder.create(LayoutInflater.from(context), mediaContent)
viewController.attachRecommendations(viewHolder)
- viewController.recommendationViewHolder.recommendations.layoutParams = lp
+ viewController.recommendationViewHolder?.recommendations?.layoutParams = lp
MediaRecommendationsViewBinder.bind(
viewHolder,
commonViewModel.recsViewModel,
@@ -762,11 +763,11 @@ constructor(
falsingManager,
)
mediaContent.addView(viewHolder.recommendations, position)
+ controllerById[commonViewModel.key] = viewController
}
}
onAddOrUpdateVisibleToUserCard(position, isMediaCardUpdate = false)
viewController.setListening(mediaCarouselScrollHandler.visibleToUser && currentlyExpanded)
- controllerByViewModel[commonViewModel] = viewController
updateViewControllerToState(viewController, noAnimation = true)
updatePageIndicator()
if (
@@ -793,14 +794,19 @@ constructor(
}
private fun onRemoved(commonViewModel: MediaCommonViewModel) {
- controllerByViewModel.remove(commonViewModel)?.let {
+ val id =
+ when (commonViewModel) {
+ is MediaCommonViewModel.MediaControl -> commonViewModel.instanceId.toString()
+ is MediaCommonViewModel.MediaRecommendations -> commonViewModel.key
+ }
+ controllerById.remove(id)?.let {
when (commonViewModel) {
is MediaCommonViewModel.MediaControl -> {
- mediaCarouselScrollHandler.onPrePlayerRemoved(it.mediaViewHolder.player)
- mediaContent.removeView(it.mediaViewHolder.player)
+ mediaCarouselScrollHandler.onPrePlayerRemoved(it.mediaViewHolder!!.player)
+ mediaContent.removeView(it.mediaViewHolder!!.player)
}
is MediaCommonViewModel.MediaRecommendations -> {
- mediaContent.removeView(it.recommendationViewHolder.recommendations)
+ mediaContent.removeView(it.recommendationViewHolder!!.recommendations)
}
}
it.onDestroy()
@@ -811,14 +817,19 @@ constructor(
}
private fun onMoved(commonViewModel: MediaCommonViewModel, from: Int, to: Int) {
- controllerByViewModel[commonViewModel]?.let {
+ val id =
+ when (commonViewModel) {
+ is MediaCommonViewModel.MediaControl -> commonViewModel.instanceId.toString()
+ is MediaCommonViewModel.MediaRecommendations -> commonViewModel.key
+ }
+ controllerById[id]?.let {
mediaContent.removeViewAt(from)
when (commonViewModel) {
is MediaCommonViewModel.MediaControl -> {
- mediaContent.addView(it.mediaViewHolder.player, to)
+ mediaContent.addView(it.mediaViewHolder!!.player, to)
}
is MediaCommonViewModel.MediaRecommendations -> {
- mediaContent.addView(it.recommendationViewHolder.recommendations, to)
+ mediaContent.addView(it.recommendationViewHolder!!.recommendations, to)
}
}
}
@@ -855,15 +866,16 @@ constructor(
}
}
.toHashSet()
- controllerByViewModel
- .filter {
- when (val viewModel = it.key) {
- is MediaCommonViewModel.MediaControl ->
- !viewIds.contains(viewModel.instanceId.toString())
- is MediaCommonViewModel.MediaRecommendations -> !viewIds.contains(viewModel.key)
- }
+ controllerById
+ .filter { !viewIds.contains(it.key) }
+ .forEach {
+ mediaCarouselScrollHandler.onPrePlayerRemoved(it.value.mediaViewHolder?.player)
+ mediaContent.removeView(it.value.mediaViewHolder?.player)
+ mediaContent.removeView(it.value.recommendationViewHolder?.recommendations)
+ it.value.onDestroy()
+ mediaCarouselScrollHandler.onPlayersChanged()
+ updatePageIndicator()
}
- .forEach { onRemoved(it.key) }
}
private suspend fun getMediaLockScreenSetting(): Boolean {
@@ -1176,12 +1188,12 @@ constructor(
commonViewModels.forEach { viewModel ->
when (viewModel) {
is MediaCommonViewModel.MediaControl -> {
- controllerByViewModel[viewModel]?.mediaViewHolder?.let {
+ controllerById[viewModel.instanceId.toString()]?.mediaViewHolder?.let {
mediaContent.addView(it.player)
}
}
is MediaCommonViewModel.MediaRecommendations -> {
- controllerByViewModel[viewModel]?.recommendationViewHolder?.let {
+ controllerById[viewModel.key]?.recommendationViewHolder?.let {
mediaContent.addView(it.recommendations)
}
}
@@ -1234,9 +1246,7 @@ constructor(
updateViewControllerToState(mediaPlayer.mediaViewController, immediately)
}
} else {
- controllerByViewModel.values.forEach {
- updateViewControllerToState(it, immediately)
- }
+ controllerById.values.forEach { updateViewControllerToState(it, immediately) }
}
maybeResetSettingsCog()
updatePageIndicatorAlpha()
@@ -1296,9 +1306,7 @@ constructor(
player.setListening(visibleToUser && currentlyExpanded)
}
} else {
- controllerByViewModel.values.forEach {
- it.setListening(visibleToUser && currentlyExpanded)
- }
+ controllerById.values.forEach { it.setListening(visibleToUser && currentlyExpanded) }
}
}
@@ -1316,7 +1324,7 @@ constructor(
Math.max(height, controller.currentHeight + controller.translationY.toInt())
}
} else {
- controllerByViewModel.values.forEach {
+ controllerById.values.forEach {
// When transitioning the view to gone, the view gets smaller, but the translation
// Doesn't, let's add the translation
width = Math.max(width, it.currentWidth + it.translationX.toInt())
@@ -1413,7 +1421,7 @@ constructor(
mediaPlayer.mediaViewController.onLocationPreChange(desiredLocation)
}
} else {
- controllerByViewModel.values.forEach { controller ->
+ controllerById.values.forEach { controller ->
if (animate) {
controller.animatePendingStateChange(duration, startDelay)
}
@@ -1441,7 +1449,7 @@ constructor(
if (!mediaFlags.isSceneContainerEnabled()) {
MediaPlayerData.players().forEach { it.closeGuts(immediate) }
} else {
- controllerByViewModel.values.forEach { it.closeGuts(immediate) }
+ controllerById.values.forEach { it.closeGuts(immediate) }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
index 681bf390e3e9..584908ff2aad 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
@@ -196,8 +196,8 @@ constructor(
private var isNextButtonAvailable = false
/** View holders for controller */
- lateinit var recommendationViewHolder: RecommendationViewHolder
- lateinit var mediaViewHolder: MediaViewHolder
+ var recommendationViewHolder: RecommendationViewHolder? = null
+ var mediaViewHolder: MediaViewHolder? = null
private lateinit var seekBarObserver: SeekBarObserver
private lateinit var turbulenceNoiseController: TurbulenceNoiseController
@@ -752,16 +752,18 @@ constructor(
private fun updateDisplayForScrubbingChange() {
mainExecutor.execute {
val isTimeVisible = canShowScrubbingTime && isScrubbing
- MediaControlViewBinder.setVisibleAndAlpha(
- expandedLayout,
- mediaViewHolder.scrubbingTotalTimeView.id,
- isTimeVisible
- )
- MediaControlViewBinder.setVisibleAndAlpha(
- expandedLayout,
- mediaViewHolder.scrubbingElapsedTimeView.id,
- isTimeVisible
- )
+ mediaViewHolder!!.let {
+ MediaControlViewBinder.setVisibleAndAlpha(
+ expandedLayout,
+ it.scrubbingTotalTimeView.id,
+ isTimeVisible
+ )
+ MediaControlViewBinder.setVisibleAndAlpha(
+ expandedLayout,
+ it.scrubbingElapsedTimeView.id,
+ isTimeVisible
+ )
+ }
MediaControlViewModel.SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING.forEach { id ->
val isButtonVisible: Boolean
@@ -780,14 +782,16 @@ constructor(
notVisibleValue = ConstraintSet.GONE
}
}
- MediaControlViewBinder.setSemanticButtonVisibleAndAlpha(
- mediaViewHolder.getAction(id),
- expandedLayout,
- collapsedLayout,
- isButtonVisible,
- notVisibleValue,
- showInCollapsed = true
- )
+ mediaViewHolder!!.let {
+ MediaControlViewBinder.setSemanticButtonVisibleAndAlpha(
+ it.getAction(id),
+ expandedLayout,
+ collapsedLayout,
+ isButtonVisible,
+ notVisibleValue,
+ showInCollapsed = true
+ )
+ }
}
if (!metadataAnimationHandler.isRunning) {
@@ -813,39 +817,41 @@ constructor(
fun setUpTurbulenceNoise() {
if (!mediaFlags.isSceneContainerEnabled()) return
- if (!this::turbulenceNoiseAnimationConfig.isInitialized) {
- turbulenceNoiseAnimationConfig =
- createTurbulenceNoiseConfig(
- mediaViewHolder.loadingEffectView,
- mediaViewHolder.turbulenceNoiseView,
- colorSchemeTransition
- )
- }
- if (Flags.shaderlibLoadingEffectRefactor()) {
- if (!this::loadingEffect.isInitialized) {
- loadingEffect =
- LoadingEffect(
- TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE,
- turbulenceNoiseAnimationConfig,
- noiseDrawCallback,
- stateChangedCallback
+ mediaViewHolder!!.let {
+ if (!this::turbulenceNoiseAnimationConfig.isInitialized) {
+ turbulenceNoiseAnimationConfig =
+ createTurbulenceNoiseConfig(
+ it.loadingEffectView,
+ it.turbulenceNoiseView,
+ colorSchemeTransition
)
}
- colorSchemeTransition.loadingEffect = loadingEffect
- loadingEffect.play()
- mainExecutor.executeDelayed(
- loadingEffect::finish,
- MediaControlViewModel.TURBULENCE_NOISE_PLAY_MS_DURATION
- )
- } else {
- turbulenceNoiseController.play(
- TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE,
- turbulenceNoiseAnimationConfig
- )
- mainExecutor.executeDelayed(
- turbulenceNoiseController::finish,
- MediaControlViewModel.TURBULENCE_NOISE_PLAY_MS_DURATION
- )
+ if (Flags.shaderlibLoadingEffectRefactor()) {
+ if (!this::loadingEffect.isInitialized) {
+ loadingEffect =
+ LoadingEffect(
+ TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE,
+ turbulenceNoiseAnimationConfig,
+ noiseDrawCallback,
+ stateChangedCallback
+ )
+ }
+ colorSchemeTransition.loadingEffect = loadingEffect
+ loadingEffect.play()
+ mainExecutor.executeDelayed(
+ loadingEffect::finish,
+ MediaControlViewModel.TURBULENCE_NOISE_PLAY_MS_DURATION
+ )
+ } else {
+ turbulenceNoiseController.play(
+ TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE,
+ turbulenceNoiseAnimationConfig
+ )
+ mainExecutor.executeDelayed(
+ turbulenceNoiseController::finish,
+ MediaControlViewModel.TURBULENCE_NOISE_PLAY_MS_DURATION
+ )
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
index f207b1de3cba..bc695bdd4e05 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
@@ -34,6 +34,7 @@ import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.res.R;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.statusbar.policy.SplitShadeStateController;
import com.android.systemui.util.leak.RotationUtils;
@@ -77,9 +78,11 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
@Override
protected void onInit() {
super.onInit();
- updateMediaExpansion();
- mMediaHost.setShowsOnlyActiveMedia(true);
- mMediaHost.init(MediaHierarchyManager.LOCATION_QQS);
+ if (!SceneContainerFlag.isEnabled()) {
+ updateMediaExpansion();
+ mMediaHost.setShowsOnlyActiveMedia(true);
+ mMediaHost.init(MediaHierarchyManager.LOCATION_QQS);
+ }
}
@Override
@@ -125,7 +128,9 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
if (newMaxTiles != mView.getNumQuickTiles()) {
setMaxTiles(newMaxTiles);
}
- updateMediaExpansion();
+ if (!SceneContainerFlag.isEnabled()) {
+ updateMediaExpansion();
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
index f6924f222e11..8aa601f3ecf0 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
@@ -26,13 +26,12 @@ class SceneWindowRootView(
attrs,
) {
- private lateinit var viewModel: SceneContainerViewModel
-
+ private var motionEventHandler: SceneContainerViewModel.MotionEventHandler? = null
// TODO(b/298525212): remove once Compose exposes window inset bounds.
private val windowInsets: MutableStateFlow<WindowInsets?> = MutableStateFlow(null)
fun init(
- viewModel: SceneContainerViewModel,
+ viewModelFactory: SceneContainerViewModel.Factory,
containerConfig: SceneContainerConfig,
sharedNotificationContainer: SharedNotificationContainer,
scenes: Set<Scene>,
@@ -40,11 +39,13 @@ class SceneWindowRootView(
sceneDataSourceDelegator: SceneDataSourceDelegator,
alternateBouncerDependencies: AlternateBouncerDependencies,
) {
- this.viewModel = viewModel
setLayoutInsetsController(layoutInsetController)
SceneWindowRootViewBinder.bind(
view = this@SceneWindowRootView,
- viewModel = viewModel,
+ viewModelFactory = viewModelFactory,
+ motionEventHandlerReceiver = { motionEventHandler ->
+ this.motionEventHandler = motionEventHandler
+ },
windowInsets = windowInsets,
containerConfig = containerConfig,
sharedNotificationContainer = sharedNotificationContainer,
@@ -69,10 +70,10 @@ class SceneWindowRootView(
}
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
- viewModel.onMotionEvent(ev)
+ motionEventHandler?.onMotionEvent(ev)
return super.dispatchTouchEvent(ev).also {
TouchLogger.logDispatchTouch(TAG, ev, it)
- viewModel.onMotionEventComplete()
+ motionEventHandler?.onMotionEventComplete()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
index 73a8e4c24578..ad68f17720c5 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
@@ -29,8 +29,6 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.core.view.isVisible
import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.lifecycleScope
-import androidx.lifecycle.repeatOnLifecycle
import com.android.compose.animation.scene.SceneKey
import com.android.compose.theme.PlatformTheme
import com.android.internal.policy.ScreenDecorationsUtils
@@ -39,7 +37,9 @@ import com.android.systemui.common.ui.compose.windowinsets.DisplayCutout
import com.android.systemui.common.ui.compose.windowinsets.ScreenDecorProvider
import com.android.systemui.keyguard.ui.composable.AlternateBouncer
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies
+import com.android.systemui.lifecycle.WindowLifecycleState
import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.lifecycle.viewModel
import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.Scene
@@ -51,6 +51,7 @@ import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
@@ -63,7 +64,8 @@ object SceneWindowRootViewBinder {
/** Binds between the view and view-model pertaining to a specific scene container. */
fun bind(
view: ViewGroup,
- viewModel: SceneContainerViewModel,
+ viewModelFactory: SceneContainerViewModel.Factory,
+ motionEventHandlerReceiver: (SceneContainerViewModel.MotionEventHandler?) -> Unit,
windowInsets: StateFlow<WindowInsets?>,
containerConfig: SceneContainerConfig,
sharedNotificationContainer: SharedNotificationContainer,
@@ -85,8 +87,11 @@ object SceneWindowRootViewBinder {
}
view.repeatWhenAttached {
- lifecycleScope.launch {
- repeatOnLifecycle(Lifecycle.State.CREATED) {
+ view.viewModel(
+ minWindowLifecycleState = WindowLifecycleState.ATTACHED,
+ factory = { viewModelFactory.create(motionEventHandlerReceiver) },
+ ) { viewModel ->
+ try {
view.setViewTreeOnBackPressedDispatcherOwner(
object : OnBackPressedDispatcherOwner {
override val onBackPressedDispatcher =
@@ -140,10 +145,11 @@ object SceneWindowRootViewBinder {
onVisibilityChangedInternal(isVisible)
}
}
+ awaitCancellation()
+ } finally {
+ // Here when destroyed.
+ view.removeAllViews()
}
-
- // Here when destroyed.
- view.removeAllViews()
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
index a28222e9cea0..2d02f5a5b79d 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
@@ -23,25 +23,26 @@ import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.classifier.Classifier
import com.android.systemui.classifier.domain.interactor.FalsingInteractor
-import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.lifecycle.SysUiViewModel
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.Scenes
-import javax.inject.Inject
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.map
/** Models UI state for the scene container. */
-@SysUISingleton
class SceneContainerViewModel
-@Inject
+@AssistedInject
constructor(
private val sceneInteractor: SceneInteractor,
private val falsingInteractor: FalsingInteractor,
private val powerInteractor: PowerInteractor,
-) {
+ @Assisted private val motionEventHandlerReceiver: (MotionEventHandler?) -> Unit,
+) : SysUiViewModel() {
/**
* Keys of all scenes in the container.
*
@@ -56,6 +57,29 @@ constructor(
/** Whether the container is visible. */
val isVisible: StateFlow<Boolean> = sceneInteractor.isVisible
+ override suspend fun onActivated() {
+ try {
+ // Sends a MotionEventHandler to the owner of the view-model so they can report
+ // MotionEvents into the view-model.
+ motionEventHandlerReceiver(
+ object : MotionEventHandler {
+ override fun onMotionEvent(motionEvent: MotionEvent) {
+ this@SceneContainerViewModel.onMotionEvent(motionEvent)
+ }
+
+ override fun onMotionEventComplete() {
+ this@SceneContainerViewModel.onMotionEventComplete()
+ }
+ }
+ )
+ awaitCancellation()
+ } finally {
+ // Clears the previously-sent MotionEventHandler so the owner of the view-model releases
+ // their reference to it.
+ motionEventHandlerReceiver(null)
+ }
+ }
+
/**
* Binds the given flow so the system remembers it.
*
@@ -136,21 +160,22 @@ constructor(
}
}
- private fun replaceSceneFamilies(
- destinationScenes: Map<UserAction, UserActionResult>,
- ): Flow<Map<UserAction, UserActionResult>> {
- return destinationScenes
- .mapValues { (_, actionResult) ->
- sceneInteractor.resolveSceneFamily(actionResult.toScene).map { scene ->
- actionResult.copy(toScene = scene)
- }
- }
- .combineValueFlows()
+ /** Defines interface for classes that can handle externally-reported [MotionEvent]s. */
+ interface MotionEventHandler {
+ /** Notifies that a [MotionEvent] has occurred. */
+ fun onMotionEvent(motionEvent: MotionEvent)
+
+ /**
+ * Notifies that the previous [MotionEvent] reported by [onMotionEvent] has finished
+ * processing.
+ */
+ fun onMotionEventComplete()
}
-}
-private fun <K, V> Map<K, Flow<V>>.combineValueFlows(): Flow<Map<K, V>> =
- combine(
- asIterable().map { (k, fv) -> fv.map { k to it } },
- transform = Array<Pair<K, V>>::toMap,
- )
+ @AssistedFactory
+ interface Factory {
+ fun create(
+ motionEventHandlerReceiver: (MotionEventHandler?) -> Unit,
+ ): SceneContainerViewModel
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
index 21bbaa5a41f2..606fef0bff62 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
@@ -79,7 +79,7 @@ abstract class ShadeViewProviderModule {
@SysUISingleton
fun providesWindowRootView(
layoutInflater: LayoutInflater,
- viewModelProvider: Provider<SceneContainerViewModel>,
+ viewModelFactory: SceneContainerViewModel.Factory,
containerConfigProvider: Provider<SceneContainerConfig>,
scenesProvider: Provider<Set<@JvmSuppressWildcards Scene>>,
layoutInsetController: NotificationInsetsController,
@@ -91,7 +91,7 @@ abstract class ShadeViewProviderModule {
val sceneWindowRootView =
layoutInflater.inflate(R.layout.scene_window_root, null) as SceneWindowRootView
sceneWindowRootView.init(
- viewModel = viewModelProvider.get(),
+ viewModelFactory = viewModelFactory,
containerConfig = containerConfigProvider.get(),
sharedNotificationContainer =
sceneWindowRootView.requireViewById(R.id.shared_notification_container),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
index 99f7a75676e1..f63ee7b9520d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
@@ -511,7 +511,7 @@ constructor(
occludedToAodTransitionViewModel.lockscreenAlpha,
occludedToGoneTransitionViewModel.notificationAlpha(viewState),
occludedToLockscreenTransitionViewModel.lockscreenAlpha,
- primaryBouncerToLockscreenTransitionViewModel.lockscreenAlpha,
+ primaryBouncerToLockscreenTransitionViewModel.lockscreenAlpha(viewState),
glanceableHubToLockscreenTransitionViewModel.keyguardAlpha,
lockscreenToGlanceableHubTransitionViewModel.keyguardAlpha,
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index f1787088ab98..04604e0bb3f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.phone;
-
-
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
@@ -38,11 +36,8 @@ import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.Dependency;
import com.android.systemui.Flags;
import com.android.systemui.Gefingerpoken;
-import com.android.systemui.plugins.DarkIconDispatcher;
-import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.res.R;
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer;
-import com.android.systemui.statusbar.policy.Clock;
import com.android.systemui.statusbar.window.StatusBarWindowController;
import com.android.systemui.user.ui.binder.StatusBarUserChipViewBinder;
import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel;
@@ -55,8 +50,6 @@ public class PhoneStatusBarView extends FrameLayout {
private final StatusBarContentInsetsProvider mContentInsetsProvider;
private final StatusBarWindowController mStatusBarWindowController;
- private DarkReceiver mBattery;
- private Clock mClock;
private int mRotationOrientation = -1;
@Nullable
private View mCutoutSpace;
@@ -93,8 +86,6 @@ public class PhoneStatusBarView extends FrameLayout {
@Override
public void onFinishInflate() {
super.onFinishInflate();
- mBattery = findViewById(R.id.battery);
- mClock = findViewById(R.id.clock);
mCutoutSpace = findViewById(R.id.cutout_space_view);
updateResources();
@@ -103,9 +94,6 @@ public class PhoneStatusBarView extends FrameLayout {
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- // Always have Battery meters in the status bar observe the dark/light modes.
- Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mBattery);
- Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mClock);
if (updateDisplayParameters()) {
updateLayoutForCutout();
updateWindowHeight();
@@ -115,8 +103,6 @@ public class PhoneStatusBarView extends FrameLayout {
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(mBattery);
- Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(mClock);
mDisplayCutout = null;
}
@@ -136,10 +122,6 @@ public class PhoneStatusBarView extends FrameLayout {
updateWindowHeight();
}
- void onDensityOrFontScaleChanged() {
- mClock.onDensityOrFontScaleChanged();
- }
-
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
if (updateDisplayParameters()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
index a818c05b1666..468a3c3a49a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
@@ -23,10 +23,13 @@ import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
+import androidx.annotation.VisibleForTesting
import com.android.systemui.Flags
import com.android.systemui.Gefingerpoken
+import com.android.systemui.battery.BatteryMeterView
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS
+import com.android.systemui.plugins.DarkIconDispatcher
import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.ui.view.WindowRootView
@@ -35,6 +38,7 @@ import com.android.systemui.shade.ShadeLogger
import com.android.systemui.shade.ShadeViewController
import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor
import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator
+import com.android.systemui.statusbar.policy.Clock
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.window.StatusBarWindowStateController
import com.android.systemui.unfold.SysUIUnfoldComponent
@@ -68,19 +72,27 @@ private constructor(
private val viewUtil: ViewUtil,
private val configurationController: ConfigurationController,
private val statusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory,
+ private val darkIconDispatcher: DarkIconDispatcher,
) : ViewController<PhoneStatusBarView>(view) {
+ private lateinit var battery: BatteryMeterView
+ private lateinit var clock: Clock
private lateinit var statusContainer: View
private val configurationListener =
object : ConfigurationController.ConfigurationListener {
override fun onDensityOrFontScaleChanged() {
- mView.onDensityOrFontScaleChanged()
+ clock.onDensityOrFontScaleChanged()
}
}
override fun onViewAttached() {
statusContainer = mView.requireViewById(R.id.system_icons)
+ clock = mView.requireViewById(R.id.clock)
+ battery = mView.requireViewById(R.id.battery)
+
+ addDarkReceivers()
+
statusContainer.setOnHoverListener(
statusOverlayHoverListenerFactory.createDarkAwareListener(statusContainer)
)
@@ -133,7 +145,9 @@ private constructor(
}
}
- override fun onViewDetached() {
+ @VisibleForTesting
+ public override fun onViewDetached() {
+ removeDarkReceivers()
statusContainer.setOnHoverListener(null)
progressProvider?.setReadyToHandleTransition(false)
moveFromCenterAnimationController?.onViewDetached()
@@ -182,6 +196,16 @@ private constructor(
}
}
+ private fun addDarkReceivers() {
+ darkIconDispatcher.addDarkReceiver(battery)
+ darkIconDispatcher.addDarkReceiver(clock)
+ }
+
+ private fun removeDarkReceivers() {
+ darkIconDispatcher.removeDarkReceiver(battery)
+ darkIconDispatcher.removeDarkReceiver(clock)
+ }
+
inner class PhoneStatusBarViewTouchHandler : Gefingerpoken {
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
return if (Flags.statusBarSwipeOverChip()) {
@@ -285,6 +309,7 @@ private constructor(
private val viewUtil: ViewUtil,
private val configurationController: ConfigurationController,
private val statusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory,
+ private val darkIconDispatcher: DarkIconDispatcher,
) {
fun create(view: PhoneStatusBarView): PhoneStatusBarViewController {
val statusBarMoveFromCenterAnimationController =
@@ -309,6 +334,7 @@ private constructor(
viewUtil,
configurationController,
statusOverlayHoverListenerFactory,
+ darkIconDispatcher,
)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java
index 9507077a89ae..7c0c5c209363 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java
@@ -22,6 +22,9 @@ import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
import static android.view.WindowInsets.Type.systemBars;
+import static com.android.internal.accessibility.common.MagnificationConstants.SCALE_MAX_VALUE;
+import static com.android.internal.accessibility.common.MagnificationConstants.SCALE_MIN_VALUE;
+
import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertEquals;
@@ -429,7 +432,7 @@ public class WindowMagnificationSettingsTest extends SysuiTestCase {
mSettingView = mWindowMagnificationSettings.getSettingView();
mZoomSeekbar = mSettingView.findViewById(R.id.magnifier_zoom_slider);
assertThat(mZoomSeekbar.getProgress()).isEqualTo(10);
- assertThat(mZoomSeekbar.getMax()).isEqualTo(70);
+ assertThat(mZoomSeekbar.getMax()).isEqualTo(getSeekBarMax());
}
@Test
@@ -473,29 +476,26 @@ public class WindowMagnificationSettingsTest extends SysuiTestCase {
@Test
public void seekbarProgress_maxMagnificationBefore_seekbarProgressIsMax() {
- mWindowMagnificationSettings.setMagnificationScale(8f);
+ mWindowMagnificationSettings.setMagnificationScale(SCALE_MAX_VALUE);
setupMagnificationCapabilityAndMode(
/* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW,
/* mode= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
mWindowMagnificationSettings.showSettingPanel();
- // 8.0f is max magnification {@link MagnificationScaleProvider#MAX_SCALE}.
- // Max zoom seek bar is 70.
- assertThat(mZoomSeekbar.getProgress()).isEqualTo(70);
+ assertThat(mZoomSeekbar.getProgress()).isEqualTo(getSeekBarMax());
}
@Test
public void seekbarProgress_aboveMaxMagnificationBefore_seekbarProgressIsMax() {
- mWindowMagnificationSettings.setMagnificationScale(9f);
+ mWindowMagnificationSettings.setMagnificationScale(SCALE_MAX_VALUE + 1f);
setupMagnificationCapabilityAndMode(
/* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW,
/* mode= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
mWindowMagnificationSettings.showSettingPanel();
- // Max zoom seek bar is 70.
- assertThat(mZoomSeekbar.getProgress()).isEqualTo(70);
+ assertThat(mZoomSeekbar.getProgress()).isEqualTo(getSeekBarMax());
}
@Test
@@ -589,4 +589,11 @@ public class WindowMagnificationSettingsTest extends SysuiTestCase {
anyInt(),
eq(UserHandle.USER_CURRENT))).thenReturn(mode);
}
+
+ private int getSeekBarMax() {
+ // Calculates the maximum index (or positions) the seekbar can have.
+ // This is achieved by multiplying the range of possible scales with the magnitude of
+ // change per each movement on the seekbar.
+ return (int) ((SCALE_MAX_VALUE - SCALE_MIN_VALUE) * mZoomSeekbar.getChangeMagnitude());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt
new file mode 100644
index 000000000000..7583399c784a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.inputdevice.data.repository
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.KEYBOARD
+import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.TOUCHPAD
+import com.android.systemui.inputdevice.tutorial.data.repository.TutorialSchedulerRepository
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.google.common.truth.Truth.assertThat
+import java.time.Instant
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.runTest
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class TutorialSchedulerRepositoryTest : SysuiTestCase() {
+
+ private lateinit var underTest: TutorialSchedulerRepository
+ private val kosmos = Kosmos()
+ private val testScope = kosmos.testScope
+
+ @Before
+ fun setup() {
+ underTest =
+ TutorialSchedulerRepository(
+ context,
+ testScope.backgroundScope,
+ "TutorialSchedulerRepositoryTest"
+ )
+ }
+
+ @After
+ fun clear() {
+ testScope.launch { underTest.clearDataStore() }
+ }
+
+ @Test
+ fun initialState() =
+ testScope.runTest {
+ assertThat(underTest.wasEverConnected(KEYBOARD)).isFalse()
+ assertThat(underTest.wasEverConnected(TOUCHPAD)).isFalse()
+ assertThat(underTest.isLaunched(KEYBOARD)).isFalse()
+ assertThat(underTest.isLaunched(TOUCHPAD)).isFalse()
+ }
+
+ @Test
+ fun connectKeyboard() =
+ testScope.runTest {
+ val now = Instant.now().toEpochMilli()
+ underTest.updateConnectTime(KEYBOARD, now)
+
+ assertThat(underTest.wasEverConnected(KEYBOARD)).isTrue()
+ assertThat(underTest.connectTime(KEYBOARD)).isEqualTo(now)
+ assertThat(underTest.wasEverConnected(TOUCHPAD)).isFalse()
+ }
+
+ @Test
+ fun launchKeyboard() =
+ testScope.runTest {
+ underTest.updateLaunch(KEYBOARD)
+
+ assertThat(underTest.isLaunched(KEYBOARD)).isTrue()
+ assertThat(underTest.isLaunched(TOUCHPAD)).isFalse()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
index 2d119174efff..63192f35ff40 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
@@ -36,6 +36,7 @@ import static org.mockito.Mockito.when;
import android.animation.Animator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.os.Handler;
+import android.platform.test.annotations.EnableFlags;
import android.service.notification.StatusBarNotification;
import android.testing.TestableLooper;
import android.view.MotionEvent;
@@ -52,6 +53,7 @@ import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.shared.NotificationContentAlphaOptimization;
import org.junit.Before;
import org.junit.Rule;
@@ -672,17 +674,31 @@ public class NotificationSwipeHelperTest extends SysuiTestCase {
}
@Test
- public void testForceResetSwipeStateDoesNothingIfTranslationIsZero() {
+ public void testForceResetSwipeStateDoesNothingIfTranslationIsZeroAndAlphaIsOne() {
doReturn(FAKE_ROW_WIDTH).when(mNotificationRow).getMeasuredWidth();
doReturn(0f).when(mNotificationRow).getTranslationX();
+ doReturn(1f).when(mNotificationRow).getAlpha();
mSwipeHelper.forceResetSwipeState(mNotificationRow);
verify(mNotificationRow).getTranslationX();
+ verify(mNotificationRow).getAlpha();
verifyNoMoreInteractions(mNotificationRow);
}
@Test
+ @EnableFlags(NotificationContentAlphaOptimization.FLAG_NAME)
+ public void testForceResetSwipeStateResetsAlphaIfTranslationIsZeroAndAlphaNotOne() {
+ doReturn(FAKE_ROW_WIDTH).when(mNotificationRow).getMeasuredWidth();
+ doReturn(0f).when(mNotificationRow).getTranslationX();
+ doReturn(0.5f).when(mNotificationRow).getAlpha();
+
+ mSwipeHelper.forceResetSwipeState(mNotificationRow);
+
+ verify(mNotificationRow).setContentAlpha(eq(1f));
+ }
+
+ @Test
public void testForceResetSwipeStateResetsTranslationAndAlpha() {
doReturn(FAKE_ROW_WIDTH).when(mNotificationRow).getMeasuredWidth();
doReturn(10f).when(mNotificationRow).getTranslationX();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
index 5b4578153233..30e7247b325e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -33,8 +33,11 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import com.android.systemui.SysuiTestCase
+import com.android.systemui.battery.BatteryMeterView
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.plugins.fakeDarkIconDispatcher
import com.android.systemui.res.R
import com.android.systemui.scene.ui.view.WindowRootView
import com.android.systemui.shade.ShadeControllerImpl
@@ -42,6 +45,7 @@ import com.android.systemui.shade.ShadeLogger
import com.android.systemui.shade.ShadeViewController
import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor
import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.statusbar.policy.Clock
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.window.StatusBarWindowStateController
import com.android.systemui.unfold.SysUIUnfoldComponent
@@ -70,7 +74,9 @@ import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(AndroidJUnit4::class)
class PhoneStatusBarViewControllerTest : SysuiTestCase() {
+ private val kosmos = Kosmos()
+ private val fakeDarkIconDispatcher = kosmos.fakeDarkIconDispatcher
@Mock private lateinit var shadeViewController: ShadeViewController
@Mock private lateinit var panelExpansionInteractor: PanelExpansionInteractor
@Mock private lateinit var featureFlags: FeatureFlags
@@ -91,6 +97,12 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
private lateinit var view: PhoneStatusBarView
private lateinit var controller: PhoneStatusBarViewController
+ private val clockView: Clock
+ get() = view.requireViewById(R.id.clock)
+
+ private val batteryView: BatteryMeterView
+ get() = view.requireViewById(R.id.battery)
+
private val unfoldConfig = UnfoldConfig()
@Before
@@ -114,16 +126,25 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
@Test
fun onViewAttachedAndDrawn_startListeningConfigurationControllerCallback() {
val view = createViewMock()
- val argumentCaptor =
- ArgumentCaptor.forClass(ConfigurationController.ConfigurationListener::class.java)
+
InstrumentationRegistry.getInstrumentation().runOnMainSync {
controller = createAndInitController(view)
}
- verify(configurationController).addCallback(argumentCaptor.capture())
- argumentCaptor.value.onDensityOrFontScaleChanged()
+ verify(configurationController).addCallback(any())
+ }
+
+ @Test
+ fun onViewAttachedAndDrawn_darkReceiversRegistered() {
+ val view = createViewMock()
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
+ controller = createAndInitController(view)
+ }
- verify(view).onDensityOrFontScaleChanged()
+ assertThat(fakeDarkIconDispatcher.receivers.size).isEqualTo(2)
+ assertThat(fakeDarkIconDispatcher.receivers).contains(clockView)
+ assertThat(fakeDarkIconDispatcher.receivers).contains(batteryView)
}
@Test
@@ -158,6 +179,21 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
}
@Test
+ fun onViewDetached_darkReceiversUnregistered() {
+ val view = createViewMock()
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
+ controller = createAndInitController(view)
+ }
+
+ assertThat(fakeDarkIconDispatcher.receivers).isNotEmpty()
+
+ controller.onViewDetached()
+
+ assertThat(fakeDarkIconDispatcher.receivers).isEmpty()
+ }
+
+ @Test
fun handleTouchEventFromStatusBar_panelsNotEnabled_returnsFalseAndNoViewEvent() {
`when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(false)
val returnVal =
@@ -353,7 +389,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
shadeLogger,
viewUtil,
configurationController,
- mStatusOverlayHoverListenerFactory
+ mStatusOverlayHoverListenerFactory,
+ fakeDarkIconDispatcher,
)
.create(view)
.also { it.init() }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
index abc50bc09e55..ed5ec7b2160a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
@@ -35,7 +35,6 @@ import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_STATUS_BAR_SWIPE_OVER_CHIP
import com.android.systemui.Gefingerpoken
import com.android.systemui.SysuiTestCase
-import com.android.systemui.plugins.DarkIconDispatcher
import com.android.systemui.res.R
import com.android.systemui.statusbar.window.StatusBarWindowController
import com.android.systemui.util.mockito.mock
@@ -64,7 +63,6 @@ class PhoneStatusBarViewTest : SysuiTestCase() {
StatusBarContentInsetsProvider::class.java,
contentInsetsProvider
)
- mDependency.injectTestDependency(DarkIconDispatcher::class.java, mock<DarkIconDispatcher>())
mDependency.injectTestDependency(StatusBarWindowController::class.java, windowController)
context.ensureTestableResources()
view = spy(createStatusBarView())
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractorKosmos.kt
new file mode 100644
index 000000000000..81242244b7a6
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractorKosmos.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.domain.interactor
+
+import com.android.systemui.common.usagestats.domain.interactor.usageStatsInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.log.logcatLogBuffer
+import com.android.systemui.plugins.activityStarter
+import com.android.systemui.shared.system.taskStackChangeListeners
+import com.android.systemui.util.time.fakeSystemClock
+
+val Kosmos.widgetTrampolineInteractor: WidgetTrampolineInteractor by
+ Kosmos.Fixture {
+ WidgetTrampolineInteractor(
+ activityStarter = activityStarter,
+ systemClock = fakeSystemClock,
+ keyguardTransitionInteractor = keyguardTransitionInteractor,
+ taskStackChangeListeners = taskStackChangeListeners,
+ usageStatsInteractor = usageStatsInteractor,
+ logBuffer = logcatLogBuffer("WidgetTrampolineInteractor"),
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 4571c19d101a..54a6c0c1d182 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -60,13 +60,13 @@ class FakeKeyguardRepository @Inject constructor() : KeyguardRepository {
override val bottomAreaAlpha: StateFlow<Float> = _bottomAreaAlpha
private val _isKeyguardShowing = MutableStateFlow(false)
- override val isKeyguardShowing: Flow<Boolean> = _isKeyguardShowing
+ override val isKeyguardShowing: StateFlow<Boolean> = _isKeyguardShowing
private val _isKeyguardUnlocked = MutableStateFlow(false)
override val isKeyguardDismissible: StateFlow<Boolean> = _isKeyguardUnlocked.asStateFlow()
private val _isKeyguardOccluded = MutableStateFlow(false)
- override val isKeyguardOccluded: Flow<Boolean> = _isKeyguardOccluded
+ override val isKeyguardOccluded: StateFlow<Boolean> = _isKeyguardOccluded
private val _isDozing = MutableStateFlow(false)
override val isDozing: StateFlow<Boolean> = _isDozing
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/DarkIconDispatcherKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/DarkIconDispatcherKosmos.kt
new file mode 100644
index 000000000000..3d125e93a030
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/DarkIconDispatcherKosmos.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.plugins
+
+import com.android.systemui.kosmos.Kosmos
+
+var Kosmos.fakeDarkIconDispatcher: FakeDarkIconDispatcher by
+ Kosmos.Fixture { FakeDarkIconDispatcher() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/FakeDarkIconDispatcher.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/FakeDarkIconDispatcher.kt
new file mode 100644
index 000000000000..102a853a8250
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/FakeDarkIconDispatcher.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.plugins
+
+import android.graphics.Rect
+import java.util.ArrayList
+
+class FakeDarkIconDispatcher : DarkIconDispatcher {
+ val receivers = mutableListOf<DarkIconDispatcher.DarkReceiver>()
+
+ override fun setIconsDarkArea(r: ArrayList<Rect>) {}
+
+ override fun addDarkReceiver(receiver: DarkIconDispatcher.DarkReceiver) {
+ receivers.add(receiver)
+ }
+
+ override fun removeDarkReceiver(receiver: DarkIconDispatcher.DarkReceiver) {
+ receivers.remove(receiver)
+ }
+
+ override fun applyDark(`object`: DarkIconDispatcher.DarkReceiver) {}
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shared/system/TaskStackChangeListenersKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shared/system/TaskStackChangeListenersKosmos.kt
new file mode 100644
index 000000000000..67f611a040cf
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shared/system/TaskStackChangeListenersKosmos.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shared.system
+
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.taskStackChangeListeners: TaskStackChangeListeners by
+ Kosmos.Fixture { TaskStackChangeListeners.getTestInstance() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioSharingRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioSharingRepository.kt
index 0a617d17b033..a4719e5a2492 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioSharingRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioSharingRepository.kt
@@ -18,7 +18,6 @@ package com.android.systemui.volume.data.repository
import com.android.settingslib.volume.data.repository.AudioSharingRepository
import com.android.settingslib.volume.data.repository.GroupIdToVolumes
-import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -30,7 +29,7 @@ class FakeAudioSharingRepository : AudioSharingRepository {
MutableStateFlow(TEST_GROUP_ID_INVALID)
private val mutableVolumeMap: MutableStateFlow<GroupIdToVolumes> = MutableStateFlow(emptyMap())
- override val inAudioSharing: Flow<Boolean> = mutableInAudioSharing
+ override val inAudioSharing: StateFlow<Boolean> = mutableInAudioSharing
override val primaryGroupId: StateFlow<Int> = mutablePrimaryGroupId
override val secondaryGroupId: StateFlow<Int> = mutableSecondaryGroupId
override val volumeMap: StateFlow<GroupIdToVolumes> = mutableVolumeMap
diff --git a/services/contentcapture/java/com/android/server/contentprotection/OWNERS b/services/contentcapture/java/com/android/server/contentprotection/OWNERS
new file mode 100644
index 000000000000..3d09da303b0f
--- /dev/null
+++ b/services/contentcapture/java/com/android/server/contentprotection/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 1040349
+
+include /core/java/android/view/contentprotection/OWNERS
+
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index f61bd6040658..154b52b86e73 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -1413,6 +1413,22 @@ public class AppOpsService extends IAppOpsService.Stub {
}
public void uidRemoved(int uid) {
+ if (Flags.dontRemoveExistingUidStates()) {
+ // b/358365471 If apps sharing UID are installed on multiple users and only one of
+ // them is installed for a single user while keeping the others we observe this
+ // subroutine get invoked incorrectly since the UID still exists.
+ final long token = Binder.clearCallingIdentity();
+ try {
+ String uidName = getPackageManagerInternal().getNameForUid(uid);
+ if (uidName != null) {
+ Slog.e(TAG, "Tried to remove existing UID. uid: " + uid + " name: " + uidName);
+ return;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
synchronized (this) {
if (mUidStates.indexOfKey(uid) >= 0) {
mUidStates.get(uid).clear();
diff --git a/services/core/java/com/android/server/biometrics/PreAuthInfo.java b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
index 0bd22f3da67f..f0da67bd9f9a 100644
--- a/services/core/java/com/android/server/biometrics/PreAuthInfo.java
+++ b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
@@ -77,13 +77,15 @@ class PreAuthInfo {
private final int mBiometricStrengthRequested;
private final BiometricCameraManager mBiometricCameraManager;
private final boolean mOnlyMandatoryBiometricsRequested;
+ private final boolean mIsMandatoryBiometricsAuthentication;
private PreAuthInfo(boolean biometricRequested, int biometricStrengthRequested,
boolean credentialRequested, List<BiometricSensor> eligibleSensors,
List<Pair<BiometricSensor, Integer>> ineligibleSensors, boolean credentialAvailable,
PromptInfo promptInfo, int userId, Context context,
BiometricCameraManager biometricCameraManager,
- boolean isOnlyMandatoryBiometricsRequested) {
+ boolean isOnlyMandatoryBiometricsRequested,
+ boolean isMandatoryBiometricsAuthentication) {
mBiometricRequested = biometricRequested;
mBiometricStrengthRequested = biometricStrengthRequested;
mBiometricCameraManager = biometricCameraManager;
@@ -97,6 +99,7 @@ class PreAuthInfo {
this.userId = userId;
this.context = context;
this.mOnlyMandatoryBiometricsRequested = isOnlyMandatoryBiometricsRequested;
+ this.mIsMandatoryBiometricsAuthentication = isMandatoryBiometricsAuthentication;
}
static PreAuthInfo create(ITrustManager trustManager,
@@ -110,10 +113,12 @@ class PreAuthInfo {
final boolean isOnlyMandatoryBiometricsRequested = promptInfo.getAuthenticators()
== BiometricManager.Authenticators.MANDATORY_BIOMETRICS;
+ boolean isMandatoryBiometricsAuthentication = false;
if (dropCredentialFallback(promptInfo.getAuthenticators(),
settingObserver.getMandatoryBiometricsEnabledAndRequirementsSatisfiedForUser(
userId), trustManager)) {
+ isMandatoryBiometricsAuthentication = true;
promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG);
promptInfo.setNegativeButtonText(context.getString(R.string.cancel));
}
@@ -166,7 +171,8 @@ class PreAuthInfo {
return new PreAuthInfo(biometricRequested, requestedStrength, credentialRequested,
eligibleSensors, ineligibleSensors, credentialAvailable, promptInfo, userId,
- context, biometricCameraManager, isOnlyMandatoryBiometricsRequested);
+ context, biometricCameraManager, isOnlyMandatoryBiometricsRequested,
+ isMandatoryBiometricsAuthentication);
}
private static boolean dropCredentialFallback(int authenticators,
@@ -387,25 +393,6 @@ class PreAuthInfo {
status = CREDENTIAL_NOT_ENROLLED;
}
}
- } else if (Flags.mandatoryBiometrics() && mOnlyMandatoryBiometricsRequested) {
- if (!eligibleSensors.isEmpty()) {
- for (BiometricSensor sensor : eligibleSensors) {
- modality |= sensor.modality;
- }
-
- if (modality == TYPE_FACE && cameraPrivacyEnabled) {
- // If the only modality requested is face, credential is unavailable,
- // and the face sensor privacy is enabled then return
- // BIOMETRIC_SENSOR_PRIVACY_ENABLED.
- //
- // Note: This sensor will not be eligible for calls to authenticate.
- status = BIOMETRIC_SENSOR_PRIVACY_ENABLED;
- } else {
- status = AUTHENTICATOR_OK;
- }
- } else {
- status = MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR;
- }
} else if (mBiometricRequested) {
if (!eligibleSensors.isEmpty()) {
for (BiometricSensor sensor : eligibleSensors) {
@@ -434,6 +421,9 @@ class PreAuthInfo {
} else if (credentialRequested) {
modality |= TYPE_CREDENTIAL;
status = credentialAvailable ? AUTHENTICATOR_OK : CREDENTIAL_NOT_ENROLLED;
+ } else if (Flags.mandatoryBiometrics() && mOnlyMandatoryBiometricsRequested
+ && !mIsMandatoryBiometricsAuthentication) {
+ status = MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR;
} else {
// This should not be possible via the public API surface and is here mainly for
// "correctness". An exception should have been thrown before getting here.
diff --git a/services/core/java/com/android/server/biometrics/Utils.java b/services/core/java/com/android/server/biometrics/Utils.java
index fb8a81be4b89..871121472938 100644
--- a/services/core/java/com/android/server/biometrics/Utils.java
+++ b/services/core/java/com/android/server/biometrics/Utils.java
@@ -35,6 +35,7 @@ import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NOT_ENROLLED;
import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NO_HARDWARE;
import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_SENSOR_PRIVACY_ENABLED;
import static com.android.server.biometrics.PreAuthInfo.CREDENTIAL_NOT_ENROLLED;
+import static com.android.server.biometrics.PreAuthInfo.MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -48,6 +49,7 @@ import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricPrompt.AuthenticationResultType;
+import android.hardware.biometrics.Flags;
import android.hardware.biometrics.IBiometricService;
import android.hardware.biometrics.PromptInfo;
import android.hardware.biometrics.SensorProperties;
@@ -309,11 +311,16 @@ public class Utils {
break;
case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT:
case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT:
- biometricManagerCode = BiometricManager.BIOMETRIC_SUCCESS;
+ biometricManagerCode = Flags.mandatoryBiometrics()
+ ? BiometricManager.BIOMETRIC_ERROR_LOCKOUT
+ : BiometricManager.BIOMETRIC_SUCCESS;
break;
case BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED:
biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE;
break;
+ case BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE:
+ biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE;
+ break;
default:
Slog.e(BiometricService.TAG, "Unhandled result code: " + biometricConstantsCode);
biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE;
@@ -375,6 +382,8 @@ public class Utils {
return BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
case BIOMETRIC_SENSOR_PRIVACY_ENABLED:
return BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED;
+ case MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR:
+ return BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE;
case BIOMETRIC_DISABLED_BY_DEVICE_POLICY:
case BIOMETRIC_HARDWARE_NOT_DETECTED:
case BIOMETRIC_NOT_ENABLED_FOR_APPS:
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index 38e6d822477a..1094bee1e7e6 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -1002,9 +1002,9 @@ public final class DeviceStateManagerService extends SystemService {
/**
* Checks if the process can cancel a device state request. If the calling process ID is not
- * both the top app and foregrounded nor does the process ID and userID match the IDs that made
- * the device state request, then check if this process holds the CONTROL_DEVICE_STATE
- * permission.
+ * both the top app and foregrounded, verify that the calling process is in the foreground and
+ * that it matches the process ID and user ID that made the device state request. If neither are
+ * true, then check if this process holds the CONTROL_DEVICE_STATE permission.
*
* @param callingPid Process ID that is requesting this state change
* @param callingUid UID that is requesting this state change
@@ -1018,8 +1018,8 @@ public final class DeviceStateManagerService extends SystemService {
if (Flags.deviceStateRequesterCancelState()) {
synchronized (mLock) {
isAllowedToControlState =
- isAllowedToControlState || doCallingIdsMatchOverrideRequestIdsLocked(
- callingPid, callingUid);
+ isTopApp || (isForegroundApp && doCallingIdsMatchOverrideRequestIdsLocked(
+ callingPid, callingUid));
}
}
diff --git a/services/core/java/com/android/server/input/InputManagerInternal.java b/services/core/java/com/android/server/input/InputManagerInternal.java
index 819b9a166daa..73f18d17d058 100644
--- a/services/core/java/com/android/server/input/InputManagerInternal.java
+++ b/services/core/java/com/android/server/input/InputManagerInternal.java
@@ -21,7 +21,7 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.graphics.PointF;
import android.hardware.display.DisplayViewport;
-import android.hardware.input.KeyboardSystemShortcut;
+import android.hardware.input.KeyGestureEvent;
import android.os.IBinder;
import android.view.InputChannel;
import android.view.inputmethod.InputMethodSubtype;
@@ -230,18 +230,14 @@ public abstract class InputManagerInternal {
public abstract int getLastUsedInputDeviceId();
/**
- * Notify Keyboard system shortcut was triggered by the user and handled by the framework.
+ * Notify key gesture was completed by the user.
*
- * NOTE: This is just to notify that a system shortcut was triggered. No further action is
- * required to execute the said shortcut. This callback is meant for purposes of providing user
- * hints or logging, etc.
- *
- * @param deviceId the device ID of the keyboard using which the shortcut was triggered
- * @param keycodes the keys pressed for triggering the shortcut
- * @param modifierState the modifier state of the key event that triggered the shortcut
- * @param shortcut the shortcut that was triggered
+ * @param deviceId the device ID of the keyboard using which the event was completed
+ * @param keycodes the keys pressed for the event
+ * @param modifierState the modifier state
+ * @param event the gesture event that was completed
*
*/
- public abstract void notifyKeyboardShortcutTriggered(int deviceId, int[] keycodes,
- int modifierState, @KeyboardSystemShortcut.SystemShortcut int shortcut);
+ public abstract void notifyKeyGestureCompleted(int deviceId, int[] keycodes, int modifierState,
+ @KeyGestureEvent.KeyGestureType int event);
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index a69c7efc5b21..a8fc8621cbc7 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -48,18 +48,18 @@ import android.hardware.input.IInputDeviceBatteryState;
import android.hardware.input.IInputDevicesChangedListener;
import android.hardware.input.IInputManager;
import android.hardware.input.IInputSensorEventListener;
+import android.hardware.input.IKeyGestureEventListener;
import android.hardware.input.IKeyboardBacklightListener;
-import android.hardware.input.IKeyboardSystemShortcutListener;
import android.hardware.input.IStickyModifierStateListener;
import android.hardware.input.ITabletModeChangedListener;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
import android.hardware.input.InputSensorInfo;
import android.hardware.input.InputSettings;
+import android.hardware.input.KeyGestureEvent;
import android.hardware.input.KeyGlyphMap;
import android.hardware.input.KeyboardLayout;
import android.hardware.input.KeyboardLayoutSelectionResult;
-import android.hardware.input.KeyboardSystemShortcut;
import android.hardware.input.TouchCalibration;
import android.hardware.lights.Light;
import android.hardware.lights.LightState;
@@ -162,7 +162,7 @@ public class InputManagerService extends IInputManager.Stub
private static final int MSG_DELIVER_INPUT_DEVICES_CHANGED = 1;
private static final int MSG_RELOAD_DEVICE_ALIASES = 2;
private static final int MSG_DELIVER_TABLET_MODE_CHANGED = 3;
- private static final int MSG_KEYBOARD_SYSTEM_SHORTCUT_TRIGGERED = 4;
+ private static final int MSG_KEY_GESTURE_COMPLETED = 4;
private static final int DEFAULT_VIBRATION_MAGNITUDE = 192;
private static final AdditionalDisplayInputProperties
@@ -314,9 +314,7 @@ public class InputManagerService extends IInputManager.Stub
// Manages Sticky modifier state
private final StickyModifierStateController mStickyModifierStateController;
-
- // Manages keyboard system shortcut callbacks
- private final KeyboardShortcutCallbackHandler mKeyboardShortcutCallbackHandler;
+ private final KeyGestureController mKeyGestureController;
// Manages Keyboard microphone mute led
private final KeyboardLedController mKeyboardLedController;
@@ -476,7 +474,7 @@ public class InputManagerService extends IInputManager.Stub
injector.getLooper(), injector.getUEventManager())
: new KeyboardBacklightControllerInterface() {};
mStickyModifierStateController = new StickyModifierStateController();
- mKeyboardShortcutCallbackHandler = new KeyboardShortcutCallbackHandler();
+ mKeyGestureController = new KeyGestureController();
mKeyboardLedController = new KeyboardLedController(mContext, injector.getLooper(),
mNative);
mKeyRemapper = new KeyRemapper(mContext, mNative, mDataStore, injector.getLooper());
@@ -2723,33 +2721,32 @@ public class InputManagerService extends IInputManager.Stub
}
@Override
- @EnforcePermission(Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS)
- public void registerKeyboardSystemShortcutListener(
- @NonNull IKeyboardSystemShortcutListener listener) {
- super.registerKeyboardSystemShortcutListener_enforcePermission();
+ @EnforcePermission(Manifest.permission.MANAGE_KEY_GESTURES)
+ public void registerKeyGestureEventListener(
+ @NonNull IKeyGestureEventListener listener) {
+ super.registerKeyGestureEventListener_enforcePermission();
Objects.requireNonNull(listener);
- mKeyboardShortcutCallbackHandler.registerKeyboardSystemShortcutListener(listener,
+ mKeyGestureController.registerKeyGestureEventListener(listener,
Binder.getCallingPid());
}
@Override
- @EnforcePermission(Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS)
- public void unregisterKeyboardSystemShortcutListener(
- @NonNull IKeyboardSystemShortcutListener listener) {
- super.unregisterKeyboardSystemShortcutListener_enforcePermission();
+ @EnforcePermission(Manifest.permission.MANAGE_KEY_GESTURES)
+ public void unregisterKeyGestureEventListener(
+ @NonNull IKeyGestureEventListener listener) {
+ super.unregisterKeyGestureEventListener_enforcePermission();
Objects.requireNonNull(listener);
- mKeyboardShortcutCallbackHandler.unregisterKeyboardSystemShortcutListener(listener,
+ mKeyGestureController.unregisterKeyGestureEventListener(listener,
Binder.getCallingPid());
}
- private void handleKeyboardSystemShortcutTriggered(int deviceId,
- KeyboardSystemShortcut shortcut) {
- InputDevice device = getInputDevice(deviceId);
- if (device == null || device.isVirtual() || !device.isFullKeyboard()) {
+ private void handleKeyGestureCompleted(KeyGestureEvent event) {
+ InputDevice device = getInputDevice(event.getDeviceId());
+ if (device == null || device.isVirtual()) {
return;
}
- KeyboardMetricsCollector.logKeyboardSystemsEventReportedAtom(device, shortcut);
- mKeyboardShortcutCallbackHandler.onKeyboardSystemShortcutTriggered(deviceId, shortcut);
+ KeyboardMetricsCollector.logKeyboardSystemsEventReportedAtom(device, event);
+ mKeyGestureController.onKeyGestureEvent(event);
}
/**
@@ -2920,10 +2917,9 @@ public class InputManagerService extends IInputManager.Stub
boolean inTabletMode = (boolean) args.arg1;
deliverTabletModeChanged(whenNanos, inTabletMode);
break;
- case MSG_KEYBOARD_SYSTEM_SHORTCUT_TRIGGERED:
- int deviceId = msg.arg1;
- KeyboardSystemShortcut shortcut = (KeyboardSystemShortcut) msg.obj;
- handleKeyboardSystemShortcutTriggered(deviceId, shortcut);
+ case MSG_KEY_GESTURE_COMPLETED:
+ KeyGestureEvent event = (KeyGestureEvent) msg.obj;
+ handleKeyGestureCompleted(event);
}
}
}
@@ -3251,10 +3247,11 @@ public class InputManagerService extends IInputManager.Stub
}
@Override
- public void notifyKeyboardShortcutTriggered(int deviceId, int[] keycodes, int modifierState,
- @KeyboardSystemShortcut.SystemShortcut int shortcut) {
- mHandler.obtainMessage(MSG_KEYBOARD_SYSTEM_SHORTCUT_TRIGGERED, deviceId, 0,
- new KeyboardSystemShortcut(keycodes, modifierState, shortcut)).sendToTarget();
+ public void notifyKeyGestureCompleted(int deviceId, int[] keycodes, int modifierState,
+ @KeyGestureEvent.KeyGestureType int gestureType) {
+ mHandler.obtainMessage(MSG_KEY_GESTURE_COMPLETED,
+ new KeyGestureEvent(deviceId, keycodes, modifierState,
+ gestureType)).sendToTarget();
}
}
diff --git a/services/core/java/com/android/server/input/KeyGestureController.java b/services/core/java/com/android/server/input/KeyGestureController.java
new file mode 100644
index 000000000000..674d3c448c86
--- /dev/null
+++ b/services/core/java/com/android/server/input/KeyGestureController.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input;
+
+import android.annotation.BinderThread;
+import android.hardware.input.IKeyGestureEventListener;
+import android.hardware.input.KeyGestureEvent;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+
+/**
+ * A thread-safe component of {@link InputManagerService} responsible for managing callbacks when a
+ * key gesture event occurs.
+ */
+final class KeyGestureController {
+
+ private static final String TAG = "KeyGestureController";
+
+ // To enable these logs, run:
+ // 'adb shell setprop log.tag.KeyGestureController DEBUG' (requires restart)
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ // List of currently registered key gesture event listeners keyed by process pid
+ @GuardedBy("mKeyGestureEventListenerRecords")
+ private final SparseArray<KeyGestureEventListenerRecord>
+ mKeyGestureEventListenerRecords = new SparseArray<>();
+
+ public void onKeyGestureEvent(KeyGestureEvent event) {
+ if (DEBUG) {
+ Slog.d(TAG, "Key gesture event occurred, event = " + event);
+ }
+
+ synchronized (mKeyGestureEventListenerRecords) {
+ for (int i = 0; i < mKeyGestureEventListenerRecords.size(); i++) {
+ mKeyGestureEventListenerRecords.valueAt(i).onKeyGestureEvent(event);
+ }
+ }
+ }
+
+ /** Register the key gesture event listener for a process. */
+ @BinderThread
+ public void registerKeyGestureEventListener(IKeyGestureEventListener listener,
+ int pid) {
+ synchronized (mKeyGestureEventListenerRecords) {
+ if (mKeyGestureEventListenerRecords.get(pid) != null) {
+ throw new IllegalStateException("The calling process has already registered "
+ + "a KeyGestureEventListener.");
+ }
+ KeyGestureEventListenerRecord record = new KeyGestureEventListenerRecord(
+ pid, listener);
+ try {
+ listener.asBinder().linkToDeath(record, 0);
+ } catch (RemoteException ex) {
+ throw new RuntimeException(ex);
+ }
+ mKeyGestureEventListenerRecords.put(pid, record);
+ }
+ }
+
+ /** Unregister the key gesture event listener for a process. */
+ @BinderThread
+ public void unregisterKeyGestureEventListener(IKeyGestureEventListener listener,
+ int pid) {
+ synchronized (mKeyGestureEventListenerRecords) {
+ KeyGestureEventListenerRecord record =
+ mKeyGestureEventListenerRecords.get(pid);
+ if (record == null) {
+ throw new IllegalStateException("The calling process has no registered "
+ + "KeyGestureEventListener.");
+ }
+ if (record.mListener.asBinder() != listener.asBinder()) {
+ throw new IllegalStateException("The calling process has a different registered "
+ + "KeyGestureEventListener.");
+ }
+ record.mListener.asBinder().unlinkToDeath(record, 0);
+ mKeyGestureEventListenerRecords.remove(pid);
+ }
+ }
+
+ private void onKeyGestureEventListenerDied(int pid) {
+ synchronized (mKeyGestureEventListenerRecords) {
+ mKeyGestureEventListenerRecords.remove(pid);
+ }
+ }
+
+ // A record of a registered key gesture event listener from one process.
+ private class KeyGestureEventListenerRecord implements IBinder.DeathRecipient {
+ public final int mPid;
+ public final IKeyGestureEventListener mListener;
+
+ KeyGestureEventListenerRecord(int pid, IKeyGestureEventListener listener) {
+ mPid = pid;
+ mListener = listener;
+ }
+
+ @Override
+ public void binderDied() {
+ if (DEBUG) {
+ Slog.d(TAG, "Key gesture event listener for pid " + mPid + " died.");
+ }
+ onKeyGestureEventListenerDied(mPid);
+ }
+
+ public void onKeyGestureEvent(KeyGestureEvent event) {
+ try {
+ mListener.onKeyGestureEvent(event.getDeviceId(), event.getKeycodes(),
+ event.getModifierState(), event.getKeyGestureType());
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to notify process " + mPid
+ + " that key gesture event occurred, assuming it died.", ex);
+ binderDied();
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/input/KeyboardMetricsCollector.java b/services/core/java/com/android/server/input/KeyboardMetricsCollector.java
index 3d2f95105e76..1daf4db699aa 100644
--- a/services/core/java/com/android/server/input/KeyboardMetricsCollector.java
+++ b/services/core/java/com/android/server/input/KeyboardMetricsCollector.java
@@ -24,9 +24,9 @@ import static android.hardware.input.KeyboardLayoutSelectionResult.layoutSelecti
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.hardware.input.KeyGestureEvent;
import android.hardware.input.KeyboardLayout;
import android.hardware.input.KeyboardLayoutSelectionResult.LayoutSelectionCriteria;
-import android.hardware.input.KeyboardSystemShortcut;
import android.icu.util.ULocale;
import android.text.TextUtils;
import android.util.Log;
@@ -66,14 +66,17 @@ public final class KeyboardMetricsCollector {
* defined in "stats/atoms/input/input_extension_atoms.proto"
*/
public static void logKeyboardSystemsEventReportedAtom(@NonNull InputDevice inputDevice,
- @NonNull KeyboardSystemShortcut keyboardSystemShortcut) {
+ @NonNull KeyGestureEvent keyGestureEvent) {
+ if (inputDevice.isVirtual() || !inputDevice.isFullKeyboard()) {
+ return;
+ }
FrameworkStatsLog.write(FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED,
inputDevice.getVendorId(), inputDevice.getProductId(),
- keyboardSystemShortcut.getSystemShortcut(), keyboardSystemShortcut.getKeycodes(),
- keyboardSystemShortcut.getModifierState(), inputDevice.getDeviceBus());
+ keyGestureEvent.getKeyGestureType(), keyGestureEvent.getKeycodes(),
+ keyGestureEvent.getModifierState(), inputDevice.getDeviceBus());
if (DEBUG) {
- Slog.d(TAG, "Logging Keyboard system event: " + keyboardSystemShortcut);
+ Slog.d(TAG, "Logging Keyboard system event: " + keyGestureEvent);
}
}
diff --git a/services/core/java/com/android/server/input/KeyboardShortcutCallbackHandler.java b/services/core/java/com/android/server/input/KeyboardShortcutCallbackHandler.java
deleted file mode 100644
index 092058e6f7d0..000000000000
--- a/services/core/java/com/android/server/input/KeyboardShortcutCallbackHandler.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.input;
-
-import android.annotation.BinderThread;
-import android.hardware.input.IKeyboardSystemShortcutListener;
-import android.hardware.input.KeyboardSystemShortcut;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-import android.util.Slog;
-import android.util.SparseArray;
-
-import com.android.internal.annotations.GuardedBy;
-
-/**
- * A thread-safe component of {@link InputManagerService} responsible for managing callbacks when a
- * keyboard shortcut is triggered.
- */
-final class KeyboardShortcutCallbackHandler {
-
- private static final String TAG = "KeyboardShortcut";
-
- // To enable these logs, run:
- // 'adb shell setprop log.tag.KeyboardShortcutCallbackHandler DEBUG' (requires restart)
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
- // List of currently registered keyboard system shortcut listeners keyed by process pid
- @GuardedBy("mKeyboardSystemShortcutListenerRecords")
- private final SparseArray<KeyboardSystemShortcutListenerRecord>
- mKeyboardSystemShortcutListenerRecords = new SparseArray<>();
-
- public void onKeyboardSystemShortcutTriggered(int deviceId,
- KeyboardSystemShortcut systemShortcut) {
- if (DEBUG) {
- Slog.d(TAG, "Keyboard system shortcut triggered, deviceId = " + deviceId
- + ", systemShortcut = " + systemShortcut);
- }
-
- synchronized (mKeyboardSystemShortcutListenerRecords) {
- for (int i = 0; i < mKeyboardSystemShortcutListenerRecords.size(); i++) {
- mKeyboardSystemShortcutListenerRecords.valueAt(i).onKeyboardSystemShortcutTriggered(
- deviceId, systemShortcut);
- }
- }
- }
-
- /** Register the keyboard system shortcut listener for a process. */
- @BinderThread
- public void registerKeyboardSystemShortcutListener(IKeyboardSystemShortcutListener listener,
- int pid) {
- synchronized (mKeyboardSystemShortcutListenerRecords) {
- if (mKeyboardSystemShortcutListenerRecords.get(pid) != null) {
- throw new IllegalStateException("The calling process has already registered "
- + "a KeyboardSystemShortcutListener.");
- }
- KeyboardSystemShortcutListenerRecord record = new KeyboardSystemShortcutListenerRecord(
- pid, listener);
- try {
- listener.asBinder().linkToDeath(record, 0);
- } catch (RemoteException ex) {
- throw new RuntimeException(ex);
- }
- mKeyboardSystemShortcutListenerRecords.put(pid, record);
- }
- }
-
- /** Unregister the keyboard system shortcut listener for a process. */
- @BinderThread
- public void unregisterKeyboardSystemShortcutListener(IKeyboardSystemShortcutListener listener,
- int pid) {
- synchronized (mKeyboardSystemShortcutListenerRecords) {
- KeyboardSystemShortcutListenerRecord record =
- mKeyboardSystemShortcutListenerRecords.get(pid);
- if (record == null) {
- throw new IllegalStateException("The calling process has no registered "
- + "KeyboardSystemShortcutListener.");
- }
- if (record.mListener.asBinder() != listener.asBinder()) {
- throw new IllegalStateException("The calling process has a different registered "
- + "KeyboardSystemShortcutListener.");
- }
- record.mListener.asBinder().unlinkToDeath(record, 0);
- mKeyboardSystemShortcutListenerRecords.remove(pid);
- }
- }
-
- private void onKeyboardSystemShortcutListenerDied(int pid) {
- synchronized (mKeyboardSystemShortcutListenerRecords) {
- mKeyboardSystemShortcutListenerRecords.remove(pid);
- }
- }
-
- // A record of a registered keyboard system shortcut listener from one process.
- private class KeyboardSystemShortcutListenerRecord implements IBinder.DeathRecipient {
- public final int mPid;
- public final IKeyboardSystemShortcutListener mListener;
-
- KeyboardSystemShortcutListenerRecord(int pid, IKeyboardSystemShortcutListener listener) {
- mPid = pid;
- mListener = listener;
- }
-
- @Override
- public void binderDied() {
- if (DEBUG) {
- Slog.d(TAG, "Keyboard system shortcut listener for pid " + mPid + " died.");
- }
- onKeyboardSystemShortcutListenerDied(mPid);
- }
-
- public void onKeyboardSystemShortcutTriggered(int deviceId, KeyboardSystemShortcut data) {
- try {
- mListener.onKeyboardSystemShortcutTriggered(deviceId, data.getKeycodes(),
- data.getModifierState(), data.getSystemShortcut());
- } catch (RemoteException ex) {
- Slog.w(TAG, "Failed to notify process " + mPid
- + " that keyboard system shortcut was triggered, assuming it died.", ex);
- binderDied();
- }
- }
- }
-}
diff --git a/services/core/java/com/android/server/notification/NotificationAttentionHelper.java b/services/core/java/com/android/server/notification/NotificationAttentionHelper.java
index 981891669e7c..abb21323f7f0 100644
--- a/services/core/java/com/android/server/notification/NotificationAttentionHelper.java
+++ b/services/core/java/com/android/server/notification/NotificationAttentionHelper.java
@@ -489,6 +489,7 @@ public final class NotificationAttentionHelper {
} else if ((record.getFlags() & Notification.FLAG_INSISTENT) != 0) {
hasValidSound = false;
+ hasValidVibrate = false;
}
}
}
@@ -753,6 +754,13 @@ public final class NotificationAttentionHelper {
// notifying app does not have the VIBRATE permission.
final long identity = Binder.clearCallingIdentity();
try {
+ // Need to explicitly cancel a previously playing vibration
+ // Otherwise a looping vibration will not be stopped when starting a new one.
+ if (mVibrateNotificationKey != null
+ && !mVibrateNotificationKey.equals(record.getKey())) {
+ mVibrateNotificationKey = null;
+ mVibratorHelper.cancelVibration();
+ }
final float scale = getVibrationIntensity(record);
final VibrationEffect scaledEffect = Float.compare(scale, DEFAULT_VOLUME) != 0
? mVibratorHelper.scale(effect, scale) : effect;
diff --git a/services/core/java/com/android/server/policy/ModifierShortcutManager.java b/services/core/java/com/android/server/policy/ModifierShortcutManager.java
index 5a4518606ca6..7ed89728a005 100644
--- a/services/core/java/com/android/server/policy/ModifierShortcutManager.java
+++ b/services/core/java/com/android/server/policy/ModifierShortcutManager.java
@@ -29,8 +29,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Icon;
-import android.hardware.input.InputManager;
-import android.hardware.input.KeyboardSystemShortcut;
+import android.hardware.input.KeyGestureEvent;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -476,7 +475,7 @@ public class ModifierShortcutManager {
+ "keyCode=" + KeyEvent.keyCodeToString(keyCode) + ","
+ " category=" + category + " role=" + role);
}
- notifyKeyboardShortcutTriggered(keyEvent, getSystemShortcutFromIntent(intent));
+ notifyKeyGestureCompleted(keyEvent, getKeyGestureTypeFromIntent(intent));
return true;
} else {
return false;
@@ -497,19 +496,19 @@ public class ModifierShortcutManager {
+ "the activity to which it is registered was not found: "
+ "META+ or SEARCH" + KeyEvent.keyCodeToString(keyCode));
}
- notifyKeyboardShortcutTriggered(keyEvent, getSystemShortcutFromIntent(shortcutIntent));
+ notifyKeyGestureCompleted(keyEvent, getKeyGestureTypeFromIntent(shortcutIntent));
return true;
}
return false;
}
- private void notifyKeyboardShortcutTriggered(KeyEvent event,
- @KeyboardSystemShortcut.SystemShortcut int systemShortcut) {
- if (systemShortcut == KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED) {
+ private void notifyKeyGestureCompleted(KeyEvent event,
+ @KeyGestureEvent.KeyGestureType int gestureType) {
+ if (gestureType == KeyGestureEvent.KEY_GESTURE_TYPE_UNSPECIFIED) {
return;
}
- mInputManagerInternal.notifyKeyboardShortcutTriggered(event.getDeviceId(),
- new int[]{event.getKeyCode()}, event.getMetaState(), systemShortcut);
+ mInputManagerInternal.notifyKeyGestureCompleted(event.getDeviceId(),
+ new int[]{event.getKeyCode()}, event.getMetaState(), gestureType);
}
/**
@@ -710,21 +709,21 @@ public class ModifierShortcutManager {
/**
- * Find Keyboard shortcut event corresponding to intent filter category. Returns
- * {@code SYSTEM_SHORTCUT_UNSPECIFIED if no matching event found}
+ * Find Key gesture type corresponding to intent filter category. Returns
+ * {@code KEY_GESTURE_TYPE_UNSPECIFIED if no matching event found}
*/
- @KeyboardSystemShortcut.SystemShortcut
- private static int getSystemShortcutFromIntent(Intent intent) {
+ @KeyGestureEvent.KeyGestureType
+ private static int getKeyGestureTypeFromIntent(Intent intent) {
Intent selectorIntent = intent.getSelector();
if (selectorIntent != null) {
Set<String> selectorCategories = selectorIntent.getCategories();
if (selectorCategories != null && !selectorCategories.isEmpty()) {
for (String intentCategory : selectorCategories) {
- int systemShortcut = getEventFromSelectorCategory(intentCategory);
- if (systemShortcut == KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED) {
+ int keyGestureType = getKeyGestureTypeFromSelectorCategory(intentCategory);
+ if (keyGestureType == KeyGestureEvent.KEY_GESTURE_TYPE_UNSPECIFIED) {
continue;
}
- return systemShortcut;
+ return keyGestureType;
}
}
}
@@ -733,69 +732,68 @@ public class ModifierShortcutManager {
// so check for that.
String role = intent.getStringExtra(ModifierShortcutManager.EXTRA_ROLE);
if (!TextUtils.isEmpty(role)) {
- return getLogEventFromRole(role);
+ return getKeyGestureTypeFromRole(role);
}
Set<String> intentCategories = intent.getCategories();
if (intentCategories == null || intentCategories.isEmpty()
|| !intentCategories.contains(Intent.CATEGORY_LAUNCHER)) {
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED;
+ return KeyGestureEvent.KEY_GESTURE_TYPE_UNSPECIFIED;
}
if (intent.getComponent() == null) {
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED;
+ return KeyGestureEvent.KEY_GESTURE_TYPE_UNSPECIFIED;
}
// TODO(b/280423320): Add new field package name associated in the
// KeyboardShortcutEvent atom and log it accordingly.
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME;
+ return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION_BY_PACKAGE_NAME;
}
- @KeyboardSystemShortcut.SystemShortcut
- private static int getEventFromSelectorCategory(String category) {
+ @KeyGestureEvent.KeyGestureType
+ private static int getKeyGestureTypeFromSelectorCategory(String category) {
switch (category) {
case Intent.CATEGORY_APP_BROWSER:
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER;
+ return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER;
case Intent.CATEGORY_APP_EMAIL:
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL;
+ return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL;
case Intent.CATEGORY_APP_CONTACTS:
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS;
+ return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS;
case Intent.CATEGORY_APP_CALENDAR:
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR;
+ return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR;
case Intent.CATEGORY_APP_CALCULATOR:
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR;
+ return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR;
case Intent.CATEGORY_APP_MUSIC:
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC;
+ return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC;
case Intent.CATEGORY_APP_MAPS:
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS;
+ return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS;
case Intent.CATEGORY_APP_MESSAGING:
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING;
+ return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING;
case Intent.CATEGORY_APP_GALLERY:
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY;
+ return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_GALLERY;
case Intent.CATEGORY_APP_FILES:
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES;
+ return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FILES;
case Intent.CATEGORY_APP_WEATHER:
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER;
+ return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_WEATHER;
case Intent.CATEGORY_APP_FITNESS:
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS;
+ return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FITNESS;
default:
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED;
+ return KeyGestureEvent.KEY_GESTURE_TYPE_UNSPECIFIED;
}
}
/**
- * Find KeyboardLogEvent corresponding to the provide system role name.
- * Returns {@code null} if no matching event found.
+ * Find KeyGestureType corresponding to the provide system role name.
+ * Returns {@code KEY_GESTURE_TYPE_UNSPECIFIED} if no matching event found.
*/
- @KeyboardSystemShortcut.SystemShortcut
- private static int getLogEventFromRole(String role) {
+ @KeyGestureEvent.KeyGestureType
+ private static int getKeyGestureTypeFromRole(String role) {
if (RoleManager.ROLE_BROWSER.equals(role)) {
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER;
+ return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER;
} else if (RoleManager.ROLE_SMS.equals(role)) {
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING;
+ return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING;
} else {
- Log.w(TAG, "Keyboard shortcut to launch "
- + role + " not supported for logging");
- return KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED;
+ Log.w(TAG, "Keyboard gesture event to launch " + role + " not supported for logging");
+ return KeyGestureEvent.KEY_GESTURE_TYPE_UNSPECIFIED;
}
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 720c1c201158..aa56e8d8eb55 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -139,7 +139,7 @@ import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPlaybackClient;
import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;
import android.hardware.input.InputManager;
-import android.hardware.input.KeyboardSystemShortcut;
+import android.hardware.input.KeyGestureEvent;
import android.media.AudioManager;
import android.media.AudioManagerInternal;
import android.media.AudioSystem;
@@ -1819,7 +1819,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
private void handleShortPressOnHome(KeyEvent event) {
- notifyKeyboardShortcutTriggered(event, KeyboardSystemShortcut.SYSTEM_SHORTCUT_HOME);
+ notifyKeyGestureCompleted(event, KeyGestureEvent.KEY_GESTURE_TYPE_HOME);
// Turn on the connected TV and switch HDMI input if we're a HDMI playback device.
final HdmiControl hdmiControl = getHdmiControl();
@@ -2053,8 +2053,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
switch (mDoubleTapOnHomeBehavior) {
case DOUBLE_TAP_HOME_RECENT_SYSTEM_UI:
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_APP_SWITCH);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH);
mHomeConsumed = true;
toggleRecentApps();
break;
@@ -2082,23 +2082,23 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case LONG_PRESS_HOME_ALL_APPS:
if (mHasFeatureLeanback) {
launchAllAppsAction();
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_ALL_APPS);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS);
} else {
launchAllAppsViaA11y();
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS);
}
break;
case LONG_PRESS_HOME_ASSIST:
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT);
launchAssistAction(null, event.getDeviceId(), event.getEventTime(),
AssistUtils.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS);
break;
case LONG_PRESS_HOME_NOTIFICATION_PANEL:
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL);
toggleNotificationPanel();
break;
default:
@@ -3285,29 +3285,29 @@ public class PhoneWindowManager implements WindowManagerPolicy {
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
};
- private void notifyKeyboardShortcutTriggeredOnActionUp(KeyEvent event,
- @KeyboardSystemShortcut.SystemShortcut int systemShortcut) {
+ private void notifyKeyGestureCompletedOnActionUp(KeyEvent event,
+ @KeyGestureEvent.KeyGestureType int gestureType) {
if (event.getAction() != KeyEvent.ACTION_UP) {
return;
}
- notifyKeyboardShortcutTriggered(event, systemShortcut);
+ notifyKeyGestureCompleted(event, gestureType);
}
- private void notifyKeyboardShortcutTriggeredOnActionDown(KeyEvent event,
- @KeyboardSystemShortcut.SystemShortcut int systemShortcut) {
+ private void notifyKeyGestureCompletedOnActionDown(KeyEvent event,
+ @KeyGestureEvent.KeyGestureType int gestureType) {
if (event.getAction() != KeyEvent.ACTION_DOWN) {
return;
}
- notifyKeyboardShortcutTriggered(event, systemShortcut);
+ notifyKeyGestureCompleted(event, gestureType);
}
- private void notifyKeyboardShortcutTriggered(KeyEvent event,
- @KeyboardSystemShortcut.SystemShortcut int systemShortcut) {
- if (systemShortcut == KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED) {
+ private void notifyKeyGestureCompleted(KeyEvent event,
+ @KeyGestureEvent.KeyGestureType int gestureType) {
+ if (gestureType == KeyGestureEvent.KEY_GESTURE_TYPE_UNSPECIFIED) {
return;
}
- mInputManagerInternal.notifyKeyboardShortcutTriggered(event.getDeviceId(),
- new int[]{event.getKeyCode()}, event.getMetaState(), systemShortcut);
+ mInputManagerInternal.notifyKeyGestureCompleted(event.getDeviceId(),
+ new int[]{event.getKeyCode()}, event.getMetaState(), gestureType);
}
@Override
@@ -3417,8 +3417,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_RECENT_APPS:
if (firstDown) {
showRecentApps(false /* triggeredFromAltTab */);
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_RECENT_APPS);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS);
}
return true;
case KeyEvent.KEYCODE_APP_SWITCH:
@@ -3427,8 +3427,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
preloadRecentApps();
} else if (!down) {
toggleRecentApps();
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_APP_SWITCH);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH);
}
}
return true;
@@ -3437,8 +3437,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD,
deviceId, event.getEventTime(),
AssistUtils.INVOCATION_TYPE_UNKNOWN);
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT);
return true;
}
break;
@@ -3451,16 +3451,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_I:
if (firstDown && event.isMetaPressed()) {
showSystemSettings();
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS);
return true;
}
break;
case KeyEvent.KEYCODE_L:
if (firstDown && event.isMetaPressed()) {
lockNow(null /* options */);
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LOCK_SCREEN);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LOCK_SCREEN);
return true;
}
break;
@@ -3468,12 +3468,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (firstDown && event.isMetaPressed()) {
if (event.isCtrlPressed()) {
sendSystemKeyToStatusBarAsync(event);
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_OPEN_NOTES);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES);
} else {
toggleNotificationPanel();
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL);
}
return true;
}
@@ -3481,8 +3481,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_S:
if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
interceptScreenshotChord(SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/);
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TAKE_SCREENSHOT);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT);
return true;
}
break;
@@ -3495,16 +3495,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} catch (RemoteException e) {
Slog.d(TAG, "Error taking bugreport", e);
}
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT);
return true;
}
}
// fall through
case KeyEvent.KEYCODE_ESCAPE:
if (firstDown && event.isMetaPressed()) {
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_BACK);
injectBackGesture(event.getDownTime());
return true;
}
@@ -3513,8 +3513,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
if (statusbar != null) {
statusbar.moveFocusedTaskToFullscreen(getTargetDisplayIdForKeyEvent(event));
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION);
return true;
}
}
@@ -3524,8 +3524,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
if (statusbar != null) {
statusbar.moveFocusedTaskToDesktop(getTargetDisplayIdForKeyEvent(event));
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_DESKTOP_MODE);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_DESKTOP_MODE);
return true;
}
}
@@ -3535,15 +3535,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (event.isCtrlPressed()) {
moveFocusedTaskToStageSplit(getTargetDisplayIdForKeyEvent(event),
true /* leftOrTop */);
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION);
} else if (event.isAltPressed()) {
setSplitscreenFocus(true /* leftOrTop */);
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS);
} else {
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_BACK);
injectBackGesture(event.getDownTime());
}
return true;
@@ -3554,13 +3554,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (event.isCtrlPressed()) {
moveFocusedTaskToStageSplit(getTargetDisplayIdForKeyEvent(event),
false /* leftOrTop */);
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION);
return true;
} else if (event.isAltPressed()) {
setSplitscreenFocus(false /* leftOrTop */);
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS);
return true;
}
}
@@ -3568,8 +3568,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_SLASH:
if (firstDown && event.isMetaPressed() && !keyguardOn) {
toggleKeyboardShortcutsMenu(event.getDeviceId());
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER);
return true;
}
break;
@@ -3622,31 +3622,31 @@ public class PhoneWindowManager implements WindowManagerPolicy {
intent.putExtra(EXTRA_FROM_BRIGHTNESS_KEY, true);
startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
- int systemShortcut = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN
- ? KeyboardSystemShortcut.SYSTEM_SHORTCUT_BRIGHTNESS_DOWN
- : KeyboardSystemShortcut.SYSTEM_SHORTCUT_BRIGHTNESS_UP;
- notifyKeyboardShortcutTriggered(event, systemShortcut);
+ int gestureType = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN
+ ? KeyGestureEvent.KEY_GESTURE_TYPE_BRIGHTNESS_DOWN
+ : KeyGestureEvent.KEY_GESTURE_TYPE_BRIGHTNESS_UP;
+ notifyKeyGestureCompleted(event, gestureType);
}
return true;
case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN:
if (down) {
mInputManagerInternal.decrementKeyboardBacklight(event.getDeviceId());
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN);
}
return true;
case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP:
if (down) {
mInputManagerInternal.incrementKeyboardBacklight(event.getDeviceId());
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP);
}
return true;
case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE:
// TODO: Add logic
if (!down) {
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE);
}
return true;
case KeyEvent.KEYCODE_VOLUME_UP:
@@ -3673,8 +3673,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (firstDown && !keyguardOn && isUserSetupComplete()) {
if (event.isMetaPressed()) {
showRecentApps(false);
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_RECENT_APPS);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS);
return true;
} else if (mRecentAppsHeldModifiers == 0) {
final int shiftlessModifiers =
@@ -3683,8 +3683,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
shiftlessModifiers, KeyEvent.META_ALT_ON)) {
mRecentAppsHeldModifiers = shiftlessModifiers;
showRecentApps(true);
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_RECENT_APPS);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS);
return true;
}
}
@@ -3697,20 +3697,20 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Message msg = mHandler.obtainMessage(MSG_HANDLE_ALL_APPS);
msg.setAsynchronous(true);
msg.sendToTarget();
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_ALL_APPS);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS);
} else {
launchAllAppsViaA11y();
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS);
}
}
return true;
case KeyEvent.KEYCODE_NOTIFICATION:
if (!down) {
toggleNotificationPanel();
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL);
}
return true;
case KeyEvent.KEYCODE_SEARCH:
@@ -3718,8 +3718,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
switch (mSearchKeyBehavior) {
case SEARCH_KEY_BEHAVIOR_TARGET_ACTIVITY: {
launchTargetSearchActivity();
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_SEARCH);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SEARCH);
return true;
}
case SEARCH_KEY_BEHAVIOR_DEFAULT_SEARCH:
@@ -3732,8 +3732,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (firstDown) {
int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
sendSwitchKeyboardLayout(event, focusedToken, direction);
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LANGUAGE_SWITCH);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LANGUAGE_SWITCH);
return true;
}
break;
@@ -3752,13 +3752,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mPendingCapsLockToggle) {
mInputManagerInternal.toggleCapsLock(event.getDeviceId());
mPendingCapsLockToggle = false;
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK);
} else if (mPendingMetaAction) {
if (!canceled) {
launchAllAppsViaA11y();
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS);
}
mPendingMetaAction = false;
}
@@ -3786,16 +3786,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mPendingCapsLockToggle) {
mInputManagerInternal.toggleCapsLock(event.getDeviceId());
mPendingCapsLockToggle = false;
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK);
return true;
}
}
break;
case KeyEvent.KEYCODE_CAPS_LOCK:
if (!down) {
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK);
}
break;
case KeyEvent.KEYCODE_STYLUS_BUTTON_PRIMARY:
@@ -3809,12 +3809,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (firstDown) {
if (mSettingsKeyBehavior == SETTINGS_KEY_BEHAVIOR_NOTIFICATION_PANEL) {
toggleNotificationPanel();
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL);
} else if (mSettingsKeyBehavior == SETTINGS_KEY_BEHAVIOR_SETTINGS_ACTIVITY) {
showSystemSettings();
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS);
}
}
return true;
@@ -4760,8 +4760,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Handle special keys.
switch (keyCode) {
case KeyEvent.KEYCODE_BACK: {
- notifyKeyboardShortcutTriggeredOnActionUp(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK);
+ notifyKeyGestureCompletedOnActionUp(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_BACK);
if (down) {
// There may have other embedded activities on the same Task. Try to move the
// focus before processing the back event.
@@ -4782,12 +4782,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_MUTE: {
- int systemShortcut = keyCode == KEYCODE_VOLUME_DOWN
- ? KeyboardSystemShortcut.SYSTEM_SHORTCUT_VOLUME_DOWN
+ int gestureType = keyCode == KEYCODE_VOLUME_DOWN
+ ? KeyGestureEvent.KEY_GESTURE_TYPE_VOLUME_DOWN
: keyCode == KEYCODE_VOLUME_UP
- ? KeyboardSystemShortcut.SYSTEM_SHORTCUT_VOLUME_UP
- : KeyboardSystemShortcut.SYSTEM_SHORTCUT_VOLUME_MUTE;
- notifyKeyboardShortcutTriggeredOnActionDown(event, systemShortcut);
+ ? KeyGestureEvent.KEY_GESTURE_TYPE_VOLUME_UP
+ : KeyGestureEvent.KEY_GESTURE_TYPE_VOLUME_MUTE;
+ notifyKeyGestureCompletedOnActionDown(event, gestureType);
if (down) {
sendSystemKeyToStatusBarAsync(event);
@@ -4888,8 +4888,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
case KeyEvent.KEYCODE_TV_POWER: {
- notifyKeyboardShortcutTriggeredOnActionUp(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_POWER);
+ notifyKeyGestureCompletedOnActionUp(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_POWER);
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false; // wake-up will be handled separately
if (down && hdmiControlManager != null) {
@@ -4899,8 +4899,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
case KeyEvent.KEYCODE_POWER: {
- notifyKeyboardShortcutTriggeredOnActionUp(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_POWER);
+ notifyKeyGestureCompletedOnActionUp(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_POWER);
EventLogTags.writeInterceptPower(
KeyEvent.actionToString(event.getAction()),
mPowerKeyHandled ? 1 : 0,
@@ -4923,16 +4923,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
// fall through
case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
- notifyKeyboardShortcutTriggeredOnActionUp(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_NAVIGATION);
+ notifyKeyGestureCompletedOnActionUp(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_NAVIGATION);
result &= ~ACTION_PASS_TO_USER;
interceptSystemNavigationKey(event);
break;
}
case KeyEvent.KEYCODE_SLEEP: {
- notifyKeyboardShortcutTriggeredOnActionUp(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_SLEEP);
+ notifyKeyGestureCompletedOnActionUp(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_SLEEP);
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false;
if (!mPowerManager.isInteractive()) {
@@ -4948,8 +4948,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
case KeyEvent.KEYCODE_SOFT_SLEEP: {
- notifyKeyboardShortcutTriggeredOnActionUp(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_SLEEP);
+ notifyKeyGestureCompletedOnActionUp(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_SLEEP);
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false;
if (!down) {
@@ -4960,8 +4960,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
case KeyEvent.KEYCODE_WAKEUP: {
- notifyKeyboardShortcutTriggeredOnActionUp(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_WAKEUP);
+ notifyKeyGestureCompletedOnActionUp(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_WAKEUP);
result &= ~ACTION_PASS_TO_USER;
isWakeKey = true;
break;
@@ -4970,8 +4970,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_MUTE:
result &= ~ACTION_PASS_TO_USER;
if (down && event.getRepeatCount() == 0) {
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_MUTE);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_MUTE);
toggleMicrophoneMuteFromKey();
}
break;
@@ -4986,8 +4986,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_MEDIA_RECORD:
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
- notifyKeyboardShortcutTriggeredOnActionUp(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_MEDIA_KEY);
+ notifyKeyGestureCompletedOnActionUp(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_MEDIA_KEY);
if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
// If the global session is active pass all media keys to it
// instead of the active window.
@@ -5032,8 +5032,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
0 /* unused */, event.getEventTime() /* eventTime */);
msg.setAsynchronous(true);
msg.sendToTarget();
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT);
}
result &= ~ACTION_PASS_TO_USER;
break;
@@ -5044,8 +5044,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK);
msg.setAsynchronous(true);
msg.sendToTarget();
- notifyKeyboardShortcutTriggered(event,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT);
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT);
}
result &= ~ACTION_PASS_TO_USER;
break;
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 2c734127b7ea..fbf09fe89164 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -1617,8 +1617,7 @@ final class AccessibilityController {
// causing the notifying, or the recents/home window is removed, then we won't need the
// delayed notification anymore.
void onWMTransition(@TransitionType int type, @TransitionFlags int flags) {
- if (Flags.delayNotificationToMagnificationWhenRecentsWindowToFrontTransition()
- && type == WindowManager.TRANSIT_TO_FRONT
+ if (type == WindowManager.TRANSIT_TO_FRONT
&& (flags & TRANSIT_FLAG_IS_RECENTS) != 0) {
// Delay the recents to front transition notification then send after if needed.
mHasDelayedNotificationForRecentsToFrontTransition = true;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 5bb4a8adbd82..121ab2c81e8f 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3771,6 +3771,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
// Shell calls back into Core with the entry bounds to be applied with startWCT.
final Transition enterPipTransition = new Transition(TRANSIT_PIP,
0 /* flags */, getTransitionController(), mWindowManager.mSyncEngine);
+ r.setPictureInPictureParams(params);
enterPipTransition.setPipActivity(r);
r.mAutoEnteringPip = isAutoEnter;
getTransitionController().startCollectOrQueue(enterPipTransition, (deferred) -> {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 3f0c9fd0bfec..434077182aaf 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -4705,6 +4705,15 @@ class Task extends TaskFragment {
// it does not follow the ActivityStarter path.
if (topActivity.shouldBeVisible()) {
mAtmService.resumeAppSwitches();
+ // In pip1, when expanding pip to full-screen, the "behind" task is not
+ // actually becoming invisible since task windowing mode is pinned.
+ if (!isPip2ExperimentEnabled) {
+ final ActivityRecord ar = mAtmService.mLastResumedActivity;
+ if (ar != null && ar.getTask() != null) {
+ mAtmService.takeTaskSnapshot(ar.getTask().mTaskId,
+ true /* updateCache */);
+ }
+ }
}
} else if (isPip2ExperimentEnabled) {
super.setWindowingMode(windowingMode);
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index a86289b317d0..701c3508be8a 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -272,6 +272,10 @@ java_genrule {
"$(location soong_zip) -o $(out) -C $(genDir)/res -D $(genDir)/res",
}
+FLAKY = [
+ "androidx.test.filters.FlakyTest",
+]
+
FLAKY_AND_IGNORED = [
"androidx.test.filters.FlakyTest",
"org.junit.Ignore",
@@ -328,7 +332,7 @@ test_module_config {
base: "FrameworksServicesTests",
test_suites: ["device-tests"],
include_filters: ["com.android.server.recoverysystem."],
- exclude_annotations: ["androidx.test.filters.FlakyTest"],
+ exclude_annotations: FLAKY,
}
// server pm TEST_MAPPING
@@ -357,3 +361,319 @@ test_module_config {
test_suites: ["device-tests"],
include_filters: ["com.android.server.os."],
}
+
+test_module_config {
+ name: "FrameworksServicesTests_presubmit",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+ exclude_annotations: FLAKY_AND_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_com_android_server_job_Presubmit",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.job"],
+ exclude_annotations: [
+ "androidx.test.filters.LargeTest",
+ "androidx.test.filters.FlakyTest",
+ ],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_com_android_server_job",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.job"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_com_android_server_tare_Presubmit",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.tare"],
+ exclude_annotations: FLAKY,
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_com_android_server_tare",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.tare"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_com_android_server_usage_Presubmit",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.usage"],
+ exclude_annotations: FLAKY,
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_com_android_server_usage",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.usage"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_battery_stats",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.am.BatteryStatsServiceTest"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_accessibility_Presubmit",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.accessibility"],
+ exclude_annotations: FLAKY,
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_accessibility",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.accessibility"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_binary_transparency",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.BinaryTransparencyServiceTest"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_pinner_service",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.PinnerServiceTest"],
+ exclude_annotations: ["org.junit.Ignore"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_am_Presubmit",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.am."],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+ exclude_annotations: FLAKY,
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_am",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.am."],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_appop",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.appop"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_audio",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.audio"],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+ exclude_annotations: FLAKY_AND_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_compat",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.compat"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_hdmi_Presubmit",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.hdmi"],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+ exclude_annotations: FLAKY_AND_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_hdmi",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.hdmi"],
+ exclude_annotations: ["org.junit.Ignore"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_integrity",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.integrity."],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_lights",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.lights"],
+ exclude_annotations: FLAKY,
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_locales",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.locales."],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_location_contexthub_Presubmit",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.location.contexthub."],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+ exclude_annotations: FLAKY_AND_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_locksettings",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.locksettings."],
+ exclude_annotations: FLAKY,
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_logcat_Presubmit",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.logcat"],
+ exclude_annotations: FLAKY,
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_logcat",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.logcat"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_net_Presubmit",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.net."],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+ exclude_annotations: FLAKY,
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_om",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.om."],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_pdb",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.pdb.PersistentDataBlockServiceTest"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_pm_dex",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.pm.dex"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_policy_Presubmit",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.policy."],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+ exclude_annotations: FLAKY,
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_policy",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.policy."],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_power",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.power"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_power_hint",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.power.hint"],
+ exclude_annotations: FLAKY,
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_powerstats",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.powerstats"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_rollback",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.rollback"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_uri",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.uri."],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_com_android_server_location_contexthub",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.location.contexthub."],
+ include_annotations: ["android.platform.test.annotations.Postsubmit"],
+ exclude_annotations: FLAKY_AND_IGNORED,
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_usage",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.usage"],
+ exclude_filters: ["com.android.server.usage.StorageStatsServiceTest"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_soundtrigger_middleware",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.soundtrigger_middleware"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_android_server_input",
+ base: "FrameworksServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.input"],
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index a4222ff5650b..d2961bc8a90f 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -79,6 +79,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
@@ -1488,15 +1489,30 @@ public class BiometricServiceTest {
}
@Test
+ @RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS)
public void testCanAuthenticate_whenLockoutTimed() throws Exception {
testCanAuthenticate_whenLockedOut(LockoutTracker.LOCKOUT_TIMED);
}
@Test
+ @RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS)
public void testCanAuthenticate_whenLockoutPermanent() throws Exception {
testCanAuthenticate_whenLockedOut(LockoutTracker.LOCKOUT_PERMANENT);
}
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
+ public void testCanAuthenticate_whenLockoutTimed_returnsLockoutError() throws Exception {
+ testCanAuthenticate_whenLockedOut_returnLockoutError(LockoutTracker.LOCKOUT_TIMED);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
+ public void testCanAuthenticate_whenLockoutPermanent_returnsLockoutError() throws Exception {
+ testCanAuthenticate_whenLockedOut_returnLockoutError(LockoutTracker.LOCKOUT_PERMANENT);
+ }
+
+ @RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS)
private void testCanAuthenticate_whenLockedOut(@LockoutTracker.LockoutMode int lockoutMode)
throws Exception {
// When only biometric is requested, and sensor is strong enough
@@ -1510,6 +1526,21 @@ public class BiometricServiceTest {
invokeCanAuthenticate(mBiometricService, Authenticators.BIOMETRIC_STRONG));
}
+ @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
+ private void testCanAuthenticate_whenLockedOut_returnLockoutError(
+ @LockoutTracker.LockoutMode int lockoutMode)
+ throws Exception {
+ // When only biometric is requested, and sensor is strong enough
+ setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
+
+ when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt()))
+ .thenReturn(lockoutMode);
+
+ // Lockout is not considered an error for BiometricManager#canAuthenticate
+ assertEquals(BiometricManager.BIOMETRIC_ERROR_LOCKOUT,
+ invokeCanAuthenticate(mBiometricService, Authenticators.BIOMETRIC_STRONG));
+ }
+
@Test
@RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
public void testCanAuthenticate_whenMandatoryBiometricsRequested()
@@ -1529,7 +1560,7 @@ public class BiometricServiceTest {
when(mTrustManager.isInSignificantPlace()).thenReturn(true);
- assertEquals(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE,
+ assertEquals(BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE,
invokeCanAuthenticate(mBiometricService, Authenticators.MANDATORY_BIOMETRICS));
}
@@ -1572,7 +1603,7 @@ public class BiometricServiceTest {
setupAuthForOnly(TYPE_CREDENTIAL, Authenticators.DEVICE_CREDENTIAL);
- assertEquals(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE,
+ assertEquals(BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE,
invokeCanAuthenticate(mBiometricService, Authenticators.MANDATORY_BIOMETRICS));
when(mTrustManager.isInSignificantPlace()).thenReturn(true);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
index 240da9fe46bd..4c3a233fdd97 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
@@ -231,7 +231,7 @@ public class PreAuthInfoTest {
@Test
@RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
- public void testMandatoryBiometricsStatus_whenRequirementsNotSatisfiedAndSensorAvailable()
+ public void testMandatoryBiometricsAndStrongBiometricsStatus_whenRequirementsNotSatisfied()
throws Exception {
when(mTrustManager.isInSignificantPlace()).thenReturn(true);
@@ -246,6 +246,24 @@ public class PreAuthInfoTest {
assertThat(preAuthInfo.eligibleSensors).hasSize(1);
}
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
+ public void testMandatoryBiometricsStatus_whenRequirementsNotSatisfiedAndSensorAvailable()
+ throws Exception {
+ when(mTrustManager.isInSignificantPlace()).thenReturn(true);
+
+ final BiometricSensor sensor = getFaceSensor();
+ final PromptInfo promptInfo = new PromptInfo();
+ promptInfo.setAuthenticators(BiometricManager.Authenticators.MANDATORY_BIOMETRICS);
+ final PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager,
+ mSettingObserver, List.of(sensor), 0 /* userId */, promptInfo, TEST_PACKAGE_NAME,
+ false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager);
+
+ assertThat(preAuthInfo.getCanAuthenticateResult()).isEqualTo(
+ BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE);
+ assertThat(preAuthInfo.eligibleSensors).hasSize(0);
+ }
+
private BiometricSensor getFingerprintSensor() {
BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FINGERPRINT,
TYPE_FINGERPRINT, BiometricManager.Authenticators.BIOMETRIC_STRONG,
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java b/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java
index cb75e1ab6cce..14cb22d7698e 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java
@@ -26,16 +26,25 @@ import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
+import android.hardware.biometrics.Flags;
import android.hardware.biometrics.PromptInfo;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import androidx.test.filters.SmallTest;
+import org.junit.Rule;
import org.junit.Test;
@Presubmit
@SmallTest
public class UtilsTest {
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule =
+ DeviceFlagsValueProvider.createCheckFlagsRule();
@Test
public void testCombineAuthenticatorBundles_withKeyDeviceCredential_andKeyAuthenticators() {
@@ -215,7 +224,8 @@ public class UtilsTest {
}
@Test
- public void testBiometricConstantsConversion() {
+ @RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS)
+ public void testBiometricConstantsConversionLegacy() {
final int[][] testCases = {
{BiometricConstants.BIOMETRIC_SUCCESS,
BiometricManager.BIOMETRIC_SUCCESS},
@@ -240,6 +250,34 @@ public class UtilsTest {
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
+ public void testBiometricConstantsConversion() {
+ final int[][] testCases = {
+ {BiometricConstants.BIOMETRIC_SUCCESS,
+ BiometricManager.BIOMETRIC_SUCCESS},
+ {BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS,
+ BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED},
+ {BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL,
+ BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED},
+ {BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
+ BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE},
+ {BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT,
+ BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE},
+ {BiometricConstants.BIOMETRIC_ERROR_LOCKOUT,
+ BiometricManager.BIOMETRIC_ERROR_LOCKOUT},
+ {BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT,
+ BiometricManager.BIOMETRIC_ERROR_LOCKOUT},
+ {BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE,
+ BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE}
+ };
+
+ for (int i = 0; i < testCases.length; i++) {
+ assertEquals(testCases[i][1],
+ Utils.biometricConstantsToBiometricManager(testCases[i][0]));
+ }
+ }
+
+ @Test
public void testGetAuthenticationTypeForResult_getsCorrectType() {
assertEquals(Utils.getAuthenticationTypeForResult(
BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED),
diff --git a/services/tests/servicestests/src/com/android/server/contentprotection/OWNERS b/services/tests/servicestests/src/com/android/server/contentprotection/OWNERS
index 24561c59bba6..3d09da303b0f 100644
--- a/services/tests/servicestests/src/com/android/server/contentprotection/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/contentprotection/OWNERS
@@ -1,3 +1,4 @@
-# Bug component: 544200
+# Bug component: 1040349
+
+include /core/java/android/view/contentprotection/OWNERS
-include /core/java/android/view/contentcapture/OWNERS
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java
index 643ee4aadd80..62e5b9a3dccc 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java
@@ -2007,6 +2007,25 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase {
}
@Test
+ public void testCanInterruptNonRingtoneInsistentBuzzWithOtherBuzzyNotification() {
+ NotificationRecord r = getInsistentBuzzyNotification();
+ mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS);
+ verifyVibrateLooped();
+ assertTrue(r.isInterruptive());
+ assertNotEquals(-1, r.getLastAudiblyAlertedMs());
+ Mockito.reset(mVibrator);
+
+ // New buzzy notification stops previous looping vibration
+ NotificationRecord interrupter = getBuzzyOtherNotification();
+ mAttentionHelper.buzzBeepBlinkLocked(interrupter, DEFAULT_SIGNALS);
+ verifyStopVibrate();
+ // And then vibrates itself
+ verifyVibrate(1);
+ assertTrue(interrupter.isInterruptive());
+ assertNotEquals(-1, interrupter.getLastAudiblyAlertedMs());
+ }
+
+ @Test
public void testRingtoneInsistentBeep_doesNotBlockFutureSoundsOnceStopped() throws Exception {
NotificationChannel ringtoneChannel =
new NotificationChannel("ringtone", "", IMPORTANCE_HIGH);
diff --git a/services/tests/wmtests/src/com/android/server/policy/KeyboardSystemShortcutTests.java b/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
index e26f3e0f699a..8f3adba81be4 100644
--- a/services/tests/wmtests/src/com/android/server/policy/KeyboardSystemShortcutTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
@@ -22,7 +22,7 @@ import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_HOME_ASSIS
import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_HOME_NOTIFICATION_PANEL;
import static com.android.server.policy.PhoneWindowManager.SETTINGS_KEY_BEHAVIOR_NOTIFICATION_PANEL;
-import android.hardware.input.KeyboardSystemShortcut;
+import android.hardware.input.KeyGestureEvent;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
@@ -44,7 +44,7 @@ import org.junit.runner.RunWith;
@Presubmit
@MediumTest
@RunWith(JUnitParamsRunner.class)
-public class KeyboardSystemShortcutTests extends ShortcutKeyTestBase {
+public class KeyGestureEventTests extends ShortcutKeyTestBase {
@Rule
public final CheckFlagsRule mCheckFlagsRule =
@@ -56,315 +56,313 @@ public class KeyboardSystemShortcutTests extends ShortcutKeyTestBase {
private static final int ALT_ON = MODIFIER.get(KeyEvent.KEYCODE_ALT_LEFT);
private static final int CTRL_KEY = KeyEvent.KEYCODE_CTRL_LEFT;
private static final int CTRL_ON = MODIFIER.get(KeyEvent.KEYCODE_CTRL_LEFT);
- private static final int SHIFT_KEY = KeyEvent.KEYCODE_SHIFT_LEFT;
- private static final int SHIFT_ON = MODIFIER.get(KeyEvent.KEYCODE_SHIFT_LEFT);
@Keep
private static Object[][] shortcutTestArguments() {
- // testName, testKeys, expectedSystemShortcut, expectedKey, expectedModifierState
+ // testName, testKeys, expectedKeyGestureType, expectedKey, expectedModifierState
return new Object[][]{
{"Meta + H -> Open Home", new int[]{META_KEY, KeyEvent.KEYCODE_H},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_HOME, KeyEvent.KEYCODE_H, META_ON},
+ KeyGestureEvent.KEY_GESTURE_TYPE_HOME, KeyEvent.KEYCODE_H, META_ON},
{"Meta + Enter -> Open Home", new int[]{META_KEY, KeyEvent.KEYCODE_ENTER},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_HOME, KeyEvent.KEYCODE_ENTER,
+ KeyGestureEvent.KEY_GESTURE_TYPE_HOME, KeyEvent.KEYCODE_ENTER,
META_ON},
{"HOME key -> Open Home", new int[]{KeyEvent.KEYCODE_HOME},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_HOME,
+ KeyGestureEvent.KEY_GESTURE_TYPE_HOME,
KeyEvent.KEYCODE_HOME, 0},
{"RECENT_APPS key -> Open Overview", new int[]{KeyEvent.KEYCODE_RECENT_APPS},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_RECENT_APPS,
+ KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS,
KeyEvent.KEYCODE_RECENT_APPS, 0},
{"Meta + Tab -> Open Overview", new int[]{META_KEY, KeyEvent.KEYCODE_TAB},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_RECENT_APPS, KeyEvent.KEYCODE_TAB,
+ KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS, KeyEvent.KEYCODE_TAB,
META_ON},
{"Alt + Tab -> Open Overview", new int[]{ALT_KEY, KeyEvent.KEYCODE_TAB},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_RECENT_APPS, KeyEvent.KEYCODE_TAB,
+ KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS, KeyEvent.KEYCODE_TAB,
ALT_ON},
{"BACK key -> Go back", new int[]{KeyEvent.KEYCODE_BACK},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK,
+ KeyGestureEvent.KEY_GESTURE_TYPE_BACK,
KeyEvent.KEYCODE_BACK, 0},
{"Meta + Escape -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_ESCAPE},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK, KeyEvent.KEYCODE_ESCAPE,
+ KeyGestureEvent.KEY_GESTURE_TYPE_BACK, KeyEvent.KEYCODE_ESCAPE,
META_ON},
{"Meta + Left arrow -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_DPAD_LEFT},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK, KeyEvent.KEYCODE_DPAD_LEFT,
+ KeyGestureEvent.KEY_GESTURE_TYPE_BACK, KeyEvent.KEYCODE_DPAD_LEFT,
META_ON},
{"Meta + Del -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_DEL},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK, KeyEvent.KEYCODE_DEL, META_ON},
+ KeyGestureEvent.KEY_GESTURE_TYPE_BACK, KeyEvent.KEYCODE_DEL, META_ON},
{"APP_SWITCH key -> Open App switcher", new int[]{KeyEvent.KEYCODE_APP_SWITCH},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_APP_SWITCH,
+ KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH,
KeyEvent.KEYCODE_APP_SWITCH, 0},
{"ASSIST key -> Launch assistant", new int[]{KeyEvent.KEYCODE_ASSIST},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT,
KeyEvent.KEYCODE_ASSIST, 0},
{"Meta + A -> Launch assistant", new int[]{META_KEY, KeyEvent.KEYCODE_A},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT, KeyEvent.KEYCODE_A,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT, KeyEvent.KEYCODE_A,
META_ON},
{"VOICE_ASSIST key -> Launch Voice Assistant",
new int[]{KeyEvent.KEYCODE_VOICE_ASSIST},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT,
KeyEvent.KEYCODE_VOICE_ASSIST, 0},
{"Meta + I -> Launch System Settings", new int[]{META_KEY, KeyEvent.KEYCODE_I},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS,
KeyEvent.KEYCODE_I, META_ON},
{"Meta + N -> Toggle Notification panel", new int[]{META_KEY, KeyEvent.KEYCODE_N},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL,
KeyEvent.KEYCODE_N, META_ON},
{"NOTIFICATION key -> Toggle Notification Panel",
new int[]{KeyEvent.KEYCODE_NOTIFICATION},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL,
KeyEvent.KEYCODE_NOTIFICATION,
0},
{"Meta + Ctrl + S -> Take Screenshot",
new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_S},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TAKE_SCREENSHOT, KeyEvent.KEYCODE_S,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT, KeyEvent.KEYCODE_S,
META_ON | CTRL_ON},
{"Meta + / -> Open Shortcut Helper", new int[]{META_KEY, KeyEvent.KEYCODE_SLASH},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER,
+ KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER,
KeyEvent.KEYCODE_SLASH, META_ON},
{"BRIGHTNESS_UP key -> Increase Brightness",
new int[]{KeyEvent.KEYCODE_BRIGHTNESS_UP},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_BRIGHTNESS_UP,
+ KeyGestureEvent.KEY_GESTURE_TYPE_BRIGHTNESS_UP,
KeyEvent.KEYCODE_BRIGHTNESS_UP, 0},
{"BRIGHTNESS_DOWN key -> Decrease Brightness",
new int[]{KeyEvent.KEYCODE_BRIGHTNESS_DOWN},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_BRIGHTNESS_DOWN,
+ KeyGestureEvent.KEY_GESTURE_TYPE_BRIGHTNESS_DOWN,
KeyEvent.KEYCODE_BRIGHTNESS_DOWN, 0},
{"KEYBOARD_BACKLIGHT_UP key -> Increase Keyboard Backlight",
new int[]{KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP,
+ KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP,
KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP, 0},
{"KEYBOARD_BACKLIGHT_DOWN key -> Decrease Keyboard Backlight",
new int[]{KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN,
+ KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN,
KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN, 0},
{"KEYBOARD_BACKLIGHT_TOGGLE key -> Toggle Keyboard Backlight",
new int[]{KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE,
+ KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE,
KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE, 0},
{"VOLUME_UP key -> Increase Volume", new int[]{KeyEvent.KEYCODE_VOLUME_UP},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_VOLUME_UP,
+ KeyGestureEvent.KEY_GESTURE_TYPE_VOLUME_UP,
KeyEvent.KEYCODE_VOLUME_UP, 0},
{"VOLUME_DOWN key -> Decrease Volume", new int[]{KeyEvent.KEYCODE_VOLUME_DOWN},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_VOLUME_DOWN,
+ KeyGestureEvent.KEY_GESTURE_TYPE_VOLUME_DOWN,
KeyEvent.KEYCODE_VOLUME_DOWN, 0},
{"VOLUME_MUTE key -> Mute Volume", new int[]{KeyEvent.KEYCODE_VOLUME_MUTE},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_VOLUME_MUTE,
+ KeyGestureEvent.KEY_GESTURE_TYPE_VOLUME_MUTE,
KeyEvent.KEYCODE_VOLUME_MUTE, 0},
{"ALL_APPS key -> Open App Drawer in Accessibility mode",
new int[]{KeyEvent.KEYCODE_ALL_APPS},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS,
+ KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS,
KeyEvent.KEYCODE_ALL_APPS, 0},
{"SEARCH key -> Launch Search Activity", new int[]{KeyEvent.KEYCODE_SEARCH},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_SEARCH,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SEARCH,
KeyEvent.KEYCODE_SEARCH, 0},
{"LANGUAGE_SWITCH key -> Switch Keyboard Language",
new int[]{KeyEvent.KEYCODE_LANGUAGE_SWITCH},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LANGUAGE_SWITCH,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LANGUAGE_SWITCH,
KeyEvent.KEYCODE_LANGUAGE_SWITCH, 0},
{"META key -> Open App Drawer in Accessibility mode", new int[]{META_KEY},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS, META_KEY,
+ KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS, META_KEY,
META_ON},
{"Meta + Alt -> Toggle CapsLock", new int[]{META_KEY, ALT_KEY},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK, ALT_KEY,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK, ALT_KEY,
META_ON | ALT_ON},
{"Alt + Meta -> Toggle CapsLock", new int[]{ALT_KEY, META_KEY},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK, META_KEY,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK, META_KEY,
META_ON | ALT_ON},
{"CAPS_LOCK key -> Toggle CapsLock", new int[]{KeyEvent.KEYCODE_CAPS_LOCK},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK,
KeyEvent.KEYCODE_CAPS_LOCK, 0},
{"MUTE key -> Mute System Microphone", new int[]{KeyEvent.KEYCODE_MUTE},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_MUTE, KeyEvent.KEYCODE_MUTE,
+ KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_MUTE, KeyEvent.KEYCODE_MUTE,
0},
{"Meta + Ctrl + DPAD_UP -> Split screen navigation",
new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DPAD_UP},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION,
+ KeyGestureEvent.KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION,
KeyEvent.KEYCODE_DPAD_UP,
META_ON | CTRL_ON},
{"Meta + Ctrl + DPAD_LEFT -> Split screen navigation",
new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DPAD_LEFT},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION,
+ KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION,
KeyEvent.KEYCODE_DPAD_LEFT,
META_ON | CTRL_ON},
{"Meta + Ctrl + DPAD_RIGHT -> Split screen navigation",
new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DPAD_RIGHT},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION,
+ KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION,
KeyEvent.KEYCODE_DPAD_RIGHT,
META_ON | CTRL_ON},
{"Meta + L -> Lock Homescreen", new int[]{META_KEY, KeyEvent.KEYCODE_L},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LOCK_SCREEN, KeyEvent.KEYCODE_L,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LOCK_SCREEN, KeyEvent.KEYCODE_L,
META_ON},
{"Meta + Ctrl + N -> Open Notes", new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_N},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_OPEN_NOTES, KeyEvent.KEYCODE_N,
+ KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES, KeyEvent.KEYCODE_N,
META_ON | CTRL_ON},
{"POWER key -> Toggle Power", new int[]{KeyEvent.KEYCODE_POWER},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_POWER, KeyEvent.KEYCODE_POWER,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_POWER, KeyEvent.KEYCODE_POWER,
0},
{"TV_POWER key -> Toggle Power", new int[]{KeyEvent.KEYCODE_TV_POWER},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_POWER,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_POWER,
KeyEvent.KEYCODE_TV_POWER, 0},
{"SYSTEM_NAVIGATION_DOWN key -> System Navigation",
new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_NAVIGATION,
+ KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_NAVIGATION,
KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN,
0},
{"SYSTEM_NAVIGATION_UP key -> System Navigation",
new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_NAVIGATION,
+ KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_NAVIGATION,
KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP,
0},
{"SYSTEM_NAVIGATION_LEFT key -> System Navigation",
new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_NAVIGATION,
+ KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_NAVIGATION,
KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT,
0},
{"SYSTEM_NAVIGATION_RIGHT key -> System Navigation",
new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_NAVIGATION,
+ KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_NAVIGATION,
KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT, 0},
{"SLEEP key -> System Sleep", new int[]{KeyEvent.KEYCODE_SLEEP},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_SLEEP, KeyEvent.KEYCODE_SLEEP, 0},
+ KeyGestureEvent.KEY_GESTURE_TYPE_SLEEP, KeyEvent.KEYCODE_SLEEP, 0},
{"SOFT_SLEEP key -> System Sleep", new int[]{KeyEvent.KEYCODE_SOFT_SLEEP},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_SLEEP, KeyEvent.KEYCODE_SOFT_SLEEP,
+ KeyGestureEvent.KEY_GESTURE_TYPE_SLEEP, KeyEvent.KEYCODE_SOFT_SLEEP,
0},
{"WAKEUP key -> System Wakeup", new int[]{KeyEvent.KEYCODE_WAKEUP},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_WAKEUP, KeyEvent.KEYCODE_WAKEUP, 0},
+ KeyGestureEvent.KEY_GESTURE_TYPE_WAKEUP, KeyEvent.KEYCODE_WAKEUP, 0},
{"MEDIA_PLAY key -> Media Control", new int[]{KeyEvent.KEYCODE_MEDIA_PLAY},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_MEDIA_KEY,
+ KeyGestureEvent.KEY_GESTURE_TYPE_MEDIA_KEY,
KeyEvent.KEYCODE_MEDIA_PLAY, 0},
{"MEDIA_PAUSE key -> Media Control", new int[]{KeyEvent.KEYCODE_MEDIA_PAUSE},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_MEDIA_KEY,
+ KeyGestureEvent.KEY_GESTURE_TYPE_MEDIA_KEY,
KeyEvent.KEYCODE_MEDIA_PAUSE, 0},
{"MEDIA_PLAY_PAUSE key -> Media Control",
new int[]{KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_MEDIA_KEY,
+ KeyGestureEvent.KEY_GESTURE_TYPE_MEDIA_KEY,
KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, 0},
{"Meta + B -> Launch Default Browser", new int[]{META_KEY, KeyEvent.KEYCODE_B},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER,
KeyEvent.KEYCODE_B, META_ON},
{"EXPLORER key -> Launch Default Browser", new int[]{KeyEvent.KEYCODE_EXPLORER},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER,
KeyEvent.KEYCODE_EXPLORER, 0},
{"Meta + C -> Launch Default Contacts", new int[]{META_KEY, KeyEvent.KEYCODE_C},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS,
KeyEvent.KEYCODE_C, META_ON},
{"CONTACTS key -> Launch Default Contacts", new int[]{KeyEvent.KEYCODE_CONTACTS},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS,
KeyEvent.KEYCODE_CONTACTS, 0},
{"Meta + E -> Launch Default Email", new int[]{META_KEY, KeyEvent.KEYCODE_E},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL,
KeyEvent.KEYCODE_E, META_ON},
{"ENVELOPE key -> Launch Default Email", new int[]{KeyEvent.KEYCODE_ENVELOPE},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL,
KeyEvent.KEYCODE_ENVELOPE, 0},
{"Meta + K -> Launch Default Calendar", new int[]{META_KEY, KeyEvent.KEYCODE_K},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR,
KeyEvent.KEYCODE_K, META_ON},
{"CALENDAR key -> Launch Default Calendar", new int[]{KeyEvent.KEYCODE_CALENDAR},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR,
KeyEvent.KEYCODE_CALENDAR, 0},
{"Meta + P -> Launch Default Music", new int[]{META_KEY, KeyEvent.KEYCODE_P},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC,
KeyEvent.KEYCODE_P, META_ON},
{"MUSIC key -> Launch Default Music", new int[]{KeyEvent.KEYCODE_MUSIC},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC,
KeyEvent.KEYCODE_MUSIC, 0},
{"Meta + U -> Launch Default Calculator", new int[]{META_KEY, KeyEvent.KEYCODE_U},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR,
KeyEvent.KEYCODE_U, META_ON},
{"CALCULATOR key -> Launch Default Calculator",
new int[]{KeyEvent.KEYCODE_CALCULATOR},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR,
KeyEvent.KEYCODE_CALCULATOR, 0},
{"Meta + M -> Launch Default Maps", new int[]{META_KEY, KeyEvent.KEYCODE_M},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS,
KeyEvent.KEYCODE_M, META_ON},
{"Meta + S -> Launch Default Messaging App",
new int[]{META_KEY, KeyEvent.KEYCODE_S},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING,
KeyEvent.KEYCODE_S, META_ON},
{"Meta + Ctrl + DPAD_DOWN -> Enter desktop mode",
new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DPAD_DOWN},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_DESKTOP_MODE,
+ KeyGestureEvent.KEY_GESTURE_TYPE_DESKTOP_MODE,
KeyEvent.KEYCODE_DPAD_DOWN,
META_ON | CTRL_ON}};
}
@Keep
private static Object[][] longPressOnHomeTestArguments() {
- // testName, testKeys, longPressOnHomeBehavior, expectedSystemShortcut, expectedKey,
+ // testName, testKeys, longPressOnHomeBehavior, expectedKeyGestureType, expectedKey,
// expectedModifierState
return new Object[][]{
{"Long press HOME key -> Toggle Notification panel",
new int[]{KeyEvent.KEYCODE_HOME}, LONG_PRESS_HOME_NOTIFICATION_PANEL,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL,
KeyEvent.KEYCODE_HOME, 0},
{"Long press META + ENTER -> Toggle Notification panel",
new int[]{META_KEY, KeyEvent.KEYCODE_ENTER},
LONG_PRESS_HOME_NOTIFICATION_PANEL,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL,
KeyEvent.KEYCODE_ENTER,
META_ON},
{"Long press META + H -> Toggle Notification panel",
new int[]{META_KEY, KeyEvent.KEYCODE_H}, LONG_PRESS_HOME_NOTIFICATION_PANEL,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL,
KeyEvent.KEYCODE_H, META_ON},
{"Long press HOME key -> Launch assistant",
new int[]{KeyEvent.KEYCODE_HOME}, LONG_PRESS_HOME_ASSIST,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT,
KeyEvent.KEYCODE_HOME, 0},
{"Long press META + ENTER -> Launch assistant",
new int[]{META_KEY, KeyEvent.KEYCODE_ENTER}, LONG_PRESS_HOME_ASSIST,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT,
KeyEvent.KEYCODE_ENTER, META_ON},
{"Long press META + H -> Launch assistant",
new int[]{META_KEY, KeyEvent.KEYCODE_H}, LONG_PRESS_HOME_ASSIST,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT, KeyEvent.KEYCODE_H,
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT, KeyEvent.KEYCODE_H,
META_ON},
{"Long press HOME key -> Open App Drawer in Accessibility mode",
new int[]{KeyEvent.KEYCODE_HOME}, LONG_PRESS_HOME_ALL_APPS,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS,
+ KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS,
KeyEvent.KEYCODE_HOME, 0},
{"Long press META + ENTER -> Open App Drawer in Accessibility mode",
new int[]{META_KEY, KeyEvent.KEYCODE_ENTER}, LONG_PRESS_HOME_ALL_APPS,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS,
+ KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS,
KeyEvent.KEYCODE_ENTER, META_ON},
{"Long press META + H -> Open App Drawer in Accessibility mode",
new int[]{META_KEY, KeyEvent.KEYCODE_H},
LONG_PRESS_HOME_ALL_APPS,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS,
+ KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS,
KeyEvent.KEYCODE_H, META_ON}};
}
@Keep
private static Object[][] doubleTapOnHomeTestArguments() {
- // testName, testKeys, doubleTapOnHomeBehavior, expectedSystemShortcut, expectedKey,
+ // testName, testKeys, doubleTapOnHomeBehavior, expectedKeyGestureType, expectedKey,
// expectedModifierState
return new Object[][]{
{"Double tap HOME -> Open App switcher",
new int[]{KeyEvent.KEYCODE_HOME}, DOUBLE_TAP_HOME_RECENT_SYSTEM_UI,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_APP_SWITCH, KeyEvent.KEYCODE_HOME,
+ KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH, KeyEvent.KEYCODE_HOME,
0},
{"Double tap META + ENTER -> Open App switcher",
new int[]{META_KEY, KeyEvent.KEYCODE_ENTER},
DOUBLE_TAP_HOME_RECENT_SYSTEM_UI,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_APP_SWITCH,
+ KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH,
KeyEvent.KEYCODE_ENTER, META_ON},
{"Double tap META + H -> Open App switcher",
new int[]{META_KEY, KeyEvent.KEYCODE_H}, DOUBLE_TAP_HOME_RECENT_SYSTEM_UI,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_APP_SWITCH, KeyEvent.KEYCODE_H,
+ KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH, KeyEvent.KEYCODE_H,
META_ON}};
}
@Keep
private static Object[][] settingsKeyTestArguments() {
- // testName, testKeys, settingsKeyBehavior, expectedSystemShortcut, expectedKey,
+ // testName, testKeys, settingsKeyBehavior, expectedKeyGestureType, expectedKey,
// expectedModifierState
return new Object[][]{
{"SETTINGS key -> Toggle Notification panel", new int[]{KeyEvent.KEYCODE_SETTINGS},
SETTINGS_KEY_BEHAVIOR_NOTIFICATION_PANEL,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL,
KeyEvent.KEYCODE_SETTINGS, 0}};
}
@@ -387,21 +385,21 @@ public class KeyboardSystemShortcutTests extends ShortcutKeyTestBase {
@Test
@Parameters(method = "shortcutTestArguments")
public void testShortcut(String testName, int[] testKeys,
- @KeyboardSystemShortcut.SystemShortcut int expectedSystemShortcut, int expectedKey,
+ @KeyGestureEvent.KeyGestureType int expectedKeyGestureType, int expectedKey,
int expectedModifierState) {
- testShortcutInternal(testName, testKeys, expectedSystemShortcut, expectedKey,
+ testShortcutInternal(testName, testKeys, expectedKeyGestureType, expectedKey,
expectedModifierState);
}
@Test
@Parameters(method = "longPressOnHomeTestArguments")
public void testLongPressOnHome(String testName, int[] testKeys, int longPressOnHomeBehavior,
- @KeyboardSystemShortcut.SystemShortcut int expectedSystemShortcut, int expectedKey,
+ @KeyGestureEvent.KeyGestureType int expectedKeyGestureType, int expectedKey,
int expectedModifierState) {
mPhoneWindowManager.overrideLongPressOnHomeBehavior(longPressOnHomeBehavior);
sendLongPressKeyCombination(testKeys);
- mPhoneWindowManager.assertKeyboardShortcutTriggered(
- new int[]{expectedKey}, expectedModifierState, expectedSystemShortcut,
+ mPhoneWindowManager.assertKeyGestureCompleted(
+ new int[]{expectedKey}, expectedModifierState, expectedKeyGestureType,
"Failed while executing " + testName);
}
@@ -409,23 +407,23 @@ public class KeyboardSystemShortcutTests extends ShortcutKeyTestBase {
@Parameters(method = "doubleTapOnHomeTestArguments")
public void testDoubleTapOnHomeBehavior(String testName, int[] testKeys,
int doubleTapOnHomeBehavior,
- @KeyboardSystemShortcut.SystemShortcut int expectedSystemShortcut, int expectedKey,
+ @KeyGestureEvent.KeyGestureType int expectedKeyGestureType, int expectedKey,
int expectedModifierState) {
mPhoneWindowManager.overriderDoubleTapOnHomeBehavior(doubleTapOnHomeBehavior);
sendKeyCombination(testKeys, 0 /* duration */);
sendKeyCombination(testKeys, 0 /* duration */);
- mPhoneWindowManager.assertKeyboardShortcutTriggered(
- new int[]{expectedKey}, expectedModifierState, expectedSystemShortcut,
+ mPhoneWindowManager.assertKeyGestureCompleted(
+ new int[]{expectedKey}, expectedModifierState, expectedKeyGestureType,
"Failed while executing " + testName);
}
@Test
@Parameters(method = "settingsKeyTestArguments")
public void testSettingsKey(String testName, int[] testKeys, int settingsKeyBehavior,
- @KeyboardSystemShortcut.SystemShortcut int expectedSystemShortcut, int expectedKey,
+ @KeyGestureEvent.KeyGestureType int expectedKeyGestureType, int expectedKey,
int expectedModifierState) {
mPhoneWindowManager.overrideSettingsKeyBehavior(settingsKeyBehavior);
- testShortcutInternal(testName, testKeys, expectedSystemShortcut, expectedKey,
+ testShortcutInternal(testName, testKeys, expectedKeyGestureType, expectedKey,
expectedModifierState);
}
@@ -434,16 +432,16 @@ public class KeyboardSystemShortcutTests extends ShortcutKeyTestBase {
public void testBugreportShortcutPress() {
testShortcutInternal("Meta + Ctrl + Del -> Trigger bug report",
new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DEL},
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT, KeyEvent.KEYCODE_DEL,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT, KeyEvent.KEYCODE_DEL,
META_ON | CTRL_ON);
}
private void testShortcutInternal(String testName, int[] testKeys,
- @KeyboardSystemShortcut.SystemShortcut int expectedSystemShortcut, int expectedKey,
+ @KeyGestureEvent.KeyGestureType int expectedKeyGestureType, int expectedKey,
int expectedModifierState) {
sendKeyCombination(testKeys, 0 /* duration */);
- mPhoneWindowManager.assertKeyboardShortcutTriggered(
- new int[]{expectedKey}, expectedModifierState, expectedSystemShortcut,
+ mPhoneWindowManager.assertKeyGestureCompleted(
+ new int[]{expectedKey}, expectedModifierState, expectedKeyGestureType,
"Failed while executing " + testName);
}
}
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index f9b5c2a6c77f..43b065dbb6a5 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -70,7 +70,6 @@ import android.hardware.SensorPrivacyManager;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.input.InputManager;
-import android.hardware.input.KeyboardSystemShortcut;
import android.media.AudioManagerInternal;
import android.os.Handler;
import android.os.HandlerThread;
@@ -804,11 +803,11 @@ class TestPhoneWindowManager {
Assert.assertEquals(targetActivity, intentCaptor.getValue().getComponent());
}
- void assertKeyboardShortcutTriggered(int[] keycodes, int modifierState, int systemShortcut,
+ void assertKeyGestureCompleted(int[] keycodes, int modifierState, int gestureType,
String errorMsg) {
mTestLooper.dispatchAll();
- verify(mInputManagerInternal, description(errorMsg)).notifyKeyboardShortcutTriggered(
- anyInt(), eq(keycodes), eq(modifierState), eq(systemShortcut));
+ verify(mInputManagerInternal, description(errorMsg)).notifyKeyGestureCompleted(
+ anyInt(), eq(keycodes), eq(modifierState), eq(gestureType));
}
void assertSwitchToTask(int persistentId) throws RemoteException {
diff --git a/telephony/java/android/telephony/satellite/ISatelliteProvisionStateCallback.aidl b/telephony/java/android/telephony/satellite/ISatelliteProvisionStateCallback.aidl
index f981fb1d67c7..5f0d986912a1 100644
--- a/telephony/java/android/telephony/satellite/ISatelliteProvisionStateCallback.aidl
+++ b/telephony/java/android/telephony/satellite/ISatelliteProvisionStateCallback.aidl
@@ -16,6 +16,8 @@
package android.telephony.satellite;
+import android.telephony.satellite.SatelliteSubscriberProvisionStatus;
+
/**
* Interface for satellite provision state callback.
* @hide
@@ -27,4 +29,14 @@ oneway interface ISatelliteProvisionStateCallback {
* @param provisioned True means the service is provisioned and false means it is not.
*/
void onSatelliteProvisionStateChanged(in boolean provisioned);
+
+ /**
+ * Called when the provisioning state of one or more SatelliteSubscriberInfos changes.
+ *
+ * @param satelliteSubscriberProvisionStatus The List contains the latest provisioning states of
+ * the SatelliteSubscriberInfos.
+ * @hide
+ */
+ void onSatelliteSubscriptionProvisionStateChanged(in List<SatelliteSubscriberProvisionStatus>
+ satelliteSubscriberProvisionStatus);
}
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index e657d7faad15..0c983278c1f6 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -1404,6 +1404,16 @@ public final class SatelliteManager {
() -> callback.onSatelliteProvisionStateChanged(
provisioned)));
}
+
+ @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ @Override
+ public void onSatelliteSubscriptionProvisionStateChanged(
+ @NonNull List<SatelliteSubscriberProvisionStatus>
+ satelliteSubscriberProvisionStatus) {
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onSatelliteSubscriptionProvisionStateChanged(
+ satelliteSubscriberProvisionStatus)));
+ }
};
sSatelliteProvisionStateCallbackMap.put(callback, internalCallback);
return telephony.registerForSatelliteProvisionStateChanged(
diff --git a/telephony/java/android/telephony/satellite/SatelliteProvisionStateCallback.java b/telephony/java/android/telephony/satellite/SatelliteProvisionStateCallback.java
index a12952be7620..e8ae0f56ee9e 100644
--- a/telephony/java/android/telephony/satellite/SatelliteProvisionStateCallback.java
+++ b/telephony/java/android/telephony/satellite/SatelliteProvisionStateCallback.java
@@ -17,10 +17,13 @@
package android.telephony.satellite;
import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
import com.android.internal.telephony.flags.Flags;
+import java.util.List;
+
/**
* A callback class for monitoring satellite provision state change events.
*
@@ -39,4 +42,16 @@ public interface SatelliteProvisionStateCallback {
*/
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
void onSatelliteProvisionStateChanged(boolean provisioned);
+
+ /**
+ * Called when the provisioning state of one or more SatelliteSubscriberInfos changes.
+ *
+ * @param satelliteSubscriberProvisionStatus The List contains the latest provisioning states
+ * of the SatelliteSubscriberInfos.
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ default void onSatelliteSubscriptionProvisionStateChanged(
+ @NonNull List<SatelliteSubscriberProvisionStatus>
+ satelliteSubscriberProvisionStatus) {};
}
diff --git a/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.aidl b/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.aidl
new file mode 100644
index 000000000000..80de77905f80
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2024, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.satellite;
+
+parcelable SatelliteSubscriberProvisionStatus; \ No newline at end of file
diff --git a/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java b/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java
new file mode 100644
index 000000000000..e3d619ea0fc8
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.satellite;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.telephony.flags.Flags;
+
+import java.util.Objects;
+
+/**
+ * Represents the provisioning state of SatelliteSubscriberInfo.
+ *
+ * @hide
+ */
+@FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+public class SatelliteSubscriberProvisionStatus implements Parcelable {
+ private SatelliteSubscriberInfo mSubscriberInfo;
+ /** {@code true} mean the satellite subscriber is provisioned, {@code false} otherwise. */
+ private boolean mProvisionStatus;
+
+ public SatelliteSubscriberProvisionStatus(@NonNull Builder builder) {
+ mSubscriberInfo = builder.mSubscriberInfo;
+ mProvisionStatus = builder.mProvisionStatus;
+ }
+
+ /**
+ * Builder class for constructing SatelliteSubscriberProvisionStatus objects
+ *
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ public static class Builder {
+ private SatelliteSubscriberInfo mSubscriberInfo;
+ private boolean mProvisionStatus;
+
+ /**
+ * Set the SatelliteSubscriberInfo and returns the Builder class.
+ * @hide
+ */
+ public Builder setSatelliteSubscriberInfo(SatelliteSubscriberInfo satelliteSubscriberInfo) {
+ mSubscriberInfo = satelliteSubscriberInfo;
+ return this;
+ }
+
+ /**
+ * Set the SatelliteSubscriberInfo's provisionStatus and returns the Builder class.
+ * @hide
+ */
+ @NonNull
+ public Builder setProvisionStatus(boolean provisionStatus) {
+ mProvisionStatus = provisionStatus;
+ return this;
+ }
+
+ /**
+ * Returns SatelliteSubscriberProvisionStatus object.
+ * @hide
+ */
+ @NonNull
+ public SatelliteSubscriberProvisionStatus build() {
+ return new SatelliteSubscriberProvisionStatus(this);
+ }
+ }
+
+ private SatelliteSubscriberProvisionStatus(Parcel in) {
+ readFromParcel(in);
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ mSubscriberInfo.writeToParcel(out, flags);
+ out.writeBoolean(mProvisionStatus);
+ }
+
+ @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ public static final @android.annotation.NonNull Creator<SatelliteSubscriberProvisionStatus>
+ CREATOR =
+ new Creator<SatelliteSubscriberProvisionStatus>() {
+ @Override
+ public SatelliteSubscriberProvisionStatus createFromParcel(Parcel in) {
+ return new SatelliteSubscriberProvisionStatus(in);
+ }
+
+ @Override
+ public SatelliteSubscriberProvisionStatus[] newArray(int size) {
+ return new SatelliteSubscriberProvisionStatus[size];
+ }
+ };
+
+ /**
+ * @hide
+ */
+ @Override
+ @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * SatelliteSubscriberInfo that has a provisioning state.
+ * @return SatelliteSubscriberInfo.
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ public @NonNull SatelliteSubscriberInfo getSatelliteSubscriberInfo() {
+ return mSubscriberInfo;
+ }
+
+ /**
+ * SatelliteSubscriberInfo's provisioning state.
+ * @return {@code true} means provisioning. {@code false} means deprovisioning.
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ public @NonNull boolean getProvisionStatus() {
+ return mProvisionStatus;
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("SatelliteSubscriberInfo:");
+ sb.append(mSubscriberInfo);
+ sb.append(",");
+
+ sb.append("ProvisionStatus:");
+ sb.append(mProvisionStatus);
+ return sb.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSubscriberInfo, mProvisionStatus);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SatelliteSubscriberProvisionStatus)) return false;
+ SatelliteSubscriberProvisionStatus that = (SatelliteSubscriberProvisionStatus) o;
+ return Objects.equals(mSubscriberInfo, that.mSubscriberInfo)
+ && mProvisionStatus == that.mProvisionStatus;
+ }
+
+ private void readFromParcel(Parcel in) {
+ mSubscriberInfo = in.readParcelable(SatelliteSubscriberInfo.class.getClassLoader(),
+ SatelliteSubscriberInfo.class);
+ mProvisionStatus = in.readBoolean();
+ }
+}
diff --git a/tests/Input/src/android/hardware/input/KeyboardSystemShortcutListenerTest.kt b/tests/Input/src/android/hardware/input/KeyGestureEventListenerTest.kt
index 24d7291bec87..14aac6637d4f 100644
--- a/tests/Input/src/android/hardware/input/KeyboardSystemShortcutListenerTest.kt
+++ b/tests/Input/src/android/hardware/input/KeyGestureEventListenerTest.kt
@@ -42,21 +42,22 @@ import kotlin.test.assertNull
import kotlin.test.fail
/**
- * Tests for [InputManager.KeyboardSystemShortcutListener].
+ * Tests for [InputManager.KeyGestureEventListener].
*
* Build/Install/Run:
- * atest InputTests:KeyboardSystemShortcutListenerTest
+ * atest InputTests:KeyGestureEventListenerTest
*/
@Presubmit
@RunWith(MockitoJUnitRunner::class)
-class KeyboardSystemShortcutListenerTest {
+class KeyGestureEventListenerTest {
companion object {
const val DEVICE_ID = 1
- val HOME_SHORTCUT = KeyboardSystemShortcut(
+ val HOME_GESTURE_EVENT = KeyGestureEvent(
+ DEVICE_ID,
intArrayOf(KeyEvent.KEYCODE_H),
KeyEvent.META_META_ON or KeyEvent.META_META_LEFT_ON,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_HOME
+ KeyGestureEvent.KEY_GESTURE_TYPE_HOME
)
}
@@ -65,7 +66,7 @@ class KeyboardSystemShortcutListenerTest {
private val testLooper = TestLooper()
private val executor = HandlerExecutor(Handler(testLooper.looper))
- private var registeredListener: IKeyboardSystemShortcutListener? = null
+ private var registeredListener: IKeyGestureEventListener? = null
private lateinit var context: Context
private lateinit var inputManager: InputManager
private lateinit var inputManagerGlobalSession: InputManagerGlobal.TestSession
@@ -81,28 +82,28 @@ class KeyboardSystemShortcutListenerTest {
`when`(context.getSystemService(Mockito.eq(Context.INPUT_SERVICE)))
.thenReturn(inputManager)
- // Handle keyboard system shortcut listener registration.
+ // Handle key gesture event listener registration.
doAnswer {
- val listener = it.getArgument(0) as IKeyboardSystemShortcutListener
+ val listener = it.getArgument(0) as IKeyGestureEventListener
if (registeredListener != null &&
registeredListener!!.asBinder() != listener.asBinder()) {
- // There can only be one registered keyboard system shortcut listener per process.
+ // There can only be one registered key gesture event listener per process.
fail("Trying to register a new listener when one already exists")
}
registeredListener = listener
null
- }.`when`(iInputManagerMock).registerKeyboardSystemShortcutListener(any())
+ }.`when`(iInputManagerMock).registerKeyGestureEventListener(any())
- // Handle keyboard system shortcut listener being unregistered.
+ // Handle key gesture event listener being unregistered.
doAnswer {
- val listener = it.getArgument(0) as IKeyboardSystemShortcutListener
+ val listener = it.getArgument(0) as IKeyGestureEventListener
if (registeredListener == null ||
registeredListener!!.asBinder() != listener.asBinder()) {
fail("Trying to unregister a listener that is not registered")
}
registeredListener = null
null
- }.`when`(iInputManagerMock).unregisterKeyboardSystemShortcutListener(any())
+ }.`when`(iInputManagerMock).unregisterKeyGestureEventListener(any())
}
@After
@@ -112,29 +113,28 @@ class KeyboardSystemShortcutListenerTest {
}
}
- private fun notifyKeyboardSystemShortcutTriggered(id: Int, shortcut: KeyboardSystemShortcut) {
- registeredListener!!.onKeyboardSystemShortcutTriggered(
- id,
- shortcut.keycodes,
- shortcut.modifierState,
- shortcut.systemShortcut
+ private fun notifyKeyGestureEvent(event: KeyGestureEvent) {
+ registeredListener!!.onKeyGestureEvent(
+ event.deviceId,
+ event.keycodes,
+ event.modifierState,
+ event.keyGestureType
)
}
@Test
- fun testListenerHasCorrectSystemShortcutNotified() {
+ fun testListenerHasCorrectGestureNotified() {
var callbackCount = 0
- // Add a keyboard system shortcut listener
- inputManager.registerKeyboardSystemShortcutListener(executor) {
- deviceId: Int, systemShortcut: KeyboardSystemShortcut ->
- assertEquals(DEVICE_ID, deviceId)
- assertEquals(HOME_SHORTCUT, systemShortcut)
+ // Add a key gesture event listener
+ inputManager.registerKeyGestureEventListener(executor) {
+ event: KeyGestureEvent ->
+ assertEquals(HOME_GESTURE_EVENT, event)
callbackCount++
}
- // Notifying keyboard system shortcut triggered will notify the listener.
- notifyKeyboardSystemShortcutTriggered(DEVICE_ID, HOME_SHORTCUT)
+ // Notifying key gesture event will notify the listener.
+ notifyKeyGestureEvent(HOME_GESTURE_EVENT)
testLooper.dispatchNext()
assertEquals(1, callbackCount)
}
@@ -142,34 +142,34 @@ class KeyboardSystemShortcutListenerTest {
@Test
fun testAddingListenersRegistersInternalCallbackListener() {
// Set up two callbacks.
- val callback1 = InputManager.KeyboardSystemShortcutListener {_, _ -> }
- val callback2 = InputManager.KeyboardSystemShortcutListener {_, _ -> }
+ val callback1 = InputManager.KeyGestureEventListener { _ -> }
+ val callback2 = InputManager.KeyGestureEventListener { _ -> }
assertNull(registeredListener)
// Adding the listener should register the callback with InputManagerService.
- inputManager.registerKeyboardSystemShortcutListener(executor, callback1)
+ inputManager.registerKeyGestureEventListener(executor, callback1)
assertNotNull(registeredListener)
// Adding another listener should not register new internal listener.
val currListener = registeredListener
- inputManager.registerKeyboardSystemShortcutListener(executor, callback2)
+ inputManager.registerKeyGestureEventListener(executor, callback2)
assertEquals(currListener, registeredListener)
}
@Test
fun testRemovingListenersUnregistersInternalCallbackListener() {
// Set up two callbacks.
- val callback1 = InputManager.KeyboardSystemShortcutListener {_, _ -> }
- val callback2 = InputManager.KeyboardSystemShortcutListener {_, _ -> }
+ val callback1 = InputManager.KeyGestureEventListener { _ -> }
+ val callback2 = InputManager.KeyGestureEventListener { _ -> }
- inputManager.registerKeyboardSystemShortcutListener(executor, callback1)
- inputManager.registerKeyboardSystemShortcutListener(executor, callback2)
+ inputManager.registerKeyGestureEventListener(executor, callback1)
+ inputManager.registerKeyGestureEventListener(executor, callback2)
// Only removing all listeners should remove the internal callback
- inputManager.unregisterKeyboardSystemShortcutListener(callback1)
+ inputManager.unregisterKeyGestureEventListener(callback1)
assertNotNull(registeredListener)
- inputManager.unregisterKeyboardSystemShortcutListener(callback2)
+ inputManager.unregisterKeyGestureEventListener(callback2)
assertNull(registeredListener)
}
@@ -178,23 +178,23 @@ class KeyboardSystemShortcutListenerTest {
// Set up two callbacks.
var callbackCount1 = 0
var callbackCount2 = 0
- val callback1 = InputManager.KeyboardSystemShortcutListener { _, _ -> callbackCount1++ }
- val callback2 = InputManager.KeyboardSystemShortcutListener { _, _ -> callbackCount2++ }
+ val callback1 = InputManager.KeyGestureEventListener { _ -> callbackCount1++ }
+ val callback2 = InputManager.KeyGestureEventListener { _ -> callbackCount2++ }
- // Add both keyboard system shortcut listeners
- inputManager.registerKeyboardSystemShortcutListener(executor, callback1)
- inputManager.registerKeyboardSystemShortcutListener(executor, callback2)
+ // Add both key gesture event listeners
+ inputManager.registerKeyGestureEventListener(executor, callback1)
+ inputManager.registerKeyGestureEventListener(executor, callback2)
- // Notifying keyboard system shortcut triggered, should notify both the callbacks.
- notifyKeyboardSystemShortcutTriggered(DEVICE_ID, HOME_SHORTCUT)
+ // Notifying key gesture event, should notify both the callbacks.
+ notifyKeyGestureEvent(HOME_GESTURE_EVENT)
testLooper.dispatchAll()
assertEquals(1, callbackCount1)
assertEquals(1, callbackCount2)
- inputManager.unregisterKeyboardSystemShortcutListener(callback2)
- // Notifying keyboard system shortcut triggered, should still trigger callback1 but not
+ inputManager.unregisterKeyGestureEventListener(callback2)
+ // Notifying key gesture event, should still trigger callback1 but not
// callback2.
- notifyKeyboardSystemShortcutTriggered(DEVICE_ID, HOME_SHORTCUT)
+ notifyKeyGestureEvent(HOME_GESTURE_EVENT)
testLooper.dispatchAll()
assertEquals(2, callbackCount1)
assertEquals(1, callbackCount2)
diff --git a/tests/Input/src/com/android/server/input/KeyboardShortcutCallbackHandlerTests.kt b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
index 5a40a1c8201e..3f611e0ead53 100644
--- a/tests/Input/src/com/android/server/input/KeyboardShortcutCallbackHandlerTests.kt
+++ b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
@@ -18,8 +18,8 @@ package com.android.server.input
import android.content.Context
import android.content.ContextWrapper
-import android.hardware.input.IKeyboardSystemShortcutListener
-import android.hardware.input.KeyboardSystemShortcut
+import android.hardware.input.IKeyGestureEventListener
+import android.hardware.input.KeyGestureEvent
import android.platform.test.annotations.Presubmit
import android.view.KeyEvent
import androidx.test.core.app.ApplicationProvider
@@ -32,65 +32,65 @@ import org.mockito.Mockito
import org.mockito.junit.MockitoJUnit
/**
- * Tests for {@link KeyboardShortcutCallbackHandler}.
+ * Tests for {@link KeyGestureController}.
*
* Build/Install/Run:
- * atest InputTests:KeyboardShortcutCallbackHandlerTests
+ * atest InputTests:KeyGestureControllerTests
*/
@Presubmit
-class KeyboardShortcutCallbackHandlerTests {
+class KeyGestureControllerTests {
companion object {
val DEVICE_ID = 1
- val HOME_SHORTCUT = KeyboardSystemShortcut(
+ val HOME_GESTURE_EVENT = KeyGestureEvent(
+ DEVICE_ID,
intArrayOf(KeyEvent.KEYCODE_H),
KeyEvent.META_META_ON or KeyEvent.META_META_LEFT_ON,
- KeyboardSystemShortcut.SYSTEM_SHORTCUT_HOME
+ KeyGestureEvent.KEY_GESTURE_TYPE_HOME
)
}
@get:Rule
val rule = MockitoJUnit.rule()!!
- private lateinit var keyboardShortcutCallbackHandler: KeyboardShortcutCallbackHandler
+ private lateinit var keyGestureController: KeyGestureController
private lateinit var context: Context
- private var lastShortcut: KeyboardSystemShortcut? = null
+ private var lastEvent: KeyGestureEvent? = null
@Before
fun setup() {
context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
- keyboardShortcutCallbackHandler = KeyboardShortcutCallbackHandler()
+ keyGestureController = KeyGestureController()
}
@Test
- fun testKeyboardSystemShortcutTriggered_registerUnregisterListener() {
- val listener = KeyboardSystemShortcutListener()
+ fun testKeyGestureEvent_registerUnregisterListener() {
+ val listener = KeyGestureEventListener()
- // Register keyboard system shortcut listener
- keyboardShortcutCallbackHandler.registerKeyboardSystemShortcutListener(listener, 0)
- keyboardShortcutCallbackHandler.onKeyboardSystemShortcutTriggered(DEVICE_ID, HOME_SHORTCUT)
+ // Register key gesture event listener
+ keyGestureController.registerKeyGestureEventListener(listener, 0)
+ keyGestureController.onKeyGestureEvent(HOME_GESTURE_EVENT)
assertEquals(
- "Listener should get callback on keyboard system shortcut triggered",
- HOME_SHORTCUT,
- lastShortcut!!
+ "Listener should get callback on key gesture event",
+ HOME_GESTURE_EVENT,
+ lastEvent!!
)
// Unregister listener
- lastShortcut = null
- keyboardShortcutCallbackHandler.unregisterKeyboardSystemShortcutListener(listener, 0)
- keyboardShortcutCallbackHandler.onKeyboardSystemShortcutTriggered(DEVICE_ID, HOME_SHORTCUT)
- assertNull("Listener should not get callback after being unregistered", lastShortcut)
+ lastEvent = null
+ keyGestureController.unregisterKeyGestureEventListener(listener, 0)
+ keyGestureController.onKeyGestureEvent(HOME_GESTURE_EVENT)
+ assertNull("Listener should not get callback after being unregistered", lastEvent)
}
- inner class KeyboardSystemShortcutListener : IKeyboardSystemShortcutListener.Stub() {
- override fun onKeyboardSystemShortcutTriggered(
+ inner class KeyGestureEventListener : IKeyGestureEventListener.Stub() {
+ override fun onKeyGestureEvent(
deviceId: Int,
keycodes: IntArray,
modifierState: Int,
- shortcut: Int
+ gestureType: Int
) {
- assertEquals(DEVICE_ID, deviceId)
- lastShortcut = KeyboardSystemShortcut(keycodes, modifierState, shortcut)
+ lastEvent = KeyGestureEvent(deviceId, keycodes, modifierState, gestureType)
}
}
} \ No newline at end of file
diff --git a/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java
index 5a48327e7576..9657225588b7 100644
--- a/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java
@@ -214,6 +214,13 @@ public class LegacyProtoLogImplTest {
verify(mReader, never()).getViewerString(anyLong());
}
+ @Test
+ public void loadViewerConfigOnLogcatGroupRegistration() {
+ TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true);
+ mProtoLog.registerGroups(TestProtoLogGroup.TEST_GROUP);
+ verify(mReader).loadViewerConfig(any(), any());
+ }
+
private static class ProtoLogData {
Long mMessageHash = null;
Long mElapsedTime = null;
diff --git a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostSyncTest.java b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostSyncTest.java
index 359eb35384c7..5012c235a2a5 100644
--- a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostSyncTest.java
+++ b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostSyncTest.java
@@ -84,6 +84,7 @@ public class SurfaceControlViewHostSyncTest extends Activity implements SurfaceH
content.addView(enableSyncButton,
new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.RIGHT | Gravity.BOTTOM));
+ content.setFitsSystemWindows(true);
setContentView(content);
mSv.setZOrderOnTop(false);
diff --git a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java
index 73e01634709e..4119ea2c73c3 100644
--- a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java
+++ b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java
@@ -37,6 +37,7 @@ public class SurfaceControlViewHostTest extends Activity implements SurfaceHolde
protected void onCreate(Bundle savedInstanceState) {
FrameLayout content = new FrameLayout(this);
+ content.setFitsSystemWindows(true);
super.onCreate(savedInstanceState);
mView = new SurfaceView(this);
content.addView(mView, new FrameLayout.LayoutParams(
diff --git a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java
index ac7dc9e2f31f..528706860b31 100644
--- a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java
+++ b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java
@@ -88,6 +88,7 @@ public class SurfaceInputTestActivity extends Activity {
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout content = new LinearLayout(this);
+ content.setFitsSystemWindows(true);
mLocalSurfaceView = new SurfaceView(this);
content.addView(mLocalSurfaceView, new LinearLayout.LayoutParams(
500, 500, Gravity.CENTER_HORIZONTAL | Gravity.TOP));