summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt2
-rw-r--r--core/api/test-current.txt1
-rw-r--r--core/java/android/app/Notification.java68
-rw-r--r--core/java/android/content/ContentCaptureOptions.java40
-rw-r--r--core/java/android/content/ContentProvider.java2
-rw-r--r--core/java/android/content/pm/PackageInstaller.java211
-rw-r--r--core/java/android/hardware/biometrics/AuthenticateOptions.java77
-rw-r--r--core/java/android/hardware/display/DisplayManager.java9
-rw-r--r--core/java/android/hardware/face/FaceAuthenticateOptions.aidl19
-rw-r--r--core/java/android/hardware/face/FaceAuthenticateOptions.java624
-rw-r--r--core/java/android/hardware/face/FaceManager.java39
-rw-r--r--core/java/android/hardware/face/IFaceService.aidl11
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.aidl19
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.java447
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintManager.java40
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintService.aidl10
-rw-r--r--core/java/android/view/KeyEvent.java134
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureContext.java13
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureManager.java44
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureSession.java12
-rw-r--r--core/java/android/view/contentcapture/MainContentCaptureSession.java12
-rw-r--r--core/java/android/view/textclassifier/TextLinks.java2
-rw-r--r--core/java/android/widget/RemoteViews.java4
-rw-r--r--core/tests/coretests/src/android/hardware/face/FaceManagerTest.java151
-rw-r--r--core/tests/coretests/src/android/hardware/face/OWNERS1
-rw-r--r--core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java152
-rw-r--r--core/tests/coretests/src/android/hardware/fingerprint/OWNERS1
-rw-r--r--core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java17
-rw-r--r--graphics/java/android/graphics/Gainmap.java2
-rw-r--r--libs/WindowManager/Shell/Android.bp1
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background.xml21
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml31
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background.xml22
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml32
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background.xml23
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml34
-rw-r--r--libs/WindowManager/Shell/res/layout/compat_mode_hint.xml6
-rw-r--r--libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml2
-rw-r--r--libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml8
-rw-r--r--libs/WindowManager/Shell/res/values/dimen.xml21
-rw-r--r--libs/WindowManager/Shell/res/values/styles.xml25
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesNavBarGestureTracker.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropConstants.java27
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java2
-rw-r--r--libs/hwui/hwui/Bitmap.cpp2
-rw-r--r--media/java/android/media/RingtoneManager.java2
-rw-r--r--packages/LocalTransport/src/com/android/localtransport/LocalTransport.java3
-rw-r--r--packages/SettingsLib/res/values/styles.xml4
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java12
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java61
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java13
-rw-r--r--packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/devicepolicy/DevicePolicyManagerExt.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/data/model/BacklightModel.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt100
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManager.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt66
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt25
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt47
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt167
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java166
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java82
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt28
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt93
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt191
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManagerTest.kt9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt108
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt83
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt94
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt130
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt112
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java20
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt9
-rw-r--r--services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java2
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java30
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java12
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceService.java34
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java13
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java26
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java23
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java24
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java1
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java3
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java3
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java42
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java3
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java9
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java10
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java119
-rw-r--r--services/core/java/com/android/server/wm/AsyncRotationController.java28
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java3
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfiguration.java15
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java27
-rw-r--r--services/core/java/com/android/server/wm/LetterboxUiController.java40
-rw-r--r--services/core/java/com/android/server/wm/Task.java5
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java52
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfaceController.java5
-rw-r--r--services/tests/mockingservicestests/src/android/hardware/face/FaceManagerTest.java86
-rw-r--r--services/tests/mockingservicestests/src/android/hardware/fingerprint/FingerprintManagerTest.java88
-rw-r--r--services/tests/mockingservicestests/src/android/hardware/fingerprint/OWNERS2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java41
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java2
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java13
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java42
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java12
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TransitionTests.java7
-rw-r--r--telecomm/java/android/telecom/CallControl.java32
-rw-r--r--telecomm/java/android/telecom/CallEventCallback.java14
-rw-r--r--telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java20
-rw-r--r--telecomm/java/com/android/internal/telecom/ICallControl.aidl2
-rw-r--r--telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl3
-rw-r--r--tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java3
-rw-r--r--tests/SilkFX/assets/gainmaps/granddam.jpgbin0 -> 1830308 bytes
-rw-r--r--tests/SilkFX/assets/gainmaps/lightbulb.jpgbin0 -> 2757109 bytes
-rw-r--r--tests/SilkFX/assets/gainmaps/porsche911.jpgbin0 -> 2869087 bytes
150 files changed, 3736 insertions, 1584 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index a7f69374ff00..9955112649d3 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -42056,6 +42056,7 @@ package android.telecom {
method public void disconnect(@NonNull android.telecom.DisconnectCause, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
method @NonNull public android.os.ParcelUuid getCallId();
method public void requestCallEndpointChange(@NonNull android.telecom.CallEndpoint, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
+ method public void sendEvent(@NonNull String, @NonNull android.os.Bundle);
method public void setActive(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
method public void setInactive(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
method public void startCallStreaming(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
@@ -42102,6 +42103,7 @@ package android.telecom {
method public void onAvailableCallEndpointsChanged(@NonNull java.util.List<android.telecom.CallEndpoint>);
method public void onCallEndpointChanged(@NonNull android.telecom.CallEndpoint);
method public void onCallStreamingFailed(int);
+ method public void onEvent(@NonNull String, @NonNull android.os.Bundle);
method public void onMuteStateChanged(boolean);
}
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 675324fe6c28..def3fa93ce3c 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1444,6 +1444,7 @@ package android.hardware.display {
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setUserDisabledHdrTypes(@NonNull int[]);
method @RequiresPermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) public boolean shouldAlwaysRespectAppRequestedMode();
field public static final String DISPLAY_CATEGORY_REAR = "android.hardware.display.category.REAR";
+ field public static final String HDR_OUTPUT_CONTROL_FLAG = "enable_hdr_output_control";
field public static final int SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS = 2; // 0x2
field public static final int SWITCHING_TYPE_NONE = 0; // 0x0
field public static final int SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY = 3; // 0x3
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 87c77c2e8602..ef5cd9334be7 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -5249,17 +5249,17 @@ public class Notification implements Parcelable
boolean hasSecondLine = showProgress;
if (p.hasTitle()) {
contentView.setViewVisibility(p.mTitleViewId, View.VISIBLE);
- contentView.setTextViewText(p.mTitleViewId, processTextSpans(p.title));
+ contentView.setTextViewText(p.mTitleViewId, processTextSpans(p.mTitle));
setTextViewColorPrimary(contentView, p.mTitleViewId, p);
} else if (p.mTitleViewId != R.id.title) {
// This alternate title view ID is not cleared by resetStandardTemplate
contentView.setViewVisibility(p.mTitleViewId, View.GONE);
contentView.setTextViewText(p.mTitleViewId, null);
}
- if (p.text != null && p.text.length() != 0
+ if (p.mText != null && p.mText.length() != 0
&& (!showProgress || p.mAllowTextWithProgress)) {
contentView.setViewVisibility(p.mTextViewId, View.VISIBLE);
- contentView.setTextViewText(p.mTextViewId, processTextSpans(p.text));
+ contentView.setTextViewText(p.mTextViewId, processTextSpans(p.mText));
setTextViewColorSecondary(contentView, p.mTextViewId, p);
hasSecondLine = true;
} else if (p.mTextViewId != R.id.text) {
@@ -5533,20 +5533,20 @@ public class Notification implements Parcelable
if (p.mHideSubText) {
return false;
}
- CharSequence summaryText = p.summaryText;
- if (summaryText == null && mStyle != null && mStyle.mSummaryTextSet
+ CharSequence headerText = p.mSubText;
+ if (headerText == null && mStyle != null && mStyle.mSummaryTextSet
&& mStyle.hasSummaryInHeader()) {
- summaryText = mStyle.mSummaryText;
+ headerText = mStyle.mSummaryText;
}
- if (summaryText == null
+ if (headerText == null
&& mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N
&& mN.extras.getCharSequence(EXTRA_INFO_TEXT) != null) {
- summaryText = mN.extras.getCharSequence(EXTRA_INFO_TEXT);
+ headerText = mN.extras.getCharSequence(EXTRA_INFO_TEXT);
}
- if (!TextUtils.isEmpty(summaryText)) {
+ if (!TextUtils.isEmpty(headerText)) {
// TODO: Remove the span entirely to only have the string with propper formating.
contentView.setTextViewText(R.id.header_text, processTextSpans(
- processLegacyText(summaryText)));
+ processLegacyText(headerText)));
setTextViewColorSecondary(contentView, R.id.header_text, p);
contentView.setViewVisibility(R.id.header_text, View.VISIBLE);
if (hasTextToLeft) {
@@ -5566,9 +5566,9 @@ public class Notification implements Parcelable
if (p.mHideSubText) {
return false;
}
- if (!TextUtils.isEmpty(p.headerTextSecondary)) {
+ if (!TextUtils.isEmpty(p.mHeaderTextSecondary)) {
contentView.setTextViewText(R.id.header_text_secondary, processTextSpans(
- processLegacyText(p.headerTextSecondary)));
+ processLegacyText(p.mHeaderTextSecondary)));
setTextViewColorSecondary(contentView, R.id.header_text_secondary, p);
contentView.setViewVisibility(R.id.header_text_secondary, View.VISIBLE);
if (hasTextToLeft) {
@@ -6175,7 +6175,7 @@ public class Notification implements Parcelable
.viewType(StandardTemplateParams.VIEW_TYPE_MINIMIZED)
.highlightExpander(false)
.fillTextsFrom(this);
- if (!useRegularSubtext || TextUtils.isEmpty(p.summaryText)) {
+ if (!useRegularSubtext || TextUtils.isEmpty(p.mSubText)) {
p.summaryText(createSummaryText());
}
RemoteViews header = makeNotificationHeader(p);
@@ -7192,7 +7192,7 @@ public class Notification implements Parcelable
checkBuilder();
if (mBigContentTitle != null) {
- p.title = mBigContentTitle;
+ p.mTitle = mBigContentTitle;
}
return mBuilder.applyStandardTemplateWithActions(layoutId, p, result);
@@ -12455,10 +12455,10 @@ public class Notification implements Parcelable
boolean mAllowTextWithProgress;
int mTitleViewId;
int mTextViewId;
- CharSequence title;
- CharSequence text;
- CharSequence headerTextSecondary;
- CharSequence summaryText;
+ @Nullable CharSequence mTitle;
+ @Nullable CharSequence mText;
+ @Nullable CharSequence mHeaderTextSecondary;
+ @Nullable CharSequence mSubText;
int maxRemoteInputHistory = Style.MAX_REMOTE_INPUT_HISTORY_LINES;
boolean allowColorization = true;
boolean mHighlightExpander = false;
@@ -12480,10 +12480,10 @@ public class Notification implements Parcelable
mAllowTextWithProgress = false;
mTitleViewId = R.id.title;
mTextViewId = R.id.text;
- title = null;
- text = null;
- summaryText = null;
- headerTextSecondary = null;
+ mTitle = null;
+ mText = null;
+ mSubText = null;
+ mHeaderTextSecondary = null;
maxRemoteInputHistory = Style.MAX_REMOTE_INPUT_HISTORY_LINES;
allowColorization = true;
mHighlightExpander = false;
@@ -12491,7 +12491,7 @@ public class Notification implements Parcelable
}
final boolean hasTitle() {
- return !TextUtils.isEmpty(title) && !mHideTitle;
+ return !TextUtils.isEmpty(mTitle) && !mHideTitle;
}
final StandardTemplateParams viewType(int viewType) {
@@ -12564,23 +12564,23 @@ public class Notification implements Parcelable
return this;
}
- final StandardTemplateParams title(CharSequence title) {
- this.title = title;
+ final StandardTemplateParams title(@Nullable CharSequence title) {
+ this.mTitle = title;
return this;
}
- final StandardTemplateParams text(CharSequence text) {
- this.text = text;
+ final StandardTemplateParams text(@Nullable CharSequence text) {
+ this.mText = text;
return this;
}
- final StandardTemplateParams summaryText(CharSequence text) {
- this.summaryText = text;
+ final StandardTemplateParams summaryText(@Nullable CharSequence text) {
+ this.mSubText = text;
return this;
}
- final StandardTemplateParams headerTextSecondary(CharSequence text) {
- this.headerTextSecondary = text;
+ final StandardTemplateParams headerTextSecondary(@Nullable CharSequence text) {
+ this.mHeaderTextSecondary = text;
return this;
}
@@ -12607,9 +12607,9 @@ public class Notification implements Parcelable
final StandardTemplateParams fillTextsFrom(Builder b) {
Bundle extras = b.mN.extras;
- this.title = b.processLegacyText(extras.getCharSequence(EXTRA_TITLE));
- this.text = b.processLegacyText(extras.getCharSequence(EXTRA_TEXT));
- this.summaryText = extras.getCharSequence(EXTRA_SUB_TEXT);
+ this.mTitle = b.processLegacyText(extras.getCharSequence(EXTRA_TITLE));
+ this.mText = b.processLegacyText(extras.getCharSequence(EXTRA_TEXT));
+ this.mSubText = extras.getCharSequence(EXTRA_SUB_TEXT);
return this;
}
diff --git a/core/java/android/content/ContentCaptureOptions.java b/core/java/android/content/ContentCaptureOptions.java
index 77072890a1eb..856bde870bcf 100644
--- a/core/java/android/content/ContentCaptureOptions.java
+++ b/core/java/android/content/ContentCaptureOptions.java
@@ -70,6 +70,12 @@ public final class ContentCaptureOptions implements Parcelable {
public final int logHistorySize;
/**
+ * Disable flush when receiving a VIEW_TREE_APPEARING event.
+ * @hide
+ */
+ public final boolean disableFlushForViewTreeAppearing;
+
+ /**
* List of activities explicitly allowlisted for content capture (or {@code null} if allowlisted
* for all acitivites in the package).
*/
@@ -90,7 +96,8 @@ public final class ContentCaptureOptions implements Parcelable {
public ContentCaptureOptions(int loggingLevel) {
this(/* lite= */ true, loggingLevel, /* maxBufferSize= */ 0,
/* idleFlushingFrequencyMs= */ 0, /* textChangeFlushingFrequencyMs= */ 0,
- /* logHistorySize= */ 0, /* whitelistedComponents= */ null);
+ /* logHistorySize= */ 0, /* disableFlushForViewTreeAppearing= */ false,
+ /* whitelistedComponents= */ null);
}
/**
@@ -98,10 +105,23 @@ public final class ContentCaptureOptions implements Parcelable {
*/
public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
int textChangeFlushingFrequencyMs, int logHistorySize,
- @SuppressLint("NullableCollection")
+ @SuppressLint({"ConcreteCollection", "NullableCollection"})
+ @Nullable ArraySet<ComponentName> whitelistedComponents) {
+ this(/* lite= */ false, loggingLevel, maxBufferSize, idleFlushingFrequencyMs,
+ textChangeFlushingFrequencyMs, logHistorySize,
+ ContentCaptureManager.DEFAULT_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
+ whitelistedComponents);
+ }
+
+ /** @hide */
+ public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
+ int textChangeFlushingFrequencyMs, int logHistorySize,
+ boolean disableFlushForViewTreeAppearing,
+ @SuppressLint({"ConcreteCollection", "NullableCollection"})
@Nullable ArraySet<ComponentName> whitelistedComponents) {
this(/* lite= */ false, loggingLevel, maxBufferSize, idleFlushingFrequencyMs,
- textChangeFlushingFrequencyMs, logHistorySize, whitelistedComponents);
+ textChangeFlushingFrequencyMs, logHistorySize, disableFlushForViewTreeAppearing,
+ whitelistedComponents);
}
/** @hide */
@@ -111,11 +131,14 @@ public final class ContentCaptureOptions implements Parcelable {
ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE,
ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS,
ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS,
- ContentCaptureManager.DEFAULT_LOG_HISTORY_SIZE, whitelistedComponents);
+ ContentCaptureManager.DEFAULT_LOG_HISTORY_SIZE,
+ ContentCaptureManager.DEFAULT_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
+ whitelistedComponents);
}
private ContentCaptureOptions(boolean lite, int loggingLevel, int maxBufferSize,
int idleFlushingFrequencyMs, int textChangeFlushingFrequencyMs, int logHistorySize,
+ boolean disableFlushForViewTreeAppearing,
@Nullable ArraySet<ComponentName> whitelistedComponents) {
this.lite = lite;
this.loggingLevel = loggingLevel;
@@ -123,6 +146,7 @@ public final class ContentCaptureOptions implements Parcelable {
this.idleFlushingFrequencyMs = idleFlushingFrequencyMs;
this.textChangeFlushingFrequencyMs = textChangeFlushingFrequencyMs;
this.logHistorySize = logHistorySize;
+ this.disableFlushForViewTreeAppearing = disableFlushForViewTreeAppearing;
this.whitelistedComponents = whitelistedComponents;
}
@@ -171,7 +195,8 @@ public final class ContentCaptureOptions implements Parcelable {
.append(", maxBufferSize=").append(maxBufferSize)
.append(", idleFlushingFrequencyMs=").append(idleFlushingFrequencyMs)
.append(", textChangeFlushingFrequencyMs=").append(textChangeFlushingFrequencyMs)
- .append(", logHistorySize=").append(logHistorySize);
+ .append(", logHistorySize=").append(logHistorySize)
+ .append(", disableFlushForViewTreeAppearing=").append(disableFlushForViewTreeAppearing);
if (whitelistedComponents != null) {
string.append(", whitelisted=").append(whitelistedComponents);
}
@@ -189,6 +214,7 @@ public final class ContentCaptureOptions implements Parcelable {
pw.print(", idle="); pw.print(idleFlushingFrequencyMs);
pw.print(", textIdle="); pw.print(textChangeFlushingFrequencyMs);
pw.print(", logSize="); pw.print(logHistorySize);
+ pw.print(", disableFlushForViewTreeAppearing="); pw.print(disableFlushForViewTreeAppearing);
if (whitelistedComponents != null) {
pw.print(", whitelisted="); pw.print(whitelistedComponents);
}
@@ -209,6 +235,7 @@ public final class ContentCaptureOptions implements Parcelable {
parcel.writeInt(idleFlushingFrequencyMs);
parcel.writeInt(textChangeFlushingFrequencyMs);
parcel.writeInt(logHistorySize);
+ parcel.writeBoolean(disableFlushForViewTreeAppearing);
parcel.writeArraySet(whitelistedComponents);
}
@@ -226,12 +253,13 @@ public final class ContentCaptureOptions implements Parcelable {
final int idleFlushingFrequencyMs = parcel.readInt();
final int textChangeFlushingFrequencyMs = parcel.readInt();
final int logHistorySize = parcel.readInt();
+ final boolean disableFlushForViewTreeAppearing = parcel.readBoolean();
@SuppressWarnings("unchecked")
final ArraySet<ComponentName> whitelistedComponents =
(ArraySet<ComponentName>) parcel.readArraySet(null);
return new ContentCaptureOptions(loggingLevel, maxBufferSize,
idleFlushingFrequencyMs, textChangeFlushingFrequencyMs, logHistorySize,
- whitelistedComponents);
+ disableFlushForViewTreeAppearing, whitelistedComponents);
}
@Override
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index b72db5bdafa3..795c77ff5105 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -363,7 +363,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
enumCheckUriPermission,
callingUid, uri.getAuthority(), type);
}
- } catch (RemoteException e) {
+ } catch (Exception e) {
//does nothing
}
} else {
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 7766896c7367..8acdf510484b 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -3981,8 +3981,7 @@ public class PackageInstaller {
/**
* Details for requesting the pre-commit install approval.
*/
- @DataClass(genParcelable = true, genHiddenConstructor = true, genBuilder = true,
- genToString = true)
+ @DataClass(genConstructor = false, genToString = true)
public static final class PreapprovalDetails implements Parcelable {
/**
* The icon representing the app to be installed.
@@ -4001,22 +4000,6 @@ public class PackageInstaller {
*/
private final @NonNull String mPackageName;
-
-
-
- // 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/content/pm/PackageInstaller.java
- //
- // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
- // Settings > Editor > Code Style > Formatter Control
- //@formatter:off
-
-
/**
* Creates a new PreapprovalDetails.
*
@@ -4030,78 +4013,25 @@ public class PackageInstaller {
* The package name of the app to be installed.
* @hide
*/
- @DataClass.Generated.Member
public PreapprovalDetails(
@Nullable Bitmap icon,
@NonNull CharSequence label,
@NonNull ULocale locale,
@NonNull String packageName) {
- this.mIcon = icon;
- this.mLabel = label;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mLabel);
- this.mLocale = locale;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mLocale);
- this.mPackageName = packageName;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mPackageName);
-
- // onConstructed(); // You can define this method to get a callback
- }
-
- /**
- * The icon representing the app to be installed.
- */
- @DataClass.Generated.Member
- public @Nullable Bitmap getIcon() {
- return mIcon;
- }
-
- /**
- * The label representing the app to be installed.
- */
- @DataClass.Generated.Member
- public @NonNull CharSequence getLabel() {
- return mLabel;
- }
-
- /**
- * The locale of the app label being used.
- */
- @DataClass.Generated.Member
- public @NonNull ULocale getLocale() {
- return mLocale;
- }
-
- /**
- * The package name of the app to be installed.
- */
- @DataClass.Generated.Member
- public @NonNull String getPackageName() {
- return mPackageName;
+ mIcon = icon;
+ mLabel = label;
+ Preconditions.checkArgument(!TextUtils.isEmpty(mLabel),
+ "App label cannot be empty.");
+ mLocale = locale;
+ Preconditions.checkArgument(!Objects.isNull(mLocale),
+ "Locale cannot be null.");
+ mPackageName = packageName;
+ Preconditions.checkArgument(!TextUtils.isEmpty(mPackageName),
+ "Package name cannot be empty.");
}
@Override
- @DataClass.Generated.Member
- public String toString() {
- // You can override field toString logic by defining methods like:
- // String fieldNameToString() { ... }
-
- return "PreapprovalDetails { " +
- "icon = " + mIcon + ", " +
- "label = " + mLabel + ", " +
- "locale = " + mLocale + ", " +
- "packageName = " + mPackageName +
- " }";
- }
-
- @Override
- @DataClass.Generated.Member
public void writeToParcel(@NonNull Parcel dest, int flags) {
- // You can override field parcelling by defining methods like:
- // void parcelFieldName(Parcel dest, int flags) { ... }
-
byte flg = 0;
if (mIcon != null) flg |= 0x1;
dest.writeByte(flg);
@@ -4112,37 +4042,28 @@ public class PackageInstaller {
}
@Override
- @DataClass.Generated.Member
public int describeContents() { return 0; }
/** @hide */
- @SuppressWarnings({"unchecked", "RedundantCast"})
- @DataClass.Generated.Member
/* package-private */ PreapprovalDetails(@NonNull Parcel in) {
- // You can override field unparcelling by defining methods like:
- // static FieldType unparcelFieldName(Parcel in) { ... }
-
byte flg = in.readByte();
- Bitmap icon = (flg & 0x1) == 0 ? null : Bitmap.CREATOR.createFromParcel(in);
- CharSequence label = (CharSequence) in.readCharSequence();
- ULocale locale = new ULocale(in.readString8());
- String packageName = in.readString8();
-
- this.mIcon = icon;
- this.mLabel = label;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mLabel);
- this.mLocale = locale;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mLocale);
- this.mPackageName = packageName;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mPackageName);
-
- // onConstructed(); // You can define this method to get a callback
+ final Bitmap icon = (flg & 0x1) == 0 ? null : Bitmap.CREATOR.createFromParcel(in);
+ final CharSequence label = in.readCharSequence();
+ final ULocale locale = new ULocale(in.readString8());
+ final String packageName = in.readString8();
+
+ mIcon = icon;
+ mLabel = label;
+ Preconditions.checkArgument(!TextUtils.isEmpty(mLabel),
+ "App label cannot be empty.");
+ mLocale = locale;
+ Preconditions.checkArgument(!Objects.isNull(mLocale),
+ "Locale cannot be null.");
+ mPackageName = packageName;
+ Preconditions.checkArgument(!TextUtils.isEmpty(mPackageName),
+ "Package name cannot be empty.");
}
- @DataClass.Generated.Member
public static final @NonNull Parcelable.Creator<PreapprovalDetails> CREATOR
= new Parcelable.Creator<PreapprovalDetails>() {
@Override
@@ -4159,8 +4080,6 @@ public class PackageInstaller {
/**
* A builder for {@link PreapprovalDetails}
*/
- @SuppressWarnings("WeakerAccess")
- @DataClass.Generated.Member
public static final class Builder {
private @Nullable Bitmap mIcon;
@@ -4178,7 +4097,6 @@ public class PackageInstaller {
/**
* The icon representing the app to be installed.
*/
- @DataClass.Generated.Member
public @NonNull Builder setIcon(@NonNull Bitmap value) {
checkNotUsed();
mBuilderFieldsSet |= 0x1;
@@ -4189,7 +4107,6 @@ public class PackageInstaller {
/**
* The label representing the app to be installed.
*/
- @DataClass.Generated.Member
public @NonNull Builder setLabel(@NonNull CharSequence value) {
checkNotUsed();
mBuilderFieldsSet |= 0x2;
@@ -4200,7 +4117,6 @@ public class PackageInstaller {
/**
* The locale of the app label being used.
*/
- @DataClass.Generated.Member
public @NonNull Builder setLocale(@NonNull ULocale value) {
checkNotUsed();
mBuilderFieldsSet |= 0x4;
@@ -4211,7 +4127,6 @@ public class PackageInstaller {
/**
* The package name of the app to be installed.
*/
- @DataClass.Generated.Member
public @NonNull Builder setPackageName(@NonNull String value) {
checkNotUsed();
mBuilderFieldsSet |= 0x8;
@@ -4234,17 +4149,79 @@ public class PackageInstaller {
private void checkNotUsed() {
if ((mBuilderFieldsSet & 0x10) != 0) {
- throw new IllegalStateException(
- "This Builder should not be reused. Use a new Builder instance instead");
+ throw new IllegalStateException("This Builder should not be reused. "
+ + "Use a new Builder instance instead");
}
}
}
+
+
+
+ // 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/content/pm/PackageInstaller.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * The icon representing the app to be installed.
+ */
+ @DataClass.Generated.Member
+ public @Nullable Bitmap getIcon() {
+ return mIcon;
+ }
+
+ /**
+ * The label representing the app to be installed.
+ */
+ @DataClass.Generated.Member
+ public @NonNull CharSequence getLabel() {
+ return mLabel;
+ }
+
+ /**
+ * The locale of the app label being used.
+ */
+ @DataClass.Generated.Member
+ public @NonNull ULocale getLocale() {
+ return mLocale;
+ }
+
+ /**
+ * The package name of the app to be installed.
+ */
+ @DataClass.Generated.Member
+ public @NonNull String getPackageName() {
+ return mPackageName;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "PreapprovalDetails { " +
+ "icon = " + mIcon + ", " +
+ "label = " + mLabel + ", " +
+ "locale = " + mLocale + ", " +
+ "packageName = " + mPackageName +
+ " }";
+ }
+
@DataClass.Generated(
- time = 1666748098353L,
+ time = 1676970504308L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java",
- inputSignatures = "private final @android.annotation.Nullable android.graphics.Bitmap mIcon\nprivate final @android.annotation.NonNull java.lang.CharSequence mLabel\nprivate final @android.annotation.NonNull android.icu.util.ULocale mLocale\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nclass PreapprovalDetails extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true, genBuilder=true, genToString=true)")
+ inputSignatures = "private final @android.annotation.Nullable android.graphics.Bitmap mIcon\nprivate final @android.annotation.NonNull java.lang.CharSequence mLabel\nprivate final @android.annotation.NonNull android.icu.util.ULocale mLocale\nprivate final @android.annotation.NonNull java.lang.String mPackageName\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<android.content.pm.PackageInstaller.PreapprovalDetails> CREATOR\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\npublic @java.lang.Override int describeContents()\nclass PreapprovalDetails extends java.lang.Object implements [android.os.Parcelable]\nprivate @android.annotation.Nullable android.graphics.Bitmap mIcon\nprivate @android.annotation.NonNull java.lang.CharSequence mLabel\nprivate @android.annotation.NonNull android.icu.util.ULocale mLocale\nprivate @android.annotation.NonNull java.lang.String mPackageName\nprivate long mBuilderFieldsSet\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setIcon(android.graphics.Bitmap)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setLabel(java.lang.CharSequence)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setLocale(android.icu.util.ULocale)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setPackageName(java.lang.String)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails build()\nprivate void checkNotUsed()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genToString=true)")
@Deprecated
private void __metadata() {}
@@ -4347,7 +4324,7 @@ public class PackageInstaller {
};
@DataClass.Generated(
- time = 1675135664641L,
+ time = 1676970504336L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java",
inputSignatures = "private boolean mAllConstraintsSatisfied\npublic boolean areAllConstraintsSatisfied()\nclass InstallConstraintsResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true)")
@@ -4635,7 +4612,7 @@ public class PackageInstaller {
};
@DataClass.Generated(
- time = 1675135664653L,
+ time = 1676970504352L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java",
inputSignatures = "public static final @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints GENTLE_UPDATE\nprivate final boolean mDeviceIdleRequired\nprivate final boolean mAppNotForegroundRequired\nprivate final boolean mAppNotInteractingRequired\nprivate final boolean mAppNotTopVisibleRequired\nprivate final boolean mNotInCallRequired\nclass InstallConstraints extends java.lang.Object implements [android.os.Parcelable]\nprivate boolean mDeviceIdleRequired\nprivate boolean mAppNotForegroundRequired\nprivate boolean mAppNotInteractingRequired\nprivate boolean mAppNotTopVisibleRequired\nprivate boolean mNotInCallRequired\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setDeviceIdleRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotForegroundRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotInteractingRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotTopVisibleRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setNotInCallRequired()\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints build()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true, genEqualsHashCode=true)")
diff --git a/core/java/android/hardware/biometrics/AuthenticateOptions.java b/core/java/android/hardware/biometrics/AuthenticateOptions.java
new file mode 100644
index 000000000000..77660713275f
--- /dev/null
+++ b/core/java/android/hardware/biometrics/AuthenticateOptions.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Common authentication options that are exposed across all modalities.
+ *
+ * @hide
+ */
+public interface AuthenticateOptions {
+
+ /** The user id for this operation. */
+ int getUserId();
+
+ /** The sensor id for this operation. */
+ int getSensorId();
+
+ /** The state is unknown. */
+ int DISPLAY_STATE_UNKNOWN = 0;
+
+ /** The display is on and showing the lockscreen (or an occluding app). */
+ int DISPLAY_STATE_LOCKSCREEN = 1;
+
+ /** The display is off or dozing. */
+ int DISPLAY_STATE_NO_UI = 2;
+
+ /** The display is showing a screensaver (dreaming). */
+ int DISPLAY_STATE_SCREENSAVER = 3;
+
+ /** The display is dreaming with always on display. */
+ int DISPLAY_STATE_AOD = 4;
+
+ /** The doze state of the device. */
+ @IntDef(prefix = "DISPLAY_STATE_", value = {
+ DISPLAY_STATE_UNKNOWN,
+ DISPLAY_STATE_LOCKSCREEN,
+ DISPLAY_STATE_NO_UI,
+ DISPLAY_STATE_SCREENSAVER,
+ DISPLAY_STATE_AOD
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface DisplayState {}
+
+ /** The current doze state of the device. */
+ @DisplayState
+ int getDisplayState();
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ */
+ @NonNull String getOpPackageName();
+
+ /** The attribution tag, if any. */
+ @Nullable String getAttributionTag();
+}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index eeff6ccafd5d..b766cd19cdb0 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -68,6 +68,15 @@ public final class DisplayManager {
private static final boolean DEBUG = false;
private static final boolean ENABLE_VIRTUAL_DISPLAY_REFRESH_RATE = true;
+ /**
+ * The hdr output control feature flag, the value should be read via
+ * {@link android.provider.DeviceConfig#getBoolean(String, String, boolean)} with
+ * {@link android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER} as the namespace.
+ * @hide
+ */
+ @TestApi
+ public static final String HDR_OUTPUT_CONTROL_FLAG = "enable_hdr_output_control";
+
private final Context mContext;
private final DisplayManagerGlobal mGlobal;
diff --git a/core/java/android/hardware/face/FaceAuthenticateOptions.aidl b/core/java/android/hardware/face/FaceAuthenticateOptions.aidl
new file mode 100644
index 000000000000..7c72b405383c
--- /dev/null
+++ b/core/java/android/hardware/face/FaceAuthenticateOptions.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.face;
+
+parcelable FaceAuthenticateOptions;
diff --git a/core/java/android/hardware/face/FaceAuthenticateOptions.java b/core/java/android/hardware/face/FaceAuthenticateOptions.java
new file mode 100644
index 000000000000..4009fa7682fe
--- /dev/null
+++ b/core/java/android/hardware/face/FaceAuthenticateOptions.java
@@ -0,0 +1,624 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.face;
+
+
+import static android.os.PowerManager.WAKE_REASON_UNKNOWN;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.biometrics.AuthenticateOptions;
+import android.os.Parcelable;
+import android.os.PowerManager;
+
+import com.android.internal.util.DataClass;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Additional options when requesting Face authentication or detection.
+ *
+ * @hide
+ */
+@DataClass(
+ genParcelable = true,
+ genAidl = true,
+ genBuilder = true,
+ genSetters = true,
+ genEqualsHashCode = true
+)
+public class FaceAuthenticateOptions implements AuthenticateOptions, Parcelable {
+
+ /** The user id for this operation. */
+ private final int mUserId;
+ private static int defaultUserId() {
+ return 0;
+ }
+
+ /** The sensor id for this operation. */
+ private final int mSensorId;
+ private static int defaultSensorId() {
+ return -1;
+ }
+
+ /** The current doze state of the device. */
+ @AuthenticateOptions.DisplayState
+ private final int mDisplayState;
+ private static int defaultDisplayState() {
+ return DISPLAY_STATE_UNKNOWN;
+ }
+
+ public static final int AUTHENTICATE_REASON_UNKNOWN = 0;
+ public static final int AUTHENTICATE_REASON_STARTED_WAKING_UP = 1;
+ public static final int AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN = 2;
+ public static final int AUTHENTICATE_REASON_ASSISTANT_VISIBLE = 3;
+ public static final int AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN = 4;
+ public static final int AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED = 5;
+ public static final int AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED = 6;
+ public static final int AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED = 7;
+ public static final int AUTHENTICATE_REASON_QS_EXPANDED = 8;
+ public static final int AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER = 9;
+ public static final int AUTHENTICATE_REASON_UDFPS_POINTER_DOWN = 10;
+
+ /**
+ * The reason for this operation when requested by the system (sysui),
+ * otherwise AUTHENTICATE_REASON_UNKNOWN.
+ *
+ * See frameworks/base/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+ * for more details about each reason.
+ */
+ @AuthenticateReason
+ private final int mAuthenticateReason;
+ private static int defaultAuthenticateReason() {
+ return AUTHENTICATE_REASON_UNKNOWN;
+ }
+
+ /** A reason if this request was triggered due to a power event or WAKE_REASON_UNKNOWN. */
+ @PowerManager.WakeReason
+ private final int mWakeReason;
+ private static int defaultWakeReason() {
+ return WAKE_REASON_UNKNOWN;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @NonNull
+ private String mOpPackageName;
+ private static String defaultOpPackageName() {
+ return "";
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @Nullable
+ private String mAttributionTag;
+ private static String defaultAttributionTag() {
+ return null;
+ }
+
+
+
+ // 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/face/FaceAuthenticateOptions.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @IntDef(prefix = "AUTHENTICATE_REASON_", value = {
+ AUTHENTICATE_REASON_UNKNOWN,
+ AUTHENTICATE_REASON_STARTED_WAKING_UP,
+ AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN,
+ AUTHENTICATE_REASON_ASSISTANT_VISIBLE,
+ AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN,
+ AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED,
+ AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED,
+ AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED,
+ AUTHENTICATE_REASON_QS_EXPANDED,
+ AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER,
+ AUTHENTICATE_REASON_UDFPS_POINTER_DOWN
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @DataClass.Generated.Member
+ public @interface AuthenticateReason {}
+
+ @DataClass.Generated.Member
+ public static String authenticateReasonToString(@AuthenticateReason int value) {
+ switch (value) {
+ case AUTHENTICATE_REASON_UNKNOWN:
+ return "AUTHENTICATE_REASON_UNKNOWN";
+ case AUTHENTICATE_REASON_STARTED_WAKING_UP:
+ return "AUTHENTICATE_REASON_STARTED_WAKING_UP";
+ case AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN:
+ return "AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN";
+ case AUTHENTICATE_REASON_ASSISTANT_VISIBLE:
+ return "AUTHENTICATE_REASON_ASSISTANT_VISIBLE";
+ case AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN:
+ return "AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN";
+ case AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED:
+ return "AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED";
+ case AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED:
+ return "AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED";
+ case AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED:
+ return "AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED";
+ case AUTHENTICATE_REASON_QS_EXPANDED:
+ return "AUTHENTICATE_REASON_QS_EXPANDED";
+ case AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER:
+ return "AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER";
+ case AUTHENTICATE_REASON_UDFPS_POINTER_DOWN:
+ return "AUTHENTICATE_REASON_UDFPS_POINTER_DOWN";
+ default: return Integer.toHexString(value);
+ }
+ }
+
+ @DataClass.Generated.Member
+ /* package-private */ FaceAuthenticateOptions(
+ int userId,
+ int sensorId,
+ @AuthenticateOptions.DisplayState int displayState,
+ @AuthenticateReason int authenticateReason,
+ @PowerManager.WakeReason int wakeReason,
+ @NonNull String opPackageName,
+ @Nullable String attributionTag) {
+ this.mUserId = userId;
+ this.mSensorId = sensorId;
+ this.mDisplayState = displayState;
+ com.android.internal.util.AnnotationValidations.validate(
+ AuthenticateOptions.DisplayState.class, null, mDisplayState);
+ this.mAuthenticateReason = authenticateReason;
+
+ if (!(mAuthenticateReason == AUTHENTICATE_REASON_UNKNOWN)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_STARTED_WAKING_UP)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_ASSISTANT_VISIBLE)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_QS_EXPANDED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_UDFPS_POINTER_DOWN)) {
+ throw new java.lang.IllegalArgumentException(
+ "authenticateReason was " + mAuthenticateReason + " but must be one of: "
+ + "AUTHENTICATE_REASON_UNKNOWN(" + AUTHENTICATE_REASON_UNKNOWN + "), "
+ + "AUTHENTICATE_REASON_STARTED_WAKING_UP(" + AUTHENTICATE_REASON_STARTED_WAKING_UP + "), "
+ + "AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN(" + AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN + "), "
+ + "AUTHENTICATE_REASON_ASSISTANT_VISIBLE(" + AUTHENTICATE_REASON_ASSISTANT_VISIBLE + "), "
+ + "AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN(" + AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN + "), "
+ + "AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED(" + AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED + "), "
+ + "AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED(" + AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED + "), "
+ + "AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED(" + AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED + "), "
+ + "AUTHENTICATE_REASON_QS_EXPANDED(" + AUTHENTICATE_REASON_QS_EXPANDED + "), "
+ + "AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER(" + AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER + "), "
+ + "AUTHENTICATE_REASON_UDFPS_POINTER_DOWN(" + AUTHENTICATE_REASON_UDFPS_POINTER_DOWN + ")");
+ }
+
+ this.mWakeReason = wakeReason;
+ com.android.internal.util.AnnotationValidations.validate(
+ PowerManager.WakeReason.class, null, mWakeReason);
+ this.mOpPackageName = opPackageName;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mOpPackageName);
+ this.mAttributionTag = attributionTag;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * The user id for this operation.
+ */
+ @DataClass.Generated.Member
+ public int getUserId() {
+ return mUserId;
+ }
+
+ /**
+ * The sensor id for this operation.
+ */
+ @DataClass.Generated.Member
+ public int getSensorId() {
+ return mSensorId;
+ }
+
+ /**
+ * The current doze state of the device.
+ */
+ @DataClass.Generated.Member
+ public @AuthenticateOptions.DisplayState int getDisplayState() {
+ return mDisplayState;
+ }
+
+ /**
+ * The reason for this operation when requested by the system (sysui),
+ * otherwise AUTHENTICATE_REASON_UNKNOWN.
+ *
+ * See frameworks/base/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+ * for more details about each reason.
+ */
+ @DataClass.Generated.Member
+ public @AuthenticateReason int getAuthenticateReason() {
+ return mAuthenticateReason;
+ }
+
+ /**
+ * A reason if this request was triggered due to a power event or WAKE_REASON_UNKNOWN.
+ */
+ @DataClass.Generated.Member
+ public @PowerManager.WakeReason int getWakeReason() {
+ return mWakeReason;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull String getOpPackageName() {
+ return mOpPackageName;
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @Nullable String getAttributionTag() {
+ return mAttributionTag;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull FaceAuthenticateOptions setOpPackageName(@NonNull String value) {
+ mOpPackageName = value;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mOpPackageName);
+ return this;
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull FaceAuthenticateOptions setAttributionTag(@NonNull String value) {
+ mAttributionTag = value;
+ return this;
+ }
+
+ @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(FaceAuthenticateOptions other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ FaceAuthenticateOptions that = (FaceAuthenticateOptions) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && mUserId == that.mUserId
+ && mSensorId == that.mSensorId
+ && mDisplayState == that.mDisplayState
+ && mAuthenticateReason == that.mAuthenticateReason
+ && mWakeReason == that.mWakeReason
+ && java.util.Objects.equals(mOpPackageName, that.mOpPackageName)
+ && java.util.Objects.equals(mAttributionTag, that.mAttributionTag);
+ }
+
+ @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 + mUserId;
+ _hash = 31 * _hash + mSensorId;
+ _hash = 31 * _hash + mDisplayState;
+ _hash = 31 * _hash + mAuthenticateReason;
+ _hash = 31 * _hash + mWakeReason;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mOpPackageName);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mAttributionTag);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (mAttributionTag != null) flg |= 0x40;
+ dest.writeByte(flg);
+ dest.writeInt(mUserId);
+ dest.writeInt(mSensorId);
+ dest.writeInt(mDisplayState);
+ dest.writeInt(mAuthenticateReason);
+ dest.writeInt(mWakeReason);
+ dest.writeString(mOpPackageName);
+ if (mAttributionTag != null) dest.writeString(mAttributionTag);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ protected FaceAuthenticateOptions(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ int userId = in.readInt();
+ int sensorId = in.readInt();
+ int displayState = in.readInt();
+ int authenticateReason = in.readInt();
+ int wakeReason = in.readInt();
+ String opPackageName = in.readString();
+ String attributionTag = (flg & 0x40) == 0 ? null : in.readString();
+
+ this.mUserId = userId;
+ this.mSensorId = sensorId;
+ this.mDisplayState = displayState;
+ com.android.internal.util.AnnotationValidations.validate(
+ AuthenticateOptions.DisplayState.class, null, mDisplayState);
+ this.mAuthenticateReason = authenticateReason;
+
+ if (!(mAuthenticateReason == AUTHENTICATE_REASON_UNKNOWN)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_STARTED_WAKING_UP)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_ASSISTANT_VISIBLE)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_QS_EXPANDED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_UDFPS_POINTER_DOWN)) {
+ throw new java.lang.IllegalArgumentException(
+ "authenticateReason was " + mAuthenticateReason + " but must be one of: "
+ + "AUTHENTICATE_REASON_UNKNOWN(" + AUTHENTICATE_REASON_UNKNOWN + "), "
+ + "AUTHENTICATE_REASON_STARTED_WAKING_UP(" + AUTHENTICATE_REASON_STARTED_WAKING_UP + "), "
+ + "AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN(" + AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN + "), "
+ + "AUTHENTICATE_REASON_ASSISTANT_VISIBLE(" + AUTHENTICATE_REASON_ASSISTANT_VISIBLE + "), "
+ + "AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN(" + AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN + "), "
+ + "AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED(" + AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED + "), "
+ + "AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED(" + AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED + "), "
+ + "AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED(" + AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED + "), "
+ + "AUTHENTICATE_REASON_QS_EXPANDED(" + AUTHENTICATE_REASON_QS_EXPANDED + "), "
+ + "AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER(" + AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER + "), "
+ + "AUTHENTICATE_REASON_UDFPS_POINTER_DOWN(" + AUTHENTICATE_REASON_UDFPS_POINTER_DOWN + ")");
+ }
+
+ this.mWakeReason = wakeReason;
+ com.android.internal.util.AnnotationValidations.validate(
+ PowerManager.WakeReason.class, null, mWakeReason);
+ this.mOpPackageName = opPackageName;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mOpPackageName);
+ this.mAttributionTag = attributionTag;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<FaceAuthenticateOptions> CREATOR
+ = new Parcelable.Creator<FaceAuthenticateOptions>() {
+ @Override
+ public FaceAuthenticateOptions[] newArray(int size) {
+ return new FaceAuthenticateOptions[size];
+ }
+
+ @Override
+ public FaceAuthenticateOptions createFromParcel(@NonNull android.os.Parcel in) {
+ return new FaceAuthenticateOptions(in);
+ }
+ };
+
+ /**
+ * A builder for {@link FaceAuthenticateOptions}
+ */
+ @SuppressWarnings("WeakerAccess")
+ @DataClass.Generated.Member
+ public static class Builder {
+
+ private int mUserId;
+ private int mSensorId;
+ private @AuthenticateOptions.DisplayState int mDisplayState;
+ private @AuthenticateReason int mAuthenticateReason;
+ private @PowerManager.WakeReason int mWakeReason;
+ private @NonNull String mOpPackageName;
+ private @Nullable String mAttributionTag;
+
+ private long mBuilderFieldsSet = 0L;
+
+ public Builder() {
+ }
+
+ /**
+ * The user id for this operation.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setUserId(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x1;
+ mUserId = value;
+ return this;
+ }
+
+ /**
+ * The sensor id for this operation.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setSensorId(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2;
+ mSensorId = value;
+ return this;
+ }
+
+ /**
+ * The current doze state of the device.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setDisplayState(@AuthenticateOptions.DisplayState int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4;
+ mDisplayState = value;
+ return this;
+ }
+
+ /**
+ * The reason for this operation when requested by the system (sysui),
+ * otherwise AUTHENTICATE_REASON_UNKNOWN.
+ *
+ * See frameworks/base/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+ * for more details about each reason.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setAuthenticateReason(@AuthenticateReason int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x8;
+ mAuthenticateReason = value;
+ return this;
+ }
+
+ /**
+ * A reason if this request was triggered due to a power event or WAKE_REASON_UNKNOWN.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setWakeReason(@PowerManager.WakeReason int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x10;
+ mWakeReason = value;
+ return this;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setOpPackageName(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x20;
+ mOpPackageName = value;
+ return this;
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setAttributionTag(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x40;
+ mAttributionTag = value;
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @NonNull FaceAuthenticateOptions build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x80; // Mark builder used
+
+ if ((mBuilderFieldsSet & 0x1) == 0) {
+ mUserId = defaultUserId();
+ }
+ if ((mBuilderFieldsSet & 0x2) == 0) {
+ mSensorId = defaultSensorId();
+ }
+ if ((mBuilderFieldsSet & 0x4) == 0) {
+ mDisplayState = defaultDisplayState();
+ }
+ if ((mBuilderFieldsSet & 0x8) == 0) {
+ mAuthenticateReason = defaultAuthenticateReason();
+ }
+ if ((mBuilderFieldsSet & 0x10) == 0) {
+ mWakeReason = defaultWakeReason();
+ }
+ if ((mBuilderFieldsSet & 0x20) == 0) {
+ mOpPackageName = defaultOpPackageName();
+ }
+ if ((mBuilderFieldsSet & 0x40) == 0) {
+ mAttributionTag = defaultAttributionTag();
+ }
+ FaceAuthenticateOptions o = new FaceAuthenticateOptions(
+ mUserId,
+ mSensorId,
+ mDisplayState,
+ mAuthenticateReason,
+ mWakeReason,
+ mOpPackageName,
+ mAttributionTag);
+ return o;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x80) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
+ }
+ }
+
+ @DataClass.Generated(
+ time = 1676508211385L,
+ codegenVersion = "1.0.23",
+ sourceFile = "frameworks/base/core/java/android/hardware/face/FaceAuthenticateOptions.java",
+ inputSignatures = "private final int mUserId\nprivate final int mSensorId\nprivate final @android.hardware.biometrics.AuthenticateOptions.DisplayState int mDisplayState\npublic static final int AUTHENTICATE_REASON_UNKNOWN\npublic static final int AUTHENTICATE_REASON_STARTED_WAKING_UP\npublic static final int AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN\npublic static final int AUTHENTICATE_REASON_ASSISTANT_VISIBLE\npublic static final int AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN\npublic static final int AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED\npublic static final int AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED\npublic static final int AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED\npublic static final int AUTHENTICATE_REASON_QS_EXPANDED\npublic static final int AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER\npublic static final int AUTHENTICATE_REASON_UDFPS_POINTER_DOWN\nprivate final @android.hardware.face.FaceAuthenticateOptions.AuthenticateReason int mAuthenticateReason\nprivate final @android.os.PowerManager.WakeReason int mWakeReason\nprivate @android.annotation.NonNull java.lang.String mOpPackageName\nprivate @android.annotation.Nullable java.lang.String mAttributionTag\nprivate static int defaultUserId()\nprivate static int defaultSensorId()\nprivate static int defaultDisplayState()\nprivate static int defaultAuthenticateReason()\nprivate static int defaultWakeReason()\nprivate static java.lang.String defaultOpPackageName()\nprivate static java.lang.String defaultAttributionTag()\nclass FaceAuthenticateOptions extends java.lang.Object implements [android.hardware.biometrics.AuthenticateOptions, android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genBuilder=true, genSetters=true, genEqualsHashCode=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 96098f853552..55b20e17d4d7 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -194,18 +194,30 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
}
/**
- * Request authentication of a crypto object. This call operates the face recognition hardware
- * and starts capturing images. It terminates when
+ * @deprecated use {@link #authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, Handler, FaceAuthenticateOptions)}.
+ */
+ @Deprecated
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+ public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
+ @NonNull AuthenticationCallback callback, @Nullable Handler handler, int userId) {
+ authenticate(crypto, cancel, callback, handler, new FaceAuthenticateOptions.Builder()
+ .setUserId(userId)
+ .build());
+ }
+
+ /**
+ * Request authentication. This call operates the face recognition hardware and starts capturing images.
+ * It terminates when
* {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
* {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, at
* which point the object is no longer valid. The operation can be canceled by using the
* provided cancel object.
*
- * @param crypto object associated with the call or null if none required.
+ * @param crypto object associated with the call or null if none required
* @param cancel an object that can be used to cancel authentication
* @param callback an object to receive authentication events
* @param handler an optional handler to handle callback events
- * @param userId userId to authenticate for
+ * @param options additional options to customize this request
* @throws IllegalArgumentException if the crypto operation is not supported or is not backed
* by
* <a href="{@docRoot}training/articles/keystore.html">Android
@@ -215,8 +227,8 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
- @NonNull AuthenticationCallback callback, @Nullable Handler handler, int userId,
- boolean isKeyguardBypassEnabled) {
+ @NonNull AuthenticationCallback callback, @Nullable Handler handler,
+ @NonNull FaceAuthenticateOptions options) {
if (callback == null) {
throw new IllegalArgumentException("Must supply an authentication callback");
}
@@ -226,6 +238,9 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
return;
}
+ options.setOpPackageName(mContext.getOpPackageName());
+ options.setAttributionTag(mContext.getAttributionTag());
+
if (mService != null) {
try {
useHandler(handler);
@@ -233,8 +248,8 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
mCryptoObject = crypto;
final long operationId = crypto != null ? crypto.getOpId() : 0;
Trace.beginSection("FaceManager#authenticate");
- final long authId = mService.authenticate(mToken, operationId, userId,
- mServiceReceiver, mContext.getOpPackageName(), isKeyguardBypassEnabled);
+ final long authId = mService.authenticate(
+ mToken, operationId, mServiceReceiver, options);
if (cancel != null) {
cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId));
}
@@ -258,7 +273,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public void detectFace(@NonNull CancellationSignal cancel,
- @NonNull FaceDetectionCallback callback, int userId) {
+ @NonNull FaceDetectionCallback callback, @NonNull FaceAuthenticateOptions options) {
if (mService == null) {
return;
}
@@ -268,11 +283,13 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
return;
}
+ options.setOpPackageName(mContext.getOpPackageName());
+ options.setAttributionTag(mContext.getAttributionTag());
+
mFaceDetectionCallback = callback;
try {
- final long authId = mService.detectFace(
- mToken, userId, mServiceReceiver, mContext.getOpPackageName());
+ final long authId = mService.detectFace(mToken, mServiceReceiver, options);
cancel.setOnCancelListener(new OnFaceDetectionCancelListener(authId));
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception when requesting finger detect", e);
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 5fcc31e3ea25..2857627bf712 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -24,6 +24,7 @@ import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
import android.hardware.face.IFaceServiceReceiver;
import android.hardware.face.Face;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.view.Surface;
@@ -52,14 +53,14 @@ interface IFaceService {
// Authenticate with a face. A requestId is returned that can be used to cancel this operation.
@EnforcePermission("USE_BIOMETRIC_INTERNAL")
- long authenticate(IBinder token, long operationId, int userId, IFaceServiceReceiver receiver,
- String opPackageName, boolean isKeyguardBypassEnabled);
+ long authenticate(IBinder token, long operationId, IFaceServiceReceiver receiver,
+ in FaceAuthenticateOptions options);
// Uses the face hardware to detect for the presence of a face, without giving details
// about accept/reject/lockout. A requestId is returned that can be used to cancel this
// operation.
@EnforcePermission("USE_BIOMETRIC_INTERNAL")
- long detectFace(IBinder token, int userId, IFaceServiceReceiver receiver, String opPackageName);
+ long detectFace(IBinder token, IFaceServiceReceiver receiver, in FaceAuthenticateOptions options);
// This method prepares the service to start authenticating, but doesn't start authentication.
// This is protected by the MANAGE_BIOMETRIC signatuer permission. This method should only be
@@ -68,8 +69,8 @@ interface IFaceService {
// startPreparedClient().
@EnforcePermission("USE_BIOMETRIC_INTERNAL")
void prepareForAuthentication(int sensorId, boolean requireConfirmation, IBinder token,
- long operationId, int userId, IBiometricSensorReceiver sensorReceiver,
- String opPackageName, long requestId, int cookie,
+ long operationId, IBiometricSensorReceiver sensorReceiver,
+ in FaceAuthenticateOptions options, long requestId, int cookie,
boolean allowBackgroundAuthentication);
// Starts authentication with the previously prepared client.
diff --git a/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.aidl b/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.aidl
new file mode 100644
index 000000000000..ad30fab89a3b
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.fingerprint;
+
+parcelable FingerprintAuthenticateOptions;
diff --git a/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.java b/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.java
new file mode 100644
index 000000000000..cecb3172a8d1
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.java
@@ -0,0 +1,447 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.fingerprint;
+
+import static android.hardware.fingerprint.FingerprintManager.SENSOR_ID_ANY;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.biometrics.AuthenticateOptions;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Additional options when requesting Fingerprint authentication or detection.
+ *
+ * @hide
+ */
+@DataClass(
+ genParcelable = true,
+ genAidl = true,
+ genBuilder = true,
+ genSetters = true,
+ genEqualsHashCode = true
+)
+public final class FingerprintAuthenticateOptions implements AuthenticateOptions, Parcelable {
+
+ /** The user id for this operation. */
+ private final int mUserId;
+ private static int defaultUserId() {
+ return 0;
+ }
+
+ /** The sensor id for this operation. */
+ private final int mSensorId;
+ private static int defaultSensorId() {
+ return SENSOR_ID_ANY;
+ }
+
+ /** If enrollment state should be ignored. */
+ private final boolean mIgnoreEnrollmentState;
+ private static boolean defaultIgnoreEnrollmentState() {
+ return false;
+ }
+
+ /** The current doze state of the device. */
+ @AuthenticateOptions.DisplayState
+ private final int mDisplayState;
+ private static int defaultDisplayState() {
+ return DISPLAY_STATE_UNKNOWN;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @NonNull private String mOpPackageName;
+ private static String defaultOpPackageName() {
+ return "";
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @Nullable private String mAttributionTag;
+ private static String defaultAttributionTag() {
+ return null;
+ }
+
+
+
+ // 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/fingerprint/FingerprintAuthenticateOptions.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ /* package-private */ FingerprintAuthenticateOptions(
+ int userId,
+ int sensorId,
+ boolean ignoreEnrollmentState,
+ @AuthenticateOptions.DisplayState int displayState,
+ @NonNull String opPackageName,
+ @Nullable String attributionTag) {
+ this.mUserId = userId;
+ this.mSensorId = sensorId;
+ this.mIgnoreEnrollmentState = ignoreEnrollmentState;
+ this.mDisplayState = displayState;
+ com.android.internal.util.AnnotationValidations.validate(
+ AuthenticateOptions.DisplayState.class, null, mDisplayState);
+ this.mOpPackageName = opPackageName;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mOpPackageName);
+ this.mAttributionTag = attributionTag;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * The user id for this operation.
+ */
+ @DataClass.Generated.Member
+ public int getUserId() {
+ return mUserId;
+ }
+
+ /**
+ * The sensor id for this operation.
+ */
+ @DataClass.Generated.Member
+ public int getSensorId() {
+ return mSensorId;
+ }
+
+ /**
+ * If enrollment state should be ignored.
+ */
+ @DataClass.Generated.Member
+ public boolean isIgnoreEnrollmentState() {
+ return mIgnoreEnrollmentState;
+ }
+
+ /**
+ * The current doze state of the device.
+ */
+ @DataClass.Generated.Member
+ public @AuthenticateOptions.DisplayState int getDisplayState() {
+ return mDisplayState;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull String getOpPackageName() {
+ return mOpPackageName;
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @Nullable String getAttributionTag() {
+ return mAttributionTag;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull FingerprintAuthenticateOptions setOpPackageName(@NonNull String value) {
+ mOpPackageName = value;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mOpPackageName);
+ return this;
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull FingerprintAuthenticateOptions setAttributionTag(@NonNull String value) {
+ mAttributionTag = value;
+ return this;
+ }
+
+ @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(FingerprintAuthenticateOptions other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ FingerprintAuthenticateOptions that = (FingerprintAuthenticateOptions) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && mUserId == that.mUserId
+ && mSensorId == that.mSensorId
+ && mIgnoreEnrollmentState == that.mIgnoreEnrollmentState
+ && mDisplayState == that.mDisplayState
+ && java.util.Objects.equals(mOpPackageName, that.mOpPackageName)
+ && java.util.Objects.equals(mAttributionTag, that.mAttributionTag);
+ }
+
+ @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 + mUserId;
+ _hash = 31 * _hash + mSensorId;
+ _hash = 31 * _hash + Boolean.hashCode(mIgnoreEnrollmentState);
+ _hash = 31 * _hash + mDisplayState;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mOpPackageName);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mAttributionTag);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (mIgnoreEnrollmentState) flg |= 0x4;
+ if (mAttributionTag != null) flg |= 0x20;
+ dest.writeByte(flg);
+ dest.writeInt(mUserId);
+ dest.writeInt(mSensorId);
+ dest.writeInt(mDisplayState);
+ dest.writeString(mOpPackageName);
+ if (mAttributionTag != null) dest.writeString(mAttributionTag);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ FingerprintAuthenticateOptions(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ boolean ignoreEnrollmentState = (flg & 0x4) != 0;
+ int userId = in.readInt();
+ int sensorId = in.readInt();
+ int displayState = in.readInt();
+ String opPackageName = in.readString();
+ String attributionTag = (flg & 0x20) == 0 ? null : in.readString();
+
+ this.mUserId = userId;
+ this.mSensorId = sensorId;
+ this.mIgnoreEnrollmentState = ignoreEnrollmentState;
+ this.mDisplayState = displayState;
+ com.android.internal.util.AnnotationValidations.validate(
+ AuthenticateOptions.DisplayState.class, null, mDisplayState);
+ this.mOpPackageName = opPackageName;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mOpPackageName);
+ this.mAttributionTag = attributionTag;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<FingerprintAuthenticateOptions> CREATOR
+ = new Parcelable.Creator<FingerprintAuthenticateOptions>() {
+ @Override
+ public FingerprintAuthenticateOptions[] newArray(int size) {
+ return new FingerprintAuthenticateOptions[size];
+ }
+
+ @Override
+ public FingerprintAuthenticateOptions createFromParcel(@NonNull android.os.Parcel in) {
+ return new FingerprintAuthenticateOptions(in);
+ }
+ };
+
+ /**
+ * A builder for {@link FingerprintAuthenticateOptions}
+ */
+ @SuppressWarnings("WeakerAccess")
+ @DataClass.Generated.Member
+ public static final class Builder {
+
+ private int mUserId;
+ private int mSensorId;
+ private boolean mIgnoreEnrollmentState;
+ private @AuthenticateOptions.DisplayState int mDisplayState;
+ private @NonNull String mOpPackageName;
+ private @Nullable String mAttributionTag;
+
+ private long mBuilderFieldsSet = 0L;
+
+ public Builder() {
+ }
+
+ /**
+ * The user id for this operation.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setUserId(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x1;
+ mUserId = value;
+ return this;
+ }
+
+ /**
+ * The sensor id for this operation.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setSensorId(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2;
+ mSensorId = value;
+ return this;
+ }
+
+ /**
+ * If enrollment state should be ignored.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setIgnoreEnrollmentState(boolean value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4;
+ mIgnoreEnrollmentState = value;
+ return this;
+ }
+
+ /**
+ * The current doze state of the device.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setDisplayState(@AuthenticateOptions.DisplayState int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x8;
+ mDisplayState = value;
+ return this;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setOpPackageName(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x10;
+ mOpPackageName = value;
+ return this;
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setAttributionTag(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x20;
+ mAttributionTag = value;
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @NonNull FingerprintAuthenticateOptions build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x40; // Mark builder used
+
+ if ((mBuilderFieldsSet & 0x1) == 0) {
+ mUserId = defaultUserId();
+ }
+ if ((mBuilderFieldsSet & 0x2) == 0) {
+ mSensorId = defaultSensorId();
+ }
+ if ((mBuilderFieldsSet & 0x4) == 0) {
+ mIgnoreEnrollmentState = defaultIgnoreEnrollmentState();
+ }
+ if ((mBuilderFieldsSet & 0x8) == 0) {
+ mDisplayState = defaultDisplayState();
+ }
+ if ((mBuilderFieldsSet & 0x10) == 0) {
+ mOpPackageName = defaultOpPackageName();
+ }
+ if ((mBuilderFieldsSet & 0x20) == 0) {
+ mAttributionTag = defaultAttributionTag();
+ }
+ FingerprintAuthenticateOptions o = new FingerprintAuthenticateOptions(
+ mUserId,
+ mSensorId,
+ mIgnoreEnrollmentState,
+ mDisplayState,
+ mOpPackageName,
+ mAttributionTag);
+ return o;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x40) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
+ }
+ }
+
+ @DataClass.Generated(
+ time = 1676508212083L,
+ codegenVersion = "1.0.23",
+ sourceFile = "frameworks/base/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.java",
+ inputSignatures = "private final int mUserId\nprivate final int mSensorId\nprivate final boolean mIgnoreEnrollmentState\nprivate final @android.hardware.biometrics.AuthenticateOptions.DisplayState int mDisplayState\nprivate @android.annotation.NonNull java.lang.String mOpPackageName\nprivate @android.annotation.Nullable java.lang.String mAttributionTag\nprivate static int defaultUserId()\nprivate static int defaultSensorId()\nprivate static boolean defaultIgnoreEnrollmentState()\nprivate static int defaultDisplayState()\nprivate static java.lang.String defaultOpPackageName()\nprivate static java.lang.String defaultAttributionTag()\nclass FingerprintAuthenticateOptions extends java.lang.Object implements [android.hardware.biometrics.AuthenticateOptions, android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genBuilder=true, genSetters=true, genEqualsHashCode=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index d9f8f8e0e715..eb8136e39d29 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -577,8 +577,10 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
/**
* Per-user version of authenticate.
+ * @deprecated use {@link #authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, Handler, FingerprintAuthenticateOptions)}.
* @hide
*/
+ @Deprecated
@RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
@NonNull AuthenticationCallback callback, Handler handler, int userId) {
@@ -587,13 +589,29 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
/**
* Per-user and per-sensor version of authenticate.
+ * @deprecated use {@link #authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, Handler, FingerprintAuthenticateOptions)}.
* @hide
*/
+ @Deprecated
@RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
@NonNull AuthenticationCallback callback, Handler handler, int sensorId, int userId,
int flags) {
+ authenticate(crypto, cancel, callback, handler, new FingerprintAuthenticateOptions.Builder()
+ .setSensorId(sensorId)
+ .setUserId(userId)
+ .setIgnoreEnrollmentState(flags != 0)
+ .build());
+ }
+ /**
+ * Version of authenticate with additional options.
+ * @hide
+ */
+ @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
+ public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
+ @NonNull AuthenticationCallback callback, @NonNull Handler handler,
+ @NonNull FingerprintAuthenticateOptions options) {
FrameworkStatsLog.write(FrameworkStatsLog.AUTH_DEPRECATED_API_USED,
AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_AUTHENTICATE,
mContext.getApplicationInfo().uid,
@@ -608,7 +626,8 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
return;
}
- final boolean ignoreEnrollmentState = flags == 0 ? false : true;
+ options.setOpPackageName(mContext.getOpPackageName());
+ options.setAttributionTag(mContext.getAttributionTag());
if (mService != null) {
try {
@@ -616,16 +635,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
mAuthenticationCallback = callback;
mCryptoObject = crypto;
final long operationId = crypto != null ? crypto.getOpId() : 0;
- final long authId =
- mService.authenticate(
- mToken,
- operationId,
- sensorId,
- userId,
- mServiceReceiver,
- mContext.getOpPackageName(),
- mContext.getAttributionTag(),
- ignoreEnrollmentState);
+ final long authId = mService.authenticate(mToken, operationId, mServiceReceiver, options);
if (cancel != null) {
cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId));
}
@@ -647,7 +657,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public void detectFingerprint(@NonNull CancellationSignal cancel,
- @NonNull FingerprintDetectionCallback callback, int userId) {
+ @NonNull FingerprintDetectionCallback callback, @NonNull FingerprintAuthenticateOptions options) {
if (mService == null) {
return;
}
@@ -657,11 +667,13 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
return;
}
+ options.setOpPackageName(mContext.getOpPackageName());
+ options.setAttributionTag(mContext.getAttributionTag());
+
mFingerprintDetectionCallback = callback;
try {
- final long authId = mService.detectFingerprint(mToken, userId, mServiceReceiver,
- mContext.getOpPackageName());
+ final long authId = mService.detectFingerprint(mToken, mServiceReceiver, options);
cancel.setOnCancelListener(new OnFingerprintDetectionCancelListener(authId));
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception when requesting finger detect", e);
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 6f35713d434f..e3ae299be730 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -29,6 +29,7 @@ import android.hardware.fingerprint.IUdfpsOverlayController;
import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.IUdfpsOverlay;
import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import java.util.List;
@@ -56,16 +57,15 @@ interface IFingerprintService {
// Authenticate with a fingerprint. This is protected by USE_FINGERPRINT/USE_BIOMETRIC
// permission. This is effectively deprecated, since it only comes through FingerprintManager
// now. A requestId is returned that can be used to cancel this operation.
- long authenticate(IBinder token, long operationId, int sensorId, int userId,
- IFingerprintServiceReceiver receiver, String opPackageName, String attributionTag,
- boolean shouldIgnoreEnrollmentState);
+ long authenticate(IBinder token, long operationId, IFingerprintServiceReceiver receiver,
+ in FingerprintAuthenticateOptions options);
// Uses the fingerprint hardware to detect for the presence of a finger, without giving details
// about accept/reject/lockout. A requestId is returned that can be used to cancel this
// operation.
@EnforcePermission("USE_BIOMETRIC_INTERNAL")
- long detectFingerprint(IBinder token, int userId, IFingerprintServiceReceiver receiver,
- String opPackageName);
+ long detectFingerprint(IBinder token, IFingerprintServiceReceiver receiver,
+ in FingerprintAuthenticateOptions options);
// This method prepares the service to start authenticating, but doesn't start authentication.
// This is protected by the MANAGE_BIOMETRIC signatuer permission. This method should only be
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 66442bb9e2c9..1a5613ebef02 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1352,7 +1352,6 @@ public class KeyEvent extends InputEvent implements Parcelable {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private int mSource;
private int mDisplayId = INVALID_DISPLAY;
- // NOTE: mHmac is private and not used in this class, but it's used on native side / parcel.
private @Nullable byte[] mHmac;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private int mMetaState;
@@ -1378,7 +1377,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
*/
private long mEventTime;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private @Nullable String mCharacters;
+ private String mCharacters;
public interface Callback {
/**
@@ -1442,11 +1441,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
private static native int nativeKeyCodeFromString(String keyCode);
private static native int nativeNextId();
- private KeyEvent() {
- this(/* downTime= */ 0, /* eventTime= */ 0, /* action= */ 0, /* code= */0, /* repeat= */ 0,
- /* metaState= */ 0, /* deviceId= */ 0, /* scancode= */ 0, /* flags= */ 0,
- /* source= */ 0);
- }
+ private KeyEvent() {}
/**
* Create a new key event.
@@ -1456,9 +1451,11 @@ public class KeyEvent extends InputEvent implements Parcelable {
* @param code The key code.
*/
public KeyEvent(int action, int code) {
- this(/* downTime= */ 0, /* eventTime= */ 0, action, code, /* repeat= */ 0,
- /* metaState= */ 0, /* deviceId= */ KeyCharacterMap.VIRTUAL_KEYBOARD,
- /* scancode= */ 0, /* flags= */ 0, /* source= */ 0);
+ mId = nativeNextId();
+ mAction = action;
+ mKeyCode = code;
+ mRepeatCount = 0;
+ mDeviceId = KeyCharacterMap.VIRTUAL_KEYBOARD;
}
/**
@@ -1476,9 +1473,13 @@ public class KeyEvent extends InputEvent implements Parcelable {
*/
public KeyEvent(long downTime, long eventTime, int action,
int code, int repeat) {
- this(downTime, eventTime, action, code, repeat, /* metaState= */ 0,
- KeyCharacterMap.VIRTUAL_KEYBOARD, /* scancode= */ 0, /* flags= */ 0,
- /* source= */ 0);
+ mId = nativeNextId();
+ mDownTime = TimeUnit.NANOSECONDS.convert(downTime, TimeUnit.MILLISECONDS);
+ mEventTime = TimeUnit.NANOSECONDS.convert(eventTime, TimeUnit.MILLISECONDS);
+ mAction = action;
+ mKeyCode = code;
+ mRepeatCount = repeat;
+ mDeviceId = KeyCharacterMap.VIRTUAL_KEYBOARD;
}
/**
@@ -1497,8 +1498,14 @@ public class KeyEvent extends InputEvent implements Parcelable {
*/
public KeyEvent(long downTime, long eventTime, int action,
int code, int repeat, int metaState) {
- this(downTime, eventTime, action, code, repeat, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD,
- /* scancode= */ 0, /* flags= */ 0, /* source= */ 0);
+ mId = nativeNextId();
+ mDownTime = TimeUnit.NANOSECONDS.convert(downTime, TimeUnit.MILLISECONDS);
+ mEventTime = TimeUnit.NANOSECONDS.convert(eventTime, TimeUnit.MILLISECONDS);
+ mAction = action;
+ mKeyCode = code;
+ mRepeatCount = repeat;
+ mMetaState = metaState;
+ mDeviceId = KeyCharacterMap.VIRTUAL_KEYBOARD;
}
/**
@@ -1520,8 +1527,15 @@ public class KeyEvent extends InputEvent implements Parcelable {
public KeyEvent(long downTime, long eventTime, int action,
int code, int repeat, int metaState,
int deviceId, int scancode) {
- this(downTime, eventTime, action, code, repeat, metaState, deviceId, scancode,
- /* flags= */ 0, /* source= */ 0);
+ mId = nativeNextId();
+ mDownTime = TimeUnit.NANOSECONDS.convert(downTime, TimeUnit.MILLISECONDS);
+ mEventTime = TimeUnit.NANOSECONDS.convert(eventTime, TimeUnit.MILLISECONDS);
+ mAction = action;
+ mKeyCode = code;
+ mRepeatCount = repeat;
+ mMetaState = metaState;
+ mDeviceId = deviceId;
+ mScanCode = scancode;
}
/**
@@ -1544,8 +1558,16 @@ public class KeyEvent extends InputEvent implements Parcelable {
public KeyEvent(long downTime, long eventTime, int action,
int code, int repeat, int metaState,
int deviceId, int scancode, int flags) {
- this(downTime, eventTime, action, code, repeat, metaState, deviceId, scancode, flags,
- /* source= */ 0);
+ mId = nativeNextId();
+ mDownTime = TimeUnit.NANOSECONDS.convert(downTime, TimeUnit.MILLISECONDS);
+ mEventTime = TimeUnit.NANOSECONDS.convert(eventTime, TimeUnit.MILLISECONDS);
+ mAction = action;
+ mKeyCode = code;
+ mRepeatCount = repeat;
+ mMetaState = metaState;
+ mDeviceId = deviceId;
+ mScanCode = scancode;
+ mFlags = flags;
}
/**
@@ -1569,8 +1591,6 @@ public class KeyEvent extends InputEvent implements Parcelable {
public KeyEvent(long downTime, long eventTime, int action,
int code, int repeat, int metaState,
int deviceId, int scancode, int flags, int source) {
- // NOTE: this is the canonical constructor, every other constructor that takes KeyEvent
- // attributes should call it
mId = nativeNextId();
mDownTime = TimeUnit.NANOSECONDS.convert(downTime, TimeUnit.MILLISECONDS);
mEventTime = TimeUnit.NANOSECONDS.convert(eventTime, TimeUnit.MILLISECONDS);
@@ -1597,18 +1617,36 @@ public class KeyEvent extends InputEvent implements Parcelable {
* @param flags The flags for this key event
*/
public KeyEvent(long time, String characters, int deviceId, int flags) {
- this(/* downTime= */ time, /* eventTime= */ time, ACTION_MULTIPLE, KEYCODE_UNKNOWN,
- /* repeat= */ 0, /* metaState= */ 0, deviceId, /* scancode= */ 0, flags,
- /* source= */ InputDevice.SOURCE_KEYBOARD);
+ mId = nativeNextId();
+ mDownTime = TimeUnit.NANOSECONDS.convert(time, TimeUnit.MILLISECONDS);
+ mEventTime = TimeUnit.NANOSECONDS.convert(time, TimeUnit.MILLISECONDS);
+ mCharacters = characters;
+ mAction = ACTION_MULTIPLE;
+ mKeyCode = KEYCODE_UNKNOWN;
+ mRepeatCount = 0;
+ mDeviceId = deviceId;
+ mFlags = flags;
+ mSource = InputDevice.SOURCE_KEYBOARD;
}
/**
* Make an exact copy of an existing key event.
*/
public KeyEvent(KeyEvent origEvent) {
- this(origEvent, origEvent.mId, origEvent.mEventTime, origEvent.mAction,
- origEvent.mRepeatCount, origEvent.mHmac == null ? null : origEvent.mHmac.clone(),
- origEvent.mCharacters);
+ mId = origEvent.mId;
+ mDownTime = origEvent.mDownTime;
+ mEventTime = origEvent.mEventTime;
+ mAction = origEvent.mAction;
+ mKeyCode = origEvent.mKeyCode;
+ mRepeatCount = origEvent.mRepeatCount;
+ mMetaState = origEvent.mMetaState;
+ mDeviceId = origEvent.mDeviceId;
+ mSource = origEvent.mSource;
+ mDisplayId = origEvent.mDisplayId;
+ mHmac = origEvent.mHmac == null ? null : origEvent.mHmac.clone();
+ mScanCode = origEvent.mScanCode;
+ mFlags = origEvent.mFlags;
+ mCharacters = origEvent.mCharacters;
}
/**
@@ -1624,30 +1662,20 @@ public class KeyEvent extends InputEvent implements Parcelable {
*/
@Deprecated
public KeyEvent(KeyEvent origEvent, long eventTime, int newRepeat) {
- // Not an exact copy so assign a new ID.
- // Don't copy HMAC, it will be invalid because eventTime is changing
- this(origEvent, nativeNextId(),
- TimeUnit.NANOSECONDS.convert(eventTime, TimeUnit.MILLISECONDS), origEvent.mAction,
- newRepeat, /* hmac= */ null, origEvent.mCharacters);
- }
-
- // This is the canonical constructor that should be called for constructors that take a KeyEvent
- private KeyEvent(KeyEvent origEvent, int id, long eventTime, int action, int newRepeat,
- @Nullable byte[] hmac, @Nullable String characters) {
- mId = id;
+ mId = nativeNextId(); // Not an exact copy so assign a new ID.
mDownTime = origEvent.mDownTime;
- mEventTime = eventTime;
- mAction = action;
+ mEventTime = TimeUnit.NANOSECONDS.convert(eventTime, TimeUnit.MILLISECONDS);
+ mAction = origEvent.mAction;
mKeyCode = origEvent.mKeyCode;
mRepeatCount = newRepeat;
mMetaState = origEvent.mMetaState;
mDeviceId = origEvent.mDeviceId;
mSource = origEvent.mSource;
mDisplayId = origEvent.mDisplayId;
- mHmac = hmac;
+ mHmac = null; // Don't copy HMAC, it will be invalid because eventTime is changing
mScanCode = origEvent.mScanCode;
mFlags = origEvent.mFlags;
- mCharacters = characters;
+ mCharacters = origEvent.mCharacters;
}
private static KeyEvent obtain() {
@@ -1829,11 +1857,21 @@ public class KeyEvent extends InputEvent implements Parcelable {
* @param action The new action code of the event.
*/
private KeyEvent(KeyEvent origEvent, int action) {
- // Not an exact copy so assign a new ID
- // Don't copy the hmac, it will be invalid since action is changing
- // Don't copy mCharacters, since one way or the other we'll lose it when changing action.
- this(origEvent, nativeNextId(), origEvent.mEventTime, action, origEvent.mRepeatCount,
- /* hmac= */ null, /* characters= */ null);
+ mId = nativeNextId(); // Not an exact copy so assign a new ID.
+ mDownTime = origEvent.mDownTime;
+ mEventTime = origEvent.mEventTime;
+ mAction = action;
+ mKeyCode = origEvent.mKeyCode;
+ mRepeatCount = origEvent.mRepeatCount;
+ mMetaState = origEvent.mMetaState;
+ mDeviceId = origEvent.mDeviceId;
+ mSource = origEvent.mSource;
+ mDisplayId = origEvent.mDisplayId;
+ mHmac = null; // Don't copy the hmac, it will be invalid since action is changing
+ mScanCode = origEvent.mScanCode;
+ mFlags = origEvent.mFlags;
+ // Don't copy mCharacters, since one way or the other we'll lose it
+ // when changing the action.
}
/**
@@ -3181,8 +3219,6 @@ public class KeyEvent extends InputEvent implements Parcelable {
}
private KeyEvent(Parcel in) {
- // NOTE: ideally this constructor should call the canonical one, but that would require
- // changing the order the fields are written to the parcel, which could break native code
mId = in.readInt();
mDeviceId = in.readInt();
mSource = in.readInt();
diff --git a/core/java/android/view/contentcapture/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java
index 59b5286f6fc5..34c7b8b9889f 100644
--- a/core/java/android/view/contentcapture/ContentCaptureContext.java
+++ b/core/java/android/view/contentcapture/ContentCaptureContext.java
@@ -82,11 +82,19 @@ public final class ContentCaptureContext implements Parcelable {
@SystemApi
public static final int FLAG_RECONNECTED = 0x4;
+ /**
+ * Flag used to disable flush when receiving a VIEW_TREE_APPEARING event.
+ *
+ * @hide
+ */
+ public static final int FLAG_DISABLED_FLUSH_FOR_VIEW_TREE_APPEARING = 1 << 3;
+
/** @hide */
@IntDef(flag = true, prefix = { "FLAG_" }, value = {
FLAG_DISABLED_BY_APP,
FLAG_DISABLED_BY_FLAG_SECURE,
- FLAG_RECONNECTED
+ FLAG_RECONNECTED,
+ FLAG_DISABLED_FLUSH_FOR_VIEW_TREE_APPEARING
})
@Retention(RetentionPolicy.SOURCE)
@interface ContextCreationFlags{}
@@ -252,7 +260,8 @@ public final class ContentCaptureContext implements Parcelable {
* Gets the flags associated with this context.
*
* @return any combination of {@link #FLAG_DISABLED_BY_FLAG_SECURE},
- * {@link #FLAG_DISABLED_BY_APP} and {@link #FLAG_RECONNECTED}.
+ * {@link #FLAG_DISABLED_BY_APP}, {@link #FLAG_RECONNECTED} and {@link
+ * #FLAG_DISABLED_FLUSH_FOR_VIEW_TREE_APPEARING}.
*
* @hide
*/
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 497f0668107f..668351b949c1 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -51,6 +51,7 @@ import android.view.WindowManager;
import android.view.contentcapture.ContentCaptureSession.FlushReason;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.SyncResultReceiver;
import java.io.PrintWriter;
@@ -343,6 +344,14 @@ public final class ContentCaptureManager {
*/
public static final String DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT = "idle_unbind_timeout";
+ /**
+ * Sets to disable flush when receiving a VIEW_TREE_APPEARING event.
+ *
+ * @hide
+ */
+ public static final String DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING =
+ "disable_flush_for_view_tree_appearing";
+
/** @hide */
@TestApi
public static final int LOGGING_LEVEL_OFF = 0;
@@ -373,6 +382,8 @@ public final class ContentCaptureManager {
public static final int DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS = 1_000;
/** @hide */
public static final int DEFAULT_LOG_HISTORY_SIZE = 10;
+ /** @hide */
+ public static final boolean DEFAULT_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING = false;
private final Object mLock = new Object();
@@ -448,6 +459,7 @@ public final class ContentCaptureManager {
mOptions = Objects.requireNonNull(options, "options cannot be null");
ContentCaptureHelper.setLoggingLevel(mOptions.loggingLevel);
+ setFlushViewTreeAppearingEventDisabled(mOptions.disableFlushForViewTreeAppearing);
if (sVerbose) Log.v(TAG, "Constructor for " + context.getPackageName());
@@ -687,6 +699,38 @@ public final class ContentCaptureManager {
}
/**
+ * Explicitly sets enable or disable flush for view tree appearing event.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public void setFlushViewTreeAppearingEventDisabled(boolean disabled) {
+ if (sDebug) {
+ Log.d(TAG, "setFlushViewTreeAppearingEventDisabled(): setting to " + disabled);
+ }
+
+ synchronized (mLock) {
+ if (disabled) {
+ mFlags |= ContentCaptureContext.FLAG_DISABLED_FLUSH_FOR_VIEW_TREE_APPEARING;
+ } else {
+ mFlags &= ~ContentCaptureContext.FLAG_DISABLED_FLUSH_FOR_VIEW_TREE_APPEARING;
+ }
+ }
+ }
+
+ /**
+ * Gets whether content capture is needed to flush for view tree appearing event.
+ *
+ * @hide
+ */
+ public boolean getFlushViewTreeAppearingEventDisabled() {
+ synchronized (mLock) {
+ return (mFlags & ContentCaptureContext.FLAG_DISABLED_FLUSH_FOR_VIEW_TREE_APPEARING)
+ != 0;
+ }
+ }
+
+ /**
* Gets whether content capture is enabled for the given user.
*
* <p>This method is typically used by the content capture service settings page, so it can
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 0da7e3b95863..b7f03e1d6d72 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -177,6 +177,10 @@ public abstract class ContentCaptureSession implements AutoCloseable {
public static final int FLUSH_REASON_SESSION_CONNECTED = 7;
/** @hide */
public static final int FLUSH_REASON_FORCE_FLUSH = 8;
+ /** @hide */
+ public static final int FLUSH_REASON_VIEW_TREE_APPEARING = 9;
+ /** @hide */
+ public static final int FLUSH_REASON_VIEW_TREE_APPEARED = 10;
@ChangeId
@EnabledSince(targetSdkVersion = UPSIDE_DOWN_CAKE)
@@ -191,7 +195,9 @@ public abstract class ContentCaptureSession implements AutoCloseable {
FLUSH_REASON_IDLE_TIMEOUT,
FLUSH_REASON_TEXT_CHANGE_TIMEOUT,
FLUSH_REASON_SESSION_CONNECTED,
- FLUSH_REASON_FORCE_FLUSH
+ FLUSH_REASON_FORCE_FLUSH,
+ FLUSH_REASON_VIEW_TREE_APPEARING,
+ FLUSH_REASON_VIEW_TREE_APPEARED
})
@Retention(RetentionPolicy.SOURCE)
public @interface FlushReason{}
@@ -671,6 +677,10 @@ public abstract class ContentCaptureSession implements AutoCloseable {
return "CONNECTED";
case FLUSH_REASON_FORCE_FLUSH:
return "FORCE_FLUSH";
+ case FLUSH_REASON_VIEW_TREE_APPEARING:
+ return "VIEW_TREE_APPEARING";
+ case FLUSH_REASON_VIEW_TREE_APPEARED:
+ return "VIEW_TREE_APPEARED";
default:
return "UNKOWN-" + reason;
}
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index 8c040e482cdf..6ddfcb825acc 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -458,6 +458,12 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
case ContentCaptureEvent.TYPE_SESSION_FINISHED:
flushReason = FLUSH_REASON_SESSION_FINISHED;
break;
+ case ContentCaptureEvent.TYPE_VIEW_TREE_APPEARING:
+ flushReason = FLUSH_REASON_VIEW_TREE_APPEARING;
+ break;
+ case ContentCaptureEvent.TYPE_VIEW_TREE_APPEARED:
+ flushReason = FLUSH_REASON_VIEW_TREE_APPEARED;
+ break;
default:
flushReason = forceFlush ? FLUSH_REASON_FORCE_FLUSH : FLUSH_REASON_FULL;
}
@@ -774,7 +780,11 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
/** Public because is also used by ViewRootImpl */
public void notifyViewTreeEvent(int sessionId, boolean started) {
final int type = started ? TYPE_VIEW_TREE_APPEARING : TYPE_VIEW_TREE_APPEARED;
- mHandler.post(() -> sendEvent(new ContentCaptureEvent(sessionId, type), FORCE_FLUSH));
+ final boolean disableFlush = mManager.getFlushViewTreeAppearingEventDisabled();
+
+ mHandler.post(() -> sendEvent(
+ new ContentCaptureEvent(sessionId, type),
+ disableFlush ? !started : FORCE_FLUSH));
}
void notifySessionResumed(int sessionId) {
diff --git a/core/java/android/view/textclassifier/TextLinks.java b/core/java/android/view/textclassifier/TextLinks.java
index 445e9ecff54f..b5b6f5ae8af8 100644
--- a/core/java/android/view/textclassifier/TextLinks.java
+++ b/core/java/android/view/textclassifier/TextLinks.java
@@ -478,7 +478,7 @@ public final class TextLinks implements Parcelable {
/**
* Sets the entity configuration to use. This determines what types of entities the
* TextClassifier will look for.
- * Set to {@code null} for the default entity config and teh TextClassifier will
+ * Set to {@code null} for the default entity config and the TextClassifier will
* automatically determine what links to generate.
*
* @return this builder
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index a33906267736..18874f768929 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -6717,6 +6717,10 @@ public class RemoteViews implements Parcelable, Filter {
Log.w(LOG_TAG, "getLaunchOptions: view.getDisplay() is null!",
new Exception());
}
+ // If the user interacts with a visible element it is safe to assume they consent that
+ // something is going to start.
+ opts.setPendingIntentBackgroundActivityStartMode(
+ ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
return Pair.create(intent, opts);
}
}
diff --git a/core/tests/coretests/src/android/hardware/face/FaceManagerTest.java b/core/tests/coretests/src/android/hardware/face/FaceManagerTest.java
new file mode 100644
index 000000000000..9b1f0cd9e8da
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/face/FaceManagerTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.face;
+
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.res.Resources;
+import android.os.CancellationSignal;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.test.TestLooper;
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.MockitoRule;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Presubmit
+@RunWith(MockitoJUnitRunner.class)
+public class FaceManagerTest {
+ private static final int USER_ID = 4;
+ private static final String PACKAGE_NAME = "f.m.test";
+ private static final String ATTRIBUTION_TAG = "blue";
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private IFaceService mService;
+ @Mock
+ private FaceManager.AuthenticationCallback mAuthCallback;
+
+ @Captor
+ private ArgumentCaptor<IFaceAuthenticatorsRegisteredCallback> mCaptor;
+ @Captor
+ private ArgumentCaptor<FaceAuthenticateOptions> mOptionsCaptor;
+
+ private List<FaceSensorPropertiesInternal> mProps;
+ private TestLooper mLooper;
+ private Handler mHandler;
+ private FaceManager mFaceManager;
+
+ @Before
+ public void setUp() throws Exception {
+ mLooper = new TestLooper();
+ mHandler = new Handler(mLooper.getLooper());
+
+ when(mContext.getMainLooper()).thenReturn(mLooper.getLooper());
+ when(mContext.getOpPackageName()).thenReturn(PACKAGE_NAME);
+ when(mContext.getAttributionTag()).thenReturn(ATTRIBUTION_TAG);
+ when(mContext.getApplicationInfo()).thenReturn(new ApplicationInfo());
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getString(anyInt())).thenReturn("string");
+
+ mFaceManager = new FaceManager(mContext, mService);
+ mProps = List.of(new FaceSensorPropertiesInternal(
+ 0 /* id */,
+ FaceSensorProperties.STRENGTH_STRONG,
+ 1 /* maxTemplatesAllowed */,
+ new ArrayList<>() /* componentInfo */,
+ FaceSensorProperties.TYPE_UNKNOWN,
+ true /* supportsFaceDetection */,
+ true /* supportsSelfIllumination */,
+ false /* resetLockoutRequiresChallenge */));
+ }
+
+ @Test
+ public void getSensorPropertiesInternal_noBinderCalls() throws RemoteException {
+ verify(mService).addAuthenticatorsRegisteredCallback(mCaptor.capture());
+
+ mCaptor.getValue().onAllAuthenticatorsRegistered(mProps);
+ List<FaceSensorPropertiesInternal> actual = mFaceManager.getSensorPropertiesInternal();
+
+ assertThat(actual).isEqualTo(mProps);
+ verify(mService, never()).getSensorPropertiesInternal(any());
+ }
+
+ @Test
+ public void authenticate_withOptions() throws Exception {
+ mFaceManager.authenticate(null, new CancellationSignal(), mAuthCallback, mHandler,
+ new FaceAuthenticateOptions.Builder()
+ .setUserId(USER_ID)
+ .setOpPackageName("some.thing")
+ .setAttributionTag(null)
+ .build());
+
+ verify(mService).authenticate(any(IBinder.class), eq(0L),
+ any(IFaceServiceReceiver.class), mOptionsCaptor.capture());
+
+ assertThat(mOptionsCaptor.getValue()).isEqualTo(
+ new FaceAuthenticateOptions.Builder()
+ .setUserId(USER_ID)
+ .setOpPackageName(PACKAGE_NAME)
+ .setAttributionTag(ATTRIBUTION_TAG)
+ .build()
+ );
+ }
+
+ @Test
+ public void authenticate_errorWhenUnavailable() throws Exception {
+ when(mService.authenticate(any(), anyLong(), any(), any()))
+ .thenThrow(new RemoteException());
+
+ mFaceManager.authenticate(null, new CancellationSignal(),
+ mAuthCallback, mHandler,
+ new FaceAuthenticateOptions.Builder().build());
+
+ verify(mAuthCallback).onAuthenticationError(eq(FACE_ERROR_HW_UNAVAILABLE), any());
+ }
+}
diff --git a/core/tests/coretests/src/android/hardware/face/OWNERS b/core/tests/coretests/src/android/hardware/face/OWNERS
new file mode 100644
index 000000000000..6a2192a2c7fb
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/face/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/biometrics/OWNERS
diff --git a/core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java b/core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java
new file mode 100644
index 000000000000..f31903a73111
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.fingerprint;
+
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.res.Resources;
+import android.os.CancellationSignal;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.test.TestLooper;
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.MockitoRule;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Presubmit
+@RunWith(MockitoJUnitRunner.class)
+public class FingerprintManagerTest {
+ private static final int USER_ID = 9;
+ private static final String PACKAGE_NAME = "finger.food.test";
+ private static final String ATTRIBUTION_TAG = "taz";
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private IFingerprintService mService;
+ @Mock
+ private FingerprintManager.AuthenticationCallback mAuthCallback;
+
+ @Captor
+ private ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mCaptor;
+ @Captor
+ private ArgumentCaptor<FingerprintAuthenticateOptions> mOptionsCaptor;
+
+ private List<FingerprintSensorPropertiesInternal> mProps;
+ private TestLooper mLooper;
+ private Handler mHandler;
+ private FingerprintManager mFingerprintManager;
+
+ @Before
+ public void setUp() throws Exception {
+ mLooper = new TestLooper();
+ mHandler = new Handler(mLooper.getLooper());
+
+ when(mContext.getMainLooper()).thenReturn(mLooper.getLooper());
+ when(mContext.getOpPackageName()).thenReturn(PACKAGE_NAME);
+ when(mContext.getAttributionTag()).thenReturn(ATTRIBUTION_TAG);
+ when(mContext.getApplicationInfo()).thenReturn(new ApplicationInfo());
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getString(anyInt())).thenReturn("string");
+
+ mFingerprintManager = new FingerprintManager(mContext, mService);
+ mProps = List.of(new FingerprintSensorPropertiesInternal(
+ 0 /* sensorId */,
+ FingerprintSensorProperties.STRENGTH_STRONG,
+ 1 /* maxEnrollmentsPerUser */,
+ new ArrayList<>() /* componentInfo */,
+ FingerprintSensorProperties.TYPE_UNKNOWN,
+ true /* halControlsIllumination */,
+ true /* resetLockoutRequiresHardwareAuthToken */,
+ new ArrayList<>() /* sensorLocations */));
+ }
+
+ @Test
+ public void getSensorPropertiesInternal_noBinderCalls() throws RemoteException {
+ verify(mService).addAuthenticatorsRegisteredCallback(mCaptor.capture());
+
+ mCaptor.getValue().onAllAuthenticatorsRegistered(mProps);
+ List<FingerprintSensorPropertiesInternal> actual =
+ mFingerprintManager.getSensorPropertiesInternal();
+
+ assertThat(actual).isEqualTo(mProps);
+ verify(mService, never()).getSensorPropertiesInternal(any());
+ }
+
+ @Test
+ public void authenticate_withOptions() throws Exception {
+ mFingerprintManager.authenticate(null, new CancellationSignal(), mAuthCallback, mHandler,
+ new FingerprintAuthenticateOptions.Builder()
+ .setUserId(USER_ID)
+ .setOpPackageName("some.thing")
+ .setAttributionTag(null)
+ .build());
+
+ verify(mService).authenticate(any(IBinder.class), eq(0L),
+ any(IFingerprintServiceReceiver.class), mOptionsCaptor.capture());
+
+ assertThat(mOptionsCaptor.getValue()).isEqualTo(
+ new FingerprintAuthenticateOptions.Builder()
+ .setUserId(USER_ID)
+ .setOpPackageName(PACKAGE_NAME)
+ .setAttributionTag(ATTRIBUTION_TAG)
+ .build()
+ );
+ }
+
+ @Test
+ public void authenticate_errorWhenUnavailable() throws Exception {
+ when(mService.authenticate(any(), anyLong(), any(), any()))
+ .thenThrow(new RemoteException());
+
+ mFingerprintManager.authenticate(null, new CancellationSignal(),
+ mAuthCallback, mHandler,
+ new FingerprintAuthenticateOptions.Builder().build());
+
+ verify(mAuthCallback).onAuthenticationError(eq(FINGERPRINT_ERROR_HW_UNAVAILABLE), any());
+ }
+}
diff --git a/core/tests/coretests/src/android/hardware/fingerprint/OWNERS b/core/tests/coretests/src/android/hardware/fingerprint/OWNERS
new file mode 100644
index 000000000000..6a2192a2c7fb
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/fingerprint/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/biometrics/OWNERS
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
index eae1bbc930d4..17ed4c478350 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
@@ -15,6 +15,8 @@
*/
package android.view.contentcapture;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Mockito.mock;
import static org.testng.Assert.assertThrows;
@@ -54,4 +56,19 @@ public class ContentCaptureManagerTest {
assertThrows(NullPointerException.class, () -> manager.removeData(null));
}
+
+ @Test
+ @SuppressWarnings("GuardedBy")
+ public void testFlushViewTreeAppearingEventDisabled_setAndGet() {
+ final IContentCaptureManager mockService = mock(IContentCaptureManager.class);
+ final ContentCaptureOptions options = new ContentCaptureOptions(null);
+ final ContentCaptureManager manager =
+ new ContentCaptureManager(mMockContext, mockService, options);
+
+ assertThat(manager.getFlushViewTreeAppearingEventDisabled()).isFalse();
+ manager.setFlushViewTreeAppearingEventDisabled(true);
+ assertThat(manager.getFlushViewTreeAppearingEventDisabled()).isTrue();
+ manager.setFlushViewTreeAppearingEventDisabled(false);
+ assertThat(manager.getFlushViewTreeAppearingEventDisabled()).isFalse();
+ }
}
diff --git a/graphics/java/android/graphics/Gainmap.java b/graphics/java/android/graphics/Gainmap.java
index 470a06c1f1f5..a7c508c75ac9 100644
--- a/graphics/java/android/graphics/Gainmap.java
+++ b/graphics/java/android/graphics/Gainmap.java
@@ -96,8 +96,8 @@ public final class Gainmap implements Parcelable {
throw new RuntimeException("internal error: native gainmap is 0");
}
- mGainmapContents = gainmapContents;
mNativePtr = nativeGainmap;
+ setGainmapContents(gainmapContents);
NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, nativeGainmap);
}
diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp
index 0f4521951e3d..c7c94246b96a 100644
--- a/libs/WindowManager/Shell/Android.bp
+++ b/libs/WindowManager/Shell/Android.bp
@@ -49,6 +49,7 @@ filegroup {
"src/com/android/wm/shell/animation/Interpolators.java",
"src/com/android/wm/shell/pip/PipContentOverlay.java",
"src/com/android/wm/shell/startingsurface/SplashScreenExitAnimationUtils.java",
+ "src/com/android/wm/shell/draganddrop/DragAndDropConstants.java",
],
path: "src",
}
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background.xml
deleted file mode 100644
index 0d8811357c05..000000000000
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2022 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="@color/letterbox_education_accent_primary"/>
- <corners android:radius="12dp"/>
-</shape> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml
index 42572d64b96f..a2699681e656 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml
@@ -14,7 +14,30 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/letterbox_education_dismiss_button_background_ripple">
- <item android:drawable="@drawable/letterbox_education_dismiss_button_background"/>
-</ripple> \ No newline at end of file
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetTop="@dimen/letterbox_education_dialog_vertical_inset"
+ android:insetBottom="@dimen/letterbox_education_dialog_vertical_inset">
+ <ripple android:color="@color/letterbox_education_dismiss_button_background_ripple">
+ <item android:id="@android:id/mask">
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/letterbox_education_dialog_button_radius"/>
+ <solid android:color="@android:color/white"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@android:color/transparent"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@color/letterbox_education_accent_primary"/>
+ <corners android:radius="@dimen/letterbox_education_dialog_button_radius"/>
+ <padding android:left="@dimen/letterbox_education_dialog_horizontal_padding"
+ android:top="@dimen/letterbox_education_dialog_vertical_padding"
+ android:right="@dimen/letterbox_education_dialog_horizontal_padding"
+ android:bottom="@dimen/letterbox_education_dialog_vertical_padding"/>
+ </shape>
+ </item>
+ </ripple>
+</inset>
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background.xml
deleted file mode 100644
index 60f3cfe6dde6..000000000000
--- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2023 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- android:shape="rectangle">
- <solid android:color="?androidprv:attr/colorAccentPrimaryVariant"/>
- <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
-</shape> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml
index ef97ea19e993..1f125148775d 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml
@@ -14,7 +14,31 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/letterbox_restart_button_background_ripple">
- <item android:drawable="@drawable/letterbox_restart_button_background"/>
-</ripple> \ No newline at end of file
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:insetTop="@dimen/letterbox_restart_dialog_vertical_inset"
+ android:insetBottom="@dimen/letterbox_restart_dialog_vertical_inset">
+ <ripple android:color="@color/letterbox_restart_dismiss_button_background_ripple">
+ <item android:id="@android:id/mask">
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
+ <solid android:color="@android:color/white"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@android:color/transparent"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="?androidprv:attr/colorAccentPrimaryVariant"/>
+ <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
+ <padding android:left="@dimen/letterbox_restart_dialog_horizontal_padding"
+ android:top="@dimen/letterbox_restart_dialog_vertical_padding"
+ android:right="@dimen/letterbox_restart_dialog_horizontal_padding"
+ android:bottom="@dimen/letterbox_restart_dialog_vertical_padding"/>
+ </shape>
+ </item>
+ </ripple>
+</inset> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background.xml
deleted file mode 100644
index af89d41ee6b5..000000000000
--- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2023 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- android:shape="rectangle">
- <stroke android:color="?androidprv:attr/colorAccentPrimaryVariant" android:width="1dp"/>
- <solid android:color="?androidprv:attr/colorSurface" />
- <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
-</shape> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml
index e32aefca78ac..3aa0981e45aa 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml
@@ -14,7 +14,33 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/letterbox_restart_dismiss_button_background_ripple">
- <item android:drawable="@drawable/letterbox_restart_dismiss_button_background"/>
-</ripple> \ No newline at end of file
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:insetTop="@dimen/letterbox_restart_dialog_vertical_inset"
+ android:insetBottom="@dimen/letterbox_restart_dialog_vertical_inset">
+ <ripple android:color="@color/letterbox_restart_dismiss_button_background_ripple">
+ <item android:id="@android:id/mask">
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
+ <solid android:color="@android:color/white"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@android:color/transparent"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <stroke android:color="?androidprv:attr/colorAccentPrimaryVariant"
+ android:width="1dp"/>
+ <solid android:color="?androidprv:attr/colorSurface"/>
+ <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
+ <padding android:left="@dimen/letterbox_restart_dialog_horizontal_padding"
+ android:top="@dimen/letterbox_restart_dialog_vertical_padding"
+ android:right="@dimen/letterbox_restart_dialog_horizontal_padding"
+ android:bottom="@dimen/letterbox_restart_dialog_vertical_padding"/>
+ </shape>
+ </item>
+ </ripple>
+</inset> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml b/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml
index 44b2f45052ba..3d3c00381164 100644
--- a/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml
+++ b/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml
@@ -29,11 +29,15 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="4sp"
+ android:letterSpacing="0.02"
android:background="@drawable/compat_hint_bubble"
android:padding="16dp"
android:textAlignment="viewStart"
android:textColor="@color/compat_controls_text"
- android:textSize="14sp"/>
+ android:textSize="14sp"
+ android:fontFamily="@*android:string/config_bodyFontFamily"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"
+ />
<ImageView
android:layout_width="wrap_content"
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
index c65f24d84e37..095576b581df 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
@@ -29,6 +29,8 @@
android:layout_marginBottom="20dp"/>
<TextView
+ android:fontFamily="@*android:string/config_bodyFontFamily"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body2"
android:id="@+id/letterbox_education_dialog_action_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
index 3a44eb9089dd..e8edad15dfc3 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
@@ -69,6 +69,8 @@
android:text="@string/letterbox_education_dialog_title"
android:textAlignment="center"
android:textColor="@color/compat_controls_text"
+ android:fontFamily="@*android:string/config_bodyFontFamilyMedium"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Headline"
android:textSize="24sp"/>
<LinearLayout
@@ -95,10 +97,16 @@
</LinearLayout>
<Button
+ android:fontFamily="@*android:string/config_bodyFontFamily"
+ android:fontWeight="500"
+ android:lineHeight="20dp"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Small"
android:id="@+id/letterbox_education_dialog_dismiss_button"
+ android:textStyle="bold"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginTop="40dp"
+ android:textSize="14sp"
android:background=
"@drawable/letterbox_education_dismiss_button_background_ripple"
android:text="@string/letterbox_education_got_it"
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 1f9b6cf6c64f..336c156e831a 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -273,6 +273,18 @@
<!-- The space between two actions in the letterbox education dialog -->
<dimen name="letterbox_education_dialog_space_between_actions">24dp</dimen>
+ <!-- The corner radius of the buttons in the letterbox education dialog -->
+ <dimen name="letterbox_education_dialog_button_radius">12dp</dimen>
+
+ <!-- The horizontal padding for the buttons in the letterbox education dialog -->
+ <dimen name="letterbox_education_dialog_horizontal_padding">16dp</dimen>
+
+ <!-- The vertical padding for the buttons in the letterbox education dialog -->
+ <dimen name="letterbox_education_dialog_vertical_padding">8dp</dimen>
+
+ <!-- The insets for the buttons in the letterbox education dialog -->
+ <dimen name="letterbox_education_dialog_vertical_inset">6dp</dimen>
+
<!-- The margin between the dialog container and its parent. -->
<dimen name="letterbox_restart_dialog_margin">24dp</dimen>
@@ -306,6 +318,15 @@
<!-- The corner radius of the buttons in the restart dialog -->
<dimen name="letterbox_restart_dialog_button_radius">18dp</dimen>
+ <!-- The insets for the buttons in the letterbox restart dialog -->
+ <dimen name="letterbox_restart_dialog_vertical_inset">6dp</dimen>
+
+ <!-- The horizontal padding for the buttons in the letterbox restart dialog -->
+ <dimen name="letterbox_restart_dialog_horizontal_padding">16dp</dimen>
+
+ <!-- The vertical padding for the buttons in the letterbox restart dialog -->
+ <dimen name="letterbox_restart_dialog_vertical_padding">8dp</dimen>
+
<!-- The width of the brand image on staring surface. -->
<dimen name="starting_surface_brand_image_width">200dp</dimen>
diff --git a/libs/WindowManager/Shell/res/values/styles.xml b/libs/WindowManager/Shell/res/values/styles.xml
index bae009a0526f..0a0c49f2d93f 100644
--- a/libs/WindowManager/Shell/res/values/styles.xml
+++ b/libs/WindowManager/Shell/res/values/styles.xml
@@ -87,6 +87,9 @@
<item name="android:textAppearance">
@*android:style/TextAppearance.DeviceDefault.Headline
</item>
+ <item name="android:fontFamily">
+ @*android:string/config_bodyFontFamilyMedium
+ </item>
</style>
<style name="RestartDialogBodyText">
@@ -97,24 +100,44 @@
<item name="android:textAppearance">
@*android:style/TextAppearance.DeviceDefault.Body2
</item>
+ <item name="android:fontFamily">
+ @*android:string/config_bodyFontFamily
+ </item>
</style>
<style name="RestartDialogCheckboxText">
<item name="android:textSize">16sp</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:lineSpacingExtra">4sp</item>
- <item name="android:textAppearance">@*android:style/TextAppearance.DeviceDefault</item>
+ <item name="android:textAppearance">
+ @*android:style/TextAppearance.DeviceDefault.Headline
+ </item>
+ <item name="android:fontFamily">
+ @*android:string/config_bodyFontFamilyMedium
+ </item>
</style>
<style name="RestartDialogDismissButton">
<item name="android:lineSpacingExtra">2sp</item>
<item name="android:textSize">14sp</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:textAppearance">
+ @*android:style/TextAppearance.DeviceDefault.Body2
+ </item>
+ <item name="android:fontFamily">
+ @*android:string/config_bodyFontFamily
+ </item>
</style>
<style name="RestartDialogConfirmButton">
<item name="android:lineSpacingExtra">2sp</item>
<item name="android:textSize">14sp</item>
<item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
+ <item name="android:textAppearance">
+ @*android:style/TextAppearance.DeviceDefault.Body2
+ </item>
+ <item name="android:fontFamily">
+ @*android:string/config_bodyFontFamily
+ </item>
</style>
</resources>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index ee5d205498c3..acf17e670041 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -403,7 +403,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
InputDevice.SOURCE_KEYBOARD);
ev.setDisplayId(mContext.getDisplay().getDisplayId());
- if (!InputManager.getInstance()
+ if (!mContext.getSystemService(InputManager.class)
.injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC)) {
Log.e(TAG, "Inject input event fail");
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesNavBarGestureTracker.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesNavBarGestureTracker.java
index e7beeeb06534..3a3a378e00d3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesNavBarGestureTracker.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesNavBarGestureTracker.java
@@ -64,8 +64,8 @@ class BubblesNavBarGestureTracker {
stopInternal();
- mInputMonitor = InputManager.getInstance().monitorGestureInput(GESTURE_MONITOR,
- mContext.getDisplayId());
+ mInputMonitor = mContext.getSystemService(InputManager.class)
+ .monitorGestureInput(GESTURE_MONITOR, mContext.getDisplayId());
InputChannel inputChannel = mInputMonitor.getInputChannel();
BubblesNavBarMotionEventHandler motionEventHandler =
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropConstants.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropConstants.java
new file mode 100644
index 000000000000..20da54efd286
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropConstants.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.draganddrop;
+
+/** Constants that can be used by both Shell and other users of the library, e.g. Launcher */
+public class DragAndDropConstants {
+
+ /**
+ * An Intent extra that Launcher can use to specify a region of the screen where Shell should
+ * ignore drag events.
+ */
+ public static final String EXTRA_DISALLOW_HIT_REGION = "DISALLOW_HIT_REGION";
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
index d93a9012c8f1..df94b414c092 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
@@ -34,6 +34,7 @@ import static android.content.Intent.EXTRA_USER;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
+import static com.android.wm.shell.draganddrop.DragAndDropConstants.EXTRA_DISALLOW_HIT_REGION;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_FULLSCREEN;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_BOTTOM;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_LEFT;
@@ -53,6 +54,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.LauncherApps;
import android.graphics.Insets;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -86,6 +88,7 @@ public class DragAndDropPolicy {
private final Starter mStarter;
private final SplitScreenController mSplitScreen;
private final ArrayList<DragAndDropPolicy.Target> mTargets = new ArrayList<>();
+ private final RectF mDisallowHitRegion = new RectF();
private InstanceId mLoggerSessionId;
private DragSession mSession;
@@ -111,6 +114,12 @@ public class DragAndDropPolicy {
mSession = new DragSession(mActivityTaskManager, displayLayout, data);
// TODO(b/169894807): Also update the session data with task stack changes
mSession.update();
+ RectF disallowHitRegion = (RectF) mSession.dragData.getExtra(EXTRA_DISALLOW_HIT_REGION);
+ if (disallowHitRegion == null) {
+ mDisallowHitRegion.setEmpty();
+ } else {
+ mDisallowHitRegion.set(disallowHitRegion);
+ }
}
/**
@@ -218,6 +227,9 @@ public class DragAndDropPolicy {
*/
@Nullable
Target getTargetAtLocation(int x, int y) {
+ if (mDisallowHitRegion.contains(x, y)) {
+ return null;
+ }
for (int i = mTargets.size() - 1; i >= 0; i--) {
DragAndDropPolicy.Target t = mTargets.get(i);
if (t.hitRegion.contains(x, y)) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
index bb6e3917ff3c..44fd8eec4d06 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
@@ -118,7 +118,7 @@ public class DragLayout extends LinearLayout {
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- mInsets = insets.getInsets(Type.systemBars() | Type.displayCutout());
+ mInsets = insets.getInsets(Type.tappableElement() | Type.displayCutout());
recomputeDropTargets();
final int orientation = getResources().getConfiguration().orientation;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
index 41ff0b35a035..fee9140d0c2c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
@@ -228,7 +228,7 @@ public class PipResizeGestureHandler {
if (mIsEnabled) {
// Register input event receiver
- mInputMonitor = InputManager.getInstance().monitorGestureInput(
+ mInputMonitor = mContext.getSystemService(InputManager.class).monitorGestureInput(
"pip-resize", mDisplayId);
try {
mMainExecutor.executeBlocking(() -> {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 19d8cfac559a..7833cfe7df9d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -1705,9 +1705,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
mSyncQueue.queue(wct);
- mSyncQueue.runInSync(t -> {
- setDividerVisibility(mainStageVisible, t);
- });
+ setDividerVisibility(mainStageVisible, null);
}
private void setDividerVisibility(boolean visible, @Nullable SurfaceControl.Transaction t) {
@@ -1789,6 +1787,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Override
public void onAnimationEnd(Animator animation) {
+ if (dividerLeash != null && dividerLeash.isValid()) {
+ transaction.setAlpha(dividerLeash, 1);
+ transaction.apply();
+ }
mTransactionPool.release(transaction);
mDividerFadeInAnimator = null;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
index c2da70595a3d..8e916e63cac6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
@@ -186,7 +186,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler {
private boolean isHomeOpening(@NonNull TransitionInfo.Change change) {
return change.getTaskInfo() != null
- && change.getTaskInfo().getActivityType() != ACTIVITY_TYPE_HOME;
+ && change.getTaskInfo().getActivityType() == ACTIVITY_TYPE_HOME;
}
private boolean isWallpaper(@NonNull TransitionInfo.Change change) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index de5f2f467e99..75bc98555665 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -505,7 +505,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
}
private void createInputChannel(int displayId) {
- final InputManager inputManager = InputManager.getInstance();
+ final InputManager inputManager = mContext.getSystemService(InputManager.class);
final InputMonitor inputMonitor =
mInputMonitorFactory.create(inputManager, mContext);
final EventReceiver eventReceiver = new EventReceiver(inputMonitor,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java
index aea340464304..d0fcd8651481 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java
@@ -65,7 +65,7 @@ class TaskOperations {
InputDevice.SOURCE_KEYBOARD);
ev.setDisplayId(mContext.getDisplay().getDisplayId());
- if (!InputManager.getInstance()
+ if (!mContext.getSystemService(InputManager.class)
.injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC)) {
Log.e(TAG, "Inject input event fail");
}
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index cbebae9ed438..ecf6cfc05444 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -464,7 +464,7 @@ bool Bitmap::compress(JavaCompressFormat format, int32_t quality, SkWStream* str
SkBitmap baseBitmap = getSkBitmap();
SkBitmap gainmapBitmap = gainmap()->bitmap->getSkBitmap();
SkJpegEncoder::Options options{.fQuality = quality};
- return SkJpegGainmapEncoder::EncodeJpegR(stream, baseBitmap.pixmap(), options,
+ return SkJpegGainmapEncoder::EncodeHDRGM(stream, baseBitmap.pixmap(), options,
gainmapBitmap.pixmap(), options, gainmap()->info);
}
#endif
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 40a4858d30ba..d2b21ae19162 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -849,7 +849,7 @@ public class RingtoneManager {
if (ringtoneUri != null) {
final Uri cacheUri = getCacheForType(type, context.getUserId());
try (InputStream in = openRingtone(context, ringtoneUri);
- OutputStream out = resolver.openOutputStream(cacheUri)) {
+ OutputStream out = resolver.openOutputStream(cacheUri, "wt")) {
FileUtils.copy(in, out);
} catch (IOException e) {
Log.w(TAG, "Failed to cache ringtone: " + e);
diff --git a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
index 95b49a8ef335..73f87302dd05 100644
--- a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
@@ -21,7 +21,6 @@ import android.app.backup.BackupAgent;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupManagerMonitor;
-import android.app.backup.BackupRestoreEventLogger;
import android.app.backup.BackupRestoreEventLogger.DataTypeResult;
import android.app.backup.BackupTransport;
import android.app.backup.RestoreDescription;
@@ -48,6 +47,7 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
/**
@@ -915,6 +915,7 @@ public class LocalTransport extends BackupTransport {
Log.i(TAG, "\tdataType: " + result.getDataType());
Log.i(TAG, "\tsuccessCount: " + result.getSuccessCount());
Log.i(TAG, "\tfailCount: " + result.getFailCount());
+ Log.i(TAG, "\tmetadataHash: " + Arrays.toString(result.getMetadataHash()));
if (!result.getErrors().isEmpty()) {
Log.i(TAG, "\terrors {");
diff --git a/packages/SettingsLib/res/values/styles.xml b/packages/SettingsLib/res/values/styles.xml
index 5a9e780df8e9..cc60382b48f9 100644
--- a/packages/SettingsLib/res/values/styles.xml
+++ b/packages/SettingsLib/res/values/styles.xml
@@ -14,7 +14,7 @@
~ limitations under the License
-->
-<resources>
+<resources xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<style name="TextAppearanceSmall">
<item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
</style>
@@ -73,7 +73,7 @@
</style>
<style name="TextAppearanceBroadcastDialogButton" parent="@android:TextAppearance.DeviceDefault.Headline">
- <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:textColor">?androidprv:attr/textColorOnAccent</item>
<item name="android:textSize">@dimen/broadcast_dialog_btn_text_size</item>
</style>
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt
index a1d9d90523eb..e42b589f05cf 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt
@@ -24,7 +24,7 @@ import com.android.systemui.animation.LaunchableView
import com.android.systemui.animation.LaunchableViewDelegate
/** An [ImageView] that also implements [LaunchableView]. */
-class LaunchableImageView : ImageView, LaunchableView {
+open class LaunchableImageView : ImageView, LaunchableView {
private val delegate =
LaunchableViewDelegate(
this,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt
index 286996dcaeaa..147669528c5e 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt
@@ -24,7 +24,7 @@ import com.android.systemui.animation.LaunchableView
import com.android.systemui.animation.LaunchableViewDelegate
/** A [TextView] that also implements [LaunchableView]. */
-class LaunchableTextView : TextView, LaunchableView {
+open class LaunchableTextView : TextView, LaunchableView {
private val delegate =
LaunchableViewDelegate(
this,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index eec788b7add8..f164e7d33642 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -492,12 +492,14 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
case MotionEvent.ACTION_MOVE:
mVelocityTracker.addMovement(event);
int pointerIndex = event.findPointerIndex(mActivePointerId);
- float y = event.getY(pointerIndex);
- if (mLastTouchY != -1) {
- float dy = y - mLastTouchY;
- setTranslationY(getTranslationY() + dy * TOUCH_Y_MULTIPLIER);
+ if (pointerIndex != -1) {
+ float y = event.getY(pointerIndex);
+ if (mLastTouchY != -1) {
+ float dy = y - mLastTouchY;
+ setTranslationY(getTranslationY() + dy * TOUCH_Y_MULTIPLIER);
+ }
+ mLastTouchY = y;
}
- mLastTouchY = y;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 23f887ef0016..f1abdc68f97e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -17,7 +17,6 @@
package com.android.keyguard;
import static android.app.StatusBarManager.SESSION_KEYGUARD;
-import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_BIOMETRIC;
import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_EXTENDED_ACCESS;
@@ -36,7 +35,6 @@ import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.hardware.biometrics.BiometricOverlayConstants;
-import android.hardware.biometrics.BiometricSourceType;
import android.media.AudioManager;
import android.metrics.LogMaker;
import android.os.SystemClock;
@@ -321,7 +319,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
KeyguardSecurityContainerController.this.onDensityOrFontScaleChanged();
}
};
- private boolean mBouncerVisible = false;
private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@Override
@@ -356,19 +353,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
public void onDevicePolicyManagerStateChanged() {
showPrimarySecurityScreen(false);
}
-
- @Override
- public void onBiometricRunningStateChanged(boolean running,
- BiometricSourceType biometricSourceType) {
- if (biometricSourceType == FINGERPRINT) {
- updateSideFpsVisibility();
- }
- }
-
- @Override
- public void onStrongAuthStateChanged(int userId) {
- updateSideFpsVisibility();
- }
};
@Inject
@@ -460,35 +444,24 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
getCurrentSecurityController().onPause();
}
mView.onPause();
- // It might happen that onStartingToHide is not called when the device is locked while on
- // bouncer.
- setBouncerVisible(false);
mView.clearFocus();
}
- private void updateSideFpsVisibility() {
+ /**
+ * Shows and hides the side finger print sensor animation.
+ *
+ * @param isVisible sets whether we show or hide the side fps animation
+ */
+ public void updateSideFpsVisibility(boolean isVisible) {
if (!mSideFpsController.isPresent()) {
return;
}
- final boolean sfpsEnabled = getResources().getBoolean(
- R.bool.config_show_sidefps_hint_on_bouncer);
- final boolean fpsDetectionRunning = mUpdateMonitor.isFingerprintDetectionRunning();
- final boolean isUnlockingWithFpAllowed =
- mUpdateMonitor.isUnlockingWithFingerprintAllowed();
- boolean toShow = mBouncerVisible && sfpsEnabled && fpsDetectionRunning
- && isUnlockingWithFpAllowed;
-
- if (DEBUG) {
- Log.d(TAG, "sideFpsToShow=" + toShow + ", "
- + "mBouncerVisible=" + mBouncerVisible + ", "
- + "configEnabled=" + sfpsEnabled + ", "
- + "fpsDetectionRunning=" + fpsDetectionRunning + ", "
- + "isUnlockingWithFpAllowed=" + isUnlockingWithFpAllowed);
- }
- if (toShow) {
- mSideFpsController.get().show(SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
+ if (isVisible) {
+ mSideFpsController.get().show(
+ SideFpsUiRequestSource.PRIMARY_BOUNCER,
+ BiometricOverlayConstants.REASON_AUTH_KEYGUARD
+ );
} else {
mSideFpsController.get().hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
}
@@ -637,7 +610,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED, state);
getCurrentSecurityController().onResume(reason);
- updateSideFpsVisibility();
}
mView.onResume(
mSecurityModel.getSecurityMode(KeyguardUpdateMonitor.getCurrentUser()),
@@ -691,22 +663,15 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
if (mCurrentSecurityMode != SecurityMode.None) {
getCurrentSecurityController().onStartingToHide();
}
- setBouncerVisible(false);
}
/** Called when the bouncer changes visibility. */
- public void onBouncerVisibilityChanged(@View.Visibility int visibility) {
- setBouncerVisible(visibility == View.VISIBLE);
- if (visibility == View.INVISIBLE) {
+ public void onBouncerVisibilityChanged(boolean isVisible) {
+ if (!isVisible) {
mView.resetScale();
}
}
- private void setBouncerVisible(boolean visible) {
- mBouncerVisible = visible;
- updateSideFpsVisibility();
- }
-
/**
* Shows the next security screen if there is one.
* @param authenticated true if the user entered the correct authentication
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index b8e1499a5ae7..eb4b05b42b91 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -96,8 +96,10 @@ import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
import android.hardware.biometrics.SensorProperties;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorPropertiesInternal;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
@@ -2942,7 +2944,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
// Trigger the fingerprint success path so the bouncer can be shown
handleFingerprintAuthenticated(user, isStrongBiometric);
},
- userId);
+ new FingerprintAuthenticateOptions.Builder()
+ .setUserId(userId)
+ .build());
} else {
mLogger.v("startListeningForFingerprint - authenticate");
mFpm.authenticate(null /* crypto */, mFingerprintCancelSignal,
@@ -2988,7 +2992,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
if (supportsFaceDetection && !udfpsFingerprintAuthRunning) {
// Run face detection. (If a face is detected, show the bouncer.)
mLogger.v("startListeningForFace - detect");
- mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback, userId);
+ mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback,
+ new FaceAuthenticateOptions.Builder()
+ .setUserId(userId)
+ .build());
} else {
// Don't run face detection. Instead, inform the user
// face auth is unavailable and how to proceed.
@@ -3007,7 +3014,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
final boolean isBypassEnabled = mKeyguardBypassController != null
&& mKeyguardBypassController.isBypassEnabled();
mFaceManager.authenticate(null /* crypto */, mFaceCancelSignal,
- mFaceAuthenticationCallback, null /* handler */, userId, isBypassEnabled);
+ mFaceAuthenticationCallback, null /* handler */, userId);
}
setFaceRunningState(BIOMETRIC_STATE_RUNNING);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt b/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt
index 0f00a040b094..603471b1de41 100644
--- a/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt
+++ b/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt
@@ -73,6 +73,10 @@ class ScreenOnCoordinator @Inject constructor(
@BinderThread
fun onScreenTurnedOn() {
foldAodAnimationController?.onScreenTurnedOn()
+ }
+
+ @BinderThread
+ fun onScreenTurnedOff() {
pendingTasks.reset()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
index 00f5ac2ffa23..12b5705190d9 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -58,13 +58,13 @@ import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
import com.android.systemui.util.Assert;
+import dagger.Lazy;
+
import java.util.Locale;
import java.util.Optional;
import javax.inject.Inject;
-import dagger.Lazy;
-
/**
* Class to register system actions with accessibility framework.
*/
@@ -473,7 +473,7 @@ public class SystemActions implements CoreStartable {
KeyEvent event = KeyEvent.obtain(downTime, time, action, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
InputDevice.SOURCE_KEYBOARD, null);
- InputManager.getInstance()
+ mContext.getSystemService(InputManager.class)
.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
event.recycle();
}
diff --git a/packages/SystemUI/src/com/android/systemui/devicepolicy/DevicePolicyManagerExt.kt b/packages/SystemUI/src/com/android/systemui/devicepolicy/DevicePolicyManagerExt.kt
new file mode 100644
index 000000000000..1390b4db3576
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/devicepolicy/DevicePolicyManagerExt.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.devicepolicy
+
+import android.app.admin.DevicePolicyManager
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL
+import android.content.ComponentName
+
+/** Returns true if the admin of [userId] disallows keyguard shortcuts. */
+fun DevicePolicyManager.areKeyguardShortcutsDisabled(
+ admin: ComponentName? = null,
+ userId: Int
+): Boolean {
+ val flags = getKeyguardDisabledFeatures(admin, userId)
+ return flags and KEYGUARD_DISABLE_SHORTCUTS_ALL == KEYGUARD_DISABLE_SHORTCUTS_ALL ||
+ flags and KEYGUARD_DISABLE_FEATURES_ALL == KEYGUARD_DISABLE_FEATURES_ALL
+}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index fa4caaf8960d..2e37b348c5e3 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -62,7 +62,7 @@ object Flags {
val FSI_REQUIRES_KEYGUARD = releasedFlag(110, "fsi_requires_keyguard")
// TODO(b/259130119): Tracking Bug
- val FSI_ON_DND_UPDATE = unreleasedFlag(259130119, "fsi_on_dnd_update", teamfood = true)
+ val FSI_ON_DND_UPDATE = releasedFlag(259130119, "fsi_on_dnd_update")
// TODO(b/265804648): Tracking Bug
@JvmField val DISABLE_FSI = unreleasedFlag(265804648, "disable_fsi")
@@ -266,6 +266,12 @@ object Flags {
@JvmField
val ENABLE_FONT_SCALING_TILE = unreleasedFlag(509, "enable_font_scaling_tile", teamfood = false)
+ /** Enables new QS Edit Mode visual refresh */
+ // TODO(b/269787742): Tracking Bug
+ @JvmField
+ val ENABLE_NEW_QS_EDIT_MODE =
+ unreleasedFlag(510, "enable_new_qs_edit_mode", teamfood = false)
+
// 600- status bar
// TODO(b/256614753): Tracking Bug
@@ -630,7 +636,8 @@ object Flags {
// 2600 - keyboard
// TODO(b/259352579): Tracking Bug
- @JvmField val SHORTCUT_LIST_SEARCH_LAYOUT = unreleasedFlag(2600, "shortcut_list_search_layout")
+ @JvmField val SHORTCUT_LIST_SEARCH_LAYOUT =
+ unreleasedFlag(2600, "shortcut_list_search_layout", teamfood = true)
// TODO(b/259428678): Tracking Bug
@JvmField
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt
index e9b8908214fc..496c64e1120e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt
@@ -17,6 +17,14 @@
package com.android.systemui.keyboard
+import com.android.systemui.keyboard.data.repository.KeyboardRepository
+import com.android.systemui.keyboard.data.repository.KeyboardRepositoryImpl
+import dagger.Binds
import dagger.Module
-@Module abstract class KeyboardModule
+@Module
+abstract class KeyboardModule {
+
+ @Binds
+ abstract fun bindKeyboardRepository(repository: KeyboardRepositoryImpl): KeyboardRepository
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/data/model/BacklightModel.kt b/packages/SystemUI/src/com/android/systemui/keyboard/data/model/BacklightModel.kt
new file mode 100644
index 000000000000..ea15a9f18584
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/data/model/BacklightModel.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyboard.data.model
+
+/**
+ * Model for current state of keyboard backlight brightness. [level] indicates current level of
+ * backlight brightness and [maxLevel] its max possible value.
+ */
+data class BacklightModel(val level: Int, val maxLevel: Int)
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt
new file mode 100644
index 000000000000..70faf406d621
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyboard.data.repository
+
+import android.hardware.input.InputManager
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.keyboard.data.model.BacklightModel
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.shareIn
+
+interface KeyboardRepository {
+ val keyboardConnected: Flow<Boolean>
+ val backlight: Flow<BacklightModel>
+}
+
+@SysUISingleton
+class KeyboardRepositoryImpl
+@Inject
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
+ private val inputManager: InputManager,
+) : KeyboardRepository {
+
+ private val connectedDeviceIds: Flow<Set<Int>> =
+ conflatedCallbackFlow {
+ fun send(element: Set<Int>) = trySendWithFailureLogging(element, TAG)
+
+ var connectedKeyboards = inputManager.inputDeviceIds.toSet()
+ val listener =
+ object : InputManager.InputDeviceListener {
+ override fun onInputDeviceAdded(deviceId: Int) {
+ connectedKeyboards = connectedKeyboards + deviceId
+ send(connectedKeyboards)
+ }
+
+ override fun onInputDeviceChanged(deviceId: Int) = Unit
+
+ override fun onInputDeviceRemoved(deviceId: Int) {
+ connectedKeyboards = connectedKeyboards - deviceId
+ send(connectedKeyboards)
+ }
+ }
+ send(connectedKeyboards)
+ inputManager.registerInputDeviceListener(listener, /* handler= */ null)
+ awaitClose { inputManager.unregisterInputDeviceListener(listener) }
+ }
+ .shareIn(
+ scope = applicationScope,
+ started = SharingStarted.Lazily,
+ replay = 1,
+ )
+
+ override val keyboardConnected: Flow<Boolean> =
+ connectedDeviceIds
+ .map { it.any { deviceId -> isPhysicalFullKeyboard(deviceId) } }
+ .distinctUntilChanged()
+ .flowOn(backgroundDispatcher)
+
+ override val backlight: Flow<BacklightModel> =
+ conflatedCallbackFlow {
+ // TODO(b/268645734) register BacklightListener
+ }
+
+ private fun isPhysicalFullKeyboard(deviceId: Int): Boolean {
+ val device = inputManager.getInputDevice(deviceId)
+ return !device.isVirtual && device.isFullKeyboard
+ }
+
+ companion object {
+ const val TAG = "KeyboardRepositoryImpl"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 7a891b0058af..eef7ccc65d95 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -602,6 +602,7 @@ public class KeyguardService extends Service {
checkPermission();
mKeyguardViewMediator.onScreenTurnedOff();
mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.SCREEN_TURNED_OFF);
+ mScreenOnCoordinator.onScreenTurnedOff();
}
@Override // Binder interface
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 54fc5b588db7..02bee3efbe2f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -59,6 +59,7 @@ import android.hardware.biometrics.BiometricSourceType;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
+import android.os.Binder;
import android.os.Bundle;
import android.os.DeadObjectException;
import android.os.Handler;
@@ -67,6 +68,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
@@ -102,6 +104,7 @@ import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IKeyguardExitCallback;
import com.android.internal.policy.IKeyguardStateCallback;
import com.android.internal.policy.ScreenDecorationsUtils;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardConstants;
@@ -270,6 +273,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
private AlarmManager mAlarmManager;
private AudioManager mAudioManager;
private StatusBarManager mStatusBarManager;
+ private final IStatusBarService mStatusBarService;
+ private final IBinder mStatusBarDisableToken = new Binder();
private final UserTracker mUserTracker;
private final SysuiStatusBarStateController mStatusBarStateController;
private final Executor mUiBgExecutor;
@@ -1213,6 +1218,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
mPM = powerManager;
mTrustManager = trustManager;
mUserSwitcherController = userSwitcherController;
+ mStatusBarService = IStatusBarService.Stub.asInterface(
+ ServiceManager.getService(Context.STATUS_BAR_SERVICE));
mKeyguardDisplayManager = keyguardDisplayManager;
mShadeController = shadeControllerLazy;
dumpManager.registerDumpable(getClass().getName(), this);
@@ -2918,7 +2925,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
// TODO (b/155663717) After restart, status bar will not properly hide home button
// unless disable is called to show un-hide it once first
if (forceClearFlags) {
- mStatusBarManager.disable(flags);
+ try {
+ mStatusBarService.disableForUser(flags, mStatusBarDisableToken,
+ mContext.getPackageName(), mUserTracker.getUserId());
+ } catch (RemoteException e) {
+ Log.d(TAG, "Failed to force clear flags", e);
+ }
}
if (forceHideHomeRecentsButtons || isShowingAndNotOccluded()) {
@@ -2934,7 +2946,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
+ " --> flags=0x" + Integer.toHexString(flags));
}
- mStatusBarManager.disable(flags);
+ try {
+ mStatusBarService.disableForUser(flags, mStatusBarDisableToken,
+ mContext.getPackageName(), mUserTracker.getUserId());
+ } catch (RemoteException e) {
+ Log.d(TAG, "Failed to set disable flags: " + flags, e);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
index 4331fe66a0dc..0e85347c24b0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
@@ -60,7 +60,6 @@ interface KeyguardBouncerRepository {
*/
val panelExpansionAmount: StateFlow<Float>
val keyguardPosition: StateFlow<Float>
- val onScreenTurnedOff: StateFlow<Boolean>
val isBackButtonEnabled: StateFlow<Boolean?>
/** Determines if user is already unlocked */
val keyguardAuthenticated: StateFlow<Boolean?>
@@ -70,6 +69,8 @@ interface KeyguardBouncerRepository {
val bouncerErrorMessage: CharSequence?
val alternateBouncerVisible: StateFlow<Boolean>
val alternateBouncerUIAvailable: StateFlow<Boolean>
+ val sideFpsShowing: StateFlow<Boolean>
+
var lastAlternateBouncerVisibleTime: Long
fun setPrimaryScrimmed(isScrimmed: Boolean)
@@ -98,11 +99,11 @@ interface KeyguardBouncerRepository {
fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean)
- fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean)
-
fun setAlternateVisible(isVisible: Boolean)
fun setAlternateBouncerUIAvailable(isAvailable: Boolean)
+
+ fun setSideFpsShowing(isShowing: Boolean)
}
@SysUISingleton
@@ -142,8 +143,6 @@ constructor(
override val panelExpansionAmount = _panelExpansionAmount.asStateFlow()
private val _keyguardPosition = MutableStateFlow(0f)
override val keyguardPosition = _keyguardPosition.asStateFlow()
- private val _onScreenTurnedOff = MutableStateFlow(false)
- override val onScreenTurnedOff = _onScreenTurnedOff.asStateFlow()
private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null)
override val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow()
private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null)
@@ -165,6 +164,8 @@ constructor(
private val _alternateBouncerUIAvailable = MutableStateFlow(false)
override val alternateBouncerUIAvailable: StateFlow<Boolean> =
_alternateBouncerUIAvailable.asStateFlow()
+ private val _sideFpsShowing = MutableStateFlow(false)
+ override val sideFpsShowing: StateFlow<Boolean> = _sideFpsShowing.asStateFlow()
init {
setUpLogging()
@@ -235,8 +236,8 @@ constructor(
_isBackButtonEnabled.value = isBackButtonEnabled
}
- override fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) {
- _onScreenTurnedOff.value = onScreenTurnedOff
+ override fun setSideFpsShowing(isShowing: Boolean) {
+ _sideFpsShowing.value = isShowing
}
/** Sets up logs for state flows. */
@@ -276,9 +277,6 @@ constructor(
.map { it.toInt() }
.logDiffsForTable(buffer, "", "KeyguardPosition", -1)
.launchIn(applicationScope)
- onScreenTurnedOff
- .logDiffsForTable(buffer, "", "OnScreenTurnedOff", false)
- .launchIn(applicationScope)
isBackButtonEnabled
.filterNotNull()
.logDiffsForTable(buffer, "", "IsBackButtonEnabled", false)
@@ -293,6 +291,9 @@ constructor(
alternateBouncerUIAvailable
.logDiffsForTable(buffer, "", "IsAlternateBouncerUIAvailable", false)
.launchIn(applicationScope)
+ sideFpsShowing
+ .logDiffsForTable(buffer, "", "isSideFpsShowing", false)
+ .launchIn(applicationScope)
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManager.kt
index 2069891a23e0..a3268405a830 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManager.kt
@@ -18,6 +18,7 @@ package com.android.systemui.keyguard.data.repository
import android.app.StatusBarManager
import android.content.Context
+import android.hardware.face.FaceAuthenticateOptions
import android.hardware.face.FaceManager
import android.os.CancellationSignal
import com.android.internal.logging.InstanceId
@@ -235,8 +236,7 @@ constructor(
cancellationSignal,
faceAuthCallback,
null,
- currentUserId,
- lockscreenBypassEnabled
+ FaceAuthenticateOptions.Builder().setUserId(currentUserId).build()
)
}
}
@@ -255,7 +255,11 @@ constructor(
withContext(mainDispatcher) {
// We always want to invoke face detect in the main thread.
faceAuthLogger.faceDetectionStarted()
- faceManager?.detectFace(cancellationSignal, detectionCallback, currentUserId)
+ faceManager?.detectFace(
+ cancellationSignal,
+ detectionCallback,
+ FaceAuthenticateOptions.Builder().setUserId(currentUserId).build()
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
index dfbe1c216847..9b5f7f606c60 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
@@ -26,6 +26,7 @@ import com.android.systemui.animation.DialogLaunchAnimator
import com.android.systemui.animation.Expandable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.devicepolicy.areKeyguardShortcutsDisabled
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
@@ -410,16 +411,10 @@ constructor(
)
}
- private suspend fun isFeatureDisabledByDevicePolicy(): Boolean {
- val flags =
- withContext(backgroundDispatcher) {
- devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId)
- }
- val flagsToCheck =
- DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL or
- DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL
- return flagsToCheck and flags != 0
- }
+ private suspend fun isFeatureDisabledByDevicePolicy(): Boolean =
+ withContext(backgroundDispatcher) {
+ devicePolicyManager.areKeyguardShortcutsDisabled(userId = userTracker.userId)
+ }
companion object {
private const val TAG = "KeyguardQuickAffordanceInteractor"
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
index e819da9a50be..edd28972c05e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
@@ -16,14 +16,19 @@
package com.android.systemui.keyguard.domain.interactor
+import android.content.Context
import android.content.res.ColorStateList
import android.hardware.biometrics.BiometricSourceType
import android.os.Handler
import android.os.Trace
import android.view.View
+import android.util.Log
+import com.android.keyguard.KeyguardConstants
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.DejankUtils
+import com.android.systemui.R
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
@@ -60,8 +65,9 @@ constructor(
private val primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor,
private val falsingCollector: FalsingCollector,
private val dismissCallbackRegistry: DismissCallbackRegistry,
+ private val context: Context,
+ private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
keyguardBypassController: KeyguardBypassController,
- keyguardUpdateMonitor: KeyguardUpdateMonitor,
) {
/** Whether we want to wait for face auth. */
private val primaryBouncerFaceDelay =
@@ -88,7 +94,6 @@ constructor(
}
val keyguardAuthenticated: Flow<Boolean> = repository.keyguardAuthenticated.filterNotNull()
- val screenTurnedOff: Flow<Unit> = repository.onScreenTurnedOff.filter { it }.map {}
val show: Flow<KeyguardBouncerModel> = repository.primaryBouncerShow.filterNotNull()
val hide: Flow<Unit> = repository.primaryBouncerHide.filter { it }.map {}
val startingToHide: Flow<Unit> = repository.primaryBouncerStartingToHide.filter { it }.map {}
@@ -113,6 +118,24 @@ constructor(
}
/** Allow for interaction when just about fully visible */
val isInteractable: Flow<Boolean> = bouncerExpansion.map { it > 0.9 }
+ val sideFpsShowing: Flow<Boolean> = repository.sideFpsShowing
+
+ init {
+ keyguardUpdateMonitor.registerCallback(
+ object : KeyguardUpdateMonitorCallback() {
+ override fun onBiometricRunningStateChanged(
+ running: Boolean,
+ biometricSourceType: BiometricSourceType?
+ ) {
+ updateSideFpsVisibility()
+ }
+
+ override fun onStrongAuthStateChanged(userId: Int) {
+ updateSideFpsVisibility()
+ }
+ }
+ )
+ }
// TODO(b/243685699): Move isScrimmed logic to data layer.
// TODO(b/243695312): Encapsulate all of the show logic for the bouncer.
@@ -120,7 +143,6 @@ constructor(
@JvmOverloads
fun show(isScrimmed: Boolean) {
// Reset some states as we show the bouncer.
- repository.setOnScreenTurnedOff(false)
repository.setKeyguardAuthenticated(null)
repository.setPrimaryHide(false)
repository.setPrimaryStartingToHide(false)
@@ -254,11 +276,6 @@ constructor(
repository.setKeyguardAuthenticated(strongAuth)
}
- /** Tell the bouncer the screen has turned off. */
- fun onScreenTurnedOff() {
- repository.setOnScreenTurnedOff(true)
- }
-
/** Update the position of the bouncer when showing. */
fun setKeyguardPosition(position: Float) {
repository.setKeyguardPosition(position)
@@ -293,6 +310,35 @@ constructor(
repository.setPrimaryStartDisappearAnimation(finishRunnable)
}
+ /** Determine whether to show the side fps animation. */
+ fun updateSideFpsVisibility() {
+ val sfpsEnabled: Boolean =
+ context.resources.getBoolean(R.bool.config_show_sidefps_hint_on_bouncer)
+ val fpsDetectionRunning: Boolean = keyguardUpdateMonitor.isFingerprintDetectionRunning
+ val isUnlockingWithFpAllowed: Boolean =
+ keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed
+ val bouncerVisible = repository.primaryBouncerVisible.value
+ val toShow =
+ (repository.primaryBouncerVisible.value &&
+ sfpsEnabled &&
+ fpsDetectionRunning &&
+ isUnlockingWithFpAllowed &&
+ !isAnimatingAway())
+
+ if (KeyguardConstants.DEBUG) {
+ Log.d(
+ TAG,
+ ("sideFpsToShow=$toShow\n" +
+ "bouncerVisible=$bouncerVisible\n" +
+ "configEnabled=$sfpsEnabled\n" +
+ "fpsDetectionRunning=$fpsDetectionRunning\n" +
+ "isUnlockingWithFpAllowed=$isUnlockingWithFpAllowed\n" +
+ "isAnimatingAway=${isAnimatingAway()}")
+ )
+ }
+ repository.setSideFpsShowing(toShow)
+ }
+
/** Returns whether bouncer is fully showing. */
fun isFullyShowing(): Boolean {
return (repository.primaryBouncerShowingSoon.value ||
@@ -336,4 +382,8 @@ constructor(
DejankUtils.removeCallbacks(showRunnable)
mainHandler.removeCallbacks(showRunnable)
}
+
+ companion object {
+ private const val TAG = "PrimaryBouncerInteractor"
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
index 56f911f8b1da..7db567b2a0e9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
@@ -34,6 +34,7 @@ import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.plugins.ActivityStarter
import kotlinx.coroutines.awaitCancellation
+import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
@@ -121,7 +122,6 @@ object KeyguardBouncerViewBinder {
launch {
viewModel.hide.collect {
securityContainerController.cancelDismissAction()
- securityContainerController.onPause()
securityContainerController.reset()
}
}
@@ -155,13 +155,18 @@ object KeyguardBouncerViewBinder {
launch {
viewModel.isBouncerVisible.collect { isVisible ->
- val visibility = if (isVisible) View.VISIBLE else View.INVISIBLE
- view.visibility = visibility
- securityContainerController.onBouncerVisibilityChanged(visibility)
+ view.visibility = if (isVisible) View.VISIBLE else View.INVISIBLE
+ securityContainerController.onBouncerVisibilityChanged(isVisible)
}
}
launch {
+ viewModel.isBouncerVisible
+ .filter { !it }
+ .collect { securityContainerController.onPause() }
+ }
+
+ launch {
viewModel.isInteractable.collect { isInteractable ->
securityContainerController.setInteractable(isInteractable)
}
@@ -204,10 +209,14 @@ object KeyguardBouncerViewBinder {
}
launch {
- viewModel.screenTurnedOff.collect {
- if (view.visibility == View.VISIBLE) {
- securityContainerController.onPause()
- }
+ viewModel.shouldUpdateSideFps.collect {
+ viewModel.updateSideFpsVisibility()
+ }
+ }
+
+ launch {
+ viewModel.sideFpsShowing.collect {
+ securityContainerController.updateSideFpsVisibility(it)
}
}
awaitCancellation()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
index b8b3a8e5db20..97e94d8f3232 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
@@ -24,7 +24,9 @@ import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
/** Models UI state for the lock screen bouncer; handles user input. */
class KeyguardBouncerViewModel
@@ -66,8 +68,16 @@ constructor(
/** Observe whether keyguard is authenticated already. */
val keyguardAuthenticated: Flow<Boolean> = interactor.keyguardAuthenticated
- /** Observe whether screen is turned off. */
- val screenTurnedOff: Flow<Unit> = interactor.screenTurnedOff
+ /** Observe whether the side fps is showing. */
+ val sideFpsShowing: Flow<Boolean> = interactor.sideFpsShowing
+
+ /** Observe whether we should update fps is showing. */
+ val shouldUpdateSideFps: Flow<Unit> =
+ merge(
+ interactor.startingToHide,
+ interactor.isVisible.map {},
+ interactor.startingDisappearAnimation.filterNotNull().map {}
+ )
/** Observe whether we want to update resources. */
fun notifyUpdateResources() {
@@ -84,6 +94,10 @@ constructor(
interactor.onMessageShown()
}
+ fun updateSideFpsVisibility() {
+ interactor.updateSideFpsVisibility()
+ }
+
/** Observe whether back button is enabled. */
fun observeOnIsBackButtonEnabled(systemUiVisibility: () -> Int): Flow<Int> {
return interactor.isBackButtonEnabled.map { enabled ->
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index c3d736917b5d..f1a5c3e8ef43 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -75,6 +75,7 @@ import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.BarTransitions;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LightBarTransitionsController;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.wm.shell.back.BackAnimation;
import com.android.wm.shell.pip.Pip;
@@ -166,16 +167,20 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
private BackAnimation mBackAnimation;
+ private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Inject
public TaskbarDelegate(Context context,
EdgeBackGestureHandler.Factory edgeBackGestureHandlerFactory,
- LightBarTransitionsController.Factory lightBarTransitionsControllerFactory) {
+ LightBarTransitionsController.Factory lightBarTransitionsControllerFactory,
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
mLightBarTransitionsControllerFactory = lightBarTransitionsControllerFactory;
mEdgeBackGestureHandler = edgeBackGestureHandlerFactory.create(context);
mContext = context;
mDisplayManager = mContext.getSystemService(DisplayManager.class);
mPipListener = mEdgeBackGestureHandler::setPipStashExclusionBounds;
+ mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
+ mStatusBarKeyguardViewManager.setTaskbarDelegate(this);
}
public void setDependencies(CommandQueue commandQueue,
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 389034af8a33..f3d60145a057 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -580,7 +580,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
}
// Register input event receiver
- mInputMonitor = InputManager.getInstance().monitorGestureInput(
+ mInputMonitor = mContext.getSystemService(InputManager.class).monitorGestureInput(
"edge-swipe", mDisplayId);
mInputEventReceiver = new InputChannelCompat.InputEventReceiver(
mInputMonitor.getInputChannel(), Looper.getMainLooper(),
@@ -1039,7 +1039,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
InputDevice.SOURCE_KEYBOARD);
ev.setDisplayId(mContext.getDisplay().getDisplayId());
- return InputManager.getInstance()
+ return mContext.getSystemService(InputManager.class)
.injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
index be615d63a3d7..5702681d9240 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
@@ -17,17 +17,21 @@
package com.android.systemui.notetask
import android.app.KeyguardManager
+import android.app.admin.DevicePolicyManager
import android.content.ActivityNotFoundException
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
+import android.os.Build
import android.os.UserManager
import android.util.Log
import com.android.internal.logging.UiEvent
import com.android.internal.logging.UiEventLogger
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.devicepolicy.areKeyguardShortcutsDisabled
import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
+import com.android.systemui.settings.UserTracker
import com.android.systemui.util.kotlin.getOrNull
import com.android.wm.shell.bubbles.Bubbles
import java.util.Optional
@@ -49,8 +53,10 @@ constructor(
private val optionalBubbles: Optional<Bubbles>,
private val optionalKeyguardManager: Optional<KeyguardManager>,
private val optionalUserManager: Optional<UserManager>,
+ private val devicePolicyManager: DevicePolicyManager,
@NoteTaskEnabledKey private val isEnabled: Boolean,
private val uiEventLogger: UiEventLogger,
+ private val userTracker: UserTracker,
) {
/**
@@ -80,6 +86,18 @@ constructor(
// TODO(b/249954038): We should handle direct boot (isUserUnlocked). For now, we do nothing.
if (!userManager.isUserUnlocked) return
+ val isKeyguardLocked = keyguardManager.isKeyguardLocked
+ // KeyguardQuickAffordanceInteractor blocks the quick affordance from showing in the
+ // keyguard if it is not allowed by the admin policy. Here we block any other way to show
+ // note task when the screen is locked.
+ if (
+ isKeyguardLocked &&
+ devicePolicyManager.areKeyguardShortcutsDisabled(userId = userTracker.userId)
+ ) {
+ logDebug { "Enterprise policy disallows launching note app when the screen is locked." }
+ return
+ }
+
val noteTaskInfo = resolver.resolveInfo() ?: return
uiEvent?.let { uiEventLogger.log(it, noteTaskInfo.uid, noteTaskInfo.packageName) }
@@ -87,7 +105,7 @@ constructor(
// TODO(b/266686199): We should handle when app not available. For now, we log.
val intent = noteTaskInfo.toCreateNoteIntent()
try {
- if (isInMultiWindowMode || keyguardManager.isKeyguardLocked) {
+ if (isInMultiWindowMode || isKeyguardLocked) {
context.startActivity(intent)
} else {
bubbles.showOrHideAppBubble(intent)
@@ -144,7 +162,7 @@ constructor(
}
companion object {
- private val TAG = NoteTaskController::class.simpleName.orEmpty()
+ val TAG = NoteTaskController::class.simpleName.orEmpty()
private fun NoteTaskInfoResolver.NoteTaskInfo.toCreateNoteIntent(): Intent {
return Intent(ACTION_CREATE_NOTE)
@@ -165,3 +183,9 @@ constructor(
const val INTENT_EXTRA_USE_STYLUS_MODE = "android.intent.extra.USE_STYLUS_MODE"
}
}
+
+private inline fun logDebug(message: () -> String) {
+ if (Build.IS_DEBUGGABLE) {
+ Log.d(NoteTaskController.TAG, message())
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index f4640ad2e3cd..a5da06e3f1e5 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -1197,6 +1197,7 @@ public final class NotificationPanelViewController implements Dumpable {
}
private void onSplitShadeEnabledChanged() {
+ mShadeLog.logSplitShadeChanged(mSplitShadeEnabled);
// when we switch between split shade and regular shade we want to enforce setting qs to
// the default state: expanded for split shade and collapsed otherwise
if (!isOnKeyguard() && mPanelExpanded) {
@@ -1777,7 +1778,7 @@ public final class NotificationPanelViewController implements Dumpable {
if (animate && !isFullyCollapsed()) {
animateCloseQs(true);
} else {
- mQsController.closeQs();
+ closeQsIfPossible();
}
mNotificationStackScrollLayoutController.setOverScrollAmount(0f, true /* onTop */, animate,
!animate /* cancelAnimators */);
@@ -1914,7 +1915,6 @@ public final class NotificationPanelViewController implements Dumpable {
// we want to perform an overshoot animation when flinging open
final boolean addOverscroll =
expand
- && !mSplitShadeEnabled // Split shade has its own overscroll logic
&& mStatusBarStateController.getState() != KEYGUARD
&& mOverExpansion == 0.0f
&& vel >= 0;
@@ -2590,9 +2590,14 @@ public final class NotificationPanelViewController implements Dumpable {
return;
}
mOverExpansion = overExpansion;
- // Translating the quick settings by half the overexpansion to center it in the background
- // frame
- mQsController.updateQsFrameTranslation();
+ if (mSplitShadeEnabled) {
+ mQsController.setOverScrollAmount((int) overExpansion);
+ mScrimController.setNotificationsOverScrollAmount((int) overExpansion);
+ } else {
+ // Translating the quick settings by half the overexpansion to center it in the
+ // background frame
+ mQsController.updateQsFrameTranslation();
+ }
mNotificationStackScrollLayoutController.setOverExpansion(overExpansion);
}
@@ -3594,7 +3599,7 @@ public final class NotificationPanelViewController implements Dumpable {
private void fling(float vel, boolean expand, float collapseSpeedUpFactor,
boolean expandBecauseOfFalsing) {
- float target = expand ? getMaxPanelHeight() : 0;
+ float target = expand ? getMaxPanelTransitionDistance() : 0;
if (!expand) {
setClosing(true);
}
@@ -3679,7 +3684,7 @@ public final class NotificationPanelViewController implements Dumpable {
float maxPanelHeight = getMaxPanelTransitionDistance();
if (mHeightAnimator == null) {
// Split shade has its own overscroll logic
- if (mTracking && !mSplitShadeEnabled) {
+ if (mTracking) {
float overExpansionPixels = Math.max(0, h - maxPanelHeight);
setOverExpansionInternal(overExpansionPixels, true /* isFromGesture */);
}
@@ -4025,9 +4030,17 @@ public final class NotificationPanelViewController implements Dumpable {
return mExpandingFromHeadsUp;
}
- /** TODO: remove need for this delegate (b/254870148) */
- public void closeQs() {
- mQsController.closeQs();
+ /**
+ * We don't always want to close QS when requested as shade might be in a different state
+ * already e.g. when going from collapse to expand very quickly. In that case StatusBar
+ * window might send signal to collapse QS but we might be already expanding and in split
+ * shade QS are always expanded
+ */
+ private void closeQsIfPossible() {
+ boolean openOrOpening = isShadeFullyOpen() || isExpanding();
+ if (!(mSplitShadeEnabled && openOrOpening)) {
+ mQsController.closeQs();
+ }
}
/** TODO: remove need for this delegate (b/254870148) */
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
index d041212d24c7..a8378df81968 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
@@ -663,8 +663,15 @@ public class QuickSettingsController {
mDozing = dozing;
}
- /** set QS state to closed */
+ /**
+ * This method closes QS but in split shade it should be used only in special cases: to make
+ * sure QS closes when shade is closed as well. Otherwise it will result in QS disappearing
+ * from split shade
+ */
public void closeQs() {
+ if (mSplitShadeEnabled) {
+ mShadeLog.d("Closing QS while in split shade");
+ }
cancelExpansionAnimation();
setExpansionHeight(getMinExpansionHeight());
// qsExpandImmediate is a safety latch in case we're calling closeQS while we're in the
@@ -803,6 +810,10 @@ public class QuickSettingsController {
}
}
+ void setOverScrollAmount(int overExpansion) {
+ mQs.setOverScrollAmount(overExpansion);
+ }
+
private void setOverScrolling(boolean overscrolling) {
mStackScrollerOverscrolling = overscrolling;
if (mQs != null) {
@@ -1710,12 +1721,16 @@ public class QuickSettingsController {
*/
private void flingQs(float vel, int type, final Runnable onFinishRunnable,
boolean isClick) {
+ mShadeLog.flingQs(type, isClick);
float target;
switch (type) {
case FLING_EXPAND:
target = getMaxExpansionHeight();
break;
case FLING_COLLAPSE:
+ if (mSplitShadeEnabled) { // TODO:(b/269742565) remove below log
+ Log.wtfStack(TAG, "FLING_COLLAPSE called in split shade");
+ }
target = getMinExpansionHeight();
break;
case FLING_HIDE:
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
index 026673adb86b..c1369935db54 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
@@ -270,8 +270,6 @@ public final class ShadeControllerImpl implements ShadeController {
// Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868)
mNotificationPanelViewController.collapsePanel(false, false, 1.0f);
- mNotificationPanelViewController.closeQs();
-
mExpandedVisible = false;
notifyVisibilityChanged(false);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
index aa8c5b65e0fe..d34e127b194b 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
@@ -20,6 +20,9 @@ import android.view.MotionEvent
import com.android.systemui.log.dagger.ShadeLog
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.shade.NotificationPanelViewController.FLING_COLLAPSE
+import com.android.systemui.shade.NotificationPanelViewController.FLING_EXPAND
+import com.android.systemui.shade.NotificationPanelViewController.FLING_HIDE
import com.google.errorprone.annotations.CompileTimeConstant
import javax.inject.Inject
@@ -241,18 +244,40 @@ class ShadeLogger @Inject constructor(@ShadeLog private val buffer: LogBuffer) {
)
}
- fun logLastFlingWasExpanding(
- expand: Boolean
- ) {
+ fun logLastFlingWasExpanding(expand: Boolean) {
buffer.log(
- TAG,
- LogLevel.VERBOSE,
- {
- bool1 = expand
- },
- {
- "NPVC mLastFlingWasExpanding set to: $bool1"
- }
+ TAG,
+ LogLevel.VERBOSE,
+ { bool1 = expand },
+ { "NPVC mLastFlingWasExpanding set to: $bool1" }
+ )
+ }
+
+ fun flingQs(flingType: Int, isClick: Boolean) {
+ buffer.log(
+ TAG,
+ LogLevel.VERBOSE,
+ {
+ str1 = flingTypeToString(flingType)
+ bool1 = isClick
+ },
+ { "QS fling with type $str1, originated from click: $isClick" }
+ )
+ }
+
+ private fun flingTypeToString(flingType: Int) = when (flingType) {
+ FLING_EXPAND -> "FLING_EXPAND"
+ FLING_COLLAPSE -> "FLING_COLLAPSE"
+ FLING_HIDE -> "FLING_HIDE"
+ else -> "UNKNOWN"
+ }
+
+ fun logSplitShadeChanged(splitShadeEnabled: Boolean) {
+ buffer.log(
+ TAG,
+ LogLevel.VERBOSE,
+ { bool1 = splitShadeEnabled },
+ { "Split shade state changed: split shade ${if (bool1) "enabled" else "disabled"}" }
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
index 07820ecd513e..129d09ec3c14 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
@@ -43,8 +43,6 @@ constructor(
shadeExpansionStateManager: ShadeExpansionStateManager,
dumpManager: DumpManager,
private val context: Context,
- private val splitShadeOverScrollerFactory: SplitShadeOverScroller.Factory,
- private val noOpOverScroller: NoOpOverScroller,
private val scrimShadeTransitionController: ScrimShadeTransitionController,
private val statusBarStateController: SysuiStatusBarStateController,
) {
@@ -57,17 +55,6 @@ constructor(
private var currentPanelState: Int? = null
private var lastShadeExpansionChangeEvent: ShadeExpansionChangeEvent? = null
- private val splitShadeOverScroller by lazy {
- splitShadeOverScrollerFactory.create({ qs }, { notificationStackScrollLayoutController })
- }
- private val shadeOverScroller: ShadeOverScroller
- get() =
- if (inSplitShade && isScreenUnlocked() && propertiesInitialized()) {
- splitShadeOverScroller
- } else {
- noOpOverScroller
- }
-
init {
updateResources()
configurationController.addCallback(
@@ -89,21 +76,14 @@ constructor(
private fun onPanelStateChanged(@PanelState state: Int) {
currentPanelState = state
- shadeOverScroller.onPanelStateChanged(state)
scrimShadeTransitionController.onPanelStateChanged(state)
}
private fun onPanelExpansionChanged(event: ShadeExpansionChangeEvent) {
lastShadeExpansionChangeEvent = event
- shadeOverScroller.onDragDownAmountChanged(event.dragDownPxAmount)
scrimShadeTransitionController.onPanelExpansionChanged(event)
}
- private fun propertiesInitialized() =
- this::qs.isInitialized &&
- this::notificationPanelViewController.isInitialized &&
- this::notificationStackScrollLayoutController.isInitialized
-
private fun dump(pw: PrintWriter) {
pw.println(
"""
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt
deleted file mode 100644
index f95125f5cb6c..000000000000
--- a/packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2022 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.shade.transition
-
-import android.animation.Animator
-import android.animation.ValueAnimator
-import android.content.Context
-import android.content.res.Configuration
-import android.util.MathUtils
-import com.android.internal.annotations.VisibleForTesting
-import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.plugins.qs.QS
-import com.android.systemui.shade.PanelState
-import com.android.systemui.shade.STATE_CLOSED
-import com.android.systemui.shade.STATE_OPENING
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
-import com.android.systemui.statusbar.phone.ScrimController
-import com.android.systemui.statusbar.policy.ConfigurationController
-import dagger.assisted.Assisted
-import dagger.assisted.AssistedFactory
-import dagger.assisted.AssistedInject
-import java.io.PrintWriter
-
-class SplitShadeOverScroller
-@AssistedInject
-constructor(
- configurationController: ConfigurationController,
- dumpManager: DumpManager,
- private val context: Context,
- private val scrimController: ScrimController,
- @Assisted private val qSProvider: () -> QS,
- @Assisted private val nsslControllerProvider: () -> NotificationStackScrollLayoutController
-) : ShadeOverScroller {
-
- private var releaseOverScrollDuration = 0L
- private var maxOverScrollAmount = 0
- private var previousOverscrollAmount = 0
- private var dragDownAmount: Float = 0f
- @PanelState private var panelState: Int = STATE_CLOSED
-
- private var releaseOverScrollAnimator: Animator? = null
-
- private val qS: QS
- get() = qSProvider()
-
- private val nsslController: NotificationStackScrollLayoutController
- get() = nsslControllerProvider()
-
- init {
- updateResources()
- configurationController.addCallback(
- object : ConfigurationController.ConfigurationListener {
- override fun onConfigChanged(newConfig: Configuration?) {
- updateResources()
- }
- })
- dumpManager.registerCriticalDumpable("SplitShadeOverScroller") { printWriter, _ ->
- dump(printWriter)
- }
- }
-
- private fun updateResources() {
- val resources = context.resources
- maxOverScrollAmount = resources.getDimensionPixelSize(R.dimen.shade_max_over_scroll_amount)
- releaseOverScrollDuration =
- resources.getInteger(R.integer.lockscreen_shade_over_scroll_release_duration).toLong()
- }
-
- override fun onPanelStateChanged(@PanelState newPanelState: Int) {
- if (shouldReleaseOverscroll(previousState = panelState, newState = newPanelState)) {
- releaseOverScroll()
- }
- panelState = newPanelState
- }
-
- override fun onDragDownAmountChanged(newDragDownAmount: Float) {
- if (dragDownAmount == newDragDownAmount) {
- return
- }
- dragDownAmount = newDragDownAmount
- if (shouldOverscroll()) {
- overScroll(newDragDownAmount)
- }
- }
-
- private fun shouldOverscroll() = panelState == STATE_OPENING
-
- private fun shouldReleaseOverscroll(@PanelState previousState: Int, @PanelState newState: Int) =
- previousState == STATE_OPENING && newState != STATE_OPENING
-
- private fun overScroll(dragDownAmount: Float) {
- val overscrollAmount: Int = calculateOverscrollAmount(dragDownAmount)
- applyOverscroll(overscrollAmount)
- previousOverscrollAmount = overscrollAmount
- }
-
- private fun calculateOverscrollAmount(dragDownAmount: Float): Int {
- val fullHeight: Int = nsslController.height
- val fullHeightProgress: Float = MathUtils.saturate(dragDownAmount / fullHeight)
- return (fullHeightProgress * maxOverScrollAmount).toInt()
- }
-
- private fun applyOverscroll(overscrollAmount: Int) {
- qS.setOverScrollAmount(overscrollAmount)
- scrimController.setNotificationsOverScrollAmount(overscrollAmount)
- nsslController.setOverScrollAmount(overscrollAmount)
- }
-
- private fun releaseOverScroll() {
- val animator = ValueAnimator.ofInt(previousOverscrollAmount, 0)
- animator.addUpdateListener {
- val overScrollAmount = it.animatedValue as Int
- qS.setOverScrollAmount(overScrollAmount)
- scrimController.setNotificationsOverScrollAmount(overScrollAmount)
- nsslController.setOverScrollAmount(overScrollAmount)
- }
- animator.interpolator = Interpolators.STANDARD
- animator.duration = releaseOverScrollDuration
- animator.start()
- releaseOverScrollAnimator = animator
- previousOverscrollAmount = 0
- }
-
- @VisibleForTesting
- internal fun finishAnimations() {
- releaseOverScrollAnimator?.end()
- releaseOverScrollAnimator = null
- }
-
- private fun dump(pw: PrintWriter) {
- pw.println(
- """
- SplitShadeOverScroller:
- Resources:
- releaseOverScrollDuration: $releaseOverScrollDuration
- maxOverScrollAmount: $maxOverScrollAmount
- State:
- previousOverscrollAmount: $previousOverscrollAmount
- dragDownAmount: $dragDownAmount
- panelState: $panelState
- """.trimIndent())
- }
-
- @AssistedFactory
- fun interface Factory {
- fun create(
- qSProvider: () -> QS,
- nsslControllerProvider: () -> NotificationStackScrollLayoutController
- ): SplitShadeOverScroller
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index f20f929637cd..43fbc7cbae03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -356,7 +356,7 @@ public final class KeyboardShortcuts {
* Keyboard with its default map.
*/
private void retrieveKeyCharacterMap(int deviceId) {
- final InputManager inputManager = InputManager.getInstance();
+ final InputManager inputManager = mContext.getSystemService(InputManager.class);
mBackupKeyCharacterMap = inputManager.getInputDevice(-1).getKeyCharacterMap();
if (deviceId != -1) {
final InputDevice inputDevice = inputManager.getInputDevice(deviceId);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index b1152333b5e1..a127139fcc69 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -66,6 +66,7 @@ import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInt
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.navigationbar.TaskbarDelegate;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shade.NotificationPanelViewController;
import com.android.systemui.shade.ShadeController;
@@ -300,6 +301,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
@Nullable private KeyguardBypassController mBypassController;
@Nullable private OccludingAppBiometricUI mOccludingAppBiometricUI;
+ @Nullable private TaskbarDelegate mTaskbarDelegate;
private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@Override
@@ -564,6 +566,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
updateStates();
}
+ public void setTaskbarDelegate(TaskbarDelegate taskbarDelegate) {
+ mTaskbarDelegate = taskbarDelegate;
+ }
+
/**
* Show the keyguard. Will handle creating and attaching to the view manager
* lazily.
@@ -790,7 +796,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
@Override
public void onFinishedGoingToSleep() {
- mPrimaryBouncerInteractor.onScreenTurnedOff();
+ mPrimaryBouncerInteractor.hide();
}
@Override
@@ -1193,7 +1199,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
* Updates the visibility of the nav bar window (which will cause insets changes).
*/
protected void updateNavigationBarVisibility(boolean navBarVisible) {
- if (mCentralSurfaces.getNavigationBarView() != null) {
+ if (mCentralSurfaces.getNavigationBarView() != null
+ || (mTaskbarDelegate != null && mTaskbarDelegate.isInitialized())) {
if (navBarVisible) {
long delay = getNavBarShowDelay();
if (delay == 0) {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index 568e8d20cd76..064bc9c0036d 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -32,11 +32,9 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -44,7 +42,6 @@ import static org.mockito.Mockito.when;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.hardware.biometrics.BiometricOverlayConstants;
-import android.hardware.biometrics.BiometricSourceType;
import android.media.AudioManager;
import android.telephony.TelephonyManager;
import android.testing.AndroidTestingRunner;
@@ -53,7 +50,6 @@ import android.testing.TestableResources;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
-import android.view.View;
import android.view.WindowInsetsController;
import android.widget.FrameLayout;
@@ -96,10 +92,8 @@ import java.util.Optional;
@TestableLooper.RunWithLooper()
public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
private static final int TARGET_USER_ID = 100;
-
@Rule
public MockitoRule mRule = MockitoJUnit.rule();
-
@Mock
private KeyguardSecurityContainer mView;
@Mock
@@ -368,134 +362,12 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
}
@Test
- public void onBouncerVisibilityChanged_allConditionsGood_sideFpsHintShown() {
- setupConditionsToEnableSideFpsHint();
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
-
- verify(mSideFpsController).show(SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
- verify(mSideFpsController, never()).hide(any());
- }
-
- @Test
- public void onBouncerVisibilityChanged_fpsSensorNotRunning_sideFpsHintHidden() {
- setupConditionsToEnableSideFpsHint();
- setFingerprintDetectionRunning(false);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
- public void onBouncerVisibilityChanged_withoutSidedSecurity_sideFpsHintHidden() {
- setupConditionsToEnableSideFpsHint();
- setSideFpsHintEnabledFromResources(false);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
- public void onBouncerVisibilityChanged_unlockingWithFingerprintNotAllowed_sideFpsHintHidden() {
- setupConditionsToEnableSideFpsHint();
- setUnlockingWithFingerprintAllowed(false);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
- public void onBouncerVisibilityChanged_sideFpsHintShown_sideFpsHintHidden() {
- setupGetSecurityView();
- setupConditionsToEnableSideFpsHint();
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
- verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.INVISIBLE);
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
public void onBouncerVisibilityChanged_resetsScale() {
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.INVISIBLE);
-
+ mKeyguardSecurityContainerController.onBouncerVisibilityChanged(false);
verify(mView).resetScale();
}
@Test
- public void onStartingToHide_sideFpsHintShown_sideFpsHintHidden() {
- setupGetSecurityView();
- setupConditionsToEnableSideFpsHint();
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
- verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onStartingToHide();
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
- public void onPause_sideFpsHintShown_sideFpsHintHidden() {
- setupGetSecurityView();
- setupConditionsToEnableSideFpsHint();
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
- verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onPause();
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
- public void onResume_sideFpsHintShouldBeShown_sideFpsHintShown() {
- setupGetSecurityView();
- setupConditionsToEnableSideFpsHint();
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onResume(0);
-
- verify(mSideFpsController).show(SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
- verify(mSideFpsController, never()).hide(any());
- }
-
- @Test
- public void onResume_sideFpsHintShouldNotBeShown_sideFpsHintHidden() {
- setupGetSecurityView();
- setupConditionsToEnableSideFpsHint();
- setSideFpsHintEnabledFromResources(false);
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onResume(0);
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
public void showNextSecurityScreenOrFinish_setsSecurityScreenToPinAfterSimPinUnlock() {
// GIVEN the current security method is SimPin
when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false);
@@ -721,39 +593,31 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
any(KeyguardSecurityCallback.class));
}
+ @Test
+ public void testSideFpsControllerShow() {
+ mKeyguardSecurityContainerController.updateSideFpsVisibility(/* isVisible= */ true);
+ verify(mSideFpsController).show(
+ SideFpsUiRequestSource.PRIMARY_BOUNCER,
+ BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
+ }
+
+ @Test
+ public void testSideFpsControllerHide() {
+ mKeyguardSecurityContainerController.updateSideFpsVisibility(/* isVisible= */ false);
+ verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
+ }
+
private KeyguardSecurityContainer.SwipeListener getRegisteredSwipeListener() {
mKeyguardSecurityContainerController.onViewAttached();
verify(mView).setSwipeListener(mSwipeListenerArgumentCaptor.capture());
return mSwipeListenerArgumentCaptor.getValue();
}
- private void setupConditionsToEnableSideFpsHint() {
- attachView();
- setSideFpsHintEnabledFromResources(true);
- setFingerprintDetectionRunning(true);
- setUnlockingWithFingerprintAllowed(true);
- }
-
private void attachView() {
mKeyguardSecurityContainerController.onViewAttached();
verify(mKeyguardUpdateMonitor).registerCallback(mKeyguardUpdateMonitorCallback.capture());
}
- private void setFingerprintDetectionRunning(boolean running) {
- when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(running);
- mKeyguardUpdateMonitorCallback.getValue().onBiometricRunningStateChanged(running,
- BiometricSourceType.FINGERPRINT);
- }
-
- private void setSideFpsHintEnabledFromResources(boolean enabled) {
- mTestableResources.addOverride(R.bool.config_show_sidefps_hint_on_bouncer,
- enabled);
- }
-
- private void setUnlockingWithFingerprintAllowed(boolean allowed) {
- when(mKeyguardUpdateMonitor.isUnlockingWithFingerprintAllowed()).thenReturn(allowed);
- }
-
private void setupGetSecurityView() {
when(mKeyguardSecurityViewFlipperController.getSecurityView(
any(), any(KeyguardSecurityCallback.class)))
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index e5d0692aaac2..a1e4f70352d6 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -617,7 +617,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
anyInt());
- verify(mFingerprintManager, never()).detectFingerprint(any(), any(), anyInt());
+ verify(mFingerprintManager, never()).detectFingerprint(any(), any(), any());
}
@Test
@@ -629,7 +629,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
anyInt(), anyInt());
- verify(mFingerprintManager, never()).detectFingerprint(any(), any(), anyInt());
+ verify(mFingerprintManager, never()).detectFingerprint(any(), any(), any());
}
@Test
@@ -644,7 +644,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt());
- verify(mFingerprintManager).detectFingerprint(any(), any(), anyInt());
+ verify(mFingerprintManager).detectFingerprint(any(), any(), any());
}
@Test
@@ -733,7 +733,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
public void testTriesToAuthenticate_whenBouncer() {
setKeyguardBouncerVisibility(true);
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
verify(mFaceManager, never()).hasEnrolledTemplates(anyInt());
}
@@ -742,8 +742,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.sendPrimaryBouncerChanged(
/* bouncerIsOrWillBeShowing */ true, /* bouncerFullyShown */ false);
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -751,7 +750,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
keyguardIsVisible();
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
verify(mUiEventLogger).logWithInstanceIdAndPosition(
eq(FaceAuthUiEvent.FACE_AUTH_UPDATED_STARTED_WAKING_UP),
eq(0),
@@ -767,8 +766,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -779,8 +777,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -804,9 +801,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
// THEN face detect and authenticate are NOT triggered
- verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verify(mFaceManager, never()).detectFace(any(), any(), any());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
// THEN biometric help message sent to callback
verify(keyguardUpdateMonitorCallback).onBiometricHelp(
@@ -827,9 +823,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
// FACE detect is triggered, not authenticate
- verify(mFaceManager).detectFace(any(), any(), anyInt());
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verify(mFaceManager).detectFace(any(), any(), any());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
// WHEN bouncer becomes visible
setKeyguardBouncerVisibility(true);
@@ -837,9 +832,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
// THEN face scanning is not run
mKeyguardUpdateMonitor.requestFaceAuth(FaceAuthApiRequestReason.UDFPS_POINTER_DOWN);
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
- verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
+ verify(mFaceManager, never()).detectFace(any(), any(), any());
}
@Test
@@ -854,9 +848,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
// FACE detect and authenticate are NOT triggered
- verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verify(mFaceManager, never()).detectFace(any(), any(), any());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -894,7 +887,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.setKeyguardShowing(true, true);
mKeyguardUpdateMonitor.setAssistantVisible(true);
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -906,8 +899,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
any(),
any(),
any(),
- anyInt(),
- anyBoolean());
+ anyInt());
}
@Test
@@ -938,7 +930,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
KeyguardUpdateMonitor.getCurrentUser(), 0 /* flags */,
new ArrayList<>());
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -946,7 +938,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.setKeyguardShowing(true, true);
mKeyguardUpdateMonitor.setAssistantVisible(true);
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
mTestableLooper.processAllMessages();
clearInvocations(mFaceManager);
@@ -963,8 +955,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
any(),
any(),
any(),
- anyInt(),
- anyBoolean());
+ anyInt());
}
@Test
@@ -974,8 +965,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.onTrustChanged(true /* enabled */, true /* newlyUnlocked */,
KeyguardUpdateMonitor.getCurrentUser(), 0 /* flags */, new ArrayList<>());
keyguardIsVisible();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -987,9 +977,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
keyguardIsVisible();
mTestableLooper.processAllMessages();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
- verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
+ verify(mFaceManager, never()).detectFace(any(), any(), any());
}
@Test
@@ -1019,8 +1008,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
setKeyguardBouncerVisibility(true);
mTestableLooper.processAllMessages();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -1147,7 +1135,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
anyInt());
@@ -1599,8 +1587,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.setCredentialAttempted();
verify(mFingerprintManager, never()).authenticate(any(), any(), any(),
any(), anyInt());
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -1975,7 +1962,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
anyInt());
@@ -2004,7 +1991,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
verify(mFaceManager, never()).authenticate(
- any(), any(), any(), any(), anyInt(), anyBoolean());
+ any(), any(), any(), any(), anyInt());
}
@Test
@@ -2018,14 +2005,14 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
// THEN face auth isn't triggered
verify(mFaceManager, never()).authenticate(
- any(), any(), any(), any(), anyInt(), anyBoolean());
+ any(), any(), any(), any(), anyInt());
// WHEN device wakes up from the power button
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
// THEN face auth is triggered
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -2195,7 +2182,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
anyInt());
@@ -2228,7 +2215,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
final CancellationSignal faceCancel = spy(mKeyguardUpdateMonitor.mFaceCancelSignal);
mKeyguardUpdateMonitor.mFaceCancelSignal = faceCancel;
@@ -2596,8 +2583,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
any(),
mAuthenticationCallbackCaptor.capture(),
any(),
- anyInt(),
- anyBoolean());
+ anyInt());
mAuthenticationCallbackCaptor.getValue()
.onAuthenticationSucceeded(
new FaceManager.AuthenticationResult(null, null, mCurrentUserId, false));
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt
index e9a2789bb5c8..9fe32f1e378b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt
@@ -32,6 +32,7 @@ import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import java.util.Optional
@@ -83,6 +84,33 @@ class ScreenOnCoordinatorTest : SysuiTestCase() {
}
@Test
+ fun testTasksReady_onScreenTurningOnAndTurnedOnEventsCalledTogether_callsDrawnCallback() {
+ screenOnCoordinator.onScreenTurningOn(runnable)
+ screenOnCoordinator.onScreenTurnedOn()
+
+ onUnfoldOverlayReady()
+ onFoldAodReady()
+ waitHandlerIdle(testHandler)
+
+ // Should be called when both unfold overlay and keyguard drawn ready
+ verify(runnable).run()
+ }
+
+ @Test
+ fun testTasksReady_onScreenTurnedOnAndTurnedOffBeforeCompletion_doesNotCallDrawnCallback() {
+ screenOnCoordinator.onScreenTurningOn(runnable)
+ screenOnCoordinator.onScreenTurnedOn()
+ screenOnCoordinator.onScreenTurnedOff()
+
+ onUnfoldOverlayReady()
+ onFoldAodReady()
+ waitHandlerIdle(testHandler)
+
+ // Should not be called because this screen turning on call is not valid anymore
+ verify(runnable, never()).run()
+ }
+
+ @Test
fun testUnfoldTransitionDisabledDrawnTasksReady_onScreenTurningOn_callsDrawnCallback() {
// Recreate with empty unfoldComponent
screenOnCoordinator = ScreenOnCoordinator(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
index c73ff1dab3d8..54c9d392ad1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
@@ -86,8 +86,9 @@ class UdfpsKeyguardViewControllerWithCoroutinesTest : UdfpsKeyguardViewControlle
mock(PrimaryBouncerCallbackInteractor::class.java),
mock(FalsingCollector::class.java),
mock(DismissCallbackRegistry::class.java),
+ context,
+ mKeyguardUpdateMonitor,
mock(KeyguardBypassController::class.java),
- mKeyguardUpdateMonitor
)
mAlternateBouncerInteractor =
AlternateBouncerInteractor(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt b/packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt
new file mode 100644
index 000000000000..34d5661597ca
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.devicepolicy
+
+import android.app.admin.DevicePolicyManager
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FACE
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL
+import androidx.test.filters.SmallTest
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(JUnit4::class)
+class DevicePolicyManagerExtTest {
+
+ @Mock lateinit var devicePolicyManager: DevicePolicyManager
+ @Mock private lateinit var userTracker: UserTracker
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ whenever(userTracker.userId).thenReturn(CURRENT_USER_ID)
+ }
+
+ // region areKeyguardShortcutsDisabled
+ @Test
+ fun areKeyguardShortcutsDisabled_noDisabledKeyguardFeature_shouldReturnFalse() {
+ whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+ .thenReturn(KEYGUARD_DISABLE_FEATURES_NONE)
+
+ assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+ .isFalse()
+ }
+
+ @Test
+ fun areKeyguardShortcutsDisabled_otherDisabledKeyguardFeatures_shouldReturnFalse() {
+ whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+ .thenReturn(KEYGUARD_DISABLE_SECURE_CAMERA or KEYGUARD_DISABLE_FACE)
+
+ assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+ .isFalse()
+ }
+
+ @Test
+ fun areKeyguardShortcutsDisabled_disabledShortcutsKeyguardFeature_shouldReturnTrue() {
+ whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+ .thenReturn(KEYGUARD_DISABLE_SHORTCUTS_ALL)
+
+ assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+ .isTrue()
+ }
+
+ @Test
+ fun areKeyguardShortcutsDisabled_disabledAllKeyguardFeatures_shouldReturnTrue() {
+ whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+ .thenReturn(KEYGUARD_DISABLE_FEATURES_ALL)
+
+ assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+ .isTrue()
+ }
+ // endregion
+
+ private companion object {
+ const val CURRENT_USER_ID = 123
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt
new file mode 100644
index 000000000000..f6ff4b214035
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyboard.data.repository
+
+import android.hardware.input.InputManager
+import android.view.InputDevice
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.nullable
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class KeyboardRepositoryTest : SysuiTestCase() {
+
+ @Captor
+ private lateinit var deviceListenerCaptor: ArgumentCaptor<InputManager.InputDeviceListener>
+ @Mock private lateinit var inputManager: InputManager
+
+ private lateinit var underTest: KeyboardRepository
+ private lateinit var dispatcher: CoroutineDispatcher
+ private lateinit var testScope: TestScope
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf())
+ whenever(inputManager.getInputDevice(any())).then { invocation ->
+ val id = invocation.arguments.first()
+ INPUT_DEVICES_MAP[id]
+ }
+ dispatcher = StandardTestDispatcher()
+ testScope = TestScope(dispatcher)
+ underTest = KeyboardRepositoryImpl(testScope.backgroundScope, dispatcher, inputManager)
+ }
+
+ @Test
+ fun emitsDisconnected_ifNothingIsConnected() =
+ testScope.runTest {
+ val initialState = underTest.keyboardConnected.first()
+ assertThat(initialState).isFalse()
+ }
+
+ @Test
+ fun emitsConnected_ifKeyboardAlreadyConnectedAtTheStart() =
+ testScope.runTest {
+ whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf(PHYSICAL_FULL_KEYBOARD_ID))
+ val initialValue = underTest.keyboardConnected.first()
+ assertThat(initialValue).isTrue()
+ }
+
+ @Test
+ fun emitsConnected_whenNewPhysicalKeyboardConnects() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID)
+
+ assertThat(isKeyboardConnected).isTrue()
+ }
+
+ @Test
+ fun emitsDisconnected_whenKeyboardDisconnects() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isTrue()
+
+ deviceListener.onInputDeviceRemoved(PHYSICAL_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isFalse()
+ }
+
+ private suspend fun captureDeviceListener(): InputManager.InputDeviceListener {
+ underTest.keyboardConnected.first()
+ verify(inputManager).registerInputDeviceListener(deviceListenerCaptor.capture(), nullable())
+ return deviceListenerCaptor.value
+ }
+
+ @Test
+ fun emitsDisconnected_whenVirtualOrNotFullKeyboardConnects() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_NOT_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isFalse()
+
+ deviceListener.onInputDeviceAdded(VIRTUAL_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isFalse()
+ }
+
+ @Test
+ fun emitsDisconnected_whenKeyboardDisconnectsAndWasAlreadyConnectedAtTheStart() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceRemoved(PHYSICAL_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isFalse()
+ }
+
+ @Test
+ fun emitsConnected_whenAnotherDeviceDisconnects() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID)
+ deviceListener.onInputDeviceRemoved(VIRTUAL_FULL_KEYBOARD_ID)
+
+ assertThat(isKeyboardConnected).isTrue()
+ }
+
+ @Test
+ fun emitsConnected_whenOnePhysicalKeyboardDisconnectsButAnotherRemainsConnected() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID)
+ deviceListener.onInputDeviceAdded(ANOTHER_PHYSICAL_FULL_KEYBOARD_ID)
+ deviceListener.onInputDeviceRemoved(ANOTHER_PHYSICAL_FULL_KEYBOARD_ID)
+
+ assertThat(isKeyboardConnected).isTrue()
+ }
+
+ @Test
+ fun passesKeyboardBacklightValues_fromBacklightListener() {
+ // TODO(b/268645734): implement when implementing backlight listener
+ }
+
+ private companion object {
+ private const val PHYSICAL_FULL_KEYBOARD_ID = 1
+ private const val VIRTUAL_FULL_KEYBOARD_ID = 2
+ private const val PHYSICAL_NOT_FULL_KEYBOARD_ID = 3
+ private const val ANOTHER_PHYSICAL_FULL_KEYBOARD_ID = 4
+
+ private val INPUT_DEVICES_MAP: Map<Int, InputDevice> =
+ mapOf(
+ PHYSICAL_FULL_KEYBOARD_ID to inputDevice(virtual = false, fullKeyboard = true),
+ VIRTUAL_FULL_KEYBOARD_ID to inputDevice(virtual = true, fullKeyboard = true),
+ PHYSICAL_NOT_FULL_KEYBOARD_ID to inputDevice(virtual = false, fullKeyboard = false),
+ ANOTHER_PHYSICAL_FULL_KEYBOARD_ID to
+ inputDevice(virtual = false, fullKeyboard = true)
+ )
+
+ private fun inputDevice(virtual: Boolean, fullKeyboard: Boolean): InputDevice =
+ mock<InputDevice>().also {
+ whenever(it.isVirtual).thenReturn(virtual)
+ whenever(it.isFullKeyboard).thenReturn(fullKeyboard)
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManagerTest.kt
index 7c604f760681..d55370b20d09 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManagerTest.kt
@@ -21,6 +21,7 @@ import android.content.pm.UserInfo
import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_CANCELED
import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT
import android.hardware.biometrics.ComponentInfoInternal
+import android.hardware.face.FaceAuthenticateOptions
import android.hardware.face.FaceManager
import android.hardware.face.FaceSensorProperties
import android.hardware.face.FaceSensorPropertiesInternal
@@ -62,7 +63,6 @@ import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.any
-import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.eq
import org.mockito.Captor
import org.mockito.Mock
@@ -276,7 +276,7 @@ class KeyguardFaceAuthManagerTest : SysuiTestCase() {
underTest.detect()
- verify(faceManager, never()).detectFace(any(), any(), anyInt())
+ verify(faceManager, never()).detectFace(any(), any(), any())
}
@Test
@@ -379,7 +379,7 @@ class KeyguardFaceAuthManagerTest : SysuiTestCase() {
.detectFace(
cancellationSignal.capture(),
detectionCallback.capture(),
- eq(currentUserId)
+ eq(FaceAuthenticateOptions.Builder().setUserId(currentUserId).build())
)
}
@@ -390,8 +390,7 @@ class KeyguardFaceAuthManagerTest : SysuiTestCase() {
cancellationSignal.capture(),
authenticationCallback.capture(),
isNull(),
- eq(currentUserId),
- eq(true)
+ eq(FaceAuthenticateOptions.Builder().setUserId(currentUserId).build())
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
index 46ed829e0574..6b7fd616e678 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
@@ -19,11 +19,13 @@ package com.android.systemui.keyguard.domain.interactor
import android.os.Looper
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
+import android.testing.TestableResources
import android.view.View
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.DejankUtils
+import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.keyguard.DismissCallbackRegistry
@@ -69,6 +71,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
private val mainHandler = FakeHandler(Looper.getMainLooper())
private lateinit var underTest: PrimaryBouncerInteractor
+ private lateinit var resources: TestableResources
@Before
fun setUp() {
@@ -84,18 +87,19 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
mPrimaryBouncerCallbackInteractor,
falsingCollector,
dismissCallbackRegistry,
- keyguardBypassController,
+ context,
keyguardUpdateMonitor,
+ keyguardBypassController,
)
`when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
`when`(repository.primaryBouncerShow.value).thenReturn(null)
`when`(bouncerView.delegate).thenReturn(bouncerViewDelegate)
+ resources = context.orCreateTestableResources
}
@Test
fun testShow_isScrimmed() {
underTest.show(true)
- verify(repository).setOnScreenTurnedOff(false)
verify(repository).setKeyguardAuthenticated(null)
verify(repository).setPrimaryHide(false)
verify(repository).setPrimaryStartingToHide(false)
@@ -207,12 +211,6 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
}
@Test
- fun testOnScreenTurnedOff() {
- underTest.onScreenTurnedOff()
- verify(repository).setOnScreenTurnedOff(true)
- }
-
- @Test
fun testSetKeyguardPosition() {
underTest.setKeyguardPosition(0f)
verify(repository).setKeyguardPosition(0f)
@@ -286,4 +284,98 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
`when`(bouncerViewDelegate.willDismissWithActions()).thenReturn(false)
assertThat(underTest.willDismissWithAction()).isFalse()
}
+
+ @Test
+ fun testSideFpsVisibility() {
+ updateSideFpsVisibilityParameters(
+ isVisible = true,
+ sfpsEnabled = true,
+ fpsDetectionRunning = true,
+ isUnlockingWithFpAllowed = true,
+ isAnimatingAway = false
+ )
+ underTest.updateSideFpsVisibility()
+ verify(repository).setSideFpsShowing(true)
+ }
+
+ @Test
+ fun testSideFpsVisibility_notVisible() {
+ updateSideFpsVisibilityParameters(
+ isVisible = false,
+ sfpsEnabled = true,
+ fpsDetectionRunning = true,
+ isUnlockingWithFpAllowed = true,
+ isAnimatingAway = false
+ )
+ underTest.updateSideFpsVisibility()
+ verify(repository).setSideFpsShowing(false)
+ }
+
+ @Test
+ fun testSideFpsVisibility_sfpsNotEnabled() {
+ updateSideFpsVisibilityParameters(
+ isVisible = true,
+ sfpsEnabled = false,
+ fpsDetectionRunning = true,
+ isUnlockingWithFpAllowed = true,
+ isAnimatingAway = false
+ )
+ underTest.updateSideFpsVisibility()
+ verify(repository).setSideFpsShowing(false)
+ }
+
+ @Test
+ fun testSideFpsVisibility_fpsDetectionNotRunning() {
+ updateSideFpsVisibilityParameters(
+ isVisible = true,
+ sfpsEnabled = true,
+ fpsDetectionRunning = false,
+ isUnlockingWithFpAllowed = true,
+ isAnimatingAway = false
+ )
+ underTest.updateSideFpsVisibility()
+ verify(repository).setSideFpsShowing(false)
+ }
+
+ @Test
+ fun testSideFpsVisibility_UnlockingWithFpNotAllowed() {
+ updateSideFpsVisibilityParameters(
+ isVisible = true,
+ sfpsEnabled = true,
+ fpsDetectionRunning = true,
+ isUnlockingWithFpAllowed = false,
+ isAnimatingAway = false
+ )
+ underTest.updateSideFpsVisibility()
+ verify(repository).setSideFpsShowing(false)
+ }
+
+ @Test
+ fun testSideFpsVisibility_AnimatingAway() {
+ updateSideFpsVisibilityParameters(
+ isVisible = true,
+ sfpsEnabled = true,
+ fpsDetectionRunning = true,
+ isUnlockingWithFpAllowed = true,
+ isAnimatingAway = true
+ )
+ underTest.updateSideFpsVisibility()
+ verify(repository).setSideFpsShowing(false)
+ }
+
+ private fun updateSideFpsVisibilityParameters(
+ isVisible: Boolean,
+ sfpsEnabled: Boolean,
+ fpsDetectionRunning: Boolean,
+ isUnlockingWithFpAllowed: Boolean,
+ isAnimatingAway: Boolean
+ ) {
+ `when`(repository.primaryBouncerVisible.value).thenReturn(isVisible)
+ resources.addOverride(R.bool.config_show_sidefps_hint_on_bouncer, sfpsEnabled)
+ `when`(keyguardUpdateMonitor.isFingerprintDetectionRunning).thenReturn(fpsDetectionRunning)
+ `when`(keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed)
+ .thenReturn(isUnlockingWithFpAllowed)
+ `when`(repository.primaryBouncerStartingDisappearAnimation.value)
+ .thenReturn(if (isAnimatingAway) Runnable {} else null)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
index 75b74b0cfe28..f675e7997eb4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
@@ -26,7 +26,6 @@ import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.BouncerView
-import com.android.systemui.keyguard.data.BouncerViewDelegate
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -44,7 +43,6 @@ import org.mockito.MockitoAnnotations
class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() {
private lateinit var repository: FakeKeyguardBouncerRepository
@Mock private lateinit var bouncerView: BouncerView
- @Mock private lateinit var bouncerViewDelegate: BouncerViewDelegate
@Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
@Mock private lateinit var primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor
@@ -69,8 +67,9 @@ class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() {
primaryBouncerCallbackInteractor,
falsingCollector,
dismissCallbackRegistry,
- keyguardBypassController,
+ context,
keyguardUpdateMonitor,
+ keyguardBypassController,
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt
index 586af626d29e..65e4c10265cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt
@@ -16,15 +16,23 @@
package com.android.systemui.keyguard.ui.viewmodel
+import android.os.Looper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.SysuiTestCase
+import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.BouncerView
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.utils.os.FakeHandler
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.test.runCurrent
@@ -33,7 +41,6 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
-import org.mockito.Mockito
import org.mockito.MockitoAnnotations
@SmallTest
@@ -41,31 +48,69 @@ import org.mockito.MockitoAnnotations
@kotlinx.coroutines.ExperimentalCoroutinesApi
class KeyguardBouncerViewModelTest : SysuiTestCase() {
lateinit var underTest: KeyguardBouncerViewModel
+ lateinit var bouncerInteractor: PrimaryBouncerInteractor
@Mock lateinit var bouncerView: BouncerView
- @Mock lateinit var bouncerInteractor: PrimaryBouncerInteractor
+ @Mock private lateinit var keyguardStateController: KeyguardStateController
+ @Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
+ @Mock private lateinit var primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor
+ @Mock private lateinit var falsingCollector: FalsingCollector
+ @Mock private lateinit var dismissCallbackRegistry: DismissCallbackRegistry
+ @Mock private lateinit var keyguardBypassController: KeyguardBypassController
+ @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+ private val mainHandler = FakeHandler(Looper.getMainLooper())
+ val repository = FakeKeyguardBouncerRepository()
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
+ bouncerInteractor =
+ PrimaryBouncerInteractor(
+ repository,
+ bouncerView,
+ mainHandler,
+ keyguardStateController,
+ keyguardSecurityModel,
+ primaryBouncerCallbackInteractor,
+ falsingCollector,
+ dismissCallbackRegistry,
+ context,
+ keyguardUpdateMonitor,
+ keyguardBypassController,
+ )
underTest = KeyguardBouncerViewModel(bouncerView, bouncerInteractor)
}
@Test
- fun setMessage() =
- runTest {
- val flow = MutableStateFlow<BouncerShowMessageModel?>(null)
- var message: BouncerShowMessageModel? = null
- Mockito.`when`(bouncerInteractor.showMessage)
- .thenReturn(flow as Flow<BouncerShowMessageModel>)
- // Reinitialize the view model.
- underTest = KeyguardBouncerViewModel(bouncerView, bouncerInteractor)
+ fun setMessage() = runTest {
+ var message: BouncerShowMessageModel? = null
+ val job = underTest.bouncerShowMessage.onEach { message = it }.launchIn(this)
- flow.value = BouncerShowMessageModel(message = "abc", colorStateList = null)
+ repository.setShowMessage(BouncerShowMessageModel("abc", null))
+ // Run the tasks that are pending at this point of virtual time.
+ runCurrent()
+ assertThat(message?.message).isEqualTo("abc")
+ job.cancel()
+ }
+
+ @Test
+ fun shouldUpdateSideFps() = runTest {
+ var count = 0
+ val job = underTest.shouldUpdateSideFps.onEach { count++ }.launchIn(this)
+ repository.setPrimaryVisible(true)
+ // Run the tasks that are pending at this point of virtual time.
+ runCurrent()
+ assertThat(count).isEqualTo(1)
+ job.cancel()
+ }
- val job = underTest.bouncerShowMessage.onEach { message = it }.launchIn(this)
- // Run the tasks that are pending at this point of virtual time.
- runCurrent()
- assertThat(message?.message).isEqualTo("abc")
- job.cancel()
- }
+ @Test
+ fun sideFpsShowing() = runTest {
+ var sideFpsIsShowing = false
+ val job = underTest.sideFpsShowing.onEach { sideFpsIsShowing = it }.launchIn(this)
+ repository.setSideFpsShowing(true)
+ // Run the tasks that are pending at this point of virtual time.
+ runCurrent()
+ assertThat(sideFpsIsShowing).isEqualTo(true)
+ job.cancel()
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
index 537dfb821fef..1c9336a3fc66 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
@@ -13,6 +13,7 @@ import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.phone.AutoHideController
import com.android.systemui.statusbar.phone.LightBarController
import com.android.systemui.statusbar.phone.LightBarTransitionsController
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.wm.shell.back.BackAnimation
import com.android.wm.shell.pip.Pip
import org.junit.Before
@@ -66,6 +67,8 @@ class TaskbarDelegateTest : SysuiTestCase() {
lateinit var mBackAnimation: BackAnimation
@Mock
lateinit var mCurrentSysUiState: NavBarHelper.CurrentSysuiState
+ @Mock
+ lateinit var mStatusBarKeyguardViewManager: StatusBarKeyguardViewManager
@Before
fun setup() {
@@ -76,7 +79,7 @@ class TaskbarDelegateTest : SysuiTestCase() {
`when`(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState)
mTaskStackChangeListeners = TaskStackChangeListeners.getTestInstance()
mTaskbarDelegate = TaskbarDelegate(context, mEdgeBackGestureHandlerFactory,
- mLightBarControllerFactory)
+ mLightBarControllerFactory, mStatusBarKeyguardViewManager)
mTaskbarDelegate.setDependencies(mCommandQueue, mOverviewProxyService, mNavBarHelper,
mNavigationModeController, mSysUiState, mDumpManager, mAutoHideController,
mLightBarController, mOptionalPip, mBackAnimation, mTaskStackChangeListeners)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
index 39c4e06ff0bb..52b29ac909fe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.notetask
import android.app.KeyguardManager
+import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
@@ -29,6 +30,7 @@ import com.android.systemui.notetask.NoteTaskController.Companion.INTENT_EXTRA_U
import com.android.systemui.notetask.NoteTaskController.ShowNoteTaskUiEvent
import com.android.systemui.notetask.NoteTaskInfoResolver.NoteTaskInfo
import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
+import com.android.systemui.settings.UserTracker
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
@@ -39,6 +41,7 @@ import java.util.Optional
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
@@ -64,6 +67,8 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
@Mock lateinit var optionalUserManager: Optional<UserManager>
@Mock lateinit var userManager: UserManager
@Mock lateinit var uiEventLogger: UiEventLogger
+ @Mock private lateinit var userTracker: UserTracker
+ @Mock private lateinit var devicePolicyManager: DevicePolicyManager
@Before
fun setUp() {
@@ -75,6 +80,13 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
whenever(optionalKeyguardManager.orElse(null)).thenReturn(keyguardManager)
whenever(optionalUserManager.orElse(null)).thenReturn(userManager)
whenever(userManager.isUserUnlocked).thenReturn(true)
+ whenever(
+ devicePolicyManager.getKeyguardDisabledFeatures(
+ /* admin= */ eq(null),
+ /* userHandle= */ anyInt()
+ )
+ )
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE)
}
private fun createNoteTaskController(isEnabled: Boolean = true): NoteTaskController {
@@ -84,8 +96,10 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
optionalBubbles = optionalBubbles,
optionalKeyguardManager = optionalKeyguardManager,
optionalUserManager = optionalUserManager,
+ devicePolicyManager = devicePolicyManager,
isEnabled = isEnabled,
uiEventLogger = uiEventLogger,
+ userTracker = userTracker,
)
}
@@ -291,6 +305,86 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
}
// endregion
+ // region keyguard policy
+ @Test
+ fun showNoteTask_keyguardLocked_keyguardDisableShortcutsAll_shouldDoNothing() {
+ whenever(keyguardManager.isKeyguardLocked).thenReturn(true)
+ whenever(
+ devicePolicyManager.getKeyguardDisabledFeatures(
+ /* admin= */ eq(null),
+ /* userHandle= */ anyInt()
+ )
+ )
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL)
+
+ createNoteTaskController().showNoteTask(isInMultiWindowMode = false, uiEvent = null)
+
+ verifyZeroInteractions(context, bubbles, uiEventLogger)
+ }
+
+ @Test
+ fun showNoteTask_keyguardLocked_keyguardDisableFeaturesAll_shouldDoNothing() {
+ whenever(keyguardManager.isKeyguardLocked).thenReturn(true)
+ whenever(
+ devicePolicyManager.getKeyguardDisabledFeatures(
+ /* admin= */ eq(null),
+ /* userHandle= */ anyInt()
+ )
+ )
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
+
+ createNoteTaskController().showNoteTask(isInMultiWindowMode = false, uiEvent = null)
+
+ verifyZeroInteractions(context, bubbles, uiEventLogger)
+ }
+
+ @Test
+ fun showNoteTask_keyguardUnlocked_keyguardDisableShortcutsAll_shouldStartBubble() {
+ whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
+ whenever(
+ devicePolicyManager.getKeyguardDisabledFeatures(
+ /* admin= */ eq(null),
+ /* userHandle= */ anyInt()
+ )
+ )
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL)
+
+ createNoteTaskController().showNoteTask(isInMultiWindowMode = false, uiEvent = null)
+
+ val intentCaptor = argumentCaptor<Intent>()
+ verify(bubbles).showOrHideAppBubble(capture(intentCaptor))
+ intentCaptor.value.let { intent ->
+ assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+ assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
+ assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
+ assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
+ }
+ }
+
+ @Test
+ fun showNoteTask_keyguardUnlocked_keyguardDisableFeaturesAll_shouldStartBubble() {
+ whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
+ whenever(
+ devicePolicyManager.getKeyguardDisabledFeatures(
+ /* admin= */ eq(null),
+ /* userHandle= */ anyInt()
+ )
+ )
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
+
+ createNoteTaskController().showNoteTask(isInMultiWindowMode = false, uiEvent = null)
+
+ val intentCaptor = argumentCaptor<Intent>()
+ verify(bubbles).showOrHideAppBubble(capture(intentCaptor))
+ intentCaptor.value.let { intent ->
+ assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+ assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
+ assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
+ assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
+ }
+ }
+ // endregion
+
private companion object {
const val NOTES_PACKAGE_NAME = "com.android.note.app"
const val NOTES_UID = 123456
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java
index d828e510999a..515e1ee172ed 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java
@@ -57,6 +57,7 @@ import com.android.systemui.settings.UserTracker;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -65,7 +66,6 @@ import org.mockito.MockitoAnnotations;
import java.util.function.BiConsumer;
-
@RunWith(AndroidTestingRunner.class)
public final class AppClipsActivityTest extends SysuiTestCase {
@@ -140,6 +140,7 @@ public final class AppClipsActivityTest extends SysuiTestCase {
mActivityRule.finishActivity();
}
+ @Ignore("b/269403503")
@Test
public void appClipsLaunched_screenshotDisplayed() {
launchActivity();
@@ -147,6 +148,7 @@ public final class AppClipsActivityTest extends SysuiTestCase {
assertThat(((ImageView) mActivity.findViewById(R.id.preview)).getDrawable()).isNotNull();
}
+ @Ignore("b/269403503")
@Test
public void screenshotDisplayed_userConsented_screenshotExportedSuccessfully() {
ResultReceiver resultReceiver = createResultReceiver((resultCode, data) -> {
@@ -166,6 +168,7 @@ public final class AppClipsActivityTest extends SysuiTestCase {
verify(mUiEventLogger).log(SCREENSHOT_FOR_NOTE_ACCEPTED, TEST_UID, TEST_CALLING_PACKAGE);
}
+ @Ignore("b/269403503")
@Test
public void screenshotDisplayed_userDeclined() {
ResultReceiver resultReceiver = createResultReceiver((resultCode, data) -> {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
index 7cac854c0853..d5a1f804e6a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
@@ -2,37 +2,24 @@ package com.android.systemui.shade.transition
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
-import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
-import com.android.systemui.plugins.qs.QS
-import com.android.systemui.shade.NotificationPanelViewController
import com.android.systemui.shade.STATE_OPENING
import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.shade.ShadeExpansionStateManager
-import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.policy.FakeConfigurationController
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
-import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@SmallTest
class ShadeTransitionControllerTest : SysuiTestCase() {
- @Mock private lateinit var npvc: NotificationPanelViewController
- @Mock private lateinit var nsslController: NotificationStackScrollLayoutController
- @Mock private lateinit var qs: QS
- @Mock private lateinit var noOpOverScroller: NoOpOverScroller
- @Mock private lateinit var splitShadeOverScroller: SplitShadeOverScroller
@Mock private lateinit var scrimShadeTransitionController: ScrimShadeTransitionController
@Mock private lateinit var dumpManager: DumpManager
@Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
@@ -52,119 +39,19 @@ class ShadeTransitionControllerTest : SysuiTestCase() {
shadeExpansionStateManager,
dumpManager,
context,
- splitShadeOverScrollerFactory = { _, _ -> splitShadeOverScroller },
- noOpOverScroller,
scrimShadeTransitionController,
statusBarStateController,
)
-
- // Resetting as they are notified upon initialization.
- reset(noOpOverScroller, splitShadeOverScroller)
- }
-
- @Test
- fun onPanelExpansionChanged_inSplitShade_forwardsToSplitShadeOverScroller() {
- initLateProperties()
- enableSplitShade()
-
- startPanelExpansion()
-
- verify(splitShadeOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(splitShadeOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(noOpOverScroller)
- }
-
- @Test
- fun onPanelStateChanged_inSplitShade_propertiesNotInitialized_forwardsToNoOpOverScroller() {
- enableSplitShade()
-
- startPanelExpansion()
-
- verify(noOpOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(noOpOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(splitShadeOverScroller)
- }
-
- @Test
- fun onPanelStateChanged_inSplitShade_onKeyguard_forwardsToNoOpOverScroller() {
- initLateProperties()
- enableSplitShade()
- setOnKeyguard()
-
- startPanelExpansion()
-
- verify(noOpOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(noOpOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(splitShadeOverScroller)
- }
-
- @Test
- fun onPanelStateChanged_inSplitShade_onLockedShade_forwardsToNoOpOverScroller() {
- initLateProperties()
- enableSplitShade()
- setOnLockedShade()
-
- startPanelExpansion()
-
- verify(noOpOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(noOpOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(splitShadeOverScroller)
- }
-
- @Test
- fun onPanelExpansionChanged_inSplitShade_onUnlockedShade_forwardsToSplitShadeOverScroller() {
- initLateProperties()
- enableSplitShade()
- setOnUnlockedShade()
-
- startPanelExpansion()
-
- verify(splitShadeOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(splitShadeOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(noOpOverScroller)
- }
-
- @Test
- fun onPanelStateChanged_notInSplitShade_forwardsToNoOpOverScroller() {
- initLateProperties()
- disableSplitShade()
-
- startPanelExpansion()
-
- verify(noOpOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(noOpOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(splitShadeOverScroller)
}
@Test
fun onPanelStateChanged_forwardsToScrimTransitionController() {
- initLateProperties()
-
startPanelExpansion()
verify(scrimShadeTransitionController).onPanelStateChanged(STATE_OPENING)
verify(scrimShadeTransitionController).onPanelExpansionChanged(DEFAULT_EXPANSION_EVENT)
}
- private fun initLateProperties() {
- controller.qs = qs
- controller.notificationStackScrollLayoutController = nsslController
- controller.notificationPanelViewController = npvc
- }
-
- private fun disableSplitShade() {
- setSplitShadeEnabled(false)
- }
-
- private fun enableSplitShade() {
- setSplitShadeEnabled(true)
- }
-
- private fun setSplitShadeEnabled(enabled: Boolean) {
- overrideResource(R.bool.config_use_split_notification_shade, enabled)
- configurationController.notifyConfigurationChanged()
- }
-
private fun startPanelExpansion() {
shadeExpansionStateManager.onPanelExpansionChanged(
DEFAULT_EXPANSION_EVENT.fraction,
@@ -174,23 +61,6 @@ class ShadeTransitionControllerTest : SysuiTestCase() {
)
}
- private fun setOnKeyguard() {
- setShadeState(StatusBarState.KEYGUARD)
- }
-
- private fun setOnLockedShade() {
- setShadeState(StatusBarState.SHADE_LOCKED)
- }
-
- private fun setOnUnlockedShade() {
- setShadeState(StatusBarState.SHADE)
- }
-
- private fun setShadeState(state: Int) {
- whenever(statusBarStateController.state).thenReturn(state)
- whenever(statusBarStateController.currentOrUpcomingState).thenReturn(state)
- }
-
companion object {
private const val DEFAULT_DRAG_DOWN_AMOUNT = 123f
private val DEFAULT_EXPANSION_EVENT =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt
deleted file mode 100644
index 0e48b4835dfe..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-package com.android.systemui.shade.transition
-
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import androidx.test.filters.SmallTest
-import com.android.systemui.R
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.plugins.qs.QS
-import com.android.systemui.shade.STATE_CLOSED
-import com.android.systemui.shade.STATE_OPEN
-import com.android.systemui.shade.STATE_OPENING
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
-import com.android.systemui.statusbar.phone.ScrimController
-import com.android.systemui.statusbar.policy.FakeConfigurationController
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.atLeastOnce
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.Mockito.`when` as whenever
-import org.mockito.MockitoAnnotations
-
-@RunWith(AndroidTestingRunner::class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-@SmallTest
-class SplitShadeOverScrollerTest : SysuiTestCase() {
-
- @Mock private lateinit var dumpManager: DumpManager
- @Mock private lateinit var scrimController: ScrimController
- @Mock private lateinit var qs: QS
- @Mock private lateinit var nsslController: NotificationStackScrollLayoutController
-
- private val configurationController = FakeConfigurationController()
- private lateinit var overScroller: SplitShadeOverScroller
-
- @Before
- fun setUp() {
- MockitoAnnotations.initMocks(this)
-
- whenever(nsslController.height).thenReturn(1000)
- overScroller =
- SplitShadeOverScroller(
- configurationController,
- dumpManager,
- context,
- scrimController,
- { qs },
- { nsslController })
- }
-
- @Test
- fun onDragDownAmountChanged_panelOpening_overScrolls_basedOnHeightAndMaxAmount() {
- val maxOverScrollAmount = 50
- val dragDownAmount = 100f
- overrideResource(R.dimen.shade_max_over_scroll_amount, maxOverScrollAmount)
- configurationController.notifyConfigurationChanged()
-
- overScroller.onPanelStateChanged(STATE_OPENING)
- overScroller.onDragDownAmountChanged(dragDownAmount)
-
- val expectedOverScrollAmount =
- (dragDownAmount / nsslController.height * maxOverScrollAmount).toInt()
- verify(qs).setOverScrollAmount(expectedOverScrollAmount)
- verify(nsslController).setOverScrollAmount(expectedOverScrollAmount)
- verify(scrimController).setNotificationsOverScrollAmount(expectedOverScrollAmount)
- }
-
- @Test
- fun onDragDownAmountChanged_panelClosed_doesNotOverScroll() {
- overScroller.onPanelStateChanged(STATE_CLOSED)
- overScroller.onDragDownAmountChanged(100f)
-
- verifyZeroInteractions(qs, scrimController, nsslController)
- }
-
- @Test
- fun onDragDownAmountChanged_panelOpen_doesNotOverScroll() {
- overScroller.onPanelStateChanged(STATE_OPEN)
- overScroller.onDragDownAmountChanged(100f)
-
- verifyZeroInteractions(qs, scrimController, nsslController)
- }
-
- @Test
- fun onPanelStateChanged_opening_thenOpen_releasesOverScroll() {
- overScroller.onPanelStateChanged(STATE_OPENING)
- overScroller.onDragDownAmountChanged(100f)
-
- overScroller.onPanelStateChanged(STATE_OPEN)
- overScroller.finishAnimations()
-
- verify(qs, atLeastOnce()).setOverScrollAmount(0)
- verify(scrimController, atLeastOnce()).setNotificationsOverScrollAmount(0)
- verify(nsslController, atLeastOnce()).setOverScrollAmount(0)
- }
-
- @Test
- fun onPanelStateChanged_opening_thenClosed_releasesOverScroll() {
- overScroller.onPanelStateChanged(STATE_OPENING)
- overScroller.onDragDownAmountChanged(100f)
-
- overScroller.onPanelStateChanged(STATE_CLOSED)
- overScroller.finishAnimations()
-
- verify(qs, atLeastOnce()).setOverScrollAmount(0)
- verify(scrimController, atLeastOnce()).setNotificationsOverScrollAmount(0)
- verify(nsslController, atLeastOnce()).setOverScrollAmount(0)
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index d8446f4721b3..1aad83eb73ae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -38,6 +38,8 @@ import android.testing.TestableLooper;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
+import android.view.WindowInsets;
+import android.view.WindowInsetsController;
import android.window.BackEvent;
import android.window.OnBackAnimationCallback;
import android.window.OnBackInvokedCallback;
@@ -65,8 +67,10 @@ import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInt
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.navigationbar.TaskbarDelegate;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.shade.NotificationPanelViewController;
+import com.android.systemui.shade.NotificationShadeWindowView;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.shade.ShadeExpansionStateManager;
@@ -123,6 +127,9 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
@Mock private BouncerView mBouncerView;
@Mock private BouncerViewDelegate mBouncerViewDelegate;
@Mock private OnBackAnimationCallback mBouncerViewDelegateBackCallback;
+ @Mock private NotificationShadeWindowView mNotificationShadeWindowView;
+ @Mock private WindowInsetsController mWindowInsetsController;
+ @Mock private TaskbarDelegate mTaskbarDelegate;
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback
@@ -151,6 +158,11 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_BOUNCER_ANIM))
.thenReturn(true);
+ when(mCentralSurfaces.getNotificationShadeWindowView())
+ .thenReturn(mNotificationShadeWindowView);
+ when(mNotificationShadeWindowView.getWindowInsetsController())
+ .thenReturn(mWindowInsetsController);
+
mStatusBarKeyguardViewManager =
new StatusBarKeyguardViewManager(
getContext(),
@@ -640,6 +652,14 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
}
@Test
+ public void testHideTaskbar() {
+ when(mTaskbarDelegate.isInitialized()).thenReturn(true);
+ mStatusBarKeyguardViewManager.setTaskbarDelegate(mTaskbarDelegate);
+ mStatusBarKeyguardViewManager.updateNavigationBarVisibility(false);
+ verify(mWindowInsetsController).hide(WindowInsets.Type.navigationBars());
+ }
+
+ @Test
public void hideAlternateBouncer_beforeCentralSurfacesRegistered() {
mStatusBarKeyguardViewManager =
new StatusBarKeyguardViewManager(
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
index 337421974562..9cdce20bbf1e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
@@ -21,6 +21,7 @@ import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.E
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
/** Fake implementation of [KeyguardRepository] */
@@ -44,8 +45,6 @@ class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
override val panelExpansionAmount = _panelExpansionAmount.asStateFlow()
private val _keyguardPosition = MutableStateFlow(0f)
override val keyguardPosition = _keyguardPosition.asStateFlow()
- private val _onScreenTurnedOff = MutableStateFlow(false)
- override val onScreenTurnedOff = _onScreenTurnedOff.asStateFlow()
private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null)
override val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow()
private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null)
@@ -61,6 +60,8 @@ class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
override var lastAlternateBouncerVisibleTime: Long = 0L
private val _isAlternateBouncerUIAvailable = MutableStateFlow<Boolean>(false)
override val alternateBouncerUIAvailable = _isAlternateBouncerUIAvailable.asStateFlow()
+ private val _sideFpsShowing: MutableStateFlow<Boolean> = MutableStateFlow(false)
+ override val sideFpsShowing: StateFlow<Boolean> = _sideFpsShowing.asStateFlow()
override fun setPrimaryScrimmed(isScrimmed: Boolean) {
_primaryBouncerScrimmed.value = isScrimmed
@@ -122,7 +123,7 @@ class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
_isBackButtonEnabled.value = isBackButtonEnabled
}
- override fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) {
- _onScreenTurnedOff.value = onScreenTurnedOff
+ override fun setSideFpsShowing(isShowing: Boolean) {
+ _sideFpsShowing.value = isShowing
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
index e6abc4c90fac..eba92305dd7b 100644
--- a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
+++ b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
@@ -335,7 +335,7 @@ public class SystemActionPerformer {
KeyEvent event = KeyEvent.obtain(downTime, time, action, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
InputDevice.SOURCE_KEYBOARD, null);
- InputManager.getInstance()
+ mContext.getSystemService(InputManager.class)
.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
event.recycle();
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 08ee6d76f284..61fc32d5fa15 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -169,6 +169,7 @@ public final class ContentCaptureManagerService extends
@GuardedBy("mLock") int mDevCfgTextChangeFlushingFrequencyMs;
@GuardedBy("mLock") int mDevCfgLogHistorySize;
@GuardedBy("mLock") int mDevCfgIdleUnbindTimeoutMs;
+ @GuardedBy("mLock") boolean mDevCfgDisableFlushForViewTreeAppearing;
private final Executor mDataShareExecutor = Executors.newCachedThreadPool();
private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -359,6 +360,8 @@ public final class ContentCaptureManagerService extends
case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE:
case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY:
case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT:
+ case ContentCaptureManager
+ .DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING:
setFineTuneParamsFromDeviceConfig();
return;
default:
@@ -388,13 +391,20 @@ public final class ContentCaptureManagerService extends
DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT,
(int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS);
+ mDevCfgDisableFlushForViewTreeAppearing = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+ ContentCaptureManager
+ .DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
+ false);
if (verbose) {
Slog.v(TAG, "setFineTuneParamsFromDeviceConfig(): "
+ "bufferSize=" + mDevCfgMaxBufferSize
+ ", idleFlush=" + mDevCfgIdleFlushingFrequencyMs
+ ", textFluxh=" + mDevCfgTextChangeFlushingFrequencyMs
+ ", logHistory=" + mDevCfgLogHistorySize
- + ", idleUnbindTimeoutMs=" + mDevCfgIdleUnbindTimeoutMs);
+ + ", idleUnbindTimeoutMs=" + mDevCfgIdleUnbindTimeoutMs
+ + ", disableFlushForViewTreeAppearing="
+ + mDevCfgDisableFlushForViewTreeAppearing);
}
}
}
@@ -629,6 +639,7 @@ public final class ContentCaptureManagerService extends
}
@Override // from AbstractMasterSystemService
+ @GuardedBy("mLock")
protected void dumpLocked(String prefix, PrintWriter pw) {
super.dumpLocked(prefix, pw);
@@ -646,6 +657,8 @@ public final class ContentCaptureManagerService extends
pw.print(prefix2); pw.print("logHistorySize: "); pw.println(mDevCfgLogHistorySize);
pw.print(prefix2); pw.print("idleUnbindTimeoutMs: ");
pw.println(mDevCfgIdleUnbindTimeoutMs);
+ pw.print(prefix2); pw.print("disableFlushForViewTreeAppearing: ");
+ pw.println(mDevCfgDisableFlushForViewTreeAppearing);
pw.print(prefix); pw.println("Global Options:");
mGlobalContentCaptureOptions.dump(prefix2, pw);
}
@@ -1005,12 +1018,15 @@ public final class ContentCaptureManagerService extends
return null;
}
- final ContentCaptureOptions options = new ContentCaptureOptions(mDevCfgLoggingLevel,
- mDevCfgMaxBufferSize, mDevCfgIdleFlushingFrequencyMs,
- mDevCfgTextChangeFlushingFrequencyMs, mDevCfgLogHistorySize,
- whitelistedComponents);
- if (verbose) Slog.v(TAG, "getOptionsForPackage(" + packageName + "): " + options);
- return options;
+ synchronized (mLock) {
+ final ContentCaptureOptions options = new ContentCaptureOptions(mDevCfgLoggingLevel,
+ mDevCfgMaxBufferSize, mDevCfgIdleFlushingFrequencyMs,
+ mDevCfgTextChangeFlushingFrequencyMs, mDevCfgLogHistorySize,
+ mDevCfgDisableFlushForViewTreeAppearing,
+ whitelistedComponents);
+ if (verbose) Slog.v(TAG, "getOptionsForPackage(" + packageName + "): " + options);
+ return options;
+ }
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index 57d28f95eb6a..dce88da6f111 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -75,7 +75,6 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
private final LockoutTracker mLockoutTracker;
private final boolean mIsRestricted;
private final boolean mAllowBackgroundAuthentication;
- private final boolean mIsKeyguardBypassEnabled;
// TODO: This is currently hard to maintain, as each AuthenticationClient subclass must update
// the state. We should think of a way to improve this in the future.
@State
@@ -95,7 +94,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
@NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext,
boolean isStrongBiometric, @Nullable TaskStackListener taskStackListener,
@NonNull LockoutTracker lockoutTracker, boolean allowBackgroundAuthentication,
- boolean shouldVibrate, boolean isKeyguardBypassEnabled, int sensorStrength) {
+ boolean shouldVibrate, int sensorStrength) {
super(context, lazyDaemon, token, listener, targetUserId, owner, cookie, sensorId,
shouldVibrate, biometricLogger, biometricContext);
mIsStrongBiometric = isStrongBiometric;
@@ -107,7 +106,6 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
mLockoutTracker = lockoutTracker;
mIsRestricted = restricted;
mAllowBackgroundAuthentication = allowBackgroundAuthentication;
- mIsKeyguardBypassEnabled = isKeyguardBypassEnabled;
mShouldUseLockoutTracker = lockoutTracker != null;
mSensorStrength = sensorStrength;
}
@@ -374,14 +372,6 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
return mState;
}
- /**
- * @return true if the client supports bypass (e.g. passive auth such as face), and if it's
- * enabled by the user.
- */
- public boolean isKeyguardBypassEnabled() {
- return mIsKeyguardBypassEnabled;
- }
-
@Override
public int getProtoEnum() {
return BiometricsProto.CM_AUTHENTICATE;
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
index b2fd46d1475d..51829684f3ab 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
@@ -23,6 +23,7 @@ import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.biometrics.SensorPropertiesInternal;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.IFaceService;
import android.os.IBinder;
import android.os.RemoteException;
@@ -64,8 +65,11 @@ public final class FaceAuthenticator extends IBiometricAuthenticator.Stub {
String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication)
throws RemoteException {
mFaceService.prepareForAuthentication(mSensorId, requireConfirmation, token, operationId,
- userId, sensorReceiver, opPackageName, requestId, cookie,
- allowBackgroundAuthentication);
+ sensorReceiver, new FaceAuthenticateOptions.Builder()
+ .setUserId(userId)
+ .setOpPackageName(opPackageName)
+ .build(),
+ requestId, cookie, allowBackgroundAuthentication);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
index 0248010bc9f3..1ee9f53c5774 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
@@ -35,6 +35,7 @@ import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.SensorProps;
import android.hardware.face.Face;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.FaceServiceReceiver;
import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
@@ -238,14 +239,15 @@ public class FaceService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
- public long authenticate(final IBinder token, final long operationId, int userId,
- final IFaceServiceReceiver receiver, final String opPackageName,
- boolean isKeyguardBypassEnabled) {
+ public long authenticate(final IBinder token, final long operationId,
+ final IFaceServiceReceiver receiver, final FaceAuthenticateOptions options) {
// TODO(b/152413782): If the sensor supports face detect and the device is encrypted or
// lockdown, something wrong happened. See similar path in FingerprintService.
super.authenticate_enforcePermission();
+ final int userId = options.getUserId();
+ final String opPackageName = options.getOpPackageName();
final boolean restricted = false; // Face APIs are private
final int statsClient = Utils.isKeyguard(getContext(), opPackageName)
? BiometricsProtoEnums.CLIENT_KEYGUARD
@@ -261,18 +263,18 @@ public class FaceService extends SystemService {
return -1;
}
- return provider.second.scheduleAuthenticate(provider.first, token, operationId, userId,
- 0 /* cookie */,
- new ClientMonitorCallbackConverter(receiver), opPackageName, restricted,
- statsClient, isKeyguard, isKeyguardBypassEnabled);
+ return provider.second.scheduleAuthenticate(provider.first, token, operationId,
+ 0 /* cookie */, new ClientMonitorCallbackConverter(receiver), options,
+ restricted, statsClient, isKeyguard);
}
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
- public long detectFace(final IBinder token, final int userId,
- final IFaceServiceReceiver receiver, final String opPackageName) {
+ public long detectFace(final IBinder token,
+ final IFaceServiceReceiver receiver, final FaceAuthenticateOptions options) {
super.detectFace_enforcePermission();
+ final String opPackageName = options.getOpPackageName();
if (!Utils.isKeyguard(getContext(), opPackageName)) {
Slog.w(TAG, "detectFace called from non-sysui package: " + opPackageName);
return -1;
@@ -284,7 +286,7 @@ public class FaceService extends SystemService {
return -1;
}
- return provider.second.scheduleFaceDetect(provider.first, token, userId,
+ return provider.second.scheduleFaceDetect(provider.first, token, options.getUserId(),
new ClientMonitorCallbackConverter(receiver), opPackageName,
BiometricsProtoEnums.CLIENT_KEYGUARD);
}
@@ -292,9 +294,9 @@ public class FaceService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
public void prepareForAuthentication(int sensorId, boolean requireConfirmation,
- IBinder token, long operationId, int userId,
- IBiometricSensorReceiver sensorReceiver, String opPackageName, long requestId,
- int cookie, boolean allowBackgroundAuthentication) {
+ IBinder token, long operationId, IBiometricSensorReceiver sensorReceiver,
+ FaceAuthenticateOptions options, long requestId, int cookie,
+ boolean allowBackgroundAuthentication) {
super.prepareForAuthentication_enforcePermission();
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
@@ -305,10 +307,10 @@ public class FaceService extends SystemService {
final boolean isKeyguardBypassEnabled = false; // only valid for keyguard clients
final boolean restricted = true; // BiometricPrompt is always restricted
- provider.scheduleAuthenticate(sensorId, token, operationId, userId, cookie,
- new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, requestId,
+ provider.scheduleAuthenticate(sensorId, token, operationId, cookie,
+ new ClientMonitorCallbackConverter(sensorReceiver), options, requestId,
restricted, BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
- allowBackgroundAuthentication, isKeyguardBypassEnabled);
+ allowBackgroundAuthentication);
}
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
index 85f95cec8377..609c6a77e50a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
@@ -22,6 +22,7 @@ import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.face.Face;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.IFaceServiceReceiver;
@@ -88,15 +89,15 @@ public interface ServiceProvider extends BiometricServiceProvider<FaceSensorProp
void cancelFaceDetect(int sensorId, @NonNull IBinder token, long requestId);
- long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
+ long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled);
+ @NonNull FaceAuthenticateOptions options,
+ boolean restricted, int statsClient, boolean allowBackgroundAuthentication);
- void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
+ void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled);
+ @NonNull FaceAuthenticateOptions options, long requestId,
+ boolean restricted, int statsClient, boolean allowBackgroundAuthentication);
void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index d8b825d2c0e5..29dd707a7c1d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -85,11 +85,11 @@ class FaceAuthenticationClient extends AuthenticationClient<AidlSession>
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
boolean isStrongBiometric, @NonNull UsageStats usageStats,
@NonNull LockoutCache lockoutCache, boolean allowBackgroundAuthentication,
- boolean isKeyguardBypassEnabled, @Authenticators.Types int sensorStrength) {
+ @Authenticators.Types int sensorStrength) {
this(context, lazyDaemon, token, requestId, listener, targetUserId, operationId,
restricted, owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
isStrongBiometric, usageStats, lockoutCache /* lockoutCache */,
- allowBackgroundAuthentication, isKeyguardBypassEnabled,
+ allowBackgroundAuthentication,
context.getSystemService(SensorPrivacyManager.class), sensorStrength);
}
@@ -102,13 +102,13 @@ class FaceAuthenticationClient extends AuthenticationClient<AidlSession>
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
boolean isStrongBiometric, @NonNull UsageStats usageStats,
@NonNull LockoutCache lockoutCache, boolean allowBackgroundAuthentication,
- boolean isKeyguardBypassEnabled, SensorPrivacyManager sensorPrivacyManager,
+ SensorPrivacyManager sensorPrivacyManager,
@Authenticators.Types int biometricStrength) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
isStrongBiometric, null /* taskStackListener */, null /* lockoutCache */,
allowBackgroundAuthentication, false /* shouldVibrate */,
- isKeyguardBypassEnabled, biometricStrength);
+ biometricStrength);
setRequestId(requestId);
mUsageStats = usageStats;
mNotificationManager = context.getSystemService(NotificationManager.class);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index 89852a14ba9b..41e02691ddf8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -32,6 +32,7 @@ import android.hardware.biometrics.common.ComponentInfo;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.SensorProps;
import android.hardware.face.Face;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.IFaceServiceReceiver;
import android.os.Binder;
@@ -435,21 +436,21 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@Override
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
- int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) {
+ int cookie, @NonNull ClientMonitorCallbackConverter callback,
+ @NonNull FaceAuthenticateOptions options,
+ long requestId, boolean restricted, int statsClient,
+ boolean allowBackgroundAuthentication) {
mHandler.post(() -> {
+ final int userId = options.getUserId();
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
final FaceAuthenticationClient client = new FaceAuthenticationClient(
mContext, mSensors.get(sensorId).getLazySession(), token, requestId, callback,
- userId, operationId, restricted, opPackageName, cookie,
+ userId, operationId, restricted, options.getOpPackageName(), cookie,
false /* requireConfirmation */, sensorId,
createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
mBiometricContext, isStrongBiometric,
mUsageStats, mSensors.get(sensorId).getLockoutCache(),
- allowBackgroundAuthentication, isKeyguardBypassEnabled,
- Utils.getCurrentStrength(sensorId)
- );
+ allowBackgroundAuthentication, Utils.getCurrentStrength(sensorId));
scheduleForSensor(sensorId, client, new ClientMonitorCallback() {
@Override
public void onClientStarted(
@@ -470,14 +471,13 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@Override
public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
- int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) {
+ int cookie, @NonNull ClientMonitorCallbackConverter callback,
+ @NonNull FaceAuthenticateOptions options, boolean restricted, int statsClient,
+ boolean allowBackgroundAuthentication) {
final long id = mRequestCounter.incrementAndGet();
- scheduleAuthenticate(sensorId, token, operationId, userId, cookie, callback,
- opPackageName, id, restricted, statsClient,
- allowBackgroundAuthentication, isKeyguardBypassEnabled);
+ scheduleAuthenticate(sensorId, token, operationId, cookie, callback,
+ options, id, restricted, statsClient, allowBackgroundAuthentication);
return id;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index 1adc5e3e74b5..7e575bc23f9c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -31,6 +31,7 @@ import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback;
import android.hardware.face.Face;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.IFaceServiceReceiver;
import android.os.Binder;
@@ -665,19 +666,20 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
@Override
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
- int userId, int cookie, @NonNull ClientMonitorCallbackConverter receiver,
- @NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) {
+ int cookie, @NonNull ClientMonitorCallbackConverter receiver,
+ @NonNull FaceAuthenticateOptions options, long requestId, boolean restricted,
+ int statsClient, boolean allowBackgroundAuthentication) {
mHandler.post(() -> {
+ final int userId = options.getUserId();
scheduleUpdateActiveUserWithoutHandler(userId);
final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorId);
final FaceAuthenticationClient client = new FaceAuthenticationClient(mContext,
mLazyDaemon, token, requestId, receiver, userId, operationId, restricted,
- opPackageName, cookie, false /* requireConfirmation */, mSensorId,
+ options.getOpPackageName(), cookie, false /* requireConfirmation */, mSensorId,
createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
mBiometricContext, isStrongBiometric, mLockoutTracker,
- mUsageStats, allowBackgroundAuthentication, isKeyguardBypassEnabled,
+ mUsageStats, allowBackgroundAuthentication,
Utils.getCurrentStrength(mSensorId));
mScheduler.scheduleClientMonitor(client);
});
@@ -685,14 +687,13 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
@Override
public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
- int userId, int cookie, @NonNull ClientMonitorCallbackConverter receiver,
- @NonNull String opPackageName, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) {
+ int cookie, @NonNull ClientMonitorCallbackConverter receiver,
+ @NonNull FaceAuthenticateOptions options, boolean restricted, int statsClient,
+ boolean allowBackgroundAuthentication) {
final long id = mRequestCounter.incrementAndGet();
- scheduleAuthenticate(sensorId, token, operationId, userId, cookie, receiver,
- opPackageName, id, restricted, statsClient,
- allowBackgroundAuthentication, isKeyguardBypassEnabled);
+ scheduleAuthenticate(sensorId, token, operationId, cookie, receiver,
+ options, id, restricted, statsClient, allowBackgroundAuthentication);
return id;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index d4a7f085b8c5..1c1f56ccddd5 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -72,12 +72,12 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
boolean isStrongBiometric, @NonNull LockoutTracker lockoutTracker,
@NonNull UsageStats usageStats, boolean allowBackgroundAuthentication,
- boolean isKeyguardBypassEnabled, @Authenticators.Types int sensorStrength) {
+ @Authenticators.Types int sensorStrength) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
isStrongBiometric, null /* taskStackListener */,
lockoutTracker, allowBackgroundAuthentication, false /* shouldVibrate */,
- isKeyguardBypassEnabled, sensorStrength);
+ sensorStrength);
setRequestId(requestId);
mUsageStats = usageStats;
mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index 1c57151ed7bd..affc496edc70 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -45,6 +45,7 @@ import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.biometrics.fingerprint.IFingerprint;
import android.hardware.biometrics.fingerprint.PointerContext;
import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.FingerprintServiceReceiver;
@@ -252,15 +253,15 @@ public class FingerprintService extends SystemService {
public long authenticate(
final IBinder token,
final long operationId,
- final int sensorId,
- final int userId,
final IFingerprintServiceReceiver receiver,
- final String opPackageName,
- final String attributionTag,
- boolean ignoreEnrollmentState) {
+ final FingerprintAuthenticateOptions options) {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
final int callingUserId = UserHandle.getCallingUserId();
+ final String opPackageName = options.getOpPackageName();
+ final String attributionTag = options.getAttributionTag();
+ final int userId = options.getUserId();
+ final int sensorId = options.getSensorId();
if (!canUseFingerprint(
opPackageName,
@@ -314,7 +315,8 @@ public class FingerprintService extends SystemService {
&& sensorProps != null && sensorProps.isAnyUdfpsType()) {
try {
return authenticateWithPrompt(operationId, sensorProps, callingUid,
- callingUserId, receiver, opPackageName, ignoreEnrollmentState);
+ callingUserId, receiver, opPackageName,
+ options.isIgnoreEnrollmentState());
} catch (PackageManager.NameNotFoundException e) {
Slog.e(TAG, "Invalid package", e);
return -1;
@@ -412,16 +414,18 @@ public class FingerprintService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override
- public long detectFingerprint(final IBinder token, final int userId,
- final IFingerprintServiceReceiver receiver, final String opPackageName) {
+ public long detectFingerprint(final IBinder token,
+ final IFingerprintServiceReceiver receiver,
+ final FingerprintAuthenticateOptions options) {
super.detectFingerprint_enforcePermission();
+ final String opPackageName = options.getOpPackageName();
if (!Utils.isKeyguard(getContext(), opPackageName)) {
Slog.w(TAG, "detectFingerprint called from non-sysui package: " + opPackageName);
return -1;
}
- if (!Utils.isUserEncryptedOrLockdown(mLockPatternUtils, userId)) {
+ if (!Utils.isUserEncryptedOrLockdown(mLockPatternUtils, options.getUserId())) {
// If this happens, something in KeyguardUpdateMonitor is wrong. This should only
// ever be invoked when the user is encrypted or lockdown.
Slog.e(TAG, "detectFingerprint invoked when user is not encrypted or lockdown");
@@ -434,7 +438,7 @@ public class FingerprintService extends SystemService {
return -1;
}
- return provider.second.scheduleFingerDetect(provider.first, token, userId,
+ return provider.second.scheduleFingerDetect(provider.first, token, options.getUserId(),
new ClientMonitorCallbackConverter(receiver), opPackageName,
BiometricsProtoEnums.CLIENT_KEYGUARD);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index a90679e755cf..d1a7b1339179 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -136,7 +136,6 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
null /* lockoutCache */,
allowBackgroundAuthentication,
false /* shouldVibrate */,
- false /* isKeyguardBypassEnabled */,
biometricStrength);
setRequestId(requestId);
mSensorOverlays = new SensorOverlays(udfpsOverlayController,
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
index a9cc897a2937..957005a9223e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
@@ -87,8 +87,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
isStrongBiometric, taskStackListener, lockoutTracker, allowBackgroundAuthentication,
- false /* shouldVibrate */, false /* isKeyguardBypassEnabled */,
- sensorStrength);
+ false /* shouldVibrate */, sensorStrength);
setRequestId(requestId);
mLockoutFrameworkImpl = lockoutTracker;
mSensorOverlays = new SensorOverlays(udfpsOverlayController,
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 5d31e40ad9d3..ab2c002c2b24 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -258,7 +258,8 @@ public class Vpn {
public static final int AUTOMATIC_KEEPALIVE_DELAY_SECONDS = 30;
// Default keepalive timeout for carrier config is 5 minutes. Mimic this.
- private static final int DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT = 5 * 60;
+ @VisibleForTesting
+ static final int DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT = 5 * 60;
// TODO: create separate trackers for each unique VPN to support
// automated reconnection
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 81e550e3d62f..6eb465e1049e 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -24,6 +24,7 @@ import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
import static android.hardware.display.DisplayManager.EventsMask;
+import static android.hardware.display.DisplayManager.HDR_OUTPUT_CONTROL_FLAG;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
@@ -38,8 +39,10 @@ import static android.hardware.display.DisplayManagerGlobal.DisplayEvent;
import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL;
import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL;
import static android.hardware.display.DisplayViewport.VIEWPORT_VIRTUAL;
+import static android.hardware.display.HdrConversionMode.HDR_CONVERSION_UNSUPPORTED;
import static android.os.Process.FIRST_APPLICATION_UID;
import static android.os.Process.ROOT_UID;
+import static android.provider.DeviceConfig.NAMESPACE_DISPLAY_MANAGER;
import android.Manifest;
import android.annotation.NonNull;
@@ -137,6 +140,7 @@ import android.window.ScreenCapture;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
+import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
@@ -232,6 +236,9 @@ public final class DisplayManagerService extends SystemService {
private static final int MSG_LOAD_BRIGHTNESS_CONFIGURATIONS = 6;
private static final int MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE = 7;
private static final int MSG_DELIVER_DISPLAY_GROUP_EVENT = 8;
+ private static final int[] EMPTY_ARRAY = new int[0];
+ private static final HdrConversionMode HDR_CONVERSION_MODE_UNSUPPORTED = new HdrConversionMode(
+ HDR_CONVERSION_UNSUPPORTED);
private final Context mContext;
private final DisplayManagerHandler mHandler;
@@ -250,6 +257,10 @@ public final class DisplayManagerService extends SystemService {
@GuardedBy("mSyncRoot")
private boolean mAreUserDisabledHdrTypesAllowed = true;
+ // This value indicates whether or not HDR output control is enabled.
+ // It is read from DeviceConfig and is updated via a listener if the config changes.
+ private volatile boolean mIsHdrOutputControlEnabled;
+
// Display mode chosen by user.
private Display.Mode mUserPreferredMode;
// HDR conversion mode chosen by user
@@ -674,6 +685,11 @@ public final class DisplayManagerService extends SystemService {
synchronized (mSyncRoot) {
mSafeMode = safeMode;
mSystemReady = true;
+ mIsHdrOutputControlEnabled = isDeviceConfigHdrOutputControlEnabled();
+ DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_DISPLAY_MANAGER,
+ BackgroundThread.getExecutor(),
+ properties -> mIsHdrOutputControlEnabled =
+ isDeviceConfigHdrOutputControlEnabled());
// Just in case the top inset changed before the system was ready. At this point, any
// relevant configuration should be in place.
recordTopInsetLocked(mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY));
@@ -681,7 +697,9 @@ public final class DisplayManagerService extends SystemService {
updateSettingsLocked();
updateUserDisabledHdrTypesFromSettingsLocked();
updateUserPreferredDisplayModeSettingsLocked();
- updateHdrConversionModeSettingsLocked();
+ if (mIsHdrOutputControlEnabled) {
+ updateHdrConversionModeSettingsLocked();
+ }
}
mDisplayModeDirector.setDesiredDisplayModeSpecsListener(
@@ -702,6 +720,12 @@ public final class DisplayManagerService extends SystemService {
mContext.registerReceiver(mIdleModeReceiver, filter);
}
+ private boolean isDeviceConfigHdrOutputControlEnabled() {
+ return DeviceConfig.getBoolean(NAMESPACE_DISPLAY_MANAGER,
+ HDR_OUTPUT_CONTROL_FLAG,
+ true);
+ }
+
@VisibleForTesting
Handler getDisplayHandler() {
return mHandler;
@@ -2117,7 +2141,7 @@ public final class DisplayManagerService extends SystemService {
private HdrConversionMode getHdrConversionModeSettingInternal() {
if (!mInjector.getHdrOutputConversionSupport()) {
- return new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_UNSUPPORTED);
+ return HDR_CONVERSION_MODE_UNSUPPORTED;
}
synchronized (mSyncRoot) {
if (mHdrConversionMode != null) {
@@ -2129,7 +2153,7 @@ public final class DisplayManagerService extends SystemService {
private HdrConversionMode getHdrConversionModeInternal() {
if (!mInjector.getHdrOutputConversionSupport()) {
- return new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_UNSUPPORTED);
+ return HDR_CONVERSION_MODE_UNSUPPORTED;
}
HdrConversionMode mode;
synchronized (mSyncRoot) {
@@ -3948,6 +3972,9 @@ public final class DisplayManagerService extends SystemService {
@Override // Binder call
public void setHdrConversionMode(HdrConversionMode hdrConversionMode) {
+ if (!mIsHdrOutputControlEnabled) {
+ return;
+ }
mContext.enforceCallingOrSelfPermission(
Manifest.permission.MODIFY_HDR_CONVERSION_MODE,
"Permission required to set the HDR conversion mode.");
@@ -3961,6 +3988,9 @@ public final class DisplayManagerService extends SystemService {
@Override // Binder call
public HdrConversionMode getHdrConversionModeSetting() {
+ if (!mIsHdrOutputControlEnabled) {
+ return HDR_CONVERSION_MODE_UNSUPPORTED;
+ }
final long token = Binder.clearCallingIdentity();
try {
return getHdrConversionModeSettingInternal();
@@ -3971,6 +4001,9 @@ public final class DisplayManagerService extends SystemService {
@Override // Binder call
public HdrConversionMode getHdrConversionMode() {
+ if (!mIsHdrOutputControlEnabled) {
+ return HDR_CONVERSION_MODE_UNSUPPORTED;
+ }
final long token = Binder.clearCallingIdentity();
try {
return getHdrConversionModeInternal();
@@ -3982,6 +4015,9 @@ public final class DisplayManagerService extends SystemService {
@Display.HdrCapabilities.HdrType
@Override // Binder call
public int[] getSupportedHdrOutputTypes() {
+ if (!mIsHdrOutputControlEnabled) {
+ return EMPTY_ARRAY;
+ }
final long token = Binder.clearCallingIdentity();
try {
return getSupportedHdrOutputTypesInternal();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 38cddc4c0127..0d394570ab8e 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -229,7 +229,6 @@ import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.VibrationEffect;
-import android.permission.PermissionCheckerManager;
import android.permission.PermissionManager;
import android.provider.DeviceConfig;
import android.provider.Settings;
@@ -6774,7 +6773,7 @@ public class NotificationManagerService extends SystemService {
final int permissionResult = mPermissionManager.checkPermissionForDataDelivery(
Manifest.permission.USE_FULL_SCREEN_INTENT, source, /* message= */ null);
- if (permissionResult != PermissionCheckerManager.PERMISSION_GRANTED) {
+ if (permissionResult != PermissionManager.PERMISSION_GRANTED) {
makeStickyHun(notification);
}
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 69ea55969b03..c63cdddc8560 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -22,6 +22,7 @@ import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_MAX;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.util.StatsLog.ANNOTATION_ID_IS_UID;
@@ -905,6 +906,9 @@ public class PreferencesHelper implements RankingConfig {
Objects.requireNonNull(channel);
Objects.requireNonNull(channel.getId());
Preconditions.checkArgument(!TextUtils.isEmpty(channel.getName()));
+ Preconditions.checkArgument(channel.getImportance() >= IMPORTANCE_NONE
+ && channel.getImportance() <= IMPORTANCE_MAX, "Invalid importance level");
+
boolean needsPolicyFileChange = false, wasUndeleted = false, needsDndChange = false;
synchronized (mPackagePreferences) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
@@ -993,11 +997,6 @@ public class PreferencesHelper implements RankingConfig {
needsPolicyFileChange = true;
- if (channel.getImportance() < IMPORTANCE_NONE
- || channel.getImportance() > NotificationManager.IMPORTANCE_MAX) {
- throw new IllegalArgumentException("Invalid importance level");
- }
-
// Reset fields that apps aren't allowed to set.
if (fromTargetApp && !hasDndAccess) {
channel.setBypassDnd(r.priority == Notification.PRIORITY_MAX);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 96b37bf0b4cb..336ad75c5b2c 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -129,7 +129,6 @@ import android.media.AudioSystem;
import android.media.IAudioService;
import android.media.session.MediaSessionLegacyHelper;
import android.os.Binder;
-import android.os.Build;
import android.os.Bundle;
import android.os.DeviceIdleManager;
import android.os.FactoryTest;
@@ -203,6 +202,7 @@ import com.android.internal.policy.PhoneWindow;
import com.android.internal.policy.TransitionAnimation;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.widget.LockPatternUtils;
import com.android.server.AccessibilityManagerInternal;
import com.android.server.ExtconStateObserver;
import com.android.server.ExtconUEventObserver;
@@ -416,6 +416,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
AppOpsManager mAppOpsManager;
PackageManager mPackageManager;
SideFpsEventHandler mSideFpsEventHandler;
+ LockPatternUtils mLockPatternUtils;
private boolean mHasFeatureAuto;
private boolean mHasFeatureWatch;
private boolean mHasFeatureLeanback;
@@ -1074,8 +1075,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
synchronized (mLock) {
- // Lock the device after the dream transition has finished.
- mLockAfterAppTransitionFinished = true;
+ // If the setting to lock instantly on power button press is true, then set the flag to
+ // lock after the dream transition has finished.
+ mLockAfterAppTransitionFinished =
+ mLockPatternUtils.getPowerButtonInstantlyLocks(mCurrentUserId);
}
dreamManagerInternal.requestDream();
@@ -1993,6 +1996,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mAccessibilityShortcutController = injector.getAccessibilityShortcutController(
mContext, new Handler(), mCurrentUserId);
mGlobalActionsFactory = injector.getGlobalActionsFactory();
+ mLockPatternUtils = new LockPatternUtils(mContext);
mLogger = new MetricsLogger();
mScreenOffSleepTokenAcquirer = mActivityTaskManagerInternal
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 89b796836617..d21274a7b6ba 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -5225,7 +5225,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
Debug.getCallers(6));
// Before setting mVisibleRequested so we can track changes.
- mTransitionController.collect(this);
+ boolean isCollecting = false;
+ if (mTransitionController.isShellTransitionsEnabled()) {
+ isCollecting = mTransitionController.isCollecting();
+ if (isCollecting) {
+ mTransitionController.collect(this);
+ } else {
+ Slog.e(TAG, "setVisibility=" + visible + " while transition is not collecting "
+ + this + " caller=" + Debug.getCallers(8));
+ }
+ }
onChildVisibilityRequested(visible);
@@ -5297,9 +5306,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
// Defer committing visibility until transition starts.
- if (inTransition()) {
- if (!visible && mTransitionController.inPlayingTransition(this)
- && mTransitionController.isCollecting(this)) {
+ if (isCollecting) {
+ // It may be occluded by the activity above that calls convertFromTranslucent().
+ if (!visible && mTransitionController.inPlayingTransition(this)) {
mTransitionChangeFlags |= FLAG_IS_OCCLUDED;
}
return;
@@ -5319,11 +5328,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* Then its visibility will be committed until the transition is ready.
*/
private boolean deferCommitVisibilityChange(boolean visible) {
+ if (mTransitionController.isShellTransitionsEnabled()) {
+ // Shell transition doesn't use opening/closing sets.
+ return false;
+ }
if (!mDisplayContent.mAppTransition.isTransitionSet()) {
- if (mTransitionController.isShellTransitionsEnabled()) {
- // Shell transition doesn't use opening/closing sets.
- return false;
- }
// Defer committing visibility for non-home app which is animating by recents.
if (isActivityTypeHome() || !isAnimating(PARENTS, ANIMATION_TYPE_RECENTS)) {
return false;
@@ -7978,6 +7987,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
/**
+ * @return The {@code true} if the current instance has {@link mCompatDisplayInsets} without
+ * considering the inheritance implemented in {@link #getCompatDisplayInsets()}
+ */
+ boolean hasCompatDisplayInsetsWithoutInheritance() {
+ return mCompatDisplayInsets != null;
+ }
+
+ /**
* @return {@code true} if this activity is in size compatibility mode that uses the different
* density than its parent or its bounds don't fit in parent naturally.
*/
@@ -7985,7 +8002,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (mInSizeCompatModeForBounds) {
return true;
}
- if (mCompatDisplayInsets == null || !shouldCreateCompatDisplayInsets()
+ if (getCompatDisplayInsets() == null || !shouldCreateCompatDisplayInsets()
// The orientation is different from parent when transforming.
|| isFixedRotationTransforming()) {
return false;
@@ -8056,11 +8073,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
private void updateCompatDisplayInsets() {
- if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
- mCompatDisplayInsets = mLetterboxUiController.getInheritedCompatDisplayInsets();
- return;
- }
- if (mCompatDisplayInsets != null || !shouldCreateCompatDisplayInsets()) {
+ if (getCompatDisplayInsets() != null || !shouldCreateCompatDisplayInsets()) {
// The override configuration is set only once in size compatibility mode.
return;
}
@@ -8123,9 +8136,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@Override
float getCompatScale() {
- if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
- return mLetterboxUiController.getInheritedSizeCompatScale();
- }
return hasSizeCompatBounds() ? mSizeCompatScale : super.getCompatScale();
}
@@ -8172,7 +8182,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
resolveFixedOrientationConfiguration(newParentConfiguration);
}
- if (mCompatDisplayInsets != null) {
+ if (getCompatDisplayInsets() != null) {
resolveSizeCompatModeConfiguration(newParentConfiguration);
} else if (inMultiWindowMode() && !isFixedOrientationLetterboxAllowed) {
// We ignore activities' requested orientation in multi-window modes. They may be
@@ -8190,7 +8200,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
resolveAspectRatioRestriction(newParentConfiguration);
}
- if (isFixedOrientationLetterboxAllowed || mCompatDisplayInsets != null
+ if (isFixedOrientationLetterboxAllowed || getCompatDisplayInsets() != null
// In fullscreen, can be letterboxed for aspect ratio.
|| !inMultiWindowMode()) {
updateResolvedBoundsPosition(newParentConfiguration);
@@ -8198,7 +8208,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
boolean isIgnoreOrientationRequest = mDisplayContent != null
&& mDisplayContent.getIgnoreOrientationRequest();
- if (mCompatDisplayInsets == null // for size compat mode set in updateCompatDisplayInsets
+ if (getCompatDisplayInsets() == null
+ // for size compat mode set in updateCompatDisplayInsets
// Fixed orientation letterboxing is possible on both large screen devices
// with ignoreOrientationRequest enabled and on phones in split screen even with
// ignoreOrientationRequest disabled.
@@ -8244,7 +8255,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
info.neverSandboxDisplayApis(sConstrainDisplayApisConfig),
info.alwaysSandboxDisplayApis(sConstrainDisplayApisConfig),
!matchParentBounds(),
- mCompatDisplayInsets != null,
+ getCompatDisplayInsets() != null,
shouldCreateCompatDisplayInsets());
}
resolvedConfig.windowConfiguration.setMaxBounds(mTmpBounds);
@@ -8551,8 +8562,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|| orientationRespectedWithInsets)) {
return;
}
+ final CompatDisplayInsets compatDisplayInsets = getCompatDisplayInsets();
- if (mCompatDisplayInsets != null && !mCompatDisplayInsets.mIsInFixedOrientationLetterbox) {
+ if (compatDisplayInsets != null && !compatDisplayInsets.mIsInFixedOrientationLetterbox) {
// App prefers to keep its original size.
// If the size compat is from previous fixed orientation letterboxing, we may want to
// have fixed orientation letterbox again, otherwise it will show the size compat
@@ -8607,9 +8619,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mIsAspectRatioApplied = applyAspectRatio(resolvedBounds, containingBoundsWithInsets,
containingBounds, desiredAspectRatio);
- if (mCompatDisplayInsets != null) {
- mCompatDisplayInsets.getBoundsByRotation(
- mTmpBounds, newParentConfig.windowConfiguration.getRotation());
+ if (compatDisplayInsets != null) {
+ compatDisplayInsets.getBoundsByRotation(mTmpBounds,
+ newParentConfig.windowConfiguration.getRotation());
if (resolvedBounds.width() != mTmpBounds.width()
|| resolvedBounds.height() != mTmpBounds.height()) {
// The app shouldn't be resized, we only do fixed orientation letterboxing if the
@@ -8623,7 +8635,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Calculate app bounds using fixed orientation bounds because they will be needed later
// for comparison with size compat app bounds in {@link resolveSizeCompatModeConfiguration}.
getTaskFragment().computeConfigResourceOverrides(getResolvedOverrideConfiguration(),
- newParentConfig, mCompatDisplayInsets);
+ newParentConfig, compatDisplayInsets);
mLetterboxBoundsForFixedOrientationAndAspectRatio = new Rect(resolvedBounds);
}
@@ -8680,13 +8692,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
? requestedOrientation
// We should use the original orientation of the activity when possible to avoid
// forcing the activity in the opposite orientation.
- : mCompatDisplayInsets.mOriginalRequestedOrientation != ORIENTATION_UNDEFINED
- ? mCompatDisplayInsets.mOriginalRequestedOrientation
+ : getCompatDisplayInsets().mOriginalRequestedOrientation != ORIENTATION_UNDEFINED
+ ? getCompatDisplayInsets().mOriginalRequestedOrientation
: newParentConfiguration.orientation;
int rotation = newParentConfiguration.windowConfiguration.getRotation();
final boolean isFixedToUserRotation = mDisplayContent == null
|| mDisplayContent.getDisplayRotation().isFixedToUserRotation();
- if (!isFixedToUserRotation && !mCompatDisplayInsets.mIsFloating) {
+ if (!isFixedToUserRotation && !getCompatDisplayInsets().mIsFloating) {
// Use parent rotation because the original display can be rotated.
resolvedConfig.windowConfiguration.setRotation(rotation);
} else {
@@ -8702,11 +8714,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// rely on them to contain the original and unchanging width and height of the app.
final Rect containingAppBounds = new Rect();
final Rect containingBounds = mTmpBounds;
- mCompatDisplayInsets.getContainerBounds(containingAppBounds, containingBounds, rotation,
+ getCompatDisplayInsets().getContainerBounds(containingAppBounds, containingBounds, rotation,
orientation, orientationRequested, isFixedToUserRotation);
resolvedBounds.set(containingBounds);
// The size of floating task is fixed (only swap), so the aspect ratio is already correct.
- if (!mCompatDisplayInsets.mIsFloating) {
+ if (!getCompatDisplayInsets().mIsFloating) {
mIsAspectRatioApplied =
applyAspectRatio(resolvedBounds, containingAppBounds, containingBounds);
}
@@ -8715,7 +8727,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// are calculated in compat container space. The actual position on screen will be applied
// later, so the calculation is simpler that doesn't need to involve offset from parent.
getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
- mCompatDisplayInsets);
+ getCompatDisplayInsets());
// Use current screen layout as source because the size of app is independent to parent.
resolvedConfig.screenLayout = computeScreenLayout(
getConfiguration().screenLayout, resolvedConfig.screenWidthDp,
@@ -8750,14 +8762,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Calculates the scale the size compatibility bounds into the region which is available
// to application.
- final int contentW = resolvedAppBounds.width();
- final int contentH = resolvedAppBounds.height();
- final int viewportW = containerAppBounds.width();
- final int viewportH = containerAppBounds.height();
final float lastSizeCompatScale = mSizeCompatScale;
- // Only allow to scale down.
- mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
- ? 1f : Math.min((float) viewportW / contentW, (float) viewportH / contentH);
+ updateSizeCompatScale(resolvedAppBounds, containerAppBounds);
+
final int containerTopInset = containerAppBounds.top - containerBounds.top;
final boolean topNotAligned =
containerTopInset != resolvedAppBounds.top - resolvedBounds.top;
@@ -8797,6 +8804,20 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
isInSizeCompatModeForBounds(resolvedAppBounds, containerAppBounds);
}
+ void updateSizeCompatScale(Rect resolvedAppBounds, Rect containerAppBounds) {
+ // Only allow to scale down.
+ mSizeCompatScale = mLetterboxUiController.findOpaqueNotFinishingActivityBelow()
+ .map(activityRecord -> activityRecord.mSizeCompatScale)
+ .orElseGet(() -> {
+ final int contentW = resolvedAppBounds.width();
+ final int contentH = resolvedAppBounds.height();
+ final int viewportW = containerAppBounds.width();
+ final int viewportH = containerAppBounds.height();
+ return (contentW <= viewportW && contentH <= viewportH) ? 1f : Math.min(
+ (float) viewportW / contentW, (float) viewportH / contentH);
+ });
+ }
+
private boolean isInSizeCompatModeForBounds(final Rect appBounds, final Rect containerBounds) {
if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
// To avoid wrong app behaviour, we decided to disable SCM when a translucent activity
@@ -8859,10 +8880,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@Override
public Rect getBounds() {
- if (mSizeCompatBounds != null) {
- return mSizeCompatBounds;
- }
- return super.getBounds();
+ // TODO(b/268458693): Refactor configuration inheritance in case of translucent activities
+ final Rect superBounds = super.getBounds();
+ return mLetterboxUiController.findOpaqueNotFinishingActivityBelow()
+ .map(ActivityRecord::getBounds)
+ .orElseGet(() -> {
+ if (mSizeCompatBounds != null) {
+ return mSizeCompatBounds;
+ }
+ return superBounds;
+ });
}
@Override
@@ -8887,7 +8914,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Max bounds should be sandboxed when an activity should have compatDisplayInsets, and it
// will keep the same bounds and screen configuration when it was first launched regardless
// how its parent window changes, so that the sandbox API will provide a consistent result.
- if (mCompatDisplayInsets != null || shouldCreateCompatDisplayInsets()) {
+ if (getCompatDisplayInsets() != null || shouldCreateCompatDisplayInsets()) {
return true;
}
@@ -8929,7 +8956,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mTransitionController.collect(this);
}
}
- if (mCompatDisplayInsets != null) {
+ if (getCompatDisplayInsets() != null) {
Configuration overrideConfig = getRequestedOverrideConfiguration();
// Adapt to changes in orientation locking. The app is still non-resizable, but
// it can change which orientation is fixed. If the fixed orientation changes,
@@ -9005,7 +9032,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (mVisibleRequested) {
// It may toggle the UI for user to restart the size compatibility mode activity.
display.handleActivitySizeCompatModeIfNeeded(this);
- } else if (mCompatDisplayInsets != null && !visibleIgnoringKeyguard
+ } else if (getCompatDisplayInsets() != null && !visibleIgnoringKeyguard
&& (app == null || !app.hasVisibleActivities())) {
// visibleIgnoringKeyguard is checked to avoid clearing mCompatDisplayInsets during
// displays change. Displays are turned off during the change so mVisibleRequested
diff --git a/services/core/java/com/android/server/wm/AsyncRotationController.java b/services/core/java/com/android/server/wm/AsyncRotationController.java
index dcafe80686ad..0dc6e0ff1054 100644
--- a/services/core/java/com/android/server/wm/AsyncRotationController.java
+++ b/services/core/java/com/android/server/wm/AsyncRotationController.java
@@ -217,6 +217,34 @@ class AsyncRotationController extends FadeAnimationController implements Consume
if (DEBUG) Slog.d(TAG, "Requested to sync draw transaction");
}
+ /**
+ * If an async window is not requested to redraw or its surface is removed, then complete its
+ * operation directly to avoid waiting until timeout.
+ */
+ void updateTargetWindows() {
+ if (mTransitionOp == OP_LEGACY || !mIsStartTransactionCommitted) return;
+ for (int i = mTargetWindowTokens.size() - 1; i >= 0; i--) {
+ final Operation op = mTargetWindowTokens.valueAt(i);
+ if (op.mIsCompletionPending || op.mAction == Operation.ACTION_SEAMLESS) {
+ // Skip completed target. And seamless windows use the signal from blast sync.
+ continue;
+ }
+ final WindowToken token = mTargetWindowTokens.keyAt(i);
+ int readyCount = 0;
+ final int childCount = token.getChildCount();
+ for (int j = childCount - 1; j >= 0; j--) {
+ final WindowState w = token.getChildAt(j);
+ // If the token no longer contains pending drawn windows, then it is ready.
+ if (w.isDrawn() || !w.mWinAnimator.getShown()) {
+ readyCount++;
+ }
+ }
+ if (readyCount == childCount) {
+ mDisplayContent.finishAsyncRotation(token);
+ }
+ }
+ }
+
/** Lets the window fit in new rotation naturally. */
private void finishOp(WindowToken windowToken) {
final Operation op = mTargetWindowTokens.remove(windowToken);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index ade2fe7152c0..17ec9cbd7428 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -4761,6 +4761,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
void updateWindowsForAnimator() {
forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */);
+ if (mAsyncRotationController != null) {
+ mAsyncRotationController.updateTargetWindows();
+ }
}
boolean isInputMethodClientFocus(int uid, int pid) {
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index 513667024caa..fa49a6ba6c2b 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -22,6 +22,7 @@ import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ALLOW
import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_CAMERA_COMPAT_TREATMENT;
import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_COMPAT_FAKE_FOCUS;
import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY;
+import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -296,7 +297,6 @@ final class LetterboxConfiguration {
R.bool.config_isCompatFakeFocusEnabled);
mIsPolicyForIgnoringRequestedOrientationEnabled = mContext.getResources().getBoolean(
R.bool.config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled);
-
mIsDisplayRotationImmersiveAppCompatPolicyEnabled = mContext.getResources().getBoolean(
R.bool.config_letterboxIsDisplayRotationImmersiveAppCompatPolicyEnabled);
mDeviceConfig.updateFlagActiveStatus(
@@ -311,7 +311,9 @@ final class LetterboxConfiguration {
mDeviceConfig.updateFlagActiveStatus(
/* isActive */ mIsCompatFakeFocusEnabled,
/* key */ KEY_ENABLE_COMPAT_FAKE_FOCUS);
-
+ mDeviceConfig.updateFlagActiveStatus(
+ /* isActive */ mTranslucentLetterboxingEnabled,
+ /* key */ KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY);
mLetterboxConfigurationPersister = letterboxConfigurationPersister;
mLetterboxConfigurationPersister.start();
}
@@ -1003,7 +1005,7 @@ final class LetterboxConfiguration {
boolean isTranslucentLetterboxingEnabled() {
return mTranslucentLetterboxingOverrideEnabled || (mTranslucentLetterboxingEnabled
- && isTranslucentLetterboxingAllowed());
+ && mDeviceConfig.getFlag(KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY));
}
void setTranslucentLetterboxingEnabled(boolean translucentLetterboxingEnabled) {
@@ -1051,13 +1053,6 @@ final class LetterboxConfiguration {
isDeviceInTabletopMode, nextVerticalPosition);
}
- // TODO(b/262378106): Cache a runtime flag and implement
- // DeviceConfig.OnPropertiesChangedListener
- static boolean isTranslucentLetterboxingAllowed() {
- return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
- "enable_translucent_activity_letterbox", false);
- }
-
/** Whether fake sending focus is enabled for unfocused apps in splitscreen */
boolean isCompatFakeFocusEnabled() {
return mIsCompatFakeFocusEnabled && mDeviceConfig.getFlag(KEY_ENABLE_COMPAT_FAKE_FOCUS);
diff --git a/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java b/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
index b364872e56e7..df3c8f0fdccc 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
@@ -48,6 +48,11 @@ final class LetterboxConfigurationDeviceConfig
static final String KEY_ENABLE_COMPAT_FAKE_FOCUS = "enable_compat_fake_focus";
private static final boolean DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS = true;
+ static final String KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY =
+ "enable_letterbox_translucent_activity";
+
+ private static final boolean DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY = true;
+
@VisibleForTesting
static final Map<String, Boolean> sKeyToDefaultValueMap = Map.of(
KEY_ENABLE_CAMERA_COMPAT_TREATMENT,
@@ -57,7 +62,9 @@ final class LetterboxConfigurationDeviceConfig
KEY_ALLOW_IGNORE_ORIENTATION_REQUEST,
DEFAULT_VALUE_ALLOW_IGNORE_ORIENTATION_REQUEST,
KEY_ENABLE_COMPAT_FAKE_FOCUS,
- DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS
+ DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS,
+ KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY,
+ DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY
);
// Whether camera compatibility treatment is enabled.
@@ -82,6 +89,10 @@ final class LetterboxConfigurationDeviceConfig
// which isn't guaranteed by default in multi-window modes.
private boolean mIsCompatFakeFocusAllowed = DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS;
+ // Whether the letterbox strategy for transparent activities is allowed
+ private boolean mIsTranslucentLetterboxingAllowed =
+ DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY;
+
// Set of active device configs that need to be updated in
// DeviceConfig.OnPropertiesChangedListener#onPropertiesChanged.
private final ArraySet<String> mActiveDeviceConfigsSet = new ArraySet<>();
@@ -129,6 +140,8 @@ final class LetterboxConfigurationDeviceConfig
return mIsAllowIgnoreOrientationRequest;
case KEY_ENABLE_COMPAT_FAKE_FOCUS:
return mIsCompatFakeFocusAllowed;
+ case KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY:
+ return mIsTranslucentLetterboxingAllowed;
default:
throw new AssertionError("Unexpected flag name: " + key);
}
@@ -141,20 +154,20 @@ final class LetterboxConfigurationDeviceConfig
}
switch (key) {
case KEY_ENABLE_CAMERA_COMPAT_TREATMENT:
- mIsCameraCompatTreatmentEnabled =
- getDeviceConfig(key, defaultValue);
+ mIsCameraCompatTreatmentEnabled = getDeviceConfig(key, defaultValue);
break;
case KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY:
mIsDisplayRotationImmersiveAppCompatPolicyEnabled =
getDeviceConfig(key, defaultValue);
break;
case KEY_ALLOW_IGNORE_ORIENTATION_REQUEST:
- mIsAllowIgnoreOrientationRequest =
- getDeviceConfig(key, defaultValue);
+ mIsAllowIgnoreOrientationRequest = getDeviceConfig(key, defaultValue);
break;
case KEY_ENABLE_COMPAT_FAKE_FOCUS:
- mIsCompatFakeFocusAllowed =
- getDeviceConfig(key, defaultValue);
+ mIsCompatFakeFocusAllowed = getDeviceConfig(key, defaultValue);
+ break;
+ case KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY:
+ mIsTranslucentLetterboxingAllowed = getDeviceConfig(key, defaultValue);
break;
default:
throw new AssertionError("Unexpected flag name: " + key);
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index e3437683e957..e1dbe01aca61 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -193,12 +193,6 @@ final class LetterboxUiController {
// The app compat state for the opaque activity if any
private int mInheritedAppCompatState = APP_COMPAT_STATE_CHANGED__STATE__UNKNOWN;
- // If true it means that the opaque activity beneath a translucent one is in SizeCompatMode.
- private boolean mIsInheritedInSizeCompatMode;
-
- // This is the SizeCompatScale of the opaque activity beneath a translucent one
- private float mInheritedSizeCompatScale;
-
// The CompatDisplayInsets of the opaque activity beneath the translucent one.
private ActivityRecord.CompatDisplayInsets mInheritedCompatDisplayInsets;
@@ -735,8 +729,21 @@ final class LetterboxUiController {
: mActivityRecord.inMultiWindowMode()
? mActivityRecord.getTask().getBounds()
: mActivityRecord.getRootTask().getParent().getBounds();
+ // In case of translucent activities an option is to use the WindowState#getFrame() of
+ // the first opaque activity beneath. In some cases (e.g. an opaque activity is using
+ // non MATCH_PARENT layouts or a Dialog theme) this might not provide the correct
+ // information and in particular it might provide a value for a smaller area making
+ // the letterbox overlap with the translucent activity's frame.
+ // If we use WindowState#getFrame() for the translucent activity's letterbox inner
+ // frame, the letterbox will then be overlapped with the translucent activity's frame.
+ // Because the surface layer of letterbox is lower than an activity window, this
+ // won't crop the content, but it may affect other features that rely on values stored
+ // in mLetterbox, e.g. transitions, a status bar scrim and recents preview in Launcher
+ // For this reason we use ActivityRecord#getBounds() that the translucent activity
+ // inherits from the first opaque activity beneath and also takes care of the scaling
+ // in case of activities in size compat mode.
final Rect innerFrame = hasInheritedLetterboxBehavior()
- ? mActivityRecord.getWindowConfiguration().getBounds() : w.getFrame();
+ ? mActivityRecord.getBounds() : w.getFrame();
mLetterbox.layout(spaceToFill, innerFrame, mTmpPoint);
} else if (mLetterbox != null) {
mLetterbox.hide();
@@ -1386,10 +1393,10 @@ final class LetterboxUiController {
mLetterboxConfigListener.onRemoved();
clearInheritedConfig();
}
- // In case mActivityRecord.getCompatDisplayInsets() is not null we don't apply the
+ // In case mActivityRecord.hasCompatDisplayInsetsWithoutOverride() we don't apply the
// opaque activity constraints because we're expecting the activity is already letterboxed.
- if (mActivityRecord.getTask() == null || mActivityRecord.getCompatDisplayInsets() != null
- || mActivityRecord.fillsParent()) {
+ if (mActivityRecord.getTask() == null || mActivityRecord.fillsParent()
+ || mActivityRecord.hasCompatDisplayInsetsWithoutInheritance()) {
return;
}
final ActivityRecord firstOpaqueActivityBeneath = mActivityRecord.getTask().getActivity(
@@ -1417,6 +1424,7 @@ final class LetterboxUiController {
// We need to initialize appBounds to avoid NPE. The actual value will
// be set ahead when resolving the Configuration for the activity.
mutatedConfiguration.windowConfiguration.setAppBounds(new Rect());
+ inheritConfiguration(firstOpaqueActivityBeneath);
return mutatedConfiguration;
});
}
@@ -1457,16 +1465,12 @@ final class LetterboxUiController {
return mInheritedAppCompatState;
}
- float getInheritedSizeCompatScale() {
- return mInheritedSizeCompatScale;
- }
-
@Configuration.Orientation
int getInheritedOrientation() {
return mInheritedOrientation;
}
- public ActivityRecord.CompatDisplayInsets getInheritedCompatDisplayInsets() {
+ ActivityRecord.CompatDisplayInsets getInheritedCompatDisplayInsets() {
return mInheritedCompatDisplayInsets;
}
@@ -1486,7 +1490,7 @@ final class LetterboxUiController {
* @return The first not finishing opaque activity beneath the current translucent activity
* if it exists and the strategy is enabled.
*/
- private Optional<ActivityRecord> findOpaqueNotFinishingActivityBelow() {
+ Optional<ActivityRecord> findOpaqueNotFinishingActivityBelow() {
if (!hasInheritedLetterboxBehavior() || mActivityRecord.getTask() == null) {
return Optional.empty();
}
@@ -1508,8 +1512,6 @@ final class LetterboxUiController {
}
mInheritedOrientation = firstOpaque.getRequestedConfigurationOrientation();
mInheritedAppCompatState = firstOpaque.getAppCompatState();
- mIsInheritedInSizeCompatMode = firstOpaque.inSizeCompatMode();
- mInheritedSizeCompatScale = firstOpaque.getCompatScale();
mInheritedCompatDisplayInsets = firstOpaque.getCompatDisplayInsets();
}
@@ -1519,8 +1521,6 @@ final class LetterboxUiController {
mInheritedMaxAspectRatio = UNDEFINED_ASPECT_RATIO;
mInheritedOrientation = Configuration.ORIENTATION_UNDEFINED;
mInheritedAppCompatState = APP_COMPAT_STATE_CHANGED__STATE__UNKNOWN;
- mIsInheritedInSizeCompatMode = false;
- mInheritedSizeCompatScale = 1f;
mInheritedCompatDisplayInsets = null;
}
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index c7d855360df9..2af5460182dd 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3389,6 +3389,11 @@ class Task extends TaskFragment {
&& top.getOrganizedTask() == this && top.isState(RESUMED);
// Whether the direct top activity is in size compat mode on foreground.
info.topActivityInSizeCompat = isTopActivityResumed && top.inSizeCompatMode();
+ if (info.topActivityInSizeCompat
+ && mWmService.mLetterboxConfiguration.isTranslucentLetterboxingEnabled()) {
+ // We hide the restart button in case of transparent activities.
+ info.topActivityInSizeCompat = top.fillsParent();
+ }
// Whether the direct top activity is eligible for letterbox education.
info.topActivityEligibleForLetterboxEducation = isTopActivityResumed
&& top.isEligibleForLetterboxEducation();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 41c112526787..98563f6e73fc 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7357,7 +7357,8 @@ public class WindowManagerService extends IWindowManager.Stub
ProtoLog.w(WM_ERROR, "unable to restore pointer icon");
}
} else {
- InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_DEFAULT);
+ mContext.getSystemService(InputManager.class)
+ .setPointerIconType(PointerIcon.TYPE_DEFAULT);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index a102986832fe..e8625bc3d64b 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -32,7 +32,6 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
-import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
@@ -424,7 +423,7 @@ class WindowStateAnimator {
computeShownFrameLocked();
- if (w.isParentWindowHidden() || !w.isOnScreen()) {
+ if (!w.isOnScreen()) {
hide(t, "prepareSurfaceLocked");
mWallpaperControllerLocked.hideWallpapers(w);
@@ -449,30 +448,23 @@ class WindowStateAnimator {
if (prepared && mDrawState == HAS_DRAWN) {
if (mLastHidden) {
- if (showSurfaceRobustlyLocked(t)) {
- mAnimator.requestRemovalOfReplacedWindows(w);
- mLastHidden = false;
- final DisplayContent displayContent = w.getDisplayContent();
- if (!displayContent.getLastHasContent()) {
- // This draw means the difference between unique content and mirroring.
- // Run another pass through performLayout to set mHasContent in the
- // LogicalDisplay.
- displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
- if (DEBUG_LAYOUT_REPEATS) {
- mService.mWindowPlacerLocked.debugLayoutRepeats(
- "showSurfaceRobustlyLocked " + w,
- displayContent.pendingLayoutChanges);
- }
+ mSurfaceController.showRobustly(t);
+ mAnimator.requestRemovalOfReplacedWindows(w);
+ mLastHidden = false;
+ final DisplayContent displayContent = w.getDisplayContent();
+ if (!displayContent.getLastHasContent()) {
+ // This draw means the difference between unique content and mirroring.
+ // Run another pass through performLayout to set mHasContent in the
+ // LogicalDisplay.
+ displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
+ if (DEBUG_LAYOUT_REPEATS) {
+ mService.mWindowPlacerLocked.debugLayoutRepeats(
+ "showSurfaceRobustlyLocked " + w,
+ displayContent.pendingLayoutChanges);
}
- } else {
- w.setOrientationChanging(false);
}
}
}
- } else {
- if (mWin.isAnimating(TRANSITION | PARENTS)) {
- ProtoLog.v(WM_DEBUG_ANIM, "prepareSurface: No changes in animation for %s", this);
- }
}
if (w.getOrientationChanging()) {
@@ -511,22 +503,6 @@ class WindowStateAnimator {
mSurfaceController.setColorSpaceAgnostic(mWin.getPendingTransaction(), agnostic);
}
- /**
- * Have the surface flinger show a surface, robustly dealing with
- * error conditions. In particular, if there is not enough memory
- * to show the surface, then we will try to get rid of other surfaces
- * in order to succeed.
- *
- * @return Returns true if the surface was successfully shown.
- */
- private boolean showSurfaceRobustlyLocked(SurfaceControl.Transaction t) {
- boolean shown = mSurfaceController.showRobustly(t);
- if (!shown)
- return false;
-
- return true;
- }
-
void applyEnterAnimationLocked() {
// If we are the new part of a window replacement transition and we have requested
// not to animate, we instead want to make it seamless, so we don't want to apply
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 607ce251c4d1..33751b9f16a0 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -245,13 +245,13 @@ class WindowSurfaceController {
t.setColorSpaceAgnostic(mSurfaceControl, agnostic);
}
- boolean showRobustly(SurfaceControl.Transaction t) {
+ void showRobustly(SurfaceControl.Transaction t) {
ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SHOW (performLayout): %s", title);
if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
+ " during relayout");
if (mSurfaceShown) {
- return true;
+ return;
}
setShown(true);
@@ -262,7 +262,6 @@ class WindowSurfaceController {
dc.mDisplayId, 1 /* request shown */,
String.valueOf(dc.mWallpaperController.getWallpaperTarget()));
}
- return true;
}
boolean clearWindowContentFrameStats() {
diff --git a/services/tests/mockingservicestests/src/android/hardware/face/FaceManagerTest.java b/services/tests/mockingservicestests/src/android/hardware/face/FaceManagerTest.java
deleted file mode 100644
index f3feb0269598..000000000000
--- a/services/tests/mockingservicestests/src/android/hardware/face/FaceManagerTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.face;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.os.Looper;
-import android.os.RemoteException;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoJUnitRunner;
-import org.mockito.junit.MockitoRule;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(MockitoJUnitRunner.class)
-public class FaceManagerTest {
- @Rule
- public final MockitoRule mockito = MockitoJUnit.rule();
-
- @Mock
- Context mContext;
- @Mock
- IFaceService mService;
-
- @Captor
- ArgumentCaptor<IFaceAuthenticatorsRegisteredCallback> mCaptor;
-
- List<FaceSensorPropertiesInternal> mProps;
- FaceManager mFaceManager;
-
- @Before
- public void setUp() throws Exception {
- when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
- mFaceManager = new FaceManager(mContext, mService);
- mProps = new ArrayList<>();
- mProps.add(new FaceSensorPropertiesInternal(
- 0 /* id */,
- FaceSensorProperties.STRENGTH_STRONG,
- 1 /* maxTemplatesAllowed */,
- new ArrayList<>() /* conponentInfo */,
- FaceSensorProperties.TYPE_UNKNOWN,
- true /* supportsFaceDetection */,
- true /* supportsSelfIllumination */,
- false /* resetLockoutRequiresChallenge */));
- }
-
- @Test
- public void getSensorPropertiesInternal_noBinderCalls() throws RemoteException {
- verify(mService).addAuthenticatorsRegisteredCallback(mCaptor.capture());
-
- mCaptor.getValue().onAllAuthenticatorsRegistered(mProps);
- List<FaceSensorPropertiesInternal> actual = mFaceManager.getSensorPropertiesInternal();
-
- assertThat(actual).isEqualTo(mProps);
- verify(mService, never()).getSensorPropertiesInternal(any());
- }
-}
diff --git a/services/tests/mockingservicestests/src/android/hardware/fingerprint/FingerprintManagerTest.java b/services/tests/mockingservicestests/src/android/hardware/fingerprint/FingerprintManagerTest.java
deleted file mode 100644
index 558202d51b27..000000000000
--- a/services/tests/mockingservicestests/src/android/hardware/fingerprint/FingerprintManagerTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.fingerprint;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.os.Looper;
-import android.os.RemoteException;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoJUnitRunner;
-import org.mockito.junit.MockitoRule;
-
-import java.util.ArrayList;
-import java.util.List;
-
-
-@RunWith(MockitoJUnitRunner.class)
-public class FingerprintManagerTest {
- @Rule
- public final MockitoRule mockito = MockitoJUnit.rule();
-
- @Mock
- Context mContext;
- @Mock
- IFingerprintService mService;
-
- @Captor
- ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mCaptor;
-
- List<FingerprintSensorPropertiesInternal> mProps;
- FingerprintManager mFingerprintManager;
-
- @Before
- public void setUp() throws Exception {
- when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
- mFingerprintManager = new FingerprintManager(mContext, mService);
- mProps = new ArrayList<>();
- mProps.add(new FingerprintSensorPropertiesInternal(
- 0 /* sensorId */,
- FingerprintSensorProperties.STRENGTH_STRONG,
- 1 /* maxEnrollmentsPerUser */,
- new ArrayList<>() /* componentInfo */,
- FingerprintSensorProperties.TYPE_UNKNOWN,
- true /* halControlsIllumination */,
- true /* resetLockoutRequiresHardwareAuthToken */,
- new ArrayList<>() /* sensorLocations */));
- }
-
- @Test
- public void getSensorPropertiesInternal_noBinderCalls() throws RemoteException {
- verify(mService).addAuthenticatorsRegisteredCallback(mCaptor.capture());
-
- mCaptor.getValue().onAllAuthenticatorsRegistered(mProps);
- List<FingerprintSensorPropertiesInternal> actual =
- mFingerprintManager.getSensorPropertiesInternal();
-
- assertThat(actual).isEqualTo(mProps);
- verify(mService, never()).getSensorPropertiesInternal(any());
- }
-}
diff --git a/services/tests/mockingservicestests/src/android/hardware/fingerprint/OWNERS b/services/tests/mockingservicestests/src/android/hardware/fingerprint/OWNERS
index 3edcf70d7e67..6a2192a2c7fb 100644
--- a/services/tests/mockingservicestests/src/android/hardware/fingerprint/OWNERS
+++ b/services/tests/mockingservicestests/src/android/hardware/fingerprint/OWNERS
@@ -1 +1 @@
-include /services/core/java/com/android/server/biometrics/OWNERS \ No newline at end of file
+include /services/core/java/com/android/server/biometrics/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
index 3fd0e072809f..f8cfdf131a28 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
@@ -17,9 +17,12 @@
package com.android.server.am;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+
import static com.android.server.am.ActivityManagerService.Injector;
import static com.android.server.am.CachedAppOptimizer.compactActionIntToAction;
+
import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
@@ -34,27 +37,30 @@ import android.os.Process;
import android.platform.test.annotations.Presubmit;
import android.provider.DeviceConfig;
import android.text.TextUtils;
+
import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
import com.android.modules.utils.testing.TestableDeviceConfig;
+import com.android.server.ExtendedMockitoTestCase;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.appop.AppOpsService;
import com.android.server.wm.ActivityTaskManagerService;
-import java.io.File;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
+
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
-import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* Tests for {@link CachedAppOptimizer}.
@@ -63,10 +69,7 @@ import org.mockito.junit.MockitoJUnitRunner;
* atest FrameworksMockingServicesTests:CachedAppOptimizerTest
*/
@Presubmit
-@RunWith(MockitoJUnitRunner.class)
-@Ignore("TODO(b/226641572): this test is broken and it cannot use ExtendedMockitoTestCase as it "
- + "uses TestableDeviceConfigRule, which creates its own mockito session")
-public final class CachedAppOptimizerTest {
+public final class CachedAppOptimizerTest extends ExtendedMockitoTestCase {
private ServiceThread mThread;
@@ -84,16 +87,21 @@ public final class CachedAppOptimizerTest {
@Mock
private PackageManagerInternal mPackageManagerInt;
- @Rule
- public final TestableDeviceConfig.TestableDeviceConfigRule
- mDeviceConfigRule = new TestableDeviceConfig.TestableDeviceConfigRule();
+ private final TestableDeviceConfig mDeviceConfig = new TestableDeviceConfig();
+
@Rule
public final ApplicationExitInfoTest.ServiceThreadRule
mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule();
+ @Override
+ protected void initializeSession(StaticMockitoSessionBuilder builder) {
+ mDeviceConfig.setUpMockedClasses(builder);
+ }
+
@Before
public void setUp() {
System.loadLibrary("mockingservicestestjni");
+ mDeviceConfig.setUpMockBehaviors();
mHandlerThread = new HandlerThread("");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
@@ -124,6 +132,7 @@ public final class CachedAppOptimizerTest {
mHandlerThread.quit();
mThread.quit();
mCountDown = null;
+ mDeviceConfig.tearDown();
}
private ProcessRecord makeProcessRecord(int pid, int uid, int packageUid, String processName,
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
index 4c898b0c4d58..b0c3a6e26b7a 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
@@ -705,7 +705,7 @@ public class BiometricSchedulerTest {
TEST_SENSOR_ID, mock(BiometricLogger.class), biometricContext,
true /* isStrongBiometric */, null /* taskStackListener */,
null /* lockoutTracker */, false /* isKeyguard */,
- true /* shouldVibrate */, false /* isKeyguardBypassEnabled */,
+ true /* shouldVibrate */,
0 /* sensorStrength */);
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
index 139910ba8926..184a5562a689 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
@@ -159,7 +159,7 @@ public class FaceAuthenticationClientTest {
false /* requireConfirmation */, 9 /* sensorId */,
mBiometricLogger, mBiometricContext, true /* isStrongBiometric */,
mUsageStats, null /* mLockoutCache */, false /* allowBackgroundAuthentication */,
- false /* isKeyguardBypassEnabled */, null /* sensorPrivacyManager */,
+ null /* sensorPrivacyManager */,
0 /* biometricStrength */) {
@Override
protected ActivityTaskManager getActivityTaskManager() {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index ef3b007171b2..f08d0f5f71a4 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -177,7 +177,6 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
-import android.permission.PermissionCheckerManager;
import android.permission.PermissionManager;
import android.provider.DeviceConfig;
import android.provider.MediaStore;
@@ -10254,7 +10253,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
- /* permissionState= */ PermissionCheckerManager.PERMISSION_HARD_DENIED,
+ /* permissionState= */ PermissionManager.PERMISSION_HARD_DENIED,
/* isSticky= */ true);
}
@@ -10263,7 +10262,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
- /* permissionState= */ PermissionCheckerManager.PERMISSION_SOFT_DENIED,
+ /* permissionState= */ PermissionManager.PERMISSION_SOFT_DENIED,
/* isSticky= */ true);
}
@@ -10272,7 +10271,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
- /* permissionState= */ PermissionCheckerManager.PERMISSION_GRANTED,
+ /* permissionState= */ PermissionManager.PERMISSION_GRANTED,
/* isSticky= */ false);
}
@@ -10281,7 +10280,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE,
- /* permissionState= */ PermissionCheckerManager.PERMISSION_HARD_DENIED,
+ /* permissionState= */ PermissionManager.PERMISSION_HARD_DENIED,
/* isSticky= */ true);
}
@@ -10290,7 +10289,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE,
- /* permissionState= */ PermissionCheckerManager.PERMISSION_SOFT_DENIED,
+ /* permissionState= */ PermissionManager.PERMISSION_SOFT_DENIED,
/* isSticky= */ true);
}
@@ -10299,7 +10298,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE,
- /* permissionState= */ PermissionCheckerManager.PERMISSION_GRANTED,
+ /* permissionState= */ PermissionManager.PERMISSION_GRANTED,
/* isSticky= */ true);
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index f0f9204c4e4e..1ecd4a1ffd7e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -57,6 +57,7 @@ import static junit.framework.Assert.fail;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -1576,6 +1577,47 @@ public class PreferencesHelperTest extends UiServiceTestCase {
new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX), true, false));
}
+ @Test
+ public void testUpdateChannel_downgradeImportance() {
+ mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_DEFAULT),
+ true, false);
+
+ assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true, false));
+ }
+
+ @Test
+ public void testUpdateChannel_upgradeImportance_ignored() {
+ mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_DEFAULT),
+ true, false);
+
+ assertFalse(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX), true, false));
+ }
+
+ @Test
+ public void testUpdateChannel_badImportance() {
+ mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_DEFAULT),
+ true, false);
+
+ assertThrows(IllegalArgumentException.class,
+ () -> mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE - 1), true,
+ false));
+
+ assertThrows(IllegalArgumentException.class,
+ () -> mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_UNSPECIFIED), true,
+ false));
+
+ assertThrows(IllegalArgumentException.class,
+ () -> mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX + 1), true,
+ false));
+ }
@Test
public void testUpdate() throws Exception {
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index c9f758ce1f55..e9aca5666a93 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -279,7 +279,8 @@ public class SizeCompatTests extends WindowTestsBase {
public void testTranslucentActivitiesWhenUnfolding() {
mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true);
setUpDisplaySizeWithApp(2800, 1400);
- mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(
+ true /* ignoreOrientationRequest */);
mActivity.mWmService.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(
1.0f /*letterboxVerticalPositionMultiplier*/);
prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
@@ -290,18 +291,23 @@ public class SizeCompatTests extends WindowTestsBase {
.build();
doReturn(false).when(translucentActivity).fillsParent();
mTask.addChild(translucentActivity);
+ assertEquals(translucentActivity.getBounds(), mActivity.getBounds());
mTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
spyOn(mActivity);
// Halffold
- setFoldablePosture(translucentActivity, true /* isHalfFolded */, false /* isTabletop */);
+ setFoldablePosture(translucentActivity, true /* isHalfFolded */,
+ false /* isTabletop */);
verify(mActivity).recomputeConfiguration();
+ assertEquals(translucentActivity.getBounds(), mActivity.getBounds());
clearInvocations(mActivity);
// Unfold
- setFoldablePosture(translucentActivity, false /* isHalfFolded */, false /* isTabletop */);
+ setFoldablePosture(translucentActivity, false /* isHalfFolded */,
+ false /* isTabletop */);
verify(mActivity).recomputeConfiguration();
+ assertEquals(translucentActivity.getBounds(), mActivity.getBounds());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 05ee2f24fbaf..3f14217b7a18 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -1018,6 +1018,10 @@ public class TransitionTests extends WindowTestsBase {
@Test
public void testDisplayRotationChange() {
+ final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
+ spyOn(displayPolicy);
+ // Simulate gesture navigation (non-movable) so it is not seamless.
+ doReturn(false).when(displayPolicy).navigationBarCanMove();
final Task task = createActivityRecord(mDisplayContent).getTask();
final WindowState statusBar = createWindow(null, TYPE_STATUS_BAR, "statusBar");
final WindowState navBar = createWindow(null, TYPE_NAVIGATION_BAR, "navBar");
@@ -1072,7 +1076,8 @@ public class TransitionTests extends WindowTestsBase {
// Navigation bar finishes drawing after the start transaction, so its fade-in animation
// can execute directly.
- asyncRotationController.handleFinishDrawing(navBar, mMockT);
+ navBar.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
+ asyncRotationController.updateTargetWindows();
assertFalse(asyncRotationController.isTargetToken(navBar.mToken));
assertNull(mDisplayContent.getAsyncRotationController());
}
diff --git a/telecomm/java/android/telecom/CallControl.java b/telecomm/java/android/telecom/CallControl.java
index 2135e276e591..6b2bea032a00 100644
--- a/telecomm/java/android/telecom/CallControl.java
+++ b/telecomm/java/android/telecom/CallControl.java
@@ -147,10 +147,8 @@ public final class CallControl {
* <li>{@link DisconnectCause#REJECTED}</li>
* <li>{@link DisconnectCause#MISSED}</li>
* </ul>
- *
* @param executor The {@link Executor} on which the {@link OutcomeReceiver} callback
* will be called on.
- *
* @param callback That will be completed on the Telecom side that details success or
* failure of the requested operation.
*
@@ -254,6 +252,36 @@ public final class CallControl {
}
/**
+ * Raises an event to the {@link android.telecom.InCallService} implementations tracking this
+ * call via {@link android.telecom.Call.Callback#onConnectionEvent(Call, String, Bundle)}.
+ * These events and the associated extra keys for the {@code Bundle} parameter are defined
+ * in Android X. This API is used to relay additional information about a call other than
+ * what is specified in the {@link android.telecom.CallAttributes} to
+ * {@link android.telecom.InCallService}s. This might include, for example, a change to the list
+ * of participants in a meeting, or the name of the speakers who have their hand raised. Where
+ * appropriate, the {@link InCallService}s tracking this call may choose to render this
+ * additional information about the call. An automotive calling UX, for example may have enough
+ * screen real estate to indicate the number of participants in a meeting, but to prevent
+ * distractions could suppress the list of participants.
+ *
+ * @param event that is defined in AndroidX (ex. The number of participants changed)
+ * @param extras the updated value in relation to the event (ex. 4 participants)
+ */
+ public void sendEvent(@NonNull String event, @NonNull Bundle extras) {
+ Objects.requireNonNull(event);
+ Objects.requireNonNull(extras);
+ if (mServerInterface != null) {
+ try {
+ mServerInterface.sendEvent(mCallId, event, extras);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ } else {
+ throw new IllegalStateException(INTERFACE_ERROR_MSG);
+ }
+ }
+
+ /**
* Since {@link OutcomeReceiver}s cannot be passed via AIDL, a ResultReceiver (which can) must
* wrap the Clients {@link OutcomeReceiver} passed in and await for the Telecom Server side
* response in {@link ResultReceiver#onReceiveResult(int, Bundle)}.
diff --git a/telecomm/java/android/telecom/CallEventCallback.java b/telecomm/java/android/telecom/CallEventCallback.java
index bfe368560a22..d96c406c4294 100644
--- a/telecomm/java/android/telecom/CallEventCallback.java
+++ b/telecomm/java/android/telecom/CallEventCallback.java
@@ -17,6 +17,7 @@
package android.telecom;
import android.annotation.NonNull;
+import android.os.Bundle;
import java.util.List;
@@ -56,4 +57,17 @@ public interface CallEventCallback {
* @param reason Code to indicate the reason of this failure
*/
void onCallStreamingFailed(@CallStreamingService.StreamingFailedReason int reason);
+
+ /**
+ * Informs this {@link android.telecom.CallEventCallback} on events raised from a
+ * {@link android.telecom.InCallService} presenting this call. The event key and extra values
+ * are defined in AndroidX. This enables alternative calling surfaces, such as an automotive
+ * UI, to relay requests to perform other non-standard call actions to the app. For example,
+ * an automotive calling solution may offer the ability for the user to raise their hand
+ * during a meeting.
+ *
+ * @param event that is defined in AndroidX (ex. the number of participants changed)
+ * @param extras the updated value in relation to the event (ex. 4 participants)
+ */
+ void onEvent(@NonNull String event, @NonNull Bundle extras);
}
diff --git a/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java b/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java
index 7bba1eb07ebd..e44e2b31c189 100644
--- a/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java
+++ b/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java
@@ -19,6 +19,7 @@ package com.android.internal.telecom;
import static android.telecom.TelecomManager.TELECOM_TRANSACTION_SUCCESS;
import android.os.Binder;
+import android.os.Bundle;
import android.os.OutcomeReceiver;
import android.os.ResultReceiver;
import android.telecom.CallAttributes;
@@ -148,6 +149,7 @@ public class ClientTransactionalServiceWrapper {
private static final String ON_AVAILABLE_CALL_ENDPOINTS = "onAvailableCallEndpointsChanged";
private static final String ON_MUTE_STATE_CHANGED = "onMuteStateChanged";
private static final String ON_CALL_STREAMING_FAILED = "onCallStreamingFailed";
+ private static final String ON_EVENT = "onEvent";
private void handleHandshakeCallback(String action, String callId, int code,
ResultReceiver ackResultReceiver) {
@@ -314,5 +316,23 @@ public class ClientTransactionalServiceWrapper {
Log.i(TAG, TextUtils.formatSimple("oCSF: id=[%s], reason=[%s]", callId, reason));
handleEventCallback(callId, ON_CALL_STREAMING_FAILED, reason);
}
+
+ @Override
+ public void onEvent(String callId, String event, Bundle extras) {
+ // lookup the callEventCallback associated with the particular call
+ TransactionalCall call = mCallIdToTransactionalCall.get(callId);
+ if (call != null) {
+ CallEventCallback callback = call.getCallStateCallback();
+ Executor executor = call.getExecutor();
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> {
+ callback.onEvent(event, extras);
+ });
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
};
}
diff --git a/telecomm/java/com/android/internal/telecom/ICallControl.aidl b/telecomm/java/com/android/internal/telecom/ICallControl.aidl
index b78a77ec9756..3e651e92e612 100644
--- a/telecomm/java/com/android/internal/telecom/ICallControl.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallControl.aidl
@@ -16,6 +16,7 @@
package com.android.internal.telecom;
+import android.os.Bundle;
import android.telecom.CallControl;
import android.telecom.CallEndpoint;
import android.telecom.DisconnectCause;
@@ -30,4 +31,5 @@ oneway interface ICallControl {
void disconnect(String callId, in DisconnectCause disconnectCause, in ResultReceiver callback);
void startCallStreaming(String callId, in ResultReceiver callback);
void requestCallEndpointChange(in CallEndpoint callEndpoint, in ResultReceiver callback);
+ void sendEvent(String callId, String event, in Bundle extras);
} \ No newline at end of file
diff --git a/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl b/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl
index fef5e9e47dc5..dd61d173ef7e 100644
--- a/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl
@@ -16,6 +16,7 @@
package com.android.internal.telecom;
+import android.os.Bundle;
import android.telecom.CallControl;
import android.telecom.CallEndpoint;
import com.android.internal.telecom.ICallControl;
@@ -44,6 +45,8 @@ oneway interface ICallEventCallback {
void onCallEndpointChanged(String callId, in CallEndpoint endpoint);
void onAvailableCallEndpointsChanged(String callId, in List<CallEndpoint> endpoint);
void onMuteStateChanged(String callId, boolean isMuted);
+ // -- Events
+ void onEvent(String callId, String event, in Bundle extras);
// hidden methods that help with cleanup
void removeCallFromTransactionalServiceWrapper(String callId);
} \ No newline at end of file
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
index 90ddb6ffb34a..d2a6bf288be4 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
+++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
@@ -31,6 +31,7 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -299,6 +300,8 @@ public final class BackgroundDexOptServiceIntegrationTests {
// Test that background dexopt under low storage conditions downgrades unused packages.
@Test
+ @Ignore("b/251438180: This test has been failing for a long time; temporarily disable it while"
+ + " we investigate this issue.")
public void testBackgroundDexOptDowngradeSuccessful() throws IOException {
// Should be more than DOWNGRADE_AFTER_DAYS.
long deltaDays = DOWNGRADE_AFTER_DAYS + 1;
diff --git a/tests/SilkFX/assets/gainmaps/granddam.jpg b/tests/SilkFX/assets/gainmaps/granddam.jpg
new file mode 100644
index 000000000000..823f14efcbb2
--- /dev/null
+++ b/tests/SilkFX/assets/gainmaps/granddam.jpg
Binary files differ
diff --git a/tests/SilkFX/assets/gainmaps/lightbulb.jpg b/tests/SilkFX/assets/gainmaps/lightbulb.jpg
new file mode 100644
index 000000000000..232c5f0937df
--- /dev/null
+++ b/tests/SilkFX/assets/gainmaps/lightbulb.jpg
Binary files differ
diff --git a/tests/SilkFX/assets/gainmaps/porsche911.jpg b/tests/SilkFX/assets/gainmaps/porsche911.jpg
new file mode 100644
index 000000000000..50f4fc83910e
--- /dev/null
+++ b/tests/SilkFX/assets/gainmaps/porsche911.jpg
Binary files differ