summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/JobService.java3
-rw-r--r--core/api/test-current.txt1
-rw-r--r--core/java/android/app/ActivityManagerInternal.java7
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java17
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl2
-rw-r--r--core/java/android/content/Intent.java8
-rw-r--r--core/java/android/content/res/FontScaleConverterFactory.java26
-rw-r--r--core/java/android/hardware/input/InputManager.java5
-rw-r--r--core/java/android/hardware/input/InputManagerGlobal.java2
-rw-r--r--core/java/android/hardware/input/InputSettings.java12
-rw-r--r--core/java/android/util/TypedValue.java20
-rw-r--r--core/java/android/view/InputMonitor.java27
-rw-r--r--core/java/android/view/SurfaceControlViewHost.java7
-rw-r--r--core/java/android/view/ViewRootImpl.java43
-rw-r--r--core/java/android/widget/ScrollView.java7
-rw-r--r--core/java/android/widget/TextView.java80
-rw-r--r--core/java/com/android/internal/policy/DecorContext.java7
-rw-r--r--core/java/com/android/internal/util/QuickSelect.java256
-rw-r--r--core/jni/Android.bp4
-rw-r--r--core/proto/android/server/windowmanagerservice.proto1
-rw-r--r--core/res/AndroidManifest.xml11
-rw-r--r--core/res/res/values/config_telephony.xml8
-rw-r--r--core/res/res/values/strings.xml3
-rw-r--r--core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt16
-rw-r--r--core/tests/utiltests/src/com/android/internal/util/QuickSelectTest.java152
-rw-r--r--data/etc/privapp-permissions-platform.xml1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java45
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java31
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java22
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java58
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java16
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java49
-rw-r--r--libs/hwui/Android.bp2
-rw-r--r--libs/hwui/jni/YuvToJpegEncoder.cpp32
-rw-r--r--libs/hwui/jni/YuvToJpegEncoder.h6
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt20
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt18
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt39
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/getflow/GetGenericCredentialComponents.kt174
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt4
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt12
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt4
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt6
-rw-r--r--packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt10
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt39
-rw-r--r--packages/SystemUI/docs/dagger.md19
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt26
-rw-r--r--packages/SystemUI/proguard.flags153
-rw-r--r--packages/SystemUI/proguard_common.flags141
-rw-r--r--packages/SystemUI/res/values/strings.xml2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/ClockEventController.kt85
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java9
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java12
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java65
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt52
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FaceAuthenticationModels.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFragmentStartable.kt47
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt26
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandlerTest.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/demomode/DemoModeControllerTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt67
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfigTest.kt16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManagerTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt21
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt46
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt26
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskEventLoggerTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/power/data/repository/PowerRepositoryImplTest.kt14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/QsBatteryModeControllerTest.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMediaManagerTest.kt139
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfigTest.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt38
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapterTest.kt12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt28
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/RefreshUsersSchedulerTest.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt70
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsControllerTest.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java37
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java63
-rw-r--r--services/autofill/java/com/android/server/autofill/SessionCommittedEventLogger.java6
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java247
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerConstants.java19
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java21
-rw-r--r--services/core/java/com/android/server/am/AppProfiler.java202
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java2
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java13
-rw-r--r--services/core/java/com/android/server/am/ServiceRecord.java28
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java38
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java15
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java7
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController2.java7
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java23
-rw-r--r--services/core/java/com/android/server/media/MediaRoute2Provider.java24
-rw-r--r--services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java11
-rw-r--r--services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java1
-rw-r--r--services/core/java/com/android/server/media/SystemMediaRoute2Provider.java9
-rw-r--r--services/core/java/com/android/server/pm/BroadcastHelper.java11
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java2
-rw-r--r--services/core/java/com/android/server/stats/pull/StatsPullAtomService.java19
-rw-r--r--services/core/java/com/android/server/wm/ActivityMetricsLogger.java18
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java40
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java3
-rw-r--r--services/core/java/com/android/server/wm/StartingData.java20
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java6
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java33
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java152
-rw-r--r--services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java9
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java9
-rw-r--r--telephony/OWNERS6
-rw-r--r--telephony/common/com/android/internal/telephony/TelephonyPermissions.java4
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java172
-rw-r--r--telephony/java/android/telephony/satellite/stub/ISatelliteGateway.aidl26
-rw-r--r--telephony/java/android/telephony/satellite/stub/SatelliteGatewayService.java77
-rw-r--r--telephony/java/com/android/internal/telephony/ISub.aidl13
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl9
-rw-r--r--tests/SharedLibraryLoadingTest/AndroidTest.xml1
-rw-r--r--wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java6
188 files changed, 3006 insertions, 1535 deletions
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobService.java b/apex/jobscheduler/framework/java/android/app/job/JobService.java
index f48e07812637..3b5f11bea6c8 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobService.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobService.java
@@ -265,7 +265,8 @@ public abstract class JobService extends Service {
* @see JobInfo.Builder#setRequiredNetworkType(int)
*/
public void onNetworkChanged(@NonNull JobParameters params) {
- Log.w(TAG, "onNetworkChanged() not implemented. Must override in a subclass.");
+ Log.w(TAG, "onNetworkChanged() not implemented in " + getClass().getName()
+ + ". Must override in a subclass.");
}
/**
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 2d9a99cf0d8c..9bbc4a67a79a 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -538,6 +538,7 @@ package android.app.admin {
public class DevicePolicyManager {
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void acknowledgeNewUserDisclaimer();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void calculateHasIncompatibleAccounts();
method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void clearOrganizationId();
method @RequiresPermission(android.Manifest.permission.CLEAR_FREEZE_PERIOD) public void clearSystemUpdatePolicyFreezePeriodRecord();
method @RequiresPermission(android.Manifest.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS) public long forceNetworkLogs();
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 95e446dde4da..021f932c562c 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -45,6 +45,7 @@ import android.os.TransactionTooLargeException;
import android.os.WorkSource;
import android.util.ArraySet;
import android.util.Pair;
+import android.util.StatsEvent;
import com.android.internal.os.TimeoutRecord;
@@ -1217,4 +1218,10 @@ public abstract class ActivityManagerInternal {
*/
public abstract void notifyMediaProjectionEvent(int uid, @NonNull IBinder projectionToken,
@MediaProjectionTokenEvent int event);
+
+ /**
+ * @return The stats event for the cached apps high watermark since last pull.
+ */
+ @NonNull
+ public abstract StatsEvent getCachedAppsHighWatermarkStats(int atomTag, boolean resetAfterPull);
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 4d3338beded5..a8a2ad1bb8df 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -16825,6 +16825,23 @@ public class DevicePolicyManager {
}
/**
+ * Recalculate the incompatible accounts cache.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
+ public void calculateHasIncompatibleAccounts() {
+ if (mService != null) {
+ try {
+ mService.calculateHasIncompatibleAccounts();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
* @return {@code true} if bypassing the device policy management role qualification is allowed
* with the current state of the device.
*
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 9b0b18ac74ec..9795caba95b8 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -608,4 +608,6 @@ interface IDevicePolicyManager {
boolean isDeviceFinanced(String callerPackageName);
String getFinancedDeviceKioskRoleHolder(String callerPackageName);
+
+ void calculateHasIncompatibleAccounts();
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 74a69a623790..307f30619be2 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -12349,7 +12349,9 @@ public class Intent implements Parcelable, Cloneable {
null, new String[] { getType() },
new ClipData.Item(text, htmlText, null, stream));
setClipData(clipData);
- addFlags(FLAG_GRANT_READ_URI_PERMISSION);
+ if (stream != null) {
+ addFlags(FLAG_GRANT_READ_URI_PERMISSION);
+ }
return true;
}
} catch (ClassCastException e) {
@@ -12388,7 +12390,9 @@ public class Intent implements Parcelable, Cloneable {
}
setClipData(clipData);
- addFlags(FLAG_GRANT_READ_URI_PERMISSION);
+ if (streams != null) {
+ addFlags(FLAG_GRANT_READ_URI_PERMISSION);
+ }
return true;
}
} catch (ClassCastException e) {
diff --git a/core/java/android/content/res/FontScaleConverterFactory.java b/core/java/android/content/res/FontScaleConverterFactory.java
index 6b09c303e3cd..5eb65262918d 100644
--- a/core/java/android/content/res/FontScaleConverterFactory.java
+++ b/core/java/android/content/res/FontScaleConverterFactory.java
@@ -34,6 +34,8 @@ public class FontScaleConverterFactory {
@VisibleForTesting
static final SparseArray<FontScaleConverter> LOOKUP_TABLES = new SparseArray<>();
+ private static float sMinScaleBeforeCurvesApplied = 1.05f;
+
static {
// These were generated by frameworks/base/tools/fonts/font-scaling-array-generator.js and
// manually tweaked for optimum readability.
@@ -82,11 +84,30 @@ public class FontScaleConverterFactory {
new float[] { 16f, 20f, 24f, 26f, 30f, 34f, 36f, 38f, 100})
);
+ sMinScaleBeforeCurvesApplied = getScaleFromKey(LOOKUP_TABLES.keyAt(0)) - 0.02f;
+ if (sMinScaleBeforeCurvesApplied <= 1.0f) {
+ throw new IllegalStateException(
+ "You should only apply non-linear scaling to font scales > 1"
+ );
+ }
}
private FontScaleConverterFactory() {}
/**
+ * Returns true if non-linear font scaling curves would be in effect for the given scale, false
+ * if the scaling would follow a linear curve or for no scaling.
+ *
+ * <p>Example usage:
+ * <code>isNonLinearFontScalingActive(getResources().getConfiguration().fontScale)</code>
+ *
+ * @hide
+ */
+ public static boolean isNonLinearFontScalingActive(float fontScale) {
+ return fontScale >= sMinScaleBeforeCurvesApplied;
+ }
+
+ /**
* Finds a matching FontScaleConverter for the given fontScale factor.
*
* @param fontScale the scale factor, usually from {@link Configuration#fontScale}.
@@ -97,10 +118,7 @@ public class FontScaleConverterFactory {
*/
@Nullable
public static FontScaleConverter forScale(float fontScale) {
- if (fontScale <= 1) {
- // We don't need non-linear curves for shrinking text or for 100%.
- // Also, fontScale==0 should not have a curve either.
- // And ignore negative font scales; that's just silly.
+ if (!isNonLinearFontScalingActive(fontScale)) {
return null;
}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 2fec02f91e39..a0cceae98ba9 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -39,7 +39,6 @@ import android.os.InputEventInjectionSync;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Vibrator;
-import android.sysprop.InputProperties;
import android.util.Log;
import android.view.Display;
import android.view.InputDevice;
@@ -1038,9 +1037,7 @@ public final class InputManager {
*/
public boolean isStylusPointerIconEnabled() {
if (mIsStylusPointerIconEnabled == null) {
- mIsStylusPointerIconEnabled = mContext.getResources()
- .getBoolean(com.android.internal.R.bool.config_enableStylusPointerIcon)
- || InputProperties.force_enable_stylus_pointer_icon().orElse(false);
+ mIsStylusPointerIconEnabled = InputSettings.isStylusPointerIconEnabled(mContext);
}
return mIsStylusPointerIconEnabled;
}
diff --git a/core/java/android/hardware/input/InputManagerGlobal.java b/core/java/android/hardware/input/InputManagerGlobal.java
index 5462171be7e1..c0877d3ad8e2 100644
--- a/core/java/android/hardware/input/InputManagerGlobal.java
+++ b/core/java/android/hardware/input/InputManagerGlobal.java
@@ -1252,7 +1252,7 @@ public final class InputManagerGlobal {
/**
* @see InputManager#requestPointerCapture(IBinder, boolean)
*/
- void requestPointerCapture(IBinder windowToken, boolean enable) {
+ public void requestPointerCapture(IBinder windowToken, boolean enable) {
try {
mIm.requestPointerCapture(windowToken, enable);
} catch (RemoteException ex) {
diff --git a/core/java/android/hardware/input/InputSettings.java b/core/java/android/hardware/input/InputSettings.java
index cdf9ea5131ba..6cd32ff1e8e5 100644
--- a/core/java/android/hardware/input/InputSettings.java
+++ b/core/java/android/hardware/input/InputSettings.java
@@ -25,6 +25,7 @@ import android.annotation.TestApi;
import android.content.Context;
import android.os.UserHandle;
import android.provider.Settings;
+import android.sysprop.InputProperties;
/**
* InputSettings encapsulates reading and writing settings related to input
@@ -316,4 +317,15 @@ public class InputSettings {
Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE, enabled ? 1 : 0,
UserHandle.USER_CURRENT);
}
+
+ /**
+ * Whether a pointer icon will be shown over the location of a
+ * stylus pointer.
+ * @hide
+ */
+ public static boolean isStylusPointerIconEnabled(@NonNull Context context) {
+ return context.getResources()
+ .getBoolean(com.android.internal.R.bool.config_enableStylusPointerIcon)
+ || InputProperties.force_enable_stylus_pointer_icon().orElse(false);
+ }
}
diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java
index b93e3386b7cc..330a9fce1b83 100644
--- a/core/java/android/util/TypedValue.java
+++ b/core/java/android/util/TypedValue.java
@@ -385,10 +385,22 @@ public class TypedValue {
*
* @return The complex unit type.
*/
- public int getComplexUnit()
- {
- return COMPLEX_UNIT_MASK & (data>>TypedValue.COMPLEX_UNIT_SHIFT);
- }
+ public int getComplexUnit() {
+ return getUnitFromComplexDimension(data);
+ }
+
+ /**
+ * Return the complex unit type for the given complex dimension. For example, a dimen type
+ * with value 12sp will return {@link #COMPLEX_UNIT_SP}. Use with values created with {@link
+ * #createComplexDimension(int, int)} etc.
+ *
+ * @return The complex unit type.
+ *
+ * @hide
+ */
+ public static int getUnitFromComplexDimension(int complexDimension) {
+ return COMPLEX_UNIT_MASK & (complexDimension >> TypedValue.COMPLEX_UNIT_SHIFT);
+ }
/**
* Converts an unpacked complex data value holding a dimension to its final floating point pixel
diff --git a/core/java/android/view/InputMonitor.java b/core/java/android/view/InputMonitor.java
index 8801fe0b47c8..4996f5a41c82 100644
--- a/core/java/android/view/InputMonitor.java
+++ b/core/java/android/view/InputMonitor.java
@@ -43,7 +43,8 @@ public final class InputMonitor implements Parcelable {
private final InputChannel mInputChannel;
@NonNull
private final IInputMonitorHost mHost;
-
+ @NonNull
+ private final SurfaceControl mSurface;
/**
* Takes all of the current pointer events streams that are currently being sent to this
@@ -70,6 +71,7 @@ public final class InputMonitor implements Parcelable {
*/
public void dispose() {
mInputChannel.dispose();
+ mSurface.release();
try {
mHost.dispose();
} catch (RemoteException e) {
@@ -95,13 +97,17 @@ public final class InputMonitor implements Parcelable {
@DataClass.Generated.Member
public InputMonitor(
@NonNull InputChannel inputChannel,
- @NonNull IInputMonitorHost host) {
+ @NonNull IInputMonitorHost host,
+ @NonNull SurfaceControl surface) {
this.mInputChannel = inputChannel;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mInputChannel);
this.mHost = host;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mHost);
+ this.mSurface = surface;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mSurface);
// onConstructed(); // You can define this method to get a callback
}
@@ -116,6 +122,11 @@ public final class InputMonitor implements Parcelable {
return mHost;
}
+ @DataClass.Generated.Member
+ public @NonNull SurfaceControl getSurface() {
+ return mSurface;
+ }
+
@Override
@DataClass.Generated.Member
public String toString() {
@@ -124,7 +135,8 @@ public final class InputMonitor implements Parcelable {
return "InputMonitor { " +
"inputChannel = " + mInputChannel + ", " +
- "host = " + mHost +
+ "host = " + mHost + ", " +
+ "surface = " + mSurface +
" }";
}
@@ -136,6 +148,7 @@ public final class InputMonitor implements Parcelable {
dest.writeTypedObject(mInputChannel, flags);
dest.writeStrongInterface(mHost);
+ dest.writeTypedObject(mSurface, flags);
}
@Override
@@ -151,6 +164,7 @@ public final class InputMonitor implements Parcelable {
InputChannel inputChannel = (InputChannel) in.readTypedObject(InputChannel.CREATOR);
IInputMonitorHost host = IInputMonitorHost.Stub.asInterface(in.readStrongBinder());
+ SurfaceControl surface = (SurfaceControl) in.readTypedObject(SurfaceControl.CREATOR);
this.mInputChannel = inputChannel;
com.android.internal.util.AnnotationValidations.validate(
@@ -158,6 +172,9 @@ public final class InputMonitor implements Parcelable {
this.mHost = host;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mHost);
+ this.mSurface = surface;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mSurface);
// onConstructed(); // You can define this method to get a callback
}
@@ -177,10 +194,10 @@ public final class InputMonitor implements Parcelable {
};
@DataClass.Generated(
- time = 1637697281750L,
+ time = 1679692514588L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/view/InputMonitor.java",
- inputSignatures = "private static final java.lang.String TAG\nprivate static final boolean DEBUG\nprivate final @android.annotation.NonNull android.view.InputChannel mInputChannel\nprivate final @android.annotation.NonNull android.view.IInputMonitorHost mHost\npublic void pilferPointers()\npublic void dispose()\nclass InputMonitor extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true)")
+ inputSignatures = "private static final java.lang.String TAG\nprivate static final boolean DEBUG\nprivate final @android.annotation.NonNull android.view.InputChannel mInputChannel\nprivate final @android.annotation.NonNull android.view.IInputMonitorHost mHost\nprivate final @android.annotation.NonNull android.view.SurfaceControl mSurface\npublic void pilferPointers()\npublic void dispose()\nclass InputMonitor extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index bd6224b07b16..d9872174f9be 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -410,6 +410,13 @@ public class SurfaceControlViewHost {
}
/**
+ * @hide
+ */
+ public @NonNull AttachedSurfaceControl getRootSurfaceControl() {
+ return mViewRoot;
+ }
+
+ /**
* Set the root view of the SurfaceControlViewHost. This view will render in to
* the SurfaceControl, and receive input based on the SurfaceControls positioning on
* screen. It will be laid as if it were in a window of the passed in width and height.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 86e7fb09c5ea..2b29e7878a5d 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -133,7 +133,9 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
-import android.hardware.input.InputManager;
+import android.hardware.display.DisplayManagerGlobal;
+import android.hardware.input.InputManagerGlobal;
+import android.hardware.input.InputSettings;
import android.media.AudioManager;
import android.os.Binder;
import android.os.Build;
@@ -443,9 +445,7 @@ public final class ViewRootImpl implements ViewParent,
@UnsupportedAppUsage
final IWindowSession mWindowSession;
@NonNull Display mDisplay;
- final DisplayManager mDisplayManager;
final String mBasePackageName;
- final InputManager mInputManager;
final int[] mTmpLocation = new int[2];
@@ -550,6 +550,9 @@ public final class ViewRootImpl implements ViewParent,
// Whether to draw this surface as DISPLAY_DECORATION.
boolean mDisplayDecorationCached = false;
+ // Is the stylus pointer icon enabled
+ private final boolean mIsStylusPointerIconEnabled;
+
/**
* Update the Choreographer's FrameInfo object with the timing information for the current
* ViewRootImpl instance. Erase the data in the current ViewFrameInfo to prepare for the next
@@ -994,14 +997,14 @@ public final class ViewRootImpl implements ViewParent,
mFallbackEventHandler = new PhoneFallbackEventHandler(context);
// TODO(b/222696368): remove getSfInstance usage and use vsyncId for transactions
mChoreographer = Choreographer.getInstance();
- mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
- mInputManager = context.getSystemService(InputManager.class);
mInsetsController = new InsetsController(new ViewRootInsetsControllerHost(this));
mHandwritingInitiator = new HandwritingInitiator(
mViewConfiguration,
mContext.getSystemService(InputMethodManager.class));
mViewBoundsSandboxingEnabled = getViewBoundsSandboxingEnabled();
+ mIsStylusPointerIconEnabled =
+ InputSettings.isStylusPointerIconEnabled(mContext);
String processorOverrideName = context.getResources().getString(
R.string.config_inputEventCompatProcessorOverrideClassName);
@@ -1488,7 +1491,14 @@ public final class ViewRootImpl implements ViewParent,
mAccessibilityInteractionConnectionManager, mHandler);
mAccessibilityManager.addHighTextContrastStateChangeListener(
mHighContrastTextManager, mHandler);
- mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
+ DisplayManagerGlobal
+ .getInstance()
+ .registerDisplayListener(
+ mDisplayListener,
+ mHandler,
+ DisplayManager.EVENT_FLAG_DISPLAY_ADDED
+ | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
}
/**
@@ -1499,7 +1509,9 @@ public final class ViewRootImpl implements ViewParent,
mAccessibilityInteractionConnectionManager);
mAccessibilityManager.removeHighTextContrastStateChangeListener(
mHighContrastTextManager);
- mDisplayManager.unregisterDisplayListener(mDisplayListener);
+ DisplayManagerGlobal
+ .getInstance()
+ .unregisterDisplayListener(mDisplayListener);
}
private void setTag() {
@@ -5382,7 +5394,9 @@ public final class ViewRootImpl implements ViewParent,
Log.e(mTag, "No input channel to request Pointer Capture.");
return;
}
- mInputManager.requestPointerCapture(inputToken, enabled);
+ InputManagerGlobal
+ .getInstance()
+ .requestPointerCapture(inputToken, enabled);
}
private void handlePointerCaptureChanged(boolean hasCapture) {
@@ -6947,7 +6961,7 @@ public final class ViewRootImpl implements ViewParent,
}
final boolean needsStylusPointerIcon = event.isStylusPointer()
&& event.isHoverEvent()
- && mInputManager.isStylusPointerIconEnabled();
+ && mIsStylusPointerIconEnabled;
if (needsStylusPointerIcon || event.isFromSource(InputDevice.SOURCE_MOUSE)) {
if (event.getActionMasked() == MotionEvent.ACTION_HOVER_ENTER
|| event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT) {
@@ -7018,8 +7032,7 @@ public final class ViewRootImpl implements ViewParent,
}
PointerIcon pointerIcon = null;
-
- if (event.isStylusPointer() && mInputManager.isStylusPointerIconEnabled()) {
+ if (event.isStylusPointer() && mIsStylusPointerIconEnabled) {
pointerIcon = mHandwritingInitiator.onResolvePointerIcon(mContext, event);
}
@@ -7034,14 +7047,18 @@ public final class ViewRootImpl implements ViewParent,
mPointerIconType = pointerType;
mCustomPointerIcon = null;
if (mPointerIconType != PointerIcon.TYPE_CUSTOM) {
- mInputManager.setPointerIconType(pointerType);
+ InputManagerGlobal
+ .getInstance()
+ .setPointerIconType(pointerType);
return true;
}
}
if (mPointerIconType == PointerIcon.TYPE_CUSTOM &&
!pointerIcon.equals(mCustomPointerIcon)) {
mCustomPointerIcon = pointerIcon;
- mInputManager.setCustomPointerIcon(mCustomPointerIcon);
+ InputManagerGlobal
+ .getInstance()
+ .setCustomPointerIcon(mCustomPointerIcon);
}
return true;
}
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index a5e708642c9f..b65c1a17e26b 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -845,11 +845,7 @@ public class ScrollView extends FrameLayout {
// Calling overScrollBy will call onOverScrolled, which
// calls onScrollChanged if applicable.
- if (overScrollBy(0, deltaY, 0, mScrollY, 0, range, 0, mOverscrollDistance, true)
- && !hasNestedScrollingParent()) {
- // Break our velocity if we hit a scroll barrier.
- mVelocityTracker.clear();
- }
+ overScrollBy(0, deltaY, 0, mScrollY, 0, range, 0, mOverscrollDistance, true);
final int scrolledDeltaY = mScrollY - oldY;
final int unconsumedY = deltaY - scrolledDeltaY;
@@ -894,6 +890,7 @@ public class ScrollView extends FrameLayout {
mActivePointerId = INVALID_POINTER;
endDrag();
+ velocityTracker.clear();
}
break;
case MotionEvent.ACTION_CANCEL:
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 67c9f8ca0048..3fbb50581b25 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -62,6 +62,7 @@ import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
+import android.content.res.FontScaleConverterFactory;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
@@ -867,6 +868,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@UnsupportedAppUsage
private float mSpacingAdd = 0.0f;
+ /**
+ * Remembers what line height was set to originally, before we broke it down into raw pixels.
+ *
+ * <p>This is stored as a complex dimension with both value and unit packed into one field!
+ * {@see TypedValue}
+ */
+ private int mLineHeightComplexDimen;
+
private int mBreakStrategy;
private int mHyphenationFrequency;
private int mJustificationMode;
@@ -1233,7 +1242,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
defStyleAttr, defStyleRes);
int firstBaselineToTopHeight = -1;
int lastBaselineToBottomHeight = -1;
- int lineHeight = -1;
+ float lineHeight = -1f;
+ int lineHeightUnit = -1;
readTextAppearance(context, a, attributes, true /* styleArray */);
@@ -1583,7 +1593,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
break;
case com.android.internal.R.styleable.TextView_lineHeight:
- lineHeight = a.getDimensionPixelSize(attr, -1);
+ TypedValue peekValue = a.peekValue(attr);
+ if (peekValue != null && peekValue.type == TypedValue.TYPE_DIMENSION) {
+ lineHeightUnit = peekValue.getComplexUnit();
+ lineHeight = TypedValue.complexToFloat(peekValue.data);
+ } else {
+ lineHeight = a.getDimensionPixelSize(attr, -1);
+ }
break;
}
}
@@ -1936,7 +1952,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
setLastBaselineToBottomHeight(lastBaselineToBottomHeight);
}
if (lineHeight >= 0) {
- setLineHeight(lineHeight);
+ if (lineHeightUnit == -1) {
+ setLineHeightPx(lineHeight);
+ } else {
+ setLineHeight(lineHeightUnit, lineHeight);
+ }
}
}
@@ -4629,6 +4649,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (size != mTextPaint.getTextSize()) {
mTextPaint.setTextSize(size);
+ maybeRecalculateLineHeight();
if (shouldRequestLayout && mLayout != null) {
// Do not auto-size right after setting the text size.
mNeedsAutoSizeText = false;
@@ -6214,6 +6235,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (lineHeight != fontHeight) {
// Set lineSpacingExtra by the difference of lineSpacing with lineHeight
setLineSpacing(lineHeight - fontHeight, 1f);
+
+ mLineHeightComplexDimen =
+ TypedValue.createComplexDimension(lineHeight, TypedValue.COMPLEX_UNIT_PX);
}
}
@@ -6236,8 +6260,54 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@TypedValue.ComplexDimensionUnit int unit,
@FloatRange(from = 0) float lineHeight
) {
- setLineHeightPx(
- TypedValue.applyDimension(unit, lineHeight, getDisplayMetricsOrSystem()));
+ var metrics = getDisplayMetricsOrSystem();
+ // We can avoid the recalculation if we know non-linear font scaling isn't being used
+ // (an optimization for the majority case).
+ // We also don't try to do the recalculation unless both textSize and lineHeight are in SP.
+ if (!FontScaleConverterFactory.isNonLinearFontScalingActive(
+ getResources().getConfiguration().fontScale)
+ || unit != TypedValue.COMPLEX_UNIT_SP
+ || mTextSizeUnit != TypedValue.COMPLEX_UNIT_SP
+ ) {
+ setLineHeightPx(TypedValue.applyDimension(unit, lineHeight, metrics));
+
+ // Do this last so it overwrites what setLineHeightPx() sets it to.
+ mLineHeightComplexDimen = TypedValue.createComplexDimension(lineHeight, unit);
+ return;
+ }
+
+ // Recalculate a proportional line height when non-linear font scaling is in effect.
+ // Otherwise, a desired 2x line height at font scale 1.0 will not be 2x at font scale 2.0,
+ // due to non-linear font scaling compressing higher SP sizes. See b/273326061 for details.
+ // We know they are using SP units for both the text size and the line height
+ // at this point, so determine the ratio between them. This is the *intended* line spacing
+ // multiplier if font scale == 1.0. We can then determine what the pixel value for the line
+ // height would be if we preserved proportions.
+ var textSizePx = getTextSize();
+ var textSizeSp = TypedValue.convertPixelsToDimension(
+ TypedValue.COMPLEX_UNIT_SP,
+ textSizePx,
+ metrics
+ );
+ var ratio = lineHeight / textSizeSp;
+ setLineHeightPx(textSizePx * ratio);
+
+ // Do this last so it overwrites what setLineHeightPx() sets it to.
+ mLineHeightComplexDimen = TypedValue.createComplexDimension(lineHeight, unit);
+ }
+
+ private void maybeRecalculateLineHeight() {
+ if (mLineHeightComplexDimen == 0) {
+ return;
+ }
+ int unit = TypedValue.getUnitFromComplexDimension(mLineHeightComplexDimen);
+ if (unit != TypedValue.COMPLEX_UNIT_SP) {
+ // The lineHeight was never supplied in SP, so we didn't do any fancy recalculations
+ // in setLineHeight(). We don't need to recalculate.
+ return;
+ }
+
+ setLineHeight(unit, TypedValue.complexToFloat(mLineHeightComplexDimen));
}
/**
diff --git a/core/java/com/android/internal/policy/DecorContext.java b/core/java/com/android/internal/policy/DecorContext.java
index 134a91710c0b..efaedd1073d6 100644
--- a/core/java/com/android/internal/policy/DecorContext.java
+++ b/core/java/com/android/internal/policy/DecorContext.java
@@ -82,13 +82,6 @@ public class DecorContext extends ContextThemeWrapper {
}
return mContentCaptureManager;
}
- // TODO(b/154191411): Try to revisit this issue in S.
- // We use application to get DisplayManager here because ViewRootImpl holds reference of
- // DisplayManager and implicitly holds reference of mContext, which makes activity cannot
- // be GC'd even after destroyed if mContext is an activity object.
- if (Context.DISPLAY_SERVICE.equals(name)) {
- return super.getSystemService(name);
- }
// LayoutInflater and WallpaperManagerService should also be obtained from visual context
// instead of base context.
return (context != null) ? context.getSystemService(name) : super.getSystemService(name);
diff --git a/core/java/com/android/internal/util/QuickSelect.java b/core/java/com/android/internal/util/QuickSelect.java
new file mode 100644
index 000000000000..17739c9c8832
--- /dev/null
+++ b/core/java/com/android/internal/util/QuickSelect.java
@@ -0,0 +1,256 @@
+/*
+ * 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.internal.util;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * An implementation of the quick selection algorithm as described in
+ * http://en.wikipedia.org/wiki/Quickselect.
+ *
+ * @hide
+ */
+public final class QuickSelect {
+ private static <T> int selectImpl(@NonNull List<T> list, int left, int right, int k,
+ @NonNull Comparator<? super T> comparator) {
+ while (true) {
+ if (left == right) {
+ return left;
+ }
+ final int pivotIndex = partition(list, left, right, (left + right) >> 1, comparator);
+ if (k == pivotIndex) {
+ return k;
+ } else if (k < pivotIndex) {
+ right = pivotIndex - 1;
+ } else {
+ left = pivotIndex + 1;
+ }
+ }
+ }
+
+ private static int selectImpl(@NonNull int[] array, int left, int right, int k) {
+ while (true) {
+ if (left == right) {
+ return left;
+ }
+ final int pivotIndex = partition(array, left, right, (left + right) >> 1);
+ if (k == pivotIndex) {
+ return k;
+ } else if (k < pivotIndex) {
+ right = pivotIndex - 1;
+ } else {
+ left = pivotIndex + 1;
+ }
+ }
+ }
+
+ private static int selectImpl(@NonNull long[] array, int left, int right, int k) {
+ while (true) {
+ if (left == right) {
+ return left;
+ }
+ final int pivotIndex = partition(array, left, right, (left + right) >> 1);
+ if (k == pivotIndex) {
+ return k;
+ } else if (k < pivotIndex) {
+ right = pivotIndex - 1;
+ } else {
+ left = pivotIndex + 1;
+ }
+ }
+ }
+
+ private static <T> int selectImpl(@NonNull T[] array, int left, int right, int k,
+ @NonNull Comparator<? super T> comparator) {
+ while (true) {
+ if (left == right) {
+ return left;
+ }
+ final int pivotIndex = partition(array, left, right, (left + right) >> 1, comparator);
+ if (k == pivotIndex) {
+ return k;
+ } else if (k < pivotIndex) {
+ right = pivotIndex - 1;
+ } else {
+ left = pivotIndex + 1;
+ }
+ }
+ }
+
+ private static <T> int partition(@NonNull List<T> list, int left, int right, int pivotIndex,
+ @NonNull Comparator<? super T> comparator) {
+ final T pivotValue = list.get(pivotIndex);
+ swap(list, right, pivotIndex);
+ int storeIndex = left;
+ for (int i = left; i < right; i++) {
+ if (comparator.compare(list.get(i), pivotValue) < 0) {
+ swap(list, storeIndex, i);
+ storeIndex++;
+ }
+ }
+ swap(list, right, storeIndex);
+ return storeIndex;
+ }
+
+ private static int partition(@NonNull int[] array, int left, int right, int pivotIndex) {
+ final int pivotValue = array[pivotIndex];
+ swap(array, right, pivotIndex);
+ int storeIndex = left;
+ for (int i = left; i < right; i++) {
+ if (array[i] < pivotValue) {
+ swap(array, storeIndex, i);
+ storeIndex++;
+ }
+ }
+ swap(array, right, storeIndex);
+ return storeIndex;
+ }
+
+ private static int partition(@NonNull long[] array, int left, int right, int pivotIndex) {
+ final long pivotValue = array[pivotIndex];
+ swap(array, right, pivotIndex);
+ int storeIndex = left;
+ for (int i = left; i < right; i++) {
+ if (array[i] < pivotValue) {
+ swap(array, storeIndex, i);
+ storeIndex++;
+ }
+ }
+ swap(array, right, storeIndex);
+ return storeIndex;
+ }
+
+ private static <T> int partition(@NonNull T[] array, int left, int right, int pivotIndex,
+ @NonNull Comparator<? super T> comparator) {
+ final T pivotValue = array[pivotIndex];
+ swap(array, right, pivotIndex);
+ int storeIndex = left;
+ for (int i = left; i < right; i++) {
+ if (comparator.compare(array[i], pivotValue) < 0) {
+ swap(array, storeIndex, i);
+ storeIndex++;
+ }
+ }
+ swap(array, right, storeIndex);
+ return storeIndex;
+ }
+
+ private static <T> void swap(@NonNull List<T> list, int left, int right) {
+ final T tmp = list.get(left);
+ list.set(left, list.get(right));
+ list.set(right, tmp);
+ }
+
+ private static void swap(@NonNull int[] array, int left, int right) {
+ final int tmp = array[left];
+ array[left] = array[right];
+ array[right] = tmp;
+ }
+
+ private static void swap(@NonNull long[] array, int left, int right) {
+ final long tmp = array[left];
+ array[left] = array[right];
+ array[right] = tmp;
+ }
+
+ private static <T> void swap(@NonNull T[] array, int left, int right) {
+ final T tmp = array[left];
+ array[left] = array[right];
+ array[right] = tmp;
+ }
+
+ /**
+ * Return the kth(0-based) smallest element from the given unsorted list.
+ *
+ * @param list The input list, it <b>will</b> be modified by the algorithm here.
+ * @param start The start offset of the list, inclusive.
+ * @param length The length of the sub list to be searched in.
+ * @param k The 0-based index.
+ * @param comparator The comparator which knows how to compare the elements in the list.
+ * @return The kth smallest element from the given list,
+ * or IllegalArgumentException will be thrown if not found.
+ */
+ @Nullable
+ public static <T> T select(@NonNull List<T> list, int start, int length, int k,
+ @NonNull Comparator<? super T> comparator) {
+ if (list == null || start < 0 || length <= 0 || list.size() < start + length
+ || k < 0 || length <= k) {
+ throw new IllegalArgumentException();
+ }
+ return list.get(selectImpl(list, start, start + length - 1, k + start, comparator));
+ }
+
+ /**
+ * Return the kth(0-based) smallest element from the given unsorted array.
+ *
+ * @param array The input array, it <b>will</b> be modified by the algorithm here.
+ * @param start The start offset of the array, inclusive.
+ * @param length The length of the sub array to be searched in.
+ * @param k The 0-based index to search for.
+ * @return The kth smallest element from the given array,
+ * or IllegalArgumentException will be thrown if not found.
+ */
+ public static int select(@NonNull int[] array, int start, int length, int k) {
+ if (array == null || start < 0 || length <= 0 || array.length < start + length
+ || k < 0 || length <= k) {
+ throw new IllegalArgumentException();
+ }
+ return array[selectImpl(array, start, start + length - 1, k + start)];
+ }
+
+ /**
+ * Return the kth(0-based) smallest element from the given unsorted array.
+ *
+ * @param array The input array, it <b>will</b> be modified by the algorithm here.
+ * @param start The start offset of the array, inclusive.
+ * @param length The length of the sub array to be searched in.
+ * @param k The 0-based index to search for.
+ * @return The kth smallest element from the given array,
+ * or IllegalArgumentException will be thrown if not found.
+ */
+ public static long select(@NonNull long[] array, int start, int length, int k) {
+ if (array == null || start < 0 || length <= 0 || array.length < start + length
+ || k < 0 || length <= k) {
+ throw new IllegalArgumentException();
+ }
+ return array[selectImpl(array, start, start + length - 1, k + start)];
+ }
+
+ /**
+ * Return the kth(0-based) smallest element from the given unsorted array.
+ *
+ * @param array The input array, it <b>will</b> be modified by the algorithm here.
+ * @param start The start offset of the array, inclusive.
+ * @param length The length of the sub array to be searched in.
+ * @param k The 0-based index to search for.
+ * @param comparator The comparator which knows how to compare the elements in the list.
+ * @return The kth smallest element from the given array,
+ * or IllegalArgumentException will be thrown if not found.
+ */
+ public static <T> T select(@NonNull T[] array, int start, int length, int k,
+ @NonNull Comparator<? super T> comparator) {
+ if (array == null || start < 0 || length <= 0 || array.length < start + length
+ || k < 0 || length <= k) {
+ throw new IllegalArgumentException();
+ }
+ return array[selectImpl(array, start, start + length - 1, k + start, comparator)];
+ }
+}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 6bec6bc236bd..42d68960cafd 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -334,7 +334,7 @@ cc_library_shared {
"libtimeinstate",
"server_configurable_flags",
"libimage_io",
- "libjpegrecoverymap",
+ "libultrahdr",
],
export_shared_lib_headers: [
// our headers include libnativewindow's public headers
@@ -393,7 +393,7 @@ cc_library_shared {
"libimage_io",
"libjpegdecoder",
"libjpegencoder",
- "libjpegrecoverymap",
+ "libultrahdr",
],
},
host_linux: {
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index bb3089bb397a..325ebbe885b4 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -458,6 +458,7 @@ message WindowStateProto {
optional float global_scale = 44;
repeated .android.graphics.RectProto keep_clear_areas = 45;
repeated .android.graphics.RectProto unrestricted_keep_clear_areas = 46;
+ repeated .android.view.InsetsSourceProto mergedLocalInsetsSources = 47;
}
message IdentifierProto {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 05b38a562e29..e62477f0dbe3 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1466,6 +1466,9 @@
<!-- Allows an application to initiate a phone call without going through
the Dialer user interface for the user to confirm the call.
+ <p>
+ <em>Note: An app holding this permission can also call carrier MMI codes to change settings
+ such as call forwarding or call waiting preferences.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.CALL_PHONE"
@@ -2917,6 +2920,14 @@
<permission android:name="android.permission.BIND_SATELLITE_SERVICE"
android:protectionLevel="signature|privileged|vendorPrivileged" />
+ <!-- Must be required by a SatelliteGatewayService to ensure that only the
+ system can bind to it.
+ <p>Protection level: signature
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_SATELLITE_GATEWAY_SERVICE"
+ android:protectionLevel="signature" />
+
<!-- Must be required by a telephony data service to ensure that only the
system can bind to it.
<p>Protection level: signature
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index fab760948787..a57a0517c58d 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -125,6 +125,10 @@
<string name="config_satellite_service_package" translatable="false"></string>
<java-symbol type="string" name="config_satellite_service_package" />
+ <!-- Telephony satellite gateway service package name to bind to by default. -->
+ <string name="config_satellite_gateway_service_package" translatable="false"></string>
+ <java-symbol type="string" name="config_satellite_gateway_service_package" />
+
<!-- Telephony pointing UI package name to be launched. -->
<string name="config_pointing_ui_package" translatable="false"></string>
<java-symbol type="string" name="config_pointing_ui_package" />
@@ -142,10 +146,6 @@
<bool name="config_enhanced_iwlan_handover_check">true</bool>
<java-symbol type="bool" name="config_enhanced_iwlan_handover_check" />
- <!-- Whether using the new SubscriptionManagerService or the old SubscriptionController -->
- <bool name="config_using_subscription_manager_service">true</bool>
- <java-symbol type="bool" name="config_using_subscription_manager_service" />
-
<!-- Whether asynchronously update the subscription database or not. Async mode increases
the performance, but sync mode reduces the chance of database/cache out-of-sync. -->
<bool name="config_subscription_database_async_update">true</bool>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 362d8596ebb8..b0932d60c39a 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1452,7 +1452,8 @@
without your intervention. This may result in unexpected charges or calls.
Note that this doesn\'t allow the app to call emergency numbers.
Malicious apps may cost you money by making calls without your
- confirmation.</string>
+ confirmation, or dial carrier codes which cause incoming calls to be
+ automatically forwarded to another number.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_accessImsCallService">access IMS call service</string>
diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
index a0d8dcf830e8..ba6c8fab48d4 100644
--- a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
+++ b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
@@ -122,6 +122,22 @@ class FontScaleConverterFactoryTest {
}
}
+ @SmallTest
+ fun testIsNonLinearFontScalingActive() {
+ assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1f)).isFalse()
+ assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(0f)).isFalse()
+ assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(-1f)).isFalse()
+ assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(0.85f)).isFalse()
+ assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1.02f)).isFalse()
+ assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1.10f)).isFalse()
+ assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1.15f)).isTrue()
+ assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1.1499999f))
+ .isTrue()
+ assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1.5f)).isTrue()
+ assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(2f)).isTrue()
+ assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(3f)).isTrue()
+ }
+
@LargeTest
@Test
fun allFeasibleScalesAndConversionsDoNotCrash() {
diff --git a/core/tests/utiltests/src/com/android/internal/util/QuickSelectTest.java b/core/tests/utiltests/src/com/android/internal/util/QuickSelectTest.java
new file mode 100644
index 000000000000..1b9d2ef58c10
--- /dev/null
+++ b/core/tests/utiltests/src/com/android/internal/util/QuickSelectTest.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 com.android.internal.util;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Tests for {@link QuickSelect}.
+ */
+public final class QuickSelectTest extends TestCase {
+
+ public void testQuickSelect() throws Exception {
+ test((List<Integer>) null, 0, null);
+ test(Arrays.asList(), -1, null);
+ test(Arrays.asList(), 0, null);
+ test(Arrays.asList(), 1, null);
+ test(Arrays.asList(1), -1, 1, 0, null);
+ test(Arrays.asList(1), 1, -1, 0, null);
+ test(Arrays.asList(1), 0, 1, -1, null);
+ test(Arrays.asList(1), 1, 1, 0, null);
+ test(Arrays.asList(1), 0, 1);
+ test(Arrays.asList(1), 1, null);
+ test(Arrays.asList(1, 2, 3, 4, 5), 0, 1);
+ test(Arrays.asList(1, 2, 3, 4, 5), 1, 2);
+ test(Arrays.asList(1, 2, 3, 4, 5), 2, 3);
+ test(Arrays.asList(1, 2, 3, 4, 5), 3, 4);
+ test(Arrays.asList(1, 2, 3, 4, 5), 4, 5);
+ test(Arrays.asList(1, 2, 3, 4, 5), 5, null);
+ test(Arrays.asList(7, 10, 4, 3, 20, 15, 8, 9), 2, 7);
+ test(Arrays.asList(7, 10, 4, 3, 20, 15, 8, 9), 4, 9);
+ test(Arrays.asList(7, 10, 4, 3, 20, 15, 8, 9), 7, 20);
+ test(Arrays.asList(7, 10, 4, 3, 20, 15, 8, 9), 8, null);
+ test(Arrays.asList(7, 10, 4, 3, 20, 15, 8, 9), 1, 3, 0, 3);
+ test(Arrays.asList(7, 10, 4, 3, 20, 15, 8, 9), 1, 3, 1, 4);
+ test(Arrays.asList(7, 10, 4, 3, 20, 15, 8, 9), 1, 3, 2, 10);
+ test(Arrays.asList(7, 10, 4, 3, 20, 15, 8, 9), 1, 3, 3, null);
+
+ test((int[]) null, 0, null);
+ test(new int[0], -1, null);
+ test(new int[0], 0, null);
+ test(new int[0], 1, null);
+ test(new int[] {1}, -1, 1, 0, null);
+ test(new int[] {1}, 1, -1, 0, null);
+ test(new int[] {1}, 1, 0, -1, null);
+ test(new int[] {1}, 1, 1, 0, null);
+ test(new int[] {1}, 0, 1);
+ test(new int[] {1}, 1, null);
+ test(new int[] {1, 2, 3, 4, 5}, 0, 1);
+ test(new int[] {1, 2, 3, 4, 5}, 1, 2);
+ test(new int[] {1, 2, 3, 4, 5}, 2, 3);
+ test(new int[] {1, 2, 3, 4, 5}, 3, 4);
+ test(new int[] {1, 2, 3, 4, 5}, 4, 5);
+ test(new int[] {1, 2, 3, 4, 5}, 5, null);
+ test(new int[] {7, 10, 4, 3, 20, 15, 8, 9}, 2, 7);
+ test(new int[] {7, 10, 4, 3, 20, 15, 8, 9}, 4, 9);
+ test(new int[] {7, 10, 4, 3, 20, 15, 8, 9}, 7, 20);
+ test(new int[] {7, 10, 4, 3, 20, 15, 8, 9}, 8, null);
+ test(new int[] {7, 10, 4, 3, 20, 15, 8, 9}, 1, 3, 0, 3);
+ test(new int[] {7, 10, 4, 3, 20, 15, 8, 9}, 1, 3, 1, 4);
+ test(new int[] {7, 10, 4, 3, 20, 15, 8, 9}, 1, 3, 2, 10);
+ test(new int[] {7, 10, 4, 3, 20, 15, 8, 9}, 1, 3, 3, null);
+
+ test((long[]) null, 0, null);
+ test(new long[0], -1, null);
+ test(new long[0], 0, null);
+ test(new long[0], 1, null);
+ test(new long[] {1}, -1, 1, 0, null);
+ test(new long[] {1}, 1, -1, 0, null);
+ test(new long[] {1}, 1, 0, -1, null);
+ test(new long[] {1}, 1, 1, 0, null);
+ test(new long[] {1}, 0, 1L);
+ test(new long[] {1}, 1, null);
+ test(new long[] {1, 2, 3, 4, 5}, 0, 1L);
+ test(new long[] {1, 2, 3, 4, 5}, 1, 2L);
+ test(new long[] {1, 2, 3, 4, 5}, 2, 3L);
+ test(new long[] {1, 2, 3, 4, 5}, 3, 4L);
+ test(new long[] {1, 2, 3, 4, 5}, 4, 5L);
+ test(new long[] {1, 2, 3, 4, 5}, 5, null);
+ test(new long[] {7, 10, 4, 3, 20, 15, 8, 9}, 2, 7L);
+ test(new long[] {7, 10, 4, 3, 20, 15, 8, 9}, 4, 9L);
+ test(new long[] {7, 10, 4, 3, 20, 15, 8, 9}, 7, 20L);
+ test(new long[] {7, 10, 4, 3, 20, 15, 8, 9}, 8, null);
+ test(new long[] {7, 10, 4, 3, 20, 15, 8, 9}, 1, 3, 0, 3L);
+ test(new long[] {7, 10, 4, 3, 20, 15, 8, 9}, 1, 3, 1, 4L);
+ test(new long[] {7, 10, 4, 3, 20, 15, 8, 9}, 1, 3, 2, 10L);
+ test(new long[] {7, 10, 4, 3, 20, 15, 8, 9}, 1, 3, 3, null);
+ }
+
+ private void test(List<Integer> input, int k, Integer expected) throws Exception {
+ test(input, 0, input == null ? 0 : input.size(), k, expected);
+ }
+
+ private void test(List<Integer> input, int start, int length, int k, Integer expected)
+ throws Exception {
+ try {
+ final Integer result = QuickSelect.select(input, start, length, k, Integer::compare);
+ assertEquals(expected, result);
+ } catch (IllegalArgumentException e) {
+ if (expected != null) {
+ throw new Exception(e);
+ }
+ }
+ }
+
+ private void test(int[] input, int k, Integer expected) throws Exception {
+ test(input, 0, input == null ? 0 : input.length, k, expected);
+ }
+
+ private void test(int[] input, int start, int length, int k, Integer expected)
+ throws Exception {
+ try {
+ final int result = QuickSelect.select(input, start, length, k);
+ assertEquals((int) expected, result);
+ } catch (IllegalArgumentException e) {
+ if (expected != null) {
+ throw new Exception(e);
+ }
+ }
+ }
+
+ private void test(long[] input, int k, Long expected) throws Exception {
+ test(input, 0, input == null ? 0 : input.length, k, expected);
+ }
+
+ private void test(long[] input, int start, int length, int k, Long expected) throws Exception {
+ try {
+ final long result = QuickSelect.select(input, start, length, k);
+ assertEquals((long) expected, result);
+ } catch (IllegalArgumentException e) {
+ if (expected != null) {
+ throw new Exception(e);
+ }
+ }
+ }
+}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index ebfa47f9eb23..8ece337971a9 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -122,6 +122,7 @@ applications that come with the platform
<permission name="android.permission.BIND_CARRIER_SERVICES"/>
<permission name="android.permission.BIND_CELL_BROADCAST_SERVICE"/>
<permission name="android.permission.BIND_IMS_SERVICE"/>
+ <permission name="android.permission.BIND_SATELLITE_GATEWAY_SERVICE"/>
<permission name="android.permission.BIND_SATELLITE_SERVICE"/>
<permission name="android.permission.BIND_TELEPHONY_DATA_SERVICE"/>
<permission name="android.permission.BIND_VISUAL_VOICEMAIL_SERVICE"/>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index 79e0a4868cae..d3f395846894 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -64,7 +64,11 @@ import java.util.concurrent.Executor;
public class Bubble implements BubbleViewProvider {
private static final String TAG = "Bubble";
- public static final String KEY_APP_BUBBLE = "key_app_bubble";
+ /** A string suffix used in app bubbles' {@link #mKey}. */
+ private static final String KEY_APP_BUBBLE = "key_app_bubble";
+
+ /** Whether the bubble is an app bubble. */
+ private final boolean mIsAppBubble;
private final String mKey;
@Nullable
@@ -181,7 +185,7 @@ public class Bubble implements BubbleViewProvider {
private PendingIntent mDeleteIntent;
/**
- * Used only for a special bubble in the stack that has the key {@link #KEY_APP_BUBBLE}.
+ * Used only for a special bubble in the stack that has {@link #mIsAppBubble} set to true.
* There can only be one of these bubbles in the stack and this intent will be populated for
* that bubble.
*/
@@ -216,24 +220,54 @@ public class Bubble implements BubbleViewProvider {
mMainExecutor = mainExecutor;
mTaskId = taskId;
mBubbleMetadataFlagListener = listener;
+ mIsAppBubble = false;
}
- public Bubble(Intent intent,
+ private Bubble(
+ Intent intent,
UserHandle user,
@Nullable Icon icon,
+ boolean isAppBubble,
+ String key,
Executor mainExecutor) {
- mKey = KEY_APP_BUBBLE;
mGroupKey = null;
mLocusId = null;
mFlags = 0;
mUser = user;
mIcon = icon;
+ mIsAppBubble = isAppBubble;
+ mKey = key;
mShowBubbleUpdateDot = false;
mMainExecutor = mainExecutor;
mTaskId = INVALID_TASK_ID;
mAppIntent = intent;
mDesiredHeight = Integer.MAX_VALUE;
mPackageName = intent.getPackage();
+
+ }
+
+ /** Creates an app bubble. */
+ public static Bubble createAppBubble(
+ Intent intent,
+ UserHandle user,
+ @Nullable Icon icon,
+ Executor mainExecutor) {
+ return new Bubble(intent,
+ user,
+ icon,
+ /* isAppBubble= */ true,
+ /* key= */ getAppBubbleKeyForApp(intent.getPackage(), user),
+ mainExecutor);
+ }
+
+ /**
+ * Returns the key for an app bubble from an app with package name, {@code packageName} on an
+ * Android user, {@code user}.
+ */
+ public static String getAppBubbleKeyForApp(String packageName, UserHandle user) {
+ Objects.requireNonNull(packageName);
+ Objects.requireNonNull(user);
+ return KEY_APP_BUBBLE + ":" + user.getIdentifier() + ":" + packageName;
}
@VisibleForTesting(visibility = PRIVATE)
@@ -241,6 +275,7 @@ public class Bubble implements BubbleViewProvider {
final Bubbles.BubbleMetadataFlagListener listener,
final Bubbles.PendingIntentCanceledListener intentCancelListener,
Executor mainExecutor) {
+ mIsAppBubble = false;
mKey = entry.getKey();
mGroupKey = entry.getGroupKey();
mLocusId = entry.getLocusId();
@@ -815,7 +850,7 @@ public class Bubble implements BubbleViewProvider {
}
boolean isAppBubble() {
- return KEY_APP_BUBBLE.equals(mKey);
+ return mIsAppBubble;
}
Intent getSettingsIntent(final Context context) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index c407b0624985..21f02b10035b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -24,7 +24,6 @@ import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-import static com.android.wm.shell.bubbles.Bubble.KEY_APP_BUBBLE;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_CONTROLLER;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_GESTURE;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES;
@@ -1193,14 +1192,15 @@ public class BubbleController implements ConfigurationChangeListener,
return;
}
+ String appBubbleKey = Bubble.getAppBubbleKeyForApp(intent.getPackage(), user);
PackageManager packageManager = getPackageManagerForUser(mContext, user.getIdentifier());
- if (!isResizableActivity(intent, packageManager, KEY_APP_BUBBLE)) return;
+ if (!isResizableActivity(intent, packageManager, appBubbleKey)) return;
- Bubble existingAppBubble = mBubbleData.getBubbleInStackWithKey(KEY_APP_BUBBLE);
+ Bubble existingAppBubble = mBubbleData.getBubbleInStackWithKey(appBubbleKey);
if (existingAppBubble != null) {
BubbleViewProvider selectedBubble = mBubbleData.getSelectedBubble();
if (isStackExpanded()) {
- if (selectedBubble != null && KEY_APP_BUBBLE.equals(selectedBubble.getKey())) {
+ if (selectedBubble != null && appBubbleKey.equals(selectedBubble.getKey())) {
// App bubble is expanded, lets collapse
collapseStack();
} else {
@@ -1214,7 +1214,7 @@ public class BubbleController implements ConfigurationChangeListener,
}
} else {
// App bubble does not exist, lets add and expand it
- Bubble b = new Bubble(intent, user, icon, mMainExecutor);
+ Bubble b = Bubble.createAppBubble(intent, user, icon, mMainExecutor);
b.setShouldAutoExpand(true);
inflateAndAdd(b, /* suppressFlyout= */ true, /* showInShade= */ false);
}
@@ -1247,8 +1247,8 @@ public class BubbleController implements ConfigurationChangeListener,
}
/** Sets the app bubble's taskId which is cached for SysUI. */
- public void setAppBubbleTaskId(int taskId) {
- mImpl.mCachedState.setAppBubbleTaskId(taskId);
+ public void setAppBubbleTaskId(String key, int taskId) {
+ mImpl.mCachedState.setAppBubbleTaskId(key, taskId);
}
/**
@@ -2045,7 +2045,8 @@ public class BubbleController implements ConfigurationChangeListener,
private HashSet<String> mSuppressedBubbleKeys = new HashSet<>();
private HashMap<String, String> mSuppressedGroupToNotifKeys = new HashMap<>();
private HashMap<String, Bubble> mShortcutIdToBubble = new HashMap<>();
- private int mAppBubbleTaskId = INVALID_TASK_ID;
+
+ private HashMap<String, Integer> mAppBubbleTaskIds = new HashMap();
private ArrayList<Bubble> mTmpBubbles = new ArrayList<>();
@@ -2077,20 +2078,20 @@ public class BubbleController implements ConfigurationChangeListener,
mSuppressedBubbleKeys.clear();
mShortcutIdToBubble.clear();
- mAppBubbleTaskId = INVALID_TASK_ID;
+ mAppBubbleTaskIds.clear();
for (Bubble b : mTmpBubbles) {
mShortcutIdToBubble.put(b.getShortcutId(), b);
updateBubbleSuppressedState(b);
- if (KEY_APP_BUBBLE.equals(b.getKey())) {
- mAppBubbleTaskId = b.getTaskId();
+ if (b.isAppBubble()) {
+ mAppBubbleTaskIds.put(b.getKey(), b.getTaskId());
}
}
}
/** Sets the app bubble's taskId which is cached for SysUI. */
- synchronized void setAppBubbleTaskId(int taskId) {
- mAppBubbleTaskId = taskId;
+ synchronized void setAppBubbleTaskId(String key, int taskId) {
+ mAppBubbleTaskIds.put(key, taskId);
}
/**
@@ -2143,7 +2144,7 @@ public class BubbleController implements ConfigurationChangeListener,
pw.println(" suppressing: " + key);
}
- pw.print("mAppBubbleTaskId: " + mAppBubbleTaskId);
+ pw.print("mAppBubbleTaskIds: " + mAppBubbleTaskIds.values());
}
}
@@ -2205,7 +2206,7 @@ public class BubbleController implements ConfigurationChangeListener,
@Override
public boolean isAppBubbleTaskId(int taskId) {
- return mCachedState.mAppBubbleTaskId == taskId;
+ return mCachedState.mAppBubbleTaskIds.values().contains(taskId);
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
index 92b969bb6f97..cc8f50e09fcb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
@@ -17,7 +17,6 @@ package com.android.wm.shell.bubbles;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
-import static com.android.wm.shell.bubbles.Bubble.KEY_APP_BUBBLE;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_DATA;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
@@ -780,7 +779,7 @@ public class BubbleData {
|| !(reason == Bubbles.DISMISS_AGED
|| reason == Bubbles.DISMISS_USER_GESTURE
|| reason == Bubbles.DISMISS_RELOAD_FROM_DISK)
- || KEY_APP_BUBBLE.equals(bubble.getKey())) {
+ || bubble.isAppBubble()) {
return;
}
if (DEBUG_BUBBLE_DATA) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index 684a23a198c2..6c482c831152 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -287,9 +287,9 @@ public class BubbleExpandedView extends LinearLayout {
// The taskId is saved to use for removeTask, preventing appearance in recent tasks.
mTaskId = taskId;
- if (Bubble.KEY_APP_BUBBLE.equals(getBubbleKey())) {
+ if (mBubble != null && mBubble.isAppBubble()) {
// Let the controller know sooner what the taskId is.
- mController.setAppBubbleTaskId(mTaskId);
+ mController.setAppBubbleTaskId(mBubble.getKey(), mTaskId);
}
// With the task org, the taskAppeared callback will only happen once the task has
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
index 4970fa0cb087..56616cb6bd88 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
@@ -165,6 +165,10 @@ public class SplitDecorManager extends WindowlessWindowManager {
t.remove(mGapBackgroundLeash);
mGapBackgroundLeash = null;
}
+ if (mScreenshot != null) {
+ t.remove(mScreenshot);
+ mScreenshot = null;
+ }
mHostLeash = null;
mIcon = null;
mResizingIconView = null;
@@ -324,6 +328,8 @@ public class SplitDecorManager extends WindowlessWindowManager {
if (!mShown && mIsResizing && !mOldBounds.equals(mResizingBounds)) {
if (mScreenshotAnimator != null && mScreenshotAnimator.isRunning()) {
mScreenshotAnimator.cancel();
+ } else if (mScreenshot != null) {
+ t.remove(mScreenshot);
}
mTempRect.set(mOldBounds);
@@ -340,6 +346,8 @@ public class SplitDecorManager extends WindowlessWindowManager {
if (!mShown && mIsResizing && !mOldBounds.equals(mResizingBounds)) {
if (mScreenshotAnimator != null && mScreenshotAnimator.isRunning()) {
mScreenshotAnimator.cancel();
+ } else if (mScreenshot != null) {
+ t.remove(mScreenshot);
}
mScreenshot = screenshot;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 24dee5fe5e79..c8062bcf8519 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -146,13 +146,17 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
t.apply();
// execute the runnable if non-null after WCT is applied to finish resizing pip
- if (mPipFinishResizeWCTRunnable != null) {
- mPipFinishResizeWCTRunnable.run();
- mPipFinishResizeWCTRunnable = null;
- }
+ maybePerformFinishResizeCallback();
}
};
+ private void maybePerformFinishResizeCallback() {
+ if (mPipFinishResizeWCTRunnable != null) {
+ mPipFinishResizeWCTRunnable.run();
+ mPipFinishResizeWCTRunnable = null;
+ }
+ }
+
// These callbacks are called on the update thread
private final PipAnimationController.PipAnimationCallback mPipAnimationCallback =
new PipAnimationController.PipAnimationCallback() {
@@ -619,11 +623,11 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
* Removes PiP immediately.
*/
public void removePip() {
- if (!mPipTransitionState.isInPip() || mToken == null) {
+ if (!mPipTransitionState.isInPip() || mToken == null || mLeash == null) {
ProtoLog.wtf(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: Not allowed to removePip in current state"
- + " mState=%d mToken=%s", TAG, mPipTransitionState.getTransitionState(),
- mToken);
+ + " mState=%d mToken=%s mLeash=%s", TAG,
+ mPipTransitionState.getTransitionState(), mToken, mLeash);
return;
}
@@ -1607,6 +1611,10 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
if (direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) {
mSplitScreenOptional.ifPresent(splitScreenController ->
splitScreenController.enterSplitScreen(mTaskInfo.taskId, wasPipTopLeft, wct));
+ } else if (direction == TRANSITION_DIRECTION_LEAVE_PIP) {
+ // when leaving PiP we can call the callback without sync
+ maybePerformFinishResizeCallback();
+ mTaskOrganizer.applyTransaction(wct);
} else {
mTaskOrganizer.applySyncTransaction(wct, mPipFinishResizeWCTCallback);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index 44d7e6de8ec4..a8b209fc7da6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -213,12 +213,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
RecentsController(IRecentsAnimationRunner listener) {
mListener = listener;
- mDeathHandler = () -> mExecutor.execute(() -> {
- if (mListener == null) return;
- if (mFinishCB != null) {
- finish(mWillFinishToHome, false /* leaveHint */);
- }
- });
+ mDeathHandler = () -> finish(mWillFinishToHome, false /* leaveHint */);
try {
mListener.asBinder().linkToDeath(mDeathHandler, 0 /* flags */);
} catch (RemoteException e) {
@@ -245,7 +240,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
}
}
if (mFinishCB != null) {
- finish(toHome, false /* userLeave */);
+ finishInner(toHome, false /* userLeave */);
} else {
cleanUp();
}
@@ -552,13 +547,13 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
t.apply();
// not using the incoming anim-only surfaces
info.releaseAnimSurfaces();
- finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */);
if (appearedTargets == null) return;
try {
mListener.onTasksAppeared(appearedTargets);
} catch (RemoteException e) {
Slog.e(TAG, "Error sending appeared tasks to recents animation", e);
}
+ finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */);
}
/** For now, just set-up a jump-cut to the new activity. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index 8e8facadfd5d..e8a6a159cb19 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -127,7 +127,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
if (decoration == null) {
createWindowDecoration(taskInfo, taskSurface, startT, finishT);
} else {
- decoration.relayout(taskInfo, startT, finishT);
+ decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */);
}
}
@@ -139,7 +139,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
if (decoration == null) return;
- decoration.relayout(taskInfo, startT, finishT);
+ decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */);
}
@Override
@@ -192,7 +192,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
windowDecoration.setDragPositioningCallback(taskPositioner);
windowDecoration.setDragDetector(touchEventListener.mDragDetector);
- windowDecoration.relayout(taskInfo, startT, finishT);
+ windowDecoration.relayout(taskInfo, startT, finishT,
+ false /* applyStartTransactionOnDraw */);
setupCaptionColor(taskInfo, windowDecoration);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
index dfde7e6feff5..116af7094e13 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -90,15 +90,15 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
@Override
void relayout(RunningTaskInfo taskInfo) {
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- relayout(taskInfo, t, t);
- mSyncQueue.runInSync(transaction -> {
- transaction.merge(t);
- t.close();
- });
+ // Use |applyStartTransactionOnDraw| so that the transaction (that applies task crop) is
+ // synced with the buffer transaction (that draws the View). Both will be shown on screen
+ // at the same, whereas applying them independently causes flickering. See b/270202228.
+ relayout(taskInfo, t, t, true /* applyStartTransactionOnDraw */);
}
void relayout(RunningTaskInfo taskInfo,
- SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) {
+ SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
+ boolean applyStartTransactionOnDraw) {
final int shadowRadiusID = taskInfo.isFocused
? R.dimen.freeform_decor_shadow_focused_thickness
: R.dimen.freeform_decor_shadow_unfocused_thickness;
@@ -115,6 +115,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
mRelayoutParams.mLayoutResId = R.layout.caption_window_decor;
mRelayoutParams.mCaptionHeightId = R.dimen.freeform_decor_caption_height;
mRelayoutParams.mShadowRadiusId = shadowRadiusID;
+ mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
// After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
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 e137bc462607..49a5eac5fd07 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
@@ -247,7 +247,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
if (decoration == null) {
createWindowDecoration(taskInfo, taskSurface, startT, finishT);
} else {
- decoration.relayout(taskInfo, startT, finishT);
+ decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */);
}
}
@@ -259,7 +259,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
if (decoration == null) return;
- decoration.relayout(taskInfo, startT, finishT);
+ decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */);
}
@Override
@@ -781,7 +781,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
windowDecoration.setDragPositioningCallback(taskPositioner);
windowDecoration.setDragDetector(touchEventListener.mDragDetector);
- windowDecoration.relayout(taskInfo, startT, finishT);
+ windowDecoration.relayout(taskInfo, startT, finishT,
+ false /* applyStartTransactionOnDraw */);
incrementEventReceiverTasks(taskInfo.displayId);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 67e99d73b811..af3fb0ead55c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -173,15 +173,15 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
@Override
void relayout(ActivityManager.RunningTaskInfo taskInfo) {
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- relayout(taskInfo, t, t);
- mSyncQueue.runInSync(transaction -> {
- transaction.merge(t);
- t.close();
- });
+ // Use |applyStartTransactionOnDraw| so that the transaction (that applies task crop) is
+ // synced with the buffer transaction (that draws the View). Both will be shown on screen
+ // at the same, whereas applying them independently causes flickering. See b/270202228.
+ relayout(taskInfo, t, t, true /* applyStartTransactionOnDraw */);
}
void relayout(ActivityManager.RunningTaskInfo taskInfo,
- SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) {
+ SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
+ boolean applyStartTransactionOnDraw) {
final int shadowRadiusID = taskInfo.isFocused
? R.dimen.freeform_decor_shadow_focused_thickness
: R.dimen.freeform_decor_shadow_unfocused_thickness;
@@ -216,6 +216,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
mRelayoutParams.mLayoutResId = windowDecorLayoutId;
mRelayoutParams.mCaptionHeightId = R.dimen.freeform_decor_caption_height;
mRelayoutParams.mShadowRadiusId = shadowRadiusID;
+ mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
// After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 8b35694ff8fd..9a1b4ffbd50c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -238,30 +238,6 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
startT.setWindowCrop(mCaptionContainerSurface, captionWidth, captionHeight)
.show(mCaptionContainerSurface);
- if (mCaptionWindowManager == null) {
- // Put caption under a container surface because ViewRootImpl sets the destination frame
- // of windowless window layers and BLASTBufferQueue#update() doesn't support offset.
- mCaptionWindowManager = new WindowlessWindowManager(
- mTaskInfo.getConfiguration(), mCaptionContainerSurface,
- null /* hostInputToken */);
- }
-
- // Caption view
- mCaptionWindowManager.setConfiguration(taskConfig);
- final WindowManager.LayoutParams lp =
- new WindowManager.LayoutParams(captionWidth, captionHeight,
- WindowManager.LayoutParams.TYPE_APPLICATION,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT);
- lp.setTitle("Caption of Task=" + mTaskInfo.taskId);
- lp.setTrustedOverlay();
- if (mViewHost == null) {
- mViewHost = mSurfaceControlViewHostFactory.create(mDecorWindowContext, mDisplay,
- mCaptionWindowManager);
- mViewHost.setView(outResult.mRootView, lp);
- } else {
- mViewHost.relayout(lp);
- }
-
if (ViewRootImpl.CAPTION_ON_SHELL) {
outResult.mRootView.setTaskFocusState(mTaskInfo.isFocused);
@@ -287,6 +263,36 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
.show(mTaskSurface);
finishT.setPosition(mTaskSurface, taskPosition.x, taskPosition.y)
.setWindowCrop(mTaskSurface, outResult.mWidth, outResult.mHeight);
+
+ if (mCaptionWindowManager == null) {
+ // Put caption under a container surface because ViewRootImpl sets the destination frame
+ // of windowless window layers and BLASTBufferQueue#update() doesn't support offset.
+ mCaptionWindowManager = new WindowlessWindowManager(
+ mTaskInfo.getConfiguration(), mCaptionContainerSurface,
+ null /* hostInputToken */);
+ }
+
+ // Caption view
+ mCaptionWindowManager.setConfiguration(taskConfig);
+ final WindowManager.LayoutParams lp =
+ new WindowManager.LayoutParams(captionWidth, captionHeight,
+ WindowManager.LayoutParams.TYPE_APPLICATION,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT);
+ lp.setTitle("Caption of Task=" + mTaskInfo.taskId);
+ lp.setTrustedOverlay();
+ if (mViewHost == null) {
+ mViewHost = mSurfaceControlViewHostFactory.create(mDecorWindowContext, mDisplay,
+ mCaptionWindowManager);
+ if (params.mApplyStartTransactionOnDraw) {
+ mViewHost.getRootSurfaceControl().applyTransactionOnDraw(startT);
+ }
+ mViewHost.setView(outResult.mRootView, lp);
+ } else {
+ if (params.mApplyStartTransactionOnDraw) {
+ mViewHost.getRootSurfaceControl().applyTransactionOnDraw(startT);
+ }
+ mViewHost.relayout(lp);
+ }
}
/**
@@ -411,6 +417,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
int mCaptionX;
int mCaptionY;
+ boolean mApplyStartTransactionOnDraw;
+
void reset() {
mLayoutResId = Resources.ID_NULL;
mCaptionHeightId = Resources.ID_NULL;
@@ -419,6 +427,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
mCaptionX = 0;
mCaptionY = 0;
+
+ mApplyStartTransactionOnDraw = false;
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
index 919bf0665b5e..4a55429eacb6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
@@ -16,8 +16,6 @@
package com.android.wm.shell.bubbles;
-import static com.android.wm.shell.bubbles.Bubble.KEY_APP_BUBBLE;
-
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -185,7 +183,10 @@ public class BubbleDataTest extends ShellTestCase {
Intent appBubbleIntent = new Intent(mContext, BubblesTestActivity.class);
appBubbleIntent.setPackage(mContext.getPackageName());
- mAppBubble = new Bubble(appBubbleIntent, new UserHandle(1), mock(Icon.class),
+ mAppBubble = Bubble.createAppBubble(
+ appBubbleIntent,
+ new UserHandle(1),
+ mock(Icon.class),
mMainExecutor);
mPositioner = new TestableBubblePositioner(mContext,
@@ -1101,14 +1102,15 @@ public class BubbleDataTest extends ShellTestCase {
@Test
public void test_removeAppBubble_skipsOverflow() {
+ String appBubbleKey = mAppBubble.getKey();
mBubbleData.notificationEntryUpdated(mAppBubble, true /* suppressFlyout*/,
false /* showInShade */);
- assertThat(mBubbleData.getBubbleInStackWithKey(KEY_APP_BUBBLE)).isEqualTo(mAppBubble);
+ assertThat(mBubbleData.getBubbleInStackWithKey(appBubbleKey)).isEqualTo(mAppBubble);
- mBubbleData.dismissBubbleWithKey(KEY_APP_BUBBLE, Bubbles.DISMISS_USER_GESTURE);
+ mBubbleData.dismissBubbleWithKey(appBubbleKey, Bubbles.DISMISS_USER_GESTURE);
- assertThat(mBubbleData.getOverflowBubbleWithKey(KEY_APP_BUBBLE)).isNull();
- assertThat(mBubbleData.getBubbleInStackWithKey(KEY_APP_BUBBLE)).isNull();
+ assertThat(mBubbleData.getOverflowBubbleWithKey(appBubbleKey)).isNull();
+ assertThat(mBubbleData.getBubbleInStackWithKey(appBubbleKey)).isNull();
}
private void verifyUpdateReceived() {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index c1e53a90b7e0..fc4bfd9754a0 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -33,6 +33,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.same;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.content.Context;
@@ -42,6 +43,7 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
import android.util.DisplayMetrics;
+import android.view.AttachedSurfaceControl;
import android.view.Display;
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
@@ -97,6 +99,8 @@ public class WindowDecorationTests extends ShellTestCase {
@Mock
private SurfaceControlViewHost mMockSurfaceControlViewHost;
@Mock
+ private AttachedSurfaceControl mMockRootSurfaceControl;
+ @Mock
private TestView mMockView;
@Mock
private WindowContainerTransaction mMockWindowContainerTransaction;
@@ -129,6 +133,8 @@ public class WindowDecorationTests extends ShellTestCase {
doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory)
.create(any(), any(), any());
+ when(mMockSurfaceControlViewHost.getRootSurfaceControl())
+ .thenReturn(mMockRootSurfaceControl);
}
@Test
@@ -461,6 +467,43 @@ public class WindowDecorationTests extends ShellTestCase {
verify(mMockSurfaceControlStartT).show(captionContainerSurface);
}
+ @Test
+ public void testRelayout_applyTransactionInSyncWithDraw() {
+ final Display defaultDisplay = mock(Display.class);
+ doReturn(defaultDisplay).when(mMockDisplayController)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+
+ final SurfaceControl decorContainerSurface = mock(SurfaceControl.class);
+ final SurfaceControl.Builder decorContainerSurfaceBuilder =
+ createMockSurfaceControlBuilder(decorContainerSurface);
+ mMockSurfaceControlBuilders.add(decorContainerSurfaceBuilder);
+ final SurfaceControl captionContainerSurface = mock(SurfaceControl.class);
+ final SurfaceControl.Builder captionContainerSurfaceBuilder =
+ createMockSurfaceControlBuilder(captionContainerSurface);
+ mMockSurfaceControlBuilders.add(captionContainerSurfaceBuilder);
+
+ final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
+ mMockSurfaceControlTransactions.add(t);
+ final ActivityManager.TaskDescription.Builder taskDescriptionBuilder =
+ new ActivityManager.TaskDescription.Builder()
+ .setBackgroundColor(Color.YELLOW);
+ final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
+ .setDisplayId(Display.DEFAULT_DISPLAY)
+ .setTaskDescriptionBuilder(taskDescriptionBuilder)
+ .setBounds(TASK_BOUNDS)
+ .setPositionInParent(TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y)
+ .setVisible(true)
+ .build();
+ taskInfo.isFocused = true;
+ taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2;
+ final SurfaceControl taskSurface = mock(SurfaceControl.class);
+ final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
+
+ windowDecor.relayout(taskInfo, true /* applyStartTransactionOnDraw */);
+
+ verify(mMockRootSurfaceControl).applyTransactionOnDraw(mMockSurfaceControlStartT);
+ }
+
private TestWindowDecoration createWindowDecoration(
ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) {
return new TestWindowDecoration(InstrumentationRegistry.getInstrumentation().getContext(),
@@ -516,6 +559,12 @@ public class WindowDecorationTests extends ShellTestCase {
@Override
void relayout(ActivityManager.RunningTaskInfo taskInfo) {
+ relayout(taskInfo, false /* applyStartTransactionOnDraw */);
+ }
+
+ void relayout(ActivityManager.RunningTaskInfo taskInfo,
+ boolean applyStartTransactionOnDraw) {
+ mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
relayout(mRelayoutParams, mMockSurfaceControlStartT, mMockSurfaceControlFinishT,
mMockWindowContainerTransaction, mMockView, mRelayoutResult);
}
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 70c36a5803ee..34af1f9ea039 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -399,7 +399,7 @@ cc_defaults {
"libharfbuzz_ng",
"libimage_io",
"libjpeg",
- "libjpegrecoverymap",
+ "libultrahdr",
"liblog",
"libminikin",
"libz",
diff --git a/libs/hwui/jni/YuvToJpegEncoder.cpp b/libs/hwui/jni/YuvToJpegEncoder.cpp
index 8874ef1d2fe0..69418b09fee6 100644
--- a/libs/hwui/jni/YuvToJpegEncoder.cpp
+++ b/libs/hwui/jni/YuvToJpegEncoder.cpp
@@ -298,39 +298,39 @@ void Yuv422IToJpegEncoder::configSamplingFactors(jpeg_compress_struct* cinfo) {
}
///////////////////////////////////////////////////////////////////////////////
-using namespace android::jpegrecoverymap;
+using namespace android::ultrahdr;
-jpegr_color_gamut P010Yuv420ToJpegREncoder::findColorGamut(JNIEnv* env, int aDataSpace) {
+ultrahdr_color_gamut P010Yuv420ToJpegREncoder::findColorGamut(JNIEnv* env, int aDataSpace) {
switch (aDataSpace & ADataSpace::STANDARD_MASK) {
case ADataSpace::STANDARD_BT709:
- return jpegr_color_gamut::JPEGR_COLORGAMUT_BT709;
+ return ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
case ADataSpace::STANDARD_DCI_P3:
- return jpegr_color_gamut::JPEGR_COLORGAMUT_P3;
+ return ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_P3;
case ADataSpace::STANDARD_BT2020:
- return jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100;
+ return ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
default:
jclass IllegalArgumentException = env->FindClass("java/lang/IllegalArgumentException");
env->ThrowNew(IllegalArgumentException,
"The requested color gamut is not supported by JPEG/R.");
}
- return jpegr_color_gamut::JPEGR_COLORGAMUT_UNSPECIFIED;
+ return ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_UNSPECIFIED;
}
-jpegr_transfer_function P010Yuv420ToJpegREncoder::findHdrTransferFunction(JNIEnv* env,
+ultrahdr_transfer_function P010Yuv420ToJpegREncoder::findHdrTransferFunction(JNIEnv* env,
int aDataSpace) {
switch (aDataSpace & ADataSpace::TRANSFER_MASK) {
case ADataSpace::TRANSFER_ST2084:
- return jpegr_transfer_function::JPEGR_TF_PQ;
+ return ultrahdr_transfer_function::ULTRAHDR_TF_PQ;
case ADataSpace::TRANSFER_HLG:
- return jpegr_transfer_function::JPEGR_TF_HLG;
+ return ultrahdr_transfer_function::ULTRAHDR_TF_HLG;
default:
jclass IllegalArgumentException = env->FindClass("java/lang/IllegalArgumentException");
env->ThrowNew(IllegalArgumentException,
"The requested HDR transfer function is not supported by JPEG/R.");
}
- return jpegr_transfer_function::JPEGR_TF_UNSPECIFIED;
+ return ultrahdr_transfer_function::ULTRAHDR_TF_UNSPECIFIED;
}
bool P010Yuv420ToJpegREncoder::encode(JNIEnv* env,
@@ -344,13 +344,13 @@ bool P010Yuv420ToJpegREncoder::encode(JNIEnv* env,
return false;
}
- jpegr_color_gamut hdrColorGamut = findColorGamut(env, hdrColorSpace);
- jpegr_color_gamut sdrColorGamut = findColorGamut(env, sdrColorSpace);
- jpegr_transfer_function hdrTransferFunction = findHdrTransferFunction(env, hdrColorSpace);
+ ultrahdr_color_gamut hdrColorGamut = findColorGamut(env, hdrColorSpace);
+ ultrahdr_color_gamut sdrColorGamut = findColorGamut(env, sdrColorSpace);
+ ultrahdr_transfer_function hdrTransferFunction = findHdrTransferFunction(env, hdrColorSpace);
- if (hdrColorGamut == jpegr_color_gamut::JPEGR_COLORGAMUT_UNSPECIFIED
- || sdrColorGamut == jpegr_color_gamut::JPEGR_COLORGAMUT_UNSPECIFIED
- || hdrTransferFunction == jpegr_transfer_function::JPEGR_TF_UNSPECIFIED) {
+ if (hdrColorGamut == ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_UNSPECIFIED
+ || sdrColorGamut == ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_UNSPECIFIED
+ || hdrTransferFunction == ultrahdr_transfer_function::ULTRAHDR_TF_UNSPECIFIED) {
return false;
}
diff --git a/libs/hwui/jni/YuvToJpegEncoder.h b/libs/hwui/jni/YuvToJpegEncoder.h
index d22a26c83567..8ef780547184 100644
--- a/libs/hwui/jni/YuvToJpegEncoder.h
+++ b/libs/hwui/jni/YuvToJpegEncoder.h
@@ -2,7 +2,7 @@
#define _ANDROID_GRAPHICS_YUV_TO_JPEG_ENCODER_H_
#include <android/data_space.h>
-#include <jpegrecoverymap/jpegr.h>
+#include <ultrahdr/jpegr.h>
extern "C" {
#include "jpeglib.h"
@@ -103,7 +103,7 @@ public:
* @param aDataSpace data space defined in data_space.h.
* @return color gamut for JPEG/R.
*/
- static android::jpegrecoverymap::jpegr_color_gamut findColorGamut(JNIEnv* env, int aDataSpace);
+ static android::ultrahdr::ultrahdr_color_gamut findColorGamut(JNIEnv* env, int aDataSpace);
/** Map data space (defined in DataSpace.java and data_space.h) to the transfer function
* used in JPEG/R
@@ -112,7 +112,7 @@ public:
* @param aDataSpace data space defined in data_space.h.
* @return color gamut for JPEG/R.
*/
- static android::jpegrecoverymap::jpegr_transfer_function findHdrTransferFunction(
+ static android::ultrahdr::ultrahdr_transfer_function findHdrTransferFunction(
JNIEnv* env, int aDataSpace);
};
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
index 7581b5c0aa91..8b9c8b9a768f 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
@@ -40,9 +40,7 @@ import com.android.credentialmanager.common.ui.Snackbar
import com.android.credentialmanager.createflow.CreateCredentialScreen
import com.android.credentialmanager.createflow.hasContentToDisplay
import com.android.credentialmanager.getflow.GetCredentialScreen
-import com.android.credentialmanager.getflow.GetGenericCredentialScreen
import com.android.credentialmanager.getflow.hasContentToDisplay
-import com.android.credentialmanager.getflow.isFallbackScreen
import com.android.credentialmanager.ui.theme.PlatformTheme
@ExperimentalMaterialApi
@@ -161,19 +159,11 @@ class CredentialSelectorActivity : ComponentActivity() {
providerActivityLauncher = launcher
)
} else if (getCredentialUiState != null && hasContentToDisplay(getCredentialUiState)) {
- if (isFallbackScreen(getCredentialUiState)) {
- GetGenericCredentialScreen(
- viewModel = viewModel,
- getCredentialUiState = getCredentialUiState,
- providerActivityLauncher = launcher
- )
- } else {
- GetCredentialScreen(
- viewModel = viewModel,
- getCredentialUiState = getCredentialUiState,
- providerActivityLauncher = launcher
- )
- }
+ GetCredentialScreen(
+ viewModel = viewModel,
+ getCredentialUiState = getCredentialUiState,
+ providerActivityLauncher = launcher
+ )
} else {
Log.d(Constants.LOG_TAG, "UI wasn't able to render neither get nor create flow")
reportInstantiationErrorAndFinishActivity(credManRepo)
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
index f08bbf430440..57035d426654 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
@@ -50,9 +50,7 @@ import com.android.credentialmanager.getflow.TopBrandingContent
import androidx.credentials.CreateCredentialRequest
import androidx.credentials.CreateCustomCredentialRequest
import androidx.credentials.CreatePasswordRequest
-import androidx.credentials.CredentialOption
import androidx.credentials.CreatePublicKeyCredentialRequest
-import androidx.credentials.GetPublicKeyCredentialOption
import androidx.credentials.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
import androidx.credentials.provider.Action
import androidx.credentials.provider.AuthenticationAction
@@ -194,20 +192,8 @@ class GetFlowUtils {
originName: String?,
): com.android.credentialmanager.getflow.RequestDisplayInfo? {
val getCredentialRequest = requestInfo?.getCredentialRequest ?: return null
- val preferImmediatelyAvailableCredentials = getCredentialRequest.credentialOptions.any {
- val credentialOptionJetpack = CredentialOption.createFrom(
- it.type,
- it.credentialRetrievalData,
- it.credentialRetrievalData,
- it.isSystemProviderRequired,
- it.allowedProviders,
- )
- if (credentialOptionJetpack is GetPublicKeyCredentialOption) {
- credentialOptionJetpack.preferImmediatelyAvailableCredentials
- } else {
- false
- }
- }
+ val preferImmediatelyAvailableCredentials = getCredentialRequest.data.getBoolean(
+ "androidx.credentials.BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS")
val preferUiBrandingComponentName =
getCredentialRequest.data.getParcelable(
"androidx.credentials.BUNDLE_KEY_PREFER_UI_BRANDING_COMPONENT_NAME",
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
index 516c1a3bb1e3..74933c9e3da6 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -200,18 +200,31 @@ fun PrimarySelectionCard(
authenticationEntryList.isEmpty()) || (sortedUserNameToCredentialEntryList.isEmpty() &&
authenticationEntryList.size == 1)
item {
- HeadlineText(
- text = stringResource(
- if (hasSingleEntry) {
- if (sortedUserNameToCredentialEntryList.firstOrNull()
- ?.sortedCredentialEntryList?.first()?.credentialType
- == CredentialType.PASSKEY
- ) R.string.get_dialog_title_use_passkey_for
- else R.string.get_dialog_title_use_sign_in_for
- } else R.string.get_dialog_title_choose_sign_in_for,
- requestDisplayInfo.appName
- ),
- )
+ if (requestDisplayInfo.preferIdentityDocUi) {
+ HeadlineText(
+ text = stringResource(
+ if (hasSingleEntry) {
+ R.string.get_dialog_title_use_info_on
+ } else {
+ R.string.get_dialog_title_choose_option_for
+ },
+ requestDisplayInfo.appName
+ ),
+ )
+ } else {
+ HeadlineText(
+ text = stringResource(
+ if (hasSingleEntry) {
+ if (sortedUserNameToCredentialEntryList.firstOrNull()
+ ?.sortedCredentialEntryList?.first()?.credentialType
+ == CredentialType.PASSKEY
+ ) R.string.get_dialog_title_use_passkey_for
+ else R.string.get_dialog_title_use_sign_in_for
+ } else R.string.get_dialog_title_choose_sign_in_for,
+ requestDisplayInfo.appName
+ ),
+ )
+ }
}
item { Divider(thickness = 24.dp, color = Color.Transparent) }
item {
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetGenericCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetGenericCredentialComponents.kt
deleted file mode 100644
index 57fefbe577b4..000000000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetGenericCredentialComponents.kt
+++ /dev/null
@@ -1,174 +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 com.android.credentialmanager.getflow
-
-import androidx.activity.compose.ManagedActivityResultLauncher
-import androidx.activity.result.ActivityResult
-import androidx.activity.result.IntentSenderRequest
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Column
-import androidx.compose.material3.Divider
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.asImageBitmap
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.unit.dp
-import androidx.core.graphics.drawable.toBitmap
-import com.android.compose.rememberSystemUiController
-import com.android.credentialmanager.CredentialSelectorViewModel
-import com.android.credentialmanager.R
-import com.android.credentialmanager.common.BaseEntry
-import com.android.credentialmanager.common.ProviderActivityState
-import com.android.credentialmanager.common.ui.ConfirmButton
-import com.android.credentialmanager.common.ui.CredentialContainerCard
-import com.android.credentialmanager.common.ui.CtaButtonRow
-import com.android.credentialmanager.common.ui.HeadlineIcon
-import com.android.credentialmanager.common.ui.HeadlineText
-import com.android.credentialmanager.common.ui.LargeLabelTextOnSurfaceVariant
-import com.android.credentialmanager.common.ui.ModalBottomSheet
-import com.android.credentialmanager.common.ui.SheetContainerCard
-import com.android.credentialmanager.common.ui.setBottomSheetSystemBarsColor
-import com.android.credentialmanager.logging.GetCredentialEvent
-import com.android.internal.logging.UiEventLogger
-
-
-@Composable
-fun GetGenericCredentialScreen(
- viewModel: CredentialSelectorViewModel,
- getCredentialUiState: GetCredentialUiState,
- providerActivityLauncher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
-) {
- val sysUiController = rememberSystemUiController()
- setBottomSheetSystemBarsColor(sysUiController)
- ModalBottomSheet(
- sheetContent = {
- when (viewModel.uiState.providerActivityState) {
- ProviderActivityState.NOT_APPLICABLE -> {
- PrimarySelectionCardGeneric(
- requestDisplayInfo = getCredentialUiState.requestDisplayInfo,
- providerDisplayInfo = getCredentialUiState.providerDisplayInfo,
- providerInfoList = getCredentialUiState.providerInfoList,
- onEntrySelected = viewModel::getFlowOnEntrySelected,
- onConfirm = viewModel::getFlowOnConfirmEntrySelected,
- onLog = { viewModel.logUiEvent(it) },
- )
- viewModel.uiMetrics.log(GetCredentialEvent
- .CREDMAN_GET_CRED_SCREEN_PRIMARY_SELECTION)
- }
- ProviderActivityState.READY_TO_LAUNCH -> {
- // Launch only once per providerActivityState change so that the provider
- // UI will not be accidentally launched twice.
- LaunchedEffect(viewModel.uiState.providerActivityState) {
- viewModel.launchProviderUi(providerActivityLauncher)
- }
- viewModel.uiMetrics.log(GetCredentialEvent
- .CREDMAN_GET_CRED_PROVIDER_ACTIVITY_READY_TO_LAUNCH)
- }
- ProviderActivityState.PENDING -> {
- // Hide our content when the provider activity is active.
- viewModel.uiMetrics.log(GetCredentialEvent
- .CREDMAN_GET_CRED_PROVIDER_ACTIVITY_PENDING)
- }
- }
- },
- onDismiss = viewModel::onUserCancel,
- )
-}
-
-@Composable
-fun PrimarySelectionCardGeneric(
- requestDisplayInfo: RequestDisplayInfo,
- providerDisplayInfo: ProviderDisplayInfo,
- providerInfoList: List<ProviderInfo>,
- onEntrySelected: (BaseEntry) -> Unit,
- onConfirm: () -> Unit,
- onLog: @Composable (UiEventLogger.UiEventEnum) -> Unit,
-) {
- val sortedUserNameToCredentialEntryList =
- providerDisplayInfo.sortedUserNameToCredentialEntryList
- val totalEntriesCount = sortedUserNameToCredentialEntryList
- .flatMap { it.sortedCredentialEntryList }.size
- SheetContainerCard {
- // When only one provider (not counting the remote-only provider) exists, display that
- // provider's icon + name up top.
- if (providerInfoList.size <= 2) { // It's only possible to be the single provider case
- // if we are started with no more than 2 providers.
- val nonRemoteProviderList = providerInfoList.filter(
- { it.credentialEntryList.isNotEmpty() || it.authenticationEntryList.isNotEmpty() }
- )
- if (nonRemoteProviderList.size == 1) {
- val providerInfo = nonRemoteProviderList.firstOrNull() // First should always work
- // but just to be safe.
- if (providerInfo != null) {
- item {
- HeadlineIcon(
- bitmap = providerInfo.icon.toBitmap().asImageBitmap(),
- tint = Color.Unspecified,
- )
- }
- item { Divider(thickness = 4.dp, color = Color.Transparent) }
- item { LargeLabelTextOnSurfaceVariant(text = providerInfo.displayName) }
- item { Divider(thickness = 16.dp, color = Color.Transparent) }
- }
- }
- }
-
- item {
- HeadlineText(
- text = stringResource(
- if (totalEntriesCount == 1) {
- R.string.get_dialog_title_use_info_on
- } else {
- R.string.get_dialog_title_choose_option_for
- },
- requestDisplayInfo.appName
- ),
- )
- }
- item { Divider(thickness = 24.dp, color = Color.Transparent) }
- item {
- CredentialContainerCard {
- Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
- sortedUserNameToCredentialEntryList.forEach {
- // TODO(b/275375861): fallback UI merges entries by account names.
- // Need a strategy to be able to show all entries.
- CredentialEntryRow(
- credentialEntryInfo = it.sortedCredentialEntryList.first(),
- onEntrySelected = onEntrySelected,
- enforceOneLine = true,
- )
- }
- }
- }
- }
- item { Divider(thickness = 24.dp, color = Color.Transparent) }
- item {
- if (totalEntriesCount == 1) {
- CtaButtonRow(
- rightButton = {
- ConfirmButton(
- stringResource(R.string.get_dialog_button_label_continue),
- onClick = onConfirm
- )
- }
- )
- }
- }
- }
- onLog(GetCredentialEvent.CREDMAN_GET_CRED_PRIMARY_SELECTION_CARD)
-}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
index a4a163bbabc3..716f47450ae9 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
@@ -41,10 +41,6 @@ internal fun hasContentToDisplay(state: GetCredentialUiState): Boolean {
!state.requestDisplayInfo.preferImmediatelyAvailableCredentials)
}
-internal fun isFallbackScreen(state: GetCredentialUiState): Boolean {
- return state.requestDisplayInfo.preferIdentityDocUi
-}
-
internal fun findAutoSelectEntry(providerDisplayInfo: ProviderDisplayInfo): CredentialEntryInfo? {
if (providerDisplayInfo.authenticationEntryList.isNotEmpty()) {
return null
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt
index 1786d139e966..91c0a5b635c9 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt
@@ -19,17 +19,11 @@ data class RippleAnimationConfig(
val maxHeight: Float = 0f,
val pixelDensity: Float = 1f,
var color: Int = Color.WHITE,
- val opacity: Int = RIPPLE_DEFAULT_ALPHA,
- val sparkleStrength: Float = RIPPLE_SPARKLE_STRENGTH,
+ val opacity: Int = RippleShader.RIPPLE_DEFAULT_ALPHA,
+ val sparkleStrength: Float = RippleShader.RIPPLE_SPARKLE_STRENGTH,
// Null means it uses default fade parameter values.
val baseRingFadeParams: RippleShader.FadeParams? = null,
val sparkleRingFadeParams: RippleShader.FadeParams? = null,
val centerFillFadeParams: RippleShader.FadeParams? = null,
val shouldDistort: Boolean = true
-) {
- companion object {
- const val RIPPLE_SPARKLE_STRENGTH: Float = 0.3f
- const val RIPPLE_DEFAULT_COLOR: Int = 0xffffffff.toInt()
- const val RIPPLE_DEFAULT_ALPHA: Int = 115 // full opacity is 255.
- }
-}
+)
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
index b5b6037aeae4..7e56f4b3d2b2 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
@@ -60,6 +60,10 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
const val DEFAULT_CENTER_FILL_FADE_OUT_START = 0f
const val DEFAULT_CENTER_FILL_FADE_OUT_END = 0.6f
+ const val RIPPLE_SPARKLE_STRENGTH: Float = 0.3f
+ const val RIPPLE_DEFAULT_COLOR: Int = 0xffffffff.toInt()
+ const val RIPPLE_DEFAULT_ALPHA: Int = 115 // full opacity is 255.
+
private const val SHADER_UNIFORMS =
"""
uniform vec2 in_center;
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
index ef5ad436ec38..b89912709576 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
@@ -72,9 +72,9 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a
this.rippleShape = rippleShape
rippleShader = RippleShader(rippleShape)
- rippleShader.color = RippleAnimationConfig.RIPPLE_DEFAULT_COLOR
+ rippleShader.color = RippleShader.RIPPLE_DEFAULT_COLOR
rippleShader.rawProgress = 0f
- rippleShader.sparkleStrength = RippleAnimationConfig.RIPPLE_SPARKLE_STRENGTH
+ rippleShader.sparkleStrength = RippleShader.RIPPLE_SPARKLE_STRENGTH
rippleShader.pixelDensity = resources.displayMetrics.density
ripplePaint.shader = rippleShader
@@ -209,7 +209,7 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a
*
* The alpha value of the color will be applied to the ripple. The alpha range is [0-255].
*/
- fun setColor(color: Int, alpha: Int = RippleAnimationConfig.RIPPLE_DEFAULT_ALPHA) {
+ fun setColor(color: Int, alpha: Int = RippleShader.RIPPLE_DEFAULT_ALPHA) {
rippleShader.color = ColorUtils.setAlphaComponent(color, alpha)
}
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
index a5f832a17de4..ff150c8cba13 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
@@ -38,7 +38,7 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
}
@Test
- fun `No violations`() {
+ fun noViolations() {
lint()
.files(
*LEGITIMATE_FILES,
@@ -51,7 +51,7 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
}
@Test
- fun `Violation - domain depends on ui`() {
+ fun violation_domainDependsOnUi() {
lint()
.files(
*LEGITIMATE_FILES,
@@ -86,7 +86,7 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
}
@Test
- fun `Violation - ui depends on data`() {
+ fun violation_uiDependsOnData() {
lint()
.files(
*LEGITIMATE_FILES,
@@ -121,7 +121,7 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
}
@Test
- fun `Violation - shared depends on all other layers`() {
+ fun violation_sharedDependsOnAllOtherLayers() {
lint()
.files(
*LEGITIMATE_FILES,
@@ -166,7 +166,7 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
}
@Test
- fun `Violation - data depends on domain`() {
+ fun violation_dataDependsOnDomain() {
lint()
.files(
*LEGITIMATE_FILES,
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
index 3ec3b5c3f758..6ca7f12e842b 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
@@ -62,10 +62,7 @@ class DefaultClockController(
private val defaultLineSpacing = resources.getFloat(R.dimen.keyguard_clock_line_spacing_scale)
override val events: DefaultClockEvents
- override lateinit var animations: DefaultClockAnimations
- private set
-
- override val config = ClockConfig(hasCustomPositionUpdatedAnimation = true)
+ override val config = ClockConfig()
init {
val parent = FrameLayout(ctx)
@@ -84,13 +81,13 @@ class DefaultClockController(
clocks = listOf(smallClock.view, largeClock.view)
events = DefaultClockEvents()
- animations = DefaultClockAnimations(0f, 0f)
events.onLocaleChanged(Locale.getDefault())
}
override fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) {
largeClock.recomputePadding(null)
- animations = DefaultClockAnimations(dozeFraction, foldFraction)
+ largeClock.animations = LargeClockAnimations(largeClock.view, dozeFraction, foldFraction)
+ smallClock.animations = DefaultClockAnimations(smallClock.view, dozeFraction, foldFraction)
events.onColorPaletteChanged(resources)
events.onTimeZoneChanged(TimeZone.getDefault())
smallClock.events.onTimeTick()
@@ -115,6 +112,9 @@ class DefaultClockController(
view.logBuffer = value
}
+ override var animations: DefaultClockAnimations = DefaultClockAnimations(view, 0f, 0f)
+ internal set
+
init {
if (seedColor != null) {
currentColor = seedColor!!
@@ -170,6 +170,12 @@ class DefaultClockController(
view: AnimatableClockView,
seedColor: Int?,
) : DefaultClockFaceController(view, seedColor) {
+ override val config = ClockFaceConfig(hasCustomPositionUpdatedAnimation = true)
+
+ init {
+ animations = LargeClockAnimations(view, 0f, 0f)
+ }
+
override fun recomputePadding(targetRegion: Rect?) {
// We center the view within the targetRegion instead of within the parent
// view by computing the difference and adding that to the padding.
@@ -220,7 +226,8 @@ class DefaultClockController(
}
}
- inner class DefaultClockAnimations(
+ open inner class DefaultClockAnimations(
+ val view: AnimatableClockView,
dozeFraction: Float,
foldFraction: Float,
) : ClockAnimations {
@@ -229,34 +236,40 @@ class DefaultClockController(
init {
if (foldState.isActive) {
- clocks.forEach { it.animateFoldAppear(false) }
+ view.animateFoldAppear(false)
} else {
- clocks.forEach { it.animateDoze(dozeState.isActive, false) }
+ view.animateDoze(dozeState.isActive, false)
}
}
override fun enter() {
if (!dozeState.isActive) {
- clocks.forEach { it.animateAppearOnLockscreen() }
+ view.animateAppearOnLockscreen()
}
}
- override fun charge() = clocks.forEach { it.animateCharge { dozeState.isActive } }
+ override fun charge() = view.animateCharge { dozeState.isActive }
override fun fold(fraction: Float) {
val (hasChanged, hasJumped) = foldState.update(fraction)
if (hasChanged) {
- clocks.forEach { it.animateFoldAppear(!hasJumped) }
+ view.animateFoldAppear(!hasJumped)
}
}
override fun doze(fraction: Float) {
val (hasChanged, hasJumped) = dozeState.update(fraction)
if (hasChanged) {
- clocks.forEach { it.animateDoze(dozeState.isActive, !hasJumped) }
+ view.animateDoze(dozeState.isActive, !hasJumped)
}
}
+ }
+ inner class LargeClockAnimations(
+ view: AnimatableClockView,
+ dozeFraction: Float,
+ foldFraction: Float,
+ ) : DefaultClockAnimations(view, dozeFraction, foldFraction) {
override fun onPositionUpdated(fromRect: Rect, toRect: Rect, fraction: Float) {
largeClock.moveForSplitShade(fromRect, toRect, fraction)
}
diff --git a/packages/SystemUI/docs/dagger.md b/packages/SystemUI/docs/dagger.md
index 9b4c21efb27f..4a6240b56081 100644
--- a/packages/SystemUI/docs/dagger.md
+++ b/packages/SystemUI/docs/dagger.md
@@ -108,20 +108,13 @@ You can then include your module in one of three places:
### Using injection with Fragments
-Fragments are created as part of the FragmentManager, so they need to be
-setup so the manager knows how to create them. To do that, add a method
-to com.android.systemui.fragments.FragmentService$FragmentCreator that
-returns your fragment class. That is all that is required, once the method
-exists, FragmentService will automatically pick it up and use injection
-whenever your fragment needs to be created.
+Fragments are created as part of the FragmentManager, so injectable Fragments need to be registered
+so the manager knows how to create them. This is done via
+[FragmentService#addFragmentInstantiationProvider](../src/com/android/systemui/fragments/FragmentService.java).
+Pass it the class of your fragment and a `Provider` for your fragment at some time before your
+Fragment is accessed.
-```java
-public interface FragmentCreator {
- NavigationBarFragment createNavigationBar();
-}
-```
-
-If you need to create your fragment (i.e. for the add or replace transaction),
+When you need to create your fragment (i.e. for the add or replace transaction),
then the FragmentHostManager can do this for you.
```java
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
index 05630e795476..8ef2d8033000 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
@@ -69,9 +69,6 @@ interface ClockController {
/** Events that clocks may need to respond to */
val events: ClockEvents
- /** Triggers for various animations */
- val animations: ClockAnimations
-
/** Initializes various rendering parameters. If never called, provides reasonable defaults. */
fun initialize(
resources: Resources,
@@ -79,8 +76,10 @@ interface ClockController {
foldFraction: Float,
) {
events.onColorPaletteChanged(resources)
- animations.doze(dozeFraction)
- animations.fold(foldFraction)
+ smallClock.animations.doze(dozeFraction)
+ largeClock.animations.doze(dozeFraction)
+ smallClock.animations.fold(foldFraction)
+ largeClock.animations.fold(foldFraction)
smallClock.events.onTimeTick()
largeClock.events.onTimeTick()
}
@@ -100,6 +99,9 @@ interface ClockFaceController {
/** Events specific to this clock face */
val events: ClockFaceEvents
+ /** Triggers for various animations */
+ val animations: ClockAnimations
+
/** Some clocks may log debug information */
var logBuffer: LogBuffer?
}
@@ -192,13 +194,6 @@ data class ClockMetadata(
/** Render configuration for the full clock. Modifies the way systemUI behaves with this clock. */
data class ClockConfig(
- /**
- * Whether this clock has a custom position update animation. If true, the keyguard will call
- * `onPositionUpdated` to notify the clock of a position update animation. If false, a default
- * animation will be used (e.g. a simple translation).
- */
- val hasCustomPositionUpdatedAnimation: Boolean = false,
-
/** Transition to AOD should move smartspace like large clock instead of small clock */
val useAlternateSmartspaceAODTransition: Boolean = false,
@@ -213,6 +208,13 @@ data class ClockFaceConfig(
/** Call to check whether the clock consumes weather data */
val hasCustomWeatherDataDisplay: Boolean = false,
+
+ /**
+ * Whether this clock has a custom position update animation. If true, the keyguard will call
+ * `onPositionUpdated` to notify the clock of a position update animation. If false, a default
+ * animation will be used (e.g. a simple translation).
+ */
+ val hasCustomPositionUpdatedAnimation: Boolean = false,
)
/** Structure for keeping clock-specific settings */
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 10bb00cad1a0..a8ed84393cfb 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -1,156 +1,13 @@
-# Preserve line number information for debugging stack traces.
--keepattributes SourceFile,LineNumberTable
+-include proguard_common.flags
-# Preserve relationship information that can impact simple class naming.
--keepattributes EnclosingMethod,InnerClasses
-
--keep class com.android.systemui.recents.OverviewProxyRecentsImpl
--keep class com.android.systemui.statusbar.car.CarStatusBar
--keep class com.android.systemui.statusbar.phone.CentralSurfaces
-keep class com.android.systemui.statusbar.tv.TvStatusBar
--keep class ** extends com.android.systemui.SystemUIInitializer {
+-keep class com.android.systemui.SystemUIInitializerImpl {
*;
}
--keep class * extends com.android.systemui.CoreStartable
--keep class * implements com.android.systemui.CoreStartable$Injector
-
-# Needed for builds to properly initialize KeyFrames from xml scene
--keepclassmembers class * extends androidx.constraintlayout.motion.widget.Key {
- public <init>();
-}
-# Needed to ensure callback field references are kept in their respective
-# owning classes when the downstream callback registrars only store weak refs.
-# TODO(b/264686688): Handle these cases with more targeted annotations.
--keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
- private com.android.keyguard.KeyguardUpdateMonitorCallback *;
- private com.android.systemui.privacy.PrivacyConfig$Callback *;
- private com.android.systemui.privacy.PrivacyItemController$Callback *;
- private com.android.systemui.settings.UserTracker$Callback *;
- private com.android.systemui.statusbar.phone.StatusBarWindowCallback *;
- private com.android.systemui.util.service.Observer$Callback *;
- private com.android.systemui.util.service.ObservableServiceConnection$Callback *;
-}
-# Note that these rules are temporary companions to the above rules, required
-# for cases like Kotlin where fields with anonymous types use the anonymous type
-# rather than the supertype.
--if class * extends com.android.keyguard.KeyguardUpdateMonitorCallback
--keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
- <1> *;
-}
--if class * extends com.android.systemui.privacy.PrivacyConfig$Callback
--keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
- <1> *;
-}
--if class * extends com.android.systemui.privacy.PrivacyItemController$Callback
--keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
- <1> *;
-}
--if class * extends com.android.systemui.settings.UserTracker$Callback
--keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
- <1> *;
-}
--if class * extends com.android.systemui.statusbar.phone.StatusBarWindowCallback
--keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
- <1> *;
-}
--if class * extends com.android.systemui.util.service.Observer$Callback
--keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
- <1> *;
-}
--if class * extends com.android.systemui.util.service.ObservableServiceConnection$Callback
--keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
- <1> *;
-}
-
--keepclasseswithmembers class * {
- public <init>(android.content.Context, android.util.AttributeSet);
-}
-
--keep class ** extends androidx.preference.PreferenceFragment
--keep class com.android.systemui.tuner.*
-
-# The plugins subpackage acts as a shared library that might be referenced in
-# dynamically-loaded plugin APKs.
--keep class com.android.systemui.plugins.** {
- *;
-}
--keep class com.android.systemui.fragments.FragmentService$FragmentCreator {
+-keep class com.android.systemui.tv.TvSystemUIInitializer {
*;
}
--keep class androidx.core.app.CoreComponentFactory
--keep public class * extends com.android.systemui.CoreStartable {
- public <init>(android.content.Context);
-}
-
-# Keep the wm shell lib
--keep class com.android.wm.shell.*
-# Keep the protolog group methods that are called by the generated code
--keepclassmembers class com.android.wm.shell.protolog.ShellProtoLogGroup {
- *;
-}
-
--keep,allowoptimization,allowaccessmodification class com.android.systemui.dagger.GlobalRootComponent { !synthetic *; }
--keep,allowoptimization,allowaccessmodification class com.android.systemui.dagger.GlobalRootComponent$SysUIComponentImpl { !synthetic *; }
--keep,allowoptimization,allowaccessmodification class com.android.systemui.dagger.Dagger** { !synthetic *; }
--keep,allowoptimization,allowaccessmodification class com.android.systemui.tv.Dagger** { !synthetic *; }
-
-# Prevent optimization or access modification of any referenced code that may
-# conflict with code in the bootclasspath.
-# TODO(b/222468116): Resolve such collisions in the build system.
--keepnames class android.**.nano.** { *; }
--keepnames class com.android.**.nano.** { *; }
--keepnames class com.android.internal.protolog.** { *; }
--keepnames class android.hardware.common.** { *; }
-
-# Allows proguard to make private and protected methods and fields public as
-# part of optimization. This lets proguard inline trivial getter/setter methods.
--allowaccessmodification
-
-# Removes runtime checks added through Kotlin to JVM code genereration to
-# avoid linear growth as more Kotlin code is converted / added to the codebase.
-# These checks are generally applied to Java platform types (values returned
-# from Java code that don't have nullness annotations), but we remove them to
-# avoid code size increases.
-#
-# See also https://kotlinlang.org/docs/reference/java-interop.html
-#
-# TODO(b/199941987): Consider standardizing these rules in a central place as
-# Kotlin gains adoption with other platform targets.
--assumenosideeffects class kotlin.jvm.internal.Intrinsics {
- # Remove check for method parameters being null
- static void checkParameterIsNotNull(java.lang.Object, java.lang.String);
-
- # When a Java platform type is returned and passed to Kotlin NonNull method,
- # remove the null check
- static void checkExpressionValueIsNotNull(java.lang.Object, java.lang.String);
- static void checkNotNullExpressionValue(java.lang.Object, java.lang.String);
-
- # Remove check that final value returned from method is null, if passing
- # back Java platform type.
- static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String, java.lang.String);
- static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String);
-
- # Null check for accessing a field from a parent class written in Java.
- static void checkFieldIsNotNull(java.lang.Object, java.lang.String, java.lang.String);
- static void checkFieldIsNotNull(java.lang.Object, java.lang.String);
-
- # Removes code generated from !! operator which converts Nullable type to
- # NonNull type. These would throw an NPE immediate after on access.
- static void checkNotNull(java.lang.Object, java.lang.String);
- static void checkNotNullParameter(java.lang.Object, java.lang.String);
-
- # Removes lateinit var check being used before being set. Check is applied
- # on every field access without this.
- static void throwUninitializedPropertyAccessException(java.lang.String);
-}
-# Strip verbose logs.
--assumenosideeffects class android.util.Log {
- static *** v(...);
- static *** isLoggable(...);
-}
--assumenosideeffects class android.util.Slog {
- static *** v(...);
-}
--maximumremovedandroidloglevel 2
+-keep,allowoptimization,allowaccessmodification class com.android.systemui.dagger.DaggerReferenceGlobalRootComponent** { !synthetic *; }
+-keep,allowoptimization,allowaccessmodification class com.android.systemui.tv.DaggerTvGlobalRootComponent** { !synthetic *; } \ No newline at end of file
diff --git a/packages/SystemUI/proguard_common.flags b/packages/SystemUI/proguard_common.flags
new file mode 100644
index 000000000000..1d008cf57ea7
--- /dev/null
+++ b/packages/SystemUI/proguard_common.flags
@@ -0,0 +1,141 @@
+# Preserve line number information for debugging stack traces.
+-keepattributes SourceFile,LineNumberTable
+
+-keep class com.android.systemui.VendorServices
+
+# the `#inject` methods are accessed via reflection to work on ContentProviders
+-keepclassmembers class * extends com.android.systemui.dagger.SysUIComponent { void inject(***); }
+
+# Needed for builds to properly initialize KeyFrames from xml scene
+-keepclassmembers class * extends androidx.constraintlayout.motion.widget.Key {
+ public <init>();
+}
+
+# Needed to ensure callback field references are kept in their respective
+# owning classes when the downstream callback registrars only store weak refs.
+# TODO(b/264686688): Handle these cases with more targeted annotations.
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+ private com.android.keyguard.KeyguardUpdateMonitorCallback *;
+ private com.android.systemui.privacy.PrivacyConfig$Callback *;
+ private com.android.systemui.privacy.PrivacyItemController$Callback *;
+ private com.android.systemui.settings.UserTracker$Callback *;
+ private com.android.systemui.statusbar.phone.StatusBarWindowCallback *;
+ private com.android.systemui.util.service.Observer$Callback *;
+ private com.android.systemui.util.service.ObservableServiceConnection$Callback *;
+}
+# Note that these rules are temporary companions to the above rules, required
+# for cases like Kotlin where fields with anonymous types use the anonymous type
+# rather than the supertype.
+-if class * extends com.android.keyguard.KeyguardUpdateMonitorCallback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+ <1> *;
+}
+-if class * extends com.android.systemui.privacy.PrivacyConfig$Callback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+ <1> *;
+}
+-if class * extends com.android.systemui.privacy.PrivacyItemController$Callback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+ <1> *;
+}
+-if class * extends com.android.systemui.settings.UserTracker$Callback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+ <1> *;
+}
+-if class * extends com.android.systemui.statusbar.phone.StatusBarWindowCallback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+ <1> *;
+}
+-if class * extends com.android.systemui.util.service.Observer$Callback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+ <1> *;
+}
+-if class * extends com.android.systemui.util.service.ObservableServiceConnection$Callback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+ <1> *;
+}
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet);
+}
+
+-keep class ** extends androidx.preference.PreferenceFragment
+-keep class com.android.systemui.tuner.*
+
+# The plugins subpackage acts as a shared library that might be referenced in
+# dynamically-loaded plugin APKs.
+-keep class com.android.systemui.plugins.** {
+ *;
+}
+-keep class com.android.systemui.fragments.FragmentService$FragmentCreator {
+ *;
+}
+-keep class androidx.core.app.CoreComponentFactory
+
+# Keep the wm shell lib
+-keep class com.android.wm.shell.*
+# Keep the protolog group methods that are called by the generated code
+-keepclassmembers class com.android.wm.shell.protolog.ShellProtoLogGroup {
+ *;
+}
+
+# Prevent optimization or access modification of any referenced code that may
+# conflict with code in the bootclasspath.
+# TODO(b/222468116): Resolve such collisions in the build system.
+-keepnames class android.**.nano.** { *; }
+-keepnames class com.android.**.nano.** { *; }
+-keepnames class com.android.internal.protolog.** { *; }
+-keepnames class android.hardware.common.** { *; }
+
+# Allows proguard to make private and protected methods and fields public as
+# part of optimization. This lets proguard inline trivial getter/setter methods.
+-allowaccessmodification
+
+# Removes runtime checks added through Kotlin to JVM code genereration to
+# avoid linear growth as more Kotlin code is converted / added to the codebase.
+# These checks are generally applied to Java platform types (values returned
+# from Java code that don't have nullness annotations), but we remove them to
+# avoid code size increases.
+#
+# See also https://kotlinlang.org/docs/reference/java-interop.html
+#
+# TODO(b/199941987): Consider standardizing these rules in a central place as
+# Kotlin gains adoption with other platform targets.
+-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
+ # Remove check for method parameters being null
+ static void checkParameterIsNotNull(java.lang.Object, java.lang.String);
+
+ # When a Java platform type is returned and passed to Kotlin NonNull method,
+ # remove the null check
+ static void checkExpressionValueIsNotNull(java.lang.Object, java.lang.String);
+ static void checkNotNullExpressionValue(java.lang.Object, java.lang.String);
+
+ # Remove check that final value returned from method is null, if passing
+ # back Java platform type.
+ static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String, java.lang.String);
+ static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String);
+
+ # Null check for accessing a field from a parent class written in Java.
+ static void checkFieldIsNotNull(java.lang.Object, java.lang.String, java.lang.String);
+ static void checkFieldIsNotNull(java.lang.Object, java.lang.String);
+
+ # Removes code generated from !! operator which converts Nullable type to
+ # NonNull type. These would throw an NPE immediate after on access.
+ static void checkNotNull(java.lang.Object, java.lang.String);
+ static void checkNotNullParameter(java.lang.Object, java.lang.String);
+
+ # Removes lateinit var check being used before being set. Check is applied
+ # on every field access without this.
+ static void throwUninitializedPropertyAccessException(java.lang.String);
+}
+
+
+# Strip verbose logs.
+-assumenosideeffects class android.util.Log {
+ static *** v(...);
+ static *** isLoggable(...);
+}
+-assumenosideeffects class android.util.Slog {
+ static *** v(...);
+}
+-maximumremovedandroidloglevel 2
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 26502f1c1752..bbac7b014064 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2467,7 +2467,7 @@
<!-- Controls management controls screen default title [CHAR LIMIT=30] -->
<string name="controls_favorite_default_title">Controls</string>
<!-- Controls management controls screen subtitle [CHAR LIMIT=NONE] -->
- <string name="controls_favorite_subtitle">Choose controls to access from Quick Settings</string>
+ <string name="controls_favorite_subtitle">Choose device controls to access quickly</string>
<!-- Controls management editing screen, user direction for rearranging controls [CHAR LIMIT=NONE] -->
<string name="controls_favorite_rearrange">Hold &amp; drag to rearrange controls</string>
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index 7262a736c433..8b87e2a538ca 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -99,8 +99,10 @@ constructor(
value.initialize(resources, dozeAmount, 0f)
if (regionSamplingEnabled) {
- clock?.smallClock?.view?.addOnLayoutChangeListener(mLayoutChangedListener)
- clock?.largeClock?.view?.addOnLayoutChangeListener(mLayoutChangedListener)
+ clock?.run {
+ smallClock.view.addOnLayoutChangeListener(mLayoutChangedListener)
+ largeClock.view.addOnLayoutChangeListener(mLayoutChangedListener)
+ }
} else {
updateColors()
}
@@ -175,15 +177,17 @@ constructor(
private fun updateColors() {
val wallpaperManager = WallpaperManager.getInstance(context)
if (regionSamplingEnabled && !wallpaperManager.lockScreenWallpaperExists()) {
- if (regionSampler != null) {
- if (regionSampler?.sampledView == clock?.smallClock?.view) {
- smallClockIsDark = regionSampler!!.currentRegionDarkness().isDark
- clock?.smallClock?.events?.onRegionDarknessChanged(smallClockIsDark)
- return
- } else if (regionSampler?.sampledView == clock?.largeClock?.view) {
- largeClockIsDark = regionSampler!!.currentRegionDarkness().isDark
- clock?.largeClock?.events?.onRegionDarknessChanged(largeClockIsDark)
- return
+ regionSampler?.let { regionSampler ->
+ clock?.let { clock ->
+ if (regionSampler.sampledView == clock.smallClock.view) {
+ smallClockIsDark = regionSampler.currentRegionDarkness().isDark
+ clock.smallClock.events.onRegionDarknessChanged(smallClockIsDark)
+ return@updateColors
+ } else if (regionSampler.sampledView == clock.largeClock.view) {
+ largeClockIsDark = regionSampler.currentRegionDarkness().isDark
+ clock.largeClock.events.onRegionDarknessChanged(largeClockIsDark)
+ return@updateColors
+ }
}
}
}
@@ -193,8 +197,10 @@ constructor(
smallClockIsDark = isLightTheme.data == 0
largeClockIsDark = isLightTheme.data == 0
- clock?.smallClock?.events?.onRegionDarknessChanged(smallClockIsDark)
- clock?.largeClock?.events?.onRegionDarknessChanged(largeClockIsDark)
+ clock?.run {
+ smallClock.events.onRegionDarknessChanged(smallClockIsDark)
+ largeClock.events.onRegionDarknessChanged(largeClockIsDark)
+ }
}
private fun updateRegionSampler(sampledRegion: View) {
@@ -240,7 +246,7 @@ constructor(
private val configListener =
object : ConfigurationController.ConfigurationListener {
override fun onThemeChanged() {
- clock?.events?.onColorPaletteChanged(resources)
+ clock?.run { events.onColorPaletteChanged(resources) }
updateColors()
}
@@ -253,7 +259,10 @@ constructor(
object : BatteryStateChangeCallback {
override fun onBatteryLevelChanged(level: Int, pluggedIn: Boolean, charging: Boolean) {
if (isKeyguardVisible && !isCharging && charging) {
- clock?.animations?.charge()
+ clock?.run {
+ smallClock.animations.charge()
+ largeClock.animations.charge()
+ }
}
isCharging = charging
}
@@ -262,7 +271,7 @@ constructor(
private val localeBroadcastReceiver =
object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
- clock?.events?.onLocaleChanged(Locale.getDefault())
+ clock?.run { events.onLocaleChanged(Locale.getDefault()) }
}
}
@@ -272,7 +281,10 @@ constructor(
isKeyguardVisible = visible
if (!featureFlags.isEnabled(DOZING_MIGRATION_1)) {
if (!isKeyguardVisible) {
- clock?.animations?.doze(if (isDozing) 1f else 0f)
+ clock?.run {
+ smallClock.animations.doze(if (isDozing) 1f else 0f)
+ largeClock.animations.doze(if (isDozing) 1f else 0f)
+ }
}
}
@@ -281,19 +293,19 @@ constructor(
}
override fun onTimeFormatChanged(timeFormat: String?) {
- clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context))
+ clock?.run { events.onTimeFormatChanged(DateFormat.is24HourFormat(context)) }
}
override fun onTimeZoneChanged(timeZone: TimeZone) {
- clock?.events?.onTimeZoneChanged(timeZone)
+ clock?.run { events.onTimeZoneChanged(timeZone) }
}
override fun onUserSwitchComplete(userId: Int) {
- clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context))
+ clock?.run { events.onTimeFormatChanged(DateFormat.is24HourFormat(context)) }
}
override fun onWeatherDataChanged(data: WeatherData) {
- clock?.events?.onWeatherDataChanged(data)
+ clock?.run { events.onWeatherDataChanged(data) }
}
}
@@ -349,34 +361,33 @@ constructor(
smallTimeListener = null
largeTimeListener = null
- clock?.smallClock?.let {
- smallTimeListener = TimeListener(it, mainExecutor)
- smallTimeListener?.update(shouldTimeListenerRun)
- }
- clock?.largeClock?.let {
- largeTimeListener = TimeListener(it, mainExecutor)
- largeTimeListener?.update(shouldTimeListenerRun)
+ clock?.let {
+ smallTimeListener = TimeListener(it.smallClock, mainExecutor).apply {
+ update(shouldTimeListenerRun)
+ }
+ largeTimeListener = TimeListener(it.largeClock, mainExecutor).apply {
+ update(shouldTimeListenerRun)
+ }
}
}
private fun updateFontSizes() {
- clock
- ?.smallClock
- ?.events
- ?.onFontSettingChanged(
+ clock?.run {
+ smallClock.events.onFontSettingChanged(
resources.getDimensionPixelSize(R.dimen.small_clock_text_size).toFloat()
)
- clock
- ?.largeClock
- ?.events
- ?.onFontSettingChanged(
+ largeClock.events.onFontSettingChanged(
resources.getDimensionPixelSize(R.dimen.large_clock_text_size).toFloat()
)
+ }
}
private fun handleDoze(doze: Float) {
dozeAmount = doze
- clock?.animations?.doze(dozeAmount)
+ clock?.run {
+ smallClock.animations.doze(dozeAmount)
+ largeClock.animations.doze(dozeAmount)
+ }
smallTimeListener?.update(doze < DOZE_TICKRATE_THRESHOLD)
largeTimeListener?.update(doze < DOZE_TICKRATE_THRESHOLD)
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 5ba0ad62e9fb..a6c782d88e18 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -26,8 +26,6 @@ import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import kotlin.Unit;
-
/**
* Switch to show plugin clock when plugin is connected, otherwise it will show default clock.
*/
@@ -38,6 +36,8 @@ public class KeyguardClockSwitch extends RelativeLayout {
private static final long CLOCK_OUT_MILLIS = 150;
private static final long CLOCK_IN_MILLIS = 200;
+ public static final long CLOCK_IN_START_DELAY_MILLIS = CLOCK_OUT_MILLIS / 2;
+ private static final long STATUS_AREA_START_DELAY_MILLIS = 50;
private static final long STATUS_AREA_MOVE_MILLIS = 350;
@IntDef({LARGE, SMALL})
@@ -173,7 +173,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
msg.setBool1(useLargeClock);
msg.setBool2(animate);
msg.setBool3(mChildrenAreLaidOut);
- return Unit.INSTANCE;
+ return kotlin.Unit.INSTANCE;
}, (msg) -> "updateClockViews"
+ "; useLargeClock=" + msg.getBool1()
+ "; animate=" + msg.getBool2()
@@ -235,7 +235,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
mClockInAnim.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
mClockInAnim.playTogether(ObjectAnimator.ofFloat(in, View.ALPHA, 1f),
ObjectAnimator.ofFloat(in, View.TRANSLATION_Y, direction * mClockSwitchYAmount, 0));
- mClockInAnim.setStartDelay(CLOCK_OUT_MILLIS / 2);
+ mClockInAnim.setStartDelay(CLOCK_IN_START_DELAY_MILLIS);
mClockInAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
mClockInAnim = null;
@@ -247,6 +247,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
mStatusAreaAnim = ObjectAnimator.ofFloat(mStatusArea, View.TRANSLATION_Y,
statusAreaYTranslation);
+ mStatusAreaAnim.setStartDelay(useLargeClock ? STATUS_AREA_START_DELAY_MILLIS : 0L);
mStatusAreaAnim.setDuration(STATUS_AREA_MOVE_MILLIS);
mStatusAreaAnim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
mStatusAreaAnim.addListener(new AnimatorListenerAdapter() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index ad333b7bfbb6..a34c9fa5aced 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -53,11 +53,11 @@ import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
import com.android.systemui.util.ViewController;
+import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.settings.SecureSettings;
import java.io.PrintWriter;
import java.util.Locale;
-import java.util.concurrent.Executor;
import javax.inject.Inject;
@@ -98,7 +98,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
private boolean mOnlyClock = false;
- private final Executor mUiExecutor;
+ private final DelayableExecutor mUiExecutor;
private boolean mCanShowDoubleLineClock = true;
private final ContentObserver mDoubleLineClockObserver = new ContentObserver(null) {
@Override
@@ -133,7 +133,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
LockscreenSmartspaceController smartspaceController,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
SecureSettings secureSettings,
- @Main Executor uiExecutor,
+ @Main DelayableExecutor uiExecutor,
DumpManager dumpManager,
ClockEventController clockEventController,
@KeyguardClockLog LogBuffer logBuffer) {
@@ -344,7 +344,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
ClockController clock = getClock();
boolean appeared = mView.switchToClock(clockSize, animate);
if (clock != null && animate && appeared && clockSize == LARGE) {
- clock.getAnimations().enter();
+ mUiExecutor.executeDelayed(() -> clock.getLargeClock().getAnimations().enter(),
+ KeyguardClockSwitch.CLOCK_IN_START_DELAY_MILLIS);
}
}
@@ -354,7 +355,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
public void animateFoldToAod(float foldFraction) {
ClockController clock = getClock();
if (clock != null) {
- clock.getAnimations().fold(foldFraction);
+ clock.getSmallClock().getAnimations().fold(foldFraction);
+ clock.getLargeClock().getAnimations().fold(foldFraction);
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 0cdef4d63639..edfcb8d0d1a6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -349,7 +349,7 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
ClockController clock = mKeyguardClockSwitchController.getClock();
boolean customClockAnimation = clock != null
- && clock.getConfig().getHasCustomPositionUpdatedAnimation();
+ && clock.getLargeClock().getConfig().getHasCustomPositionUpdatedAnimation();
if (mFeatureFlags.isEnabled(Flags.STEP_CLOCK_ANIMATION) && customClockAnimation) {
// Find the clock, so we can exclude it from this transition.
@@ -436,7 +436,8 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
return;
}
- clock.getAnimations().onPositionUpdated(from, to, animation.getAnimatedFraction());
+ clock.getLargeClock().getAnimations()
+ .onPositionUpdated(from, to, animation.getAnimatedFraction());
});
return anim;
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java
index b6ee4cbc7641..3349fe5f1147 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java
@@ -24,6 +24,7 @@ import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.res.Configuration;
import android.util.Range;
+import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
@@ -68,14 +69,18 @@ public class MagnificationSettingsController implements ComponentCallbacks {
@NonNull Callback settingsControllerCallback,
SecureSettings secureSettings,
WindowMagnificationSettings windowMagnificationSettings) {
- mContext = context;
+ mContext = context.createWindowContext(
+ context.getDisplay(),
+ WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+ null);
+ mContext.setTheme(com.android.systemui.R.style.Theme_SystemUI);
mDisplayId = mContext.getDisplayId();
- mConfiguration = new Configuration(context.getResources().getConfiguration());
+ mConfiguration = new Configuration(mContext.getResources().getConfiguration());
mSettingsControllerCallback = settingsControllerCallback;
if (windowMagnificationSettings != null) {
mWindowMagnificationSettings = windowMagnificationSettings;
} else {
- mWindowMagnificationSettings = new WindowMagnificationSettings(context,
+ mWindowMagnificationSettings = new WindowMagnificationSettings(mContext,
mWindowMagnificationSettingsCallback,
sfVsyncFrameProvider, secureSettings);
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
index 71c5f247b899..6e8275f64eea 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
@@ -559,7 +559,7 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest
final LayoutParams params = new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT,
- LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY,
+ LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSPARENT);
params.gravity = Gravity.TOP | Gravity.START;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index f435b227542f..aeebb010eb1e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -880,7 +880,7 @@ public class AuthContainerView extends LinearLayout
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL,
+ WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,
windowFlags,
PixelFormat.TRANSLUCENT);
lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
index 98a3e4b55256..11ef749573b7 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
@@ -34,7 +34,6 @@ import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.surfaceeffects.ripple.RippleAnimationConfig;
import com.android.systemui.surfaceeffects.ripple.RippleShader;
import com.android.systemui.surfaceeffects.ripple.RippleShader.RippleShape;
import com.android.systemui.surfaceeffects.ripple.RippleView;
@@ -177,7 +176,7 @@ final class WirelessChargingLayout extends FrameLayout {
mRippleView.setBlur(6.5f, 2.5f);
} else {
mRippleView.setDuration(CIRCLE_RIPPLE_ANIMATION_DURATION);
- mRippleView.setColor(color, RippleAnimationConfig.RIPPLE_DEFAULT_ALPHA);
+ mRippleView.setColor(color, RippleShader.RIPPLE_DEFAULT_ALPHA);
}
OnAttachStateChangeListener listener = new OnAttachStateChangeListener() {
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
index 5230159aaef4..0aeab10101f6 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
@@ -32,7 +32,6 @@ import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBO
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SWIPE_DISMISSED;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_TAP_OUTSIDE;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_TIMED_OUT;
-import static com.android.systemui.flags.Flags.CLIPBOARD_REMOTE_BEHAVIOR;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -277,7 +276,7 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
} else if (!mIsMinimized) {
setExpandedView();
}
- if (mFeatureFlags.isEnabled(CLIPBOARD_REMOTE_BEHAVIOR) && mClipboardModel.isRemote()) {
+ if (mClipboardModel.isRemote()) {
mTimeoutHandler.cancelTimeout();
mOnUiUpdate = null;
} else {
@@ -291,8 +290,7 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
mView.setMinimized(false);
switch (model.getType()) {
case TEXT:
- if ((mFeatureFlags.isEnabled(CLIPBOARD_REMOTE_BEHAVIOR) && model.isRemote())
- || DeviceConfig.getBoolean(
+ if (model.isRemote() || DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_SHOW_ACTIONS, false)) {
if (model.getTextLinks() != null) {
classifyText(model);
@@ -326,11 +324,7 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv
mView.showDefaultTextPreview();
break;
}
- if (mFeatureFlags.isEnabled(CLIPBOARD_REMOTE_BEHAVIOR)) {
- if (!model.isRemote()) {
- maybeShowRemoteCopy(model.getClipData());
- }
- } else {
+ if (!model.isRemote()) {
maybeShowRemoteCopy(model.getClipData());
}
if (model.getType() != ClipboardModel.Type.OTHER) {
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 044dd6a47241..75f70ae8eb7a 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -48,7 +48,6 @@ import com.android.systemui.dreams.dagger.DreamModule;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.FlagsModule;
-import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyboard.KeyboardModule;
import com.android.systemui.keyguard.data.BouncerViewModule;
import com.android.systemui.log.dagger.LogModule;
@@ -64,6 +63,7 @@ import com.android.systemui.privacy.PrivacyModule;
import com.android.systemui.qrcodescanner.dagger.QRCodeScannerModule;
import com.android.systemui.qs.FgsManagerController;
import com.android.systemui.qs.FgsManagerControllerImpl;
+import com.android.systemui.qs.QSFragmentStartableModule;
import com.android.systemui.qs.footer.dagger.FooterActionsModule;
import com.android.systemui.recents.Recents;
import com.android.systemui.screenrecord.ScreenRecordModule;
@@ -169,6 +169,7 @@ import javax.inject.Named;
PolicyModule.class,
PrivacyModule.class,
QRCodeScannerModule.class,
+ QSFragmentStartableModule.class,
ScreenshotModule.class,
SensorModule.class,
SecurityRepositoryModule.class,
@@ -198,8 +199,7 @@ import javax.inject.Named;
DozeComponent.class,
ExpandableNotificationRowComponent.class,
KeyguardBouncerComponent.class,
- NotificationShelfComponent.class,
- FragmentService.FragmentCreator.class
+ NotificationShelfComponent.class
})
public abstract class SystemUIModule {
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 8783ec328b40..29c63bb3e000 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -72,7 +72,7 @@ object Flags {
@JvmField
val SIMPLIFIED_APPEAR_FRACTION =
- unreleasedFlag(259395680, "simplified_appear_fraction", teamfood = true)
+ releasedFlag(259395680, "simplified_appear_fraction")
// TODO(b/257315550): Tracking Bug
val NO_HUN_FOR_OLD_WHEN = releasedFlag(118, "no_hun_for_old_when")
@@ -383,7 +383,7 @@ object Flags {
val MEDIA_RETAIN_RECOMMENDATIONS = releasedFlag(916, "media_retain_recommendations")
// TODO(b/270437894): Tracking Bug
- val MEDIA_REMOTE_RESUME = unreleasedFlag(917, "media_remote_resume", teamfood = true)
+ val MEDIA_REMOTE_RESUME = releasedFlag(917, "media_remote_resume")
// 1000 - dock
val SIMULATE_DOCK_THROUGH_CHARGING = releasedFlag(1000, "simulate_dock_through_charging")
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 6a27ee7c0c89..81a520661cfe 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -39,15 +39,16 @@ import com.android.settingslib.applications.InterestingConfigChanges;
import com.android.systemui.plugins.Plugin;
import com.android.systemui.util.leak.LeakDetector;
+import dagger.assisted.Assisted;
+import dagger.assisted.AssistedFactory;
+import dagger.assisted.AssistedInject;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
-import dagger.assisted.Assisted;
-import dagger.assisted.AssistedFactory;
-import dagger.assisted.AssistedInject;
+import javax.inject.Provider;
public class FragmentHostManager {
@@ -322,25 +323,17 @@ public class FragmentHostManager {
return instantiateWithInjections(context, className, arguments);
}
- private Fragment instantiateWithInjections(
- Context context, String className, Bundle args) {
- FragmentService.FragmentInstantiationInfo fragmentInstantiationInfo =
+ private Fragment instantiateWithInjections(Context context, String className, Bundle args) {
+ Provider<? extends Fragment> fragmentProvider =
mManager.getInjectionMap().get(className);
- if (fragmentInstantiationInfo != null) {
- try {
- Fragment f = (Fragment) fragmentInstantiationInfo
- .mMethod
- .invoke(fragmentInstantiationInfo.mDaggerComponent);
- // Setup the args, taken from Fragment#instantiate.
- if (args != null) {
- args.setClassLoader(f.getClass().getClassLoader());
- f.setArguments(args);
- }
- return f;
- } catch (IllegalAccessException | InvocationTargetException e) {
- throw new Fragment.InstantiationException("Unable to instantiate " + className,
- e);
+ if (fragmentProvider != null) {
+ Fragment f = fragmentProvider.get();
+ // Setup the args, taken from Fragment#instantiate.
+ if (args != null) {
+ args.setClassLoader(f.getClass().getClassLoader());
+ f.setArguments(args);
}
+ return f;
}
return Fragment.instantiate(context, className, args);
}
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
index d302b13a68b6..a75c056c5c71 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
@@ -24,16 +24,12 @@ import android.view.View;
import com.android.systemui.Dumpable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.qs.QSFragment;
import com.android.systemui.statusbar.policy.ConfigurationController;
import java.io.PrintWriter;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
import javax.inject.Inject;
-
-import dagger.Subcomponent;
+import javax.inject.Provider;
/**
* Holds a map of root views to FragmentHostStates and generates them as needed.
@@ -49,9 +45,9 @@ public class FragmentService implements Dumpable {
* A map with the means to create fragments via Dagger injection.
*
* key: the fragment class name.
- * value: see {@link FragmentInstantiationInfo}.
+ * value: A {@link Provider} for the Fragment
*/
- private final ArrayMap<String, FragmentInstantiationInfo> mInjectionMap = new ArrayMap<>();
+ private final ArrayMap<String, Provider<? extends Fragment>> mInjectionMap = new ArrayMap<>();
private final Handler mHandler = new Handler();
private final FragmentHostManager.Factory mFragmentHostManagerFactory;
@@ -67,38 +63,31 @@ public class FragmentService implements Dumpable {
@Inject
public FragmentService(
- FragmentCreator.Factory fragmentCreatorFactory,
FragmentHostManager.Factory fragmentHostManagerFactory,
ConfigurationController configurationController,
DumpManager dumpManager) {
mFragmentHostManagerFactory = fragmentHostManagerFactory;
- addFragmentInstantiationProvider(fragmentCreatorFactory.build());
configurationController.addCallback(mConfigurationListener);
- dumpManager.registerDumpable(getClass().getSimpleName(), this);
+ dumpManager.registerNormalDumpable(this);
}
- ArrayMap<String, FragmentInstantiationInfo> getInjectionMap() {
+ ArrayMap<String, Provider<? extends Fragment>> getInjectionMap() {
return mInjectionMap;
}
/**
* Adds a new Dagger component object that provides method(s) to create fragments via injection.
*/
- public void addFragmentInstantiationProvider(Object daggerComponent) {
- for (Method method : daggerComponent.getClass().getDeclaredMethods()) {
- if (Fragment.class.isAssignableFrom(method.getReturnType())
- && (method.getModifiers() & Modifier.PUBLIC) != 0) {
- String fragmentName = method.getReturnType().getName();
- if (mInjectionMap.containsKey(fragmentName)) {
- Log.w(TAG, "Fragment " + fragmentName + " is already provided by different"
- + " Dagger component; Not adding method");
- continue;
- }
- mInjectionMap.put(
- fragmentName, new FragmentInstantiationInfo(method, daggerComponent));
- }
+ public void addFragmentInstantiationProvider(
+ Class<?> fragmentCls, Provider<? extends Fragment> provider) {
+ String fragmentName = fragmentCls.getName();
+ if (mInjectionMap.containsKey(fragmentName)) {
+ Log.w(TAG, "Fragment " + fragmentName + " is already provided by different"
+ + " Dagger component; Not adding method");
+ return;
}
+ mInjectionMap.put(fragmentName, provider);
}
public FragmentHostManager getFragmentHostManager(View view) {
@@ -132,22 +121,6 @@ public class FragmentService implements Dumpable {
}
}
- /**
- * The subcomponent of dagger that holds all fragments that need injection.
- */
- @Subcomponent
- public interface FragmentCreator {
- /** Factory for creating a FragmentCreator. */
- @Subcomponent.Factory
- interface Factory {
- FragmentCreator build();
- }
- /**
- * Inject a QSFragment.
- */
- QSFragment createQSFragment();
- }
-
private class FragmentHostState {
private final View mView;
@@ -170,16 +143,4 @@ public class FragmentService implements Dumpable {
mFragmentHostManager.onConfigurationChanged(newConfig);
}
}
-
- /** An object containing the information needed to instantiate a fragment. */
- static class FragmentInstantiationInfo {
- /** The method that returns a newly-created fragment of the given class. */
- final Method mMethod;
- /** The Dagger component that the method should be invoked on. */
- final Object mDaggerComponent;
- FragmentInstantiationInfo(Method method, Object daggerComponent) {
- this.mMethod = method;
- this.mDaggerComponent = daggerComponent;
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
index 5f6098b8758f..05ab01bf2b9a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
@@ -140,8 +140,10 @@ constructor(
private var authCancellationSignal: CancellationSignal? = null
private var detectCancellationSignal: CancellationSignal? = null
private var faceAcquiredInfoIgnoreList: Set<Int>
+ private var retryCount = 0
private var cancelNotReceivedHandlerJob: Job? = null
+ private var halErrorRetryJob: Job? = null
private val _authenticationStatus: MutableStateFlow<AuthenticationStatus?> =
MutableStateFlow(null)
@@ -228,6 +230,8 @@ constructor(
.onEach { goingAwayOrUserSwitchingInProgress ->
if (goingAwayOrUserSwitchingInProgress) {
_isAuthenticated.value = false
+ retryCount = 0
+ halErrorRetryJob?.cancel()
}
}
.launchIn(applicationScope)
@@ -385,14 +389,11 @@ constructor(
_authenticationStatus.value = errorStatus
_isAuthenticated.value = false
if (errorStatus.isCancellationError()) {
- cancelNotReceivedHandlerJob?.cancel()
- applicationScope.launch {
- faceAuthLogger.launchingQueuedFaceAuthRequest(
- faceAuthRequestedWhileCancellation
- )
- faceAuthRequestedWhileCancellation?.let { authenticate(it) }
- faceAuthRequestedWhileCancellation = null
- }
+ handleFaceCancellationError()
+ }
+ if (errorStatus.isHardwareError()) {
+ faceAuthLogger.hardwareError(errorStatus)
+ handleFaceHardwareError()
}
faceAuthLogger.authenticationError(
errorCode,
@@ -418,6 +419,35 @@ constructor(
}
}
+ private fun handleFaceCancellationError() {
+ cancelNotReceivedHandlerJob?.cancel()
+ applicationScope.launch {
+ faceAuthRequestedWhileCancellation?.let {
+ faceAuthLogger.launchingQueuedFaceAuthRequest(it)
+ authenticate(it)
+ }
+ faceAuthRequestedWhileCancellation = null
+ }
+ }
+
+ private fun handleFaceHardwareError() {
+ if (retryCount < HAL_ERROR_RETRY_MAX) {
+ retryCount++
+ halErrorRetryJob?.cancel()
+ halErrorRetryJob =
+ applicationScope.launch {
+ delay(HAL_ERROR_RETRY_TIMEOUT)
+ if (retryCount < HAL_ERROR_RETRY_MAX) {
+ faceAuthLogger.attemptingRetryAfterHardwareError(retryCount)
+ authenticate(
+ FaceAuthUiEvent.FACE_AUTH_TRIGGERED_RETRY_AFTER_HW_UNAVAILABLE,
+ fallbackToDetection = false
+ )
+ }
+ }
+ }
+ }
+
private fun onFaceAuthRequestCompleted() {
cancellationInProgress = false
_isAuthRunning.value = false
@@ -558,6 +588,12 @@ constructor(
* cancelled.
*/
const val DEFAULT_CANCEL_SIGNAL_TIMEOUT = 3000L
+
+ /** Number of allowed retries whenever there is a face hardware error */
+ const val HAL_ERROR_RETRY_MAX = 20
+
+ /** Timeout before retries whenever there is a HAL error. */
+ const val HAL_ERROR_RETRY_TIMEOUT = 500L // ms
}
override fun dump(pw: PrintWriter, args: Array<out String>) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FaceAuthenticationModels.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FaceAuthenticationModels.kt
index eded9c1454f2..c8bd958615cf 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FaceAuthenticationModels.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FaceAuthenticationModels.kt
@@ -50,6 +50,11 @@ data class ErrorAuthenticationStatus(val msgId: Int, val msg: String?) : Authent
* was cancelled before it completed.
*/
fun isCancellationError() = msgId == FaceManager.FACE_ERROR_CANCELED
+
+ /** Method that checks if [msgId] is a hardware error. */
+ fun isHardwareError() =
+ msgId == FaceManager.FACE_ERROR_HW_UNAVAILABLE ||
+ msgId == FaceManager.FACE_ERROR_UNABLE_TO_PROCESS
}
/** Face detection success message. */
diff --git a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
index 7f6e4a903d76..efd3ad620de0 100644
--- a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
@@ -4,6 +4,7 @@ import android.hardware.face.FaceManager
import android.hardware.face.FaceSensorPropertiesInternal
import com.android.keyguard.FaceAuthUiEvent
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.shared.model.ErrorAuthenticationStatus
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.log.dagger.FaceAuthLog
import com.android.systemui.plugins.log.LogBuffer
@@ -239,4 +240,25 @@ constructor(
{ "Requesting face auth for trigger: $str1" }
)
}
+
+ fun hardwareError(errorStatus: ErrorAuthenticationStatus) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = "${errorStatus.msg}"
+ int1 = errorStatus.msgId
+ },
+ { "Received face hardware error: $str1 , code: $int1" }
+ )
+ }
+
+ fun attemptingRetryAfterHardwareError(retryCount: Int) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { int1 = retryCount },
+ { "Attempting face auth again because of HW error: retry attempt $int1" }
+ )
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
index 8f703765fbd9..aab898e2efcf 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
@@ -85,12 +85,12 @@ constructor(
fun onBubbleExpandChanged(isExpanding: Boolean, key: String?) {
if (!isEnabled) return
- if (key != Bubble.KEY_APP_BUBBLE) return
+ val info = infoReference.getAndSet(null) ?: return
- val info = infoReference.getAndSet(null)
+ if (key != Bubble.getAppBubbleKeyForApp(info.packageName, info.user)) return
// Safe guard mechanism, this callback should only be called for app bubbles.
- if (info?.launchMode != NoteTaskLaunchMode.AppBubble) return
+ if (info.launchMode != NoteTaskLaunchMode.AppBubble) return
if (isExpanding) {
logDebug { "onBubbleExpandChanged - expanding: $info" }
@@ -173,7 +173,7 @@ constructor(
return
}
- val info = resolver.resolveInfo(entryPoint, isKeyguardLocked)
+ val info = resolver.resolveInfo(entryPoint, isKeyguardLocked, user)
if (info == null) {
logDebug { "Default notes app isn't set" }
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt
index 2b9f0af046ff..a75834760d30 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt
@@ -15,10 +15,13 @@
*/
package com.android.systemui.notetask
+import android.os.UserHandle
+
/** Contextual information required to launch a Note Task by [NoteTaskController]. */
data class NoteTaskInfo(
val packageName: String,
val uid: Int,
+ val user: UserHandle,
val entryPoint: NoteTaskEntryPoint? = null,
val isKeyguardLocked: Boolean = false,
) {
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt
index 616f9b526156..89a8526ff42f 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt
@@ -25,7 +25,6 @@ import android.content.pm.PackageManager.ApplicationInfoFlags
import android.os.UserHandle
import android.util.Log
import com.android.systemui.notetask.NoteTaskRoleManagerExt.getDefaultRoleHolderAsUser
-import com.android.systemui.settings.UserTracker
import javax.inject.Inject
class NoteTaskInfoResolver
@@ -33,15 +32,13 @@ class NoteTaskInfoResolver
constructor(
private val roleManager: RoleManager,
private val packageManager: PackageManager,
- private val userTracker: UserTracker,
) {
fun resolveInfo(
entryPoint: NoteTaskEntryPoint? = null,
isKeyguardLocked: Boolean = false,
+ user: UserHandle,
): NoteTaskInfo? {
- val user = userTracker.userHandle
-
val packageName = roleManager.getDefaultRoleHolderAsUser(ROLE_NOTES, user)
if (packageName.isNullOrEmpty()) return null
@@ -49,6 +46,7 @@ constructor(
return NoteTaskInfo(
packageName = packageName,
uid = packageManager.getUidOf(packageName, user),
+ user = user,
entryPoint = entryPoint,
isKeyguardLocked = isKeyguardLocked,
)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentStartable.kt b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentStartable.kt
new file mode 100644
index 000000000000..253560b93f1a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentStartable.kt
@@ -0,0 +1,47 @@
+/*
+ * 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.qs
+
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.fragments.FragmentService
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
+import javax.inject.Inject
+import javax.inject.Provider
+
+@SysUISingleton
+class QSFragmentStartable
+@Inject
+constructor(
+ private val fragmentService: FragmentService,
+ private val qsFragmentProvider: Provider<QSFragment>
+) : CoreStartable {
+ override fun start() {
+ fragmentService.addFragmentInstantiationProvider(QSFragment::class.java, qsFragmentProvider)
+ }
+}
+
+@Module
+interface QSFragmentStartableModule {
+ @Binds
+ @IntoMap
+ @ClassKey(QSFragmentStartable::class)
+ fun bindsQSFragmentStartable(startable: QSFragmentStartable): CoreStartable
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 72ae16e607c8..1714f48f6657 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -71,6 +71,8 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.Utils;
import com.android.systemui.util.concurrency.DelayableExecutor;
+import dagger.Lazy;
+
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -80,8 +82,6 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
-import dagger.Lazy;
-
/**
* Handles tasks and state related to media notifications. For example, there is a 'current' media
* notification, which this class keeps track of.
@@ -161,12 +161,49 @@ public class NotificationMediaManager implements Dumpable {
Log.v(TAG, "DEBUG_MEDIA: onMetadataChanged: " + metadata);
}
mMediaArtworkProcessor.clearCache();
- mMediaMetadata = metadata;
+ mMediaMetadata = cleanMetadata(metadata);
dispatchUpdateMediaMetaData(true /* changed */, true /* allowAnimation */);
}
};
/**
+ * If this build is not configured for lockscreen artwork, clear artwork references from the
+ * metadata to avoid excess memory usage. Otherwise, return as is.
+ * @param data Original metadata
+ * @return a copy without artwork data, or original
+ */
+ private MediaMetadata cleanMetadata(MediaMetadata data) {
+ if (SHOW_LOCKSCREEN_MEDIA_ARTWORK) {
+ return data;
+ }
+ if (data == null) {
+ return null;
+ }
+ if (DEBUG_MEDIA) {
+ String[] artKeys = new String[] {
+ MediaMetadata.METADATA_KEY_ART,
+ MediaMetadata.METADATA_KEY_ALBUM_ART,
+ MediaMetadata.METADATA_KEY_DISPLAY_ICON,
+ MediaMetadata.METADATA_KEY_ALBUM_ART_URI,
+ MediaMetadata.METADATA_KEY_ART_URI,
+ MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI
+ };
+ Log.v(TAG, "DEBUG_MEDIA: removing artwork from metadata");
+ for (String key: artKeys) {
+ Log.v(TAG, " " + key + ": " + data.containsKey(key));
+ }
+ }
+ return new MediaMetadata.Builder(data)
+ .putBitmap(MediaMetadata.METADATA_KEY_ART, null)
+ .putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, null)
+ .putBitmap(MediaMetadata.METADATA_KEY_DISPLAY_ICON, null)
+ .putString(MediaMetadata.METADATA_KEY_ALBUM_ART_URI, null)
+ .putString(MediaMetadata.METADATA_KEY_ART_URI, null)
+ .putString(MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI, null)
+ .build();
+ }
+
+ /**
* Injected constructor. See {@link CentralSurfacesModule}.
*/
public NotificationMediaManager(
@@ -313,6 +350,7 @@ public class NotificationMediaManager implements Dumpable {
return mMediaNotificationKey;
}
+ @VisibleForTesting
public MediaMetadata getMediaMetadata() {
return mMediaMetadata;
}
@@ -350,7 +388,7 @@ public class NotificationMediaManager implements Dumpable {
* update this manager's internal state.
* @return whether the current MediaMetadata changed (and needs to be announced to listeners).
*/
- boolean findPlayingMediaNotification(
+ private boolean findPlayingMediaNotification(
@NonNull Collection<NotificationEntry> allNotifications) {
boolean metaDataChanged = false;
// Promote the media notification with a controller in 'playing' state, if any.
@@ -383,7 +421,7 @@ public class NotificationMediaManager implements Dumpable {
clearCurrentMediaNotificationSession();
mMediaController = controller;
mMediaController.registerCallback(mMediaListener);
- mMediaMetadata = mMediaController.getMetadata();
+ mMediaMetadata = cleanMetadata(mMediaController.getMetadata());
if (DEBUG_MEDIA) {
Log.v(TAG, "DEBUG_MEDIA: insert listener, found new controller: "
+ mMediaController + ", receive metadata: " + mMediaMetadata);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
index f579d304b268..b15d241adac2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
@@ -75,7 +75,7 @@ public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwn
boolean DEBUG_WAKEUP_DELAY = Compile.IS_DEBUG;
// additional instrumentation for testing purposes; intended to be left on during development
boolean CHATTY = DEBUG;
- boolean SHOW_LOCKSCREEN_MEDIA_ARTWORK = true;
+ boolean SHOW_LOCKSCREEN_MEDIA_ARTWORK = false;
String ACTION_FAKE_ARTWORK = "fake_artwork";
int FADE_KEYGUARD_START_DELAY = 100;
int FADE_KEYGUARD_DURATION = 300;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index fab334c5ebc4..b3953a251598 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -232,6 +232,7 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
@@ -1632,7 +1633,9 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
}
}
mCentralSurfacesComponent = mCentralSurfacesComponentFactory.create();
- mFragmentService.addFragmentInstantiationProvider(mCentralSurfacesComponent);
+ mFragmentService.addFragmentInstantiationProvider(
+ CollapsedStatusBarFragment.class,
+ mCentralSurfacesComponent::createCollapsedStatusBarFragment);
mNotificationShadeWindowView = mCentralSurfacesComponent.getNotificationShadeWindowView();
mNotificationShadeWindowViewController = mCentralSurfacesComponent
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
index a9920ec77c23..8f4b32006919 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -101,7 +101,8 @@ class ClockEventControllerTest : SysuiTestCase() {
whenever(smallClockController.events).thenReturn(smallClockEvents)
whenever(largeClockController.events).thenReturn(largeClockEvents)
whenever(clock.events).thenReturn(events)
- whenever(clock.animations).thenReturn(animations)
+ whenever(smallClockController.animations).thenReturn(animations)
+ whenever(largeClockController.animations).thenReturn(animations)
whenever(smallClockController.config)
.thenReturn(ClockFaceConfig(tickRate = ClockTickRate.PER_MINUTE))
whenever(largeClockController.config)
@@ -184,7 +185,7 @@ class ClockEventControllerTest : SysuiTestCase() {
keyguardCaptor.value.onKeyguardVisibilityChanged(true)
batteryCaptor.value.onBatteryLevelChanged(10, false, true)
- verify(animations).charge()
+ verify(animations, times(2)).charge()
}
@Test
@@ -198,7 +199,7 @@ class ClockEventControllerTest : SysuiTestCase() {
batteryCaptor.value.onBatteryLevelChanged(10, false, true)
batteryCaptor.value.onBatteryLevelChanged(10, false, true)
- verify(animations, times(1)).charge()
+ verify(animations, times(2)).charge()
}
@Test
@@ -246,7 +247,7 @@ class ClockEventControllerTest : SysuiTestCase() {
verify(animations, never()).doze(0f)
captor.value.onKeyguardVisibilityChanged(false)
- verify(animations, times(1)).doze(0f)
+ verify(animations, times(2)).doze(0f)
}
@Test
@@ -284,7 +285,7 @@ class ClockEventControllerTest : SysuiTestCase() {
yield()
- verify(animations).doze(0.4f)
+ verify(animations, times(2)).doze(0.4f)
job.cancel()
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index fc906dedfa1d..95db0c096faf 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -184,13 +184,14 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
when(mClockController.getEvents()).thenReturn(mClockEvents);
when(mSmallClockController.getEvents()).thenReturn(mClockFaceEvents);
when(mLargeClockController.getEvents()).thenReturn(mClockFaceEvents);
- when(mClockController.getAnimations()).thenReturn(mClockAnimations);
+ when(mLargeClockController.getAnimations()).thenReturn(mClockAnimations);
+ when(mSmallClockController.getAnimations()).thenReturn(mClockAnimations);
when(mClockRegistry.createCurrentClock()).thenReturn(mClockController);
when(mClockEventController.getClock()).thenReturn(mClockController);
when(mSmallClockController.getConfig())
- .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false));
+ .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false, false));
when(mLargeClockController.getConfig())
- .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false));
+ .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false, false));
mSliceView = new View(getContext());
when(mView.findViewById(R.id.keyguard_slice_view)).thenReturn(mSliceView);
@@ -384,9 +385,9 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
assertEquals(View.VISIBLE, mFakeDateView.getVisibility());
when(mSmallClockController.getConfig())
- .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, true));
+ .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, true, false));
when(mLargeClockController.getConfig())
- .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, true));
+ .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, true, false));
verify(mClockRegistry).registerClockChangeListener(listenerArgumentCaptor.capture());
listenerArgumentCaptor.getValue().onCurrentClockChanged();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
index 2c1d2adb11ee..a2c632936047 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
@@ -130,7 +130,7 @@ public class KeyguardStatusViewControllerTest extends SysuiTestCase {
public void updatePosition_primaryClockAnimation() {
ClockController mockClock = mock(ClockController.class);
when(mKeyguardClockSwitchController.getClock()).thenReturn(mockClock);
- when(mockClock.getConfig()).thenReturn(new ClockConfig(false, false, true));
+ when(mockClock.getConfig()).thenReturn(new ClockConfig(false, true));
mController.updatePosition(10, 15, 20f, true);
@@ -145,7 +145,7 @@ public class KeyguardStatusViewControllerTest extends SysuiTestCase {
public void updatePosition_alternateClockAnimation() {
ClockController mockClock = mock(ClockController.class);
when(mKeyguardClockSwitchController.getClock()).thenReturn(mockClock);
- when(mockClock.getConfig()).thenReturn(new ClockConfig(false, true, true));
+ when(mockClock.getConfig()).thenReturn(new ClockConfig(true, true));
mController.updatePosition(10, 15, 20f, true);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index db86ac6fbb0d..ed40eed54978 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -155,6 +155,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
import org.mockito.internal.util.reflection.FieldSetter;
+import org.mockito.quality.Strictness;
import java.util.ArrayList;
import java.util.Arrays;
@@ -303,6 +304,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mMockitoSession = ExtendedMockito.mockitoSession()
.spyStatic(SubscriptionManager.class)
+ .strictness(Strictness.WARN)
.startMocking();
ExtendedMockito.doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
.when(SubscriptionManager::getDefaultSubscriptionId);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt
index 80c3e5eaff15..937a7a92ec46 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt
@@ -172,64 +172,64 @@ class CameraGestureHelperTest : SysuiTestCase() {
}
@Test
- fun `canCameraGestureBeLaunched - status bar state is keyguard - returns true`() {
+ fun canCameraGestureBeLaunched_statusBarStateIsKeyguard_returnsTrue() {
assertThat(underTest.canCameraGestureBeLaunched(StatusBarState.KEYGUARD)).isTrue()
}
@Test
- fun `canCameraGestureBeLaunched - state is shade-locked - returns true`() {
+ fun canCameraGestureBeLaunched_stateIsShadeLocked_returnsTrue() {
assertThat(underTest.canCameraGestureBeLaunched(StatusBarState.SHADE_LOCKED)).isTrue()
}
@Test
- fun `canCameraGestureBeLaunched - state is keyguard - camera activity on top - returns true`() {
+ fun canCameraGestureBeLaunched_stateIsKeyguard_cameraActivityOnTop_returnsTrue() {
prepare(isCameraActivityRunningOnTop = true)
assertThat(underTest.canCameraGestureBeLaunched(StatusBarState.KEYGUARD)).isTrue()
}
@Test
- fun `canCameraGestureBeLaunched - state is shade-locked - camera activity on top - true`() {
+ fun canCameraGestureBeLaunched_stateIsShadeLocked_cameraActivityOnTop_true() {
prepare(isCameraActivityRunningOnTop = true)
assertThat(underTest.canCameraGestureBeLaunched(StatusBarState.SHADE_LOCKED)).isTrue()
}
@Test
- fun `canCameraGestureBeLaunched - not allowed by admin - returns false`() {
+ fun canCameraGestureBeLaunched_notAllowedByAdmin_returnsFalse() {
prepare(isCameraAllowedByAdmin = false)
assertThat(underTest.canCameraGestureBeLaunched(StatusBarState.KEYGUARD)).isFalse()
}
@Test
- fun `canCameraGestureBeLaunched - intent does not resolve to any app - returns false`() {
+ fun canCameraGestureBeLaunched_intentDoesNotResolveToAnyApp_returnsFalse() {
prepare(installedCameraAppCount = 0)
assertThat(underTest.canCameraGestureBeLaunched(StatusBarState.KEYGUARD)).isFalse()
}
@Test
- fun `canCameraGestureBeLaunched - state is shade - no running tasks - returns true`() {
+ fun canCameraGestureBeLaunched_stateIsShade_noRunningTasks_returnsTrue() {
prepare(isCameraActivityRunningOnTop = false, isTaskListEmpty = true)
assertThat(underTest.canCameraGestureBeLaunched(StatusBarState.SHADE)).isTrue()
}
@Test
- fun `canCameraGestureBeLaunched - state is shade - camera activity on top - returns false`() {
+ fun canCameraGestureBeLaunched_stateIsShade_cameraActivityOnTop_returnsFalse() {
prepare(isCameraActivityRunningOnTop = true)
assertThat(underTest.canCameraGestureBeLaunched(StatusBarState.SHADE)).isFalse()
}
@Test
- fun `canCameraGestureBeLaunched - state is shade - camera activity not on top - true`() {
+ fun canCameraGestureBeLaunched_stateIsShade_cameraActivityNotOnTop_true() {
assertThat(underTest.canCameraGestureBeLaunched(StatusBarState.SHADE)).isTrue()
}
@Test
- fun `launchCamera - only one camera app installed - using secure screen lock option`() {
+ fun launchCamera_onlyOneCameraAppInstalled_usingSecureScreenLockOption() {
val source = 1337
underTest.launchCamera(source)
@@ -238,7 +238,7 @@ class CameraGestureHelperTest : SysuiTestCase() {
}
@Test
- fun `launchCamera - only one camera app installed - using non-secure screen lock option`() {
+ fun launchCamera_onlyOneCameraAppInstalled_usingNonSecureScreenLockOption() {
prepare(isUsingSecureScreenLockOption = false)
val source = 1337
@@ -248,7 +248,7 @@ class CameraGestureHelperTest : SysuiTestCase() {
}
@Test
- fun `launchCamera - multiple camera apps installed - using secure screen lock option`() {
+ fun launchCamera_multipleCameraAppsInstalled_usingSecureScreenLockOption() {
prepare(installedCameraAppCount = 2)
val source = 1337
@@ -262,7 +262,7 @@ class CameraGestureHelperTest : SysuiTestCase() {
}
@Test
- fun `launchCamera - multiple camera apps installed - using non-secure screen lock option`() {
+ fun launchCamera_multipleCameraAppsInstalled_usingNonSecureScreenLockOption() {
prepare(
isUsingSecureScreenLockOption = false,
installedCameraAppCount = 2,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java
index 8600b7c48d33..fe5fa1fdd39f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java
@@ -25,7 +25,6 @@ import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBO
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SHOWN_EXPANDED;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SHOWN_MINIMIZED;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SWIPE_DISMISSED;
-import static com.android.systemui.flags.Flags.CLIPBOARD_REMOTE_BEHAVIOR;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -121,7 +120,6 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
mSampleClipData = new ClipData("Test", new String[]{"text/plain"},
new ClipData.Item("Test Item"));
- mFeatureFlags.set(CLIPBOARD_REMOTE_BEHAVIOR, false);
mOverlayController = new ClipboardOverlayController(
mContext,
@@ -234,7 +232,6 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
@Test
public void test_remoteCopy_withFlagOn() {
- mFeatureFlags.set(CLIPBOARD_REMOTE_BEHAVIOR, true);
when(mClipboardUtils.isRemoteCopy(any(), any(), any())).thenReturn(true);
mOverlayController.setClipData(mSampleClipData, "");
@@ -243,17 +240,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
}
@Test
- public void test_remoteCopy_withFlagOff() {
- when(mClipboardUtils.isRemoteCopy(any(), any(), any())).thenReturn(true);
-
- mOverlayController.setClipData(mSampleClipData, "");
-
- verify(mTimeoutHandler).resetTimeout();
- }
-
- @Test
public void test_nonRemoteCopy() {
- mFeatureFlags.set(CLIPBOARD_REMOTE_BEHAVIOR, true);
when(mClipboardUtils.isRemoteCopy(any(), any(), any())).thenReturn(false);
mOverlayController.setClipData(mSampleClipData, "");
@@ -279,7 +266,6 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase {
public void test_logOnClipboardActionsShown() {
ClipData.Item item = mSampleClipData.getItemAt(0);
item.setTextLinks(Mockito.mock(TextLinks.class));
- mFeatureFlags.set(CLIPBOARD_REMOTE_BEHAVIOR, true);
when(mClipboardUtils.isRemoteCopy(any(Context.class), any(ClipData.class), anyString()))
.thenReturn(true);
when(mClipboardUtils.getAction(any(TextLinks.class), anyString()))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandlerTest.kt
index fe352fd078f0..1b2fc93ddb3f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandlerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandlerTest.kt
@@ -72,7 +72,7 @@ class LongPressHandlingViewInteractionHandlerTest : SysuiTestCase() {
}
@Test
- fun `long-press`() = runTest {
+ fun longPress() = runTest {
val downX = 123
val downY = 456
dispatchTouchEvents(
@@ -91,7 +91,7 @@ class LongPressHandlingViewInteractionHandlerTest : SysuiTestCase() {
}
@Test
- fun `long-press but feature not enabled`() = runTest {
+ fun longPressButFeatureNotEnabled() = runTest {
underTest.isLongPressHandlingEnabled = false
dispatchTouchEvents(
Down(
@@ -106,7 +106,7 @@ class LongPressHandlingViewInteractionHandlerTest : SysuiTestCase() {
}
@Test
- fun `long-press but view not attached`() = runTest {
+ fun longPressButViewNotAttached() = runTest {
isAttachedToWindow = false
dispatchTouchEvents(
Down(
@@ -121,7 +121,7 @@ class LongPressHandlingViewInteractionHandlerTest : SysuiTestCase() {
}
@Test
- fun `dragged too far to be considered a long-press`() = runTest {
+ fun draggedTooFarToBeConsideredAlongPress() = runTest {
dispatchTouchEvents(
Down(
x = 123,
@@ -138,7 +138,7 @@ class LongPressHandlingViewInteractionHandlerTest : SysuiTestCase() {
}
@Test
- fun `held down too briefly to be considered a long-press`() = runTest {
+ fun heldDownTooBrieflyToBeConsideredAlongPress() = runTest {
dispatchTouchEvents(
Down(
x = 123,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/demomode/DemoModeControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/demomode/DemoModeControllerTest.kt
index 87c66b5a98ac..75eec72a949c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/demomode/DemoModeControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/demomode/DemoModeControllerTest.kt
@@ -74,7 +74,7 @@ class DemoModeControllerTest : SysuiTestCase() {
}
@Test
- fun `demo command flow - returns args`() =
+ fun demoCommandFlow_returnsArgs() =
testScope.runTest {
var latest: Bundle? = null
val flow = underTest.demoFlowForCommand(TEST_COMMAND)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt
index a2dc1eb606ed..4ba1bc6dfbbb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt
@@ -5,7 +5,6 @@ import android.os.Looper
import android.test.suitebuilder.annotation.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
-import com.android.systemui.qs.QSFragment
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import org.junit.Before
@@ -13,9 +12,7 @@ import org.junit.Test
@SmallTest
class FragmentServiceTest : SysuiTestCase() {
- private val fragmentCreator = TestFragmentCreator()
- private val fragmenetHostManagerFactory: FragmentHostManager.Factory = mock()
- private val fragmentCreatorFactory = FragmentService.FragmentCreator.Factory { fragmentCreator }
+ private val fragmentHostManagerFactory: FragmentHostManager.Factory = mock()
private lateinit var fragmentService: FragmentService
@@ -25,65 +22,29 @@ class FragmentServiceTest : SysuiTestCase() {
Looper.prepare()
}
- fragmentService =
- FragmentService(
- fragmentCreatorFactory,
- fragmenetHostManagerFactory,
- mock(),
- DumpManager()
- )
- }
-
- @Test
- fun constructor_addsFragmentCreatorMethodsToMap() {
- val map = fragmentService.injectionMap
- assertThat(map).hasSize(2)
- assertThat(map.keys).contains(QSFragment::class.java.name)
- assertThat(map.keys).contains(TestFragmentInCreator::class.java.name)
+ fragmentService = FragmentService(fragmentHostManagerFactory, mock(), DumpManager())
}
@Test
fun addFragmentInstantiationProvider_objectHasNoFragmentMethods_nothingAdded() {
- fragmentService.addFragmentInstantiationProvider(Object())
-
- assertThat(fragmentService.injectionMap).hasSize(2)
- }
-
- @Test
- fun addFragmentInstantiationProvider_objectHasFragmentMethods_methodsAdded() {
- fragmentService.addFragmentInstantiationProvider(
- @Suppress("unused")
- object : Any() {
- fun createTestFragment2() = TestFragment2()
- fun createTestFragment3() = TestFragment3()
- }
- )
+ fragmentService.addFragmentInstantiationProvider(TestFragment::class.java) {
+ TestFragment()
+ }
- val map = fragmentService.injectionMap
- assertThat(map).hasSize(4)
- assertThat(map.keys).contains(TestFragment2::class.java.name)
- assertThat(map.keys).contains(TestFragment3::class.java.name)
+ assertThat(fragmentService.injectionMap).hasSize(1)
}
@Test
fun addFragmentInstantiationProvider_objectFragmentMethodsAlreadyProvided_nothingAdded() {
- fragmentService.addFragmentInstantiationProvider(
- @Suppress("unused")
- object : Any() {
- fun createTestFragment() = TestFragmentInCreator()
- }
- )
-
- assertThat(fragmentService.injectionMap).hasSize(2)
- }
+ fragmentService.addFragmentInstantiationProvider(TestFragment::class.java) {
+ TestFragment()
+ }
+ fragmentService.addFragmentInstantiationProvider(TestFragment::class.java) {
+ TestFragment()
+ }
- class TestFragmentCreator : FragmentService.FragmentCreator {
- override fun createQSFragment(): QSFragment = mock()
- @Suppress("unused")
- fun createTestFragment(): TestFragmentInCreator = TestFragmentInCreator()
+ assertThat(fragmentService.injectionMap).hasSize(1)
}
- class TestFragmentInCreator : Fragment()
- class TestFragment2 : Fragment()
- class TestFragment3 : Fragment()
+ class TestFragment : Fragment()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
index 1044131d17c0..4daecd91efa0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
@@ -211,7 +211,7 @@ class CustomizationProviderTest : SysuiTestCase() {
}
@Test
- fun `onAttachInfo - reportsContext`() {
+ fun onAttachInfo_reportsContext() {
val callback: SystemUIAppComponentFactoryBase.ContextAvailableCallback = mock()
underTest.setContextAvailableCallback(callback)
@@ -254,7 +254,7 @@ class CustomizationProviderTest : SysuiTestCase() {
}
@Test
- fun `insert and query selection`() =
+ fun insertAndQuerySelection() =
testScope.runTest {
val slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START
val affordanceId = AFFORDANCE_2
@@ -278,7 +278,7 @@ class CustomizationProviderTest : SysuiTestCase() {
}
@Test
- fun `query slots`() =
+ fun querySlotsProvidesTwoSlots() =
testScope.runTest {
assertThat(querySlots())
.isEqualTo(
@@ -296,7 +296,7 @@ class CustomizationProviderTest : SysuiTestCase() {
}
@Test
- fun `query affordances`() =
+ fun queryAffordancesProvidesTwoAffordances() =
testScope.runTest {
assertThat(queryAffordances())
.isEqualTo(
@@ -316,7 +316,7 @@ class CustomizationProviderTest : SysuiTestCase() {
}
@Test
- fun `delete and query selection`() =
+ fun deleteAndQuerySelection() =
testScope.runTest {
insertSelection(
slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
@@ -351,7 +351,7 @@ class CustomizationProviderTest : SysuiTestCase() {
}
@Test
- fun `delete all selections in a slot`() =
+ fun deleteAllSelectionsInAslot() =
testScope.runTest {
insertSelection(
slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
index 5bb8367432fc..e20d3afaca53 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
@@ -73,7 +73,7 @@ class CameraQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `affordance triggered -- camera launch called`() {
+ fun affordanceTriggered_cameraLaunchCalled() {
// When
val result = underTest.onTriggered(null)
@@ -84,7 +84,7 @@ class CameraQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `getPickerScreenState - default when launchable`() =
+ fun getPickerScreenState_defaultWhenLaunchable() =
testScope.runTest {
setLaunchable(true)
@@ -93,7 +93,7 @@ class CameraQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `getPickerScreenState - unavailable when camera app not installed`() =
+ fun getPickerScreenState_unavailableWhenCameraAppNotInstalled() =
testScope.runTest {
setLaunchable(isCameraAppInstalled = false)
@@ -102,7 +102,7 @@ class CameraQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `getPickerScreenState - unavailable when camera disabled by admin`() =
+ fun getPickerScreenState_unavailableWhenCameraDisabledByAdmin() =
testScope.runTest {
setLaunchable(isCameraDisabledByDeviceAdmin = true)
@@ -111,7 +111,7 @@ class CameraQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `getPickerScreenState - unavailable when secure camera disabled by admin`() =
+ fun getPickerScreenState_unavailableWhenSecureCameraDisabledByAdmin() =
testScope.runTest {
setLaunchable(isSecureCameraDisabledByDeviceAdmin = true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt
index 64839e2c1105..c326a86a4011 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt
@@ -97,7 +97,7 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `dnd not available - picker state hidden`() =
+ fun dndNotAvailable_pickerStateHidden() =
testScope.runTest {
// given
whenever(zenModeController.isZenAvailable).thenReturn(false)
@@ -113,7 +113,7 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `dnd available - picker state visible`() =
+ fun dndAvailable_pickerStateVisible() =
testScope.runTest {
// given
whenever(zenModeController.isZenAvailable).thenReturn(true)
@@ -132,7 +132,7 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `onTriggered - dnd mode is not ZEN_MODE_OFF - set to ZEN_MODE_OFF`() =
+ fun onTriggered_dndModeIsNotZEN_MODE_OFF_setToZEN_MODE_OFF() =
testScope.runTest {
// given
whenever(zenModeController.isZenAvailable).thenReturn(true)
@@ -157,7 +157,7 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `onTriggered - dnd mode is ZEN_MODE_OFF - setting FOREVER - set zen without condition`() =
+ fun onTriggered_dndModeIsZEN_MODE_OFF_settingFOREVER_setZenWithoutCondition() =
testScope.runTest {
// given
whenever(zenModeController.isZenAvailable).thenReturn(true)
@@ -182,7 +182,7 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `onTriggered - dnd ZEN_MODE_OFF - setting not FOREVER or PROMPT - zen with condition`() =
+ fun onTriggered_dndZEN_MODE_OFF_settingNotFOREVERorPROMPT_zenWithCondition() =
testScope.runTest {
// given
whenever(zenModeController.isZenAvailable).thenReturn(true)
@@ -207,7 +207,7 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `onTriggered - dnd mode is ZEN_MODE_OFF - setting is PROMPT - show dialog`() =
+ fun onTriggered_dndModeIsZEN_MODE_OFF_settingIsPROMPT_showDialog() =
testScope.runTest {
// given
val expandable: Expandable = mock()
@@ -230,7 +230,7 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `lockScreenState - dndAvailable starts as true - change to false - State is Hidden`() =
+ fun lockScreenState_dndAvailableStartsAsTrue_changeToFalse_StateIsHidden() =
testScope.runTest {
// given
whenever(zenModeController.isZenAvailable).thenReturn(true)
@@ -249,7 +249,7 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `lockScreenState - dndMode starts as ZEN_MODE_OFF - change to not OFF - State Visible`() =
+ fun lockScreenState_dndModeStartsAsZEN_MODE_OFF_changeToNotOFF_StateVisible() =
testScope.runTest {
// given
whenever(zenModeController.isZenAvailable).thenReturn(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfigTest.kt
index 31391ee8c0eb..292d06780c5f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfigTest.kt
@@ -60,7 +60,7 @@ class FlashlightQuickAffordanceConfigTest : LeakCheckedTest() {
}
@Test
- fun `flashlight is off -- triggered -- icon is on and active`() = runTest {
+ fun flashlightIsOff_triggered_iconIsOnAndActive() = runTest {
// given
flashlightController.isEnabled = false
flashlightController.isAvailable = true
@@ -83,7 +83,7 @@ class FlashlightQuickAffordanceConfigTest : LeakCheckedTest() {
}
@Test
- fun `flashlight is on -- triggered -- icon is off and inactive`() = runTest {
+ fun flashlightIsOn_triggered_iconIsOffAndInactive() = runTest {
// given
flashlightController.isEnabled = true
flashlightController.isAvailable = true
@@ -106,7 +106,7 @@ class FlashlightQuickAffordanceConfigTest : LeakCheckedTest() {
}
@Test
- fun `flashlight is on -- receives error -- icon is off and inactive`() = runTest {
+ fun flashlightIsOn_receivesError_iconIsOffAndInactive() = runTest {
// given
flashlightController.isEnabled = true
flashlightController.isAvailable = false
@@ -129,7 +129,7 @@ class FlashlightQuickAffordanceConfigTest : LeakCheckedTest() {
}
@Test
- fun `flashlight availability now off -- hidden`() = runTest {
+ fun flashlightAvailabilityNowOff_hidden() = runTest {
// given
flashlightController.isEnabled = true
flashlightController.isAvailable = false
@@ -146,7 +146,7 @@ class FlashlightQuickAffordanceConfigTest : LeakCheckedTest() {
}
@Test
- fun `flashlight availability now on -- flashlight on -- inactive and icon off`() = runTest {
+ fun flashlightAvailabilityNowOn_flashlightOn_inactiveAndIconOff() = runTest {
// given
flashlightController.isEnabled = true
flashlightController.isAvailable = false
@@ -168,7 +168,7 @@ class FlashlightQuickAffordanceConfigTest : LeakCheckedTest() {
}
@Test
- fun `flashlight availability now on -- flashlight off -- inactive and icon off`() = runTest {
+ fun flashlightAvailabilityNowOn_flashlightOff_inactiveAndIconOff() = runTest {
// given
flashlightController.isEnabled = false
flashlightController.isAvailable = false
@@ -190,7 +190,7 @@ class FlashlightQuickAffordanceConfigTest : LeakCheckedTest() {
}
@Test
- fun `flashlight available -- picker state default`() = runTest {
+ fun flashlightAvailable_pickerStateDefault() = runTest {
// given
flashlightController.isAvailable = true
@@ -202,7 +202,7 @@ class FlashlightQuickAffordanceConfigTest : LeakCheckedTest() {
}
@Test
- fun `flashlight not available -- picker state unavailable`() = runTest {
+ fun flashlightNotAvailable_pickerStateUnavailable() = runTest {
// given
flashlightController.isAvailable = false
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt
index 2c1c04cefdc7..26f0cdbc2caa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt
@@ -61,7 +61,7 @@ class HomeControlsKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `state - when cannot show while locked - returns Hidden`() = runBlockingTest {
+ fun state_whenCannotShowWhileLocked_returnsHidden() = runBlockingTest {
whenever(component.canShowWhileLockedSetting).thenReturn(MutableStateFlow(false))
whenever(component.isEnabled()).thenReturn(true)
whenever(component.getTileImageId()).thenReturn(R.drawable.controls_icon)
@@ -81,7 +81,7 @@ class HomeControlsKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `state - when listing controller is missing - returns Hidden`() = runBlockingTest {
+ fun state_whenListingControllerIsMissing_returnsHidden() = runBlockingTest {
whenever(component.isEnabled()).thenReturn(true)
whenever(component.getTileImageId()).thenReturn(R.drawable.controls_icon)
whenever(component.getTileTitleId()).thenReturn(R.string.quick_controls_title)
@@ -100,7 +100,7 @@ class HomeControlsKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `onQuickAffordanceTriggered - canShowWhileLockedSetting is true`() = runBlockingTest {
+ fun onQuickAffordanceTriggered_canShowWhileLockedSettingIsTrue() = runBlockingTest {
whenever(component.canShowWhileLockedSetting).thenReturn(MutableStateFlow(true))
val onClickedResult = underTest.onTriggered(expandable)
@@ -110,7 +110,7 @@ class HomeControlsKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `onQuickAffordanceTriggered - canShowWhileLockedSetting is false`() = runBlockingTest {
+ fun onQuickAffordanceTriggered_canShowWhileLockedSettingIsFalse() = runBlockingTest {
whenever(component.canShowWhileLockedSetting).thenReturn(MutableStateFlow(false))
val onClickedResult = underTest.onTriggered(expandable)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt
index 3bae7f709b69..9a18ba847de8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt
@@ -106,7 +106,7 @@ class KeyguardQuickAffordanceLegacySettingSyncerTest : SysuiTestCase() {
}
@Test
- fun `Setting a setting selects the affordance`() =
+ fun settingAsettingSelectsTheAffordance() =
testScope.runTest {
val job = underTest.startSyncing()
@@ -129,7 +129,7 @@ class KeyguardQuickAffordanceLegacySettingSyncerTest : SysuiTestCase() {
}
@Test
- fun `Clearing a setting selects the affordance`() =
+ fun clearingAsettingSelectsTheAffordance() =
testScope.runTest {
val job = underTest.startSyncing()
@@ -156,7 +156,7 @@ class KeyguardQuickAffordanceLegacySettingSyncerTest : SysuiTestCase() {
}
@Test
- fun `Selecting an affordance sets its setting`() =
+ fun selectingAnAffordanceSetsItsSetting() =
testScope.runTest {
val job = underTest.startSyncing()
@@ -172,7 +172,7 @@ class KeyguardQuickAffordanceLegacySettingSyncerTest : SysuiTestCase() {
}
@Test
- fun `Unselecting an affordance clears its setting`() =
+ fun unselectingAnAffordanceClearsItsSetting() =
testScope.runTest {
val job = underTest.startSyncing()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt
index 1259b478dec5..6989f4467080 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt
@@ -164,7 +164,7 @@ class KeyguardQuickAffordanceLocalUserSelectionManagerTest : SysuiTestCase() {
}
@Test
- fun `remembers selections by user`() = runTest {
+ fun remembersSelectionsByUser() = runTest {
overrideResource(
R.array.config_keyguardQuickAffordanceDefaults,
arrayOf<String>(),
@@ -246,7 +246,7 @@ class KeyguardQuickAffordanceLocalUserSelectionManagerTest : SysuiTestCase() {
}
@Test
- fun `selections respects defaults`() = runTest {
+ fun selectionsRespectsDefaults() = runTest {
val slotId1 = "slot1"
val slotId2 = "slot2"
val affordanceId1 = "affordance1"
@@ -277,7 +277,7 @@ class KeyguardQuickAffordanceLocalUserSelectionManagerTest : SysuiTestCase() {
}
@Test
- fun `selections ignores defaults after selecting an affordance`() = runTest {
+ fun selectionsIgnoresDefaultsAfterSelectingAnAffordance() = runTest {
val slotId1 = "slot1"
val slotId2 = "slot2"
val affordanceId1 = "affordance1"
@@ -309,7 +309,7 @@ class KeyguardQuickAffordanceLocalUserSelectionManagerTest : SysuiTestCase() {
}
@Test
- fun `selections ignores defaults after clearing a slot`() = runTest {
+ fun selectionsIgnoresDefaultsAfterClearingAslot() = runTest {
val slotId1 = "slot1"
val slotId2 = "slot2"
val affordanceId1 = "affordance1"
@@ -341,7 +341,7 @@ class KeyguardQuickAffordanceLocalUserSelectionManagerTest : SysuiTestCase() {
}
@Test
- fun `responds to backup and restore by reloading the selections from disk`() = runTest {
+ fun respondsToBackupAndRestoreByReloadingTheSelectionsFromDisk() = runTest {
overrideResource(R.array.config_keyguardQuickAffordanceDefaults, arrayOf<String>())
val affordanceIdsBySlotId = mutableListOf<Map<String, List<String>>>()
val job =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManagerTest.kt
index c08ef42eef03..a1c9f87ee7bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManagerTest.kt
@@ -112,7 +112,7 @@ class KeyguardQuickAffordanceRemoteUserSelectionManagerTest : SysuiTestCase() {
}
@Test
- fun `selections - primary user process`() =
+ fun selections_primaryUserProcess() =
testScope.runTest {
val values = mutableListOf<Map<String, List<String>>>()
val job = launch { underTest.selections.toList(values) }
@@ -163,7 +163,7 @@ class KeyguardQuickAffordanceRemoteUserSelectionManagerTest : SysuiTestCase() {
}
@Test
- fun `selections - secondary user process - always empty`() =
+ fun selections_secondaryUserProcess_alwaysEmpty() =
testScope.runTest {
whenever(userHandle.isSystem).thenReturn(false)
val values = mutableListOf<Map<String, List<String>>>()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt
index 925c06fe8951..c38827a73e5f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt
@@ -85,7 +85,7 @@ class MuteQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `picker state - volume fixed - not available`() = testScope.runTest {
+ fun pickerState_volumeFixed_notAvailable() = testScope.runTest {
//given
whenever(audioManager.isVolumeFixed).thenReturn(true)
@@ -97,7 +97,7 @@ class MuteQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `picker state - volume not fixed - available`() = testScope.runTest {
+ fun pickerState_volumeNotFixed_available() = testScope.runTest {
//given
whenever(audioManager.isVolumeFixed).thenReturn(false)
@@ -109,7 +109,7 @@ class MuteQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `triggered - state was previously NORMAL - currently SILENT - move to previous state`() = testScope.runTest {
+ fun triggered_stateWasPreviouslyNORMAL_currentlySILENT_moveToPreviousState() = testScope.runTest {
//given
val ringerModeCapture = argumentCaptor<Int>()
whenever(audioManager.ringerModeInternal).thenReturn(AudioManager.RINGER_MODE_NORMAL)
@@ -127,7 +127,7 @@ class MuteQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `triggered - state is not SILENT - move to SILENT ringer`() = testScope.runTest {
+ fun triggered_stateIsNotSILENT_moveToSILENTringer() = testScope.runTest {
//given
val ringerModeCapture = argumentCaptor<Int>()
whenever(audioManager.ringerModeInternal).thenReturn(AudioManager.RINGER_MODE_NORMAL)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt
index facc7475f034..f243d7b45990 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt
@@ -101,7 +101,7 @@ class MuteQuickAffordanceCoreStartableTest : SysuiTestCase() {
}
@Test
- fun `feature flag is OFF - do nothing with keyguardQuickAffordanceRepository`() = testScope.runTest {
+ fun featureFlagIsOFF_doNothingWithKeyguardQuickAffordanceRepository() = testScope.runTest {
//given
whenever(featureFlags.isEnabled(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES)).thenReturn(false)
@@ -114,7 +114,7 @@ class MuteQuickAffordanceCoreStartableTest : SysuiTestCase() {
}
@Test
- fun `feature flag is ON - call to keyguardQuickAffordanceRepository`() = testScope.runTest {
+ fun featureFlagIsON_callToKeyguardQuickAffordanceRepository() = testScope.runTest {
//given
val ringerModeInternal = mock<MutableLiveData<Int>>()
whenever(ringerModeTracker.ringerModeInternal).thenReturn(ringerModeInternal)
@@ -129,7 +129,7 @@ class MuteQuickAffordanceCoreStartableTest : SysuiTestCase() {
}
@Test
- fun `ringer mode is changed to SILENT - do not save to shared preferences`() = testScope.runTest {
+ fun ringerModeIsChangedToSILENT_doNotSaveToSharedPreferences() = testScope.runTest {
//given
val ringerModeInternal = mock<MutableLiveData<Int>>()
val observerCaptor = argumentCaptor<Observer<Int>>()
@@ -147,7 +147,7 @@ class MuteQuickAffordanceCoreStartableTest : SysuiTestCase() {
}
@Test
- fun `ringerModeInternal changes to something not SILENT - is set in sharedpreferences`() = testScope.runTest {
+ fun ringerModeInternalChangesToSomethingNotSILENT_isSetInSharedpreferences() = testScope.runTest {
//given
val newRingerMode = 99
val observerCaptor = argumentCaptor<Observer<Int>>()
@@ -172,7 +172,7 @@ class MuteQuickAffordanceCoreStartableTest : SysuiTestCase() {
}
@Test
- fun `MUTE is in selections - observe ringerModeInternal`() = testScope.runTest {
+ fun MUTEisInSelections_observeRingerModeInternal() = testScope.runTest {
//given
val ringerModeInternal = mock<MutableLiveData<Int>>()
whenever(ringerModeTracker.ringerModeInternal).thenReturn(ringerModeInternal)
@@ -187,7 +187,7 @@ class MuteQuickAffordanceCoreStartableTest : SysuiTestCase() {
}
@Test
- fun `MUTE is in selections 2x - observe ringerModeInternal`() = testScope.runTest {
+ fun MUTEisInSelections2x_observeRingerModeInternal() = testScope.runTest {
//given
val config: KeyguardQuickAffordanceConfig = mock()
whenever(config.key).thenReturn(BuiltInKeyguardQuickAffordanceKeys.MUTE)
@@ -206,7 +206,7 @@ class MuteQuickAffordanceCoreStartableTest : SysuiTestCase() {
}
@Test
- fun `MUTE is not in selections - stop observing ringerModeInternal`() = testScope.runTest {
+ fun MUTEisNotInSelections_stopObservingRingerModeInternal() = testScope.runTest {
//given
val config: KeyguardQuickAffordanceConfig = mock()
whenever(config.key).thenReturn("notmutequickaffordance")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt
index 1adf808cf645..faf18d379270 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt
@@ -55,7 +55,7 @@ class QrCodeScannerKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `affordance - sets up registration and delivers initial model`() = runBlockingTest {
+ fun affordance_setsUpRegistrationAndDeliversInitialModel() = runBlockingTest {
whenever(controller.isEnabledForLockScreenButton).thenReturn(true)
var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
@@ -75,7 +75,7 @@ class QrCodeScannerKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `affordance - scanner activity changed - delivers model with updated intent`() =
+ fun affordance_scannerActivityChanged_deliversModelWithUpdatedIntent() =
runBlockingTest {
whenever(controller.isEnabledForLockScreenButton).thenReturn(true)
var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
@@ -93,7 +93,7 @@ class QrCodeScannerKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `affordance - scanner preference changed - delivers visible model`() = runBlockingTest {
+ fun affordance_scannerPreferenceChanged_deliversVisibleModel() = runBlockingTest {
var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this)
val callbackCaptor = argumentCaptor<QRCodeScannerController.Callback>()
@@ -109,7 +109,7 @@ class QrCodeScannerKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `affordance - scanner preference changed - delivers none`() = runBlockingTest {
+ fun affordance_scannerPreferenceChanged_deliversNone() = runBlockingTest {
var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this)
val callbackCaptor = argumentCaptor<QRCodeScannerController.Callback>()
@@ -136,7 +136,7 @@ class QrCodeScannerKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `getPickerScreenState - enabled if configured on device - can open camera`() = runTest {
+ fun getPickerScreenState_enabledIfConfiguredOnDevice_canOpenCamera() = runTest {
whenever(controller.isAvailableOnDevice).thenReturn(true)
whenever(controller.isAbleToOpenCameraApp).thenReturn(true)
@@ -145,7 +145,7 @@ class QrCodeScannerKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `getPickerScreenState - disabled if configured on device - cannot open camera`() = runTest {
+ fun getPickerScreenState_disabledIfConfiguredOnDevice_cannotOpenCamera() = runTest {
whenever(controller.isAvailableOnDevice).thenReturn(true)
whenever(controller.isAbleToOpenCameraApp).thenReturn(false)
@@ -154,7 +154,7 @@ class QrCodeScannerKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `getPickerScreenState - unavailable if not configured on device`() = runTest {
+ fun getPickerScreenState_unavailableIfNotConfiguredOnDevice() = runTest {
whenever(controller.isAvailableOnDevice).thenReturn(false)
whenever(controller.isAbleToOpenCameraApp).thenReturn(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
index 752963fad92d..952882da1db5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
@@ -69,7 +69,7 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `affordance - keyguard showing - has wallet card - visible model`() = runBlockingTest {
+ fun affordance_keyguardShowing_hasWalletCard_visibleModel() = runBlockingTest {
setUpState()
var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
@@ -90,7 +90,7 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `affordance - wallet not enabled - model is none`() = runBlockingTest {
+ fun affordance_walletNotEnabled_modelIsNone() = runBlockingTest {
setUpState(isWalletEnabled = false)
var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
@@ -102,7 +102,7 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `affordance - query not successful - model is none`() = runBlockingTest {
+ fun affordance_queryNotSuccessful_modelIsNone() = runBlockingTest {
setUpState(isWalletQuerySuccessful = false)
var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
@@ -114,7 +114,7 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `affordance - no selected card - model is none`() = runBlockingTest {
+ fun affordance_noSelectedCard_modelIsNone() = runBlockingTest {
setUpState(hasSelectedCard = false)
var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
@@ -143,7 +143,7 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `getPickerScreenState - default`() = runTest {
+ fun getPickerScreenState_default() = runTest {
setUpState()
assertThat(underTest.getPickerScreenState())
@@ -151,7 +151,7 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `getPickerScreenState - unavailable`() = runTest {
+ fun getPickerScreenState_unavailable() = runTest {
setUpState(
isWalletServiceAvailable = false,
)
@@ -161,7 +161,7 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `getPickerScreenState - disabled when the feature is not enabled`() = runTest {
+ fun getPickerScreenState_disabledWhenTheFeatureIsNotEnabled() = runTest {
setUpState(
isWalletEnabled = false,
)
@@ -171,7 +171,7 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `getPickerScreenState - disabled when there is no card`() = runTest {
+ fun getPickerScreenState_disabledWhenThereIsNoCard() = runTest {
setUpState(
hasSelectedCard = false,
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt
index f1b9c5f0fff8..a9b9c9011636 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt
@@ -73,7 +73,7 @@ class VideoCameraQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `lockScreenState - visible when launchable`() =
+ fun lockScreenState_visibleWhenLaunchable() =
testScope.runTest {
setLaunchable()
@@ -84,7 +84,7 @@ class VideoCameraQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `lockScreenState - hidden when app not installed on device`() =
+ fun lockScreenState_hiddenWhenAppNotInstalledOnDevice() =
testScope.runTest {
setLaunchable(isVideoCameraAppInstalled = false)
@@ -95,7 +95,7 @@ class VideoCameraQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `lockScreenState - hidden when camera disabled by admin`() =
+ fun lockScreenState_hiddenWhenCameraDisabledByAdmin() =
testScope.runTest {
setLaunchable(isCameraDisabledByAdmin = true)
@@ -106,7 +106,7 @@ class VideoCameraQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `getPickerScreenState - default when launchable`() =
+ fun getPickerScreenState_defaultWhenLaunchable() =
testScope.runTest {
setLaunchable()
@@ -115,7 +115,7 @@ class VideoCameraQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `getPickerScreenState - unavailable when app not installed on device`() =
+ fun getPickerScreenState_unavailableWhenAppNotInstalledOnDevice() =
testScope.runTest {
setLaunchable(isVideoCameraAppInstalled = false)
@@ -124,7 +124,7 @@ class VideoCameraQuickAffordanceConfigTest : SysuiTestCase() {
}
@Test
- fun `getPickerScreenState - unavailable when camera disabled by admin`() =
+ fun getPickerScreenState_unavailableWhenCameraDisabledByAdmin() =
testScope.runTest {
setLaunchable(isCameraDisabledByAdmin = true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
index fc75d47c01b7..a76d03b8ba93 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
@@ -21,6 +21,7 @@ import android.app.StatusBarManager.SESSION_KEYGUARD
import android.content.pm.UserInfo
import android.content.pm.UserInfo.FLAG_PRIMARY
import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_CANCELED
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE
import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT
import android.hardware.biometrics.ComponentInfoInternal
import android.hardware.face.FaceAuthenticateOptions
@@ -824,6 +825,26 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
verify(faceManager).scheduleWatchdog()
}
+ @Test
+ fun retryFaceIfThereIsAHardwareError() =
+ testScope.runTest {
+ initCollectors()
+ allPreconditionsToRunFaceAuthAreTrue()
+
+ triggerFaceAuth(fallbackToDetect = false)
+ clearInvocations(faceManager)
+
+ authenticationCallback.value.onAuthenticationError(
+ FACE_ERROR_HW_UNAVAILABLE,
+ "HW unavailable"
+ )
+
+ advanceTimeBy(DeviceEntryFaceAuthRepositoryImpl.HAL_ERROR_RETRY_TIMEOUT)
+ runCurrent()
+
+ faceAuthenticateIsCalled()
+ }
+
private suspend fun TestScope.testGatingCheckForFaceAuth(gatingCheckModifier: () -> Unit) {
initCollectors()
allPreconditionsToRunFaceAuthAreTrue()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
index a668af340e7b..12b8261fd140 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
@@ -258,7 +258,7 @@ class KeyguardQuickAffordanceRepositoryTest : SysuiTestCase() {
}
@Test
- fun `selections for secondary user`() =
+ fun selectionsForSecondaryUser() =
testScope.runTest {
userTracker.set(
userInfos =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
index 3fd97da23157..b53a43427ec7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
@@ -281,7 +281,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun `isDozing - starts with correct initial value for isDozing`() =
+ fun isDozing_startsWithCorrectInitialValueForIsDozing() =
testScope.runTest {
var latest: Boolean? = null
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
index d9d4013b09b9..d0bfaa9bedc9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
@@ -70,7 +70,7 @@ class KeyguardTransitionRepositoryTest : SysuiTestCase() {
}
@Test
- fun `startTransition runs animator to completion`() =
+ fun startTransitionRunsAnimatorToCompletion() =
TestScope().runTest {
val steps = mutableListOf<TransitionStep>()
val job = underTest.transition(AOD, LOCKSCREEN).onEach { steps.add(it) }.launchIn(this)
@@ -86,7 +86,7 @@ class KeyguardTransitionRepositoryTest : SysuiTestCase() {
}
@Test
- fun `starting second transition will cancel the first transition`() =
+ fun startingSecondTransitionWillCancelTheFirstTransition() =
TestScope().runTest {
val steps = mutableListOf<TransitionStep>()
val job = underTest.transition(AOD, LOCKSCREEN).onEach { steps.add(it) }.launchIn(this)
@@ -114,7 +114,7 @@ class KeyguardTransitionRepositoryTest : SysuiTestCase() {
}
@Test
- fun `Null animator enables manual control with updateTransition`() =
+ fun nullAnimatorEnablesManualControlWithUpdateTransition() =
TestScope().runTest {
val steps = mutableListOf<TransitionStep>()
val job = underTest.transition(AOD, LOCKSCREEN).onEach { steps.add(it) }.launchIn(this)
@@ -146,13 +146,13 @@ class KeyguardTransitionRepositoryTest : SysuiTestCase() {
}
@Test
- fun `Attempt to manually update transition with invalid UUID throws exception`() {
+ fun attemptTomanuallyUpdateTransitionWithInvalidUUIDthrowsException() {
underTest.updateTransition(UUID.randomUUID(), 0f, TransitionState.RUNNING)
assertThat(wtfHandler.failed).isTrue()
}
@Test
- fun `Attempt to manually update transition after FINISHED state throws exception`() {
+ fun attemptToManuallyUpdateTransitionAfterFINISHEDstateThrowsException() {
val uuid =
underTest.startTransition(
TransitionInfo(
@@ -171,7 +171,7 @@ class KeyguardTransitionRepositoryTest : SysuiTestCase() {
}
@Test
- fun `Attempt to manually update transition after CANCELED state throws exception`() {
+ fun attemptToManuallyUpdateTransitionAfterCANCELEDstateThrowsException() {
val uuid =
underTest.startTransition(
TransitionInfo(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
index f9493d10ff61..9daf3f3ae2f0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
@@ -48,7 +48,7 @@ class LightRevealScrimRepositoryTest : SysuiTestCase() {
}
@Test
- fun `nextRevealEffect - effect switches between default and biometric with no dupes`() =
+ fun nextRevealEffect_effectSwitchesBetweenDefaultAndBiometricWithNoDupes() =
runTest {
val values = mutableListOf<LightRevealEffect>()
val job = launch { underTest.revealEffect.collect { values.add(it) } }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt
index 77bb12c2cbda..8a0cf4f84da9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt
@@ -92,7 +92,7 @@ class KeyguardLongPressInteractorTest : SysuiTestCase() {
}
@Test
- fun `isEnabled - always false when quick settings are visible`() =
+ fun isEnabled_alwaysFalseWhenQuickSettingsAreVisible() =
testScope.runTest {
val isEnabled = collectLastValue(underTest.isLongPressHandlingEnabled)
KeyguardState.values().forEach { keyguardState ->
@@ -163,7 +163,7 @@ class KeyguardLongPressInteractorTest : SysuiTestCase() {
}
@Test
- fun `long pressed - close dialogs broadcast received - popup dismissed`() =
+ fun longPressed_closeDialogsBroadcastReceived_popupDismissed() =
testScope.runTest {
val isMenuVisible by collectLastValue(underTest.isMenuVisible)
runCurrent()
@@ -211,7 +211,7 @@ class KeyguardLongPressInteractorTest : SysuiTestCase() {
}
@Test
- fun `logs when menu is shown`() =
+ fun logsWhenMenuIsShown() =
testScope.runTest {
collectLastValue(underTest.isMenuVisible)
runCurrent()
@@ -223,7 +223,7 @@ class KeyguardLongPressInteractorTest : SysuiTestCase() {
}
@Test
- fun `logs when menu is clicked`() =
+ fun logsWhenMenuIsClicked() =
testScope.runTest {
collectLastValue(underTest.isMenuVisible)
runCurrent()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
index 503e0025ce5c..96fff6499be5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
@@ -195,7 +195,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
}
@Test
- fun `quickAffordance - bottom start affordance is visible`() =
+ fun quickAffordance_bottomStartAffordanceIsVisible() =
testScope.runTest {
val configKey = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS
homeControls.setState(
@@ -221,7 +221,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
}
@Test
- fun `quickAffordance - bottom end affordance is visible`() =
+ fun quickAffordance_bottomEndAffordanceIsVisible() =
testScope.runTest {
val configKey = BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET
quickAccessWallet.setState(
@@ -246,7 +246,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
}
@Test
- fun `quickAffordance - hidden when all features are disabled by device policy`() =
+ fun quickAffordance_hiddenWhenAllFeaturesAreDisabledByDevicePolicy() =
testScope.runTest {
whenever(devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId))
.thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
@@ -265,7 +265,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
}
@Test
- fun `quickAffordance - hidden when shortcuts feature is disabled by device policy`() =
+ fun quickAffordance_hiddenWhenShortcutsFeatureIsDisabledByDevicePolicy() =
testScope.runTest {
whenever(devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId))
.thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL)
@@ -284,7 +284,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
}
@Test
- fun `quickAffordance - hidden when quick settings is visible`() =
+ fun quickAffordance_hiddenWhenQuickSettingsIsVisible() =
testScope.runTest {
repository.setQuickSettingsVisible(true)
quickAccessWallet.setState(
@@ -302,7 +302,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
}
@Test
- fun `quickAffordance - bottom start affordance hidden while dozing`() =
+ fun quickAffordance_bottomStartAffordanceHiddenWhileDozing() =
testScope.runTest {
repository.setDozing(true)
homeControls.setState(
@@ -319,7 +319,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
}
@Test
- fun `quickAffordance - bottom start affordance hidden when lockscreen is not showing`() =
+ fun quickAffordance_bottomStartAffordanceHiddenWhenLockscreenIsNotShowing() =
testScope.runTest {
repository.setKeyguardShowing(false)
homeControls.setState(
@@ -336,7 +336,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
}
@Test
- fun `quickAffordanceAlwaysVisible - even when lock screen not showing and dozing`() =
+ fun quickAffordanceAlwaysVisible_evenWhenLockScreenNotShowingAndDozing() =
testScope.runTest {
repository.setKeyguardShowing(false)
repository.setDozing(true)
@@ -511,7 +511,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
}
@Test
- fun `unselect - one`() =
+ fun unselect_one() =
testScope.runTest {
featureFlags.set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, true)
homeControls.setState(
@@ -588,7 +588,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
}
@Test
- fun `unselect - all`() =
+ fun unselect_all() =
testScope.runTest {
featureFlags.set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, true)
homeControls.setState(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
index 276b3e39180b..503687df25d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
@@ -52,7 +52,7 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {
}
@Test
- fun `transition collectors receives only appropriate events`() = runTest {
+ fun transitionCollectorsReceivesOnlyAppropriateEvents() = runTest {
val lockscreenToAodSteps by collectValues(underTest.lockscreenToAodTransition)
val aodToLockscreenSteps by collectValues(underTest.aodToLockscreenTransition)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
index e2d0ec3ae01b..fe65236c699f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
@@ -180,7 +180,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `DREAMING to LOCKSCREEN`() =
+ fun DREAMINGtoLOCKSCREEN() =
testScope.runTest {
// GIVEN a device is dreaming
keyguardRepository.setDreamingWithOverlay(true)
@@ -215,7 +215,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `LOCKSCREEN to PRIMARY_BOUNCER via bouncer showing call`() =
+ fun LOCKSCREENtoPRIMARY_BOUNCERviaBouncerShowingCall() =
testScope.runTest {
// GIVEN a device that has at least woken up
keyguardRepository.setWakefulnessModel(startingToWake())
@@ -242,7 +242,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `OCCLUDED to DOZING`() =
+ fun OCCLUDEDtoDOZING() =
testScope.runTest {
// GIVEN a device with AOD not available
keyguardRepository.setAodAvailable(false)
@@ -269,7 +269,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `OCCLUDED to AOD`() =
+ fun OCCLUDEDtoAOD() =
testScope.runTest {
// GIVEN a device with AOD available
keyguardRepository.setAodAvailable(true)
@@ -296,7 +296,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `LOCKSCREEN to DREAMING`() =
+ fun LOCKSCREENtoDREAMING() =
testScope.runTest {
// GIVEN a device that is not dreaming or dozing
keyguardRepository.setDreamingWithOverlay(false)
@@ -327,7 +327,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `LOCKSCREEN to DOZING`() =
+ fun LOCKSCREENtoDOZING() =
testScope.runTest {
// GIVEN a device with AOD not available
keyguardRepository.setAodAvailable(false)
@@ -354,7 +354,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `LOCKSCREEN to AOD`() =
+ fun LOCKSCREENtoAOD() =
testScope.runTest {
// GIVEN a device with AOD available
keyguardRepository.setAodAvailable(true)
@@ -381,7 +381,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `DOZING to LOCKSCREEN`() =
+ fun DOZINGtoLOCKSCREEN() =
testScope.runTest {
// GIVEN a prior transition has run to DOZING
runTransition(KeyguardState.LOCKSCREEN, KeyguardState.DOZING)
@@ -404,7 +404,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `DOZING to LOCKSCREEN cannot be interruped by DREAMING`() =
+ fun DOZINGtoLOCKSCREENcannotBeInterrupedByDREAMING() =
testScope.runTest {
// GIVEN a prior transition has started to LOCKSCREEN
transitionRepository.sendTransitionStep(
@@ -430,7 +430,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `DOZING to GONE`() =
+ fun DOZINGtoGONE() =
testScope.runTest {
// GIVEN a prior transition has run to DOZING
runTransition(KeyguardState.LOCKSCREEN, KeyguardState.DOZING)
@@ -453,7 +453,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `GONE to DOZING`() =
+ fun GONEtoDOZING() =
testScope.runTest {
// GIVEN a device with AOD not available
keyguardRepository.setAodAvailable(false)
@@ -480,7 +480,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `GONE to AOD`() =
+ fun GONEtoAOD() =
testScope.runTest {
// GIVEN a device with AOD available
keyguardRepository.setAodAvailable(true)
@@ -507,7 +507,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `GONE to LOCKSREEN`() =
+ fun GONEtoLOCKSREEN() =
testScope.runTest {
// GIVEN a prior transition has run to GONE
runTransition(KeyguardState.LOCKSCREEN, KeyguardState.GONE)
@@ -530,7 +530,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `GONE to DREAMING`() =
+ fun GONEtoDREAMING() =
testScope.runTest {
// GIVEN a device that is not dreaming or dozing
keyguardRepository.setDreamingWithOverlay(false)
@@ -561,7 +561,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `ALTERNATE_BOUNCER to PRIMARY_BOUNCER`() =
+ fun ALTERNATE_BOUNCERtoPRIMARY_BOUNCER() =
testScope.runTest {
// GIVEN a prior transition has run to ALTERNATE_BOUNCER
runTransition(KeyguardState.LOCKSCREEN, KeyguardState.ALTERNATE_BOUNCER)
@@ -584,7 +584,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `ALTERNATE_BOUNCER to AOD`() =
+ fun ALTERNATE_BOUNCERtoAOD() =
testScope.runTest {
// GIVEN a prior transition has run to ALTERNATE_BOUNCER
bouncerRepository.setAlternateVisible(true)
@@ -613,7 +613,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `ALTERNATE_BOUNCER to DOZING`() =
+ fun ALTERNATE_BOUNCERtoDOZING() =
testScope.runTest {
// GIVEN a prior transition has run to ALTERNATE_BOUNCER
bouncerRepository.setAlternateVisible(true)
@@ -643,7 +643,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `ALTERNATE_BOUNCER to LOCKSCREEN`() =
+ fun ALTERNATE_BOUNCERtoLOCKSCREEN() =
testScope.runTest {
// GIVEN a prior transition has run to ALTERNATE_BOUNCER
bouncerRepository.setAlternateVisible(true)
@@ -671,7 +671,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `PRIMARY_BOUNCER to AOD`() =
+ fun PRIMARY_BOUNCERtoAOD() =
testScope.runTest {
// GIVEN a prior transition has run to PRIMARY_BOUNCER
bouncerRepository.setPrimaryShow(true)
@@ -699,7 +699,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `PRIMARY_BOUNCER to DOZING`() =
+ fun PRIMARY_BOUNCERtoDOZING() =
testScope.runTest {
// GIVEN a prior transition has run to PRIMARY_BOUNCER
bouncerRepository.setPrimaryShow(true)
@@ -727,7 +727,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `PRIMARY_BOUNCER to LOCKSCREEN`() =
+ fun PRIMARY_BOUNCERtoLOCKSCREEN() =
testScope.runTest {
// GIVEN a prior transition has run to PRIMARY_BOUNCER
bouncerRepository.setPrimaryShow(true)
@@ -754,7 +754,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `OCCLUDED to GONE`() =
+ fun OCCLUDEDtoGONE() =
testScope.runTest {
// GIVEN a device on lockscreen
keyguardRepository.setKeyguardShowing(true)
@@ -785,7 +785,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
- fun `OCCLUDED to LOCKSCREEN`() =
+ fun OCCLUDEDtoLOCKSCREEN() =
testScope.runTest {
// GIVEN a device on lockscreen
keyguardRepository.setKeyguardShowing(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt
index 62366164a17d..359854b34496 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt
@@ -69,7 +69,7 @@ class LightRevealScrimInteractorTest : SysuiTestCase() {
}
@Test
- fun `lightRevealEffect - does not change during keyguard transition`() =
+ fun lightRevealEffect_doesNotChangeDuringKeyguardTransition() =
runTest(UnconfinedTestDispatcher()) {
val values = mutableListOf<LightRevealEffect>()
val job = underTest.lightRevealEffect.onEach(values::add).launchIn(this)
@@ -103,7 +103,7 @@ class LightRevealScrimInteractorTest : SysuiTestCase() {
}
@Test
- fun `revealAmount - inverted when appropriate`() =
+ fun revealAmount_invertedWhenAppropriate() =
runTest(UnconfinedTestDispatcher()) {
val values = mutableListOf<Float>()
val job = underTest.revealAmount.onEach(values::add).launchIn(this)
@@ -132,7 +132,7 @@ class LightRevealScrimInteractorTest : SysuiTestCase() {
}
@Test
- fun `revealAmount - ignores transitions that do not affect reveal amount`() =
+ fun revealAmount_ignoresTransitionsThatDoNotAffectRevealAmount() =
runTest(UnconfinedTestDispatcher()) {
val values = mutableListOf<Float>()
val job = underTest.revealAmount.onEach(values::add).launchIn(this)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
index 224eec1bf3ac..2361c59a5c64 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
@@ -251,7 +251,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
}
@Test
- fun `startButton - present - visible model - starts activity on click`() =
+ fun startButton_present_visibleModel_startsActivityOnClick() =
testScope.runTest {
repository.setKeyguardShowing(true)
val latest = collectLastValue(underTest.startButton)
@@ -280,7 +280,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
}
@Test
- fun `startButton - hidden when device policy disables all keyguard features`() =
+ fun startButton_hiddenWhenDevicePolicyDisablesAllKeyguardFeatures() =
testScope.runTest {
whenever(devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId))
.thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
@@ -315,7 +315,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
}
@Test
- fun `startButton - in preview mode - visible even when keyguard not showing`() =
+ fun startButton_inPreviewMode_visibleEvenWhenKeyguardNotShowing() =
testScope.runTest {
underTest.enablePreviewMode(
initiallySelectedSlotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
@@ -359,7 +359,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
}
@Test
- fun `endButton - in higlighted preview mode - dimmed when other is selected`() =
+ fun endButton_inHiglightedPreviewMode_dimmedWhenOtherIsSelected() =
testScope.runTest {
underTest.enablePreviewMode(
initiallySelectedSlotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
@@ -416,7 +416,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
}
@Test
- fun `endButton - present - visible model - do nothing on click`() =
+ fun endButton_present_visibleModel_doNothingOnClick() =
testScope.runTest {
repository.setKeyguardShowing(true)
val latest = collectLastValue(underTest.endButton)
@@ -445,7 +445,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
}
@Test
- fun `startButton - not present - model is hidden`() =
+ fun startButton_notPresent_modelIsHidden() =
testScope.runTest {
val latest = collectLastValue(underTest.startButton)
@@ -524,7 +524,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
}
@Test
- fun `alpha - in preview mode - does not change`() =
+ fun alpha_inPreviewMode_doesNotChange() =
testScope.runTest {
underTest.enablePreviewMode(
initiallySelectedSlotId = null,
@@ -629,7 +629,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
}
@Test
- fun `isClickable - true when alpha at threshold`() =
+ fun isClickable_trueWhenAlphaAtThreshold() =
testScope.runTest {
repository.setKeyguardShowing(true)
repository.setBottomAreaAlpha(
@@ -661,7 +661,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
}
@Test
- fun `isClickable - true when alpha above threshold`() =
+ fun isClickable_trueWhenAlphaAboveThreshold() =
testScope.runTest {
repository.setKeyguardShowing(true)
val latest = collectLastValue(underTest.startButton)
@@ -692,7 +692,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
}
@Test
- fun `isClickable - false when alpha below threshold`() =
+ fun isClickable_falseWhenAlphaBelowThreshold() =
testScope.runTest {
repository.setKeyguardShowing(true)
val latest = collectLastValue(underTest.startButton)
@@ -723,7 +723,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
}
@Test
- fun `isClickable - false when alpha at zero`() =
+ fun isClickable_falseWhenAlphaAtZero() =
testScope.runTest {
repository.setKeyguardShowing(true)
val latest = collectLastValue(underTest.startButton)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt
index ea11f01ed580..afab25092278 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt
@@ -88,7 +88,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() {
}
@Test(expected = IllegalStateException::class)
- fun `repeatWhenAttached - enforces main thread`() =
+ fun repeatWhenAttached_enforcesMainThread() =
testScope.runTest {
Assert.setTestThread(null)
@@ -96,7 +96,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() {
}
@Test(expected = IllegalStateException::class)
- fun `repeatWhenAttached - dispose enforces main thread`() =
+ fun repeatWhenAttached_disposeEnforcesMainThread() =
testScope.runTest {
val disposableHandle = repeatWhenAttached()
Assert.setTestThread(null)
@@ -105,7 +105,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() {
}
@Test
- fun `repeatWhenAttached - view starts detached - runs block when attached`() =
+ fun repeatWhenAttached_viewStartsDetached_runsBlockWhenAttached() =
testScope.runTest {
whenever(view.isAttachedToWindow).thenReturn(false)
repeatWhenAttached()
@@ -120,7 +120,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() {
}
@Test
- fun `repeatWhenAttached - view already attached - immediately runs block`() =
+ fun repeatWhenAttached_viewAlreadyAttached_immediatelyRunsBlock() =
testScope.runTest {
whenever(view.isAttachedToWindow).thenReturn(true)
@@ -132,7 +132,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() {
}
@Test
- fun `repeatWhenAttached - starts visible without focus - STARTED`() =
+ fun repeatWhenAttached_startsVisibleWithoutFocus_STARTED() =
testScope.runTest {
whenever(view.isAttachedToWindow).thenReturn(true)
whenever(view.windowVisibility).thenReturn(View.VISIBLE)
@@ -145,7 +145,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() {
}
@Test
- fun `repeatWhenAttached - starts with focus but invisible - CREATED`() =
+ fun repeatWhenAttached_startsWithFocusButInvisible_CREATED() =
testScope.runTest {
whenever(view.isAttachedToWindow).thenReturn(true)
whenever(view.hasWindowFocus()).thenReturn(true)
@@ -158,7 +158,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() {
}
@Test
- fun `repeatWhenAttached - starts visible and with focus - RESUMED`() =
+ fun repeatWhenAttached_startsVisibleAndWithFocus_RESUMED() =
testScope.runTest {
whenever(view.isAttachedToWindow).thenReturn(true)
whenever(view.windowVisibility).thenReturn(View.VISIBLE)
@@ -172,7 +172,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() {
}
@Test
- fun `repeatWhenAttached - becomes visible without focus - STARTED`() =
+ fun repeatWhenAttached_becomesVisibleWithoutFocus_STARTED() =
testScope.runTest {
whenever(view.isAttachedToWindow).thenReturn(true)
repeatWhenAttached()
@@ -188,7 +188,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() {
}
@Test
- fun `repeatWhenAttached - gains focus but invisible - CREATED`() =
+ fun repeatWhenAttached_gainsFocusButInvisible_CREATED() =
testScope.runTest {
whenever(view.isAttachedToWindow).thenReturn(true)
repeatWhenAttached()
@@ -204,7 +204,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() {
}
@Test
- fun `repeatWhenAttached - becomes visible and gains focus - RESUMED`() =
+ fun repeatWhenAttached_becomesVisibleAndGainsFocus_RESUMED() =
testScope.runTest {
whenever(view.isAttachedToWindow).thenReturn(true)
repeatWhenAttached()
@@ -224,7 +224,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() {
}
@Test
- fun `repeatWhenAttached - view gets detached - destroys the lifecycle`() =
+ fun repeatWhenAttached_viewGetsDetached_destroysTheLifecycle() =
testScope.runTest {
whenever(view.isAttachedToWindow).thenReturn(true)
repeatWhenAttached()
@@ -238,7 +238,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() {
}
@Test
- fun `repeatWhenAttached - view gets reattached - recreates a lifecycle`() =
+ fun repeatWhenAttached_viewGetsReattached_recreatesAlifecycle() =
testScope.runTest {
whenever(view.isAttachedToWindow).thenReturn(true)
repeatWhenAttached()
@@ -255,7 +255,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() {
}
@Test
- fun `repeatWhenAttached - dispose attached`() =
+ fun repeatWhenAttached_disposeAttached() =
testScope.runTest {
whenever(view.isAttachedToWindow).thenReturn(true)
val handle = repeatWhenAttached()
@@ -269,7 +269,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() {
}
@Test
- fun `repeatWhenAttached - dispose never attached`() =
+ fun repeatWhenAttached_disposeNeverAttached() =
testScope.runTest {
whenever(view.isAttachedToWindow).thenReturn(false)
val handle = repeatWhenAttached()
@@ -281,7 +281,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() {
}
@Test
- fun `repeatWhenAttached - dispose previously attached now detached`() =
+ fun repeatWhenAttached_disposePreviouslyAttachedNowDetached() =
testScope.runTest {
whenever(view.isAttachedToWindow).thenReturn(true)
val handle = repeatWhenAttached()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt
index 411b1bd04c52..af83a560d7d0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt
@@ -31,7 +31,7 @@ class TableLogBufferFactoryTest : SysuiTestCase() {
private val underTest = TableLogBufferFactory(dumpManager, systemClock)
@Test
- fun `create - always creates new instance`() {
+ fun create_alwaysCreatesNewInstance() {
val b1 = underTest.create(NAME_1, SIZE)
val b1_copy = underTest.create(NAME_1, SIZE)
val b2 = underTest.create(NAME_2, SIZE)
@@ -43,7 +43,7 @@ class TableLogBufferFactoryTest : SysuiTestCase() {
}
@Test
- fun `getOrCreate - reuses instance`() {
+ fun getOrCreate_reusesInstance() {
val b1 = underTest.getOrCreate(NAME_1, SIZE)
val b1_copy = underTest.getOrCreate(NAME_1, SIZE)
val b2 = underTest.getOrCreate(NAME_2, SIZE)
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 a03bc1e67f3d..7dc622b86b4e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
@@ -98,7 +98,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
whenever(context.getString(R.string.note_task_button_label))
.thenReturn(NOTE_TASK_SHORT_LABEL)
whenever(context.packageManager).thenReturn(packageManager)
- whenever(resolver.resolveInfo(any(), any())).thenReturn(NOTE_TASK_INFO)
+ whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(NOTE_TASK_INFO)
whenever(userManager.isUserUnlocked).thenReturn(true)
whenever(
devicePolicyManager.getKeyguardDisabledFeatures(
@@ -142,7 +142,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
.apply { infoReference.set(expectedInfo) }
.onBubbleExpandChanged(
isExpanding = true,
- key = Bubble.KEY_APP_BUBBLE,
+ key = Bubble.getAppBubbleKeyForApp(expectedInfo.packageName, expectedInfo.user),
)
verify(eventLogger).logNoteTaskOpened(expectedInfo)
@@ -157,7 +157,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
.apply { infoReference.set(expectedInfo) }
.onBubbleExpandChanged(
isExpanding = false,
- key = Bubble.KEY_APP_BUBBLE,
+ key = Bubble.getAppBubbleKeyForApp(expectedInfo.packageName, expectedInfo.user),
)
verify(eventLogger).logNoteTaskClosed(expectedInfo)
@@ -172,7 +172,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
.apply { infoReference.set(expectedInfo) }
.onBubbleExpandChanged(
isExpanding = true,
- key = Bubble.KEY_APP_BUBBLE,
+ key = Bubble.getAppBubbleKeyForApp(expectedInfo.packageName, expectedInfo.user),
)
verifyZeroInteractions(context, bubbles, keyguardManager, userManager, eventLogger)
@@ -186,7 +186,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
.apply { infoReference.set(expectedInfo) }
.onBubbleExpandChanged(
isExpanding = false,
- key = Bubble.KEY_APP_BUBBLE,
+ key = Bubble.getAppBubbleKeyForApp(expectedInfo.packageName, expectedInfo.user),
)
verifyZeroInteractions(context, bubbles, keyguardManager, userManager, eventLogger)
@@ -208,7 +208,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
createNoteTaskController(isEnabled = false)
.onBubbleExpandChanged(
isExpanding = true,
- key = Bubble.KEY_APP_BUBBLE,
+ key = Bubble.getAppBubbleKeyForApp(NOTE_TASK_INFO.packageName, NOTE_TASK_INFO.user),
)
verifyZeroInteractions(context, bubbles, keyguardManager, userManager, eventLogger)
@@ -224,7 +224,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
isKeyguardLocked = true,
)
whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
- whenever(resolver.resolveInfo(any(), any())).thenReturn(expectedInfo)
+ whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
createNoteTaskController()
.showNoteTask(
@@ -256,9 +256,10 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
NOTE_TASK_INFO.copy(
entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
isKeyguardLocked = true,
+ user = user10,
)
whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
- whenever(resolver.resolveInfo(any(), any())).thenReturn(expectedInfo)
+ whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
createNoteTaskController()
.showNoteTaskAsUser(
@@ -292,7 +293,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
isKeyguardLocked = true,
)
whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
- whenever(resolver.resolveInfo(any(), any())).thenReturn(expectedInfo)
+ whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
whenever(activityManager.getRunningTasks(anyInt()))
.thenReturn(listOf(NOTE_RUNNING_TASK_INFO))
@@ -318,7 +319,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
isKeyguardLocked = false,
)
- whenever(resolver.resolveInfo(any(), any())).thenReturn(expectedInfo)
+ whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
createNoteTaskController()
@@ -344,7 +345,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
@Test
fun showNoteTask_intentResolverReturnsNull_shouldShowToast() {
- whenever(resolver.resolveInfo(any(), any())).thenReturn(null)
+ whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(null)
val noteTaskController = spy(createNoteTaskController())
doNothing().whenever(noteTaskController).showNoDefaultNotesAppToast()
@@ -384,7 +385,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
isKeyguardLocked = true,
)
whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
- whenever(resolver.resolveInfo(any(), any())).thenReturn(expectedInfo)
+ whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
createNoteTaskController()
.showNoteTask(
@@ -717,6 +718,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
NoteTaskInfo(
packageName = NOTE_TASK_PACKAGE_NAME,
uid = NOTE_TASK_UID,
+ user = UserHandle.of(0),
)
private val NOTE_RUNNING_TASK_INFO =
ActivityManager.RunningTaskInfo().apply {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskEventLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskEventLoggerTest.kt
index a4df346776a0..b4f5528cb523 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskEventLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskEventLoggerTest.kt
@@ -15,6 +15,7 @@
*/
package com.android.systemui.notetask
+import android.os.UserHandle
import android.test.suitebuilder.annotation.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.internal.logging.UiEventLogger
@@ -44,7 +45,7 @@ internal class NoteTaskEventLoggerTest : SysuiTestCase() {
NoteTaskEventLogger(uiEventLogger)
private fun createNoteTaskInfo(): NoteTaskInfo =
- NoteTaskInfo(packageName = NOTES_PACKAGE_NAME, uid = NOTES_UID)
+ NoteTaskInfo(packageName = NOTES_PACKAGE_NAME, uid = NOTES_UID, UserHandle.of(0))
@Before
fun setUp() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt
index 0c945dfa4b4c..e09c804e4611 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt
@@ -22,8 +22,6 @@ import android.content.pm.PackageManager
import android.test.suitebuilder.annotation.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.systemui.SysuiTestCase
-import com.android.systemui.settings.FakeUserTracker
-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
@@ -46,14 +44,13 @@ internal class NoteTaskInfoResolverTest : SysuiTestCase() {
@Mock lateinit var packageManager: PackageManager
@Mock lateinit var roleManager: RoleManager
- private val userTracker: UserTracker = FakeUserTracker()
private lateinit var underTest: NoteTaskInfoResolver
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- underTest = NoteTaskInfoResolver(roleManager, packageManager, userTracker)
+ underTest = NoteTaskInfoResolver(roleManager, packageManager)
}
@Test
@@ -72,11 +69,12 @@ internal class NoteTaskInfoResolverTest : SysuiTestCase() {
)
.thenReturn(ApplicationInfo().apply { this.uid = uid })
- val actual = underTest.resolveInfo()
+ val actual = underTest.resolveInfo(user = context.user)
requireNotNull(actual) { "Note task info must not be null" }
assertThat(actual.packageName).isEqualTo(packageName)
assertThat(actual.uid).isEqualTo(uid)
+ assertThat(actual.user).isEqualTo(context.user)
}
@Test
@@ -94,11 +92,12 @@ internal class NoteTaskInfoResolverTest : SysuiTestCase() {
)
.thenThrow(PackageManager.NameNotFoundException(packageName))
- val actual = underTest.resolveInfo()
+ val actual = underTest.resolveInfo(user = context.user)
requireNotNull(actual) { "Note task info must not be null" }
assertThat(actual.packageName).isEqualTo(packageName)
assertThat(actual.uid).isEqualTo(0)
+ assertThat(actual.user).isEqualTo(context.user)
}
@Test
@@ -107,7 +106,7 @@ internal class NoteTaskInfoResolverTest : SysuiTestCase() {
emptyList<String>()
}
- val actual = underTest.resolveInfo()
+ val actual = underTest.resolveInfo(user = context.user)
assertThat(actual).isNull()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt
index 91cd6ae5d988..34354504abf0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt
@@ -15,6 +15,7 @@
*/
package com.android.systemui.notetask
+import android.os.UserHandle
import android.test.suitebuilder.annotation.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.systemui.SysuiTestCase
@@ -28,7 +29,7 @@ import org.junit.runner.RunWith
internal class NoteTaskInfoTest : SysuiTestCase() {
private fun createNoteTaskInfo(): NoteTaskInfo =
- NoteTaskInfo(packageName = NOTES_PACKAGE_NAME, uid = NOTES_UID)
+ NoteTaskInfo(packageName = NOTES_PACKAGE_NAME, uid = NOTES_UID, UserHandle.of(0))
@Test
fun launchMode_keyguardLocked_launchModeActivity() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/data/repository/PowerRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/power/data/repository/PowerRepositoryImplTest.kt
index 249a91b0982a..bb3b3f709a7b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/data/repository/PowerRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/data/repository/PowerRepositoryImplTest.kt
@@ -66,7 +66,7 @@ class PowerRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun `isInteractive - registers for broadcasts`() =
+ fun isInteractive_registersForBroadcasts() =
runBlocking(IMMEDIATE) {
val job = underTest.isInteractive.onEach {}.launchIn(this)
@@ -78,7 +78,7 @@ class PowerRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun `isInteractive - unregisters from broadcasts`() =
+ fun isInteractive_unregistersFromBroadcasts() =
runBlocking(IMMEDIATE) {
val job = underTest.isInteractive.onEach {}.launchIn(this)
verifyRegistered()
@@ -89,7 +89,7 @@ class PowerRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun `isInteractive - emits initial true value if screen was on`() =
+ fun isInteractive_emitsInitialTrueValueIfScreenWasOn() =
runBlocking(IMMEDIATE) {
isInteractive = true
var value: Boolean? = null
@@ -102,7 +102,7 @@ class PowerRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun `isInteractive - emits initial false value if screen was off`() =
+ fun isInteractive_emitsInitialFalseValueIfScreenWasOff() =
runBlocking(IMMEDIATE) {
isInteractive = false
var value: Boolean? = null
@@ -115,7 +115,7 @@ class PowerRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun `isInteractive - emits true when the screen turns on`() =
+ fun isInteractive_emitsTrueWhenTheScreenTurnsOn() =
runBlocking(IMMEDIATE) {
var value: Boolean? = null
val job = underTest.isInteractive.onEach { value = it }.launchIn(this)
@@ -129,7 +129,7 @@ class PowerRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun `isInteractive - emits false when the screen turns off`() =
+ fun isInteractive_emitsFalseWhenTheScreenTurnsOff() =
runBlocking(IMMEDIATE) {
var value: Boolean? = null
val job = underTest.isInteractive.onEach { value = it }.launchIn(this)
@@ -143,7 +143,7 @@ class PowerRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun `isInteractive - emits correctly over time`() =
+ fun isInteractive_emitsCorrectlyOverTime() =
runBlocking(IMMEDIATE) {
val values = mutableListOf<Boolean>()
val job = underTest.isInteractive.onEach(values::add).launchIn(this)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt
index bf6a37ec8eff..31d451227a9b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt
@@ -47,7 +47,7 @@ class PowerInteractorTest : SysuiTestCase() {
}
@Test
- fun `isInteractive - screen turns off`() =
+ fun isInteractive_screenTurnsOff() =
runBlocking(IMMEDIATE) {
repository.setInteractive(true)
var value: Boolean? = null
@@ -60,7 +60,7 @@ class PowerInteractorTest : SysuiTestCase() {
}
@Test
- fun `isInteractive - becomes interactive`() =
+ fun isInteractive_becomesInteractive() =
runBlocking(IMMEDIATE) {
repository.setInteractive(false)
var value: Boolean? = null
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
index 8cb5d31fff22..355c4b667333 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
@@ -153,7 +153,7 @@ class OverviewProxyServiceTest : SysuiTestCase() {
}
@Test
- fun `WakefulnessLifecycle - dispatchFinishedWakingUp sets SysUI flag to AWAKE`() {
+ fun wakefulnessLifecycle_dispatchFinishedWakingUpSetsSysUIflagToAWAKE() {
// WakefulnessLifecycle is initialized to AWAKE initially, and won't emit a noop.
wakefulnessLifecycle.dispatchFinishedGoingToSleep()
clearInvocations(overviewProxy)
@@ -167,7 +167,7 @@ class OverviewProxyServiceTest : SysuiTestCase() {
}
@Test
- fun `WakefulnessLifecycle - dispatchStartedWakingUp sets SysUI flag to WAKING`() {
+ fun wakefulnessLifecycle_dispatchStartedWakingUpSetsSysUIflagToWAKING() {
wakefulnessLifecycle.dispatchStartedWakingUp(PowerManager.WAKE_REASON_UNKNOWN)
verify(overviewProxy)
@@ -177,7 +177,7 @@ class OverviewProxyServiceTest : SysuiTestCase() {
}
@Test
- fun `WakefulnessLifecycle - dispatchFinishedGoingToSleep sets SysUI flag to ASLEEP`() {
+ fun wakefulnessLifecycle_dispatchFinishedGoingToSleepSetsSysUIflagToASLEEP() {
wakefulnessLifecycle.dispatchFinishedGoingToSleep()
verify(overviewProxy)
@@ -187,7 +187,7 @@ class OverviewProxyServiceTest : SysuiTestCase() {
}
@Test
- fun `WakefulnessLifecycle - dispatchStartedGoingToSleep sets SysUI flag to GOING_TO_SLEEP`() {
+ fun wakefulnessLifecycle_dispatchStartedGoingToSleepSetsSysUIflagToGOING_TO_SLEEP() {
wakefulnessLifecycle.dispatchStartedGoingToSleep(
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
index 57b6b2bd6fde..beb981d89735 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
@@ -73,7 +73,7 @@ class UserTrackerImplReceiveTest : SysuiTestCase() {
}
@Test
- fun `calls callback and updates profiles when an intent received`() {
+ fun callsCallbackAndUpdatesProfilesWhenAnIntentReceived() {
tracker.initialize(0)
tracker.addCallback(callback, executor)
val profileID = tracker.userId + 10
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QsBatteryModeControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/QsBatteryModeControllerTest.kt
index b547318a99b6..d421acac2daa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QsBatteryModeControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QsBatteryModeControllerTest.kt
@@ -54,7 +54,7 @@ class QsBatteryModeControllerTest : SysuiTestCase() {
}
@Test
- fun `returns MODE_ON for qqs with center cutout`() {
+ fun returnsMODE_ONforQqsWithCenterCutout() {
assertThat(
controller.getBatteryMode(CENTER_TOP_CUTOUT, QQS_START_FRAME.prevFrameToFraction())
)
@@ -62,13 +62,13 @@ class QsBatteryModeControllerTest : SysuiTestCase() {
}
@Test
- fun `returns MODE_ESTIMATE for qs with center cutout`() {
+ fun returnsMODE_ESTIMATEforQsWithCenterCutout() {
assertThat(controller.getBatteryMode(CENTER_TOP_CUTOUT, QS_END_FRAME.nextFrameToFraction()))
.isEqualTo(BatteryMeterView.MODE_ESTIMATE)
}
@Test
- fun `returns MODE_ON for qqs with corner cutout`() {
+ fun returnsMODE_ONforQqsWithCornerCutout() {
whenever(insetsProvider.currentRotationHasCornerCutout()).thenReturn(true)
assertThat(
@@ -78,7 +78,7 @@ class QsBatteryModeControllerTest : SysuiTestCase() {
}
@Test
- fun `returns MODE_ESTIMATE for qs with corner cutout`() {
+ fun returnsMODE_ESTIMATEforQsWithCornerCutout() {
whenever(insetsProvider.currentRotationHasCornerCutout()).thenReturn(true)
assertThat(controller.getBatteryMode(CENTER_TOP_CUTOUT, QS_END_FRAME.nextFrameToFraction()))
@@ -86,7 +86,7 @@ class QsBatteryModeControllerTest : SysuiTestCase() {
}
@Test
- fun `returns null in-between`() {
+ fun returnsNullInBetween() {
assertThat(
controller.getBatteryMode(CENTER_TOP_CUTOUT, QQS_START_FRAME.nextFrameToFraction())
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
index 76f7401adbb2..9fe75abddf9c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
@@ -366,7 +366,7 @@ class ShadeHeaderControllerTest : SysuiTestCase() {
}
@Test
- fun `battery mode controller called when qsExpandedFraction changes`() {
+ fun batteryModeControllerCalledWhenQsExpandedFractionChanges() {
whenever(qsBatteryModeController.getBatteryMode(Mockito.same(null), eq(0f)))
.thenReturn(BatteryMeterView.MODE_ON)
whenever(qsBatteryModeController.getBatteryMode(Mockito.same(null), eq(1f)))
@@ -825,7 +825,7 @@ class ShadeHeaderControllerTest : SysuiTestCase() {
}
@Test
- fun `carrier left padding is set when clock layout changes`() {
+ fun carrierLeftPaddingIsSetWhenClockLayoutChanges() {
val width = 200
whenever(clock.width).thenReturn(width)
whenever(clock.scaleX).thenReturn(2.57f) // 2.57 comes from qs_header.xml
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
index 7fa27f34cd9f..3f3faf7f2327 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
@@ -201,7 +201,7 @@ class DefaultClockProviderTest : SysuiTestCase() {
@Test
fun test_aodClock_always_whiteColor() {
val clock = provider.createClock(DEFAULT_CLOCK_ID)
- clock.animations.doze(0.9f) // set AOD mode to active
+ clock.smallClock.animations.doze(0.9f) // set AOD mode to active
clock.smallClock.events.onRegionDarknessChanged(true)
verify((clock.smallClock.view as AnimatableClockView), never()).animateAppearOnLockscreen()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMediaManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMediaManagerTest.kt
index 9d6ea857fefc..b997f6447690 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMediaManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMediaManagerTest.kt
@@ -16,11 +16,34 @@
package com.android.systemui.statusbar
+import android.app.Notification
+import android.app.WallpaperManager
+import android.graphics.Bitmap
+import android.media.MediaMetadata
+import android.media.session.MediaSession
+import android.media.session.PlaybackState
import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.colorextraction.SysuiColorExtractor
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.media.controls.pipeline.MediaDataManager
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.notification.collection.NotifCollection
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider
+import com.android.systemui.statusbar.phone.CentralSurfaces
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.whenever
-import org.junit.After
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import dagger.Lazy
+import java.util.Optional
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -32,39 +55,121 @@ import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
-/**
- * Temporary test for the lock screen live wallpaper project.
- *
- * TODO(b/273443374): remove this test
- */
@RunWith(AndroidTestingRunner::class)
@SmallTest
+@RunWithLooper
class NotificationMediaManagerTest : SysuiTestCase() {
- @Mock private lateinit var notificationMediaManager: NotificationMediaManager
+ @Mock private lateinit var centralSurfaces: CentralSurfaces
+ @Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
+ @Mock private lateinit var visibilityProvider: NotificationVisibilityProvider
+ @Mock private lateinit var mediaArtworkProcessor: MediaArtworkProcessor
+ @Mock private lateinit var keyguardBypassController: KeyguardBypassController
+ @Mock private lateinit var notifPipeline: NotifPipeline
+ @Mock private lateinit var notifCollection: NotifCollection
+ @Mock private lateinit var mediaDataManager: MediaDataManager
+ @Mock private lateinit var statusBarStateController: StatusBarStateController
+ @Mock private lateinit var colorExtractor: SysuiColorExtractor
+ @Mock private lateinit var keyguardStateController: KeyguardStateController
+ @Mock private lateinit var dumpManager: DumpManager
+ @Mock private lateinit var wallpaperManager: WallpaperManager
+
+ @Mock private lateinit var notificationEntry: NotificationEntry
+
+ lateinit var manager: NotificationMediaManager
+ val clock = FakeSystemClock()
+ val mainExecutor: DelayableExecutor = FakeExecutor(clock)
+ @Mock private lateinit var mockManager: NotificationMediaManager
@Mock private lateinit var mockBackDropView: BackDropView
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- doCallRealMethod()
- .whenever(notificationMediaManager)
- .updateMediaMetaData(anyBoolean(), anyBoolean())
- doReturn(mockBackDropView).whenever(notificationMediaManager).backDropView
- }
+ doCallRealMethod().whenever(mockManager).updateMediaMetaData(anyBoolean(), anyBoolean())
+ doReturn(mockBackDropView).whenever(mockManager).backDropView
- @After fun tearDown() {}
+ manager =
+ NotificationMediaManager(
+ context,
+ Lazy { Optional.of(centralSurfaces) },
+ Lazy { notificationShadeWindowController },
+ visibilityProvider,
+ mediaArtworkProcessor,
+ keyguardBypassController,
+ notifPipeline,
+ notifCollection,
+ mainExecutor,
+ mediaDataManager,
+ statusBarStateController,
+ colorExtractor,
+ keyguardStateController,
+ dumpManager,
+ wallpaperManager,
+ )
+ }
- /** Check that updateMediaMetaData is a no-op with mIsLockscreenLiveWallpaperEnabled = true */
+ /**
+ * Check that updateMediaMetaData is a no-op with mIsLockscreenLiveWallpaperEnabled = true
+ * Temporary test for the lock screen live wallpaper project.
+ *
+ * TODO(b/273443374): remove this test
+ */
@Test
fun testUpdateMediaMetaDataDisabled() {
- notificationMediaManager.mIsLockscreenLiveWallpaperEnabled = true
+ mockManager.mIsLockscreenLiveWallpaperEnabled = true
for (metaDataChanged in listOf(true, false)) {
for (allowEnterAnimation in listOf(true, false)) {
- notificationMediaManager.updateMediaMetaData(metaDataChanged, allowEnterAnimation)
- verify(notificationMediaManager, never()).mediaMetadata
+ mockManager.updateMediaMetaData(metaDataChanged, allowEnterAnimation)
+ verify(mockManager, never()).mediaMetadata
}
}
}
+
+ @Test
+ fun testMetadataUpdated_doesNotRetainArtwork() {
+ val artBmp = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888)
+ val artUri = "content://example"
+ val inputMetadata =
+ MediaMetadata.Builder()
+ .putBitmap(MediaMetadata.METADATA_KEY_ART, artBmp)
+ .putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, artBmp)
+ .putBitmap(MediaMetadata.METADATA_KEY_DISPLAY_ICON, artBmp)
+ .putString(MediaMetadata.METADATA_KEY_ALBUM_ART_URI, artUri)
+ .putString(MediaMetadata.METADATA_KEY_ART_URI, artUri)
+ .putString(MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI, artUri)
+ .build()
+
+ // Create a playing media notification
+ val state = PlaybackState.Builder().setState(PlaybackState.STATE_PLAYING, 0L, 1f).build()
+ val session = MediaSession(context, "NotificationMediaManagerTest")
+ session.setMetadata(inputMetadata)
+ session.setPlaybackState(state)
+ val sbn =
+ SbnBuilder().run {
+ modifyNotification(context).also {
+ it.setSmallIcon(android.R.drawable.ic_media_play)
+ it.setStyle(
+ Notification.MediaStyle().apply { setMediaSession(session.sessionToken) }
+ )
+ }
+ build()
+ }
+ whenever(notificationEntry.sbn).thenReturn(sbn)
+ val collection = ArrayList<NotificationEntry>()
+ collection.add(notificationEntry)
+ whenever(notifPipeline.allNotifs).thenReturn(collection)
+
+ // Trigger update in NotificationMediaManager
+ manager.findAndUpdateMediaNotifications()
+
+ // Verify that there is no artwork data retained
+ val metadata = manager.mediaMetadata
+ assertThat(metadata.getBitmap(MediaMetadata.METADATA_KEY_ART)).isNull()
+ assertThat(metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART)).isNull()
+ assertThat(metadata.getBitmap(MediaMetadata.METADATA_KEY_DISPLAY_ICON)).isNull()
+ assertThat(metadata.getString(MediaMetadata.METADATA_KEY_ALBUM_ART_URI)).isNull()
+ assertThat(metadata.getString(MediaMetadata.METADATA_KEY_ART_URI)).isNull()
+ assertThat(metadata.getString(MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI)).isNull()
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfigTest.kt
index 63cb30ca4a33..95b132d603dc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfigTest.kt
@@ -39,7 +39,7 @@ class SystemUiCarrierConfigTest : SysuiTestCase() {
}
@Test
- fun `process new config - reflected by isUsingDefault`() {
+ fun processNewConfig_reflectedByIsUsingDefault() {
// Starts out using the defaults
assertThat(underTest.isUsingDefault).isTrue()
@@ -50,7 +50,7 @@ class SystemUiCarrierConfigTest : SysuiTestCase() {
}
@Test
- fun `process new config - updates all flows`() {
+ fun processNewConfig_updatesAllFlows() {
assertThat(underTest.shouldInflateSignalStrength.value).isFalse()
assertThat(underTest.showOperatorNameInStatusBar.value).isFalse()
@@ -66,7 +66,7 @@ class SystemUiCarrierConfigTest : SysuiTestCase() {
}
@Test
- fun `process new config - defaults to false for config overrides`() {
+ fun processNewConfig_defaultsToFalseForConfigOverrides() {
// This case is only apparent when:
// 1. The default is true
// 2. The override config has no value for a given key
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt
index dfef62e95eda..6e3af26121bf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt
@@ -96,7 +96,7 @@ class CarrierConfigRepositoryTest : SysuiTestCase() {
}
@Test
- fun `carrier config stream produces int-bundle pairs`() =
+ fun carrierConfigStreamProducesIntBundlePairs() =
testScope.runTest {
var latest: Pair<Int, PersistableBundle>? = null
val job = underTest.carrierConfigStream.onEach { latest = it }.launchIn(this)
@@ -111,7 +111,7 @@ class CarrierConfigRepositoryTest : SysuiTestCase() {
}
@Test
- fun `carrier config stream ignores invalid subscriptions`() =
+ fun carrierConfigStreamIgnoresInvalidSubscriptions() =
testScope.runTest {
var latest: Pair<Int, PersistableBundle>? = null
val job = underTest.carrierConfigStream.onEach { latest = it }.launchIn(this)
@@ -124,19 +124,19 @@ class CarrierConfigRepositoryTest : SysuiTestCase() {
}
@Test
- fun `getOrCreateConfig - uses default config if no override`() {
+ fun getOrCreateConfig_usesDefaultConfigIfNoOverride() {
val config = underTest.getOrCreateConfigForSubId(123)
assertThat(config.isUsingDefault).isTrue()
}
@Test
- fun `getOrCreateConfig - uses override if exists`() {
+ fun getOrCreateConfig_usesOverrideIfExists() {
val config = underTest.getOrCreateConfigForSubId(SUB_ID_1)
assertThat(config.isUsingDefault).isFalse()
}
@Test
- fun `config - updates while config stream is collected`() =
+ fun config_updatesWhileConfigStreamIsCollected() =
testScope.runTest {
CONFIG_1.putBoolean(CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL, false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
index 1fdcf7f27dbf..3ec96908dac8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
@@ -156,7 +156,7 @@ class MobileRepositorySwitcherTest : SysuiTestCase() {
}
@Test
- fun `active repo matches demo mode setting`() =
+ fun activeRepoMatchesDemoModeSetting() =
runBlocking(IMMEDIATE) {
whenever(demoModeController.isInDemoMode).thenReturn(false)
@@ -177,7 +177,7 @@ class MobileRepositorySwitcherTest : SysuiTestCase() {
}
@Test
- fun `subscription list updates when demo mode changes`() =
+ fun subscriptionListUpdatesWhenDemoModeChanges() =
runBlocking(IMMEDIATE) {
whenever(demoModeController.isInDemoMode).thenReturn(false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
index 47f8cd319bff..1251dfacddfc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
@@ -105,7 +105,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
- fun `network event - create new subscription`() =
+ fun networkEvent_createNewSubscription() =
testScope.runTest {
var latest: List<SubscriptionModel>? = null
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
@@ -121,7 +121,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
- fun `wifi carrier merged event - create new subscription`() =
+ fun wifiCarrierMergedEvent_createNewSubscription() =
testScope.runTest {
var latest: List<SubscriptionModel>? = null
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
@@ -137,7 +137,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
- fun `network event - reuses subscription when same Id`() =
+ fun networkEvent_reusesSubscriptionWhenSameId() =
testScope.runTest {
var latest: List<SubscriptionModel>? = null
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
@@ -159,7 +159,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
- fun `wifi carrier merged event - reuses subscription when same Id`() =
+ fun wifiCarrierMergedEvent_reusesSubscriptionWhenSameId() =
testScope.runTest {
var latest: List<SubscriptionModel>? = null
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
@@ -181,7 +181,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
- fun `multiple subscriptions`() =
+ fun multipleSubscriptions() =
testScope.runTest {
var latest: List<SubscriptionModel>? = null
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
@@ -195,7 +195,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
- fun `mobile subscription and carrier merged subscription`() =
+ fun mobileSubscriptionAndCarrierMergedSubscription() =
testScope.runTest {
var latest: List<SubscriptionModel>? = null
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
@@ -209,7 +209,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
- fun `multiple mobile subscriptions and carrier merged subscription`() =
+ fun multipleMobileSubscriptionsAndCarrierMergedSubscription() =
testScope.runTest {
var latest: List<SubscriptionModel>? = null
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
@@ -224,7 +224,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
- fun `mobile disabled event - disables connection - subId specified - single conn`() =
+ fun mobileDisabledEvent_disablesConnection_subIdSpecified_singleConn() =
testScope.runTest {
var latest: List<SubscriptionModel>? = null
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
@@ -239,7 +239,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
- fun `mobile disabled event - disables connection - subId not specified - single conn`() =
+ fun mobileDisabledEvent_disablesConnection_subIdNotSpecified_singleConn() =
testScope.runTest {
var latest: List<SubscriptionModel>? = null
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
@@ -254,7 +254,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
- fun `mobile disabled event - disables connection - subId specified - multiple conn`() =
+ fun mobileDisabledEvent_disablesConnection_subIdSpecified_multipleConn() =
testScope.runTest {
var latest: List<SubscriptionModel>? = null
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
@@ -270,7 +270,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
- fun `mobile disabled event - subId not specified - multiple conn - ignores command`() =
+ fun mobileDisabledEvent_subIdNotSpecified_multipleConn_ignoresCommand() =
testScope.runTest {
var latest: List<SubscriptionModel>? = null
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
@@ -286,7 +286,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
- fun `wifi network updates to disabled - carrier merged connection removed`() =
+ fun wifiNetworkUpdatesToDisabled_carrierMergedConnectionRemoved() =
testScope.runTest {
var latest: List<SubscriptionModel>? = null
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
@@ -303,7 +303,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
- fun `wifi network updates to active - carrier merged connection removed`() =
+ fun wifiNetworkUpdatesToActive_carrierMergedConnectionRemoved() =
testScope.runTest {
var latest: List<SubscriptionModel>? = null
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
@@ -326,7 +326,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
- fun `mobile sub updates to carrier merged - only one connection`() =
+ fun mobileSubUpdatesToCarrierMerged_onlyOneConnection() =
testScope.runTest {
var latestSubsList: List<SubscriptionModel>? = null
var connections: List<DemoMobileConnectionRepository>? = null
@@ -352,7 +352,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
- fun `mobile sub updates to carrier merged then back - has old mobile data`() =
+ fun mobileSubUpdatesToCarrierMergedThenBack_hasOldMobileData() =
testScope.runTest {
var latestSubsList: List<SubscriptionModel>? = null
var connections: List<DemoMobileConnectionRepository>? = null
@@ -393,7 +393,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
/** Regression test for b/261706421 */
@Test
- fun `multiple connections - remove all - does not throw`() =
+ fun multipleConnections_removeAll_doesNotThrow() =
testScope.runTest {
var latest: List<SubscriptionModel>? = null
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
@@ -411,7 +411,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
- fun `demo connection - single subscription`() =
+ fun demoConnection_singleSubscription() =
testScope.runTest {
var currentEvent: FakeNetworkEventModel = validMobileEvent(subId = 1)
var connections: List<DemoMobileConnectionRepository>? = null
@@ -440,7 +440,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
- fun `demo connection - two connections - update second - no affect on first`() =
+ fun demoConnection_twoConnections_updateSecond_noAffectOnFirst() =
testScope.runTest {
var currentEvent1 = validMobileEvent(subId = 1)
var connection1: DemoMobileConnectionRepository? = null
@@ -487,7 +487,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
- fun `demo connection - two connections - update carrier merged - no affect on first`() =
+ fun demoConnection_twoConnections_updateCarrierMerged_noAffectOnFirst() =
testScope.runTest {
var currentEvent1 = validMobileEvent(subId = 1)
var connection1: DemoMobileConnectionRepository? = null
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
index 423c47661fa3..9f77744e1fec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
@@ -292,7 +292,7 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() {
}
@Test
- fun `factory - reuses log buffers for same connection`() =
+ fun factory_reusesLogBuffersForSameConnection() =
testScope.runTest {
val realLoggerFactory = TableLogBufferFactory(mock(), FakeSystemClock())
@@ -327,7 +327,7 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() {
}
@Test
- fun `factory - reuses log buffers for same sub ID even if carrier merged`() =
+ fun factory_reusesLogBuffersForSameSubIDevenIfCarrierMerged() =
testScope.runTest {
val realLoggerFactory = TableLogBufferFactory(mock(), FakeSystemClock())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
index 8d7f0f6035cc..c2768654809b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
@@ -353,7 +353,7 @@ class MobileIconInteractorTest : SysuiTestCase() {
}
@Test
- fun `isInService - uses repository value`() =
+ fun isInService_usesRepositoryValue() =
testScope.runTest {
var latest: Boolean? = null
val job = underTest.isInService.onEach { latest = it }.launchIn(this)
@@ -370,7 +370,7 @@ class MobileIconInteractorTest : SysuiTestCase() {
}
@Test
- fun `roaming - is gsm - uses connection model`() =
+ fun roaming_isGsm_usesConnectionModel() =
testScope.runTest {
var latest: Boolean? = null
val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
@@ -389,7 +389,7 @@ class MobileIconInteractorTest : SysuiTestCase() {
}
@Test
- fun `roaming - is cdma - uses cdma roaming bit`() =
+ fun roaming_isCdma_usesCdmaRoamingBit() =
testScope.runTest {
var latest: Boolean? = null
val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
@@ -410,7 +410,7 @@ class MobileIconInteractorTest : SysuiTestCase() {
}
@Test
- fun `roaming - false while carrierNetworkChangeActive`() =
+ fun roaming_falseWhileCarrierNetworkChangeActive() =
testScope.runTest {
var latest: Boolean? = null
val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
@@ -431,7 +431,7 @@ class MobileIconInteractorTest : SysuiTestCase() {
}
@Test
- fun `network name - uses operatorAlphaShot when non null and repo is default`() =
+ fun networkName_usesOperatorAlphaShotWhenNonNullAndRepoIsDefault() =
testScope.runTest {
var latest: NetworkNameModel? = null
val job = underTest.networkName.onEach { latest = it }.launchIn(this)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
index dc683868f727..c84c9c032225 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
@@ -520,7 +520,7 @@ class MobileIconsInteractorTest : SysuiTestCase() {
// is private and can only be tested by looking at [isDefaultConnectionFailed].
@Test
- fun `data switch - in same group - validated matches previous value - expires after 2s`() =
+ fun dataSwitch_inSameGroup_validatedMatchesPreviousValue_expiresAfter2s() =
testScope.runTest {
var latestConnectionFailed: Boolean? = null
val job =
@@ -548,7 +548,7 @@ class MobileIconsInteractorTest : SysuiTestCase() {
}
@Test
- fun `data switch - in same group - not validated - immediately marked as failed`() =
+ fun dataSwitch_inSameGroup_notValidated_immediatelyMarkedAsFailed() =
testScope.runTest {
var latestConnectionFailed: Boolean? = null
val job =
@@ -567,7 +567,7 @@ class MobileIconsInteractorTest : SysuiTestCase() {
}
@Test
- fun `data switch - lose validation - then switch happens - clears forced bit`() =
+ fun dataSwitch_loseValidation_thenSwitchHappens_clearsForcedBit() =
testScope.runTest {
var latestConnectionFailed: Boolean? = null
val job =
@@ -602,7 +602,7 @@ class MobileIconsInteractorTest : SysuiTestCase() {
}
@Test
- fun `data switch - while already forcing validation - resets clock`() =
+ fun dataSwitch_whileAlreadyForcingValidation_resetsClock() =
testScope.runTest {
var latestConnectionFailed: Boolean? = null
val job =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
index e99be864e73f..d5fb5776b344 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
@@ -92,7 +92,7 @@ class LocationBasedMobileIconViewModelTest : SysuiTestCase() {
}
@Test
- fun `location based view models receive same icon id when common impl updates`() =
+ fun locationBasedViewModelsReceiveSameIconIdWhenCommonImplUpdates() =
testScope.runTest {
var latestHome: SignalIconModel? = null
val homeJob = homeIcon.icon.onEach { latestHome = it }.launchIn(this)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
index 297cb9d691ba..2b7bc780f7c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
@@ -249,7 +249,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
}
@Test
- fun `icon - uses empty state - when not in service`() =
+ fun icon_usesEmptyState_whenNotInService() =
testScope.runTest {
var latest: SignalIconModel? = null
val job = underTest.icon.onEach { latest = it }.launchIn(this)
@@ -480,7 +480,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
}
@Test
- fun `network type - alwaysShow - shown when not default`() =
+ fun networkType_alwaysShow_shownWhenNotDefault() =
testScope.runTest {
interactor.networkTypeIconGroup.value = NetworkTypeIconModel.DefaultIcon(THREE_G)
interactor.mobileIsDefault.value = false
@@ -500,7 +500,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
}
@Test
- fun `network type - not shown when not default`() =
+ fun networkType_notShownWhenNotDefault() =
testScope.runTest {
interactor.networkTypeIconGroup.value = NetworkTypeIconModel.DefaultIcon(THREE_G)
interactor.isDataConnected.value = true
@@ -531,7 +531,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
}
@Test
- fun `data activity - null when config is off`() =
+ fun dataActivity_nullWhenConfigIsOff() =
testScope.runTest {
// Create a new view model here so the constants are properly read
whenever(constants.shouldShowActivityConfig).thenReturn(false)
@@ -563,7 +563,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
}
@Test
- fun `data activity - config on - test indicators`() =
+ fun dataActivity_configOn_testIndicators() =
testScope.runTest {
// Create a new view model here so the constants are properly read
whenever(constants.shouldShowActivityConfig).thenReturn(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
index f8e1aa94c387..f0458fa83d38 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
@@ -111,7 +111,7 @@ class MobileIconsViewModelTest : SysuiTestCase() {
}
@Test
- fun `caching - mobile icon view model is reused for same sub id`() =
+ fun caching_mobileIconViewModelIsReusedForSameSubId() =
testScope.runTest {
val model1 = underTest.viewModelForSub(1, StatusBarLocation.HOME)
val model2 = underTest.viewModelForSub(1, StatusBarLocation.QS)
@@ -120,7 +120,7 @@ class MobileIconsViewModelTest : SysuiTestCase() {
}
@Test
- fun `caching - invalid view models are removed from cache when sub disappears`() =
+ fun caching_invalidViewModelsAreRemovedFromCacheWhenSubDisappears() =
testScope.runTest {
// Retrieve models to trigger caching
val model1 = underTest.viewModelForSub(1, StatusBarLocation.HOME)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
index 70d2d2b68460..30b95ef3b205 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
@@ -105,7 +105,7 @@ class WifiRepositorySwitcherTest : SysuiTestCase() {
}
@Test
- fun `switcher active repo - updates when demo mode changes`() =
+ fun switcherActiveRepo_updatesWhenDemoModeChanges() =
testScope.runTest {
assertThat(underTest.activeRepo.value).isSameInstanceAs(realImpl)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapterTest.kt
index 0a3da0b5b029..67727ae21641 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapterTest.kt
@@ -87,7 +87,7 @@ class BaseUserSwitcherAdapterTest : SysuiTestCase() {
}
@Test
- fun `Adds self to controller in constructor`() {
+ fun addsSelfToControllerInConstructor() {
val captor = kotlinArgumentCaptor<WeakReference<BaseUserSwitcherAdapter>>()
verify(controller).addAdapter(captor.capture())
@@ -100,7 +100,7 @@ class BaseUserSwitcherAdapterTest : SysuiTestCase() {
}
@Test
- fun `count - ignores restricted users when device is locked`() {
+ fun count_ignoresRestrictedUsersWhenDeviceIsLocked() {
whenever(controller.isKeyguardShowing).thenReturn(true)
users =
ArrayList(
@@ -131,7 +131,7 @@ class BaseUserSwitcherAdapterTest : SysuiTestCase() {
}
@Test
- fun `count - does not ignore restricted users when device is not locked`() {
+ fun count_doesNotIgnoreRestrictedUsersWhenDeviceIsNotLocked() {
whenever(controller.isKeyguardShowing).thenReturn(false)
users =
ArrayList(
@@ -185,7 +185,7 @@ class BaseUserSwitcherAdapterTest : SysuiTestCase() {
}
@Test
- fun `getName - non guest - returns real name`() {
+ fun getName_nonGuest_returnsRealName() {
val userRecord =
createUserRecord(
id = 1,
@@ -196,7 +196,7 @@ class BaseUserSwitcherAdapterTest : SysuiTestCase() {
}
@Test
- fun `getName - guest and selected - returns exit guest action name`() {
+ fun getName_guestAndSelected_returnsExitGuestActionName() {
val expected = "Exit guest"
context.orCreateTestableResources.addOverride(
com.android.settingslib.R.string.guest_exit_quick_settings_button,
@@ -215,7 +215,7 @@ class BaseUserSwitcherAdapterTest : SysuiTestCase() {
}
@Test
- fun `getName - guest and not selected - returns enter guest action name`() {
+ fun getName_guestAndNotSelected_returnsEnterGuestActionName() {
val expected = "Guest"
context.orCreateTestableResources.addOverride(
com.android.internal.R.string.guest_name,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
index e2f3cf7e085f..079fbcd0304c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
@@ -164,7 +164,7 @@ class UserRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun `refreshUsers - sorts by creation time - guest user last`() = runSelfCancelingTest {
+ fun refreshUsers_sortsByCreationTime_guestUserLast() = runSelfCancelingTest {
underTest = create(this)
val unsortedUsers =
setUpUsers(
@@ -205,7 +205,7 @@ class UserRepositoryImplTest : SysuiTestCase() {
return userInfos
}
@Test
- fun `userTrackerCallback - updates selectedUserInfo`() = runSelfCancelingTest {
+ fun userTrackerCallback_updatesSelectedUserInfo() = runSelfCancelingTest {
underTest = create(this)
var selectedUserInfo: UserInfo? = null
underTest.selectedUserInfo.onEach { selectedUserInfo = it }.launchIn(this)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt
index 0c119fd90c23..948670f95f97 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt
@@ -97,13 +97,13 @@ class GuestUserInteractorTest : SysuiTestCase() {
}
@Test
- fun `registers broadcast receivers`() {
+ fun registersBroadcastReceivers() {
verify(resumeSessionReceiver).register()
verify(resetOrExitSessionReceiver).register()
}
@Test
- fun `onDeviceBootCompleted - allowed to add - create guest`() =
+ fun onDeviceBootCompleted_allowedToAdd_createGuest() =
runBlocking(IMMEDIATE) {
setAllowedToAdd()
@@ -114,7 +114,7 @@ class GuestUserInteractorTest : SysuiTestCase() {
}
@Test
- fun `onDeviceBootCompleted - await provisioning - and create guest`() =
+ fun onDeviceBootCompleted_awaitProvisioning_andCreateGuest() =
runBlocking(IMMEDIATE) {
setAllowedToAdd(isAllowed = false)
underTest.onDeviceBootCompleted()
@@ -145,7 +145,7 @@ class GuestUserInteractorTest : SysuiTestCase() {
}
@Test
- fun `createAndSwitchTo - fails to create - does not switch to`() =
+ fun createAndSwitchTo_failsToCreate_doesNotSwitchTo() =
runBlocking(IMMEDIATE) {
whenever(manager.createGuest(any())).thenReturn(null)
@@ -162,7 +162,7 @@ class GuestUserInteractorTest : SysuiTestCase() {
}
@Test
- fun `exit - returns to target user`() =
+ fun exit_returnsToTargetUser() =
runBlocking(IMMEDIATE) {
repository.setSelectedUserInfo(GUEST_USER_INFO)
@@ -182,7 +182,7 @@ class GuestUserInteractorTest : SysuiTestCase() {
}
@Test
- fun `exit - returns to last non-guest`() =
+ fun exit_returnsToLastNonGuest() =
runBlocking(IMMEDIATE) {
val expectedUserId = NON_GUEST_USER_INFO.id
whenever(manager.getUserInfo(expectedUserId)).thenReturn(NON_GUEST_USER_INFO)
@@ -204,7 +204,7 @@ class GuestUserInteractorTest : SysuiTestCase() {
}
@Test
- fun `exit - last non-guest was removed - returns to main user`() =
+ fun exit_lastNonGuestWasRemoved_returnsToMainUser() =
runBlocking(IMMEDIATE) {
val removedUserId = 310
val mainUserId = 10
@@ -227,7 +227,7 @@ class GuestUserInteractorTest : SysuiTestCase() {
}
@Test
- fun `exit - guest was ephemeral - it is removed`() =
+ fun exit_guestWasEphemeral_itIsRemoved() =
runBlocking(IMMEDIATE) {
whenever(manager.markGuestForDeletion(anyInt())).thenReturn(true)
repository.setUserInfos(listOf(NON_GUEST_USER_INFO, EPHEMERAL_GUEST_USER_INFO))
@@ -250,7 +250,7 @@ class GuestUserInteractorTest : SysuiTestCase() {
}
@Test
- fun `exit - force remove guest - it is removed`() =
+ fun exit_forceRemoveGuest_itIsRemoved() =
runBlocking(IMMEDIATE) {
whenever(manager.markGuestForDeletion(anyInt())).thenReturn(true)
repository.setSelectedUserInfo(GUEST_USER_INFO)
@@ -272,7 +272,7 @@ class GuestUserInteractorTest : SysuiTestCase() {
}
@Test
- fun `exit - selected different from guest user - do nothing`() =
+ fun exit_selectedDifferentFromGuestUser_doNothing() =
runBlocking(IMMEDIATE) {
repository.setSelectedUserInfo(NON_GUEST_USER_INFO)
@@ -289,7 +289,7 @@ class GuestUserInteractorTest : SysuiTestCase() {
}
@Test
- fun `exit - selected is actually not a guest user - do nothing`() =
+ fun exit_selectedIsActuallyNotAguestUser_doNothing() =
runBlocking(IMMEDIATE) {
repository.setSelectedUserInfo(NON_GUEST_USER_INFO)
@@ -306,7 +306,7 @@ class GuestUserInteractorTest : SysuiTestCase() {
}
@Test
- fun `remove - returns to target user`() =
+ fun remove_returnsToTargetUser() =
runBlocking(IMMEDIATE) {
whenever(manager.markGuestForDeletion(anyInt())).thenReturn(true)
repository.setSelectedUserInfo(GUEST_USER_INFO)
@@ -327,7 +327,7 @@ class GuestUserInteractorTest : SysuiTestCase() {
}
@Test
- fun `remove - selected different from guest user - do nothing`() =
+ fun remove_selectedDifferentFromGuestUser_doNothing() =
runBlocking(IMMEDIATE) {
whenever(manager.markGuestForDeletion(anyInt())).thenReturn(true)
repository.setSelectedUserInfo(NON_GUEST_USER_INFO)
@@ -344,7 +344,7 @@ class GuestUserInteractorTest : SysuiTestCase() {
}
@Test
- fun `remove - selected is actually not a guest user - do nothing`() =
+ fun remove_selectedIsActuallyNotAguestUser_doNothing() =
runBlocking(IMMEDIATE) {
whenever(manager.markGuestForDeletion(anyInt())).thenReturn(true)
repository.setSelectedUserInfo(NON_GUEST_USER_INFO)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/RefreshUsersSchedulerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/RefreshUsersSchedulerTest.kt
index 593ce1f0a2f5..b30f77a663af 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/RefreshUsersSchedulerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/RefreshUsersSchedulerTest.kt
@@ -45,7 +45,7 @@ class RefreshUsersSchedulerTest : SysuiTestCase() {
}
@Test
- fun `pause - prevents the next refresh from happening`() =
+ fun pause_preventsTheNextRefreshFromHappening() =
runBlocking(IMMEDIATE) {
underTest =
RefreshUsersScheduler(
@@ -60,7 +60,7 @@ class RefreshUsersSchedulerTest : SysuiTestCase() {
}
@Test
- fun `unpauseAndRefresh - forces the refresh even when paused`() =
+ fun unpauseAndRefresh_forcesTheRefreshEvenWhenPaused() =
runBlocking(IMMEDIATE) {
underTest =
RefreshUsersScheduler(
@@ -76,7 +76,7 @@ class RefreshUsersSchedulerTest : SysuiTestCase() {
}
@Test
- fun `refreshIfNotPaused - refreshes when not paused`() =
+ fun refreshIfNotPaused_refreshesWhenNotPaused() =
runBlocking(IMMEDIATE) {
underTest =
RefreshUsersScheduler(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
index adba53823d2c..d252d5317d06 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
@@ -182,7 +182,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `testKeyguardUpdateMonitor_onKeyguardGoingAway`() =
+ fun testKeyguardUpdateMonitor_onKeyguardGoingAway() =
testScope.runTest {
val argumentCaptor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
verify(keyguardUpdateMonitor).registerCallback(argumentCaptor.capture())
@@ -194,7 +194,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `onRecordSelected - user`() =
+ fun onRecordSelected_user() =
testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = false)
userRepository.setUserInfos(userInfos)
@@ -211,7 +211,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `onRecordSelected - switch to guest user`() =
+ fun onRecordSelected_switchToGuestUser() =
testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = true)
userRepository.setUserInfos(userInfos)
@@ -227,7 +227,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `onRecordSelected - switch to restricted user`() =
+ fun onRecordSelected_switchToRestrictedUser() =
testScope.runTest {
var userInfos = createUserInfos(count = 2, includeGuest = false).toMutableList()
userInfos.add(
@@ -252,7 +252,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `onRecordSelected - enter guest mode`() =
+ fun onRecordSelected_enterGuestMode() =
testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = false)
userRepository.setUserInfos(userInfos)
@@ -272,7 +272,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `onRecordSelected - action`() =
+ fun onRecordSelected_action() =
testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = true)
userRepository.setUserInfos(userInfos)
@@ -288,7 +288,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `users - switcher enabled`() =
+ fun users_switcherEnabled() =
testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = true)
userRepository.setUserInfos(userInfos)
@@ -301,7 +301,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `users - switches to second user`() =
+ fun users_switchesToSecondUser() =
testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos)
@@ -315,7 +315,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `users - switcher not enabled`() =
+ fun users_switcherNotEnabled() =
testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos)
@@ -342,7 +342,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `actions - device unlocked`() =
+ fun actions_deviceUnlocked() =
testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false)
@@ -366,7 +366,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `actions - device unlocked - full screen`() =
+ fun actions_deviceUnlocked_fullScreen() =
testScope.runTest {
featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true)
val userInfos = createUserInfos(count = 2, includeGuest = false)
@@ -389,7 +389,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `actions - device unlocked user not primary - empty list`() =
+ fun actions_deviceUnlockedUserNotPrimary_emptyList() =
testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos)
@@ -402,7 +402,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `actions - device unlocked user is guest - empty list`() =
+ fun actions_deviceUnlockedUserIsGuest_emptyList() =
testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = true)
assertThat(userInfos[1].isGuest).isTrue()
@@ -416,7 +416,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `actions - device locked add from lockscreen set - full list`() =
+ fun actions_deviceLockedAddFromLockscreenSet_fullList() =
testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos)
@@ -442,7 +442,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `actions - device locked add from lockscreen set - full list - full screen`() =
+ fun actions_deviceLockedAddFromLockscreenSet_fullList_fullScreen() =
testScope.runTest {
featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true)
val userInfos = createUserInfos(count = 2, includeGuest = false)
@@ -469,7 +469,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `actions - device locked - only manage user is shown`() =
+ fun actions_deviceLocked_onlymanageUserIsShown() =
testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos)
@@ -482,7 +482,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `executeAction - add user - dialog shown`() =
+ fun executeAction_addUser_dialogShown() =
testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos)
@@ -509,7 +509,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `executeAction - add supervised user - dismisses dialog and starts activity`() =
+ fun executeAction_addSupervisedUser_dismissesDialogAndStartsActivity() =
testScope.runTest {
underTest.executeAction(UserActionModel.ADD_SUPERVISED_USER)
@@ -523,7 +523,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `executeAction - navigate to manage users`() =
+ fun executeAction_navigateToManageUsers() =
testScope.runTest {
underTest.executeAction(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT)
@@ -533,7 +533,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `executeAction - guest mode`() =
+ fun executeAction_guestMode() =
testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos)
@@ -571,7 +571,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `selectUser - already selected guest re-selected - exit guest dialog`() =
+ fun selectUser_alreadySelectedGuestReSelected_exitGuestDialog() =
testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = true)
val guestUserInfo = userInfos[1]
@@ -592,7 +592,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `selectUser - currently guest non-guest selected - exit guest dialog`() =
+ fun selectUser_currentlyGuestNonGuestSelected_exitGuestDialog() =
testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = true)
val guestUserInfo = userInfos[1]
@@ -610,7 +610,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `selectUser - not currently guest - switches users`() =
+ fun selectUser_notCurrentlyGuest_switchesUsers() =
testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos)
@@ -626,7 +626,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `Telephony call state changes - refreshes users`() =
+ fun telephonyCallStateChanges_refreshesUsers() =
testScope.runTest {
runCurrent()
@@ -639,7 +639,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `User switched broadcast`() =
+ fun userSwitchedBroadcast() =
testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos)
@@ -670,7 +670,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `User info changed broadcast`() =
+ fun userInfoChangedBroadcast() =
testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos)
@@ -690,7 +690,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `System user unlocked broadcast - refresh users`() =
+ fun systemUserUnlockedBroadcast_refreshUsers() =
testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos)
@@ -710,7 +710,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `Non-system user unlocked broadcast - do not refresh users`() =
+ fun nonSystemUserUnlockedBroadcast_doNotRefreshUsers() =
testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos)
@@ -799,7 +799,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `users - secondary user - guest user can be switched to`() =
+ fun users_secondaryUser_guestUserCanBeSwitchedTo() =
testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = true)
userRepository.setUserInfos(userInfos)
@@ -812,7 +812,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `users - secondary user - no guest action`() =
+ fun users_secondaryUser_noGuestAction() =
testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = true)
userRepository.setUserInfos(userInfos)
@@ -824,7 +824,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `users - secondary user - no guest user record`() =
+ fun users_secondaryUser_noGuestUserRecord() =
testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = true)
userRepository.setUserInfos(userInfos)
@@ -835,7 +835,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `show user switcher - full screen disabled - shows dialog switcher`() =
+ fun showUserSwitcher_fullScreenDisabled_showsDialogSwitcher() =
testScope.runTest {
val expandable = mock<Expandable>()
underTest.showUserSwitcher(expandable)
@@ -851,7 +851,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `show user switcher - full screen enabled - launches full screen dialog`() =
+ fun showUserSwitcher_fullScreenEnabled_launchesFullScreenDialog() =
testScope.runTest {
featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true)
@@ -869,7 +869,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `users - secondary user - managed profile is not included`() =
+ fun users_secondaryUser_managedProfileIsNotIncluded() =
testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = false).toMutableList()
userInfos.add(
@@ -889,7 +889,7 @@ class UserInteractorTest : SysuiTestCase() {
}
@Test
- fun `current user is not primary and user switcher is disabled`() =
+ fun currentUserIsNotPrimaryAndUserSwitcherIsDisabled() =
testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
index 9b74c1f05d71..fd8c6c76720b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
@@ -137,7 +137,7 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
}
@Test
- fun `config is false - chip is disabled`() {
+ fun configIsFalse_chipIsDisabled() {
// the enabled bit is set at SystemUI startup, so recreate the view model here
userRepository.isStatusBarUserChipEnabled = false
underTest = viewModel()
@@ -146,7 +146,7 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
}
@Test
- fun `config is true - chip is enabled`() {
+ fun configIsTrue_chipIsEnabled() {
// the enabled bit is set at SystemUI startup, so recreate the view model here
userRepository.isStatusBarUserChipEnabled = true
underTest = viewModel()
@@ -155,7 +155,7 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
}
@Test
- fun `should show chip criteria - single user`() =
+ fun shouldShowChipCriteria_singleUser() =
testScope.runTest {
userRepository.setUserInfos(listOf(USER_0))
userRepository.setSelectedUserInfo(USER_0)
@@ -172,7 +172,7 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
}
@Test
- fun `should show chip criteria - multiple users`() =
+ fun shouldShowChipCriteria_multipleUsers() =
testScope.runTest {
setMultipleUsers()
@@ -186,7 +186,7 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
}
@Test
- fun `user chip name - shows selected user info`() =
+ fun userChipName_showsSelectedUserInfo() =
testScope.runTest {
setMultipleUsers()
@@ -206,7 +206,7 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
}
@Test
- fun `user chip avatar - shows selected user info`() =
+ fun userChipAvatar_showsSelectedUserInfo() =
testScope.runTest {
setMultipleUsers()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
index a342dadcb775..91550844ceca 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
@@ -232,7 +232,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
}
@Test
- fun `maximumUserColumns - few users`() =
+ fun maximumUserColumns_fewUsers() =
testScope.runTest {
setUsers(count = 2)
val values = mutableListOf<Int>()
@@ -244,7 +244,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
}
@Test
- fun `maximumUserColumns - many users`() =
+ fun maximumUserColumns_manyUsers() =
testScope.runTest {
setUsers(count = 5)
val values = mutableListOf<Int>()
@@ -255,7 +255,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
}
@Test
- fun `isOpenMenuButtonVisible - has actions - true`() =
+ fun isOpenMenuButtonVisible_hasActions_true() =
testScope.runTest {
setUsers(2)
@@ -267,7 +267,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
}
@Test
- fun `isOpenMenuButtonVisible - no actions - false`() =
+ fun isOpenMenuButtonVisible_noActions_false() =
testScope.runTest {
val userInfos = setUsers(2)
userRepository.setSelectedUserInfo(userInfos[1])
@@ -298,7 +298,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
}
@Test
- fun `menu actions`() =
+ fun menuActions() =
testScope.runTest {
setUsers(2)
val actions = mutableListOf<List<UserActionViewModel>>()
@@ -318,7 +318,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
}
@Test
- fun `isFinishRequested - finishes when cancel button is clicked`() =
+ fun isFinishRequested_finishesWhenCancelButtonIsClicked() =
testScope.runTest {
setUsers(count = 2)
val isFinishRequested = mutableListOf<Boolean>()
@@ -338,7 +338,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
}
@Test
- fun `guest selected -- name is exit guest`() =
+ fun guestSelected_nameIsExitGuest() =
testScope.runTest {
val userInfos =
listOf(
@@ -386,7 +386,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
}
@Test
- fun `guest not selected -- name is guest`() =
+ fun guestNotSelected_nameIsGuest() =
testScope.runTest {
val userInfos =
listOf(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsControllerTest.kt
index 9bd3a799350d..3901d720ab3a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsControllerTest.kt
@@ -93,7 +93,7 @@ class WalletContextualSuggestionsControllerTest : SysuiTestCase() {
}
@Test
- fun `state - has wallet cards- callbacks called`() = runTest {
+ fun state_hasWalletCardsCallbacksCalled() = runTest {
setUpWalletClient(listOf(CARD_1, CARD_2, PAYMENT_CARD))
val controller = createWalletContextualSuggestionsController(backgroundScope)
var latest1 = emptyList<WalletCard>()
@@ -115,7 +115,7 @@ class WalletContextualSuggestionsControllerTest : SysuiTestCase() {
}
@Test
- fun `state - no wallet cards - set suggestion cards`() = runTest {
+ fun state_noWalletCards_setSuggestionCards() = runTest {
setUpWalletClient(emptyList())
val controller = createWalletContextualSuggestionsController(backgroundScope)
val latest =
@@ -132,7 +132,7 @@ class WalletContextualSuggestionsControllerTest : SysuiTestCase() {
}
@Test
- fun `state - has wallet cards - set and update suggestion cards`() = runTest {
+ fun state_hasWalletCards_setAndUpdateSuggestionCards() = runTest {
setUpWalletClient(listOf(CARD_1, CARD_2, PAYMENT_CARD))
val controller = createWalletContextualSuggestionsController(backgroundScope)
val latest =
@@ -151,7 +151,7 @@ class WalletContextualSuggestionsControllerTest : SysuiTestCase() {
}
@Test
- fun `state - wallet cards error`() = runTest {
+ fun state_walletCardsError() = runTest {
setUpWalletClient(shouldFail = true)
val controller = createWalletContextualSuggestionsController(backgroundScope)
val latest =
@@ -167,7 +167,7 @@ class WalletContextualSuggestionsControllerTest : SysuiTestCase() {
}
@Test
- fun `state - has wallet cards - received contextual cards - feature disabled`() = runTest {
+ fun state_hasWalletCards_receivedContextualCards_featureDisabled() = runTest {
whenever(featureFlags.isEnabled(eq(Flags.ENABLE_WALLET_CONTEXTUAL_LOYALTY_CARDS)))
.thenReturn(false)
setUpWalletClient(listOf(CARD_1, CARD_2, PAYMENT_CARD))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index 9a9953865037..bc3a5b7975a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -24,7 +24,6 @@ import static android.service.notification.NotificationListenerService.REASON_AP
import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
-import static com.android.wm.shell.bubbles.Bubble.KEY_APP_BUBBLE;
import static com.google.common.truth.Truth.assertThat;
@@ -1734,13 +1733,13 @@ public class BubblesTest extends SysuiTestCase {
@Test
public void testShowOrHideAppBubble_addsAndExpand() {
assertThat(mBubbleController.isStackExpanded()).isFalse();
- assertThat(mBubbleData.getBubbleInStackWithKey(KEY_APP_BUBBLE)).isNull();
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0, mAppBubbleIcon);
verify(mBubbleController).inflateAndAdd(any(Bubble.class), /* suppressFlyout= */ eq(true),
/* showInShade= */ eq(false));
- assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(KEY_APP_BUBBLE);
+ assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(
+ Bubble.getAppBubbleKeyForApp(mContext.getPackageName(), mUser0));
assertThat(mBubbleController.isStackExpanded()).isTrue();
}
@@ -1754,7 +1753,8 @@ public class BubblesTest extends SysuiTestCase {
// Calling this while collapsed will expand the app bubble
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0, mAppBubbleIcon);
- assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(KEY_APP_BUBBLE);
+ assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(
+ Bubble.getAppBubbleKeyForApp(mContext.getPackageName(), mUser0));
assertThat(mBubbleController.isStackExpanded()).isTrue();
assertThat(mBubbleData.getBubbles().size()).isEqualTo(2);
}
@@ -1762,13 +1762,15 @@ public class BubblesTest extends SysuiTestCase {
@Test
public void testShowOrHideAppBubble_collapseIfSelected() {
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0, mAppBubbleIcon);
- assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(KEY_APP_BUBBLE);
+ assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(
+ Bubble.getAppBubbleKeyForApp(mContext.getPackageName(), mUser0));
assertThat(mBubbleController.isStackExpanded()).isTrue();
// Calling this while the app bubble is expanded should collapse the stack
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0, mAppBubbleIcon);
- assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(KEY_APP_BUBBLE);
+ assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(
+ Bubble.getAppBubbleKeyForApp(mContext.getPackageName(), mUser0));
assertThat(mBubbleController.isStackExpanded()).isFalse();
assertThat(mBubbleData.getBubbles().size()).isEqualTo(1);
assertThat(mBubbleData.getBubbles().get(0).getUser()).isEqualTo(mUser0);
@@ -1777,8 +1779,9 @@ public class BubblesTest extends SysuiTestCase {
@Test
public void testShowOrHideAppBubbleWithNonPrimaryUser_bubbleCollapsedWithExpectedUser() {
UserHandle user10 = createUserHandle(/* userId = */ 10);
+ String appBubbleKey = Bubble.getAppBubbleKeyForApp(mContext.getPackageName(), user10);
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, user10, mAppBubbleIcon);
- assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(KEY_APP_BUBBLE);
+ assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(appBubbleKey);
assertThat(mBubbleController.isStackExpanded()).isTrue();
assertThat(mBubbleData.getBubbles().size()).isEqualTo(1);
assertThat(mBubbleData.getBubbles().get(0).getUser()).isEqualTo(user10);
@@ -1786,13 +1789,28 @@ public class BubblesTest extends SysuiTestCase {
// Calling this while the app bubble is expanded should collapse the stack
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, user10, mAppBubbleIcon);
- assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(KEY_APP_BUBBLE);
+ assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(appBubbleKey);
assertThat(mBubbleController.isStackExpanded()).isFalse();
assertThat(mBubbleData.getBubbles().size()).isEqualTo(1);
assertThat(mBubbleData.getBubbles().get(0).getUser()).isEqualTo(user10);
}
@Test
+ public void testShowOrHideAppBubbleOnUser10AndThenUser0_user0BubbleExpanded() {
+ UserHandle user10 = createUserHandle(/* userId = */ 10);
+ mBubbleController.showOrHideAppBubble(mAppBubbleIntent, user10, mAppBubbleIcon);
+
+ String appBubbleUser0Key = Bubble.getAppBubbleKeyForApp(mContext.getPackageName(), mUser0);
+ mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0, mAppBubbleIcon);
+
+ assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(appBubbleUser0Key);
+ assertThat(mBubbleController.isStackExpanded()).isTrue();
+ assertThat(mBubbleData.getBubbles()).hasSize(2);
+ assertThat(mBubbleData.getBubbles().get(0).getUser()).isEqualTo(mUser0);
+ assertThat(mBubbleData.getBubbles().get(1).getUser()).isEqualTo(user10);
+ }
+
+ @Test
public void testShowOrHideAppBubble_selectIfNotSelected() {
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0, mAppBubbleIcon);
mBubbleController.updateBubble(mBubbleEntry);
@@ -1801,7 +1819,8 @@ public class BubblesTest extends SysuiTestCase {
assertThat(mBubbleController.isStackExpanded()).isTrue();
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0, mAppBubbleIcon);
- assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(KEY_APP_BUBBLE);
+ assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(
+ Bubble.getAppBubbleKeyForApp(mContext.getPackageName(), mUser0));
assertThat(mBubbleController.isStackExpanded()).isTrue();
assertThat(mBubbleData.getBubbles().size()).isEqualTo(2);
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 2a964b8b701f..3bd4547dd3e6 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -56,6 +56,10 @@ import static com.android.server.autofill.Helper.getNumericValue;
import static com.android.server.autofill.Helper.sDebug;
import static com.android.server.autofill.Helper.sVerbose;
import static com.android.server.autofill.Helper.toArray;
+import static com.android.server.autofill.PresentationStatsEventLogger.AUTHENTICATION_RESULT_FAILURE;
+import static com.android.server.autofill.PresentationStatsEventLogger.AUTHENTICATION_RESULT_SUCCESS;
+import static com.android.server.autofill.PresentationStatsEventLogger.AUTHENTICATION_TYPE_DATASET_AUTHENTICATION;
+import static com.android.server.autofill.PresentationStatsEventLogger.AUTHENTICATION_TYPE_FULL_AUTHENTICATION;
import static com.android.server.autofill.PresentationStatsEventLogger.NOT_SHOWN_REASON_NO_FOCUS;
import static com.android.server.autofill.PresentationStatsEventLogger.NOT_SHOWN_REASON_REQUEST_FAILED;
import static com.android.server.autofill.PresentationStatsEventLogger.NOT_SHOWN_REASON_REQUEST_TIMEOUT;
@@ -75,6 +79,12 @@ import static com.android.server.autofill.SaveEventLogger.SAVE_UI_SHOWN_REASON_O
import static com.android.server.autofill.SaveEventLogger.SAVE_UI_SHOWN_REASON_REQUIRED_ID_CHANGE;
import static com.android.server.autofill.SaveEventLogger.SAVE_UI_SHOWN_REASON_TRIGGER_ID_SET;
import static com.android.server.autofill.SaveEventLogger.SAVE_UI_SHOWN_REASON_UNKNOWN;
+import static com.android.server.autofill.SessionCommittedEventLogger.CommitReason;
+import static com.android.server.autofill.SessionCommittedEventLogger.COMMIT_REASON_ACTIVITY_FINISHED;
+import static com.android.server.autofill.SessionCommittedEventLogger.COMMIT_REASON_VIEW_CHANGED;
+import static com.android.server.autofill.SessionCommittedEventLogger.COMMIT_REASON_VIEW_CLICKED;
+import static com.android.server.autofill.SessionCommittedEventLogger.COMMIT_REASON_VIEW_COMMITTED;
+import static com.android.server.autofill.SessionCommittedEventLogger.COMMIT_REASON_SESSION_DESTROYED;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
@@ -364,6 +374,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
private final long mStartTime;
/**
+ * Count of FillRequests in the session.
+ */
+ private int mRequestCount;
+
+ /**
* Starting timestamp of latency logger.
* This is set when Session created or when the view is reset.
*/
@@ -1132,6 +1147,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
int flags) {
final FillResponse existingResponse = viewState.getResponse();
mFillRequestEventLogger.startLogForNewRequest();
+ mRequestCount++;
mFillRequestEventLogger.maybeSetAppPackageUid(uid);
mFillRequestEventLogger.maybeSetFlags(mFlags);
if(mPreviouslyFillDialogPotentiallyStarted) {
@@ -1330,8 +1346,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
this.userId = userId;
this.taskId = taskId;
this.uid = uid;
- mStartTime = SystemClock.elapsedRealtime();
- mLatencyBaseTime = mStartTime;
mService = service;
mLock = lock;
mUi = ui;
@@ -1347,11 +1361,17 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
mComponentName = componentName;
mCompatMode = compatMode;
mSessionState = STATE_ACTIVE;
+ // Initiate all loggers & counters.
+ mStartTime = SystemClock.elapsedRealtime();
+ mLatencyBaseTime = mStartTime;
+ mRequestCount = 0;
mPresentationStatsEventLogger = PresentationStatsEventLogger.forSessionId(sessionId);
mFillRequestEventLogger = FillRequestEventLogger.forSessionId(sessionId);
mFillResponseEventLogger = FillResponseEventLogger.forSessionId(sessionId);
mSessionCommittedEventLogger = SessionCommittedEventLogger.forSessionId(sessionId);
+ mSessionCommittedEventLogger.maybeSetComponentPackageUid(uid);
mSaveEventLogger = SaveEventLogger.forSessionId(sessionId);
+
synchronized (mLock) {
mSessionFlags = new SessionFlags();
mSessionFlags.mAugmentedAutofillOnly = forAugmentedAutofillOnly;
@@ -1971,6 +1991,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
// Start a new FillRequest logger for client suggestion fallback.
mFillRequestEventLogger.startLogForNewRequest();
+ mRequestCount++;
mFillRequestEventLogger.maybeSetAppPackageUid(uid);
mFillRequestEventLogger.maybeSetFlags(
flags & ~FLAG_ENABLED_CLIENT_SUGGESTIONS);
@@ -2187,6 +2208,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
final Intent fillInIntent;
synchronized (mLock) {
+ mPresentationStatsEventLogger.maybeSetAuthenticationType(
+ AUTHENTICATION_TYPE_FULL_AUTHENTICATION);
if (mDestroyed) {
Slog.w(TAG, "Call to Session#authenticate() rejected - session: "
+ id + " destroyed");
@@ -2231,7 +2254,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
if (mDestroyed) {
Slog.w(TAG, "Call to Session#save() rejected - session: "
+ id + " destroyed");
- mSaveEventLogger.logAndEndEvent();
return;
}
}
@@ -2251,7 +2273,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
if (mDestroyed) {
Slog.w(TAG, "Call to Session#cancelSave() rejected - session: "
+ id + " destroyed");
- mSaveEventLogger.logAndEndEvent();
return;
}
}
@@ -2438,18 +2459,26 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
final int requestId = AutofillManager.getRequestIdFromAuthenticationId(authenticationId);
if (requestId == AUGMENTED_AUTOFILL_REQUEST_ID) {
setAuthenticationResultForAugmentedAutofillLocked(data, authenticationId);
+ // Augmented autofill is not logged.
+ mPresentationStatsEventLogger.logAndEndEvent();
return;
}
if (mResponses == null) {
// Typically happens when app explicitly called cancel() while the service was showing
// the auth UI.
Slog.w(TAG, "setAuthenticationResultLocked(" + authenticationId + "): no responses");
+ mPresentationStatsEventLogger.maybeSetAuthenticationResult(
+ AUTHENTICATION_RESULT_FAILURE);
+ mPresentationStatsEventLogger.logAndEndEvent();
removeFromService();
return;
}
final FillResponse authenticatedResponse = mResponses.get(requestId);
if (authenticatedResponse == null || data == null) {
Slog.w(TAG, "no authenticated response");
+ mPresentationStatsEventLogger.maybeSetAuthenticationResult(
+ AUTHENTICATION_RESULT_FAILURE);
+ mPresentationStatsEventLogger.logAndEndEvent();
removeFromService();
return;
}
@@ -2461,6 +2490,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
final Dataset dataset = authenticatedResponse.getDatasets().get(datasetIdx);
if (dataset == null) {
Slog.w(TAG, "no dataset with index " + datasetIdx + " on fill response");
+ mPresentationStatsEventLogger.maybeSetAuthenticationResult(
+ AUTHENTICATION_RESULT_FAILURE);
+ mPresentationStatsEventLogger.logAndEndEvent();
removeFromService();
return;
}
@@ -2477,11 +2509,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
if (result instanceof FillResponse) {
logAuthenticationStatusLocked(requestId, MetricsEvent.AUTOFILL_AUTHENTICATED);
+ mPresentationStatsEventLogger.maybeSetAuthenticationResult(
+ AUTHENTICATION_RESULT_SUCCESS);
replaceResponseLocked(authenticatedResponse, (FillResponse) result, newClientState);
} else if (result instanceof Dataset) {
if (datasetIdx != AutofillManager.AUTHENTICATION_ID_DATASET_ID_UNDEFINED) {
logAuthenticationStatusLocked(requestId,
MetricsEvent.AUTOFILL_DATASET_AUTHENTICATED);
+ mPresentationStatsEventLogger.maybeSetAuthenticationResult(
+ AUTHENTICATION_RESULT_SUCCESS);
if (newClientState != null) {
if (sDebug) Slog.d(TAG, "Updating client state from auth dataset");
mClientState = newClientState;
@@ -2497,6 +2533,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
+ authenticationId);
logAuthenticationStatusLocked(requestId,
MetricsEvent.AUTOFILL_INVALID_DATASET_AUTHENTICATION);
+ mPresentationStatsEventLogger.maybeSetAuthenticationResult(
+ AUTHENTICATION_RESULT_FAILURE);
}
} else {
if (result != null) {
@@ -2504,6 +2542,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
logAuthenticationStatusLocked(requestId,
MetricsEvent.AUTOFILL_INVALID_AUTHENTICATION);
+ mPresentationStatsEventLogger.maybeSetAuthenticationResult(
+ AUTHENTICATION_RESULT_FAILURE);
processNullResponseLocked(requestId, 0);
}
}
@@ -4790,6 +4830,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
// Log FillRequest for Augmented Autofill.
mFillRequestEventLogger.startLogForNewRequest();
+ mRequestCount++;
mFillRequestEventLogger.maybeSetAppPackageUid(uid);
mFillRequestEventLogger.maybeSetFlags(mFlags);
mFillRequestEventLogger.maybeSetRequestId(AUGMENTED_AUTOFILL_REQUEST_ID);
@@ -5036,6 +5077,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
if (dataset.getAuthentication() == null) {
if (generateEvent) {
mService.logDatasetSelected(dataset.getId(), id, mClientState, uiType);
+ mPresentationStatsEventLogger.maybeSetSelectedDatasetId(datasetIndex);
}
if (mCurrentViewId != null) {
mInlineSessionController.hideInlineSuggestionsUiLocked(mCurrentViewId);
@@ -5046,6 +5088,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
// ...or handle authentication.
mService.logDatasetAuthenticationSelected(dataset.getId(), id, mClientState, uiType);
+ mPresentationStatsEventLogger.maybeSetAuthenticationType(
+ AUTHENTICATION_TYPE_DATASET_AUTHENTICATION);
setViewStatesLocked(null, dataset, ViewState.STATE_WAITING_DATASET_AUTH, false);
final Intent fillInIntent = createAuthFillInIntentLocked(requestId, mClientState);
if (fillInIntent == null) {
@@ -5639,6 +5683,17 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
*/
@GuardedBy("mLock")
RemoteFillService destroyLocked() {
+ // Log unlogged events.
+ mSessionCommittedEventLogger.maybeSetCommitReason(COMMIT_REASON_SESSION_DESTROYED);
+ mSessionCommittedEventLogger.maybeSetRequestCount(mRequestCount);
+ mSessionCommittedEventLogger.maybeSetSessionDurationMillis(
+ SystemClock.elapsedRealtime() - mStartTime);
+ mSessionCommittedEventLogger.logAndEndEvent();
+ mPresentationStatsEventLogger.logAndEndEvent();
+ mSaveEventLogger.logAndEndEvent();
+ mFillResponseEventLogger.logAndEndEvent();
+ mFillRequestEventLogger.logAndEndEvent();
+
if (mDestroyed) {
return null;
}
diff --git a/services/autofill/java/com/android/server/autofill/SessionCommittedEventLogger.java b/services/autofill/java/com/android/server/autofill/SessionCommittedEventLogger.java
index 92d72ac828f3..541ec80e58ae 100644
--- a/services/autofill/java/com/android/server/autofill/SessionCommittedEventLogger.java
+++ b/services/autofill/java/com/android/server/autofill/SessionCommittedEventLogger.java
@@ -18,6 +18,7 @@ package com.android.server.autofill;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SESSION_COMMITTED;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SESSION_COMMITTED__COMMIT_REASON__COMMIT_REASON_ACTIVITY_FINISHED;
+import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SESSION_COMMITTED__COMMIT_REASON__COMMIT_REASON_SESSION_DESTROYED;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SESSION_COMMITTED__COMMIT_REASON__COMMIT_REASON_UNKNOWN;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SESSION_COMMITTED__COMMIT_REASON__COMMIT_REASON_VIEW_CHANGED;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SESSION_COMMITTED__COMMIT_REASON__COMMIT_REASON_VIEW_CLICKED;
@@ -53,7 +54,8 @@ public final class SessionCommittedEventLogger {
COMMIT_REASON_ACTIVITY_FINISHED,
COMMIT_REASON_VIEW_COMMITTED,
COMMIT_REASON_VIEW_CLICKED,
- COMMIT_REASON_VIEW_CHANGED
+ COMMIT_REASON_VIEW_CHANGED,
+ COMMIT_REASON_SESSION_DESTROYED
})
@Retention(RetentionPolicy.SOURCE)
public @interface CommitReason {
@@ -69,6 +71,8 @@ public final class SessionCommittedEventLogger {
AUTOFILL_SESSION_COMMITTED__COMMIT_REASON__COMMIT_REASON_VIEW_CLICKED;
public static final int COMMIT_REASON_VIEW_CHANGED =
AUTOFILL_SESSION_COMMITTED__COMMIT_REASON__COMMIT_REASON_VIEW_CHANGED;
+ public static final int COMMIT_REASON_SESSION_DESTROYED =
+ AUTOFILL_SESSION_COMMITTED__COMMIT_REASON__COMMIT_REASON_SESSION_DESTROYED;
private final int mSessionId;
private Optional<SessionCommittedEventInternal> mEventInternal;
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 6adccf677bc7..df3c95bdfaf3 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -829,7 +829,8 @@ public final class ActiveServices {
// Service.startForeground()), at that point we will consult the BFSL check and the timeout
// and make the necessary decisions.
setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, r, userId,
- backgroundStartPrivileges, false /* isBindService */);
+ backgroundStartPrivileges, false /* isBindService */,
+ !fgRequired /* isStartService */);
if (!mAm.mUserController.exists(r.userId)) {
Slog.w(TAG, "Trying to start service with non-existent user! " + r.userId);
@@ -2119,7 +2120,11 @@ public final class ActiveServices {
}
}
- if (r.isForeground && isOldTypeShortFgs) {
+ final boolean enableFgsWhileInUseFix = mAm.mConstants.mEnableFgsWhileInUseFix;
+ final boolean fgsTypeChangingFromShortFgs = r.isForeground && isOldTypeShortFgs;
+
+ if (fgsTypeChangingFromShortFgs) {
+
// If we get here, that means startForeground(SHORT_SERVICE) is called again
// on a SHORT_SERVICE FGS.
@@ -2128,7 +2133,7 @@ public final class ActiveServices {
setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.getPid(),
r.appInfo.uid, r.intent.getIntent(), r, r.userId,
BackgroundStartPrivileges.NONE,
- false /* isBindService */);
+ false /* isBindService */, false /* isStartService */);
if (r.mAllowStartForeground == REASON_DENIED) {
Slog.w(TAG_SERVICE, "FGS type change to/from SHORT_SERVICE: "
+ " BFSL DENIED.");
@@ -2171,8 +2176,19 @@ public final class ActiveServices {
// "if (r.mAllowStartForeground == REASON_DENIED...)" block below.
}
}
+ }
- } else if (r.mStartForegroundCount == 0) {
+ // Re-evaluate mAllowWhileInUsePermissionInFgs and mAllowStartForeground
+ // (i.e. while-in-use and BFSL flags) if needed.
+ //
+ // Consider the below if-else section to be in the else of the above
+ // `if (fgsTypeChangingFromShortFgs)`.
+ // Using an else would increase the indent further, so we don't use it here
+ // and instead just add !fgsTypeChangingFromShortFgs to all if's.
+ //
+ // The first if's are for the original while-in-use logic.
+ if (!fgsTypeChangingFromShortFgs && !enableFgsWhileInUseFix
+ && r.mStartForegroundCount == 0) {
/*
If the service was started with startService(), not
startForegroundService(), and if startForeground() isn't called within
@@ -2193,7 +2209,7 @@ public final class ActiveServices {
setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.getPid(),
r.appInfo.uid, r.intent.getIntent(), r, r.userId,
BackgroundStartPrivileges.NONE,
- false /* isBindService */);
+ false /* isBindService */, false /* isStartService */);
final String temp = "startForegroundDelayMs:" + delayMs;
if (r.mInfoAllowStartForeground != null) {
r.mInfoAllowStartForeground += "; " + temp;
@@ -2203,9 +2219,10 @@ public final class ActiveServices {
r.mLoggedInfoAllowStartForeground = false;
}
}
- } else if (r.mStartForegroundCount >= 1) {
+ } else if (!fgsTypeChangingFromShortFgs && !enableFgsWhileInUseFix
+ && r.mStartForegroundCount >= 1) {
// We get here if startForeground() is called multiple times
- // on the same sarvice after it's created, regardless of whether
+ // on the same service after it's created, regardless of whether
// stopForeground() has been called or not.
// The second or later time startForeground() is called after service is
@@ -2213,7 +2230,71 @@ public final class ActiveServices {
setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.getPid(),
r.appInfo.uid, r.intent.getIntent(), r, r.userId,
BackgroundStartPrivileges.NONE,
- false /* isBindService */);
+ false /* isBindService */, false /* isStartService */);
+ } else if (!fgsTypeChangingFromShortFgs && enableFgsWhileInUseFix) {
+ // The new while-in-use logic.
+ //
+ // When startForeground() is called, we _always_ call
+ // setFgsRestrictionLocked() to set the restrictions according to the
+ // current state of the app.
+ // (So if the app is now in TOP, for example, the service will now always
+ // get while-in-use permissions.)
+ //
+ // Note, setFgsRestrictionLocked() will never disallow
+ // mAllowWhileInUsePermissionInFgs nor mAllowStartForeground
+ // (i.e. while-in-use and BFSL flags) once they're set to "allowed".
+ //
+ // HOWEVER, if these flags were set to "allowed" in Context.startService()
+ // (as opposed to startForegroundService()), when the service wasn't yet
+ // a foreground service, then we may not always
+ // want to trust them -- for example, if the service has been running as a
+ // BG service or a bound service for a long time when the app is not longer
+ // in the foreground, then we shouldn't grant while-in-user nor BFSL.
+ // So in that case, we need to reset it first.
+
+ final long delayMs =
+ (r.mLastUntrustedSetFgsRestrictionAllowedTime == 0) ? 0
+ : (SystemClock.elapsedRealtime()
+ - r.mLastUntrustedSetFgsRestrictionAllowedTime);
+ final boolean resetNeeded =
+ !r.isForeground
+ && delayMs > mAm.mConstants.mFgsStartForegroundTimeoutMs;
+ if (resetNeeded) {
+ resetFgsRestrictionLocked(r);
+ }
+ setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.getPid(),
+ r.appInfo.uid, r.intent.getIntent(), r, r.userId,
+ BackgroundStartPrivileges.NONE,
+ false /* isBindService */, false /* isStartService */);
+
+ final String temp = "startForegroundDelayMs:" + delayMs
+ + "; started: " + r.startRequested
+ + "; num_bindings: " + r.getConnections().size()
+ + "; wasForeground: " + r.isForeground
+ + "; resetNeeded:" + resetNeeded;
+ if (r.mInfoAllowStartForeground != null) {
+ r.mInfoAllowStartForeground += "; " + temp;
+ } else {
+ r.mInfoAllowStartForeground = temp;
+ }
+ r.mLoggedInfoAllowStartForeground = false;
+ }
+
+ // If the service has any bindings and it's not yet a FGS
+ // we compare the new and old while-in-use logics.
+ // (If it's not the first startForeground() call, we already reset the
+ // while-in-use and BFSL flags, so the logic change wouldn't matter.)
+ if (enableFgsWhileInUseFix
+ && !r.isForeground
+ && (r.getConnections().size() > 0)
+ && (r.mDebugWhileInUseReasonInBindService
+ != r.mDebugWhileInUseReasonInStartForeground)) {
+ Slog.wtf(TAG, "FGS while-in-use changed (b/276963716): old="
+ + reasonCodeToString(r.mDebugWhileInUseReasonInBindService)
+ + " new="
+ + reasonCodeToString(r.mDebugWhileInUseReasonInStartForeground)
+ + " "
+ + r.shortInstanceName);
}
// If the foreground service is not started from TOP process, do not allow it to
@@ -2321,6 +2402,11 @@ public final class ActiveServices {
active.mNumActive++;
}
r.isForeground = true;
+
+ // Once the service becomes a foreground service,
+ // the FGS restriction information always becomes "trustable".
+ r.mLastUntrustedSetFgsRestrictionAllowedTime = 0;
+
// The logging of FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER event could
// be deferred, make a copy of mAllowStartForeground and
// mAllowWhileInUsePermissionInFgs.
@@ -3663,8 +3749,25 @@ public final class ActiveServices {
return 0;
}
}
- setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, s, userId,
- BackgroundStartPrivileges.NONE, true /* isBindService */);
+ if (!mAm.mConstants.mEnableFgsWhileInUseFix) {
+ // Old while-in-use logic.
+ setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, s, userId,
+ BackgroundStartPrivileges.NONE, true /* isBindService */,
+ false /* isStartService */);
+ } else {
+ // New logic will not call setFgsRestrictionLocked() here, but we still
+ // keep track of the allow reason from the old logic here, so we can compare to
+ // the new logic.
+ // Once we're confident enough in the new logic, we should remove it.
+ if (s.mDebugWhileInUseReasonInBindService == REASON_DENIED) {
+ s.mDebugWhileInUseReasonInBindService =
+ shouldAllowFgsWhileInUsePermissionLocked(
+ callingPackage, callingPid, callingUid, s.app,
+ BackgroundStartPrivileges.NONE,
+ true /* isBindService */,
+ false /* DO NOT enableFgsWhileInUseFix; use the old logic */);
+ }
+ }
if (s.app != null) {
ProcessServiceRecord servicePsr = s.app.mServices;
@@ -7357,45 +7460,76 @@ public final class ActiveServices {
* @param callingUid caller app's uid.
* @param intent intent to start/bind service.
* @param r the service to start.
+ * @param isStartService True if it's called from Context.startService().
+ * False if it's called from Context.startForegroundService() or
+ * Service.startService().
* @return true if allow, false otherwise.
*/
private void setFgsRestrictionLocked(String callingPackage,
int callingPid, int callingUid, Intent intent, ServiceRecord r, int userId,
- BackgroundStartPrivileges backgroundStartPrivileges, boolean isBindService) {
- r.mLastSetFgsRestrictionTime = SystemClock.elapsedRealtime();
+ BackgroundStartPrivileges backgroundStartPrivileges, boolean isBindService,
+ boolean isStartService) {
+ final long now = SystemClock.elapsedRealtime();
+
// Check DeviceConfig flag.
if (!mAm.mConstants.mFlagBackgroundFgsStartRestrictionEnabled) {
r.mAllowWhileInUsePermissionInFgs = true;
}
final @ReasonCode int allowWhileInUse;
+
+ // Either (or both) mAllowWhileInUsePermissionInFgs or mAllowStartForeground is
+ // newly allowed?
+ boolean newlyAllowed = false;
if (!r.mAllowWhileInUsePermissionInFgs
|| (r.mAllowStartForeground == REASON_DENIED)) {
allowWhileInUse = shouldAllowFgsWhileInUsePermissionLocked(
callingPackage, callingPid, callingUid, r.app, backgroundStartPrivileges,
isBindService);
+ // We store them to compare the old and new while-in-use logics to each other.
+ // (They're not used for any other purposes.)
+ if (isBindService) {
+ r.mDebugWhileInUseReasonInBindService = allowWhileInUse;
+ } else {
+ r.mDebugWhileInUseReasonInStartForeground = allowWhileInUse;
+ }
if (!r.mAllowWhileInUsePermissionInFgs) {
r.mAllowWhileInUsePermissionInFgs = (allowWhileInUse != REASON_DENIED);
+ newlyAllowed |= r.mAllowWhileInUsePermissionInFgs;
}
if (r.mAllowStartForeground == REASON_DENIED) {
r.mAllowStartForeground = shouldAllowFgsStartForegroundWithBindingCheckLocked(
allowWhileInUse, callingPackage, callingPid, callingUid, intent, r,
backgroundStartPrivileges, isBindService);
+ newlyAllowed |= r.mAllowStartForeground != REASON_DENIED;
}
} else {
allowWhileInUse = REASON_UNKNOWN;
}
r.mAllowWhileInUsePermissionInFgsReason = allowWhileInUse;
+
+ if (isStartService && !r.isForeground && newlyAllowed) {
+ // If it's called by Context.startService() (not by startForegroundService()),
+ // and we're setting "allowed", then we can't fully trust it yet -- we'll need to reset
+ // the restrictions if startForeground() is called after the grace period.
+ r.mLastUntrustedSetFgsRestrictionAllowedTime = now;
+ }
}
void resetFgsRestrictionLocked(ServiceRecord r) {
r.mAllowWhileInUsePermissionInFgs = false;
r.mAllowWhileInUsePermissionInFgsReason = REASON_DENIED;
+ r.mDebugWhileInUseReasonInStartForeground = REASON_DENIED;
+ // We don't reset mWhileInUseReasonInBindService here, because if we do this, we would
+ // lose it in the "reevaluation" case in startForeground(), where we call
+ // resetFgsRestrictionLocked().
+ // Not resetting this is fine because it's only used in the first Service.startForeground()
+ // case, and there's no situations where we call resetFgsRestrictionLocked() before that.
r.mAllowStartForeground = REASON_DENIED;
r.mInfoAllowStartForeground = null;
r.mInfoTempFgsAllowListReason = null;
r.mLoggedInfoAllowStartForeground = false;
- r.mLastSetFgsRestrictionTime = 0;
+ r.mLastUntrustedSetFgsRestrictionAllowedTime = 0;
r.updateAllowUiJobScheduling(r.mAllowWhileInUsePermissionInFgs);
}
@@ -7430,14 +7564,29 @@ public final class ActiveServices {
private @ReasonCode int shouldAllowFgsWhileInUsePermissionLocked(String callingPackage,
int callingPid, int callingUid, @Nullable ProcessRecord targetProcess,
BackgroundStartPrivileges backgroundStartPrivileges, boolean isBindService) {
+ return shouldAllowFgsWhileInUsePermissionLocked(callingPackage,
+ callingPid, callingUid, targetProcess, backgroundStartPrivileges, isBindService,
+ /* enableFgsWhileInUseFix =*/ mAm.mConstants.mEnableFgsWhileInUseFix);
+ }
+
+ private @ReasonCode int shouldAllowFgsWhileInUsePermissionLocked(String callingPackage,
+ int callingPid, int callingUid, @Nullable ProcessRecord targetProcess,
+ BackgroundStartPrivileges backgroundStartPrivileges, boolean isBindService,
+ boolean enableFgsWhileInUseFix) {
int ret = REASON_DENIED;
- final int uidState = mAm.getUidStateLocked(callingUid);
- if (ret == REASON_DENIED) {
- // Allow FGS while-in-use if the caller's process state is PROCESS_STATE_PERSISTENT,
- // PROCESS_STATE_PERSISTENT_UI or PROCESS_STATE_TOP.
- if (uidState <= PROCESS_STATE_TOP) {
- ret = getReasonCodeFromProcState(uidState);
+ // Define some local variables for better readability...
+ final boolean useOldLogic = !enableFgsWhileInUseFix;
+ final boolean forStartForeground = !isBindService;
+
+ if (useOldLogic || forStartForeground) {
+ final int uidState = mAm.getUidStateLocked(callingUid);
+ if (ret == REASON_DENIED) {
+ // Allow FGS while-in-use if the caller's process state is PROCESS_STATE_PERSISTENT,
+ // PROCESS_STATE_PERSISTENT_UI or PROCESS_STATE_TOP.
+ if (uidState <= PROCESS_STATE_TOP) {
+ ret = getReasonCodeFromProcState(uidState);
+ }
}
}
@@ -7480,6 +7629,10 @@ public final class ActiveServices {
}
}
+ if (enableFgsWhileInUseFix && ret == REASON_DENIED) {
+ ret = shouldAllowFgsWhileInUsePermissionByBindingsLocked(callingUid);
+ }
+
if (ret == REASON_DENIED) {
// Allow FGS while-in-use if the WindowManager allows background activity start.
// This is mainly to get the 10 seconds grace period if any activity in the caller has
@@ -7558,6 +7711,59 @@ public final class ActiveServices {
}
/**
+ * Check all bindings into the calling UID, and see if:
+ * - It's bound by a TOP app
+ * - or, bound by a persistent process with BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS.
+ */
+ private @ReasonCode int shouldAllowFgsWhileInUsePermissionByBindingsLocked(int callingUid) {
+ final ArraySet<Integer> checkedClientUids = new ArraySet<>();
+ final Integer result = mAm.mProcessList.searchEachLruProcessesLOSP(
+ false, pr -> {
+ if (pr.uid != callingUid) {
+ return null;
+ }
+ final ProcessServiceRecord psr = pr.mServices;
+ final int serviceCount = psr.mServices.size();
+ for (int svc = 0; svc < serviceCount; svc++) {
+ final ArrayMap<IBinder, ArrayList<ConnectionRecord>> conns =
+ psr.mServices.valueAt(svc).getConnections();
+ final int size = conns.size();
+ for (int conni = 0; conni < size; conni++) {
+ final ArrayList<ConnectionRecord> crs = conns.valueAt(conni);
+ for (int con = 0; con < crs.size(); con++) {
+ final ConnectionRecord cr = crs.get(con);
+ final ProcessRecord clientPr = cr.binding.client;
+ final int clientUid = clientPr.uid;
+
+ // An UID can bind to itself, do not check on itself again.
+ // Also skip already checked clientUid.
+ if (clientUid == callingUid
+ || checkedClientUids.contains(clientUid)) {
+ continue;
+ }
+
+ // Binding found, check the client procstate and the flag.
+ final int clientUidState = mAm.getUidStateLocked(callingUid);
+ final boolean boundByTop = clientUidState == PROCESS_STATE_TOP;
+ final boolean boundByPersistentWithBal =
+ clientUidState < PROCESS_STATE_TOP
+ && cr.hasFlag(
+ Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS);
+ if (boundByTop || boundByPersistentWithBal) {
+ return getReasonCodeFromProcState(clientUidState);
+ }
+
+ // Don't check the same UID.
+ checkedClientUids.add(clientUid);
+ }
+ }
+ }
+ return null;
+ });
+ return result == null ? REASON_DENIED : result;
+ }
+
+ /**
* The uid is not allowed to start FGS, but the uid has a service that is bound
* by a clientUid, if the clientUid can start FGS, then the clientUid can propagate its
* BG-FGS-start capability down to the callingUid.
@@ -8142,7 +8348,8 @@ public final class ActiveServices {
r.mFgsEnterTime = SystemClock.uptimeMillis();
r.foregroundServiceType = options.mForegroundServiceTypes;
setFgsRestrictionLocked(callingPackage, callingPid, callingUid, intent, r, userId,
- BackgroundStartPrivileges.NONE, false);
+ BackgroundStartPrivileges.NONE, false /* isBindService */,
+ false /* isStartService */);
final ProcessServiceRecord psr = callerApp.mServices;
final boolean newService = psr.startService(r);
// updateOomAdj.
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 44e198b53761..3841b6a27fa0 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -1058,6 +1058,13 @@ final class ActivityManagerConstants extends ContentObserver {
/** @see #KEY_USE_MODERN_TRIM */
public boolean USE_MODERN_TRIM = DEFAULT_USE_MODERN_TRIM;
+ private static final String KEY_ENABLE_FGS_WHILE_IN_USE_FIX =
+ "key_enable_fgs_while_in_use_fix";
+
+ private static final boolean DEFAULT_ENABLE_FGS_WHILE_IN_USE_FIX = true;
+
+ public volatile boolean mEnableFgsWhileInUseFix = DEFAULT_ENABLE_FGS_WHILE_IN_USE_FIX;
+
private final OnPropertiesChangedListener mOnDeviceConfigChangedListener =
new OnPropertiesChangedListener() {
@Override
@@ -1226,6 +1233,9 @@ final class ActivityManagerConstants extends ContentObserver {
case KEY_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION:
updateEnableWaitForFinishAttachApplication();
break;
+ case KEY_ENABLE_FGS_WHILE_IN_USE_FIX:
+ updateEnableFgsWhileInUseFix();
+ break;
case KEY_MAX_PREVIOUS_TIME:
updateMaxPreviousTime();
break;
@@ -1995,6 +2005,12 @@ final class ActivityManagerConstants extends ContentObserver {
DEFAULT_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION);
}
+ private void updateEnableFgsWhileInUseFix() {
+ mEnableFgsWhileInUseFix = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ KEY_ENABLE_FGS_WHILE_IN_USE_FIX,
+ DEFAULT_ENABLE_FGS_WHILE_IN_USE_FIX);
+ }
private void updateUseTieredCachedAdj() {
USE_TIERED_CACHED_ADJ = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
@@ -2195,6 +2211,9 @@ final class ActivityManagerConstants extends ContentObserver {
pw.print(" "); pw.print(KEY_SYSTEM_EXEMPT_POWER_RESTRICTIONS_ENABLED);
pw.print("="); pw.println(mFlagSystemExemptPowerRestrictionsEnabled);
+ pw.print(" "); pw.print(KEY_ENABLE_FGS_WHILE_IN_USE_FIX);
+ pw.print("="); pw.println(mEnableFgsWhileInUseFix);
+
pw.print(" "); pw.print(KEY_SHORT_FGS_TIMEOUT_DURATION);
pw.print("="); pw.println(mShortFgsTimeoutDuration);
pw.print(" "); pw.print(KEY_SHORT_FGS_PROC_STATE_EXTRA_WAIT_DURATION);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 805557dd9d2b..1f80aec3d443 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -382,6 +382,7 @@ import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
+import android.util.StatsEvent;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoUtils;
@@ -1595,6 +1596,7 @@ public class ActivityManagerService extends IActivityManager.Stub
static final int SERVICE_SHORT_FGS_TIMEOUT_MSG = 76;
static final int SERVICE_SHORT_FGS_PROCSTATE_TIMEOUT_MSG = 77;
static final int SERVICE_SHORT_FGS_ANR_TIMEOUT_MSG = 78;
+ static final int UPDATE_CACHED_APP_HIGH_WATERMARK = 79;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1938,6 +1940,9 @@ public class ActivityManagerService extends IActivityManager.Stub
case SERVICE_SHORT_FGS_ANR_TIMEOUT_MSG: {
mServices.onShortFgsAnrTimeout((ServiceRecord) msg.obj);
} break;
+ case UPDATE_CACHED_APP_HIGH_WATERMARK: {
+ mAppProfiler.mCachedAppsWatermarkData.updateCachedAppsSnapshot((long) msg.obj);
+ } break;
}
}
}
@@ -7310,7 +7315,14 @@ public class ActivityManagerService extends IActivityManager.Stub
// Send broadcast to shell to trigger bugreport using Bugreport API
// Always start the shell process on the current user to ensure that
// the foreground user can see all bugreport notifications.
- mContext.sendBroadcastAsUser(triggerShellBugreport, getCurrentUser().getUserHandle());
+ // In case of BUGREPORT_MODE_REMOTE send the broadcast to SYSTEM user as the device
+ // owner apps are running on the SYSTEM user.
+ if (bugreportType == BugreportParams.BUGREPORT_MODE_REMOTE) {
+ mContext.sendBroadcastAsUser(triggerShellBugreport, UserHandle.SYSTEM);
+ } else {
+ mContext.sendBroadcastAsUser(triggerShellBugreport,
+ getCurrentUser().getUserHandle());
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -18598,6 +18610,13 @@ public class ActivityManagerService extends IActivityManager.Stub
@MediaProjectionTokenEvent int event) {
ActivityManagerService.this.notifyMediaProjectionEvent(uid, projectionToken, event);
}
+
+ @Override
+ @NonNull
+ public StatsEvent getCachedAppsHighWatermarkStats(int atomTag, boolean resetAfterPull) {
+ return mAppProfiler.mCachedAppsWatermarkData.getCachedAppsHighWatermarkStats(
+ atomTag, resetAfterPull);
+ }
}
long inputDispatchingTimedOut(int pid, final boolean aboveSystem, TimeoutRecord timeoutRecord) {
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index 25ac956d328d..f29a2e1ee7da 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -82,17 +82,21 @@ import android.util.FeatureFlagUtils;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseIntArray;
+import android.util.StatsEvent;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.ProcessMap;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.os.BinderInternal;
import com.android.internal.os.ProcessCpuTracker;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.MemInfoReader;
+import com.android.internal.util.QuickSelect;
import com.android.server.am.LowMemDetector.MemFactor;
import com.android.server.power.stats.BatteryStatsImpl;
import com.android.server.utils.PriorityDump;
@@ -323,6 +327,8 @@ public class AppProfiler {
private final ActivityManagerService mService;
private final Handler mBgHandler;
+ final CachedAppsWatermarkData mCachedAppsWatermarkData = new CachedAppsWatermarkData();
+
/**
* The lock to guard some of the profiling data here and {@link ProcessProfileRecord}.
*
@@ -391,6 +397,193 @@ public class AppProfiler {
}
}
+ /**
+ * A simple data class holding the information about the cached apps high watermark.
+ *
+ * Keep it sync with the frameworks/proto_logging/stats/atoms.proto
+ */
+ class CachedAppsWatermarkData {
+ /** The high water mark of the number of cached apps. */
+ @GuardedBy("mProcLock")
+ int mCachedAppHighWatermark;
+
+ /**
+ * The uptime (in seconds) at the high watermark.
+ * Note this is going to be pull metrics, so we'll need the timestamp here.
+ */
+ @GuardedBy("mProcLock")
+ int mUptimeInSeconds;
+
+ /** The number of binder proxy at that high water mark. */
+ @GuardedBy("mProcLock")
+ int mBinderProxySnapshot;
+
+ /** Free physical memory (in kb) on device. */
+ @GuardedBy("mProcLock")
+ int mFreeInKb;
+
+ /** Cched physical memory (in kb) on device. */
+ @GuardedBy("mProcLock")
+ int mCachedInKb;
+
+ /** zram (in kb) on device. */
+ @GuardedBy("mProcLock")
+ int mZramInKb;
+
+ /** Kernel memory (in kb) on device. */
+ @GuardedBy("mProcLock")
+ int mKernelInKb;
+
+ /** The number of apps in frozen state. */
+ @GuardedBy("mProcLock")
+ int mNumOfFrozenApps;
+
+ /** The longest frozen time (now - last_frozen) in current frozen apps. */
+ @GuardedBy("mProcLock")
+ int mLongestFrozenTimeInSeconds;
+
+ /** The shortest frozen time (now - last_frozen) in current frozen apps. */
+ @GuardedBy("mProcLock")
+ int mShortestFrozenTimeInSeconds;
+
+ /** The mean frozen time (now - last_frozen) in current frozen apps. */
+ @GuardedBy("mProcLock")
+ int mMeanFrozenTimeInSeconds;
+
+ /** The average frozen time (now - last_frozen) in current frozen apps. */
+ @GuardedBy("mProcLock")
+ int mAverageFrozenTimeInSeconds;
+
+ /**
+ * This is an array holding the frozen app durations temporarily
+ * while updating the cached app high watermark.
+ */
+ @GuardedBy("mProcLock")
+ private long[] mCachedAppFrozenDurations;
+
+ /**
+ * The earliest frozen timestamp within the frozen apps.
+ */
+ @GuardedBy("mProcLock")
+ private long mEarliestFrozenTimestamp;
+
+ /**
+ * The most recent frozen timestamp within the frozen apps.
+ */
+ @GuardedBy("mProcLock")
+ private long mLatestFrozenTimestamp;
+
+ /**
+ * The sum of total frozen durations of all frozen apps.
+ */
+ @GuardedBy("mProcLock")
+ private long mTotalFrozenDurations;
+
+ @GuardedBy("mProcLock")
+ void updateCachedAppsHighWatermarkIfNecessaryLocked(int numOfCachedApps, long now) {
+ if (numOfCachedApps > mCachedAppHighWatermark) {
+ mCachedAppHighWatermark = numOfCachedApps;
+ mUptimeInSeconds = (int) (now / 1000);
+
+ // The rest of the updates are pretty costly, do it in a separated handler.
+ mService.mHandler.removeMessages(
+ ActivityManagerService.UPDATE_CACHED_APP_HIGH_WATERMARK);
+ mService.mHandler.obtainMessage(
+ ActivityManagerService.UPDATE_CACHED_APP_HIGH_WATERMARK, Long.valueOf(now))
+ .sendToTarget();
+ }
+ }
+
+ void updateCachedAppsSnapshot(long now) {
+ synchronized (mProcLock) {
+ mEarliestFrozenTimestamp = now;
+ mLatestFrozenTimestamp = 0L;
+ mTotalFrozenDurations = 0L;
+ mNumOfFrozenApps = 0;
+ if (mCachedAppFrozenDurations == null
+ || mCachedAppFrozenDurations.length < mCachedAppHighWatermark) {
+ mCachedAppFrozenDurations = new long[Math.max(
+ mCachedAppHighWatermark, mService.mConstants.CUR_MAX_CACHED_PROCESSES)];
+ }
+ mService.mProcessList.forEachLruProcessesLOSP(true, app -> {
+ if (app.mOptRecord.isFrozen()) {
+ final long freezeTime = app.mOptRecord.getFreezeUnfreezeTime();
+ if (freezeTime < mEarliestFrozenTimestamp) {
+ mEarliestFrozenTimestamp = freezeTime;
+ }
+ if (freezeTime > mLatestFrozenTimestamp) {
+ mLatestFrozenTimestamp = freezeTime;
+ }
+ final long duration = now - freezeTime;
+ mTotalFrozenDurations += duration;
+ mCachedAppFrozenDurations[mNumOfFrozenApps++] = duration;
+ }
+ });
+ if (mNumOfFrozenApps > 0) {
+ mLongestFrozenTimeInSeconds = (int) ((now - mEarliestFrozenTimestamp) / 1000);
+ mShortestFrozenTimeInSeconds = (int) ((now - mLatestFrozenTimestamp) / 1000);
+ mAverageFrozenTimeInSeconds =
+ (int) ((mTotalFrozenDurations / mNumOfFrozenApps) / 1000);
+ mMeanFrozenTimeInSeconds = (int) (QuickSelect.select(mCachedAppFrozenDurations,
+ 0, mNumOfFrozenApps, mNumOfFrozenApps / 2) / 1000);
+ }
+
+ mBinderProxySnapshot = 0;
+ final SparseIntArray counts = BinderInternal.nGetBinderProxyPerUidCounts();
+ if (counts != null) {
+ for (int i = 0, size = counts.size(); i < size; i++) {
+ final int uid = counts.keyAt(i);
+ final UidRecord uidRec = mService.mProcessList.getUidRecordLOSP(uid);
+ if (uidRec != null) {
+ mBinderProxySnapshot += counts.valueAt(i);
+ }
+ }
+ }
+
+ final MemInfoReader memInfo = new MemInfoReader();
+ memInfo.readMemInfo();
+ mFreeInKb = (int) memInfo.getFreeSizeKb();
+ mCachedInKb = (int) memInfo.getCachedSizeKb();
+ mZramInKb = (int) memInfo.getZramTotalSizeKb();
+ mKernelInKb = (int) memInfo.getKernelUsedSizeKb();
+ }
+ }
+
+ @NonNull
+ StatsEvent getCachedAppsHighWatermarkStats(int atomTag, boolean resetAfterPull) {
+ synchronized (mProcLock) {
+ final StatsEvent event = FrameworkStatsLog.buildStatsEvent(atomTag,
+ mCachedAppHighWatermark,
+ mUptimeInSeconds,
+ mBinderProxySnapshot,
+ mFreeInKb,
+ mCachedInKb,
+ mZramInKb,
+ mKernelInKb,
+ mNumOfFrozenApps,
+ mLongestFrozenTimeInSeconds,
+ mShortestFrozenTimeInSeconds,
+ mMeanFrozenTimeInSeconds,
+ mAverageFrozenTimeInSeconds);
+ if (resetAfterPull) {
+ mCachedAppHighWatermark = 0;
+ mUptimeInSeconds = 0;
+ mBinderProxySnapshot = 0;
+ mFreeInKb = 0;
+ mCachedInKb = 0;
+ mZramInKb = 0;
+ mKernelInKb = 0;
+ mNumOfFrozenApps = 0;
+ mLongestFrozenTimeInSeconds = 0;
+ mShortestFrozenTimeInSeconds = 0;
+ mMeanFrozenTimeInSeconds = 0;
+ mAverageFrozenTimeInSeconds = 0;
+ }
+ return event;
+ }
+ }
+ }
+
private class BgHandler extends Handler {
static final int COLLECT_PSS_BG_MSG = 1;
static final int DEFER_PSS_MSG = 2;
@@ -954,7 +1147,7 @@ public class AppProfiler {
}
@GuardedBy({"mService", "mProcLock"})
- boolean updateLowMemStateLSP(int numCached, int numEmpty, int numTrimming) {
+ boolean updateLowMemStateLSP(int numCached, int numEmpty, int numTrimming, long now) {
int memFactor;
if (mLowMemDetector != null && mLowMemDetector.isAvailable()) {
memFactor = mLowMemDetector.getMemFactor();
@@ -1040,11 +1233,10 @@ public class AppProfiler {
mLastNumProcesses = mService.mProcessList.getLruSizeLOSP();
boolean allChanged;
int trackerMemFactor;
- final long now;
synchronized (mService.mProcessStats.mLock) {
- now = SystemClock.uptimeMillis();
allChanged = mService.mProcessStats.setMemFactorLocked(memFactor,
- mService.mAtmInternal == null || !mService.mAtmInternal.isSleeping(), now);
+ mService.mAtmInternal == null || !mService.mAtmInternal.isSleeping(),
+ SystemClock.uptimeMillis() /* re-acquire the time within the lock */);
trackerMemFactor = mService.mProcessStats.getMemFactorLocked();
}
if (memFactor != ADJ_MEM_FACTOR_NORMAL) {
@@ -1124,6 +1316,8 @@ public class AppProfiler {
profile.setTrimMemoryLevel(0);
});
}
+ mCachedAppsWatermarkData.updateCachedAppsHighWatermarkIfNecessaryLocked(
+ numCached + numEmpty, now);
return allChanged;
}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index c3519d21eb15..1e5f187fee4a 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1401,7 +1401,7 @@ public class OomAdjuster {
mLastFreeSwapPercent = freeSwapPercent;
- return mService.mAppProfiler.updateLowMemStateLSP(numCached, numEmpty, numTrimming);
+ return mService.mAppProfiler.updateLowMemStateLSP(numCached, numEmpty, numTrimming, now);
}
@GuardedBy({"mService", "mProcLock"})
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 312f98ad6e09..d7b22a8a2da0 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -108,6 +108,7 @@ import android.os.Trace;
import android.os.UserHandle;
import android.os.storage.StorageManagerInternal;
import android.system.Os;
+import android.system.OsConstants;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -2331,9 +2332,15 @@ public final class ProcessList {
if (!regularZygote) {
// webview and app zygote don't have the permission to create the nodes
- if (Process.createProcessGroup(uid, startResult.pid) < 0) {
- throw new AssertionError("Unable to create process group for " + app.processName
- + " (" + startResult.pid + ")");
+ final int res = Process.createProcessGroup(uid, startResult.pid);
+ if (res < 0) {
+ if (res == -OsConstants.ESRCH) {
+ Slog.e(ActivityManagerService.TAG, "Unable to create process group for "
+ + app.processName + " (" + startResult.pid + ")");
+ } else {
+ throw new AssertionError("Unable to create process group for "
+ + app.processName + " (" + startResult.pid + ")");
+ }
}
}
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index a875860f016f..78aafeba3b22 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -176,6 +176,13 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
boolean mAllowWhileInUsePermissionInFgs;
@PowerExemptionManager.ReasonCode
int mAllowWhileInUsePermissionInFgsReason;
+
+ // Integer version of mAllowWhileInUsePermissionInFgs that we keep track to compare
+ // the old and new logics.
+ // TODO: Remove them once we're confident in the new logic.
+ int mDebugWhileInUseReasonInStartForeground = REASON_DENIED;
+ int mDebugWhileInUseReasonInBindService = REASON_DENIED;
+
// A copy of mAllowWhileInUsePermissionInFgs's value when the service is entering FGS state.
boolean mAllowWhileInUsePermissionInFgsAtEntering;
/** Allow scheduling user-initiated jobs from the background. */
@@ -216,8 +223,13 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
// created. (i.e. due to "bound" or "start".) It never decreases, even when stopForeground()
// is called.
int mStartForegroundCount;
- // Last time mAllowWhileInUsePermissionInFgs or mAllowStartForeground is set.
- long mLastSetFgsRestrictionTime;
+
+ // Last time mAllowWhileInUsePermissionInFgs or mAllowStartForeground was set to "allowed"
+ // from "disallowed" when the service was _not_ already a foreground service.
+ // this means they're set in startService(). (not startForegroundService)
+ // In startForeground(), if this timestamp is too old, we can't trust these flags, so
+ // we need to reset them.
+ long mLastUntrustedSetFgsRestrictionAllowedTime;
// This is a service record of a FGS delegate (not a service record of a real service)
boolean mIsFgsDelegate;
@@ -609,10 +621,14 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
pw.print(prefix); pw.print("mIsAllowedBgActivityStartsByStart=");
pw.println(mBackgroundStartPrivilegesByStartMerged);
}
- pw.print(prefix); pw.print("allowWhileInUsePermissionInFgs=");
- pw.println(mAllowWhileInUsePermissionInFgs);
pw.print(prefix); pw.print("mAllowWhileInUsePermissionInFgsReason=");
pw.println(mAllowWhileInUsePermissionInFgsReason);
+
+ pw.print(prefix); pw.print("debugWhileInUseReasonInStartForeground=");
+ pw.println(mDebugWhileInUseReasonInStartForeground);
+ pw.print(prefix); pw.print("debugWhileInUseReasonInBindService=");
+ pw.println(mDebugWhileInUseReasonInBindService);
+
pw.print(prefix); pw.print("allowUiJobScheduling="); pw.println(mAllowUiJobScheduling);
pw.print(prefix); pw.print("recentCallingPackage=");
pw.println(mRecentCallingPackage);
@@ -624,6 +640,10 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
pw.println(mStartForegroundCount);
pw.print(prefix); pw.print("infoAllowStartForeground=");
pw.println(mInfoAllowStartForeground);
+
+ pw.print(prefix); pw.print("lastUntrustedSetFgsRestrictionAllowedTime=");
+ TimeUtils.formatDuration(mLastUntrustedSetFgsRestrictionAllowedTime, now, pw);
+
if (delayed) {
pw.print(prefix); pw.print("delayed="); pw.println(delayed);
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index a3163e010efa..02c4770ba899 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -2284,8 +2284,8 @@ public class AudioService extends IAudioService.Stub
synchronized (VolumeStreamState.class) {
mStreamStates[AudioSystem.STREAM_DTMF]
.setAllIndexes(mStreamStates[dtmfStreamAlias], caller);
- mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].mVolumeIndexSettingName =
- System.VOLUME_SETTINGS_INT[a11yStreamAlias];
+ mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setSettingName(
+ System.VOLUME_SETTINGS_INT[a11yStreamAlias]);
mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setAllIndexes(
mStreamStates[a11yStreamAlias], caller);
}
@@ -7700,7 +7700,7 @@ public class AudioService extends IAudioService.Stub
private int mPublicStreamType = AudioSystem.STREAM_MUSIC;
private AudioAttributes mAudioAttributes = AudioProductStrategy.getDefaultAttributes();
private boolean mIsMuted = false;
- private final String mSettingName;
+ private String mSettingName;
// No API in AudioSystem to get a device from strategy or from attributes.
// Need a valid public stream type to use current API getDeviceForStream
@@ -8029,15 +8029,19 @@ public class AudioService extends IAudioService.Stub
}
private void persistVolumeGroup(int device) {
- if (mUseFixedVolume) {
+ // No need to persist the index if the volume group is backed up
+ // by a public stream type as this is redundant
+ if (mUseFixedVolume || mHasValidStreamType) {
return;
}
if (DEBUG_VOL) {
Log.v(TAG, "persistVolumeGroup: storing index " + getIndex(device) + " for group "
+ mAudioVolumeGroup.name()
+ ", device " + AudioSystem.getOutputDeviceName(device)
- + " and User=" + getCurrentUserId());
+ + " and User=" + getCurrentUserId()
+ + " mSettingName: " + mSettingName);
}
+
boolean success = mSettings.putSystemIntForUser(mContentResolver,
getSettingNameForDevice(device),
getIndex(device),
@@ -8100,6 +8104,14 @@ public class AudioService extends IAudioService.Stub
return mSettingName + "_" + AudioSystem.getOutputDeviceName(device);
}
+ void setSettingName(String settingName) {
+ mSettingName = settingName;
+ }
+
+ String getSettingName() {
+ return mSettingName;
+ }
+
private void dump(PrintWriter pw) {
pw.println("- VOLUME GROUP " + mAudioVolumeGroup.name() + ":");
pw.print(" Muted: ");
@@ -8242,6 +8254,9 @@ public class AudioService extends IAudioService.Stub
*/
public void setVolumeGroupState(VolumeGroupState volumeGroupState) {
mVolumeGroupState = volumeGroupState;
+ if (mVolumeGroupState != null) {
+ mVolumeGroupState.setSettingName(mVolumeIndexSettingName);
+ }
}
/**
* Update the minimum index that can be used without MODIFY_AUDIO_SETTINGS permission
@@ -8315,6 +8330,17 @@ public class AudioService extends IAudioService.Stub
return (mVolumeIndexSettingName != null && !mVolumeIndexSettingName.isEmpty());
}
+ void setSettingName(String settingName) {
+ mVolumeIndexSettingName = settingName;
+ if (mVolumeGroupState != null) {
+ mVolumeGroupState.setSettingName(mVolumeIndexSettingName);
+ }
+ }
+
+ String getSettingName() {
+ return mVolumeIndexSettingName;
+ }
+
public void readSettings() {
synchronized (mSettingsLock) {
synchronized (VolumeStreamState.class) {
@@ -8989,7 +9015,7 @@ public class AudioService extends IAudioService.Stub
if (streamState.hasValidSettingsName()) {
mSettings.putSystemIntForUser(mContentResolver,
streamState.getSettingNameForDevice(device),
- (streamState.getIndex(device) + 5)/ 10,
+ (streamState.getIndex(device) + 5) / 10,
UserHandle.USER_CURRENT);
}
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 71c4aedea0da..1dc2725feb1b 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -231,7 +231,8 @@ public class Vpn {
* <p>If retries have exceeded the length of this array, the last entry in the array will be
* used as a repeating interval.
*/
- private static final long[] IKEV2_VPN_RETRY_DELAYS_SEC = {1L, 2L, 5L, 30L, 60L, 300L, 900L};
+ private static final long[] IKEV2_VPN_RETRY_DELAYS_MS =
+ {1_000L, 2_000L, 5_000L, 30_000L, 60_000L, 300_000L, 900_000L};
/**
* A constant to pass to {@link IkeV2VpnRunner#scheduleStartIkeSession(long)} to mean the
@@ -647,14 +648,14 @@ public class Vpn {
/**
* Retrieves the next retry delay
*
- * <p>If retries have exceeded the IKEV2_VPN_RETRY_DELAYS_SEC, the last entry in
+ * <p>If retries have exceeded the size of IKEV2_VPN_RETRY_DELAYS_MS, the last entry in
* the array will be used as a repeating interval.
*/
- public long getNextRetryDelaySeconds(int retryCount) {
- if (retryCount >= IKEV2_VPN_RETRY_DELAYS_SEC.length) {
- return IKEV2_VPN_RETRY_DELAYS_SEC[IKEV2_VPN_RETRY_DELAYS_SEC.length - 1];
+ public long getNextRetryDelayMs(int retryCount) {
+ if (retryCount >= IKEV2_VPN_RETRY_DELAYS_MS.length) {
+ return IKEV2_VPN_RETRY_DELAYS_MS[IKEV2_VPN_RETRY_DELAYS_MS.length - 1];
} else {
- return IKEV2_VPN_RETRY_DELAYS_SEC[retryCount];
+ return IKEV2_VPN_RETRY_DELAYS_MS[retryCount];
}
}
@@ -3782,7 +3783,7 @@ public class Vpn {
}
final long retryDelayMs = RETRY_DELAY_AUTO_BACKOFF != delayMs
? delayMs
- : mDeps.getNextRetryDelaySeconds(mRetryCount++) * 1000;
+ : mDeps.getNextRetryDelayMs(mRetryCount++);
Log.d(TAG, "Retry new IKE session after " + retryDelayMs + " milliseconds.");
// If the default network is lost during the retry delay, the mActiveNetwork will be
// null, and the new IKE session won't be established until there is a new default
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 43082c1f1f6f..1acc20880258 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -1816,10 +1816,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// TODO(b/216365040): The decision to prevent HBM for HDR in low power mode should be
// done in HighBrightnessModeController.
if (mHbmController.getHighBrightnessMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
- && (mBrightnessReason.getModifier() & BrightnessReason.MODIFIER_DIMMED) == 0
- && (mBrightnessReason.getModifier() & BrightnessReason.MODIFIER_LOW_POWER)
+ && (mBrightnessReasonTemp.getModifier() & BrightnessReason.MODIFIER_DIMMED) == 0
+ && (mBrightnessReasonTemp.getModifier() & BrightnessReason.MODIFIER_LOW_POWER)
== 0) {
- // We want to scale HDR brightness level with the SDR level
+ // We want to scale HDR brightness level with the SDR level, we also need to restore
+ // SDR brightness immediately when entering dim or low power mode.
animateValue = mHbmController.getHdrBrightnessValue();
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index 7339874e7bfa..b36aedefa2a7 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -1456,10 +1456,11 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
// TODO(b/216365040): The decision to prevent HBM for HDR in low power mode should be
// done in HighBrightnessModeController.
if (mHbmController.getHighBrightnessMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
- && (mBrightnessReason.getModifier() & BrightnessReason.MODIFIER_DIMMED) == 0
- && (mBrightnessReason.getModifier() & BrightnessReason.MODIFIER_LOW_POWER)
+ && (mBrightnessReasonTemp.getModifier() & BrightnessReason.MODIFIER_DIMMED) == 0
+ && (mBrightnessReasonTemp.getModifier() & BrightnessReason.MODIFIER_LOW_POWER)
== 0) {
- // We want to scale HDR brightness level with the SDR level
+ // We want to scale HDR brightness level with the SDR level, we also need to restore
+ // SDR brightness immediately when entering dim or low power mode.
animateValue = mHbmController.getHdrBrightnessValue();
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index d0669e7602ed..5f45f912a87a 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -686,13 +686,7 @@ public class InputManagerService extends IInputManager.Stub
@NonNull
private InputChannel createSpyWindowGestureMonitor(IBinder monitorToken, String name,
- int displayId, int pid, int uid) {
- final SurfaceControl sc = mWindowManagerCallbacks.createSurfaceForGestureMonitor(name,
- displayId);
- if (sc == null) {
- throw new IllegalArgumentException(
- "Could not create gesture monitor surface on display: " + displayId);
- }
+ SurfaceControl sc, int displayId, int pid, int uid) {
final InputChannel channel = createInputChannel(name);
try {
@@ -749,9 +743,18 @@ public class InputManagerService extends IInputManager.Stub
final long ident = Binder.clearCallingIdentity();
try {
- final InputChannel inputChannel =
- createSpyWindowGestureMonitor(monitorToken, name, displayId, pid, uid);
- return new InputMonitor(inputChannel, new InputMonitorHost(inputChannel.getToken()));
+ final SurfaceControl sc = mWindowManagerCallbacks.createSurfaceForGestureMonitor(name,
+ displayId);
+ if (sc == null) {
+ throw new IllegalArgumentException(
+ "Could not create gesture monitor surface on display: " + displayId);
+ }
+
+ final InputChannel inputChannel = createSpyWindowGestureMonitor(
+ monitorToken, name, sc, displayId, pid, uid);
+ return new InputMonitor(inputChannel,
+ new InputMonitorHost(inputChannel.getToken()),
+ new SurfaceControl(sc, "IMS.monitorGestureInput"));
} finally {
Binder.restoreCallingIdentity(ident);
}
diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java
index b82e3a31567e..c076c0574afe 100644
--- a/services/core/java/com/android/server/media/MediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java
@@ -19,6 +19,7 @@ package com.android.server.media;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
+import android.media.MediaRoute2Info;
import android.media.MediaRoute2ProviderInfo;
import android.media.RouteDiscoveryPreference;
import android.media.RoutingSessionInfo;
@@ -26,6 +27,7 @@ import android.os.Bundle;
import com.android.internal.annotations.GuardedBy;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -108,6 +110,28 @@ abstract class MediaRoute2Provider {
&& mComponentName.getClassName().equals(className);
}
+ public void dump(PrintWriter pw, String prefix) {
+ pw.println(prefix + getDebugString());
+ prefix += " ";
+ if (mProviderInfo == null) {
+ pw.println(prefix + "<provider info not received, yet>");
+ } else if (mProviderInfo.getRoutes().isEmpty()) {
+ pw.println(prefix + "<provider info has no routes>");
+ } else {
+ for (MediaRoute2Info route : mProviderInfo.getRoutes()) {
+ pw.printf("%s%s | %s\n", prefix, route.getId(), route.getName());
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getDebugString();
+ }
+
+ /** Returns a human-readable string describing the instance, for debugging purposes. */
+ protected abstract String getDebugString();
+
public interface Callback {
void onProviderStateChanged(@Nullable MediaRoute2Provider provider);
void onSessionCreated(@NonNull MediaRoute2Provider provider,
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
index 90451b19d590..72b843672ae8 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
@@ -44,7 +44,6 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
-import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
@@ -83,10 +82,6 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
mHandler = new Handler(Looper.myLooper());
}
- public void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + getDebugString());
- }
-
public void setManagerScanning(boolean managerScanning) {
if (mIsManagerScanning != managerScanning) {
mIsManagerScanning = managerScanning;
@@ -488,11 +483,7 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
}
@Override
- public String toString() {
- return getDebugString();
- }
-
- private String getDebugString() {
+ protected String getDebugString() {
return TextUtils.formatSimple(
"ProviderServiceProxy - package: %s, bound: %b, connection (active:%b, ready:%b)",
mComponentName.getPackageName(),
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 3c97aaf87e9c..2d3b97b768d3 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -1751,6 +1751,7 @@ class MediaRouter2ServiceImpl {
String indent = prefix + " ";
pw.println(indent + "mRunning=" + mRunning);
+ mSystemProvider.dump(pw, prefix);
mWatcher.dump(pw, prefix);
}
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 5d5c621eb3f5..6d2d2e405ab9 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -392,6 +392,15 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
mCallback.onSessionUpdated(this, sessionInfo);
}
+ @Override
+ protected String getDebugString() {
+ return TextUtils.formatSimple(
+ "SystemMR2Provider - package: %s, selected route id: %s, bluetooth impl: %s",
+ mComponentName.getPackageName(),
+ mSelectedRouteId,
+ mBluetoothRouteController.getClass().getSimpleName());
+ }
+
private static class SessionCreationRequest {
final long mRequestId;
final String mRouteId;
diff --git a/services/core/java/com/android/server/pm/BroadcastHelper.java b/services/core/java/com/android/server/pm/BroadcastHelper.java
index c1171fabea7b..2704f56b539d 100644
--- a/services/core/java/com/android/server/pm/BroadcastHelper.java
+++ b/services/core/java/com/android/server/pm/BroadcastHelper.java
@@ -38,6 +38,7 @@ import android.content.Context;
import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.pm.PackageInstaller;
+import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.PowerExemptionManager;
@@ -337,7 +338,7 @@ public final class BroadcastHelper {
broadcastAllowlist, null /* filterExtrasForReceiver */, null);
// Send to PermissionController for all new users, even if it may not be running for some
// users
- if (isPrivacySafetyLabelChangeNotificationsEnabled()) {
+ if (isPrivacySafetyLabelChangeNotificationsEnabled(mContext)) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
packageName, extras, 0,
mContext.getPackageManager().getPermissionControllerPackageName(),
@@ -389,9 +390,13 @@ public final class BroadcastHelper {
}
/** Returns whether the Safety Label Change notification, a privacy feature, is enabled. */
- public static boolean isPrivacySafetyLabelChangeNotificationsEnabled() {
+ public static boolean isPrivacySafetyLabelChangeNotificationsEnabled(Context context) {
+ PackageManager packageManager = context.getPackageManager();
return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED, false);
+ SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED, false)
+ && !packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
+ && !packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+ && !packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH);
}
@NonNull
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index ecd2a90fe039..1e0c95ca9013 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -2954,7 +2954,7 @@ final class InstallPackageHelper {
}
// Send to PermissionController for all update users, even if it may not be running
// for some users
- if (BroadcastHelper.isPrivacySafetyLabelChangeNotificationsEnabled()) {
+ if (BroadcastHelper.isPrivacySafetyLabelChangeNotificationsEnabled(mContext)) {
mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/,
mPm.mRequiredPermissionControllerPackage, null /*finishedReceiver*/,
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 86403779d35a..0ce17ded31e4 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -751,6 +751,8 @@ public class StatsPullAtomService extends SystemService {
return pullPendingIntentsPerPackage(atomTag, data);
case FrameworkStatsLog.HDR_CAPABILITIES:
return pullHdrCapabilities(atomTag, data);
+ case FrameworkStatsLog.CACHED_APPS_HIGH_WATERMARK:
+ return pullCachedAppsHighWatermark(atomTag, data);
default:
throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
}
@@ -951,6 +953,7 @@ public class StatsPullAtomService extends SystemService {
registerPendingIntentsPerPackagePuller();
registerPinnerServiceStats();
registerHdrCapabilitiesPuller();
+ registerCachedAppsHighWatermarkPuller();
}
private void initAndRegisterNetworkStatsPullers() {
@@ -4732,6 +4735,12 @@ public class StatsPullAtomService extends SystemService {
return StatsManager.PULL_SUCCESS;
}
+ private int pullCachedAppsHighWatermark(int atomTag, List<StatsEvent> pulledData) {
+ pulledData.add(LocalServices.getService(ActivityManagerInternal.class)
+ .getCachedAppsHighWatermarkStats(atomTag, true));
+ return StatsManager.PULL_SUCCESS;
+ }
+
private boolean hasDolbyVisionIssue(Display display) {
AtomicInteger modesSupportingDolbyVision = new AtomicInteger();
Arrays.stream(display.getSupportedModes())
@@ -4777,6 +4786,16 @@ public class StatsPullAtomService extends SystemService {
);
}
+ private void registerCachedAppsHighWatermarkPuller() {
+ final int tagId = FrameworkStatsLog.CACHED_APPS_HIGH_WATERMARK;
+ mStatsManager.setPullAtomCallback(
+ tagId,
+ null, // use default PullAtomMetadata values
+ DIRECT_EXECUTOR,
+ mStatsCallbackImpl
+ );
+ }
+
int pullSystemServerPinnerStats(int atomTag, List<StatsEvent> pulledData) {
PinnerService pinnerService = LocalServices.getService(PinnerService.class);
List<PinnedFileStats> pinnedFileStats = pinnerService.dumpDataForStatsd();
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index a757d90b75ba..f71f3b128557 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -397,9 +397,21 @@ class ActivityMetricsLogger {
/** Returns {@code true} if the incoming activity can belong to this transition. */
boolean canCoalesce(ActivityRecord r) {
- return mLastLaunchedActivity.mDisplayContent == r.mDisplayContent
- && mLastLaunchedActivity.getTask().getBounds().equals(r.getTask().getBounds())
- && mLastLaunchedActivity.getWindowingMode() == r.getWindowingMode();
+ if (mLastLaunchedActivity.mDisplayContent != r.mDisplayContent
+ || mLastLaunchedActivity.getWindowingMode() != r.getWindowingMode()) {
+ return false;
+ }
+ // The current task should be non-null because it is just launched. While the
+ // last task can be cleared when starting activity with FLAG_ACTIVITY_CLEAR_TASK.
+ final Task lastTask = mLastLaunchedActivity.getTask();
+ final Task currentTask = r.getTask();
+ if (lastTask != null && currentTask != null) {
+ if (lastTask == currentTask) {
+ return true;
+ }
+ return lastTask.getBounds().equals(currentTask.getBounds());
+ }
+ return mLastLaunchedActivity.isUid(r.launchedFromUid);
}
/** @return {@code true} if the activity matches a launched activity in this transition. */
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 2160ce1be729..c6a2e0e51227 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2821,6 +2821,27 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
}
+ @Override
+ void waitForSyncTransactionCommit(ArraySet<WindowContainer> wcAwaitingCommit) {
+ super.waitForSyncTransactionCommit(wcAwaitingCommit);
+ if (mStartingData != null) {
+ mStartingData.mWaitForSyncTransactionCommit = true;
+ }
+ }
+
+ @Override
+ void onSyncTransactionCommitted(SurfaceControl.Transaction t) {
+ super.onSyncTransactionCommitted(t);
+ if (mStartingData == null) {
+ return;
+ }
+ mStartingData.mWaitForSyncTransactionCommit = false;
+ if (mStartingData.mRemoveAfterTransaction) {
+ mStartingData.mRemoveAfterTransaction = false;
+ removeStartingWindowAnimation(mStartingData.mPrepareRemoveAnimation);
+ }
+ }
+
void removeStartingWindowAnimation(boolean prepareAnimation) {
mTransferringSplashScreenState = TRANSFER_SPLASH_SCREEN_IDLE;
if (task != null) {
@@ -2843,6 +2864,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final WindowState startingWindow = mStartingWindow;
final boolean animate;
if (mStartingData != null) {
+ if (mStartingData.mWaitForSyncTransactionCommit
+ || mTransitionController.inCollectingTransition(startingWindow)) {
+ mStartingData.mRemoveAfterTransaction = true;
+ mStartingData.mPrepareRemoveAnimation = prepareAnimation;
+ return;
+ }
animate = prepareAnimation && mStartingData.needRevealAnimation()
&& mStartingWindow.isVisibleByPolicy();
ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Schedule remove starting %s startingWindow=%s"
@@ -2863,18 +2890,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
this);
return;
}
-
- if (animate && mTransitionController.inCollectingTransition(startingWindow)) {
- // Defer remove starting window after transition start.
- // The surface of app window could really show after the transition finish.
- startingWindow.mSyncTransaction.addTransactionCommittedListener(Runnable::run, () -> {
- synchronized (mAtmService.mGlobalLock) {
- surface.remove(true);
- }
- });
- } else {
- surface.remove(animate);
- }
+ surface.remove(animate);
}
/**
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index abf66bc7ccc0..f93afe81f804 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2008,7 +2008,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return;
}
- if (r.isState(RESUMED) && r == mRootWindowContainer.getTopResumedActivity()) {
+ if ((touchedActivity == null || r == touchedActivity) && r.isState(RESUMED)
+ && r == mRootWindowContainer.getTopResumedActivity()) {
setLastResumedActivityUncheckLocked(r, "setFocusedTask-alreadyTop");
return;
}
diff --git a/services/core/java/com/android/server/wm/StartingData.java b/services/core/java/com/android/server/wm/StartingData.java
index 300a894d15c9..cff86add7efc 100644
--- a/services/core/java/com/android/server/wm/StartingData.java
+++ b/services/core/java/com/android/server/wm/StartingData.java
@@ -41,6 +41,26 @@ public abstract class StartingData {
/** Whether the starting window is drawn. */
boolean mIsDisplayed;
+ /**
+ * For Shell transition.
+ * There will be a transition happen on attached activity, do not remove starting window during
+ * this period, because the transaction to show app window may not apply before remove starting
+ * window.
+ * Note this isn't equal to transition playing, the period should be
+ * Sync finishNow -> Start transaction apply.
+ */
+ boolean mWaitForSyncTransactionCommit;
+
+ /**
+ * For Shell transition.
+ * This starting window should be removed after applying the start transaction of transition,
+ * which ensures the app window has shown.
+ */
+ boolean mRemoveAfterTransaction;
+
+ /** Whether to prepare the removal animation. */
+ boolean mPrepareRemoveAnimation;
+
protected StartingData(WindowManagerService service, int typeParams) {
mService = service;
mTypeParams = typeParams;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index d1618e9a278b..678d4c863d5d 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -166,6 +166,7 @@ import static com.android.server.wm.WindowStateProto.IS_ON_SCREEN;
import static com.android.server.wm.WindowStateProto.IS_READY_FOR_DISPLAY;
import static com.android.server.wm.WindowStateProto.IS_VISIBLE;
import static com.android.server.wm.WindowStateProto.KEEP_CLEAR_AREAS;
+import static com.android.server.wm.WindowStateProto.MERGED_LOCAL_INSETS_SOURCES;
import static com.android.server.wm.WindowStateProto.PENDING_SEAMLESS_ROTATION;
import static com.android.server.wm.WindowStateProto.REMOVED;
import static com.android.server.wm.WindowStateProto.REMOVE_ON_EXIT;
@@ -4027,6 +4028,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
for (Rect r : mUnrestrictedKeepClearAreas) {
r.dumpDebug(proto, UNRESTRICTED_KEEP_CLEAR_AREAS);
}
+ if (mMergedLocalInsetsSources != null) {
+ for (int i = 0; i < mMergedLocalInsetsSources.size(); ++i) {
+ mMergedLocalInsetsSources.valueAt(i).dumpDebug(proto, MERGED_LOCAL_INSETS_SOURCES);
+ }
+ }
proto.end(token);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
index 1027b31b1879..415440b1f46d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
@@ -1017,8 +1017,12 @@ final class DevicePolicyEngine {
int userId = user.id;
// Apply local policies present on parent to newly created child profile.
UserInfo parentInfo = mUserManager.getProfileParent(userId);
- if (parentInfo == null || parentInfo.getUserHandle().getIdentifier() == userId) return;
-
+ if (parentInfo == null || parentInfo.getUserHandle().getIdentifier() == userId) {
+ return;
+ }
+ if (!mLocalPolicies.contains(parentInfo.getUserHandle().getIdentifier())) {
+ return;
+ }
for (Map.Entry<PolicyKey, PolicyState<?>> entry : mLocalPolicies.get(
parentInfo.getUserHandle().getIdentifier()).entrySet()) {
enforcePolicyOnUser(userId, entry.getValue());
@@ -1242,6 +1246,31 @@ final class DevicePolicyEngine {
synchronized (mLock) {
clear();
new DevicePoliciesReaderWriter().readFromFileLocked();
+ reapplyAllPolicies();
+ }
+ }
+
+ private <V> void reapplyAllPolicies() {
+ for (PolicyKey policy : mGlobalPolicies.keySet()) {
+ PolicyState<?> policyState = mGlobalPolicies.get(policy);
+ // Policy definition and value will always be of the same type
+ PolicyDefinition<V> policyDefinition =
+ (PolicyDefinition<V>) policyState.getPolicyDefinition();
+ PolicyValue<V> policyValue = (PolicyValue<V>) policyState.getCurrentResolvedPolicy();
+ enforcePolicy(policyDefinition, policyValue, UserHandle.USER_ALL);
+ }
+ for (int i = 0; i < mLocalPolicies.size(); i++) {
+ int userId = mLocalPolicies.keyAt(i);
+ for (PolicyKey policy : mLocalPolicies.get(userId).keySet()) {
+ PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy);
+ // Policy definition and value will always be of the same type
+ PolicyDefinition<V> policyDefinition =
+ (PolicyDefinition<V>) policyState.getPolicyDefinition();
+ PolicyValue<V> policyValue =
+ (PolicyValue<V>) policyState.getCurrentResolvedPolicy();
+ enforcePolicy(policyDefinition, policyValue, userId);
+
+ }
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 4566b3b28b15..18fcafa84c24 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -85,6 +85,7 @@ import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
import static android.Manifest.permission.SET_TIME;
import static android.Manifest.permission.SET_TIME_ZONE;
import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
+import static android.accounts.AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
@@ -532,6 +533,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -1140,6 +1142,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
}
+
+ if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
+ calculateHasIncompatibleAccounts();
+ }
+
if (Intent.ACTION_BOOT_COMPLETED.equals(action)
&& userHandle == mOwners.getDeviceOwnerUserId()) {
mBugreportCollectionManager.checkForPendingBugreportAfterBoot();
@@ -1253,6 +1260,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} else if (ACTION_MANAGED_PROFILE_AVAILABLE.equals(action)) {
notifyIfManagedSubscriptionsAreUnavailable(
UserHandle.of(userHandle), /* managedProfileAvailable= */ true);
+ } else if (LOGIN_ACCOUNTS_CHANGED_ACTION.equals(action)) {
+ calculateHasIncompatibleAccounts();
}
}
@@ -2105,6 +2114,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
filter.addAction(Intent.ACTION_USER_STOPPED);
filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(Intent.ACTION_USER_UNLOCKED);
+ filter.addAction(LOGIN_ACCOUNTS_CHANGED_ACTION);
filter.addAction(ACTION_MANAGED_PROFILE_UNAVAILABLE);
filter.addAction(ACTION_MANAGED_PROFILE_AVAILABLE);
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
@@ -2131,7 +2141,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mUserManagerInternal.addUserLifecycleListener(new UserLifecycleListener());
mDeviceManagementResourcesProvider.load();
- if (isPermissionCheckFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled() || isPolicyEngineForFinanceFlagEnabled()) {
mDevicePolicyEngine.load();
}
@@ -3280,8 +3290,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
policy.validatePasswordOwner();
updateMaximumTimeToLockLocked(userHandle);
- updateLockTaskPackagesLocked(mContext, policy.mLockTaskPackages, userHandle);
- updateLockTaskFeaturesLocked(policy.mLockTaskFeatures, userHandle);
+ if (!isPolicyEngineForFinanceFlagEnabled()) {
+ updateLockTaskPackagesLocked(mContext, policy.mLockTaskPackages, userHandle);
+ updateLockTaskFeaturesLocked(policy.mLockTaskFeatures, userHandle);
+ }
if (policy.mStatusBarDisabled) {
setStatusBarDisabledInternal(policy.mStatusBarDisabled, userHandle);
}
@@ -3593,7 +3605,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
startOwnerService(userId, "start-user");
- if (isPermissionCheckFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled() || isPolicyEngineForFinanceFlagEnabled()) {
mDevicePolicyEngine.handleStartUser(userId);
}
}
@@ -3620,7 +3632,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
void handleUnlockUser(int userId) {
startOwnerService(userId, "unlock-user");
- if (isPermissionCheckFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled() || isPolicyEngineForFinanceFlagEnabled()) {
mDevicePolicyEngine.handleUnlockUser(userId);
}
}
@@ -3632,7 +3644,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
void handleStopUser(int userId) {
updateNetworkPreferenceForUser(userId, List.of(PreferentialNetworkServiceConfig.DEFAULT));
mDeviceAdminServiceController.stopServicesForUser(userId, /* actionForLog= */ "stop-user");
- if (isPermissionCheckFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled() || isPolicyEngineForFinanceFlagEnabled()) {
mDevicePolicyEngine.handleStopUser(userId);
}
}
@@ -9558,6 +9570,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (getLockObject()) {
enforceCanSetDeviceOwnerLocked(caller, admin, userId, hasIncompatibleAccountsOrNonAdb);
+
Preconditions.checkArgument(isPackageInstalledForUser(admin.getPackageName(), userId),
"Invalid component " + admin + " for device owner");
final ActiveAdmin activeAdmin = getActiveAdminUncheckedLocked(admin, userId);
@@ -10247,7 +10260,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
policy.mUserProvisioningState = DevicePolicyManager.STATE_USER_UNMANAGED;
policy.mAffiliationIds.clear();
policy.mLockTaskPackages.clear();
- updateLockTaskPackagesLocked(mContext, policy.mLockTaskPackages, userId);
+ if (!isPolicyEngineForFinanceFlagEnabled()) {
+ updateLockTaskPackagesLocked(mContext, policy.mLockTaskPackages, userId);
+ }
policy.mLockTaskFeatures = DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
saveSettingsLocked(userId);
@@ -11037,7 +11052,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return false;
}
- if (!isPermissionCheckFlagEnabled()) {
+ if (!isPermissionCheckFlagEnabled() && !isPolicyEngineForFinanceFlagEnabled()) {
// TODO: Figure out if something like this needs to be restored for policy engine
final ComponentName profileOwner = getProfileOwnerAsUser(userId);
if (profileOwner == null) {
@@ -14918,6 +14933,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
final List<String> lockTaskPackages = getUserData(userId).mLockTaskPackages;
+ // TODO(b/278438525): handle in the policy engine
if (!lockTaskPackages.isEmpty()) {
Slogf.d(LOG_TAG,
"User id " + userId + " not affiliated. Clearing lock task packages");
@@ -18381,6 +18397,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return isUserAffiliatedWithDeviceLocked(userId);
}
+ private boolean hasIncompatibleAccountsOnAnyUser() {
+ if (mHasIncompatibleAccounts == null) {
+ // Hasn't loaded for the first time yet - assume the worst
+ return true;
+ }
+
+ for (boolean hasIncompatible : mHasIncompatibleAccounts.values()) {
+ if (hasIncompatible) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private boolean hasIncompatibleAccounts(int userId) {
+ return mHasIncompatibleAccounts == null ? true
+ : mHasIncompatibleAccounts.getOrDefault(userId, /* default= */ false);
+ }
+
/**
* Return true if a given user has any accounts that'll prevent installing a device or profile
* owner {@code owner}.
@@ -18418,7 +18454,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- boolean compatible = !hasIncompatibleAccounts(am, accounts);
+ boolean compatible = !hasIncompatibleAccounts(userId);
if (compatible) {
Slogf.w(LOG_TAG, "All accounts are compatible");
} else {
@@ -18428,37 +18464,67 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
});
}
- private boolean hasIncompatibleAccounts(AccountManager am, Account[] accounts) {
- // TODO(b/244284408): Add test
- final String[] feature_allow =
- { DevicePolicyManager.ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED };
- final String[] feature_disallow =
- { DevicePolicyManager.ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED };
+ @Override
+ public void calculateHasIncompatibleAccounts() {
+ new CalculateHasIncompatibleAccountsTask().executeOnExecutor(
+ AsyncTask.THREAD_POOL_EXECUTOR, null);
+ }
- for (Account account : accounts) {
- if (hasAccountFeatures(am, account, feature_disallow)) {
- Slogf.e(LOG_TAG, "%s has %s", account, feature_disallow[0]);
- return true;
- }
- if (!hasAccountFeatures(am, account, feature_allow)) {
- Slogf.e(LOG_TAG, "%s doesn't have %s", account, feature_allow[0]);
- return true;
+ @Nullable
+ private volatile Map<Integer, Boolean> mHasIncompatibleAccounts;
+
+ class CalculateHasIncompatibleAccountsTask extends AsyncTask<
+ Void, Void, Map<Integer, Boolean>> {
+ private static final String[] FEATURE_ALLOW =
+ {DevicePolicyManager.ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED};
+ private static final String[] FEATURE_DISALLOW =
+ {DevicePolicyManager.ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED};
+
+ @Override
+ protected Map<Integer, Boolean> doInBackground(Void... args) {
+ List<UserInfo> users = mUserManagerInternal.getUsers(/* excludeDying= */ true);
+ Map<Integer, Boolean> results = new HashMap<>();
+ for (UserInfo userInfo : users) {
+ results.put(userInfo.id, userHasIncompatibleAccounts(userInfo.id));
}
+
+ return results;
}
- return false;
- }
+ private boolean userHasIncompatibleAccounts(int id) {
+ AccountManager am = mContext.createContextAsUser(UserHandle.of(id), /* flags= */ 0)
+ .getSystemService(AccountManager.class);
+ Account[] accounts = am.getAccounts();
+
+ for (Account account : accounts) {
+ if (hasAccountFeatures(am, account, FEATURE_DISALLOW)) {
+ return true;
+ }
+ if (!hasAccountFeatures(am, account, FEATURE_ALLOW)) {
+ return true;
+ }
+ }
- private boolean hasAccountFeatures(AccountManager am, Account account, String[] features) {
- try {
- // TODO(267156507): Restore without blocking binder thread
- return false;
-// return am.hasFeatures(account, features, null, null).getResult();
- } catch (Exception e) {
- Slogf.w(LOG_TAG, "Failed to get account feature", e);
return false;
}
- }
+
+ @Override
+ protected void onPostExecute(Map<Integer, Boolean> results) {
+ mHasIncompatibleAccounts = Collections.unmodifiableMap(results);
+
+ Slogf.i(LOG_TAG, "Finished calculating hasIncompatibleAccountsTask");
+ }
+
+ private static boolean hasAccountFeatures(AccountManager am, Account account,
+ String[] features) {
+ try {
+ return am.hasFeatures(account, features, null, null).getResult();
+ } catch (Exception e) {
+ Slogf.w(LOG_TAG, "Failed to get account feature", e);
+ return false;
+ }
+ }
+ };
private boolean isAdb(CallerIdentity caller) {
return isShellUid(caller) || isRootUid(caller);
@@ -22290,26 +22356,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- private boolean hasIncompatibleAccountsOnAnyUser() {
- long callingIdentity = Binder.clearCallingIdentity();
- try {
- for (UserInfo user : mUserManagerInternal.getUsers(/* excludeDying= */ true)) {
- AccountManager am = mContext.createContextAsUser(
- UserHandle.of(user.id), /* flags= */ 0)
- .getSystemService(AccountManager.class);
- Account[] accounts = am.getAccounts();
-
- if (hasIncompatibleAccounts(am, accounts)) {
- return true;
- }
- }
-
- return false;
- } finally {
- Binder.restoreCallingIdentity(callingIdentity);
- }
- }
-
private void setBypassDevicePolicyManagementRoleQualificationStateInternal(
String currentRoleHolder, boolean allowBypass) {
boolean stateChanged = false;
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java
index 8c8401497d48..dc92376263a6 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java
@@ -199,10 +199,11 @@ public class PackageManagerTests extends AndroidTestCase {
}
public Intent getResult() {
- try {
- return mResult.take();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
+ while (true) {
+ try {
+ return mResult.take();
+ } catch (InterruptedException e) {
+ }
}
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index 4e001fe06fb8..37c4b3787835 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -28,6 +28,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMor
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
@@ -501,6 +502,12 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase {
onActivityLaunched(mTrampolineActivity);
mActivityMetricsLogger.notifyActivityLaunching(mTopActivity.intent,
mTrampolineActivity /* caller */, mTrampolineActivity.getUid());
+
+ // Simulate a corner case that the trampoline activity is removed by CLEAR_TASK.
+ // The 2 launch events can still be coalesced to one by matching the uid.
+ mTrampolineActivity.takeFromHistory();
+ assertNull(mTrampolineActivity.getTask());
+
notifyActivityLaunched(START_SUCCESS, mTopActivity);
transitToDrawnAndVerifyOnLaunchFinished(mTopActivity);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index 49d8da1b2880..9d597b11120d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -586,6 +586,15 @@ public class TaskFragmentTest extends WindowTestsBase {
// Making the activity0 be the focused activity and ensure the focused app is updated.
activity0.moveFocusableActivityToTop("test");
assertEquals(activity0, mDisplayContent.mFocusedApp);
+
+ // Moving activity1 to top and make both the two activities resumed.
+ activity1.moveFocusableActivityToTop("test");
+ activity0.setState(RESUMED, "test");
+ activity1.setState(RESUMED, "test");
+
+ // Verifies that the focus app can be updated to an Activity in the adjacent TF
+ mAtm.setFocusedTask(task.mTaskId, activity0);
+ assertEquals(activity0, mDisplayContent.mFocusedApp);
}
@Test
diff --git a/telephony/OWNERS b/telephony/OWNERS
index 025869dd2999..3158ad8fc58e 100644
--- a/telephony/OWNERS
+++ b/telephony/OWNERS
@@ -11,12 +11,6 @@ chinmayd@google.com
amruthr@google.com
sasindran@google.com
-# Temporarily reduced the owner during refactoring
-per-file SubscriptionManager.java=set noparent
-per-file SubscriptionManager.java=jackyu@google.com,amruthr@google.com
-per-file SubscriptionInfo.java=set noparent
-per-file SubscriptionInfo.java=jackyu@google.com,amruthr@google.com
-
# Requiring TL ownership for new carrier config keys.
per-file CarrierConfigManager.java=set noparent
per-file CarrierConfigManager.java=amruthr@google.com,tgunn@google.com,rgreenwalt@google.com,satk@google.com
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 905a90c11957..caafce2f1a7e 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -331,8 +331,8 @@ public final class TelephonyPermissions {
* Same as {@link #checkCallingOrSelfReadSubscriberIdentifiers(Context, int, String, String,
* String)} except this allows an additional parameter reportFailure. Caller may not want to
* report a failure when this is an internal/intermediate check, for example,
- * SubscriptionController calls this with an INVALID_SUBID to check if caller has the required
- * permissions to bypass carrier privilege checks.
+ * SubscriptionManagerService calls this with an INVALID_SUBID to check if caller has the
+ * required permissions to bypass carrier privilege checks.
* @param reportFailure Indicates if failure should be reported.
*/
public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId,
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 559faf9b20de..64e43568e4d6 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -91,8 +91,7 @@ import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
- * SubscriptionManager is the application interface to SubscriptionController
- * and provides information about the current Telephony Subscriptions.
+ * Subscription manager provides the mobile subscription information.
*/
@SystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@@ -119,13 +118,12 @@ public class SubscriptionManager {
public static final int DEFAULT_SUBSCRIPTION_ID = Integer.MAX_VALUE;
/**
- * Indicates the caller wants the default phone id.
- * Used in SubscriptionController and Phone but do we really need it???
+ * Indicates the default phone id.
* @hide
*/
public static final int DEFAULT_PHONE_INDEX = Integer.MAX_VALUE;
- /** Indicates the caller wants the default slot id. NOT used remove? */
+ /** Indicates the default slot index. */
/** @hide */
public static final int DEFAULT_SIM_SLOT_INDEX = Integer.MAX_VALUE;
@@ -141,29 +139,10 @@ public class SubscriptionManager {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static final Uri CONTENT_URI = SimInfo.CONTENT_URI;
- private static final String CACHE_KEY_DEFAULT_SUB_ID_PROPERTY =
- "cache_key.telephony.get_default_sub_id";
-
- private static final String CACHE_KEY_DEFAULT_DATA_SUB_ID_PROPERTY =
- "cache_key.telephony.get_default_data_sub_id";
-
- private static final String CACHE_KEY_DEFAULT_SMS_SUB_ID_PROPERTY =
- "cache_key.telephony.get_default_sms_sub_id";
-
- private static final String CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY =
- "cache_key.telephony.get_active_data_sub_id";
-
- private static final String CACHE_KEY_SLOT_INDEX_PROPERTY =
- "cache_key.telephony.get_slot_index";
-
/** The IPC cache key shared by all subscription manager service cacheable properties. */
private static final String CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY =
"cache_key.telephony.subscription_manager_service";
- /** The temporarily cache key to indicate whether subscription manager service is enabled. */
- private static final String CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_ENABLED_PROPERTY =
- "cache_key.telephony.subscription_manager_service_enabled";
-
/** @hide */
public static final String GET_SIM_SPECIFIC_SETTINGS_METHOD_NAME = "getSimSpecificSettings";
@@ -273,83 +252,41 @@ public class SubscriptionManager {
}
}
- private static VoidPropertyInvalidatedCache<Integer> sDefaultSubIdCache =
- new VoidPropertyInvalidatedCache<>(ISub::getDefaultSubId,
- CACHE_KEY_DEFAULT_SUB_ID_PROPERTY,
- INVALID_SUBSCRIPTION_ID);
-
private static VoidPropertyInvalidatedCache<Integer> sGetDefaultSubIdCache =
new VoidPropertyInvalidatedCache<>(ISub::getDefaultSubId,
CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY,
INVALID_SUBSCRIPTION_ID);
- private static VoidPropertyInvalidatedCache<Integer> sDefaultDataSubIdCache =
- new VoidPropertyInvalidatedCache<>(ISub::getDefaultDataSubId,
- CACHE_KEY_DEFAULT_DATA_SUB_ID_PROPERTY,
- INVALID_SUBSCRIPTION_ID);
-
private static VoidPropertyInvalidatedCache<Integer> sGetDefaultDataSubIdCache =
new VoidPropertyInvalidatedCache<>(ISub::getDefaultDataSubId,
CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY,
INVALID_SUBSCRIPTION_ID);
- private static VoidPropertyInvalidatedCache<Integer> sDefaultSmsSubIdCache =
- new VoidPropertyInvalidatedCache<>(ISub::getDefaultSmsSubId,
- CACHE_KEY_DEFAULT_SMS_SUB_ID_PROPERTY,
- INVALID_SUBSCRIPTION_ID);
-
private static VoidPropertyInvalidatedCache<Integer> sGetDefaultSmsSubIdCache =
new VoidPropertyInvalidatedCache<>(ISub::getDefaultSmsSubId,
CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY,
INVALID_SUBSCRIPTION_ID);
- private static VoidPropertyInvalidatedCache<Integer> sActiveDataSubIdCache =
- new VoidPropertyInvalidatedCache<>(ISub::getActiveDataSubscriptionId,
- CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY,
- INVALID_SUBSCRIPTION_ID);
-
private static VoidPropertyInvalidatedCache<Integer> sGetActiveDataSubscriptionIdCache =
new VoidPropertyInvalidatedCache<>(ISub::getActiveDataSubscriptionId,
CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY,
INVALID_SUBSCRIPTION_ID);
- private static IntegerPropertyInvalidatedCache<Integer> sSlotIndexCache =
- new IntegerPropertyInvalidatedCache<>(ISub::getSlotIndex,
- CACHE_KEY_SLOT_INDEX_PROPERTY,
- INVALID_SIM_SLOT_INDEX);
-
private static IntegerPropertyInvalidatedCache<Integer> sGetSlotIndexCache =
new IntegerPropertyInvalidatedCache<>(ISub::getSlotIndex,
CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY,
INVALID_SIM_SLOT_INDEX);
- private static IntegerPropertyInvalidatedCache<Integer> sSubIdCache =
- new IntegerPropertyInvalidatedCache<>(ISub::getSubId,
- CACHE_KEY_SLOT_INDEX_PROPERTY,
- INVALID_SUBSCRIPTION_ID);
-
private static IntegerPropertyInvalidatedCache<Integer> sGetSubIdCache =
new IntegerPropertyInvalidatedCache<>(ISub::getSubId,
CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY,
INVALID_SUBSCRIPTION_ID);
- /** Cache depends on getDefaultSubId, so we use the defaultSubId cache key */
- private static IntegerPropertyInvalidatedCache<Integer> sPhoneIdCache =
- new IntegerPropertyInvalidatedCache<>(ISub::getPhoneId,
- CACHE_KEY_DEFAULT_SUB_ID_PROPERTY,
- INVALID_PHONE_INDEX);
-
private static IntegerPropertyInvalidatedCache<Integer> sGetPhoneIdCache =
new IntegerPropertyInvalidatedCache<>(ISub::getPhoneId,
CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY,
INVALID_PHONE_INDEX);
- //TODO: Removed before U AOSP public release.
- private static VoidPropertyInvalidatedCache<Boolean> sIsSubscriptionManagerServiceEnabled =
- new VoidPropertyInvalidatedCache<>(ISub::isSubscriptionManagerServiceEnabled,
- CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_ENABLED_PROPERTY,
- false);
-
/**
* Generates a content {@link Uri} used to receive updates on simInfo change
* on the given subscriptionId
@@ -1455,17 +1392,6 @@ public class SubscriptionManager {
mContext = context;
}
- /**
- * @return {@code true} if the new subscription manager service is used. This is temporary and
- * will be removed before Android 14 release.
- *
- * @hide
- */
- //TODO: Removed before U AOSP public release.
- public static boolean isSubscriptionManagerServiceEnabled() {
- return sIsSubscriptionManagerServiceEnabled.query(null);
- }
-
private NetworkPolicyManager getNetworkPolicyManager() {
return (NetworkPolicyManager) mContext
.getSystemService(Context.NETWORK_POLICY_SERVICE);
@@ -1520,7 +1446,7 @@ public class SubscriptionManager {
+ " listener=" + listener);
}
// We use the TelephonyRegistry as it runs in the system and thus is always
- // available. Where as SubscriptionController could crash and not be available
+ // available.
TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
if (telephonyRegistryManager != null) {
@@ -1550,7 +1476,7 @@ public class SubscriptionManager {
+ " listener=" + listener);
}
// We use the TelephonyRegistry as it runs in the system and thus is always
- // available where as SubscriptionController could crash and not be available
+ // available.
TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
if (telephonyRegistryManager != null) {
@@ -1608,7 +1534,7 @@ public class SubscriptionManager {
}
// We use the TelephonyRegistry as it runs in the system and thus is always
- // available where as SubscriptionController could crash and not be available
+ // available.
TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
if (telephonyRegistryManager != null) {
@@ -2149,9 +2075,9 @@ public class SubscriptionManager {
Log.e(LOG_TAG, "[removeSubscriptionInfoRecord]- ISub service is null");
return;
}
- int result = iSub.removeSubInfo(uniqueId, subscriptionType);
- if (result < 0) {
- Log.e(LOG_TAG, "Removal of subscription didn't succeed: error = " + result);
+ boolean result = iSub.removeSubInfo(uniqueId, subscriptionType);
+ if (!result) {
+ Log.e(LOG_TAG, "Removal of subscription didn't succeed");
} else {
logd("successfully removed subscription");
}
@@ -2236,8 +2162,7 @@ public class SubscriptionManager {
* subscriptionId doesn't have an associated slot index.
*/
public static int getSlotIndex(int subscriptionId) {
- if (isSubscriptionManagerServiceEnabled()) return sGetSlotIndexCache.query(subscriptionId);
- return sSlotIndexCache.query(subscriptionId);
+ return sGetSlotIndexCache.query(subscriptionId);
}
/**
@@ -2294,15 +2219,13 @@ public class SubscriptionManager {
return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
- if (isSubscriptionManagerServiceEnabled()) return sGetSubIdCache.query(slotIndex);
- return sSubIdCache.query(slotIndex);
+ return sGetSubIdCache.query(slotIndex);
}
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public static int getPhoneId(int subId) {
- if (isSubscriptionManagerServiceEnabled()) return sGetPhoneIdCache.query(subId);
- return sPhoneIdCache.query(subId);
+ return sGetPhoneIdCache.query(subId);
}
private static void logd(String msg) {
@@ -2323,8 +2246,7 @@ public class SubscriptionManager {
* @return the "system" default subscription id.
*/
public static int getDefaultSubscriptionId() {
- if (isSubscriptionManagerServiceEnabled()) return sGetDefaultSubIdCache.query(null);
- return sDefaultSubIdCache.query(null);
+ return sGetDefaultSubIdCache.query(null);
}
/**
@@ -2412,8 +2334,7 @@ public class SubscriptionManager {
* @return the default SMS subscription Id.
*/
public static int getDefaultSmsSubscriptionId() {
- if (isSubscriptionManagerServiceEnabled()) return sGetDefaultSmsSubIdCache.query(null);
- return sDefaultSmsSubIdCache.query(null);
+ return sGetDefaultSmsSubIdCache.query(null);
}
/**
@@ -2447,8 +2368,7 @@ public class SubscriptionManager {
* @return the default data subscription Id.
*/
public static int getDefaultDataSubscriptionId() {
- if (isSubscriptionManagerServiceEnabled()) return sGetDefaultDataSubIdCache.query(null);
- return sDefaultDataSubIdCache.query(null);
+ return sGetDefaultDataSubIdCache.query(null);
}
/**
@@ -3912,10 +3832,7 @@ public class SubscriptionManager {
* @see TelephonyCallback.ActiveDataSubscriptionIdListener
*/
public static int getActiveDataSubscriptionId() {
- if (isSubscriptionManagerServiceEnabled()) {
- return sGetActiveDataSubscriptionIdCache.query(null);
- }
- return sActiveDataSubIdCache.query(null);
+ return sGetActiveDataSubscriptionIdCache.query(null);
}
/**
@@ -3934,61 +3851,16 @@ public class SubscriptionManager {
}
/** @hide */
- public static void invalidateDefaultSubIdCaches() {
- PropertyInvalidatedCache.invalidateCache(CACHE_KEY_DEFAULT_SUB_ID_PROPERTY);
- }
-
- /** @hide */
- public static void invalidateDefaultDataSubIdCaches() {
- PropertyInvalidatedCache.invalidateCache(CACHE_KEY_DEFAULT_DATA_SUB_ID_PROPERTY);
- }
-
- /** @hide */
- public static void invalidateDefaultSmsSubIdCaches() {
- PropertyInvalidatedCache.invalidateCache(CACHE_KEY_DEFAULT_SMS_SUB_ID_PROPERTY);
- }
-
- /** @hide */
- public static void invalidateActiveDataSubIdCaches() {
- if (isSubscriptionManagerServiceEnabled()) {
- PropertyInvalidatedCache.invalidateCache(
- CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY);
- } else {
- PropertyInvalidatedCache.invalidateCache(CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY);
- }
- }
-
- /** @hide */
- public static void invalidateSlotIndexCaches() {
- PropertyInvalidatedCache.invalidateCache(CACHE_KEY_SLOT_INDEX_PROPERTY);
- }
-
- /** @hide */
public static void invalidateSubscriptionManagerServiceCaches() {
PropertyInvalidatedCache.invalidateCache(CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY);
}
- /** @hide */
- //TODO: Removed before U AOSP public release.
- public static void invalidateSubscriptionManagerServiceEnabledCaches() {
- PropertyInvalidatedCache.invalidateCache(
- CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_ENABLED_PROPERTY);
- }
-
/**
* Allows a test process to disable client-side caching operations.
*
* @hide
*/
public static void disableCaching() {
- sDefaultSubIdCache.disableLocal();
- sDefaultDataSubIdCache.disableLocal();
- sActiveDataSubIdCache.disableLocal();
- sDefaultSmsSubIdCache.disableLocal();
- sSlotIndexCache.disableLocal();
- sSubIdCache.disableLocal();
- sPhoneIdCache.disableLocal();
-
sGetDefaultSubIdCache.disableLocal();
sGetDefaultDataSubIdCache.disableLocal();
sGetActiveDataSubscriptionIdCache.disableLocal();
@@ -3996,8 +3868,6 @@ public class SubscriptionManager {
sGetSlotIndexCache.disableLocal();
sGetSubIdCache.disableLocal();
sGetPhoneIdCache.disableLocal();
-
- sIsSubscriptionManagerServiceEnabled.disableLocal();
}
/**
@@ -4005,14 +3875,6 @@ public class SubscriptionManager {
*
* @hide */
public static void clearCaches() {
- sDefaultSubIdCache.clear();
- sDefaultDataSubIdCache.clear();
- sActiveDataSubIdCache.clear();
- sDefaultSmsSubIdCache.clear();
- sSlotIndexCache.clear();
- sSubIdCache.clear();
- sPhoneIdCache.clear();
-
sGetDefaultSubIdCache.clear();
sGetDefaultDataSubIdCache.clear();
sGetActiveDataSubscriptionIdCache.clear();
@@ -4020,8 +3882,6 @@ public class SubscriptionManager {
sGetSlotIndexCache.clear();
sGetSubIdCache.clear();
sGetPhoneIdCache.clear();
-
- sIsSubscriptionManagerServiceEnabled.clear();
}
/**
diff --git a/telephony/java/android/telephony/satellite/stub/ISatelliteGateway.aidl b/telephony/java/android/telephony/satellite/stub/ISatelliteGateway.aidl
new file mode 100644
index 000000000000..4f1a13623c3b
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/stub/ISatelliteGateway.aidl
@@ -0,0 +1,26 @@
+/*
+ * 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.telephony.satellite.stub;
+
+/**
+ * {@hide}
+ */
+oneway interface ISatelliteGateway {
+ // An empty service because Telephony does not need to use any APIs from this service.
+ // Once satellite modem is enabled, Telephony will bind to the ISatelliteGateway service; and
+ // when satellite modem is disabled, Telephony will unbind to the service.
+}
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteGatewayService.java b/telephony/java/android/telephony/satellite/stub/SatelliteGatewayService.java
new file mode 100644
index 000000000000..f4514a6de413
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteGatewayService.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.telephony.satellite.stub;
+
+import android.annotation.SdkConstant;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+import com.android.telephony.Rlog;
+
+/**
+ * Main SatelliteGatewayService implementation, which binds via the Telephony SatelliteController.
+ * Services that extend SatelliteGatewayService must register the service in their AndroidManifest
+ * to be detected by the framework. The application must declare that they require the
+ * "android.permission.BIND_SATELLITE_GATEWAY_SERVICE" permission to ensure that nothing else can
+ * bind to their service except the Telephony framework. The SatelliteGatewayService definition in
+ * the manifest must follow the following format:
+ *
+ * ...
+ * <service android:name=".EgSatelliteGatewayService"
+ * android:permission="android.permission.BIND_SATELLITE_GATEWAY_SERVICE" >
+ * ...
+ * <intent-filter>
+ * <action android:name="android.telephony.satellite.SatelliteGatewayService" />
+ * </intent-filter>
+ * </service>
+ * ...
+ *
+ * The telephony framework will then bind to the SatelliteGatewayService defined in the manifest if
+ * it is the default SatelliteGatewayService defined in the device overlay
+ * "config_satellite_gateway_service_package".
+ * @hide
+ */
+public abstract class SatelliteGatewayService extends Service {
+ private static final String TAG = "SatelliteGatewayService";
+
+ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+ public static final String SERVICE_INTERFACE =
+ "android.telephony.satellite.SatelliteGatewayService";
+
+ private final IBinder mBinder = new ISatelliteGateway.Stub() {};
+
+ /**
+ * @hide
+ */
+ @Override
+ public final IBinder onBind(Intent intent) {
+ if (SERVICE_INTERFACE.equals(intent.getAction())) {
+ Rlog.d(TAG, "SatelliteGatewayService bound");
+ return mBinder;
+ }
+ return null;
+ }
+
+ /**
+ * @return The binder for the ISatelliteGateway.
+ * @hide
+ */
+ public final IBinder getBinder() {
+ return mBinder;
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 6a5380ddb36e..21a6b447d6a4 100644
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -129,9 +129,9 @@ interface ISub {
* @param uniqueId This is the unique identifier for the subscription within the specific
* subscription type.
* @param subscriptionType the type of subscription to be removed
- * @return 0 if success, < 0 on error.
+ * @return true if success, false on error.
*/
- int removeSubInfo(String uniqueId, int subscriptionType);
+ boolean removeSubInfo(String uniqueId, int subscriptionType);
/**
* Set SIM icon tint color by simInfo index
@@ -260,7 +260,7 @@ interface ISub {
int[] getActiveSubIdList(boolean visibleOnly);
- int setSubscriptionProperty(int subId, String propKey, String propValue);
+ void setSubscriptionProperty(int subId, String propKey, String propValue);
String getSubscriptionProperty(int subId, String propKey, String callingPackage,
String callingFeatureId);
@@ -353,13 +353,6 @@ interface ISub {
*/
List<SubscriptionInfo> getSubscriptionInfoListAssociatedWithUser(in UserHandle userHandle);
- /**
- * @return {@code true} if using SubscriptionManagerService instead of
- * SubscriptionController.
- */
- //TODO: Removed before U AOSP public release.
- boolean isSubscriptionManagerServiceEnabled();
-
/**
* Called during setup wizard restore flow to attempt to restore the backed up sim-specific
* configs to device for all existing SIMs in the subscription database
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index ee9d6c1a2448..282b64d3f43e 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2991,6 +2991,15 @@ interface ITelephony {
boolean setSatelliteServicePackageName(in String servicePackageName);
/**
+ * This API can be used by only CTS to update satellite gateway service package name.
+ *
+ * @param servicePackageName The package name of the satellite gateway service.
+ * @return {@code true} if the satellite gateway service is set successfully,
+ * {@code false} otherwise.
+ */
+ boolean setSatelliteGatewayServicePackageName(in String servicePackageName);
+
+ /**
* This API can be used by only CTS to update the timeout duration in milliseconds that
* satellite should stay at listening mode to wait for the next incoming page before disabling
* listening mode.
diff --git a/tests/SharedLibraryLoadingTest/AndroidTest.xml b/tests/SharedLibraryLoadingTest/AndroidTest.xml
index 947453d07bd9..ad0584724fdc 100644
--- a/tests/SharedLibraryLoadingTest/AndroidTest.xml
+++ b/tests/SharedLibraryLoadingTest/AndroidTest.xml
@@ -22,7 +22,6 @@
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="cleanup" value="false" />
<option name="remount-system" value="true" />
<option name="push"
value="SharedLibraryLoadingTests_StandardSharedLibrary.apk->/product/app/SharedLibraryLoadingTests_StandardSharedLibrary.apk" />
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
index 166fbddc2f56..c6e675ade262 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
@@ -84,6 +84,12 @@ public final class NetworkProviderInfo implements Parcelable {
public @interface DeviceType {
}
+ /**
+ * Key in extras bundle indicating that the device battery is charging.
+ * @hide
+ */
+ public static final String EXTRA_KEY_IS_BATTERY_CHARGING = "is_battery_charging";
+
@DeviceType
private final int mDeviceType;
private final String mDeviceName;