summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java3
-rw-r--r--core/java/android/app/Activity.java5
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java15
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl1
-rw-r--r--core/java/android/content/pm/PackageParser.java18
-rw-r--r--core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java33
-rw-r--r--core/java/android/hardware/camera2/CameraCharacteristics.java75
-rw-r--r--core/java/android/hardware/camera2/CameraExtensionCharacteristics.java4
-rw-r--r--core/java/android/hardware/display/DisplayManager.java13
-rw-r--r--core/java/android/hardware/display/DisplayManagerGlobal.java13
-rw-r--r--core/java/android/hardware/display/IDisplayManager.aidl2
-rw-r--r--core/java/android/os/BaseBundle.java26
-rw-r--r--core/java/android/os/Bundle.java2
-rw-r--r--core/java/android/view/SurfaceView.java38
-rw-r--r--core/java/android/view/ViewRootImpl.java26
-rw-r--r--core/java/android/window/SurfaceSyncer.java111
-rw-r--r--core/java/android/window/TaskFragmentInfo.java48
-rw-r--r--core/java/com/android/internal/app/PlatLogoActivity.java70
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java6
-rw-r--r--core/java/com/android/server/SystemConfig.java28
-rw-r--r--core/res/AndroidManifest.xml2
-rw-r--r--core/res/res/drawable-nodpi/platlogo.xml28
-rw-r--r--core/res/res/values-eu/strings.xml2
-rw-r--r--core/res/res/values-fa/strings.xml6
-rw-r--r--core/res/res/values-ky/strings.xml2
-rw-r--r--core/res/res/values-mk/strings.xml2
-rw-r--r--core/res/res/values-th/strings.xml2
-rw-r--r--core/res/res/values/config.xml3
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--graphics/java/android/graphics/Point.java12
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java9
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java40
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java214
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java31
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/AndroidManifest.xml5
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java117
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java7
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/MinimumDimensionActivity.java25
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java170
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java133
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java6
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java4
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java22
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java3
-rw-r--r--media/java/android/media/MediaCodec.java10
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java2
-rw-r--r--packages/CompanionDeviceManager/res/values-fa/strings.xml2
-rw-r--r--packages/CompanionDeviceManager/res/values-hi/strings.xml2
-rw-r--r--packages/CompanionDeviceManager/res/values-ky/strings.xml2
-rw-r--r--packages/PackageInstaller/res/values-it/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-fa/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-pt-rBR/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-pt/strings.xml2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java17
-rw-r--r--packages/SystemUI/TEST_MAPPING19
-rw-r--r--packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt2
-rw-r--r--packages/SystemUI/res/values-af/strings.xml12
-rw-r--r--packages/SystemUI/res/values-am/strings.xml14
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml12
-rw-r--r--packages/SystemUI/res/values-as/strings.xml12
-rw-r--r--packages/SystemUI/res/values-az/strings.xml12
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml12
-rw-r--r--packages/SystemUI/res/values-be/strings.xml12
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml12
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml14
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml12
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml12
-rw-r--r--packages/SystemUI/res/values-da/strings.xml24
-rw-r--r--packages/SystemUI/res/values-de/strings.xml12
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml16
-rw-r--r--packages/SystemUI/res/values-es/strings.xml16
-rw-r--r--packages/SystemUI/res/values-es/tiles_states_strings.xml4
-rw-r--r--packages/SystemUI/res/values-et/strings.xml26
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml2
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml34
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml12
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml12
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml12
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml12
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml16
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml16
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml2
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml12
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml12
-rw-r--r--packages/SystemUI/res/values-in/strings.xml12
-rw-r--r--packages/SystemUI/res/values-is/strings.xml12
-rw-r--r--packages/SystemUI/res/values-it/strings.xml12
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml14
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml12
-rw-r--r--packages/SystemUI/res/values-km/strings.xml12
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml14
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml12
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml14
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml16
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml16
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml12
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml14
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml4
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml12
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml12
-rw-r--r--packages/SystemUI/res/values-my/strings.xml14
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml12
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml16
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml12
-rw-r--r--packages/SystemUI/res/values-or/strings.xml12
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml12
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml6
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml12
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml12
-rw-r--r--packages/SystemUI/res/values-si/strings.xml12
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml12
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml16
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml12
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml12
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml12
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml12
-rw-r--r--packages/SystemUI/res/values-te/strings.xml14
-rw-r--r--packages/SystemUI/res/values-th/strings.xml18
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml12
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml12
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml12
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml16
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml12
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml16
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml12
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml16
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml12
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java6
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java9
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaData.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java70
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java73
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SharedCoordinatorLogger.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt84
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsBpViewControllerTest.kt118
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt86
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt119
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt61
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java49
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java24
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java34
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt4
-rw-r--r--packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java42
-rw-r--r--services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java2
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java41
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java26
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java35
-rw-r--r--services/core/java/com/android/server/audio/RotationHelper.java16
-rw-r--r--services/core/java/com/android/server/display/AutomaticBrightnessController.java12
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java32
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java6
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplayMapper.java120
-rw-r--r--services/core/java/com/android/server/display/PersistentDataStore.java2
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java8
-rw-r--r--services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java72
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java22
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartController.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java25
-rw-r--r--services/core/java/com/android/server/wm/TaskFragment.java53
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java72
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java33
-rw-r--r--services/proguard.flags3
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt169
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java34
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java89
-rw-r--r--services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SurfaceSyncerTest.java110
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java216
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java9
215 files changed, 3338 insertions, 1518 deletions
diff --git a/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java b/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
index 517e3ce39d7e..31c92ba5e207 100644
--- a/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
@@ -70,6 +70,9 @@ public class ZipFilePerfTest {
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
ZipFile zf = new ZipFile(mFile);
+ state.pauseTiming();
+ zf.close();
+ state.resumeTiming();
}
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index ae16e01b7788..7141259d7dce 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -8260,6 +8260,11 @@ public class Activity extends ContextThemeWrapper
return mMainThread;
}
+ /** @hide */
+ public final ActivityInfo getActivityInfo() {
+ return mActivityInfo;
+ }
+
final void performCreate(Bundle icicle) {
performCreate(icicle, null);
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index b7f113609188..0e1a5461840e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -9263,6 +9263,21 @@ public class DevicePolicyManager {
}
/**
+ * Checks if the specified component is the supervision component.
+ * @hide
+ */
+ public boolean isSupervisionComponent(@NonNull ComponentName who) {
+ if (mService != null) {
+ try {
+ return getService().isSupervisionComponent(who);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+ return false;
+ }
+
+ /**
* @hide
* @return the human readable name of the organisation associated with this DPM or {@code null}
* if one is not set.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 6c6a7ca70837..fea77703191e 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -178,6 +178,7 @@ interface IDevicePolicyManager {
boolean setProfileOwner(in ComponentName who, String ownerName, int userHandle);
ComponentName getProfileOwnerAsUser(int userHandle);
ComponentName getProfileOwnerOrDeviceOwnerSupervisionComponent(in UserHandle userHandle);
+ boolean isSupervisionComponent(in ComponentName who);
String getProfileOwnerName(int userHandle);
void setProfileEnabled(in ComponentName who);
void setProfileName(in ComponentName who, String profileName);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 52e64e80e6d4..44dc28d2b0fa 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2618,15 +2618,6 @@ public class PackageParser {
return Build.VERSION_CODES.CUR_DEVELOPMENT;
}
- // STOPSHIP: hack for the pre-release SDK
- if (platformSdkCodenames.length == 0
- && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
- targetCode)) {
- Slog.w(TAG, "Package requires development platform " + targetCode
- + ", returning current version " + Build.VERSION.SDK_INT);
- return Build.VERSION.SDK_INT;
- }
-
// Otherwise, we're looking at an incompatible pre-release SDK.
if (platformSdkCodenames.length > 0) {
outError[0] = "Requires development platform " + targetCode
@@ -2698,15 +2689,6 @@ public class PackageParser {
return Build.VERSION_CODES.CUR_DEVELOPMENT;
}
- // STOPSHIP: hack for the pre-release SDK
- if (platformSdkCodenames.length == 0
- && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
- minCode)) {
- Slog.w(TAG, "Package requires min development platform " + minCode
- + ", returning current version " + Build.VERSION.SDK_INT);
- return Build.VERSION.SDK_INT;
- }
-
// Otherwise, we're looking at an incompatible pre-release SDK.
if (platformSdkCodenames.length > 0) {
outError[0] = "Requires development platform " + minCode
diff --git a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
index 8cc4cdb955ca..3e1c5bb3d7ec 100644
--- a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
@@ -316,15 +316,6 @@ public class FrameworkParsingPackageUtils {
return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
}
- // STOPSHIP: hack for the pre-release SDK
- if (platformSdkCodenames.length == 0
- && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
- minCode)) {
- Slog.w(TAG, "Parsed package requires min development platform " + minCode
- + ", returning current version " + Build.VERSION.SDK_INT);
- return input.success(Build.VERSION.SDK_INT);
- }
-
// Otherwise, we're looking at an incompatible pre-release SDK.
if (platformSdkCodenames.length > 0) {
return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
@@ -377,27 +368,19 @@ public class FrameworkParsingPackageUtils {
return input.success(targetVers);
}
- // If it's a pre-release SDK and the codename matches this platform, it
- // definitely targets this SDK.
- if (matchTargetCode(platformSdkCodenames, targetCode)) {
- return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
- }
-
- // STOPSHIP: hack for the pre-release SDK
- if (platformSdkCodenames.length == 0
- && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
- targetCode)) {
- Slog.w(TAG, "Parsed package requires development platform " + targetCode
- + ", returning current version " + Build.VERSION.SDK_INT);
- return input.success(Build.VERSION.SDK_INT);
- }
-
try {
if (allowUnknownCodenames && UnboundedSdkLevel.isAtMost(targetCode)) {
return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
}
} catch (IllegalArgumentException e) {
- return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, "Bad package SDK");
+ // isAtMost() throws it when encountering an older SDK codename
+ return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, e.getMessage());
+ }
+
+ // If it's a pre-release SDK and the codename matches this platform, it
+ // definitely targets this SDK.
+ if (matchTargetCode(platformSdkCodenames, targetCode)) {
+ return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
}
// Otherwise, we're looking at an incompatible pre-release SDK.
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index a90eb88bc109..98a8cbd8a73c 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -2356,10 +2356,11 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* <p>A subset of the available request keys that can be overridden for
* physical devices backing a logical multi-camera.</p>
* <p>This is a subset of android.request.availableRequestKeys which contains a list
- * of keys that can be overridden using {@link CaptureRequest.Builder#setPhysicalCameraKey }.
+ * of keys that can be overridden using
+ * {@link android.hardware.camera2.CaptureRequest.Builder#setPhysicalCameraKey }.
* The respective value of such request key can be obtained by calling
- * {@link CaptureRequest.Builder#getPhysicalCameraKey }. Capture requests that contain
- * individual physical device requests must be built via
+ * {@link android.hardware.camera2.CaptureRequest.Builder#getPhysicalCameraKey }.
+ * Capture requests that contain individual physical device requests must be built via
* {@link android.hardware.camera2.CameraDevice#createCaptureRequest(int, Set)}.</p>
* <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
* <p><b>Limited capability</b> -
@@ -2759,7 +2760,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* </table>
* <p>For applications targeting SDK version 31 or newer, if the mobile device declares to be
* media performance class 12 or higher by setting
- * {@link android.os.Build.VERSION_CODES.MEDIA_PERFORMANCE_CLASS } to be 31 or larger,
+ * {@link android.os.Build.VERSION#MEDIA_PERFORMANCE_CLASS } to be 31 or larger,
* the primary camera devices (first rear/front camera in the camera ID list) will not
* support JPEG sizes smaller than 1080p. If the application configures a JPEG stream
* smaller than 1080p, the camera device will round up the JPEG image size to at least
@@ -2833,7 +2834,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* </table>
* <p>For applications targeting SDK version 31 or newer, if the mobile device doesn't declare
* to be media performance class 12 or better by setting
- * {@link android.os.Build.VERSION_CODES.MEDIA_PERFORMANCE_CLASS } to be 31 or larger,
+ * {@link android.os.Build.VERSION#MEDIA_PERFORMANCE_CLASS } to be 31 or larger,
* or if the camera device isn't a primary rear/front camera, the minimum required output
* stream configurations are the same as for applications targeting SDK version older than
* 31.</p>
@@ -2958,9 +2959,27 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* can provide.</p>
* <p>Please reference the documentation for the image data destination to
* check if it limits the maximum size for image data.</p>
- * <p>The following table describes the minimum required output stream
- * configurations based on the hardware level
- * ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel}):</p>
+ * <p>For applications targeting SDK version older than 31, the following table
+ * describes the minimum required output stream configurations based on the
+ * hardware level ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel}):
+ * Format | Size | Hardware Level | Notes
+ * :-------------------------------------------------:|:--------------------------------------------:|:--------------:|:--------------:
+ * {@link android.graphics.ImageFormat#JPEG } | {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} (*1) | Any |
+ * {@link android.graphics.ImageFormat#JPEG } | 1920x1080 (1080p) | Any | if 1080p &lt;= activeArraySize
+ * {@link android.graphics.ImageFormat#JPEG } | 1280x720 (720p) | Any | if 720p &lt;= activeArraySize
+ * {@link android.graphics.ImageFormat#JPEG } | 640x480 (480p) | Any | if 480p &lt;= activeArraySize
+ * {@link android.graphics.ImageFormat#JPEG } | 320x240 (240p) | Any | if 240p &lt;= activeArraySize
+ * {@link android.graphics.ImageFormat#YUV_420_888 } | all output sizes available for JPEG | FULL |
+ * {@link android.graphics.ImageFormat#YUV_420_888 } | all output sizes available for JPEG, up to the maximum video size | LIMITED |
+ * {@link android.graphics.ImageFormat#PRIVATE } | same as YUV_420_888 | Any |</p>
+ * <p>For applications targeting SDK version 31 or newer, if the mobile device declares to be
+ * media performance class 12 or higher by setting
+ * {@link android.os.Build.VERSION#MEDIA_PERFORMANCE_CLASS } to be 31 or larger,
+ * the primary camera devices (first rear/front camera in the camera ID list) will not
+ * support JPEG sizes smaller than 1080p. If the application configures a JPEG stream
+ * smaller than 1080p, the camera device will round up the JPEG image size to at least
+ * 1080p. The requirements for IMPLEMENTATION_DEFINED and YUV_420_888 stay the same.
+ * This new minimum required output stream configurations are illustrated by the table below:</p>
* <table>
* <thead>
* <tr>
@@ -2984,32 +3003,38 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* <td align="center">if 1080p &lt;= activeArraySize</td>
* </tr>
* <tr>
- * <td align="center">{@link android.graphics.ImageFormat#JPEG }</td>
- * <td align="center">1280x720 (720p)</td>
- * <td align="center">Any</td>
+ * <td align="center">{@link android.graphics.ImageFormat#YUV_420_888 }</td>
+ * <td align="center">{@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</td>
+ * <td align="center">FULL</td>
+ * <td align="center"></td>
+ * </tr>
+ * <tr>
+ * <td align="center">{@link android.graphics.ImageFormat#YUV_420_888 }</td>
+ * <td align="center">1920x1080 (1080p)</td>
+ * <td align="center">FULL</td>
+ * <td align="center">if 1080p &lt;= activeArraySize</td>
+ * </tr>
+ * <tr>
+ * <td align="center">{@link android.graphics.ImageFormat#YUV_420_888 }</td>
+ * <td align="center">1280x720 (720)</td>
+ * <td align="center">FULL</td>
* <td align="center">if 720p &lt;= activeArraySize</td>
* </tr>
* <tr>
- * <td align="center">{@link android.graphics.ImageFormat#JPEG }</td>
+ * <td align="center">{@link android.graphics.ImageFormat#YUV_420_888 }</td>
* <td align="center">640x480 (480p)</td>
- * <td align="center">Any</td>
+ * <td align="center">FULL</td>
* <td align="center">if 480p &lt;= activeArraySize</td>
* </tr>
* <tr>
- * <td align="center">{@link android.graphics.ImageFormat#JPEG }</td>
- * <td align="center">320x240 (240p)</td>
- * <td align="center">Any</td>
- * <td align="center">if 240p &lt;= activeArraySize</td>
- * </tr>
- * <tr>
* <td align="center">{@link android.graphics.ImageFormat#YUV_420_888 }</td>
- * <td align="center">all output sizes available for JPEG</td>
+ * <td align="center">320x240 (240p)</td>
* <td align="center">FULL</td>
- * <td align="center"></td>
+ * <td align="center">if 240p &lt;= activeArraySize</td>
* </tr>
* <tr>
* <td align="center">{@link android.graphics.ImageFormat#YUV_420_888 }</td>
- * <td align="center">all output sizes available for JPEG, up to the maximum video size</td>
+ * <td align="center">all output sizes available for FULL hardware level, up to the maximum video size</td>
* <td align="center">LIMITED</td>
* <td align="center"></td>
* </tr>
@@ -3021,6 +3046,12 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* </tr>
* </tbody>
* </table>
+ * <p>For applications targeting SDK version 31 or newer, if the mobile device doesn't declare
+ * to be media performance class 12 or better by setting
+ * {@link android.os.Build.VERSION#MEDIA_PERFORMANCE_CLASS } to be 31 or larger,
+ * or if the camera device isn't a primary rear/front camera, the minimum required output
+ * stream configurations are the same as for applications targeting SDK version older than
+ * 31.</p>
* <p>Refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} and {@link android.hardware.camera2.CameraDevice#createCaptureSession } for additional mandatory
* stream configurations on a per-capability basis.</p>
* <p>*1: For JPEG format, the sizes may be restricted by below conditions:</p>
diff --git a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
index cf611fb3adcf..0f6010fffcb6 100644
--- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
@@ -854,7 +854,7 @@ public final class CameraExtensionCharacteristics {
Class<CaptureRequest.Key<?>> crKeyTyped = (Class<CaptureRequest.Key<?>>) crKey;
ret.addAll(requestChars.getAvailableKeyList(CaptureRequest.class, crKeyTyped,
- requestKeys, /*includeSynthetic*/ false));
+ requestKeys, /*includeSynthetic*/ true));
}
// Jpeg quality and orientation must always be supported
@@ -929,7 +929,7 @@ public final class CameraExtensionCharacteristics {
Class<CaptureResult.Key<?>> crKeyTyped = (Class<CaptureResult.Key<?>>)crKey;
ret.addAll(resultChars.getAvailableKeyList(CaptureResult.class, crKeyTyped,
- resultKeys, /*includeSynthetic*/ false));
+ resultKeys, /*includeSynthetic*/ true));
// Jpeg quality, orientation and sensor timestamp must always be supported
if (!ret.contains(CaptureResult.JPEG_QUALITY)) {
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index b505395a091a..69c6ba9a0f43 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -559,18 +559,21 @@ public final class DisplayManager {
* @see #DISPLAY_CATEGORY_PRESENTATION
*/
public Display[] getDisplays(String category) {
- final int[] displayIds = mGlobal.getDisplayIds();
+ boolean includeDisabledDisplays = (category != null
+ && category.equals(DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED));
+ final int[] displayIds = mGlobal.getDisplayIds(includeDisabledDisplays);
synchronized (mLock) {
try {
- if (category == null
- || DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED.equals(category)) {
- addAllDisplaysLocked(mTempDisplays, displayIds);
- } else if (category.equals(DISPLAY_CATEGORY_PRESENTATION)) {
+ if (category != null && category.equals(DISPLAY_CATEGORY_PRESENTATION)) {
addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_WIFI);
addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_EXTERNAL);
addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_OVERLAY);
addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_VIRTUAL);
addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_INTERNAL);
+ } else if ((category == null
+ || DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED.equals(category))) {
+ // All displays requested.
+ addAllDisplaysLocked(mTempDisplays, displayIds);
}
return mTempDisplays.toArray(new Display[mTempDisplays.size()]);
} finally {
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 74356ddecc76..da3a5802ee55 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -206,6 +206,16 @@ public final class DisplayManagerGlobal {
*/
@UnsupportedAppUsage
public int[] getDisplayIds() {
+ return getDisplayIds(/* includeDisabledDisplays= */ false);
+ }
+
+ /**
+ * Gets all valid logical display ids and invalid ones if specified.
+ *
+ * @return An array containing all display ids.
+ */
+ @UnsupportedAppUsage
+ public int[] getDisplayIds(boolean includeDisabledDisplays) {
try {
synchronized (mLock) {
if (USE_CACHE) {
@@ -214,7 +224,8 @@ public final class DisplayManagerGlobal {
}
}
- int[] displayIds = mDm.getDisplayIds();
+ int[] displayIds =
+ mDm.getDisplayIds(includeDisabledDisplays);
if (USE_CACHE) {
mDisplayIdCache = displayIds;
}
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index ca3e58094400..a4115d178f6f 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -36,7 +36,7 @@ import android.view.Surface;
interface IDisplayManager {
@UnsupportedAppUsage
DisplayInfo getDisplayInfo(int displayId);
- int[] getDisplayIds();
+ int[] getDisplayIds(boolean includeDisabled);
boolean isUidPresentOnDisplay(int uid, int displayId);
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index e5dab0539a8e..0418a4bb9f80 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -31,6 +31,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import java.io.Serializable;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Set;
import java.util.function.BiFunction;
@@ -102,7 +103,7 @@ public class BaseBundle {
/*
* If mParcelledData is non-null, then mMap will be null and the
* data are stored as a Parcel containing a Bundle. When the data
- * are unparcelled, mParcelledData willbe set to null.
+ * are unparcelled, mParcelledData will be set to null.
*/
@UnsupportedAppUsage
volatile Parcel mParcelledData = null;
@@ -112,6 +113,19 @@ public class BaseBundle {
*/
private boolean mParcelledByNative;
+ /*
+ * Flag indicating if mParcelledData is only referenced in this bundle.
+ * mParcelledData could be referenced by other bundles if mMap contains lazy values,
+ * and bundle data is copied to another bundle using putAll or the copy constructors.
+ */
+ boolean mOwnsLazyValues = true;
+
+ /*
+ * As mParcelledData is set to null when it is unparcelled, we keep a weak reference to
+ * it to aid in recycling it. Do not use this reference otherwise.
+ */
+ private WeakReference<Parcel> mWeakParcelledData = null;
+
/**
* The ClassLoader used when unparcelling data from mParcelledData.
*/
@@ -200,6 +214,9 @@ public class BaseBundle {
mClassLoader = from.mClassLoader;
if (from.mMap != null) {
+ mOwnsLazyValues = false;
+ from.mOwnsLazyValues = false;
+
if (!deep) {
mMap = new ArrayMap<>(from.mMap);
} else {
@@ -434,6 +451,9 @@ public class BaseBundle {
mMap = map;
if (recycleParcel) {
recycleParcel(parcelledData);
+ mWeakParcelledData = null;
+ } else {
+ mWeakParcelledData = new WeakReference<>(parcelledData);
}
mParcelledByNative = false;
mParcelledData = null;
@@ -575,6 +595,10 @@ public class BaseBundle {
*/
public void clear() {
unparcel();
+ if (mOwnsLazyValues && mWeakParcelledData != null) {
+ recycleParcel(mWeakParcelledData.get());
+ mWeakParcelledData = null;
+ }
mMap.clear();
}
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index cf28c1639fac..7e355d95cdb3 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -301,6 +301,8 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
public void putAll(Bundle bundle) {
unparcel();
bundle.unparcel();
+ mOwnsLazyValues = false;
+ bundle.mOwnsLazyValues = false;
mMap.putAll(bundle.mMap);
// FD state is now known if and only if both bundles already knew
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 7e264cea46bb..536a0ac6403b 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -41,11 +41,13 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.SystemClock;
+import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceControl.Transaction;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.IAccessibilityEmbeddedConnection;
+import android.window.SurfaceSyncer;
import com.android.internal.view.SurfaceCallbackHelper;
@@ -204,6 +206,9 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
private int mSurfaceFlags = SurfaceControl.HIDDEN;
+ private final SurfaceSyncer mSurfaceSyncer = new SurfaceSyncer();
+ private final ArraySet<Integer> mSyncIds = new ArraySet<>();
+
/**
* Transaction that should be used from the render thread. This transaction is only thread safe
* with other calls directly from the render thread.
@@ -1018,7 +1023,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
if (shouldSyncBuffer) {
handleSyncBufferCallback(callbacks, syncBufferTransactionCallback);
} else {
- redrawNeededAsync(callbacks, this::onDrawFinished);
+ handleSyncNoBuffer(callbacks);
}
}
}
@@ -1061,7 +1066,23 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
syncBufferCallback.onBufferReady(t);
onDrawFinished();
}));
+ }
+
+ private void handleSyncNoBuffer(SurfaceHolder.Callback[] callbacks) {
+ final int syncId = mSurfaceSyncer.setupSync(this::onDrawFinished);
+ mSurfaceSyncer.addToSync(syncId, syncBufferCallback -> redrawNeededAsync(callbacks,
+ () -> {
+ syncBufferCallback.onBufferReady(null);
+ synchronized (mSyncIds) {
+ mSyncIds.remove(syncId);
+ }
+ }));
+
+ mSurfaceSyncer.markSyncReady(syncId);
+ synchronized (mSyncIds) {
+ mSyncIds.add(syncId);
+ }
}
private void redrawNeededAsync(SurfaceHolder.Callback[] callbacks,
@@ -1070,6 +1091,21 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
}
+ /**
+ * @hide
+ */
+ @Override
+ public void surfaceSyncStarted() {
+ ViewRootImpl viewRoot = getViewRootImpl();
+ if (viewRoot != null) {
+ synchronized (mSyncIds) {
+ for (int syncId : mSyncIds) {
+ viewRoot.mergeSync(syncId, mSurfaceSyncer);
+ }
+ }
+ }
+ }
+
private static class SyncBufferTransactionCallback {
private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
private Transaction mTransaction;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ad3379f4c46e..97e0692a3f3c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2019,13 +2019,10 @@ public final class ViewRootImpl implements ViewParent,
renderer.setStopped(mStopped);
}
if (!mStopped) {
- // Unnecessary to traverse if the window is not yet visible.
- if (getHostVisibility() == View.VISIBLE) {
- // Make sure that relayoutWindow will be called to get valid surface because
- // the previous surface may have been released.
- mAppVisibilityChanged = true;
- scheduleTraversals();
- }
+ // Make sure that relayoutWindow will be called to get valid surface because
+ // the previous surface may have been released.
+ mAppVisibilityChanged = true;
+ scheduleTraversals();
} else {
if (renderer != null) {
renderer.destroyHardwareResources(mView);
@@ -2048,6 +2045,7 @@ public final class ViewRootImpl implements ViewParent,
void surfaceCreated(Transaction t);
void surfaceReplaced(Transaction t);
void surfaceDestroyed();
+ default void surfaceSyncStarted() {};
}
private final ArrayList<SurfaceChangedCallback> mSurfaceChangedCallbacks = new ArrayList<>();
@@ -2082,6 +2080,12 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ private void notifySurfaceSyncStarted() {
+ for (int i = 0; i < mSurfaceChangedCallbacks.size(); i++) {
+ mSurfaceChangedCallbacks.get(i).surfaceSyncStarted();
+ }
+ }
+
/**
* @return child layer with the same bounds as its parent {@code mSurface} and cropped to the
* surface insets. If the layer does not exist, it is created.
@@ -3541,6 +3545,7 @@ public final class ViewRootImpl implements ViewParent,
Log.d(mTag, "Setup new sync id=" + mSyncId);
}
mSurfaceSyncer.addToSync(mSyncId, mSyncTarget);
+ notifySurfaceSyncStarted();
}
private void notifyContentCatpureEvents() {
@@ -10965,4 +10970,11 @@ public final class ViewRootImpl implements ViewParent,
scheduleTraversals();
}
}
+
+ void mergeSync(int syncId, SurfaceSyncer otherSyncer) {
+ if (!isInLocalSync()) {
+ return;
+ }
+ mSurfaceSyncer.merge(mSyncId, syncId, otherSyncer);
+ }
}
diff --git a/core/java/android/window/SurfaceSyncer.java b/core/java/android/window/SurfaceSyncer.java
index 0e011bb0d0b3..e6eb07162a3b 100644
--- a/core/java/android/window/SurfaceSyncer.java
+++ b/core/java/android/window/SurfaceSyncer.java
@@ -117,13 +117,18 @@ public class SurfaceSyncer {
*/
public int setupSync(@NonNull Consumer<Transaction> syncRequestComplete) {
synchronized (mSyncSetLock) {
- mIdCounter++;
+ final int syncId = mIdCounter++;
if (DEBUG) {
- Log.d(TAG, "setupSync " + mIdCounter);
+ Log.d(TAG, "setupSync " + syncId);
}
- SyncSet syncSet = new SyncSet(mIdCounter, syncRequestComplete);
- mSyncSets.put(mIdCounter, syncSet);
- return mIdCounter;
+ SyncSet syncSet = new SyncSet(syncId, transaction -> {
+ synchronized (mSyncSetLock) {
+ mSyncSets.remove(syncId);
+ }
+ syncRequestComplete.accept(transaction);
+ });
+ mSyncSets.put(syncId, syncSet);
+ return syncId;
}
}
@@ -138,7 +143,6 @@ public class SurfaceSyncer {
SyncSet syncSet;
synchronized (mSyncSetLock) {
syncSet = mSyncSets.get(syncId);
- mSyncSets.remove(syncId);
}
if (syncSet == null) {
Log.e(TAG, "Failed to find syncSet for syncId=" + syncId);
@@ -148,6 +152,31 @@ public class SurfaceSyncer {
}
/**
+ * Merge another SyncSet into the specified syncId.
+ * @param syncId The current syncId to merge into
+ * @param otherSyncId The other syncId to be merged
+ * @param otherSurfaceSyncer The other SurfaceSyncer where the otherSyncId is from
+ */
+ public void merge(int syncId, int otherSyncId, SurfaceSyncer otherSurfaceSyncer) {
+ SyncSet syncSet;
+ synchronized (mSyncSetLock) {
+ syncSet = mSyncSets.get(syncId);
+ }
+
+ SyncSet otherSyncSet = otherSurfaceSyncer.getAndValidateSyncSet(otherSyncId);
+ if (otherSyncSet == null) {
+ return;
+ }
+
+ if (DEBUG) {
+ Log.d(TAG,
+ "merge id=" + otherSyncId + " from=" + otherSurfaceSyncer + " into id=" + syncId
+ + " from" + this);
+ }
+ syncSet.merge(otherSyncSet);
+ }
+
+ /**
* Add a SurfaceView to a sync set. This is different than {@link #addToSync(int, View)} because
* it requires the caller to notify the start and finish drawing in order to sync.
*
@@ -199,8 +228,7 @@ public class SurfaceSyncer {
if (DEBUG) {
Log.d(TAG, "addToSync id=" + syncId);
}
- syncSet.addSyncableSurface(syncTarget);
- return true;
+ return syncSet.addSyncableSurface(syncTarget);
}
/**
@@ -284,14 +312,21 @@ public class SurfaceSyncer {
private final Set<SyncTarget> mSyncTargets = new ArraySet<>();
private final int mSyncId;
- private final Consumer<Transaction> mSyncRequestCompleteCallback;
+ @GuardedBy("mLock")
+ private Consumer<Transaction> mSyncRequestCompleteCallback;
+
+ @GuardedBy("mLock")
+ private final Set<SyncSet> mMergedSyncSets = new ArraySet<>();
+
+ @GuardedBy("mLock")
+ private boolean mFinished;
private SyncSet(int syncId, Consumer<Transaction> syncRequestComplete) {
mSyncId = syncId;
mSyncRequestCompleteCallback = syncRequestComplete;
}
- void addSyncableSurface(SyncTarget syncTarget) {
+ boolean addSyncableSurface(SyncTarget syncTarget) {
SyncBufferCallback syncBufferCallback = new SyncBufferCallback() {
@Override
public void onBufferReady(Transaction t) {
@@ -306,10 +341,16 @@ public class SurfaceSyncer {
};
synchronized (mLock) {
+ if (mSyncReady) {
+ Log.e(TAG, "Sync " + mSyncId + " was already marked as ready. No more "
+ + "SyncTargets can be added.");
+ return false;
+ }
mPendingSyncs.add(syncBufferCallback.hashCode());
mSyncTargets.add(syncTarget);
}
syncTarget.onReadyToSync(syncBufferCallback);
+ return true;
}
void markSyncReady() {
@@ -321,10 +362,11 @@ public class SurfaceSyncer {
@GuardedBy("mLock")
private void checkIfSyncIsComplete() {
- if (!mSyncReady || !mPendingSyncs.isEmpty()) {
+ if (!mSyncReady || !mPendingSyncs.isEmpty() || !mMergedSyncSets.isEmpty()) {
if (DEBUG) {
Log.d(TAG, "Syncable is not complete. mSyncReady=" + mSyncReady
- + " mPendingSyncs=" + mPendingSyncs.size());
+ + " mPendingSyncs=" + mPendingSyncs.size() + " mergedSyncs="
+ + mMergedSyncSets.size());
}
return;
}
@@ -338,6 +380,7 @@ public class SurfaceSyncer {
}
mSyncTargets.clear();
mSyncRequestCompleteCallback.accept(mTransaction);
+ mFinished = true;
}
/**
@@ -349,6 +392,50 @@ public class SurfaceSyncer {
mTransaction.merge(t);
}
}
+
+ public void updateCallback(Consumer<Transaction> transactionConsumer) {
+ synchronized (mLock) {
+ if (mFinished) {
+ Log.e(TAG, "Attempting to merge SyncSet " + mSyncId + " when sync is"
+ + " already complete");
+ transactionConsumer.accept(new Transaction());
+ }
+
+ final Consumer<Transaction> oldCallback = mSyncRequestCompleteCallback;
+ mSyncRequestCompleteCallback = transaction -> {
+ oldCallback.accept(new Transaction());
+ transactionConsumer.accept(transaction);
+ };
+ }
+ }
+
+ /**
+ * Merge a SyncSet into this SyncSet. Since SyncSets could still have pending SyncTargets,
+ * we need to make sure those can still complete before the mergeTo syncSet is considered
+ * complete.
+ *
+ * We keep track of all the merged SyncSets until they are marked as done, and then they
+ * are removed from the set. This SyncSet is not considered done until all the merged
+ * SyncSets are done.
+ *
+ * When the merged SyncSet is complete, it will invoke the original syncRequestComplete
+ * callback but send an empty transaction to ensure the changes are applied early. This
+ * is needed in case the original sync is relying on the callback to continue processing.
+ *
+ * @param otherSyncSet The other SyncSet to merge into this one.
+ */
+ public void merge(SyncSet otherSyncSet) {
+ synchronized (mLock) {
+ mMergedSyncSets.add(otherSyncSet);
+ }
+ otherSyncSet.updateCallback(transaction -> {
+ synchronized (mLock) {
+ mMergedSyncSets.remove(otherSyncSet);
+ mTransaction.merge(transaction);
+ checkIfSyncIsComplete();
+ }
+ });
+ }
}
/**
diff --git a/core/java/android/window/TaskFragmentInfo.java b/core/java/android/window/TaskFragmentInfo.java
index f72164e1f53f..56e910769cb5 100644
--- a/core/java/android/window/TaskFragmentInfo.java
+++ b/core/java/android/window/TaskFragmentInfo.java
@@ -23,8 +23,10 @@ import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Point;
+import android.graphics.Rect;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -66,7 +68,7 @@ public final class TaskFragmentInfo implements Parcelable {
private final List<IBinder> mActivities = new ArrayList<>();
/** Relative position of the fragment's top left corner in the parent container. */
- private final Point mPositionInParent;
+ private final Point mPositionInParent = new Point();
/**
* Whether the last running activity in the TaskFragment was finished due to clearing task while
@@ -80,21 +82,31 @@ public final class TaskFragmentInfo implements Parcelable {
*/
private final boolean mIsTaskFragmentClearedForPip;
+ /**
+ * The maximum {@link ActivityInfo.WindowLayout#minWidth} and
+ * {@link ActivityInfo.WindowLayout#minHeight} aggregated from the TaskFragment's child
+ * activities.
+ */
+ @NonNull
+ private final Point mMinimumDimensions = new Point();
+
/** @hide */
public TaskFragmentInfo(
@NonNull IBinder fragmentToken, @NonNull WindowContainerToken token,
@NonNull Configuration configuration, int runningActivityCount,
boolean isVisible, @NonNull List<IBinder> activities, @NonNull Point positionInParent,
- boolean isTaskClearedForReuse, boolean isTaskFragmentClearedForPip) {
+ boolean isTaskClearedForReuse, boolean isTaskFragmentClearedForPip,
+ @NonNull Point minimumDimensions) {
mFragmentToken = requireNonNull(fragmentToken);
mToken = requireNonNull(token);
mConfiguration.setTo(configuration);
mRunningActivityCount = runningActivityCount;
mIsVisible = isVisible;
mActivities.addAll(activities);
- mPositionInParent = requireNonNull(positionInParent);
+ mPositionInParent.set(positionInParent);
mIsTaskClearedForReuse = isTaskClearedForReuse;
mIsTaskFragmentClearedForPip = isTaskFragmentClearedForPip;
+ mMinimumDimensions.set(minimumDimensions);
}
@NonNull
@@ -154,6 +166,26 @@ public final class TaskFragmentInfo implements Parcelable {
}
/**
+ * Returns the minimum width this TaskFragment can be resized to.
+ * Client side must not {@link WindowContainerTransaction#setBounds(WindowContainerToken, Rect)}
+ * that {@link Rect#width()} is shorter than the reported value.
+ * @hide pending unhide
+ */
+ public int getMinimumWidth() {
+ return mMinimumDimensions.x;
+ }
+
+ /**
+ * Returns the minimum width this TaskFragment can be resized to.
+ * Client side must not {@link WindowContainerTransaction#setBounds(WindowContainerToken, Rect)}
+ * that {@link Rect#height()} is shorter than the reported value.
+ * @hide pending unhide
+ */
+ public int getMinimumHeight() {
+ return mMinimumDimensions.y;
+ }
+
+ /**
* Returns {@code true} if the parameters that are important for task fragment organizers are
* equal between this {@link TaskFragmentInfo} and {@param that}.
*/
@@ -170,7 +202,8 @@ public final class TaskFragmentInfo implements Parcelable {
&& mActivities.equals(that.mActivities)
&& mPositionInParent.equals(that.mPositionInParent)
&& mIsTaskClearedForReuse == that.mIsTaskClearedForReuse
- && mIsTaskFragmentClearedForPip == that.mIsTaskFragmentClearedForPip;
+ && mIsTaskFragmentClearedForPip == that.mIsTaskFragmentClearedForPip
+ && mMinimumDimensions.equals(that.mMinimumDimensions);
}
private TaskFragmentInfo(Parcel in) {
@@ -180,9 +213,10 @@ public final class TaskFragmentInfo implements Parcelable {
mRunningActivityCount = in.readInt();
mIsVisible = in.readBoolean();
in.readBinderList(mActivities);
- mPositionInParent = requireNonNull(in.readTypedObject(Point.CREATOR));
+ mPositionInParent.readFromParcel(in);
mIsTaskClearedForReuse = in.readBoolean();
mIsTaskFragmentClearedForPip = in.readBoolean();
+ mMinimumDimensions.readFromParcel(in);
}
/** @hide */
@@ -194,9 +228,10 @@ public final class TaskFragmentInfo implements Parcelable {
dest.writeInt(mRunningActivityCount);
dest.writeBoolean(mIsVisible);
dest.writeBinderList(mActivities);
- dest.writeTypedObject(mPositionInParent, flags);
+ mPositionInParent.writeToParcel(dest, flags);
dest.writeBoolean(mIsTaskClearedForReuse);
dest.writeBoolean(mIsTaskFragmentClearedForPip);
+ mMinimumDimensions.writeToParcel(dest, flags);
}
@NonNull
@@ -224,6 +259,7 @@ public final class TaskFragmentInfo implements Parcelable {
+ " positionInParent=" + mPositionInParent
+ " isTaskClearedForReuse=" + mIsTaskClearedForReuse
+ " isTaskFragmentClearedForPip" + mIsTaskFragmentClearedForPip
+ + " minimumDimensions" + mMinimumDimensions
+ "}";
}
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index b7f6a615a452..bf265689c0e0 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -103,6 +103,7 @@ public class PlatLogoActivity extends Activity {
mBg.padding = 0.5f * dp;
mBg.minR = 1 * dp;
layout.setBackground(mBg);
+ layout.setOnLongClickListener(mBg);
setContentView(layout);
}
@@ -291,8 +292,8 @@ public class PlatLogoActivity extends Activity {
return true;
case MotionEvent.ACTION_UP:
- if (mOverrideMinute == 0 && (mOverrideHour % 12) == 0) {
- Log.v(TAG, "12:00 let's gooooo");
+ if (mOverrideMinute == 0 && (mOverrideHour % 12) == 1) {
+ Log.v(TAG, "13:00");
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
launchNextStage(false);
}
@@ -302,18 +303,45 @@ public class PlatLogoActivity extends Activity {
}
}
+ private static final String[][] EMOJI_SETS = {
+ {"🍇", "🍈", "🍉", "🍊", "🍋", "🍌", "🍍", "🥭", "🍎", "🍏", "🍐", "🍑",
+ "🍒", "🍓", "🫐", "🥝"},
+ {"😺", "😸", "😹", "😻", "😼", "😽", "🙀", "😿", "😾"},
+ {"😀", "😃", "😄", "😁", "😆", "😅", "🤣", "😂", "🙂", "🙃", "🫠", "😉", "😊",
+ "😇", "🥰", "😍", "🤩", "😘", "😗", "☺️", "😚", "😙", "🥲", "😋", "😛", "😜",
+ "🤪", "😝", "🤑", "🤗", "🤭", "🫢", "🫣", "🤫", "🤔", "🫡", "🤐", "🤨", "😐",
+ "😑", "😶", "🫥", "😏", "😒", "🙄", "😬", "🤥", "😌", "😔", "😪", "🤤", "😴",
+ "😷"},
+ { "🤩", "😍", "🥰", "😘", "🥳", "🥲", "🥹" },
+ { "🫠" },
+ {"💘", "💝", "💖", "💗", "💓", "💞", "💕", "❣", "💔", "❤", "🧡", "💛",
+ "💚", "💙", "💜", "🤎", "🖤", "🤍"},
+ // {"👁", "️🫦", "👁️"}, // this one is too much
+ {"👽", "🛸", "✨", "🌟", "💫", "🚀", "🪐", "🌙", "⭐", "🌍"},
+ {"🌑", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘"},
+ {"🐙", "🪸", "🦑", "🦀", "🦐", "🐡", "🦞", "🐠", "🐟", "🐳", "🐋", "🐬", "🫧", "🌊",
+ "🦈"},
+ {"🙈", "🙉", "🙊", "🐵", "🐒"},
+ {"♈", "♉", "♊", "♋", "♌", "♍", "♎", "♏", "♐", "♑", "♒", "♓"},
+ {"🕛", "🕧", "🕐", "🕜", "🕑", "🕝", "🕒", "🕞", "🕓", "🕟", "🕔", "🕠", "🕕", "🕡",
+ "🕖", "🕢", "🕗", "🕣", "🕘", "🕤", "🕙", "🕥", "🕚", "🕦"},
+ {"🌺", "🌸", "💮", "🏵️", "🌼", "🌿"},
+ {"🐢", "✨", "🌟", "👑"}
+ };
+
static class Bubble {
public float x, y, r;
public int color;
+ public String text = null;
}
- class BubblesDrawable extends Drawable {
+ class BubblesDrawable extends Drawable implements View.OnLongClickListener {
private static final int MAX_BUBBS = 2000;
private final int[] mColorIds = {
- android.R.color.system_accent1_400,
- android.R.color.system_accent1_500,
- android.R.color.system_accent1_600,
+ android.R.color.system_accent3_400,
+ android.R.color.system_accent3_500,
+ android.R.color.system_accent3_600,
android.R.color.system_accent2_400,
android.R.color.system_accent2_500,
@@ -322,6 +350,8 @@ public class PlatLogoActivity extends Activity {
private int[] mColors = new int[mColorIds.length];
+ private int mEmojiSet = -1;
+
private final Bubble[] mBubbs = new Bubble[MAX_BUBBS];
private int mNumBubbs;
@@ -342,17 +372,34 @@ public class PlatLogoActivity extends Activity {
@Override
public void draw(Canvas canvas) {
+ if (getLevel() == 0) return;
final float f = getLevel() / 10000f;
mPaint.setStyle(Paint.Style.FILL);
+ mPaint.setTextAlign(Paint.Align.CENTER);
int drawn = 0;
for (int j = 0; j < mNumBubbs; j++) {
if (mBubbs[j].color == 0 || mBubbs[j].r == 0) continue;
- mPaint.setColor(mBubbs[j].color);
- canvas.drawCircle(mBubbs[j].x, mBubbs[j].y, mBubbs[j].r * f, mPaint);
+ if (mBubbs[j].text != null) {
+ mPaint.setTextSize(mBubbs[j].r * 1.75f);
+ canvas.drawText(mBubbs[j].text, mBubbs[j].x,
+ mBubbs[j].y + mBubbs[j].r * f * 0.6f, mPaint);
+ } else {
+ mPaint.setColor(mBubbs[j].color);
+ canvas.drawCircle(mBubbs[j].x, mBubbs[j].y, mBubbs[j].r * f, mPaint);
+ }
drawn++;
}
}
+ public void chooseEmojiSet() {
+ mEmojiSet = (int) (Math.random() * EMOJI_SETS.length);
+ final String[] emojiSet = EMOJI_SETS[mEmojiSet];
+ for (int j = 0; j < mBubbs.length; j++) {
+ mBubbs[j].text = emojiSet[(int) (Math.random() * emojiSet.length)];
+ }
+ invalidateSelf();
+ }
+
@Override
protected boolean onLevelChange(int level) {
invalidateSelf();
@@ -423,6 +470,13 @@ public class PlatLogoActivity extends Activity {
public int getOpacity() {
return TRANSLUCENT;
}
+
+ @Override
+ public boolean onLongClick(View v) {
+ if (getLevel() == 0) return false;
+ chooseEmojiSet();
+ return true;
+ }
}
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 36a3c5c84ed2..40429c609150 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1501,7 +1501,10 @@ public class ResolverActivity extends Activity implements
: R.string.miniresolver_use_personal_browser);
findViewById(R.id.use_same_profile_browser).setOnClickListener(
- v -> safelyStartActivity(sameProfileResolveInfo));
+ v -> {
+ safelyStartActivity(sameProfileResolveInfo);
+ finish();
+ });
findViewById(R.id.button_open).setOnClickListener(v -> {
Intent intent = otherProfileResolveInfo.getResolvedIntent();
@@ -1510,6 +1513,7 @@ public class ResolverActivity extends Activity implements
}
safelyStartActivityAsUser(otherProfileResolveInfo,
inactiveAdapter.mResolverListController.getUserHandle());
+ finish();
});
}
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 3436b9e75c65..9b583be547c3 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -113,6 +113,24 @@ public class SystemConfig {
final ArrayList<SplitPermissionInfo> mSplitPermissions = new ArrayList<>();
+ private static boolean isAtLeastSdkLevel(String version) {
+ try {
+ return UnboundedSdkLevel.isAtLeast(version);
+ } catch (IllegalArgumentException e) {
+ // UnboundedSdkLevel throws when it sees a known old codename
+ return false;
+ }
+ }
+
+ private static boolean isAtMostSdkLevel(String version) {
+ try {
+ return UnboundedSdkLevel.isAtMost(version);
+ } catch (IllegalArgumentException e) {
+ // UnboundedSdkLevel throws when it sees a known old codename
+ return true;
+ }
+ }
+
public static final class SharedLibraryEntry {
public final String name;
public final String filename;
@@ -180,9 +198,9 @@ public class SystemConfig {
// - onBootclasspathBefore is set and we are before that SDK
canBeSafelyIgnored =
(this.onBootclasspathSince != null
- && UnboundedSdkLevel.isAtLeast(this.onBootclasspathSince))
+ && isAtLeastSdkLevel(this.onBootclasspathSince))
|| (this.onBootclasspathBefore != null
- && !UnboundedSdkLevel.isAtLeast(this.onBootclasspathBefore));
+ && !isAtLeastSdkLevel(this.onBootclasspathBefore));
}
}
@@ -885,11 +903,9 @@ public class SystemConfig {
+ parser.getPositionDescription());
} else {
boolean allowedMinSdk =
- minDeviceSdk == null || UnboundedSdkLevel.isAtLeast(
- minDeviceSdk);
+ minDeviceSdk == null || isAtLeastSdkLevel(minDeviceSdk);
boolean allowedMaxSdk =
- maxDeviceSdk == null || UnboundedSdkLevel.isAtMost(
- maxDeviceSdk);
+ maxDeviceSdk == null || isAtMostSdkLevel(maxDeviceSdk);
final boolean exists = new File(lfile).exists();
if (allowedMinSdk && allowedMaxSdk && exists) {
String bcpSince = parser.getAttributeValue(null,
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e52da0fd6787..7439b2f0921f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -6628,7 +6628,7 @@
android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.PlatLogoActivity"
- android:theme="@style/Theme.DeviceDefault.Wallpaper.NoTitleBar"
+ android:theme="@style/Theme.Wallpaper.NoTitleBar.Fullscreen"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:icon="@drawable/platlogo"
android:process=":ui">
diff --git a/core/res/res/drawable-nodpi/platlogo.xml b/core/res/res/drawable-nodpi/platlogo.xml
index f816d0c41349..da214868ca05 100644
--- a/core/res/res/drawable-nodpi/platlogo.xml
+++ b/core/res/res/drawable-nodpi/platlogo.xml
@@ -19,17 +19,27 @@ Copyright (C) 2021 The Android Open Source Project
android:viewportWidth="24"
xmlns:android="http://schemas.android.com/apk/res/android">
<path
- android:pathData="M11 0.51a2.06 2.06 0 0 1 2 0l0.58 0.37a4.15 4.15 0 0 0 2.23 0.55l0.69-0.06a2.07 2.07 0 0 1 1.81 0.95l0.33 0.6a4.14 4.14 0 0 0 1.72 1.52l0.64 0.27a2 2 0 0 1 1.16 1.68l0 0.69A4.12 4.12 0 0 0 23 9.23l0.44 0.53a2.06 2.06 0 0 1 0.24 2l-0.3 0.62a4.14 4.14 0 0 0-0.27 2.28l0.14 0.68a2.08 2.08 0 0 1-0.72 1.91l-0.56 0.41a4 4 0 0 0-1.3 1.89l-0.19 0.66A2.06 2.06 0 0 1 19 21.58l-0.68 0.11a4.09 4.09 0 0 0-2 1.07l-0.48 0.5a2.08 2.08 0 0 1-2 0.49l-0.65-0.23a4.28 4.28 0 0 0-2.3 0l-0.65 0.23a2.08 2.08 0 0 1-2-0.49l-0.48-0.5a4 4 0 0 0-2-1.07L5 21.58A2.06 2.06 0 0 1 3.5 20.23l-0.19-0.66A4 4 0 0 0 2 17.68l-0.56-0.41a2.08 2.08 0 0 1-0.72-1.91l0.14-0.68A4.14 4.14 0 0 0 0.6 12.4l-0.3-0.62a2.06 2.06 0 0 1 0.24-2L1 9.23A4.16 4.16 0 0 0 1.8 7.08l0-0.69A2 2 0 0 1 3 4.71l0.64-0.27A4.14 4.14 0 0 0 5.34 2.92l0.33-0.6a2.07 2.07 0 0 1 1.81-0.95l0.69 0.06A4.15 4.15 0 0 0 10.4 0.88Z"
- android:fillColor="@android:color/system_accent3_400"
+ android:fillColor="@android:color/system_accent1_400"
+ android:pathData="M11,0.3c0.6,-0.3 1.4,-0.3 2,0l0.6,0.4c0.7,0.4 1.4,0.6 2.2,0.6l0.7,-0.1c0.7,0 1.4,0.3 1.8,0.9l0.3,0.6c0.4,0.7 1,1.2 1.7,1.5L21,4.5c0.7,0.3 1.1,0.9 1.2,1.7v0.7C22.2,7.7 22.5,8.4 23,9l0.4,0.5c0.4,0.6 0.5,1.3 0.2,2l-0.3,0.6c-0.3,0.7 -0.4,1.5 -0.3,2.3l0.1,0.7c0.1,0.7 -0.2,1.4 -0.7,1.9L22,17.5c-0.6,0.5 -1.1,1.1 -1.3,1.9L20.5,20c-0.2,0.7 -0.8,1.2 -1.5,1.4l-0.7,0.1c-0.8,0.2 -1.4,0.5 -2,1.1l-0.5,0.5c-0.5,0.5 -1.3,0.7 -2,0.5l-0.6,-0.2c-0.8,-0.2 -1.5,-0.2 -2.3,0l-0.6,0.2c-0.7,0.2 -1.5,0 -2,-0.5l-0.5,-0.5c-0.5,-0.5 -1.2,-0.9 -2,-1.1L5,21.4c-0.7,-0.2 -1.3,-0.7 -1.5,-1.4l-0.2,-0.7C3.1,18.6 2.6,18 2,17.5l-0.6,-0.4c-0.6,-0.5 -0.8,-1.2 -0.7,-1.9l0.1,-0.7c0.1,-0.8 0,-1.6 -0.3,-2.3l-0.3,-0.6c-0.3,-0.7 -0.2,-1.4 0.2,-2L1,9c0.5,-0.6 0.7,-1.4 0.8,-2.2V6.2C1.9,5.5 2.3,4.8 3,4.5l0.6,-0.3c0.7,-0.3 1.3,-0.9 1.7,-1.5l0.3,-0.6c0.4,-0.6 1.1,-1 1.8,-0.9l0.7,0.1c0.8,0 1.6,-0.2 2.2,-0.6L11,0.3z"
/>
<path
- android:pathData="M12.34 6.53h4.05l-2 4.05a3.95 3.95 0 0 1-0.57 7.85 4.1 4.1 0 0 1-1.45-0.27"
- android:strokeColor="@android:color/system_accent1_800"
- android:strokeWidth="2"/>
+ android:pathData="M6.3,6.5l3,0l0,12.2"
+ android:strokeWidth="2.22"
+ android:strokeColor="@android:color/system_accent3_800"
+ />
+ <path
+ android:pathData="M12.3,6.5h4l-2,4c2.2,0.3 3.6,2.4 3.3,4.5c-0.3,1.9 -1.9,3.3 -3.8,3.3c-0.5,0 -1,-0.1 -1.4,-0.3"
+ android:strokeWidth="2.22"
+ android:strokeColor="@android:color/system_accent3_800"
+ />
<path
- android:pathData="M12.34 6.53h4.05l-2 4.05a3.95 3.95 0 0 1-0.57 7.85 4.1 4.1 0 0 1-1.45-0.27"
+ android:pathData="M6.3,6.5l3,0l0,12.2"
+ android:strokeWidth="0.56"
android:strokeColor="@android:color/system_neutral1_100"
- android:strokeWidth="0.5"/>
-
+ />
+ <path
+ android:pathData="M12.3,6.5h4l-2,4c2.2,0.3 3.6,2.4 3.3,4.5c-0.3,1.9 -1.9,3.3 -3.8,3.3c-0.5,0 -1,-0.1 -1.4,-0.3"
+ android:strokeWidth="0.56"
+ android:strokeColor="@android:color/system_neutral1_100"
+ />
</vector>
-
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 608368b5270e..ee8d9417b4c7 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -307,7 +307,7 @@
<string name="permgroupdesc_sms" msgid="5726462398070064542">"bidali eta ikusi SMS mezuak"</string>
<string name="permgrouplab_storage" msgid="17339216290379241">"Fitxategiak"</string>
<string name="permgroupdesc_storage" msgid="5378659041354582769">"gailuko fitxategiak atzitu"</string>
- <string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"musika eta audioa"</string>
+ <string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"Musika eta audioa"</string>
<string name="permgroupdesc_readMediaAural" msgid="7565467343667089595">"atzitu gailuko musika eta audioak"</string>
<string name="permgrouplab_readMediaVisual" msgid="4724874717811908660">"Argazkiak eta bideoak"</string>
<string name="permgroupdesc_readMediaVisual" msgid="4080463241903508688">"atzitu gailuko argazkiak eta bideoak"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 8cf7e8ad6920..4da0e40d5f07 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_category_name" msgid="5241740395748134483">"سیستم"</string>
<string name="bluetooth_a2dp_audio_route_name" msgid="4214648773120426288">"بلوتوث‌های صوتی"</string>
<string name="wireless_display_route_description" msgid="8297563323032966831">"صفحه نمایش بی‌سیم"</string>
- <string name="media_route_button_content_description" msgid="2299223698196869956">"ارسال محتوا"</string>
+ <string name="media_route_button_content_description" msgid="2299223698196869956">"پخش محتوا"</string>
<string name="media_route_chooser_title" msgid="6646594924991269208">"برقراری ارتباط با دستگاه"</string>
<string name="media_route_chooser_title_for_remote_display" msgid="3105906508794326446">"فرستادن محتوای صفحه به دستگاه"</string>
<string name="media_route_chooser_searching" msgid="6119673534251329535">"درحال جستجوی دستگاه‌ها…"</string>
@@ -2039,7 +2039,7 @@
<string name="harmful_app_warning_title" msgid="8794823880881113856">"برنامه مضر شناسایی شد"</string>
<string name="log_access_confirmation_title" msgid="2343578467290592708">"به <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> اجازه می‌دهید به همه گزارش‌های دستگاه دسترسی داشته باشد؟"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"مجاز کردن دسترسی یک‌باره"</string>
- <string name="log_access_confirmation_deny" msgid="7685790957455099845">"مجاز نیست"</string>
+ <string name="log_access_confirmation_deny" msgid="7685790957455099845">"اجازه ندادن"</string>
<string name="log_access_confirmation_body" msgid="6581985716241928135">"گزارش‌های دستگاه آنچه را در دستگاهتان رخ می‌دهد ثبت می‌کند. برنامه‌ها می‌توانند از این گزارش‌ها برای پیدا کردن مشکلات و رفع آن‌ها استفاده کنند.\n\nبرخی‌از گزارش‌ها ممکن است حاوی اطلاعات حساس باشند، بنابراین فقط به برنامه‌های مورداعتمادتان اجازه دسترسی به همه گزارش‌های دستگاه را بدهید. \n\nاگر به این برنامه اجازه ندهید به همه گزارش‌های دستگاه دسترسی داشته باشد، همچنان می‌تواند به گزارش‌های خودش دسترسی داشته باشد. سازنده دستگاه نیز ممکن است همچنان بتواند به برخی‌از گزارش‌ها یا اطلاعات دستگاهتان دسترسی داشته باشد. بیشتر بدانید"</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"دوباره نشان داده نشود"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> می‌خواهد تکه‌های <xliff:g id="APP_2">%2$s</xliff:g> را نشان دهد"</string>
@@ -2133,7 +2133,7 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"کاری"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"نمای شخصی"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"نمای کاری"</string>
- <string name="resolver_cross_profile_blocked" msgid="3014597376026044840">"سرپرست سیستم آن را مسدود کرده است"</string>
+ <string name="resolver_cross_profile_blocked" msgid="3014597376026044840">"سرپرست فناوری اطلاعات آن را مسدود کرده است"</string>
<string name="resolver_cant_share_with_work_apps_explanation" msgid="9071442683080586643">"نمی‌توان این محتوا را با برنامه‌های کاری هم‌رسانی کرد"</string>
<string name="resolver_cant_access_work_apps_explanation" msgid="1129960195389373279">"نمی‌توان این محتوا را با برنامه‌های کاری باز کرد"</string>
<string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"نمی‌توان این محتوا را با برنامه‌های شخصی هم‌رسانی کرد"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index c818fecfc5e3..3ea684e4a18c 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1684,7 +1684,7 @@
<string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Кызмат экрандагы нерселерди окуп, аларды башка колдонмолордун үстүнөн көрсөтөт."</string>
<string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Аракеттерди көрүп, аткаруу"</string>
<string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Кызмат колдонмодо жасаган аракеттериңизге же түзмөктүн сенсорлоруна көз салып, сиздин атыңыздан буйруктарды берет."</string>
- <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Уруксат берүү"</string>
+ <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Ооба"</string>
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Жок"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Функцияны колдонуп баштоо үчүн аны таптап коюңуз:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Атайын мүмкүнчүлүктөр баскычы менен колдонгуңуз келген функцияларды тандаңыз"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 2c346fde719e..040f50301cf2 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -934,7 +934,7 @@
<string name="lockscreen_transport_stop_description" msgid="1449552232598355348">"Запри"</string>
<string name="lockscreen_transport_rew_description" msgid="7680106856221622779">"Премотај назад"</string>
<string name="lockscreen_transport_ffw_description" msgid="4763794746640196772">"Брзо премотај напред"</string>
- <string name="emergency_calls_only" msgid="3057351206678279851">"Само повици за итни случаи"</string>
+ <string name="emergency_calls_only" msgid="3057351206678279851">"Само итни повици"</string>
<string name="lockscreen_network_locked_message" msgid="2814046965899249635">"Мрежата е заклучена"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="6618356415831082174">"SIM картичката е заклучена со ПУК код."</string>
<string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"Погледнете го Упатството за корисници или контактирајте со Грижа за корисници."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 5d9275ee1879..b0576b856b34 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1709,7 +1709,7 @@
<string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"หากต้องการสลับระหว่างฟีเจอร์ต่างๆ ให้ใช้ 3 นิ้วเลื่อนขึ้นแล้วค้างไว้"</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"การขยาย"</string>
<string name="user_switched" msgid="7249833311585228097">"ผู้ใช้ปัจจุบัน <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="user_switching_message" msgid="1912993630661332336">"กำลังเปลี่ยนเป็น <xliff:g id="NAME">%1$s</xliff:g>…"</string>
+ <string name="user_switching_message" msgid="1912993630661332336">"กำลังเปลี่ยนเป็น<xliff:g id="NAME">%1$s</xliff:g>…"</string>
<string name="user_logging_out_message" msgid="7216437629179710359">"กำลังออกจากระบบ <xliff:g id="NAME">%1$s</xliff:g>…"</string>
<string name="owner_name" msgid="8713560351570795743">"เจ้าของ"</string>
<string name="guest_name" msgid="8502103277839834324">"ผู้ใช้ชั่วคราว"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 54c3490740e5..2fc6da80dea9 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -5658,6 +5658,9 @@
<!-- Determines whether SafetyCenter feature is enabled. -->
<bool name="config_enableSafetyCenter">true</bool>
+ <!-- Config for whether Safety Protection is enabled. -->
+ <bool name="config_safetyProtectionEnabled">false</bool>
+
<!-- Flag indicating if help links for Settings app should be enabled. -->
<bool name="config_settingsHelpLinksEnabled">false</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 96e8de0d2d64..4e7e20ca10b0 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4738,6 +4738,8 @@
<java-symbol type="bool" name="config_enableSafetyCenter" />
+ <java-symbol type="bool" name="config_safetyProtectionEnabled" />
+
<java-symbol type="string" name="config_devicePolicyManagementUpdater" />
<java-symbol type="string" name="config_deviceSpecificDeviceStatePolicyProvider" />
diff --git a/graphics/java/android/graphics/Point.java b/graphics/java/android/graphics/Point.java
index 25f76f6f6da7..2781ac4bf1da 100644
--- a/graphics/java/android/graphics/Point.java
+++ b/graphics/java/android/graphics/Point.java
@@ -36,8 +36,7 @@ public class Point implements Parcelable {
}
public Point(@NonNull Point src) {
- this.x = src.x;
- this.y = src.y;
+ set(src);
}
/**
@@ -49,6 +48,15 @@ public class Point implements Parcelable {
}
/**
+ * Sets the point's from {@code src}'s coordinates
+ * @hide
+ */
+ public void set(@NonNull Point src) {
+ this.x = src.x;
+ this.y = src.y;
+ }
+
+ /**
* Negate the point's coordinates
*/
public final void negate() {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java
index 44af1a9fd780..f09a91018bf0 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java
@@ -18,6 +18,8 @@ package androidx.window.extensions.embedding;
import android.annotation.NonNull;
import android.app.Activity;
+import android.util.Pair;
+import android.util.Size;
/**
* Client-side descriptor of a split that holds two containers.
@@ -66,6 +68,13 @@ class SplitContainer {
return mSplitRule;
}
+ /** Returns the minimum dimension pair of primary container and secondary container. */
+ @NonNull
+ Pair<Size, Size> getMinDimensionsPair() {
+ return new Pair<>(mPrimaryContainer.getMinDimensions(),
+ mSecondaryContainer.getMinDimensions());
+ }
+
boolean isPlaceholderContainer() {
return (mSplitRule instanceof SplitPlaceholderRule);
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 575c3f002791..0ed23cb9ba6d 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -24,9 +24,11 @@ import static androidx.window.extensions.embedding.SplitContainer.getFinishSecon
import static androidx.window.extensions.embedding.SplitContainer.isStickyPlaceholderRule;
import static androidx.window.extensions.embedding.SplitContainer.shouldFinishAssociatedContainerWhenAdjacent;
import static androidx.window.extensions.embedding.SplitContainer.shouldFinishAssociatedContainerWhenStacked;
+import static androidx.window.extensions.embedding.SplitPresenter.boundsSmallerThanMinDimensions;
+import static androidx.window.extensions.embedding.SplitPresenter.getActivityIntentMinDimensionsPair;
+import static androidx.window.extensions.embedding.SplitPresenter.getMinDimensions;
+import static androidx.window.extensions.embedding.SplitPresenter.shouldShowSideBySide;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityClient;
import android.app.ActivityOptions;
@@ -43,11 +45,15 @@ import android.os.IBinder;
import android.os.Looper;
import android.util.ArraySet;
import android.util.Log;
+import android.util.Pair;
+import android.util.Size;
import android.util.SparseArray;
import android.window.TaskFragmentInfo;
import android.window.WindowContainerTransaction;
import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
import com.android.internal.annotations.VisibleForTesting;
@@ -63,7 +69,7 @@ import java.util.function.Consumer;
*/
public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmentCallback,
ActivityEmbeddingComponent {
- private static final String TAG = "SplitController";
+ static final String TAG = "SplitController";
@VisibleForTesting
@GuardedBy("mLock")
@@ -350,7 +356,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
if (!(rule instanceof SplitRule)) {
continue;
}
- if (mPresenter.shouldShowSideBySide(taskContainer.getTaskBounds(), (SplitRule) rule)) {
+ if (shouldShowSideBySide(taskContainer.getTaskBounds(), (SplitRule) rule)) {
return true;
}
}
@@ -614,12 +620,16 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// Can launch in the existing secondary container if the rules share the same
// presentation.
final TaskFragmentContainer secondaryContainer = splitContainer.getSecondaryContainer();
- if (secondaryContainer == getContainerWithActivity(secondaryActivity)) {
+ if (secondaryContainer == getContainerWithActivity(secondaryActivity)
+ && !boundsSmallerThanMinDimensions(secondaryContainer.getLastRequestedBounds(),
+ getMinDimensions(secondaryActivity))) {
// The activity is already in the target TaskFragment.
return true;
}
secondaryContainer.addPendingAppearedActivity(secondaryActivity);
final WindowContainerTransaction wct = new WindowContainerTransaction();
+ mPresenter.expandSplitContainerIfNeeded(wct, splitContainer, primaryActivity,
+ secondaryActivity, null /* secondaryIntent */);
wct.reparentActivityToTaskFragment(
secondaryContainer.getTaskFragmentToken(),
secondaryActivity.getActivityToken());
@@ -791,6 +801,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
&& (canReuseContainer(splitRule, splitContainer.getSplitRule())
// TODO(b/231845476) we should always respect clearTop.
|| !respectClearTop)) {
+ mPresenter.expandSplitContainerIfNeeded(wct, splitContainer, primaryActivity,
+ null /* secondaryActivity */, intent);
// Can launch in the existing secondary container if the rules share the same
// presentation.
return splitContainer.getSecondaryContainer();
@@ -1117,8 +1129,16 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// Check if there is enough space for launch
final SplitPlaceholderRule placeholderRule = getPlaceholderRule(activity);
- if (placeholderRule == null || !mPresenter.shouldShowSideBySide(
- mPresenter.getParentContainerBounds(activity), placeholderRule)) {
+
+ if (placeholderRule == null) {
+ return false;
+ }
+
+ final Pair<Size, Size> minDimensionsPair = getActivityIntentMinDimensionsPair(activity,
+ placeholderRule.getPlaceholderIntent());
+ if (!shouldShowSideBySide(
+ mPresenter.getParentContainerBounds(activity), placeholderRule,
+ minDimensionsPair)) {
return false;
}
@@ -1161,7 +1181,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
return false;
}
- if (mPresenter.shouldShowSideBySide(splitContainer)) {
+ if (shouldShowSideBySide(splitContainer)) {
return false;
}
@@ -1233,7 +1253,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// Splits that are not showing side-by-side are reported as having 0 split
// ratio, since by definition in the API the primary container occupies no
// width of the split when covered by the secondary.
- mPresenter.shouldShowSideBySide(container)
+ shouldShowSideBySide(container)
? container.getSplitRule().getSplitRatio()
: 0.0f);
splitStates.add(splitState);
@@ -1402,7 +1422,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
}
// Decide whether the associated container should be retained based on the current
// presentation mode.
- if (mPresenter.shouldShowSideBySide(splitContainer)) {
+ if (shouldShowSideBySide(splitContainer)) {
return !shouldFinishAssociatedContainerWhenAdjacent(finishBehavior);
} else {
return !shouldFinishAssociatedContainerWhenStacked(finishBehavior);
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index ac3b05a0e825..63be98ebe175 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -16,15 +16,23 @@
package androidx.window.extensions.embedding;
+import static android.content.pm.PackageManager.MATCH_ALL;
+
import android.app.Activity;
+import android.app.ActivityThread;
import android.app.WindowConfiguration;
import android.app.WindowConfiguration.WindowingMode;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
import android.util.LayoutDirection;
+import android.util.Pair;
+import android.util.Size;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowMetrics;
@@ -34,6 +42,8 @@ import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.concurrent.Executor;
/**
@@ -41,9 +51,12 @@ import java.util.concurrent.Executor;
* {@link SplitController}.
*/
class SplitPresenter extends JetpackTaskFragmentOrganizer {
- private static final int POSITION_START = 0;
- private static final int POSITION_END = 1;
- private static final int POSITION_FILL = 2;
+ @VisibleForTesting
+ static final int POSITION_START = 0;
+ @VisibleForTesting
+ static final int POSITION_END = 1;
+ @VisibleForTesting
+ static final int POSITION_FILL = 2;
@IntDef(value = {
POSITION_START,
@@ -103,8 +116,10 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
@NonNull WindowContainerTransaction wct, @NonNull Activity primaryActivity,
@NonNull Intent secondaryIntent, @NonNull SplitPairRule rule) {
final Rect parentBounds = getParentContainerBounds(primaryActivity);
+ final Pair<Size, Size> minDimensionsPair = getActivityIntentMinDimensionsPair(
+ primaryActivity, secondaryIntent);
final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule,
- isLtr(primaryActivity, rule));
+ primaryActivity, minDimensionsPair);
final TaskFragmentContainer primaryContainer = prepareContainerForActivity(wct,
primaryActivity, primaryRectBounds, null);
@@ -113,7 +128,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
final TaskFragmentContainer secondaryContainer = mController.newContainer(
secondaryIntent, primaryActivity, taskId);
final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds,
- rule, isLtr(primaryActivity, rule));
+ rule, primaryActivity, minDimensionsPair);
final int windowingMode = mController.getTaskContainer(taskId)
.getWindowingModeForSplitTaskFragment(secondaryRectBounds);
createTaskFragment(wct, secondaryContainer.getTaskFragmentToken(),
@@ -121,7 +136,8 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
windowingMode);
// Set adjacent to each other so that the containers below will be invisible.
- setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule);
+ setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule,
+ minDimensionsPair);
mController.registerSplit(wct, primaryContainer, primaryActivity, secondaryContainer, rule);
@@ -144,13 +160,15 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
final WindowContainerTransaction wct = new WindowContainerTransaction();
final Rect parentBounds = getParentContainerBounds(primaryActivity);
+ final Pair<Size, Size> minDimensionsPair = getActivitiesMinDimensionsPair(primaryActivity,
+ secondaryActivity);
final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule,
- isLtr(primaryActivity, rule));
+ primaryActivity, minDimensionsPair);
final TaskFragmentContainer primaryContainer = prepareContainerForActivity(wct,
primaryActivity, primaryRectBounds, null);
final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds, rule,
- isLtr(primaryActivity, rule));
+ primaryActivity, minDimensionsPair);
final TaskFragmentContainer curSecondaryContainer = mController.getContainerWithActivity(
secondaryActivity);
TaskFragmentContainer containerToAvoid = primaryContainer;
@@ -162,7 +180,8 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
secondaryActivity, secondaryRectBounds, containerToAvoid);
// Set adjacent to each other so that the containers below will be invisible.
- setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule);
+ setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule,
+ minDimensionsPair);
mController.registerSplit(wct, primaryContainer, primaryActivity, secondaryContainer, rule);
@@ -211,10 +230,12 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
void startActivityToSide(@NonNull Activity launchingActivity, @NonNull Intent activityIntent,
@Nullable Bundle activityOptions, @NonNull SplitRule rule, boolean isPlaceholder) {
final Rect parentBounds = getParentContainerBounds(launchingActivity);
+ final Pair<Size, Size> minDimensionsPair = getActivityIntentMinDimensionsPair(
+ launchingActivity, activityIntent);
final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule,
- isLtr(launchingActivity, rule));
+ launchingActivity, minDimensionsPair);
final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds, rule,
- isLtr(launchingActivity, rule));
+ launchingActivity, minDimensionsPair);
TaskFragmentContainer primaryContainer = mController.getContainerWithActivity(
launchingActivity);
@@ -258,11 +279,11 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
if (activity == null) {
return;
}
- final boolean isLtr = isLtr(activity, rule);
+ final Pair<Size, Size> minDimensionsPair = splitContainer.getMinDimensionsPair();
final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule,
- isLtr);
+ activity, minDimensionsPair);
final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds, rule,
- isLtr);
+ activity, minDimensionsPair);
final TaskFragmentContainer secondaryContainer = splitContainer.getSecondaryContainer();
// Whether the placeholder is becoming side-by-side with the primary from fullscreen.
final boolean isPlaceholderBecomingSplit = splitContainer.isPlaceholderContainer()
@@ -273,7 +294,8 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
// are created again.
resizeTaskFragmentIfRegistered(wct, primaryContainer, primaryRectBounds);
resizeTaskFragmentIfRegistered(wct, secondaryContainer, secondaryRectBounds);
- setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule);
+ setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule,
+ minDimensionsPair);
if (isPlaceholderBecomingSplit) {
// When placeholder is shown in split, we should keep the focus on the primary.
wct.requestFocusOnTaskFragment(primaryContainer.getTaskFragmentToken());
@@ -287,11 +309,12 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
private void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
@NonNull TaskFragmentContainer primaryContainer,
- @NonNull TaskFragmentContainer secondaryContainer, @NonNull SplitRule splitRule) {
+ @NonNull TaskFragmentContainer secondaryContainer, @NonNull SplitRule splitRule,
+ @NonNull Pair<Size, Size> minDimensionsPair) {
final Rect parentBounds = getParentContainerBounds(primaryContainer);
// Clear adjacent TaskFragments if the container is shown in fullscreen, or the
// secondaryContainer could not be finished.
- if (!shouldShowSideBySide(parentBounds, splitRule)) {
+ if (!shouldShowSideBySide(parentBounds, splitRule, minDimensionsPair)) {
setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(),
null /* secondary */, null /* splitRule */);
} else {
@@ -373,41 +396,160 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
super.updateWindowingMode(wct, fragmentToken, windowingMode);
}
- boolean shouldShowSideBySide(@NonNull SplitContainer splitContainer) {
+ /**
+ * Expands the split container if the current split bounds are smaller than the Activity or
+ * Intent that is added to the container.
+ */
+ void expandSplitContainerIfNeeded(@NonNull WindowContainerTransaction wct,
+ @NonNull SplitContainer splitContainer, @NonNull Activity primaryActivity,
+ @Nullable Activity secondaryActivity, @Nullable Intent secondaryIntent) {
+ if (secondaryActivity == null && secondaryIntent == null) {
+ throw new IllegalArgumentException("Either secondaryActivity or secondaryIntent must be"
+ + " non-null.");
+ }
+ final Rect taskBounds = getTaskBoundsFromActivity(primaryActivity);
+ final Pair<Size, Size> minDimensionsPair;
+ if (secondaryActivity != null) {
+ minDimensionsPair = getActivitiesMinDimensionsPair(primaryActivity, secondaryActivity);
+ } else {
+ minDimensionsPair = getActivityIntentMinDimensionsPair(primaryActivity,
+ secondaryIntent);
+ }
+ // Expand the splitContainer if minimum dimensions are not satisfied.
+ if (!shouldShowSideBySide(taskBounds, splitContainer.getSplitRule(), minDimensionsPair)) {
+ expandTaskFragment(wct, splitContainer.getPrimaryContainer()
+ .getTaskFragmentToken());
+ expandTaskFragment(wct, splitContainer.getSecondaryContainer()
+ .getTaskFragmentToken());
+ }
+ }
+
+ static boolean shouldShowSideBySide(@NonNull Rect parentBounds, @NonNull SplitRule rule) {
+ return shouldShowSideBySide(parentBounds, rule, null /* minimumDimensionPair */);
+ }
+
+ static boolean shouldShowSideBySide(@NonNull SplitContainer splitContainer) {
final Rect parentBounds = getParentContainerBounds(splitContainer.getPrimaryContainer());
- return shouldShowSideBySide(parentBounds, splitContainer.getSplitRule());
+
+ return shouldShowSideBySide(parentBounds, splitContainer.getSplitRule(),
+ splitContainer.getMinDimensionsPair());
}
- boolean shouldShowSideBySide(@Nullable Rect parentBounds, @NonNull SplitRule rule) {
+ static boolean shouldShowSideBySide(@NonNull Rect parentBounds, @NonNull SplitRule rule,
+ @Nullable Pair<Size, Size> minDimensionsPair) {
// TODO(b/190433398): Supply correct insets.
final WindowMetrics parentMetrics = new WindowMetrics(parentBounds,
new WindowInsets(new Rect()));
- return rule.checkParentMetrics(parentMetrics);
+ // Don't show side by side if bounds is not qualified.
+ if (!rule.checkParentMetrics(parentMetrics)) {
+ return false;
+ }
+ final float splitRatio = rule.getSplitRatio();
+ // We only care the size of the bounds regardless of its position.
+ final Rect primaryBounds = getPrimaryBounds(parentBounds, splitRatio, true /* isLtr */);
+ final Rect secondaryBounds = getSecondaryBounds(parentBounds, splitRatio, true /* isLtr */);
+
+ if (minDimensionsPair == null) {
+ return true;
+ }
+ return !boundsSmallerThanMinDimensions(primaryBounds, minDimensionsPair.first)
+ && !boundsSmallerThanMinDimensions(secondaryBounds, minDimensionsPair.second);
}
@NonNull
- private Rect getBoundsForPosition(@Position int position, @NonNull Rect parentBounds,
- @NonNull SplitRule rule, boolean isLtr) {
- if (!shouldShowSideBySide(parentBounds, rule)) {
- return new Rect();
+ static Pair<Size, Size> getActivitiesMinDimensionsPair(Activity primaryActivity,
+ Activity secondaryActivity) {
+ return new Pair<>(getMinDimensions(primaryActivity), getMinDimensions(secondaryActivity));
+ }
+
+ @NonNull
+ static Pair<Size, Size> getActivityIntentMinDimensionsPair(Activity primaryActivity,
+ Intent secondaryIntent) {
+ return new Pair<>(getMinDimensions(primaryActivity), getMinDimensions(secondaryIntent));
+ }
+
+ @Nullable
+ static Size getMinDimensions(@Nullable Activity activity) {
+ if (activity == null) {
+ return null;
+ }
+ final ActivityInfo.WindowLayout windowLayout = activity.getActivityInfo().windowLayout;
+ if (windowLayout == null) {
+ return null;
+ }
+ return new Size(windowLayout.minWidth, windowLayout.minHeight);
+ }
+
+ // TODO(b/232871351): find a light-weight approach for this check.
+ @Nullable
+ static Size getMinDimensions(@Nullable Intent intent) {
+ if (intent == null) {
+ return null;
+ }
+ final PackageManager packageManager = ActivityThread.currentActivityThread()
+ .getApplication().getPackageManager();
+ final ResolveInfo resolveInfo = packageManager.resolveActivity(intent,
+ PackageManager.ResolveInfoFlags.of(MATCH_ALL));
+ if (resolveInfo == null) {
+ return null;
}
+ final ActivityInfo activityInfo = resolveInfo.activityInfo;
+ if (activityInfo == null) {
+ return null;
+ }
+ final ActivityInfo.WindowLayout windowLayout = activityInfo.windowLayout;
+ if (windowLayout == null) {
+ return null;
+ }
+ return new Size(windowLayout.minWidth, windowLayout.minHeight);
+ }
+
+ static boolean boundsSmallerThanMinDimensions(@NonNull Rect bounds,
+ @Nullable Size minDimensions) {
+ if (minDimensions == null) {
+ return false;
+ }
+ return bounds.width() < minDimensions.getWidth()
+ || bounds.height() < minDimensions.getHeight();
+ }
+ @VisibleForTesting
+ @NonNull
+ static Rect getBoundsForPosition(@Position int position, @NonNull Rect parentBounds,
+ @NonNull SplitRule rule, @NonNull Activity primaryActivity,
+ @Nullable Pair<Size, Size> minDimensionsPair) {
+ if (!shouldShowSideBySide(parentBounds, rule, minDimensionsPair)) {
+ return new Rect();
+ }
+ final boolean isLtr = isLtr(primaryActivity, rule);
final float splitRatio = rule.getSplitRatio();
- final float rtlSplitRatio = 1 - splitRatio;
+
switch (position) {
case POSITION_START:
- return isLtr ? getLeftContainerBounds(parentBounds, splitRatio)
- : getRightContainerBounds(parentBounds, rtlSplitRatio);
+ return getPrimaryBounds(parentBounds, splitRatio, isLtr);
case POSITION_END:
- return isLtr ? getRightContainerBounds(parentBounds, splitRatio)
- : getLeftContainerBounds(parentBounds, rtlSplitRatio);
+ return getSecondaryBounds(parentBounds, splitRatio, isLtr);
case POSITION_FILL:
- return parentBounds;
+ default:
+ return new Rect();
}
- return parentBounds;
}
- private Rect getLeftContainerBounds(@NonNull Rect parentBounds, float splitRatio) {
+ @NonNull
+ private static Rect getPrimaryBounds(@NonNull Rect parentBounds, float splitRatio,
+ boolean isLtr) {
+ return isLtr ? getLeftContainerBounds(parentBounds, splitRatio)
+ : getRightContainerBounds(parentBounds, 1 - splitRatio);
+ }
+
+ @NonNull
+ private static Rect getSecondaryBounds(@NonNull Rect parentBounds, float splitRatio,
+ boolean isLtr) {
+ return isLtr ? getRightContainerBounds(parentBounds, splitRatio)
+ : getLeftContainerBounds(parentBounds, 1 - splitRatio);
+ }
+
+ private static Rect getLeftContainerBounds(@NonNull Rect parentBounds, float splitRatio) {
return new Rect(
parentBounds.left,
parentBounds.top,
@@ -415,7 +557,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
parentBounds.bottom);
}
- private Rect getRightContainerBounds(@NonNull Rect parentBounds, float splitRatio) {
+ private static Rect getRightContainerBounds(@NonNull Rect parentBounds, float splitRatio) {
return new Rect(
(int) (parentBounds.left + parentBounds.width() * splitRatio),
parentBounds.top,
@@ -427,7 +569,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
* Checks if a split with the provided rule should be displays in left-to-right layout
* direction, either always or with the current configuration.
*/
- private boolean isLtr(@NonNull Context context, @NonNull SplitRule rule) {
+ private static boolean isLtr(@NonNull Context context, @NonNull SplitRule rule) {
switch (rule.getLayoutDirection()) {
case LayoutDirection.LOCALE:
return context.getResources().getConfiguration().getLayoutDirection()
@@ -441,7 +583,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
}
@NonNull
- Rect getParentContainerBounds(@NonNull TaskFragmentContainer container) {
+ static Rect getParentContainerBounds(@NonNull TaskFragmentContainer container) {
return container.getTaskContainer().getTaskBounds();
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index 624cde50ff72..abf32a26efa2 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -26,6 +26,7 @@ import android.content.Intent;
import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
+import android.util.Size;
import android.window.TaskFragmentInfo;
import android.window.WindowContainerTransaction;
@@ -414,6 +415,11 @@ class TaskFragmentContainer {
}
}
+ @NonNull
+ Rect getLastRequestedBounds() {
+ return mLastRequestedBounds;
+ }
+
/**
* Checks if last requested windowing mode is equal to the provided value.
*/
@@ -439,6 +445,31 @@ class TaskFragmentContainer {
return mTaskContainer;
}
+ @Nullable
+ Size getMinDimensions() {
+ if (mInfo == null) {
+ return null;
+ }
+ int maxMinWidth = mInfo.getMinimumWidth();
+ int maxMinHeight = mInfo.getMinimumHeight();
+ for (Activity activity : mPendingAppearedActivities) {
+ final Size minDimensions = SplitPresenter.getMinDimensions(activity);
+ if (minDimensions == null) {
+ continue;
+ }
+ maxMinWidth = Math.max(maxMinWidth, minDimensions.getWidth());
+ maxMinHeight = Math.max(maxMinHeight, minDimensions.getHeight());
+ }
+ if (mPendingAppearedIntent != null) {
+ final Size minDimensions = SplitPresenter.getMinDimensions(mPendingAppearedIntent);
+ if (minDimensions != null) {
+ maxMinWidth = Math.max(maxMinWidth, minDimensions.getWidth());
+ maxMinHeight = Math.max(maxMinHeight, minDimensions.getHeight());
+ }
+ }
+ return new Size(maxMinWidth, maxMinHeight);
+ }
+
@Override
public String toString() {
return toString(true /* includeContainersToFinishOnExit */);
diff --git a/libs/WindowManager/Jetpack/tests/unittest/AndroidManifest.xml b/libs/WindowManager/Jetpack/tests/unittest/AndroidManifest.xml
index b12b6f6f0ef1..c736e9ed971e 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/AndroidManifest.xml
+++ b/libs/WindowManager/Jetpack/tests/unittest/AndroidManifest.xml
@@ -22,6 +22,11 @@
<application android:debuggable="true" android:largeHeap="true">
<uses-library android:name="android.test.mock" />
<uses-library android:name="android.test.runner" />
+
+ <activity android:name="androidx.window.extensions.embedding.MinimumDimensionActivity">
+ <layout android:minWidth="600px"
+ android:minHeight="1200px"/>
+ </activity>
</application>
<instrumentation
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
new file mode 100644
index 000000000000..3ef328141907
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.extensions.embedding;
+
+import static androidx.window.extensions.embedding.SplitRule.FINISH_ALWAYS;
+import static androidx.window.extensions.embedding.SplitRule.FINISH_NEVER;
+
+import static org.mockito.Mockito.mock;
+
+import android.annotation.NonNull;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.util.Pair;
+import android.window.TaskFragmentInfo;
+import android.window.WindowContainerToken;
+
+import java.util.Collections;
+
+public class EmbeddingTestUtils {
+ static final Rect TASK_BOUNDS = new Rect(0, 0, 600, 1200);
+ static final int TASK_ID = 10;
+ static final float SPLIT_RATIO = 0.5f;
+ /** Default finish behavior in Jetpack. */
+ static final int DEFAULT_FINISH_PRIMARY_WITH_SECONDARY = FINISH_NEVER;
+ static final int DEFAULT_FINISH_SECONDARY_WITH_PRIMARY = FINISH_ALWAYS;
+
+ private EmbeddingTestUtils() {}
+
+ /** Gets the bounds of a TaskFragment that is in split. */
+ static Rect getSplitBounds(boolean isPrimary) {
+ final int width = (int) (TASK_BOUNDS.width() * SPLIT_RATIO);
+ return isPrimary
+ ? new Rect(TASK_BOUNDS.left, TASK_BOUNDS.top, TASK_BOUNDS.left + width,
+ TASK_BOUNDS.bottom)
+ : new Rect(
+ TASK_BOUNDS.left + width, TASK_BOUNDS.top, TASK_BOUNDS.right,
+ TASK_BOUNDS.bottom);
+ }
+
+ /** Creates a rule to always split the given activity and the given intent. */
+ static SplitRule createSplitRule(@NonNull Activity primaryActivity,
+ @NonNull Intent secondaryIntent) {
+ final Pair<Activity, Intent> targetPair = new Pair<>(primaryActivity, secondaryIntent);
+ return new SplitPairRule.Builder(
+ activityPair -> false,
+ targetPair::equals,
+ w -> true)
+ .setSplitRatio(SPLIT_RATIO)
+ .setShouldClearTop(true)
+ .build();
+ }
+
+ /** Creates a rule to always split the given activities. */
+ static SplitRule createSplitRule(@NonNull Activity primaryActivity,
+ @NonNull Activity secondaryActivity) {
+ return createSplitRule(primaryActivity, secondaryActivity,
+ DEFAULT_FINISH_PRIMARY_WITH_SECONDARY, DEFAULT_FINISH_SECONDARY_WITH_PRIMARY,
+ true /* clearTop */);
+ }
+
+ /** Creates a rule to always split the given activities with the given finish behaviors. */
+ static SplitRule createSplitRule(@NonNull Activity primaryActivity,
+ @NonNull Activity secondaryActivity, int finishPrimaryWithSecondary,
+ int finishSecondaryWithPrimary, boolean clearTop) {
+ final Pair<Activity, Activity> targetPair = new Pair<>(primaryActivity, secondaryActivity);
+ return new SplitPairRule.Builder(
+ targetPair::equals,
+ activityIntentPair -> false,
+ w -> true)
+ .setSplitRatio(SPLIT_RATIO)
+ .setFinishPrimaryWithSecondary(finishPrimaryWithSecondary)
+ .setFinishSecondaryWithPrimary(finishSecondaryWithPrimary)
+ .setShouldClearTop(clearTop)
+ .build();
+ }
+
+ /** Creates a mock TaskFragmentInfo for the given TaskFragment. */
+ static TaskFragmentInfo createMockTaskFragmentInfo(@NonNull TaskFragmentContainer container,
+ @NonNull Activity activity) {
+ return new TaskFragmentInfo(container.getTaskFragmentToken(),
+ mock(WindowContainerToken.class),
+ new Configuration(),
+ 1,
+ true /* isVisible */,
+ Collections.singletonList(activity.getActivityToken()),
+ new Point(),
+ false /* isTaskClearedForReuse */,
+ false /* isTaskFragmentClearedForPip */,
+ new Point());
+ }
+
+ static ActivityInfo createActivityInfoWithMinDimensions() {
+ ActivityInfo aInfo = new ActivityInfo();
+ final Rect primaryBounds = getSplitBounds(true /* isPrimary */);
+ aInfo.windowLayout = new ActivityInfo.WindowLayout(0, 0, 0, 0, 0,
+ primaryBounds.width() + 1, primaryBounds.height() + 1);
+ return aInfo;
+ }
+}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
index a191e685f651..4d2595275f20 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
@@ -18,6 +18,8 @@ package androidx.window.extensions.embedding;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -58,8 +60,6 @@ import java.util.ArrayList;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class JetpackTaskFragmentOrganizerTest {
- private static final int TASK_ID = 10;
-
@Mock
private WindowContainerTransaction mTransaction;
@Mock
@@ -131,6 +131,7 @@ public class JetpackTaskFragmentOrganizerTest {
return new TaskFragmentInfo(container.getTaskFragmentToken(),
mock(WindowContainerToken.class), new Configuration(), 0 /* runningActivityCount */,
false /* isVisible */, new ArrayList<>(), new Point(),
- false /* isTaskClearedForReuse */, false /* isTaskFragmentClearedForPip */);
+ false /* isTaskClearedForReuse */, false /* isTaskFragmentClearedForPip */,
+ new Point());
}
}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/MinimumDimensionActivity.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/MinimumDimensionActivity.java
new file mode 100644
index 000000000000..ffcaf3e6f546
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/MinimumDimensionActivity.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.extensions.embedding;
+
+import android.app.Activity;
+
+/**
+ * Activity that declares minWidth and minHeight in
+ * {@link android.content.pm.ActivityInfo.WindowLayout}
+ */
+public class MinimumDimensionActivity extends Activity {}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
index 60390eb2b3d2..982ab8043bbc 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
@@ -19,8 +19,14 @@ package androidx.window.extensions.embedding;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.SPLIT_RATIO;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_BOUNDS;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.createActivityInfoWithMinDimensions;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.createMockTaskFragmentInfo;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitRule;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.getSplitBounds;
import static androidx.window.extensions.embedding.SplitRule.FINISH_ALWAYS;
-import static androidx.window.extensions.embedding.SplitRule.FINISH_NEVER;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -49,20 +55,19 @@ import android.app.Activity;
import android.app.ActivityOptions;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.graphics.Point;
import android.graphics.Rect;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
-import android.util.Pair;
import android.window.TaskFragmentInfo;
-import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
+import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -86,16 +91,9 @@ import java.util.List;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class SplitControllerTest {
- private static final int TASK_ID = 10;
- private static final Rect TASK_BOUNDS = new Rect(0, 0, 600, 1200);
- private static final float SPLIT_RATIO = 0.5f;
private static final Intent PLACEHOLDER_INTENT = new Intent().setComponent(
new ComponentName("test", "placeholder"));
- /** Default finish behavior in Jetpack. */
- private static final int DEFAULT_FINISH_PRIMARY_WITH_SECONDARY = FINISH_NEVER;
- private static final int DEFAULT_FINISH_SECONDARY_WITH_PRIMARY = FINISH_ALWAYS;
-
private Activity mActivity;
@Mock
private Resources mActivityResources;
@@ -420,6 +418,25 @@ public class SplitControllerTest {
}
@Test
+ public void testResolveStartActivityIntent_shouldLaunchInFullscreen() {
+ final Intent intent = new Intent().setComponent(
+ new ComponentName(ApplicationProvider.getApplicationContext(),
+ MinimumDimensionActivity.class));
+ setupSplitRule(mActivity, intent);
+ final Activity primaryActivity = createMockActivity();
+ addSplitTaskFragments(primaryActivity, mActivity);
+
+ final TaskFragmentContainer container = mSplitController.resolveStartActivityIntent(
+ mTransaction, TASK_ID, intent, null /* launchingActivity */);
+ final TaskFragmentContainer primaryContainer = mSplitController.getContainerWithActivity(
+ mActivity);
+
+ assertNotNull(mSplitController.getActiveSplitForContainers(primaryContainer, container));
+ assertTrue(primaryContainer.areLastRequestedBoundsEqual(null));
+ assertTrue(container.areLastRequestedBoundsEqual(null));
+ }
+
+ @Test
public void testPlaceActivityInTopContainer() {
mSplitController.placeActivityInTopContainer(mActivity);
@@ -767,6 +784,48 @@ public class SplitControllerTest {
}
@Test
+ public void testResolveActivityToContainer_primaryActivityMinDimensionsNotSatisfied() {
+ final Activity activityBelow = createMockActivity();
+ setupSplitRule(mActivity, activityBelow);
+
+ doReturn(createActivityInfoWithMinDimensions()).when(mActivity).getActivityInfo();
+
+ final TaskFragmentContainer container = mSplitController.newContainer(activityBelow,
+ TASK_ID);
+ container.addPendingAppearedActivity(mActivity);
+
+ // Allow to split as primary.
+ boolean result = mSplitController.resolveActivityToContainer(mActivity,
+ true /* isOnReparent */);
+
+ assertTrue(result);
+ assertSplitPair(mActivity, activityBelow, true /* matchParentBounds */);
+ }
+
+ @Test
+ public void testResolveActivityToContainer_secondaryActivityMinDimensionsNotSatisfied() {
+ final Activity activityBelow = createMockActivity();
+ setupSplitRule(activityBelow, mActivity);
+
+ ActivityInfo aInfo = new ActivityInfo();
+ final Rect secondaryBounds = getSplitBounds(false /* isPrimary */);
+ aInfo.windowLayout = new ActivityInfo.WindowLayout(0, 0, 0, 0, 0,
+ secondaryBounds.width() + 1, secondaryBounds.height() + 1);
+ doReturn(aInfo).when(mActivity).getActivityInfo();
+
+ final TaskFragmentContainer container = mSplitController.newContainer(activityBelow,
+ TASK_ID);
+ container.addPendingAppearedActivity(mActivity);
+
+ // Allow to split as primary.
+ boolean result = mSplitController.resolveActivityToContainer(mActivity,
+ false /* isOnReparent */);
+
+ assertTrue(result);
+ assertSplitPair(activityBelow, mActivity, true /* matchParentBounds */);
+ }
+
+ @Test
public void testResolveActivityToContainer_inUnknownTaskFragment() {
doReturn(new Binder()).when(mSplitController).getInitialTaskFragmentToken(mActivity);
@@ -835,23 +894,10 @@ public class SplitControllerTest {
doReturn(activityToken).when(activity).getActivityToken();
doReturn(activity).when(mSplitController).getActivity(activityToken);
doReturn(TASK_ID).when(activity).getTaskId();
+ doReturn(new ActivityInfo()).when(activity).getActivityInfo();
return activity;
}
- /** Creates a mock TaskFragmentInfo for the given TaskFragment. */
- private TaskFragmentInfo createMockTaskFragmentInfo(@NonNull TaskFragmentContainer container,
- @NonNull Activity activity) {
- return new TaskFragmentInfo(container.getTaskFragmentToken(),
- mock(WindowContainerToken.class),
- new Configuration(),
- 1,
- true /* isVisible */,
- Collections.singletonList(activity.getActivityToken()),
- new Point(),
- false /* isTaskClearedForReuse */,
- false /* isTaskFragmentClearedForPip */);
- }
-
/** Creates a mock TaskFragment that has been registered and appeared in the organizer. */
private TaskFragmentContainer createMockTaskFragmentContainer(@NonNull Activity activity) {
final TaskFragmentContainer container = mSplitController.newContainer(activity, TASK_ID);
@@ -902,49 +948,10 @@ public class SplitControllerTest {
/** Setups a rule to always split the given activities. */
private void setupSplitRule(@NonNull Activity primaryActivity,
@NonNull Activity secondaryActivity) {
- final SplitRule splitRule = createSplitRule(primaryActivity, secondaryActivity,
- DEFAULT_FINISH_PRIMARY_WITH_SECONDARY, DEFAULT_FINISH_SECONDARY_WITH_PRIMARY,
- true /* clearTop */);
+ final SplitRule splitRule = createSplitRule(primaryActivity, secondaryActivity);
mSplitController.setEmbeddingRules(Collections.singleton(splitRule));
}
- /** Creates a rule to always split the given activity and the given intent. */
- private SplitRule createSplitRule(@NonNull Activity primaryActivity,
- @NonNull Intent secondaryIntent) {
- final Pair<Activity, Intent> targetPair = new Pair<>(primaryActivity, secondaryIntent);
- return new SplitPairRule.Builder(
- activityPair -> false,
- targetPair::equals,
- w -> true)
- .setSplitRatio(SPLIT_RATIO)
- .setShouldClearTop(true)
- .build();
- }
-
- /** Creates a rule to always split the given activities. */
- private SplitRule createSplitRule(@NonNull Activity primaryActivity,
- @NonNull Activity secondaryActivity) {
- return createSplitRule(primaryActivity, secondaryActivity,
- DEFAULT_FINISH_PRIMARY_WITH_SECONDARY, DEFAULT_FINISH_SECONDARY_WITH_PRIMARY,
- true /* clearTop */);
- }
-
- /** Creates a rule to always split the given activities with the given finish behaviors. */
- private SplitRule createSplitRule(@NonNull Activity primaryActivity,
- @NonNull Activity secondaryActivity, int finishPrimaryWithSecondary,
- int finishSecondaryWithPrimary, boolean clearTop) {
- final Pair<Activity, Activity> targetPair = new Pair<>(primaryActivity, secondaryActivity);
- return new SplitPairRule.Builder(
- targetPair::equals,
- activityIntentPair -> false,
- w -> true)
- .setSplitRatio(SPLIT_RATIO)
- .setFinishPrimaryWithSecondary(finishPrimaryWithSecondary)
- .setFinishSecondaryWithPrimary(finishSecondaryWithPrimary)
- .setShouldClearTop(clearTop)
- .build();
- }
-
/** Adds a pair of TaskFragments as split for the given activities. */
private void addSplitTaskFragments(@NonNull Activity primaryActivity,
@NonNull Activity secondaryActivity) {
@@ -973,39 +980,42 @@ public class SplitControllerTest {
secondaryContainer.setLastRequestedBounds(getSplitBounds(false /* isPrimary */));
}
- /** Gets the bounds of a TaskFragment that is in split. */
- private Rect getSplitBounds(boolean isPrimary) {
- final int width = (int) (TASK_BOUNDS.width() * SPLIT_RATIO);
- return isPrimary
- ? new Rect(TASK_BOUNDS.left, TASK_BOUNDS.top, TASK_BOUNDS.left + width,
- TASK_BOUNDS.bottom)
- : new Rect(TASK_BOUNDS.left + width, TASK_BOUNDS.top, TASK_BOUNDS.right,
- TASK_BOUNDS.bottom);
+ /** Asserts that the two given activities are in split. */
+ private void assertSplitPair(@NonNull Activity primaryActivity,
+ @NonNull Activity secondaryActivity) {
+ assertSplitPair(primaryActivity, secondaryActivity, false /* matchParentBounds */);
}
/** Asserts that the two given activities are in split. */
private void assertSplitPair(@NonNull Activity primaryActivity,
- @NonNull Activity secondaryActivity) {
+ @NonNull Activity secondaryActivity, boolean matchParentBounds) {
assertSplitPair(mSplitController.getContainerWithActivity(primaryActivity),
- mSplitController.getContainerWithActivity(secondaryActivity));
+ mSplitController.getContainerWithActivity(secondaryActivity), matchParentBounds);
}
- /** Asserts that the two given TaskFragments are in split. */
private void assertSplitPair(@NonNull TaskFragmentContainer primaryContainer,
@NonNull TaskFragmentContainer secondaryContainer) {
+ assertSplitPair(primaryContainer, secondaryContainer, false /* matchParentBounds*/);
+ }
+
+ /** Asserts that the two given TaskFragments are in split. */
+ private void assertSplitPair(@NonNull TaskFragmentContainer primaryContainer,
+ @NonNull TaskFragmentContainer secondaryContainer, boolean matchParentBounds) {
assertNotNull(primaryContainer);
assertNotNull(secondaryContainer);
assertNotNull(mSplitController.getActiveSplitForContainers(primaryContainer,
secondaryContainer));
if (primaryContainer.mInfo != null) {
- assertTrue(primaryContainer.areLastRequestedBoundsEqual(
- getSplitBounds(true /* isPrimary */)));
+ final Rect primaryBounds = matchParentBounds ? new Rect()
+ : getSplitBounds(true /* isPrimary */);
+ assertTrue(primaryContainer.areLastRequestedBoundsEqual(primaryBounds));
assertTrue(primaryContainer.isLastRequestedWindowingModeEqual(
WINDOWING_MODE_MULTI_WINDOW));
}
if (secondaryContainer.mInfo != null) {
- assertTrue(secondaryContainer.areLastRequestedBoundsEqual(
- getSplitBounds(false /* isPrimary */)));
+ final Rect secondaryBounds = matchParentBounds ? new Rect()
+ : getSplitBounds(false /* isPrimary */);
+ assertTrue(secondaryContainer.areLastRequestedBoundsEqual(secondaryBounds));
assertTrue(secondaryContainer.isLastRequestedWindowingModeEqual(
WINDOWING_MODE_MULTI_WINDOW));
}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
index 906e9904566f..029503cd70d2 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
@@ -18,25 +18,46 @@ package androidx.window.extensions.embedding;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_BOUNDS;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.createActivityInfoWithMinDimensions;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitRule;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.getSplitBounds;
+import static androidx.window.extensions.embedding.SplitPresenter.POSITION_END;
+import static androidx.window.extensions.embedding.SplitPresenter.POSITION_FILL;
+import static androidx.window.extensions.embedding.SplitPresenter.POSITION_START;
+import static androidx.window.extensions.embedding.SplitPresenter.getBoundsForPosition;
+import static androidx.window.extensions.embedding.SplitPresenter.getMinDimensions;
+import static androidx.window.extensions.embedding.SplitPresenter.shouldShowSideBySide;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
+import android.util.Pair;
+import android.util.Size;
import android.window.TaskFragmentInfo;
import android.window.WindowContainerTransaction;
+import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -56,8 +77,6 @@ import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class SplitPresenterTest {
- private static final int TASK_ID = 10;
- private static final Rect TASK_BOUNDS = new Rect(0, 0, 600, 1200);
@Mock
private Activity mActivity;
@@ -77,11 +96,7 @@ public class SplitPresenterTest {
mPresenter = mController.mPresenter;
spyOn(mController);
spyOn(mPresenter);
- final Configuration activityConfig = new Configuration();
- activityConfig.windowConfiguration.setBounds(TASK_BOUNDS);
- activityConfig.windowConfiguration.setMaxBounds(TASK_BOUNDS);
- doReturn(mActivityResources).when(mActivity).getResources();
- doReturn(activityConfig).when(mActivityResources).getConfiguration();
+ mActivity = createMockActivity();
}
@Test
@@ -129,4 +144,108 @@ public class SplitPresenterTest {
verify(mTransaction, never()).setWindowingMode(any(), anyInt());
}
+
+ @Test
+ public void testGetMinDimensionsForIntent() {
+ final Intent intent = new Intent(ApplicationProvider.getApplicationContext(),
+ MinimumDimensionActivity.class);
+ assertEquals(new Size(600, 1200), getMinDimensions(intent));
+ }
+
+ @Test
+ public void testShouldShowSideBySide() {
+ Activity secondaryActivity = createMockActivity();
+ final SplitRule splitRule = createSplitRule(mActivity, secondaryActivity);
+
+ assertTrue(shouldShowSideBySide(TASK_BOUNDS, splitRule));
+
+ // Set minDimensions of primary container to larger than primary bounds.
+ final Rect primaryBounds = getSplitBounds(true /* isPrimary */);
+ Pair<Size, Size> minDimensionsPair = new Pair<>(
+ new Size(primaryBounds.width() + 1, primaryBounds.height() + 1), null);
+
+ assertFalse(shouldShowSideBySide(TASK_BOUNDS, splitRule, minDimensionsPair));
+ }
+
+ @Test
+ public void testGetBoundsForPosition() {
+ Activity secondaryActivity = createMockActivity();
+ final SplitRule splitRule = createSplitRule(mActivity, secondaryActivity);
+ final Rect primaryBounds = getSplitBounds(true /* isPrimary */);
+ final Rect secondaryBounds = getSplitBounds(false /* isPrimary */);
+
+ assertEquals("Primary bounds must be reported.",
+ primaryBounds,
+ getBoundsForPosition(POSITION_START, TASK_BOUNDS, splitRule,
+ mActivity, null /* miniDimensionsPair */));
+
+ assertEquals("Secondary bounds must be reported.",
+ secondaryBounds,
+ getBoundsForPosition(POSITION_END, TASK_BOUNDS, splitRule,
+ mActivity, null /* miniDimensionsPair */));
+ assertEquals("Task bounds must be reported.",
+ new Rect(),
+ getBoundsForPosition(POSITION_FILL, TASK_BOUNDS, splitRule,
+ mActivity, null /* miniDimensionsPair */));
+
+ Pair<Size, Size> minDimensionsPair = new Pair<>(
+ new Size(primaryBounds.width() + 1, primaryBounds.height() + 1), null);
+
+ assertEquals("Fullscreen bounds must be reported because of min dimensions.",
+ new Rect(),
+ getBoundsForPosition(POSITION_START, TASK_BOUNDS,
+ splitRule, mActivity, minDimensionsPair));
+ }
+
+ @Test
+ public void testExpandSplitContainerIfNeeded() {
+ SplitContainer splitContainer = mock(SplitContainer.class);
+ Activity secondaryActivity = createMockActivity();
+ SplitRule splitRule = createSplitRule(mActivity, secondaryActivity);
+ TaskFragmentContainer primaryTf = mController.newContainer(mActivity, TASK_ID);
+ TaskFragmentContainer secondaryTf = mController.newContainer(secondaryActivity, TASK_ID);
+ doReturn(splitRule).when(splitContainer).getSplitRule();
+ doReturn(primaryTf).when(splitContainer).getPrimaryContainer();
+ doReturn(secondaryTf).when(splitContainer).getSecondaryContainer();
+
+ assertThrows(IllegalArgumentException.class, () ->
+ mPresenter.expandSplitContainerIfNeeded(mTransaction, splitContainer, mActivity,
+ null /* secondaryActivity */, null /* secondaryIntent */));
+
+ mPresenter.expandSplitContainerIfNeeded(mTransaction, splitContainer, mActivity,
+ secondaryActivity, null /* secondaryIntent */);
+
+ verify(mPresenter, never()).expandTaskFragment(any(), any());
+
+ doReturn(createActivityInfoWithMinDimensions()).when(secondaryActivity).getActivityInfo();
+
+ mPresenter.expandSplitContainerIfNeeded(mTransaction, splitContainer, mActivity,
+ secondaryActivity, null /* secondaryIntent */);
+
+ verify(mPresenter).expandTaskFragment(eq(mTransaction),
+ eq(primaryTf.getTaskFragmentToken()));
+ verify(mPresenter).expandTaskFragment(eq(mTransaction),
+ eq(secondaryTf.getTaskFragmentToken()));
+
+ clearInvocations(mPresenter);
+ mPresenter.expandSplitContainerIfNeeded(mTransaction, splitContainer, mActivity,
+ null /* secondaryActivity */, new Intent(ApplicationProvider
+ .getApplicationContext(), MinimumDimensionActivity.class));
+
+ verify(mPresenter).expandTaskFragment(eq(mTransaction),
+ eq(primaryTf.getTaskFragmentToken()));
+ verify(mPresenter).expandTaskFragment(eq(mTransaction),
+ eq(secondaryTf.getTaskFragmentToken()));
+ }
+
+ private Activity createMockActivity() {
+ final Activity activity = mock(Activity.class);
+ final Configuration activityConfig = new Configuration();
+ activityConfig.windowConfiguration.setBounds(TASK_BOUNDS);
+ activityConfig.windowConfiguration.setMaxBounds(TASK_BOUNDS);
+ doReturn(mActivityResources).when(activity).getResources();
+ doReturn(activityConfig).when(mActivityResources).getConfiguration();
+ doReturn(new ActivityInfo()).when(activity).getActivityInfo();
+ return activity;
+ }
}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
index ebe202db4e54..dd67e48ef353 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
@@ -22,6 +22,9 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_BOUNDS;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
@@ -53,9 +56,6 @@ import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class TaskContainerTest {
- private static final int TASK_ID = 10;
- private static final Rect TASK_BOUNDS = new Rect(0, 0, 600, 1200);
-
@Mock
private SplitController mController;
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java
index af3ad70c04db..d31342bfb309 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java
@@ -16,6 +16,8 @@
package androidx.window.extensions.embedding;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -43,8 +45,6 @@ import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class TaskFragmentAnimationControllerTest {
- private static final int TASK_ID = 10;
-
@Mock
private TaskFragmentOrganizer mOrganizer;
private TaskFragmentAnimationController mAnimationController;
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
index fcbd8a3ac020..28c2773e25cb 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
@@ -16,6 +16,9 @@
package androidx.window.extensions.embedding;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.createMockTaskFragmentInfo;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static org.junit.Assert.assertEquals;
@@ -30,17 +33,13 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
-import android.annotation.NonNull;
import android.app.Activity;
import android.content.Intent;
-import android.content.res.Configuration;
-import android.graphics.Point;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import android.window.TaskFragmentInfo;
-import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -55,7 +54,6 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
/**
@@ -68,8 +66,6 @@ import java.util.List;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class TaskFragmentContainerTest {
- private static final int TASK_ID = 10;
-
@Mock
private SplitPresenter mPresenter;
@Mock
@@ -311,18 +307,4 @@ public class TaskFragmentContainerTest {
doReturn(activity).when(mController).getActivity(activityToken);
return activity;
}
-
- /** Creates a mock TaskFragmentInfo for the given TaskFragment. */
- private TaskFragmentInfo createMockTaskFragmentInfo(@NonNull TaskFragmentContainer container,
- @NonNull Activity activity) {
- return new TaskFragmentInfo(container.getTaskFragmentToken(),
- mock(WindowContainerToken.class),
- new Configuration(),
- 1,
- true /* isVisible */,
- Collections.singletonList(activity.getActivityToken()),
- new Point(),
- false /* isTaskClearedForReuse */,
- false /* isTaskFragmentClearedForPip */);
- }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 0e8dc63943a6..0a334140d616 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -2220,11 +2220,10 @@ public class BubbleStackView extends FrameLayout
private void animateSwitchBubbles() {
// If we're no longer expanded, this is meaningless.
if (!mIsExpanded) {
+ mIsBubbleSwitchAnimating = false;
return;
}
- mIsBubbleSwitchAnimating = true;
-
// The surface contains a screenshot of the animating out bubble, so we just need to animate
// it out (and then release the GraphicBuffer).
PhysicsAnimator.getInstance(mAnimatingOutSurfaceContainer).cancel();
@@ -2838,6 +2837,7 @@ public class BubbleStackView extends FrameLayout
}, 0);
if (!mIsExpansionAnimating) {
+ mIsBubbleSwitchAnimating = true;
mSurfaceSynchronizer.syncSurfaceAndRun(() -> {
post(this::animateSwitchBubbles);
});
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java
index b9ddd3650b86..0f9260c9deaa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java
@@ -54,7 +54,13 @@ public interface TaskStackListenerCallback {
default void onTaskDescriptionChanged(RunningTaskInfo taskInfo) { }
- default void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { }
+ /**
+ * @return whether the snapshot is consumed and the lifecycle of the snapshot extends beyond
+ * the lifecycle of this callback.
+ */
+ default boolean onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) {
+ return false;
+ }
default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java
index 85e2654e4ebe..9e0a48b13413 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java
@@ -275,9 +275,15 @@ public class TaskStackListenerImpl extends TaskStackListener implements Handler.
}
case ON_TASK_SNAPSHOT_CHANGED: {
Trace.beginSection("onTaskSnapshotChanged");
+ final TaskSnapshot snapshot = (TaskSnapshot) msg.obj;
+ boolean snapshotConsumed = false;
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onTaskSnapshotChanged(msg.arg1,
- (TaskSnapshot) msg.obj);
+ boolean consumed = mTaskStackListeners.get(i).onTaskSnapshotChanged(
+ msg.arg1, snapshot);
+ snapshotConsumed |= consumed;
+ }
+ if (!snapshotConsumed && snapshot.getHardwareBuffer() != null) {
+ snapshot.getHardwareBuffer().close();
}
Trace.endSection();
break;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 7ea32a6d8f86..41e23647a6a4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -76,6 +76,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.util.Slog;
+import android.view.Choreographer;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner;
import android.view.RemoteAnimationAdapter;
@@ -1124,6 +1125,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mDividerFadeInAnimator.cancel();
return;
}
+ transaction.setFrameTimelineVsync(Choreographer.getInstance().getVsyncId());
transaction.setAlpha(dividerLeash, (float) animation.getAnimatedValue());
transaction.apply();
});
@@ -1216,17 +1218,23 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Override
public void onLayoutPositionChanging(SplitLayout layout) {
- mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t, false /* applyResizingOffset */));
+ final SurfaceControl.Transaction t = mTransactionPool.acquire();
+ t.setFrameTimelineVsync(Choreographer.getInstance().getVsyncId());
+ updateSurfaceBounds(layout, t, false /* applyResizingOffset */);
+ t.apply();
+ mTransactionPool.release(t);
}
@Override
public void onLayoutSizeChanging(SplitLayout layout) {
- mSyncQueue.runInSync(t -> {
- setResizingSplits(true /* resizing */);
- updateSurfaceBounds(layout, t, true /* applyResizingOffset */);
- mMainStage.onResizing(getMainStageBounds(), t);
- mSideStage.onResizing(getSideStageBounds(), t);
- });
+ final SurfaceControl.Transaction t = mTransactionPool.acquire();
+ t.setFrameTimelineVsync(Choreographer.getInstance().getVsyncId());
+ setResizingSplits(true /* resizing */);
+ updateSurfaceBounds(layout, t, true /* applyResizingOffset */);
+ mMainStage.onResizing(getMainStageBounds(), t);
+ mSideStage.onResizing(getSideStageBounds(), t);
+ t.apply();
+ mTransactionPool.release(t);
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index cde4247c575f..95bc579a4a51 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -389,6 +389,9 @@ public class TaskSnapshotWindow {
reportDrawn();
// In case window manager leaks us, make sure we don't retain the snapshot.
+ if (mSnapshot.getHardwareBuffer() != null) {
+ mSnapshot.getHardwareBuffer().close();
+ }
mSnapshot = null;
mSurfaceControl.release();
}
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index ccc23b7069ba..8756f1e2266d 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -2320,6 +2320,10 @@ final public class MediaCodec {
*/
public final void start() {
native_start();
+ synchronized(mBufferLock) {
+ cacheBuffers(true /* input */);
+ cacheBuffers(false /* input */);
+ }
}
private native final void native_start();
@@ -3951,9 +3955,6 @@ final public class MediaCodec {
+ "objects and attach to QueueRequest objects.");
}
if (mCachedInputBuffers == null) {
- cacheBuffers(true /* input */);
- }
- if (mCachedInputBuffers == null) {
throw new IllegalStateException();
}
// FIXME: check codec status
@@ -3992,9 +3993,6 @@ final public class MediaCodec {
+ "Please use getOutputFrame to get output frames.");
}
if (mCachedOutputBuffers == null) {
- cacheBuffers(false /* input */);
- }
- if (mCachedOutputBuffers == null) {
throw new IllegalStateException();
}
// FIXME: check codec status
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
index 9a64b58a080d..ed70ab996ccd 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
@@ -1653,7 +1653,7 @@ public class StaticMetadata {
modeList.contains(CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_OFF));
checkArrayValuesInRange(key, modes,
CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_OFF,
- CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_ON);
+ CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION);
return modes;
}
diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml
index e2fa97f2259c..beabaf1842bd 100644
--- a/packages/CompanionDeviceManager/res/values-fa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fa/strings.xml
@@ -39,7 +39,7 @@
<string name="profile_name_generic" msgid="6851028682723034988">"دستگاه"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"اجازه دادن"</string>
- <string name="consent_no" msgid="2640796915611404382">"مجاز نبودن"</string>
+ <string name="consent_no" msgid="2640796915611404382">"اجازه ندادن"</string>
<string name="consent_back" msgid="2560683030046918882">"برگشت"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"انتقال اجازه‌های برنامه به ساعت"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"برای آسان‌تر کردن راه‌اندازی ساعت، برنامه‌های نصب‌شده در ساعت درحین راه‌اندازی از همان اجازه‌های تلفن استفاده خواهند کرد.\n\n ممکن است این اجازه‌ها شامل دسترسی به میکروفون و مکان ساعت باشد."</string>
diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml
index b23ac1019609..1ac399946cbe 100644
--- a/packages/CompanionDeviceManager/res/values-hi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml
@@ -19,7 +19,7 @@
<string name="app_label" msgid="4470785958457506021">"सहयोगी डिवाइस मैनेजर"</string>
<string name="confirmation_title" msgid="3785000297483688997">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; को &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ऐक्सेस करने की अनुमति दें"</string>
<string name="profile_name_watch" msgid="576290739483672360">"स्मार्टवॉच"</string>
- <string name="chooser_title" msgid="2262294130493605839">"कोई <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चुनें, ताकि उसे &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; की मदद से प्रबंधित किया जा सके"</string>
+ <string name="chooser_title" msgid="2262294130493605839">"कोई <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चुनें, ताकि उसे &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; की मदद से मैनेज किया जा सके"</string>
<string name="summary_watch" msgid="3002344206574997652">"यह ऐप्लिकेशन, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को मैनेज करने के लिए ज़रूरी है. <xliff:g id="APP_NAME">%2$s</xliff:g> आपकी सूचनाओं पर कार्रवाई कर पाएगा. साथ ही, इसे आपके फ़ोन, एसएमएस, संपर्कों, कैलेंडर, कॉल लॉग, और आस-पास मौजूद डिवाइसों को ऐक्सेस करने की अनुमति मिल पाएगी."</string>
<string name="permission_apps" msgid="6142133265286656158">"ऐप्लिकेशन"</string>
<string name="permission_apps_summary" msgid="798718816711515431">"अपने फ़ोन के ऐप्लिकेशन को स्ट्रीम करें"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml
index 3a345fbd20c5..d641f299d652 100644
--- a/packages/CompanionDeviceManager/res/values-ky/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml
@@ -38,7 +38,7 @@
<string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> түзмөгүңүздүн атынан түзмөктөрүңүздүн ортосунда колдонмолорду тышкы экранга чыгарууга уруксат сурап жатат"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"түзмөк"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
- <string name="consent_yes" msgid="8344487259618762872">"Уруксат берүү"</string>
+ <string name="consent_yes" msgid="8344487259618762872">"Ооба"</string>
<string name="consent_no" msgid="2640796915611404382">"Уруксат берилбесин"</string>
<string name="consent_back" msgid="2560683030046918882">"Артка"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Колдонмонун уруксаттарын саатка өткөрүү"</string>
diff --git a/packages/PackageInstaller/res/values-it/strings.xml b/packages/PackageInstaller/res/values-it/strings.xml
index 979de608736c..74f7d908120f 100644
--- a/packages/PackageInstaller/res/values-it/strings.xml
+++ b/packages/PackageInstaller/res/values-it/strings.xml
@@ -46,7 +46,7 @@
<string name="out_of_space_dlg_text" msgid="8727714096031856231">"Impossibile installare <xliff:g id="APP_NAME">%1$s</xliff:g>. Libera dello spazio e riprova."</string>
<string name="app_not_found_dlg_title" msgid="5107924008597470285">"App non trovata"</string>
<string name="app_not_found_dlg_text" msgid="5219983779377811611">"Impossibile trovare l\'applicazione nell\'elenco di applicazioni installate."</string>
- <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"Autorizzazione non concessa"</string>
+ <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"Non autorizzate"</string>
<string name="user_is_not_allowed_dlg_text" msgid="3468447791330611681">"L\'utente corrente non è autorizzato a eseguire questa disinstallazione."</string>
<string name="generic_error_dlg_title" msgid="5863195085927067752">"Errore"</string>
<string name="generic_error_dlg_text" msgid="5287861443265795232">"Impossibile disinstallare l\'app."</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 04549b2d46f4..b1aeebecbfec 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -124,7 +124,7 @@
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"دسترسی سیم‌کارت"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"‏صدای HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"‏صدای HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"سمعک‌ها"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"سمعک"</string>
<string name="bluetooth_profile_le_audio" msgid="5158149987518342036">"LE_AUDIO"</string>
<string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"به سمعک متصل شد"</string>
<string name="bluetooth_le_audio_profile_summary_connected" msgid="3162538609379333442">"‏متصل به LE_AUDIO"</string>
@@ -144,7 +144,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"استفاده برای تلفن صوتی"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"استفاده برای انتقال فایل"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"استفاده برای چاپ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"استفاده برای سمعک‌ها"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"استفاده کردن برای سمعک"</string>
<string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"‏استفاده برای LE_AUDIO"</string>
<string name="bluetooth_pairing_accept" msgid="2054232610815498004">"مرتبط‌سازی"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"مرتبط‌سازی"</string>
@@ -184,7 +184,7 @@
<string name="launch_defaults_some" msgid="3631650616557252926">"بعضی پیش‌فرض‌ها تنظیم شده‌اند"</string>
<string name="launch_defaults_none" msgid="8049374306261262709">"پیش‌فرضی تنظیم نشده است"</string>
<string name="tts_settings" msgid="8130616705989351312">"تنظیمات متن به گفتار"</string>
- <string name="tts_settings_title" msgid="7602210956640483039">"خروجی تبدیل متن به گفتار"</string>
+ <string name="tts_settings_title" msgid="7602210956640483039">"خروجی نوشتار به گفتار"</string>
<string name="tts_default_rate_title" msgid="3964187817364304022">"سرعت گفتار"</string>
<string name="tts_default_rate_summary" msgid="3781937042151716987">"سرعتی که متن خوانده می‌شود"</string>
<string name="tts_default_pitch_title" msgid="6988592215554485479">"زیر و بمی صدا"</string>
@@ -643,7 +643,7 @@
<string name="dream_complication_title_date" msgid="8661176085446135789">"تاریخ"</string>
<string name="dream_complication_title_weather" msgid="598609151677172783">"آب‌وهوا"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"کیفیت هوا"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"اطلاعات ارسال محتوا"</string>
+ <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"اطلاعات پخش محتوا"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"انتخاب عکس نمایه"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"نماد کاربر پیش‌فرض"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"صفحه‌کلید فیزیکی"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 8c3f1fad8211..861c1833fdf9 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -371,7 +371,7 @@
<string name="show_hw_layers_updates" msgid="5268370750002509767">"Atualizações de camadas de hardware"</string>
<string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"Piscar camadas de hardware em verde ao atualizar"</string>
<string name="debug_hw_overdraw" msgid="8944851091008756796">"Depurar overdraw da GPU"</string>
- <string name="disable_overlays" msgid="4206590799671557143">"Desativar sobreposição HW"</string>
+ <string name="disable_overlays" msgid="4206590799671557143">"Desativar sobreposição de HW"</string>
<string name="disable_overlays_summary" msgid="1954852414363338166">"Sempre usar a GPU para composição de tela"</string>
<string name="simulate_color_space" msgid="1206503300335835151">"Simular espaço de cores"</string>
<string name="enable_opengl_traces_title" msgid="4638773318659125196">"Ativar rastream. OpenGL"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 8c3f1fad8211..861c1833fdf9 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -371,7 +371,7 @@
<string name="show_hw_layers_updates" msgid="5268370750002509767">"Atualizações de camadas de hardware"</string>
<string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"Piscar camadas de hardware em verde ao atualizar"</string>
<string name="debug_hw_overdraw" msgid="8944851091008756796">"Depurar overdraw da GPU"</string>
- <string name="disable_overlays" msgid="4206590799671557143">"Desativar sobreposição HW"</string>
+ <string name="disable_overlays" msgid="4206590799671557143">"Desativar sobreposição de HW"</string>
<string name="disable_overlays_summary" msgid="1954852414363338166">"Sempre usar a GPU para composição de tela"</string>
<string name="simulate_color_space" msgid="1206503300335835151">"Simular espaço de cores"</string>
<string name="enable_opengl_traces_title" msgid="4638773318659125196">"Ativar rastream. OpenGL"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
index 1804e86a98f0..c829bc316246 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
@@ -33,6 +33,7 @@ import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
import static com.android.settingslib.media.LocalMediaManager.MediaDeviceState.STATE_SELECTED;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.media.MediaRoute2Info;
@@ -268,6 +269,20 @@ public abstract class MediaDevice implements Comparable<MediaDevice> {
}
/**
+ * Checks if route's volume is fixed, if true, we should disable volume control for the device.
+ *
+ * @return route for this device is fixed.
+ */
+ @SuppressLint("NewApi")
+ public boolean isVolumeFixed() {
+ if (mRouteInfo == null) {
+ Log.w(TAG, "RouteInfo is empty, regarded as volume fixed.");
+ return true;
+ }
+ return mRouteInfo.getVolumeHandling() == MediaRoute2Info.PLAYBACK_VOLUME_FIXED;
+ }
+
+ /**
* Transfer MediaDevice for media
*
* @return result of transfer media
@@ -439,7 +454,7 @@ public abstract class MediaDevice implements Comparable<MediaDevice> {
* Check if it is muting expected device
* @return {@code true} if it is muting expected device, otherwise return {@code false}
*/
- protected boolean isMutingExpectedDevice() {
+ public boolean isMutingExpectedDevice() {
return false;
}
diff --git a/packages/SystemUI/TEST_MAPPING b/packages/SystemUI/TEST_MAPPING
index b01fd6de5243..3bd6d51eecc6 100644
--- a/packages/SystemUI/TEST_MAPPING
+++ b/packages/SystemUI/TEST_MAPPING
@@ -20,6 +20,25 @@
]
}
],
+ "presubmit-sysui": [
+ {
+ "name": "PlatformScenarioTests",
+ "options": [
+ {
+ "include-filter": "android.platform.test.scenario.sysui"
+ },
+ {
+ "include-annotation": "android.platform.test.scenario.annotation.Scenario"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.Postsubmit"
+ }
+ ]
+ }
+ ],
"presubmit": [
{
"name": "SystemUIGoogleTests",
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
index 8e34c4757f37..b3dd95553ed0 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
@@ -435,7 +435,7 @@ class ColorScheme(
val h = "H${hct.hue.roundToInt().toString().padEnd(width)}"
val c = "C${hct.chroma.roundToInt().toString().padEnd(width)}"
val t = "T${CamUtils.lstarFromInt(color).roundToInt().toString().padEnd(width)}"
- val hex = Integer.toHexString(color).replaceRange(0, 2, "").uppercase()
+ val hex = Integer.toHexString(color and 0xffffff).padStart(6, '0').uppercase()
return "$h$c$t = #$hex"
}
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index e48e45593ebf..32848fd4b2cb 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Teks is gekopieer"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Prent is gekopieer"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Inhoud is gekopieer"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Knipbordredigeerder"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Knipbord"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Prentvoorskou"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"wysig"</string>
<string name="add" msgid="81036585205287996">"Voeg by"</string>
<string name="manage_users" msgid="1823875311934643849">"Bestuur gebruikers"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Sleep na verdeelde skerm word nie vir hierdie kennisgewing gesteun nie."</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 1991259744ce..f2d56b2c3c84 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"ካሜራ"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ስልክ"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"የድምጽ እርዳታ"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"የኪስ ቦርሳ"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"የQR ኮድ መቃኛ"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"ክፈት"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"መሣሪያ ተቆልፏል"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"ጽሁፍ ተቀድቷል"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"ምስል ተቀድቷል"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"ይዘት ተቀድቷል"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"የቅንጥብ ሰሌዳ አርታዒ"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"የቅንጥብ ሰሌዳ"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"የምስል ቅድመ-እይታ"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"አርትዕ"</string>
<string name="add" msgid="81036585205287996">"አክል"</string>
<string name="manage_users" msgid="1823875311934643849">"ተጠቃሚዎችን ያስተዳድሩ"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"ይህ ማሳወቂያ ወደ Splitscreen መጎተትን አይደግፍም።"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 9bb455e5a4a8..ad1a34d26f25 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -973,14 +973,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"تم نسخ النص."</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"تم نسخ الصورة."</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"تم نسخ المحتوى."</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"محرِّر الحافظة"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"الحافظة"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"معاينة الصورة"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"التعديل"</string>
<string name="add" msgid="81036585205287996">"إضافة"</string>
<string name="manage_users" msgid="1823875311934643849">"إدارة المستخدمين"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"لا يتيح هذا الإشعار السحب لتقسيم الشاشة."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 8286ee611f87..173a33e7e88d 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"পাঠ প্ৰতিলিপি কৰা হ’ল"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"প্ৰতিচ্ছবি প্ৰতিলিপি কৰা হ’ল"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"সমল প্ৰতিলিপি কৰা হ’ল"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"ক্লিপব’ৰ্ড সম্পাদক"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"ক্লিপব’ৰ্ড"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"প্ৰতিচ্ছবিৰ পূৰ্বদৰ্শন"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"সম্পাদনা কৰক"</string>
<string name="add" msgid="81036585205287996">"যোগ দিয়ক"</string>
<string name="manage_users" msgid="1823875311934643849">"ব্যৱহাৰকাৰী পৰিচালনা কৰক"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"এই জাননীটোৱে টানি আনি এৰাৰ পৰা বিভাজিত স্ক্ৰীন সমৰ্থন নকৰে।"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 1620056aab42..f1a3c69eed5d 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Mətn kopyalanıb"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Şəkil Kopyalanıb"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Məzmun kopyalanıb"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Mübadilə Buferi Redaktoru"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Mübadilə buferi"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Şəkil önizləməsi"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"redaktə"</string>
<string name="add" msgid="81036585205287996">"Əlavə edin"</string>
<string name="manage_users" msgid="1823875311934643849">"İstifadəçiləri idarə edin"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Bu bildiriş Ayrılmış ekrana sürüşdürməyi dəstəkləmir."</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index e18316fcd9f9..615a7090b21b 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -952,14 +952,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Tekst je kopiran"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Slika je kopirana"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Sadržaj je kopiran"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Uređivač privremene memorije"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Privremena memorija"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Pregled slike"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"izmenite"</string>
<string name="add" msgid="81036585205287996">"Dodaj"</string>
<string name="manage_users" msgid="1823875311934643849">"Upravljajte korisnicima"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Ovo obaveštenje ne podržava prevlačenje na podeljeni ekran."</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 5ea3a8c14fce..63010288e71c 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -959,14 +959,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Тэкст скапіраваны"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Відарыс скапіраваны"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Змесціва скапіравана"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Рэдактар буфера абмену"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Буфер абмену"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Папярэдні прагляд відарыса"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"змяніць"</string>
<string name="add" msgid="81036585205287996">"Дадаць"</string>
<string name="manage_users" msgid="1823875311934643849">"Кіраванне карыстальнікамі"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Гэта апавяшчэнне нельга перацягнуць на падзелены экран."</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index add650d80748..6e1b68ca7d5f 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Текстът е копиран"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Изображението е копирано"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Съдържанието е копирано"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Редактор на буферната памет"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Буферна памет"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Визуализация на изображението"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"редактиране"</string>
<string name="add" msgid="81036585205287996">"Добавяне"</string>
<string name="manage_users" msgid="1823875311934643849">"Управление на потребителите"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Това известие не поддържа плъзгане за разделяне на екрана."</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index a9e95f16b642..f4f897e23dd5 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"ক্যামেরা"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ফোন"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ভয়েস সহায়তা"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"ওয়ালেট"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR কোড স্ক্যানার"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"আনলক করুন"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"ডিভাইস লক করা আছে"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"টেক্সট কপি করা হয়েছে"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"ছবি কপি করা হয়েছে"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"কন্টেন্ট কপি করা হয়েছে"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"ক্লিপবোর্ড এডিটর"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"ক্লিপবোর্ড"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"ছবির প্রিভিউ"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"এডিট করতে"</string>
<string name="add" msgid="81036585205287996">"যোগ করুন"</string>
<string name="manage_users" msgid="1823875311934643849">"ব্যবহারকারীদের ম্যানেজ করুন"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"স্প্লিটস্ক্রিন মোডে এই বিজ্ঞপ্তি টেনে আনা যাবে না।"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index e814a5c745db..e8857ad070aa 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"El text s\'ha copiat"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"La imatge s\'ha copiat"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"El contingut s\'ha copiat"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor del porta-retalls"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Porta-retalls"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Previsualització de la imatge"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"editar"</string>
<string name="add" msgid="81036585205287996">"Afegeix"</string>
<string name="manage_users" msgid="1823875311934643849">"Gestiona els usuaris"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Aquesta notificació no es pot arrossegar a la pantalla dividida."</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 69de3b5adcb6..f46f82ab2eba 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -959,14 +959,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Text byl zkopírován"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Obrázek byl zkopírován"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Obsah byl zkopírován"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor schránky"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Schránka"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Náhled obrázku"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"upravit"</string>
<string name="add" msgid="81036585205287996">"Přidat"</string>
<string name="manage_users" msgid="1823875311934643849">"Správa uživatelů"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Toto oznámení nepodporuje přetažení na rozdělenou obrazovku."</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 8b2ef4e273de..dbbd74f8d889 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -372,7 +372,7 @@
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Din organisation ejer denne enhed og overvåger muligvis netværkstrafikken"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ejer denne enhed og overvåger muligvis netværkstrafikken"</string>
<string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"Denne enhed er leveret af <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
- <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"Denne enhed tilhører din organisation, og den har forbindelse til nettet via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"Denne enhed tilhører din organisation, og den har forbindelse til internettet via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="quick_settings_disclosure_named_management_named_vpn" msgid="2169227918166358741">"Denne enhed tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, og den har forbindelse til nettet via <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
<string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Denne enhed tilhører din organisation"</string>
<string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Denne enhed tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
@@ -382,8 +382,8 @@
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> kan overvåge netværkstrafik på din arbejdsprofil"</string>
<string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"Din it-administrator kan se netværksaktivitet på din arbejdsprofil"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Netværket kan være overvåget"</string>
- <string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"Denne enhed har forbindelse til nettet via VPN-forbindelser"</string>
- <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"Dine arbejdsapps har forbindelse til nettet via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"Denne enhed har forbindelse til internettet via VPN-forbindelser"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"Dine arbejdsapps har forbindelse til internettet via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="451254750289172191">"Dine personlige apps har forbindelse til internettet via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="quick_settings_disclosure_named_vpn" msgid="6191822916936028208">"Denne enhed har forbindelse til internettet via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_financed_device" msgid="3659962357973919387">"Denne enhed er leveret af <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
@@ -401,9 +401,9 @@
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Der er installeret et nøglecenter på denne enhed. Din sikre netværkstrafik kan overvåges eller ændres."</string>
<string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Din administrator har aktiveret netværksregistrering, som overvåger trafik på din enhed."</string>
<string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Din administrator har aktiveret netværkslogging, som overvåger trafik på din arbejdsprofil, men ikke på din personlige profil."</string>
- <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Denne enhed har forbindelse til nettet via <xliff:g id="VPN_APP">%1$s</xliff:g>. Din netværksaktivitet, herunder mails og browserdata, er synlig for din it-administrator."</string>
- <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Denne enhed har forbindelse til nettet via <xliff:g id="VPN_APP_0">%1$s</xliff:g> og <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Din netværksaktivitet, herunder mails og browserdata, er synlig for din it-administrator."</string>
- <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Dine arbejdsapps har forbindelse til nettet via <xliff:g id="VPN_APP">%1$s</xliff:g>. Din netværksaktivitet i arbejdsapps, herunder mails og browserdata, er synlig for din it-administrator og VPN-udbyder."</string>
+ <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Denne enhed har forbindelse til internettet via <xliff:g id="VPN_APP">%1$s</xliff:g>. Din netværksaktivitet, herunder mails og browserdata, er synlig for din it-administrator."</string>
+ <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Denne enhed har forbindelse til internettet via <xliff:g id="VPN_APP_0">%1$s</xliff:g> og <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Din netværksaktivitet, herunder mails og browserdata, er synlig for din it-administrator."</string>
+ <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Dine arbejdsapps har forbindelse til internettet via <xliff:g id="VPN_APP">%1$s</xliff:g>. Din netværksaktivitet i arbejdsapps, herunder mails og browserdata, er synlig for din it-administrator og VPN-udbyder."</string>
<string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Dine personlige apps har forbindelse til nettet via <xliff:g id="VPN_APP">%1$s</xliff:g>. Din netværksaktivitet, herunder mails og browserdata, er synlig for din VPN-udbyder."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
<string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Åbn VPN-indstillinger"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Teksten blev kopieret"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Billedet blev kopieret"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Indholdet blev kopieret"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Redigeringsværktøj til udklipsholder"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Udklipsholder"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Forhåndsvisning af billede"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"redigere"</string>
<string name="add" msgid="81036585205287996">"Tilføj"</string>
<string name="manage_users" msgid="1823875311934643849">"Administrer brugere"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Denne notifikation kan ikke trækkes til en opdelt skærm."</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 52b22090f261..f78662508959 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Text kopiert"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Bild kopiert"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Inhalt kopiert"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Zwischenablage bearbeiten"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Zwischenablage"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Bildvorschau"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"bearbeiten"</string>
<string name="add" msgid="81036585205287996">"Hinzufügen"</string>
<string name="manage_users" msgid="1823875311934643849">"Nutzer verwalten"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Diese Benachrichtigung lässt sich nicht auf einen geteilten Bildschirm ziehen."</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index e3b85817394d..83a1d18860a3 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Cámara"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Teléfono"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistente voz"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Billetera"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Escáner de código QR"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"Ver en modo de demostración"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string>
- <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Billetera"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"Prepárate para realizar compras rápidas y seguras con tu teléfono"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Mostrar todo"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Presiona para abrir"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Se copió el texto"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Se copió la imagen"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Se copió el contenido"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor de portapapeles"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Portapapeles"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Vista previa de la imagen"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"editar"</string>
<string name="add" msgid="81036585205287996">"Agregar"</string>
<string name="manage_users" msgid="1823875311934643849">"Administrar usuarios"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Esta notificación no admite arrastrar entre pantallas divididas."</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index f2f4bbb463ed..9b79f71a4d88 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Cámara"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Teléfono"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistente voz"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"Cartera"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Escáner de códigos QR"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
@@ -403,7 +403,7 @@
<string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Tu administrador ha activado el registro de la red, por lo que se monitorizará el tráfico de tu perfil de trabajo, aunque no el de tu perfil personal."</string>
<string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Este dispositivo está conectado a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. Tu actividad de red, como los correos electrónicos y los datos de navegación, es visible para tu administrador de TI."</string>
<string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Este dispositivo está conectado a Internet a través de <xliff:g id="VPN_APP_0">%1$s</xliff:g> y <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Tu actividad de red, como los correos electrónicos y los datos de navegación, es visible para tu administrador de TI."</string>
- <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Tus aplicaciones de trabajo están conectadas a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. Tu actividad de red en estas aplicaciones, incluidos los correos electrónicos y los datos de navegación, es visible para tu administrador de TI y tu proveedor de VPN."</string>
+ <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Tus aplicaciones de trabajo están conectadas a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. Tu actividad de red en las aplicaciones de trabajo, incluidos los correos electrónicos y los datos de navegación, es visible para tu administrador de TI y tu proveedor de VPN."</string>
<string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Tus aplicaciones personales están conectadas a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. Tu actividad de red, como los correos electrónicos y los datos de navegación, es visible para tu proveedor de VPN."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
<string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Abrir ajustes de VPN"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Texto copiado"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Imagen copiada"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Contenido copiado"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor del portapapeles"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Portapapeles"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Vista previa de la imagen"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"editar"</string>
<string name="add" msgid="81036585205287996">"Añadir"</string>
<string name="manage_users" msgid="1823875311934643849">"Gestionar usuarios"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Esta notificación no se puede arrastrar a la pantalla dividida."</string>
diff --git a/packages/SystemUI/res/values-es/tiles_states_strings.xml b/packages/SystemUI/res/values-es/tiles_states_strings.xml
index e4310af3d531..78c7669cbb47 100644
--- a/packages/SystemUI/res/values-es/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es/tiles_states_strings.xml
@@ -64,7 +64,7 @@
<string-array name="tile_states_rotation">
<item msgid="4578491772376121579">"No disponible"</item>
<item msgid="5776427577477729185">"Desactivada"</item>
- <item msgid="7105052717007227415">"Activada"</item>
+ <item msgid="7105052717007227415">"Activado"</item>
</string-array>
<string-array name="tile_states_bt">
<item msgid="5330252067413512277">"No disponible"</item>
@@ -89,7 +89,7 @@
<string-array name="tile_states_color_correction">
<item msgid="2840507878437297682">"No disponible"</item>
<item msgid="1909756493418256167">"Desactivada"</item>
- <item msgid="4531508423703413340">"Activada"</item>
+ <item msgid="4531508423703413340">"Activado"</item>
</string-array>
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"No disponible"</item>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 9bd5f0ad7b66..46f9f518628c 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kaamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Häälabi"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"Rahakott"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR-koodi skanner"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Luku avamine"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Seade on lukustatud"</string>
@@ -372,7 +372,7 @@
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Teie organisatsioon on selle seadme omanik ja võib jälgida võrguliiklust"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> on selle seadme omanik ja võib jälgida võrguliiklust"</string>
<string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"Selle seadme on andnud <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
- <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"See seade kuulub teie organisatsioonile ja on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"See seade kuulub teie organisatsioonile ja on ühendatud internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu"</string>
<string name="quick_settings_disclosure_named_management_named_vpn" msgid="2169227918166358741">"See seade kuulub organisatsioonile <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ja on internetiga rakenduse <xliff:g id="VPN_APP">%2$s</xliff:g> kaudu ühendatud"</string>
<string name="quick_settings_disclosure_management" msgid="5515296598440684962">"See seade kuulub teie organisatsioonile"</string>
<string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Selle seadme omanik on <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
@@ -382,8 +382,8 @@
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> võib jälgida võrguliiklust teie tööprofiilil"</string>
<string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"Tööprofiili võrgutegevused on teie IT-administraatorile nähtavad"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Võrku võidakse jälgida"</string>
- <string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"See seade on internetiga VPN-ide kaudu ühendatud"</string>
- <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"Teie töörakendused on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud"</string>
+ <string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"See seade on ühendatud internetiga VPN-ide kaudu"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"Teie töörakendused on ühendatud internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu"</string>
<string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="451254750289172191">"Teie isiklikud rakendused on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud"</string>
<string name="quick_settings_disclosure_named_vpn" msgid="6191822916936028208">"See seade on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud"</string>
<string name="monitoring_title_financed_device" msgid="3659962357973919387">"Selle seadme on andnud <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
@@ -402,8 +402,8 @@
<string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Teie administraator lülitas sisse võrgu logimise funktsiooni, mis jälgib teie seadmes liiklust."</string>
<string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Teie administraator on sisse lülitanud võrgu logimise funktsiooni, mis jälgib liiklust teie võrguprofiilil, kuid mitte teie isiklikul profiilil."</string>
<string name="monitoring_description_named_vpn" msgid="7502657784155456414">"See seade on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud. Teie võrgutegevus, sealhulgas meilid ja sirvimisandmed, on nähtav teie IT-administraatorile."</string>
- <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"See seade on internetiga rakenduse <xliff:g id="VPN_APP_0">%1$s</xliff:g> ja <xliff:g id="VPN_APP_1">%2$s</xliff:g> kaudu ühendatud. Teie võrgutegevus, sealhulgas meilid ja sirvimisandmed, on nähtav teie IT-administraatorile."</string>
- <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Teie töörakendused on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud. Teie töörakenduste võrgutegevus, sealhulgas meilid ja sirvimisandmed, on nähtav teie IT-administraatorile ning VPN-i teenusepakkujale."</string>
+ <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"See seade on ühendatud internetiga rakenduste <xliff:g id="VPN_APP_0">%1$s</xliff:g> ja <xliff:g id="VPN_APP_1">%2$s</xliff:g> kaudu. Teie võrgutegevused (sealhulgas meilid ja sirvimisandmed) on nähtavad teie IT-administraatorile."</string>
+ <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Teie töörakendused on ühendatud internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu. Teie töörakenduste võrgutegevused (sealhulgas meilid ja sirvimisandmed) on nähtavad teie IT-administraatorile ning VPN-i teenusepakkujale."</string>
<string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Teie isiklikud rakendused on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud. Teie võrgutegevus, sealhulgas meilid ja sirvimisandmed, on nähtav teie VPN-i teenusepakkujale."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
<string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"VPN-i seadete avamine"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"Kuva demorežiim"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Äratus"</string>
- <string name="wallet_title" msgid="5369767670735827105">"Rahakott"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"Seadistage kiirem ja turvalisem viis telefoniga ostmiseks"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Kuva kõik"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Puudutage avamiseks"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Tekst kopeeriti"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Pilt kopeeriti"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Sisu kopeeriti"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Lõikelaua sisu muutmine"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Lõikelaud"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Pildi eelvaade"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"muutmine"</string>
<string name="add" msgid="81036585205287996">"Lisa"</string>
<string name="manage_users" msgid="1823875311934643849">"Kasutajate haldamine"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"See märguanne ei toeta jagatud ekraanikuvale lohistamist."</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 896f7a0d63a0..fc760977d58c 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -406,7 +406,7 @@
<string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Laneko aplikazioak <xliff:g id="VPN_APP">%1$s</xliff:g> bidez daude konektatuta Internetera. IKT saileko administratzaileak eta VPNaren hornitzaileak laneko aplikazioen bidez egiten dituzun sareko jarduerak (mezu elektronikoak eta arakatze-datuak barne) ikusi ahalko dituzte."</string>
<string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Aplikazio pertsonalak <xliff:g id="VPN_APP">%1$s</xliff:g> bidez daude konektatuta Internetera. IKT saileko administratzaileak sareko jarduerak (mezu elektronikoak eta arakatze-datuak barne) ikusi ahalko ditu."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
- <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Ireki VPN ezarpenak"</string>
+ <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Ireki VPN sarearen ezarpenak"</string>
<string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Zure gurasoak kudeatzen du gailua. Zure gurasoak gailuko informazioa ikusi eta kudea dezake; besteak beste, zer aplikazio erabiltzen dituzun, zure kokapena zein den eta pantaila aurrean zenbat eta noiz egoten zaren."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPNa"</string>
<string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent bidez desblokeatuta"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 06a14f2dee95..5676865ecffa 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -78,7 +78,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"دوباره نماگرفت بگیرید"</string>
<string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"نماگرفت ذخیره نمی‌شود"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"برنامه یا سازمان شما اجازه نمی‌دهند نماگرفت بگیرید."</string>
- <string name="screenshot_blocked_by_admin" msgid="5486757604822795797">"سرپرست سیستم گرفتن نماگرفت را مسدود کرده است"</string>
+ <string name="screenshot_blocked_by_admin" msgid="5486757604822795797">"سرپرست فناوری اطلاعات گرفتن نماگرفت را مسدود کرده است"</string>
<string name="screenshot_edit_label" msgid="8754981973544133050">"ویرایش"</string>
<string name="screenshot_edit_description" msgid="3333092254706788906">"ویرایش نماگرفت"</string>
<string name="screenshot_share_description" msgid="2861628935812656612">"هم‌رسانی نماگرفت"</string>
@@ -353,10 +353,10 @@
<string name="user_remove_user_title" msgid="9124124694835811874">"کاربر حذف شود؟"</string>
<string name="user_remove_user_message" msgid="6702834122128031833">"همه برنامه‌ها و داده‌های این کاربر حذف می‌شود."</string>
<string name="user_remove_user_remove" msgid="8387386066949061256">"حذف"</string>
- <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> به همه اطلاعاتی که روی صفحه‌نمایش قابل‌مشاهد است و هنگام ضبط کردن یا ارسال محتوا از دستگاهتان پخش می‌شود دسترسی خواهد داشت. این شامل اطلاعاتی مانند گذرواژه‌ها، جزئیات پرداخت، عکس‌ها، پیام‌ها، و صداهایی که پخش می‌کنید می‌شود."</string>
- <string name="media_projection_dialog_service_text" msgid="958000992162214611">"سرویس ارائه‌دهنده این عملکرد به همه اطلاعاتی که روی صفحه‌نمایش قابل‌مشاهد است و هنگام ضبط کردن یا ارسال محتوا از دستگاهتان پخش می‌شود دسترسی خواهد داشت. این شامل اطلاعاتی مانند گذرواژه‌ها، جزئیات پرداخت، عکس‌ها، پیام‌ها، و صداهایی که پخش می‌کنید می‌شود."</string>
- <string name="media_projection_dialog_service_title" msgid="2888507074107884040">"ضبط یا ارسال محتوا شروع شود؟"</string>
- <string name="media_projection_dialog_title" msgid="3316063622495360646">"ضبط یا ارسال محتوا با <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> شروع شود؟"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> به همه اطلاعاتی که روی صفحه‌نمایش قابل‌مشاهد است و هنگام ضبط کردن یا پخش محتوا از دستگاهتان پخش می‌شود دسترسی خواهد داشت. این شامل اطلاعاتی مانند گذرواژه‌ها، جزئیات پرداخت، عکس‌ها، پیام‌ها، و صداهایی که پخش می‌کنید می‌شود."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"سرویس ارائه‌دهنده این عملکرد به همه اطلاعاتی که روی صفحه‌نمایش قابل‌مشاهد است و هنگام ضبط کردن یا پخش محتوا از دستگاهتان پخش می‌شود دسترسی خواهد داشت. این شامل اطلاعاتی مانند گذرواژه‌ها، جزئیات پرداخت، عکس‌ها، پیام‌ها، و صداهایی که پخش می‌کنید می‌شود."</string>
+ <string name="media_projection_dialog_service_title" msgid="2888507074107884040">"ضبط یا پخش محتوا شروع شود؟"</string>
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"ضبط یا پخش محتوا با <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> شروع شود؟"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"پاک کردن همه موارد"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"مدیریت"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"سابقه"</string>
@@ -380,7 +380,7 @@
<string name="quick_settings_disclosure_named_management_vpns" msgid="3312645578322079185">"‏این دستگاه متعلق به <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> است و ازطریق چند VPN به اینترنت متصل شده است"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"ممکن است سازمان شما ترافیک شبکه را در نمایه کاری‌تان پایش کند"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ممکن است ترافیک شبکه را در نمایه کاری شما پایش کند"</string>
- <string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"سرپرست سیستم می‌تواند فعالیت شبکه نمایه کاری را ببیند"</string>
+ <string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"سرپرست فناوری اطلاعات می‌تواند فعالیت شبکه نمایه کاری را ببیند"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"ممکن است شبکه پایش شود"</string>
<string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"‏این دستگاه ازطریق چند VPN به اینترنت متصل شده است"</string>
<string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"برنامه‌های کاری‌تان ازطریق <xliff:g id="VPN_APP">%1$s</xliff:g> به اینترنت متصل شده است"</string>
@@ -401,9 +401,9 @@
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"مرجع گواهینامه‌ای در این دستگاه نصب شده است. ممکن است ترافیک امن شبکه شما پایش یا تغییر داده شود."</string>
<string name="monitoring_description_management_network_logging" msgid="216983105036994771">"سرپرست سیستم شما گزارش‌گیری از شبکه را (که ترافیک دستگاه شما را پایش می‌کند) روشن کرده است."</string>
<string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"سرپرست شما گزارش‌گیری شبکه را که بر ترافیک نمایه کاری‌تان نظارت می‌کند، اما بر ترافیک نمایه شخصی‌تان نظارت نمی‌کند روشن کرده است."</string>
- <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"این دستگاه ازطریق <xliff:g id="VPN_APP">%1$s</xliff:g> به اینترنت متصل شده است. سرپرست سیستم شما می‌تواند فعالیت شبکه شما را (ازجمله ایمیل‌ها و داده‌های مرور) ببیند."</string>
- <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"این دستگاه ازطریق <xliff:g id="VPN_APP_0">%1$s</xliff:g> و <xliff:g id="VPN_APP_1">%2$s</xliff:g> به اینترنت متصل شده است. سرپرست سیستم شما می‌تواند فعالیت شبکه شما را (ازجمله ایمیل‌ها و داده‌های مرور) ببیند."</string>
- <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"‏برنامه‌های کاری‌تان ازطریق <xliff:g id="VPN_APP">%1$s</xliff:g> به اینترنت متصل شده است. ارائه‌دهنده VPN و سرپرست سیستم شما می‌توانند فعالیت شبکه شما در برنامه‌های کاری را (ازجمله ایمیل‌ها و داده‌های مرور) ببینند."</string>
+ <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"این دستگاه ازطریق <xliff:g id="VPN_APP">%1$s</xliff:g> به اینترنت متصل شده است. سرپرست فناوری اطلاعات شما می‌تواند فعالیت شبکه شما را (ازجمله ایمیل‌ها و داده‌های مرور) ببیند."</string>
+ <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"این دستگاه ازطریق <xliff:g id="VPN_APP_0">%1$s</xliff:g> و <xliff:g id="VPN_APP_1">%2$s</xliff:g> به اینترنت متصل شده است. سرپرست فناوری اطلاعات شما می‌تواند فعالیت شبکه شما را (ازجمله ایمیل‌ها و داده‌های مرور) ببیند."</string>
+ <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"‏برنامه‌های کاری‌تان ازطریق <xliff:g id="VPN_APP">%1$s</xliff:g> به اینترنت متصل شده است. ارائه‌دهنده VPN و سرپرست فناوری اطلاعات شما می‌توانند فعالیت شبکه شما در برنامه‌های کاری را (ازجمله ایمیل‌ها و داده‌های مرور) ببینند."</string>
<string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"‏برنامه‌های شخصی‌تان ازطریق <xliff:g id="VPN_APP">%1$s</xliff:g> به اینترنت متصل شده است. ارائه‌دهنده VPN شما می‌تواند فعالیت شبکه شما را (ازجمله ایمیل‌ها و داده‌های مرور) ببیند."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
<string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"‏باز کردن تنظیمات VPN"</string>
@@ -553,7 +553,7 @@
<string name="keyboard_key_dpad_right" msgid="6282105433822321767">"راست"</string>
<string name="keyboard_key_dpad_center" msgid="4079412840715672825">"مرکز"</string>
<string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
- <string name="keyboard_key_space" msgid="6980847564173394012">"فاصله"</string>
+ <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
<string name="keyboard_key_enter" msgid="8633362970109751646">"ورود"</string>
<string name="keyboard_key_backspace" msgid="4095278312039628074">"پس‌بر"</string>
<string name="keyboard_key_media_play_pause" msgid="8389984232732277478">"پخش/مکث"</string>
@@ -843,7 +843,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"مرتبط کردن دستگاه جدید"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"برای ارسال محتوای این جلسه، لطفاً برنامه را باز کنید."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"برنامه ناشناس"</string>
- <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"توقف ارسال محتوا"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"توقف پخش محتوا"</string>
<string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"دستگاه‌های دردسترس برای خروجی صدا."</string>
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"میزان صدا"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"همه‌فرتستی چطور کار می‌کند"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"نوشتار کپی شد"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"تصویر کپی شد"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"محتوا کپی شد"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"ویرایشگر بریده‌دان"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"بریده‌دان"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"پیش‌نمای تصویر"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"ویرایش کردن"</string>
<string name="add" msgid="81036585205287996">"افزودن"</string>
<string name="manage_users" msgid="1823875311934643849">"مدیریت کاربران"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"این اعلان از تنظیم کشیدن برای دو نیمه کردن صفحه پشتیبانی نمی‌کند."</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index c811d2251691..d1cdb9f0fb19 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Teksti kopioitu"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Kuva kopioitu"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Sisältö kopioitu"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Leikepöydän muokkaaja"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Leikepöytä"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Kuvan esikatselu"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"muokkaa"</string>
<string name="add" msgid="81036585205287996">"Lisää"</string>
<string name="manage_users" msgid="1823875311934643849">"Ylläpidä käyttäjiä"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Ilmoitus ei tue jaetulle näytölle vetämistä."</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 1c728869f102..db37f776688b 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Texte copié"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Image copiée"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Contenu copié"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Éditeur du presse-papiers"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Presse-papiers"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Aperçu de l\'image"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"modifier"</string>
<string name="add" msgid="81036585205287996">"Ajouter"</string>
<string name="manage_users" msgid="1823875311934643849">"Gérer les utilisateurs"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Cette notification ne prend pas en charge le partage d\'écran par glissement."</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index d0d781f867f5..dc708e8b8f1d 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Texte copié"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Image copiée"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Contenu copié"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Éditeur du presse-papiers"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Presse-papiers"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Aperçu de l\'image"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"modifier"</string>
<string name="add" msgid="81036585205287996">"Ajouter"</string>
<string name="manage_users" msgid="1823875311934643849">"Gérer les utilisateurs"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Impossible de faire glisser cette notification vers l\'écran partagé."</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 1718992e90fc..e64891850f44 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Texto copiado"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Imaxe copiada"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Contido copiado"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor do portapapeis"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Portapapeis"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Vista previa da imaxe"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"editar"</string>
<string name="add" msgid="81036585205287996">"Engadir"</string>
<string name="manage_users" msgid="1823875311934643849">"Xestionar usuarios"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Esta notificación non pode arrastrarse á pantalla dividida."</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 4fc38431ca15..c015403d52f1 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"કૅમેરા"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ફોન"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"વૉઇસ સહાય"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"વૉલેટ"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR કોડ સ્કૅનર"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"અનલૉક કરો"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"ડિવાઇસ લૉક કરેલું છે"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"ડેમો મોડ બતાવો"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"ઇથરનેટ"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"અલાર્મ"</string>
- <string name="wallet_title" msgid="5369767670735827105">"વૉલેટ"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"તમારા ફોન વડે વધુ ઝડપી તેમજ સુરક્ષિત ખરીદીઓ કરવાની રીત સેટઅપ કરી લો"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"બધું બતાવો"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"ખોલવા માટે ટૅપ કરો"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"ટેક્સ્ટ કૉપિ કરી"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"છબી કૉપિ કરી"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"કન્ટેન્ટ કૉપિ કર્યું"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"ક્લિપબોર્ડ એડિટર"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"ક્લિપબોર્ડ"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"છબીનો પ્રીવ્યૂ"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"ફેરફાર કરો"</string>
<string name="add" msgid="81036585205287996">"ઉમેરો"</string>
<string name="manage_users" msgid="1823875311934643849">"વપરાશકર્તાઓને મેનેજ કરો"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"આ નોટિફિકેશન તેને સ્પ્લિટસ્ક્રીનમાં ખેંચવાની સુવિધાને સપોર્ટ કરતું નથી."</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 440b3768a8ba..f2ff6d84dfbc 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"कैमरा"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"फ़ोन"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"आवाज़ से डिवाइस का इस्तेमाल"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"वॉलेट बटन"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"क्यूआर कोड स्कैनर"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"अनलॉक करें"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"डिवाइस लॉक है"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"डेमो मोड दिखाएं"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"ईथरनेट"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"अलार्म"</string>
- <string name="wallet_title" msgid="5369767670735827105">"वॉलेट"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"फ़ोन के ज़रिए तेज़ी से और सुरक्षित तरीके से खरीदारी करने के लिए सेट अप करें"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"सभी दिखाएं"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"अनलॉक करने के लिए टैप करें"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"टेक्स्ट कॉपी किया गया"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"इमेज कॉपी की गई"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"कॉन्टेंट कॉपी किया गया"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"क्लिपबोर्ड एडिटर"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"क्लिपबोर्ड"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"इमेज की झलक"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"बदलाव करें"</string>
<string name="add" msgid="81036585205287996">"जोड़ें"</string>
<string name="manage_users" msgid="1823875311934643849">"उपयोगकर्ताओं को मैनेज करें"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"इस सूचना को स्प्लिट स्क्रीन मोड में, खींचा और छोड़ा नहीं जा सकता."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 330363a8f713..e34a08e624af 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -465,7 +465,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"Prikaži demo način"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
- <string name="wallet_title" msgid="5369767670735827105">"Novčanik"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"Postavite aplikaciju za bržu i sigurniju kupnju telefonom"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Prikaži sve"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Dodirnite za otvaranje"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index c2e2acef73bf..271b1ebecb3c 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Szöveg másolva"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Kép másolva"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Tartalom másolva"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Vágólapszerkesztő"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Vágólap"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Kép előnézete"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"szerkesztés"</string>
<string name="add" msgid="81036585205287996">"Hozzáadás"</string>
<string name="manage_users" msgid="1823875311934643849">"Felhasználók kezelése"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Az értesítés nem támogatja a megosztott képernyőre való áthúzást."</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 6c9732175ccd..1c8a35140a6a 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Տեքստը պատճենվեց"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Պատկերը պատճենվեց"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Բովանդակությունը պատճենվեց"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Սեղմատախտակի խմբագրիչ"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Սեղմատախտակ"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Պատկերի նախադիտում"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"փոփոխել"</string>
<string name="add" msgid="81036585205287996">"Ավելացնել"</string>
<string name="manage_users" msgid="1823875311934643849">"Օգտատերերի կառավարում"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Այս ծանուցումը հնարավոր չէ քաշել տրոհված էկրանի մեկ հատվածից մյուսը։"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 0eb5ef3563c4..cf36c608e436 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Teks disalin"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Gambar disalin"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Konten disalin"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor Papan Klip"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Papan klip"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Pratinjau gambar"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"mengedit"</string>
<string name="add" msgid="81036585205287996">"Tambahkan"</string>
<string name="manage_users" msgid="1823875311934643849">"Kelola pengguna"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Notifikasi ini tidak mendukung fitur tarik ke Layar terpisah."</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 372dd1cb6c98..c786d0d79c06 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Texti afritaður"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Mynd afrituð"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Efni afritað"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Klippiborðsritill"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Klippiborð"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Forskoðun myndar"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"breyta"</string>
<string name="add" msgid="81036585205287996">"Bæta við"</string>
<string name="manage_users" msgid="1823875311934643849">"Stjórna notendum"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Þessi tilkynning styður ekki að draga yfir á skiptan skjá."</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index e0af9980d6c8..7065f7fcadeb 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Testo copiato"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Immagine copiata"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Contenuti copiati"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor di appunti"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Appunti"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Anteprima immagine"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"modificare"</string>
<string name="add" msgid="81036585205287996">"Aggiungi"</string>
<string name="manage_users" msgid="1823875311934643849">"Gestisci utenti"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Non è possibile trascinare questa notifica tra le due parti dello schermo diviso."</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 8b45531fc3e0..aa8f6cb3a895 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -468,7 +468,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"הצגת מצב הדגמה"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"אתרנט"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"התראה"</string>
- <string name="wallet_title" msgid="5369767670735827105">"ארנק"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"מגדירים אמצעי תשלום ונהנים מביצוע מהיר ומאובטח יותר של רכישות באמצעות הטלפון"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"הצגת הכול"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"יש להקיש לפתיחה"</string>
@@ -959,14 +959,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"הטקסט הועתק"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"התמונה הועתקה"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"התוכן הועתק"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"עורך הלוח"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"לוח"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"תצוגה מקדימה של תמונה"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"עריכה"</string>
<string name="add" msgid="81036585205287996">"הוספה"</string>
<string name="manage_users" msgid="1823875311934643849">"ניהול משתמשים"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"ההתראה הזו לא תומכת בגרירה למסך מפוצל."</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index b0171dec8195..20bdf5f87923 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Мәтін көшірілді."</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Сурет көшірілді."</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Мазмұн көшірілді."</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Буфер редакторы"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Буфер"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Суретті алдын ала көру"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"өзгерту"</string>
<string name="add" msgid="81036585205287996">"Қосу"</string>
<string name="manage_users" msgid="1823875311934643849">"Пайдаланушыларды басқару"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Бұл хабарландыруды бөлінген экранға сүйреп апару мүмкін емес."</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 9aacc3b88451..eb2f68d95173 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"បាន​ចម្លង​អត្ថបទ"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"បានចម្លង​រូបភាព"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"បានចម្លង​ខ្លឹមសារ"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"កម្មវិធី​​កែឃ្លីបបត"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"ឃ្លីបបត"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"​មើល​រូបភាព​សាកល្បង"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"កែ"</string>
<string name="add" msgid="81036585205287996">"បញ្ចូល"</string>
<string name="manage_users" msgid="1823875311934643849">"គ្រប់គ្រង​អ្នក​ប្រើប្រាស់"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"ការជូនដំណឹងនេះមិនអាចឱ្យអូសដើម្បីបំបែកអេក្រង់បានទេ។"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 6aef3bd5a165..8198d7f7bc99 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"ಕ್ಯಾಮರಾ"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ಫೋನ್"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ಧ್ವನಿ ಸಹಾಯಕ"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"ವಾಲೆಟ್"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR ಕೋಡ್ ಸ್ಕ್ಯಾನರ್"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"ಅನ್‌ಲಾಕ್"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"ಸಾಧನ ಲಾಕ್ ಆಗಿದೆ"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"ಪಠ್ಯವನ್ನು ನಕಲಿಸಲಾಗಿದೆ"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"ಚಿತ್ರವನ್ನು ನಕಲಿಸಲಾಗಿದೆ"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"ವಿಷಯವನ್ನು ನಕಲಿಸಲಾಗಿದೆ"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"ಕ್ಲಿಪ್‌ಬೋರ್ಡ್ ಎಡಿಟರ್"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"ಕ್ಲಿಪ್‌ಬೋರ್ಡ್"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"ಚಿತ್ರದ ಪೂರ್ವವೀಕ್ಷಣೆ"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"ಎಡಿಟ್ ಮಾಡಿ"</string>
<string name="add" msgid="81036585205287996">"ಸೇರಿಸಿ"</string>
<string name="manage_users" msgid="1823875311934643849">"ಬಳಕೆದಾರರನ್ನು ನಿರ್ವಹಿಸಿ"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್‌ಗೆ ಡ್ರ್ಯಾಗ್ ಮಾಡುವುದನ್ನು ಈ ಅಧಿಸೂಚನೆಯು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ."</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 899bca353b05..b14e9e8701e1 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"텍스트 복사됨"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"이미지 복사됨"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"콘텐츠 복사됨"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"클립보드 편집기"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"클립보드"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"이미지 미리보기"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"수정"</string>
<string name="add" msgid="81036585205287996">"추가"</string>
<string name="manage_users" msgid="1823875311934643849">"사용자 관리"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"드래그하여 화면을 분할하는 기능이 지원되지 않는 알림입니다."</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index deaeb431936b..11cdc7d7b6df 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"Демо режимин көрсөтүү"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Ойготкуч"</string>
- <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Капчык"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"Телефонуңуз менен тез жана коопсуз сатып алуу үчүн жөндөңүз"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Баарын көрсөтүү"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Ачуу үчүн таптап коюңуз"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Текст көчүрүлдү"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Сүрөт көчүрүлдү"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Мазмун көчүрүлдү"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Алмашуу буферин түзөткүч"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Алмашуу буфери"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Сүрөттү алдын ала көрүү"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"түзөтүү"</string>
<string name="add" msgid="81036585205287996">"Кошуу"</string>
<string name="manage_users" msgid="1823875311934643849">"Колдонуучуларды башкаруу"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Бул билдирмени бөлүнгөн экранда сүйрөөгө болбойт."</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 780e4c7f324b..cb86e04c2100 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"ກ້ອງ"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ໂທລະສັບ"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ຊ່ວຍ​ເຫຼືອ​ທາງ​ສຽງ"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"ກະເປົາ"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"ຕົວສະແກນລະຫັດ QR"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"ປົດລັອກ"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"ອຸປະກອນຖືກລັອກໄວ້"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"ສະ​ແດງ​ໂຫມດ​ສາ​ທິດ"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"ອີ​ເທ​ເນັດ"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"ໂມງປຸກ"</string>
- <string name="wallet_title" msgid="5369767670735827105">"ກະເປົາ"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"ຕັ້ງຄ່າເພື່ອຊື້ດ້ວຍໂທລະສັບຂອງທ່ານໄດ້ໄວຂຶ້ນ ແລະ ປອດໄພຂຶ້ນ"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"ສະແດງທັງໝົດ"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"ແຕະເພື່ອເປີດ"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"ສຳເນົາຂໍ້ຄວາມແລ້ວ"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"ສຳເນົາຮູບແລ້ວ"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"ສຳເນົາເນື້ອຫາແລ້ວ"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"ຕົວແກ້ໄຂຄລິບບອດ"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"​ຄລິບບອດ"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"ຕົວຢ່າງຮູບ"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"ແກ້ໄຂ"</string>
<string name="add" msgid="81036585205287996">"ເພີ່ມ"</string>
<string name="manage_users" msgid="1823875311934643849">"ຈັດການຜູ້ໃຊ້"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"ການແຈ້ງເຕືອນນີ້ບໍ່ຮອງຮັບການລາກໄປໃສ່ Splitscreen."</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index b4d5bcaaabd0..0df0af28b03d 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Fotoaparatas"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefonas"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"Piniginė"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR kodų skaitytuvas"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Atrakinti"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Įrenginys užrakintas"</string>
@@ -468,7 +468,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"Rodyti demonstraciniu režimu"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"Eternetas"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Signalas"</string>
- <string name="wallet_title" msgid="5369767670735827105">"Piniginė"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"Nustatykite, kad galėtumėte greičiau ir saugiau pirkti telefonu"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Rodyti viską"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Palieskite, kad atidarytumėte"</string>
@@ -959,14 +959,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Tekstas nukopijuotas"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Vaizdas nukopijuotas"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Turinys nukopijuotas"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Iškarpinės redagavimo priemonė"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Iškarpinė"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Vaizdo peržiūra"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"redaguoti"</string>
<string name="add" msgid="81036585205287996">"Pridėti"</string>
<string name="manage_users" msgid="1823875311934643849">"Tvarkyti naudotojus"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Šio pranešimo vilkimas išskaidyto ekrano režimu nepalaikomas."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index a74447a9d0aa..93824c823078 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -952,14 +952,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Teksts ir nokopēts"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Attēls ir nokopēts"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Saturs ir nokopēts"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Starpliktuves redaktors"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Starpliktuve"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Attēla priekšskatījums"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"rediģētu"</string>
<string name="add" msgid="81036585205287996">"Pievienot"</string>
<string name="manage_users" msgid="1823875311934643849">"Pārvaldīt lietotājus"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Šis paziņojums neatbalsta vilkšanu uz dalīto ekrānu."</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 68afb045b920..093b2a399ce5 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -402,7 +402,7 @@
<string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Вашиот администратор вклучил евиденција на мрежата, што подразбира следење на сообраќајот на вашиот уред."</string>
<string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Вашиот администратор вклучил мрежна евиденција, што подразбира следење на сообраќајот во работниот, но не и во личниот профил."</string>
<string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Уредов е поврзан на интернет преку <xliff:g id="VPN_APP">%1$s</xliff:g>. Вашата мрежна активност во работните апликации, вклучително е-пораките и податоците од прелистување, е видлива за вашиот IT-администратор."</string>
- <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Уредот е поврзан на интернет преку <xliff:g id="VPN_APP_0">%1$s</xliff:g> и <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Вашата мрежна активност во работните апликации, вклучително е-пораките и податоците од прелистување, е видлива за вашиот IT-администратор."</string>
+ <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Уредот е поврзан на интернет преку <xliff:g id="VPN_APP_0">%1$s</xliff:g> и <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Вашата мрежна активност, вклучително е-пораките и податоците од прелистување, е видлива за IT-администраторот."</string>
<string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Вашите работни апликации се поврзани на интернет преку <xliff:g id="VPN_APP">%1$s</xliff:g>. Вашата мрежна активност во работните апликации, вклучително е-пораките и податоците од прелистување, е видлива за вашиот IT-администратор и давател на услуги за VPN."</string>
<string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Вашите лични апликации се поврзани на интернет преку <xliff:g id="VPN_APP">%1$s</xliff:g>. Вашата мрежна активност во работните апликации, вклучително е-пораките и податоците од прелистување, е видлива за вашиот давател на услуги за VPN."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Текстот е копиран"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Сликата е копирана"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Содржините се копирани"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Уредувач на привремена меморија"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Привремена меморија"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Преглед на сликата"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"измени"</string>
<string name="add" msgid="81036585205287996">"Додај"</string>
<string name="manage_users" msgid="1823875311934643849">"Управувајте со корисниците"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Известувањево не поддржува влечење на поделен екран."</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index b453c8cd1d36..2fa1640a7aba 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Камер"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Утас"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Дуут туслах"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"Түрийвч"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR код сканнер"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Тайлах"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Төхөөрөмжийг түгжсэн"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"Демо горимыг харуулах"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"Этернет"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Сэрүүлэг"</string>
- <string name="wallet_title" msgid="5369767670735827105">"Түрийвч"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"Утсаараа илүү хурдан, аюулгүй худалдан авалт хийхийн тулд тохируулгыг авна уу"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Бүгдийг харуулах"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Нээх бол товшино уу"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 1d303eb0fb4e..835d08507c51 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"मजकूर कॉपी केला"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"इमेज कॉपी केली"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"आशय कॉपी केला"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"क्लिपबोर्ड संपादक"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"क्लिपबोर्ड"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"इमेजचे पूर्वावलोकन"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"संपादित करा"</string>
<string name="add" msgid="81036585205287996">"जोडा"</string>
<string name="manage_users" msgid="1823875311934643849">"वापरकर्ते व्यवस्‍थापित करा"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"ही सूचना स्प्लिटस्क्रीनवर ड्रॅग करण्याला सपोर्ट करत नाही."</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 778244331cf8..c4f30e5d6d0d 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Teks disalin"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Imej disalin"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Kandungan disalin"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor Papan Klip"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Papan klip"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Pratonton imej"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"edit"</string>
<string name="add" msgid="81036585205287996">"Tambah"</string>
<string name="manage_users" msgid="1823875311934643849">"Urus pengguna"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Pemberitahuan ini tidak menyokong penyeretan ke Skrin pisah."</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index ed509e231815..ae0eb50ab160 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -90,7 +90,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ဘယ်ဘက်အနားသတ် <xliff:g id="PERCENT">%1$d</xliff:g> ရာခိုင်နှုန်း"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ညာဘက်အနားသတ် <xliff:g id="PERCENT">%1$d</xliff:g> ရာခိုင်နှုန်း"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"ဖန်သားပြင် ရိုက်ကူးမှု"</string>
- <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ဖန်သားပြင်ရိုက်ကူးနေသည်"</string>
+ <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"စကရင်ရိုက်ကူးမှု အပြီးသတ်နေသည်"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ဖန်သားပြင် ရိုက်ကူးသည့် စက်ရှင်အတွက် ဆက်တိုက်လာနေသော အကြောင်းကြားချက်"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"စတင် ရိုက်ကူးမလား။"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"ရိုက်ကူးနေစဉ်အတွင်း Android စနစ်သည် သင့်ဖန်သားပြင်ပေါ်တွင် မြင်နိုင်သော (သို့) သင့်စက်ပစ္စည်းတွင် ဖွင့်ထားသော အရေးကြီးသည့် အချက်အလက်များကို ရိုက်ယူနိုင်သည်။ ၎င်းတွင် စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ ဓာတ်ပုံ၊ မက်ဆေ့ဂျ်နှင့် အသံများ ပါဝင်သည်။"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"စာသားကို မိတ္တူကူးပြီးပြီ"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"ပုံ ကူးပြီးပြီ"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"အကြောင်းအရာများကို ကူးယူပြီးပါပြီ"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"ကလစ်ဘုတ် တည်းဖြတ်စနစ်"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"ကလစ်ဘုတ်"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"ပုံအစမ်းကြည့်ခြင်း"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"တည်းဖြတ်ရန်"</string>
<string name="add" msgid="81036585205287996">"ထည့်ရန်"</string>
<string name="manage_users" msgid="1823875311934643849">"အသုံးပြုသူများ စီမံရန်"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"ဤအကြောင်းကြားချက်သည် ‘မျက်နှာပြင်ခွဲ၍ပြသမှု’ သို့ ဖိဆွဲခြင်းကို မပံ့ပိုးပါ။"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 5f3bc0a0e413..e6324f416ae9 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Teksten er kopiert"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Bildet er kopiert"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Innholdet er kopiert"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Utklippstavleredigerer"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Utklippstavle"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Forhåndsvisning av bilde"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"redigere"</string>
<string name="add" msgid="81036585205287996">"Legg til"</string>
<string name="manage_users" msgid="1823875311934643849">"Administrer brukere"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Dette varselet støtter ikke at du drar det til en delt skjerm."</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index c9c5b06c42f1..a18cae414c8c 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"क्यामेरा"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"फोन"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"आवाज सहायता"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"वालेट"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR कोड स्क्यानर"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"खोल्नुहोस्"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"यन्त्र लक गरिएको छ"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"डेमो मोड देखाउनुहोस्"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"इथरनेट"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"अलार्म"</string>
- <string name="wallet_title" msgid="5369767670735827105">"वालेट"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"फोनमार्फत अझ छिटो र थप सुरक्षित तरिकाले खरिद गर्न भुक्तानी विधि सेटअप गर्नुहोस्"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"सबै देखाइयोस्"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"खोल्न ट्याप गर्नुहोस्"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"टेक्स्ट कपी गरिएको छ"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"फोटो कपी गरिएको छ"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"सामग्री कपी गरिएको छ"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"क्लिपबोर्ड एडिटर"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"क्लिपबोर्ड"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"फोटोको प्रिभ्यू"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"सम्पादन गर्नुहोस्"</string>
<string name="add" msgid="81036585205287996">"हाल्नुहोस्"</string>
<string name="manage_users" msgid="1823875311934643849">"प्रयोगकर्ताहरूको व्यवस्थापन गर्नुहोस्"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"यो सूचना ड्र्याग गरेर स्प्लिटस्क्रिनमा लैजान मिल्दैन।"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 15d16152ac74..eaa4ca168e9c 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Tekst gekopieerd"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Afbeelding gekopieerd"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Content gekopieerd"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Klembordeditor"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Klembord"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Afbeeldingsvoorbeeld"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"bewerken"</string>
<string name="add" msgid="81036585205287996">"Toevoegen"</string>
<string name="manage_users" msgid="1823875311934643849">"Gebruikers beheren"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Deze melding biedt geen ondersteuning voor slepen naar het gesplitste scherm."</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index f5328302412d..99243d2e447d 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"ଟେକ୍ସଟ କପି କରାଯାଇଛି"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"ଇମେଜ କପି କରାଯାଇଛି"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"ବିଷୟବସ୍ତୁ କପି କରାଯାଇଛି"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"କ୍ଲିପବୋର୍ଡ ଏଡିଟର"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"କ୍ଲିପବୋର୍ଡ"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"ଇମେଜ ପ୍ରିଭ୍ୟୁ"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"ଏଡିଟ"</string>
<string name="add" msgid="81036585205287996">"ଯୋଗ କରନ୍ତୁ"</string>
<string name="manage_users" msgid="1823875311934643849">"ଉପଯୋଗକର୍ତ୍ତାମାନଙ୍କୁ ପରିଚାଳନା କରନ୍ତୁ"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"ଏହି ବିଜ୍ଞପ୍ତି ସ୍ପ୍ଲିଟସ୍କ୍ରିନକୁ ଡ୍ରାଗ କରିବାକୁ ସମର୍ଥନ କରେ ନାହିଁ।"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 60bc19eb47c1..a4631d8b1d36 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -959,14 +959,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Tekst został skopiowany"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Zdjęcie zostało skopiowane"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Treści zostały skopiowane"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Edytor schowka"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Schowek"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Podgląd obrazu"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"edytować"</string>
<string name="add" msgid="81036585205287996">"Dodaj"</string>
<string name="manage_users" msgid="1823875311934643849">"Zarządzaj użytkownikami"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"To powiadomienie nie obsługuje dzielenia ekranu przez przeciąganie."</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index cd69f86b107c..09591cb82d8c 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -384,8 +384,8 @@
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"A rede pode ser monitorada"</string>
<string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"Este dispositivo está conectado à Internet usando VPNs"</string>
<string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"Seus apps de trabalho estão conectados à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
- <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="451254750289172191">"Seus apps pessoais estão conectados à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
- <string name="quick_settings_disclosure_named_vpn" msgid="6191822916936028208">"Este dispositivo está conectado à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="451254750289172191">"Apps pessoais conectados à Internet via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="6191822916936028208">"Conectado à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_financed_device" msgid="3659962357973919387">"Este dispositivo é fornecido pela <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Gerenciamento de dispositivos"</string>
<string name="monitoring_subtitle_vpn" msgid="800485258004629079">"VPN"</string>
@@ -404,7 +404,7 @@
<string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Este dispositivo está conectado à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>. Suas atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o administrador de TI."</string>
<string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Seu dispositivo está conectado à Internet usando o <xliff:g id="VPN_APP_0">%1$s</xliff:g> e <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Suas atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o administrador de TI."</string>
<string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Seus apps de trabalho estão conectados à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>. Suas atividades de rede em apps de trabalho, incluindo e-mails e dados de navegação, estão visíveis para o administrador de TI e o provedor de VPN."</string>
- <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Seus apps pessoais estão conectados à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>. Suas atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o provedor de VPN."</string>
+ <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Seus apps pessoais estão conectados à Internet via <xliff:g id="VPN_APP">%1$s</xliff:g>. As atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o provedor de VPN."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
<string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Abrir configurações de VPN"</string>
<string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerenciado pelo seu pai/mãe, que pode ver e gerenciar informações como os apps que você usa, sua localização e seu tempo de uso."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index cd69f86b107c..09591cb82d8c 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -384,8 +384,8 @@
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"A rede pode ser monitorada"</string>
<string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"Este dispositivo está conectado à Internet usando VPNs"</string>
<string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"Seus apps de trabalho estão conectados à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
- <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="451254750289172191">"Seus apps pessoais estão conectados à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
- <string name="quick_settings_disclosure_named_vpn" msgid="6191822916936028208">"Este dispositivo está conectado à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="451254750289172191">"Apps pessoais conectados à Internet via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="6191822916936028208">"Conectado à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_financed_device" msgid="3659962357973919387">"Este dispositivo é fornecido pela <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Gerenciamento de dispositivos"</string>
<string name="monitoring_subtitle_vpn" msgid="800485258004629079">"VPN"</string>
@@ -404,7 +404,7 @@
<string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Este dispositivo está conectado à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>. Suas atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o administrador de TI."</string>
<string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Seu dispositivo está conectado à Internet usando o <xliff:g id="VPN_APP_0">%1$s</xliff:g> e <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Suas atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o administrador de TI."</string>
<string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Seus apps de trabalho estão conectados à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>. Suas atividades de rede em apps de trabalho, incluindo e-mails e dados de navegação, estão visíveis para o administrador de TI e o provedor de VPN."</string>
- <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Seus apps pessoais estão conectados à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>. Suas atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o provedor de VPN."</string>
+ <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Seus apps pessoais estão conectados à Internet via <xliff:g id="VPN_APP">%1$s</xliff:g>. As atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o provedor de VPN."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
<string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Abrir configurações de VPN"</string>
<string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerenciado pelo seu pai/mãe, que pode ver e gerenciar informações como os apps que você usa, sua localização e seu tempo de uso."</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 961798e67a3b..19a2bb9049e0 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -952,14 +952,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Textul a fost copiat"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Imaginea a fost copiată"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Conținutul a fost copiat"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor de clipboard"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Clipboard"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Previzualizarea imaginii"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"editați"</string>
<string name="add" msgid="81036585205287996">"Adăugați"</string>
<string name="manage_users" msgid="1823875311934643849">"Gestionați utilizatorii"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Notificarea nu acceptă tragerea pe ecranul împărțit."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index d08835750526..bd907ef52165 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -959,14 +959,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Текст скопирован"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Изображение скопировано"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Данные скопированы"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Редактор буфера обмена"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Буфер обмена"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Предварительный просмотр изображения"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"изменить"</string>
<string name="add" msgid="81036585205287996">"Добавить"</string>
<string name="manage_users" msgid="1823875311934643849">"Управление пользователями"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Это уведомление нельзя перетаскивать между частями разделенного экрана."</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 7d9944f8538d..13795a3975e4 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"පෙළ පිටපත් කරන ලදී"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"රූපය පිටපත් කරන ලදි"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"අන්තර්ගතය පිටපත් කරන ලදි"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"පසුරු පුවරු සංස්කාරක"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"පසුරු පුවරුව"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"රූප පෙරදසුන"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"සංස්කරණය"</string>
<string name="add" msgid="81036585205287996">"එක් කරන්න"</string>
<string name="manage_users" msgid="1823875311934643849">"පරිශීලකයන් කළමනාකරණය කරන්න"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"මෙම දැනුම්දීම බෙදුම් තිරය වෙත ඇද ගෙන යාමට සහාය නොදක්වයි."</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index a6868d59a3da..8ec4eefb0169 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -959,14 +959,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Besedilo je kopirano"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Slika je kopirana"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Vsebina je kopirana"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Urejevalnik odložišča"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Odložišče"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Predogled slike"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"urejanje"</string>
<string name="add" msgid="81036585205287996">"Dodaj"</string>
<string name="manage_users" msgid="1823875311934643849">"Upravljanje uporabnikov"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"To obvestilo ne podpira vlečenja v razdeljen zaslon."</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 2834960efff6..c6a06bbe01e5 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefoni"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ndihma zanore"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portofoli"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Skaneri i kodeve QR"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Shkyç"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Pajisja është e kyçur"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"Shfaq modalitetin e demonstrimit"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"Eternet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarmi"</string>
- <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Portofoli"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"Konfiguro për të kryer pagesa më të shpejta dhe më të sigurta përmes telefonit"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Shfaqi të gjitha"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Trokit për ta hapur"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Teksti u kopjua"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Imazhi u kopjua"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Përmbajtja u kopjua"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Modifikuesi i \"Kujtesës së fragmenteve\""</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Kujtesa e fragmenteve"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Pamja paraprake e imazhit"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"për të modifikuar"</string>
<string name="add" msgid="81036585205287996">"Shto"</string>
<string name="manage_users" msgid="1823875311934643849">"Menaxho përdoruesit"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Ky njoftim nuk mbështet zvarritjen në \"Ekranin e ndarë\"."</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index f0d7f840c7c5..50299de6051f 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -952,14 +952,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Текст је копиран"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Слика је копирана"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Садржај је копиран"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Уређивач привремене меморије"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Привремена меморија"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Преглед слике"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"измените"</string>
<string name="add" msgid="81036585205287996">"Додај"</string>
<string name="manage_users" msgid="1823875311934643849">"Управљаjте корисницима"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Ово обавештење не подржава превлачење на подељени екран."</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index c45b1e53e398..12bf290c9db2 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Texten har kopierats"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Bilden har kopierats"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Innehållet har kopierats"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Redigerare för urklipp"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Urklipp"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Bildförhandsgranskning"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"redigera"</string>
<string name="add" msgid="81036585205287996">"Lägg till"</string>
<string name="manage_users" msgid="1823875311934643849">"Hantera användare"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Det går inte att dra den här aviseringen till delad skärm."</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index c462c34e129e..25543fec8251 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Maandishi yamenakiliwa"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Picha imenakiliwa"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Maudhui yamenakiliwa"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Kihariri cha Ubao wa kunakili"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Ubao wa kunakili"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Onyesho la kukagua picha"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"ubadilishe"</string>
<string name="add" msgid="81036585205287996">"Weka"</string>
<string name="manage_users" msgid="1823875311934643849">"Dhibiti watumiaji"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Arifa hii hairuhusu kuburuta kwenye Skrini iliyogawanyika."</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 4423009beec0..f6cab3a8a62e 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"வார்த்தைகள் நகலெடுக்கப்பட்டன"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"படம் நகலெடுக்கப்பட்டது"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"உள்ளடக்கம் நகலெடுக்கப்பட்டது"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"கிளிப்போர்டு எடிட்டர்"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"கிளிப்போர்டு"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"படத்தின் மாதிரிக்காட்சி"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"திருத்தும்"</string>
<string name="add" msgid="81036585205287996">"சேர்"</string>
<string name="manage_users" msgid="1823875311934643849">"பயனர்களை நிர்வகித்தல்"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"பிரிக்கப்பட்ட திரைக்குள் இந்த அறிவிப்பை இழுத்துவிட முடியாது."</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index cfdddde650af..b841ef758ece 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"కెమెరా"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ఫోన్"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"వాయిస్ అసిస్టెంట్"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"వాలెట్"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR కోడ్ స్కానర్"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"అన్‌లాక్ చేయి"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"పరికరం లాక్ చేయబడింది"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"టెక్స్ట్ కాపీ చేయబడింది"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"ఇమేజ్ కాపీ చేయబడింది"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"కంటెంట్ కాపీ చేయబడింది"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"క్లిప్ బోర్డ్ ఎడిటర్"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"క్లిప్ బోర్డ్"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"ఇమేజ్ ప్రివ్యూ"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"ఎడిట్"</string>
<string name="add" msgid="81036585205287996">"జోడించండి"</string>
<string name="manage_users" msgid="1823875311934643849">"యూజర్‌లను మేనేజ్ చేయండి"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"ఈ నోటిఫికేషన్ స్ప్లిట్‌స్క్రీన్‌కు లాగడానికి సపోర్ట్ చేయదు."</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 385ee12d05aa..d4efc6372040 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -372,7 +372,7 @@
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"องค์กรของคุณเป็นเจ้าของอุปกรณ์นี้และอาจตรวจสอบการจราจรของข้อมูลในเครือข่าย"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> เป็นเจ้าของอุปกรณ์นี้และอาจตรวจสอบการจราจรของข้อมูลในเครือข่าย"</string>
<string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"อุปกรณ์นี้ให้บริการโดย <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
- <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"อุปกรณ์นี้เป็นขององค์กรและเชื่อมต่ออินเทอร์เน็ตผ่าน<xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"อุปกรณ์นี้เป็นขององค์กรและเชื่อมต่ออินเทอร์เน็ตผ่าน <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="quick_settings_disclosure_named_management_named_vpn" msgid="2169227918166358741">"อุปกรณ์นี้เป็นของ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> และเชื่อมต่ออินเทอร์เน็ตผ่าน<xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
<string name="quick_settings_disclosure_management" msgid="5515296598440684962">"องค์กรของคุณเป็นเจ้าของอุปกรณ์นี้"</string>
<string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> เป็นเจ้าของอุปกรณ์นี้"</string>
@@ -402,8 +402,8 @@
<string name="monitoring_description_management_network_logging" msgid="216983105036994771">"ผู้ดูแลระบบได้เปิดการบันทึกกิจกรรมของเครือข่าย ซึ่งจะตรวจสอบการรับส่งข้อมูลในอุปกรณ์ของคุณ"</string>
<string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"ผู้ดูแลระบบได้เปิดการบันทึกกิจกรรมของเครือข่าย ซึ่งจะตรวจสอบการรับส่งข้อมูลในโปรไฟล์งานแต่ไม่ตรวจสอบในโปรไฟล์ส่วนตัวของคุณ"</string>
<string name="monitoring_description_named_vpn" msgid="7502657784155456414">"อุปกรณ์นี้เชื่อมต่ออินเทอร์เน็ตผ่าน<xliff:g id="VPN_APP">%1$s</xliff:g> ผู้ดูแลระบบไอทีสามารถดูกิจกรรมที่คุณทำในเครือข่ายรวมถึงอีเมลและข้อมูลการท่องเว็บได้"</string>
- <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"อุปกรณ์นี้เชื่อมต่ออินเทอร์เน็ตผ่าน<xliff:g id="VPN_APP_0">%1$s</xliff:g> และ<xliff:g id="VPN_APP_1">%2$s</xliff:g> ผู้ดูแลระบบไอทีสามารถดูกิจกรรมที่คุณทำในเครือข่ายรวมถึงอีเมลและข้อมูลการท่องเว็บได้"</string>
- <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"แอปงานเชื่อมต่ออินเทอร์เน็ตผ่าน<xliff:g id="VPN_APP">%1$s</xliff:g> ผู้ดูแลระบบไอทีและผู้ให้บริการ VPN สามารถดูกิจกรรมที่คุณทำในเครือข่ายในแอปงานได้ ซึ่งรวมถึงอีเมลและข้อมูลการท่องเว็บ"</string>
+ <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"อุปกรณ์นี้เชื่อมต่ออินเทอร์เน็ตผ่าน <xliff:g id="VPN_APP_0">%1$s</xliff:g> และ <xliff:g id="VPN_APP_1">%2$s</xliff:g> ผู้ดูแลระบบไอทีสามารถดูกิจกรรมที่คุณทำในเครือข่าย ซึ่งรวมถึงอีเมลและข้อมูลการท่องเว็บได้"</string>
+ <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"แอปงานเชื่อมต่ออินเทอร์เน็ตผ่าน <xliff:g id="VPN_APP">%1$s</xliff:g> ผู้ดูแลระบบไอทีและผู้ให้บริการ VPN สามารถดูกิจกรรมที่คุณทำในเครือข่ายในแอปงานได้ ซึ่งรวมถึงอีเมลและข้อมูลการท่องเว็บ"</string>
<string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"แอปส่วนตัวเชื่อมต่ออินเทอร์เน็ตผ่าน<xliff:g id="VPN_APP">%1$s</xliff:g> ผู้ให้บริการ VPN สามารถดูกิจกรรมที่คุณทำในเครือข่ายซึ่งรวมถึงอีเมลและข้อมูลการท่องเว็บได้"</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
<string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"เปิดการตั้งค่า VPN"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"คัดลอกข้อความแล้ว"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"คัดลอกรูปภาพแล้ว"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"คัดลอกเนื้อหาแล้ว"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"เครื่องมือแก้ไขคลิปบอร์ด"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"คลิปบอร์ด"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"ตัวอย่างรูปภาพ"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"แก้ไข"</string>
<string name="add" msgid="81036585205287996">"เพิ่ม"</string>
<string name="manage_users" msgid="1823875311934643849">"จัดการผู้ใช้"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"การแจ้งเตือนนี้ไม่รองรับการลากเพื่อแบ่งหน้าจอ"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 6bf3d8fb7eec..6ed62f3e86ef 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Nakopya ang text"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Nakopya ang larawan"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Nakopya ang content"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor ng Clipboard"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Clipboard"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Preview ng larawan"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"i-edit"</string>
<string name="add" msgid="81036585205287996">"Magdagdag"</string>
<string name="manage_users" msgid="1823875311934643849">"Pamahalaan ang mga user"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Hindi sinusuportahan ng notification na ito ang pag-drag sa Splitscreen."</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 9d3c922787e4..e3182e00e921 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Metin kopyalandı"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Resim kopyalandı"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"İçerik kopyalandı"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Pano Düzenleyici"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Pano"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Resim önizleme"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"düzenleyin"</string>
<string name="add" msgid="81036585205287996">"Ekle"</string>
<string name="manage_users" msgid="1823875311934643849">"Kullanıcıları yönet"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Bu bildirim, bölünmüş ekrana sürüklenmeyi desteklemiyor."</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 6f365895e5a7..53b09091a5ce 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -959,14 +959,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Текст скопійовано"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Зображення скопійовано"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Вміст скопійовано"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Редактор буфера обміну"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Буфер обміну"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Попередній перегляд зображення"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"змінити"</string>
<string name="add" msgid="81036585205287996">"Додати"</string>
<string name="manage_users" msgid="1823875311934643849">"Керувати користувачами"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Це сповіщення не підтримує режим розділеного екрана."</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 90b7a2a8beda..81640392abd7 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"کیمرا"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"فون"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"صوتی معاون"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"والٹ"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"‏QR کوڈ اسکینر"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"غیر مقفل کریں"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"آلہ مقفل کر دیا گیا"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"ڈیمو موڈ دکھائیں"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"ایتھرنیٹ"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"الارم"</string>
- <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"والٹ"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"اپنے فون سے تیز تر مزید محفوظ خریداریاں کرنے کے لیے، سیٹ اپ مکمل کریں"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"سبھی دکھائیں"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"کھولنے کیلئے تھپتھپائیں"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"متن کاپی ہو گیا"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"تصویر کاپی ہو گئی"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"مواد کاپی ہو گیا"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"کلپ بورڈ ایڈیٹر"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"کلپ بورڈ"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"تصویر کا پیش منظر"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"ترمیم کریں"</string>
<string name="add" msgid="81036585205287996">"شامل کریں"</string>
<string name="manage_users" msgid="1823875311934643849">"صارفین کا نظم کریں"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"یہ اطلاع اسپلٹ اسکرین کو گھسیٹنے کو سپورٹ نہیں کرتا ہے۔"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 78203139cb9e..b115cfd36778 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Matndan nuxsa olindi"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Rasmdan nusxa olindi"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Kontentdan nusxa olindi."</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Vaqtinchalik xotira muharriri"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Vaqtinchalik xotira"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Rasmga razm solish"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"tahrir"</string>
<string name="add" msgid="81036585205287996">"Kiritish"</string>
<string name="manage_users" msgid="1823875311934643849">"Foydalanuvchilarni boshqarish"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Bu bildirishnoma ikkiga ajratilgan ekranda ishlamaydi."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 26f1ec06bd8d..976fa405e932 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"相机"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"电话"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"语音助理"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"电子钱包"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"钱包"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"二维码扫描器"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"解锁"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"设备已锁定"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"显示演示模式"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"以太网"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"闹钟"</string>
- <string name="wallet_title" msgid="5369767670735827105">"电子钱包"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"钱包"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"开始设置,享受更加快捷安全的手机购物体验"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"全部显示"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"点按即可打开"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"文本已复制"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"图片已复制"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"内容已复制"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"剪贴板编辑器"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"剪贴板"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"图片预览"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"修改"</string>
<string name="add" msgid="81036585205287996">"添加"</string>
<string name="manage_users" msgid="1823875311934643849">"管理用户"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"此通知不支持拖动到分屏中。"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index e1b340233a05..51670937d187 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"已複製文字"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"已複製圖片"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"已複製內容"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"剪貼簿編輯器"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"剪貼簿"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"圖像預覽"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"編輯"</string>
<string name="add" msgid="81036585205287996">"新增"</string>
<string name="manage_users" msgid="1823875311934643849">"管理使用者"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"此通知無法拖曳到分割螢幕中。"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 996cff4fe355..3d472196d67f 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"相機"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"電話"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"語音小幫手"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"電子錢包"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"錢包"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR 圖碼掃描器"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"解除鎖定"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"裝置已鎖定"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"顯示示範模式"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"乙太網路"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"鬧鐘"</string>
- <string name="wallet_title" msgid="5369767670735827105">"電子錢包"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"錢包"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"完成相關設定之後,就能以更快速安全的方式透過手機消費"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"顯示全部"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"輕觸即可開啟"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"已複製文字"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"已複製圖片"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"已複製內容"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"剪貼簿編輯器"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"剪貼簿"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"圖片預覽"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"編輯"</string>
<string name="add" msgid="81036585205287996">"新增"</string>
<string name="manage_users" msgid="1823875311934643849">"管理使用者"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"這項通知無法拖曳到分割畫面中。"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 74508bf08f7e..3e83354faa5c 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Umbhalo ukopishiwe"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Umfanekiso ukopishiwe"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Okuqukethwe kukopishiwe"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Umhleli Webhodi Lokunameka"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Ibhodi lokunamathisela"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Ukubuka kuqala kwesithombe"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"hlela"</string>
<string name="add" msgid="81036585205287996">"Faka"</string>
<string name="manage_users" msgid="1823875311934643849">"Phatha abasebenzisi"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Lesi saziso asikusekeli ukuhudulela ku-Splitscreen."</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
index 1142e05f4649..07733473f298 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
@@ -65,6 +65,12 @@ public class ThumbnailData {
snapshotId = 0;
}
+ public void recycleBitmap() {
+ if (thumbnail != null) {
+ thumbnail.recycle();
+ }
+ }
+
private static Bitmap makeThumbnail(TaskSnapshot snapshot) {
Bitmap thumbnail = null;
try (final HardwareBuffer buffer = snapshot.getHardwareBuffer()) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
index acd42228f4e2..362d7a9390d4 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
@@ -33,7 +33,14 @@ public interface TaskStackChangeListener {
// Main thread callbacks
default void onTaskStackChanged() { }
- default void onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) { }
+
+ /**
+ * @return whether the snapshot is consumed and the lifecycle of the snapshot extends beyond
+ * the lifecycle of this callback.
+ */
+ default boolean onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) {
+ return false;
+ }
default void onActivityPinned(String packageName, int userId, int taskId, int stackId) { }
default void onActivityUnpinned() { }
default void onActivityRestartAttempt(RunningTaskInfo task, boolean homeTaskVisible,
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index 2fd5aaefa34b..8af934f66b2a 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -294,8 +294,17 @@ public class TaskStackChangeListeners {
Trace.beginSection("onTaskSnapshotChanged");
final TaskSnapshot snapshot = (TaskSnapshot) msg.obj;
final ThumbnailData thumbnail = new ThumbnailData(snapshot);
+ boolean snapshotConsumed = false;
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onTaskSnapshotChanged(msg.arg1, thumbnail);
+ boolean consumed = mTaskStackListeners.get(i).onTaskSnapshotChanged(
+ msg.arg1, thumbnail);
+ snapshotConsumed |= consumed;
+ }
+ if (!snapshotConsumed) {
+ thumbnail.recycleBitmap();
+ if (snapshot.getHardwareBuffer() != null) {
+ snapshot.getHardwareBuffer().close();
+ }
}
Trace.endSection();
break;
diff --git a/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt b/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
index 8ab1ab79355f..34164f3b7306 100644
--- a/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
+++ b/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
@@ -87,20 +87,21 @@ open class DisplayCutoutBaseView : View, RegionInterceptableView {
fun onDisplayChanged(displayId: Int) {
val oldMode: Display.Mode? = displayMode
- displayMode = display.mode
+ val display: Display? = context.display
+ displayMode = display?.mode
- if (displayUniqueId != context.display?.uniqueId) {
- displayUniqueId = context.display?.uniqueId
+ if (displayUniqueId != display?.uniqueId) {
+ displayUniqueId = display?.uniqueId
shouldDrawCutout = DisplayCutout.getFillBuiltInDisplayCutout(
context.resources, displayUniqueId)
}
// Skip if display mode or cutout hasn't changed.
if (!displayModeChanged(oldMode, displayMode) &&
- display.cutout == displayInfo.displayCutout) {
+ display?.cutout == displayInfo.displayCutout) {
return
}
- if (displayId == display.displayId) {
+ if (displayId == display?.displayId) {
updateCutout()
updateProtectionBoundingPath()
onUpdate()
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 233f3648aeb3..6da2f50aac27 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -406,6 +406,15 @@ public class AuthContainerView extends LinearLayout
}
@Override
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ super.onWindowFocusChanged(hasWindowFocus);
+ if (!hasWindowFocus) {
+ Log.v(TAG, "Lost window focus, dismissing the dialog");
+ animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
+ }
+ }
+
+ @Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -720,7 +729,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_SUB_PANEL,
+ WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL,
windowFlags,
PixelFormat.TRANSLUCENT);
lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt
index 203578123999..4cd40d2f186b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt
@@ -15,11 +15,9 @@
*/
package com.android.systemui.biometrics
-import com.android.systemui.broadcast.BroadcastSender
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.phone.SystemUIDialogManager
-import com.android.systemui.statusbar.phone.panelstate.PanelExpansionListener
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager
/**
@@ -30,7 +28,6 @@ class UdfpsBpViewController(
statusBarStateController: StatusBarStateController,
panelExpansionStateManager: PanelExpansionStateManager,
systemUIDialogManager: SystemUIDialogManager,
- val broadcastSender: BroadcastSender,
dumpManager: DumpManager
) : UdfpsAnimationViewController<UdfpsBpView>(
view,
@@ -40,29 +37,4 @@ class UdfpsBpViewController(
dumpManager
) {
override val tag = "UdfpsBpViewController"
- private val bpPanelExpansionListener = PanelExpansionListener { event ->
- // Notification shade can be expanded but not visible (fraction: 0.0), for example
- // when a heads-up notification (HUN) is showing.
- notificationShadeVisible = event.expanded && event.fraction > 0f
- view.onExpansionChanged(event.fraction)
- cancelAuth()
- }
-
- fun cancelAuth() {
- if (shouldPauseAuth()) {
- broadcastSender.closeSystemDialogs()
- }
- }
-
- override fun onViewAttached() {
- super.onViewAttached()
-
- panelExpansionStateManager.addExpansionListener(bpPanelExpansionListener)
- }
-
- override fun onViewDetached() {
- super.onViewDetached()
-
- panelExpansionStateManager.removeExpansionListener(bpPanelExpansionListener)
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 903b3de0f444..6e2dcae4728e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -54,7 +54,6 @@ import com.android.internal.util.LatencyTracker;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.biometrics.dagger.BiometricsBackground;
-import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.DozeReceiver;
@@ -128,7 +127,6 @@ public class UdfpsController implements DozeReceiver {
@NonNull private final UnlockedScreenOffAnimationController
mUnlockedScreenOffAnimationController;
@NonNull private final LatencyTracker mLatencyTracker;
- @NonNull private final BroadcastSender mBroadcastSender;
@VisibleForTesting @NonNull final BiometricDisplayListener mOrientationListener;
@NonNull private final ActivityLaunchAnimator mActivityLaunchAnimator;
@@ -209,7 +207,7 @@ public class UdfpsController implements DozeReceiver {
mUnlockedScreenOffAnimationController, mHalControlsIllumination,
mHbmProvider, requestId, reason, callback,
(view, event, fromUdfpsView) -> onTouch(requestId, event,
- fromUdfpsView), mActivityLaunchAnimator, mBroadcastSender)));
+ fromUdfpsView), mActivityLaunchAnimator)));
}
@Override
@@ -606,7 +604,6 @@ public class UdfpsController implements DozeReceiver {
@NonNull LatencyTracker latencyTracker,
@NonNull ActivityLaunchAnimator activityLaunchAnimator,
@NonNull Optional<AlternateUdfpsTouchProvider> aternateTouchProvider,
- @NonNull BroadcastSender broadcastSender,
@BiometricsBackground Executor biometricsExecutor) {
mContext = context;
mExecution = execution;
@@ -637,7 +634,6 @@ public class UdfpsController implements DozeReceiver {
mLatencyTracker = latencyTracker;
mActivityLaunchAnimator = activityLaunchAnimator;
mAlternateTouchProvider = aternateTouchProvider.orElse(null);
- mBroadcastSender = broadcastSender;
mBiometricExecutor = biometricsExecutor;
mOrientationListener = new BiometricDisplayListener(
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
index 37db2bd51238..ec720579fbee 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
@@ -41,7 +41,6 @@ import androidx.annotation.LayoutRes
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.R
import com.android.systemui.animation.ActivityLaunchAnimator
-import com.android.systemui.broadcast.BroadcastSender
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.LockscreenShadeTransitionController
@@ -84,8 +83,7 @@ class UdfpsControllerOverlay(
@ShowReason val requestReason: Int,
private val controllerCallback: IUdfpsOverlayControllerCallback,
private val onTouch: (View, MotionEvent, Boolean) -> Boolean,
- private val activityLaunchAnimator: ActivityLaunchAnimator,
- private val broadcastSender: BroadcastSender
+ private val activityLaunchAnimator: ActivityLaunchAnimator
) {
/** The view, when [isShowing], or null. */
var overlayView: UdfpsView? = null
@@ -104,8 +102,8 @@ class UdfpsControllerOverlay(
fitInsetsTypes = 0
gravity = android.view.Gravity.TOP or android.view.Gravity.LEFT
layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
- flags = (Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS
- or WindowManager.LayoutParams.FLAG_SPLIT_TOUCH)
+ flags =
+ (Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS or WindowManager.LayoutParams.FLAG_SPLIT_TOUCH)
privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY
// Avoid announcing window title.
accessibilityTitle = " "
@@ -227,7 +225,6 @@ class UdfpsControllerOverlay(
statusBarStateController,
panelExpansionStateManager,
dialogManager,
- broadcastSender,
dumpManager
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index d63403033723..c686b48278a3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -216,13 +216,6 @@ class KeyguardUnlockAnimationController @Inject constructor(
*/
override fun setLauncherUnlockController(callback: ILauncherUnlockAnimationController?) {
launcherUnlockController = callback
-
- // If the provided callback dies, set it to null. We'll always check whether it's null
- // to avoid DeadObjectExceptions.
- callback?.asBinder()?.linkToDeath({
- launcherUnlockController = null
- launcherSmartspaceState = null
- }, 0 /* flags */)
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 80ad93fd84e7..3ad43ac32185 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -485,6 +485,8 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
*/
private IRemoteAnimationRunner mKeyguardExitAnimationRunner;
+ private CentralSurfaces mCentralSurfaces;
+
private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
new DeviceConfig.OnPropertiesChangedListener() {
@Override
@@ -845,6 +847,13 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
+ mOccluded);
}
+ @Override
+ public void onLaunchAnimationEnd(boolean launchIsFullScreen) {
+ if (launchIsFullScreen) {
+ mCentralSurfaces.instantCollapseNotificationPanel();
+ }
+ }
+
@NonNull
@Override
public ViewGroup getLaunchContainer() {
@@ -2846,6 +2855,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
@Nullable PanelExpansionStateManager panelExpansionStateManager,
BiometricUnlockController biometricUnlockController,
View notificationContainer, KeyguardBypassController bypassController) {
+ mCentralSurfaces = centralSurfaces;
mKeyguardViewControllerLazy.get().registerCentralSurfaces(
centralSurfaces,
panelView,
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index dea13251e100..33453a4c31d6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -677,6 +677,7 @@ public class MediaControlPanel {
scaleTransitionDrawableLayer(transitionDrawable, 1, width, height);
transitionDrawable.setLayerGravity(0, Gravity.CENTER);
transitionDrawable.setLayerGravity(1, Gravity.CENTER);
+ transitionDrawable.setCrossFadeEnabled(!isArtworkBound);
albumView.setImageDrawable(transitionDrawable);
transitionDrawable.startTransition(isArtworkBound ? 333 : 80);
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
index 360f86548e13..aeeef6b24a1c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
@@ -216,4 +216,20 @@ data class MediaDeviceData
/** Unique id for this device */
val id: String? = null
-)
+) {
+ /**
+ * Check whether [MediaDeviceData] objects are equal in all fields except the icon. The icon
+ * is ignored because it can change by reference frequently depending on the device type's
+ * implementation, but this is not usually relevant unless other info has changed
+ */
+ fun equalsWithoutIcon(other: MediaDeviceData?): Boolean {
+ if (other == null) {
+ return false
+ }
+
+ return enabled == other.enabled &&
+ name == other.name &&
+ intent == other.intent &&
+ id == other.id
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
index 8558859638d5..baed1c4286e9 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
@@ -155,8 +155,8 @@ class MediaDeviceManager @Inject constructor(
private var playbackType = PLAYBACK_TYPE_UNKNOWN
private var current: MediaDeviceData? = null
set(value) {
- val hasSameId = value?.id != null && value.id == field?.id
- if (!started || (!hasSameId && value != field)) {
+ val sameWithoutIcon = value != null && value.equalsWithoutIcon(field)
+ if (!started || !sameWithoutIcon) {
field = value
fgExecutor.execute {
processDevice(key, oldKey, value)
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index 24dfeafa0dec..f0ce30d2dc66 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -107,6 +107,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
@Override
void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin, int position) {
super.onBind(device, topMargin, bottomMargin, position);
+ boolean isMutingExpectedDeviceExist = mController.hasMutingExpectedDevice();
final boolean currentlyConnected = !mIncludeDynamicGroup
&& isCurrentlyConnected(device);
boolean isCurrentSeekbarInvisible = mSeekBar.getVisibility() == View.GONE;
@@ -146,7 +147,19 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
}
} else {
// Set different layout for each device
- if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
+ if (device.isMutingExpectedDevice()
+ && !mController.isCurrentConnectedDeviceRemote()) {
+ mTitleIcon.setImageDrawable(
+ mContext.getDrawable(R.drawable.media_output_icon_volume));
+ mTitleIcon.setColorFilter(mController.getColorItemContent());
+ mTitleText.setTextColor(mController.getColorItemContent());
+ setSingleLineLayout(getItemTitle(device), true /* bFocused */,
+ false /* showSeekBar */,
+ false /* showProgressBar */, false /* showStatus */);
+ initMutingExpectedDevice();
+ mCurrentActivePosition = position;
+ mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
+ } else if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
setUpDeviceIcon(device);
mStatusIcon.setImageDrawable(
mContext.getDrawable(R.drawable.media_output_status_failed));
@@ -193,17 +206,26 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
mEndTouchArea.setImportantForAccessibility(
View.IMPORTANT_FOR_ACCESSIBILITY_YES);
setUpContentDescriptionForView(mEndTouchArea, true, device);
- } else if (!mController.hasAdjustVolumeUserRestriction() && currentlyConnected) {
- mTitleIcon.setImageDrawable(
- mContext.getDrawable(R.drawable.media_output_icon_volume));
- mTitleIcon.setColorFilter(mController.getColorItemContent());
- mTitleText.setTextColor(mController.getColorItemContent());
- setSingleLineLayout(getItemTitle(device), true /* bFocused */,
- true /* showSeekBar */,
- false /* showProgressBar */, false /* showStatus */);
- initSeekbar(device, isCurrentSeekbarInvisible);
- setUpContentDescriptionForView(mContainerLayout, false, device);
- mCurrentActivePosition = position;
+ } else if (!mController.hasAdjustVolumeUserRestriction()
+ && currentlyConnected) {
+ if (isMutingExpectedDeviceExist
+ && !mController.isCurrentConnectedDeviceRemote()) {
+ // mark as disconnected and set special click listener
+ setUpDeviceIcon(device);
+ setSingleLineLayout(getItemTitle(device), false /* bFocused */);
+ mContainerLayout.setOnClickListener(v -> cancelMuteAwaitConnection());
+ } else {
+ mTitleIcon.setImageDrawable(
+ mContext.getDrawable(R.drawable.media_output_icon_volume));
+ mTitleIcon.setColorFilter(mController.getColorItemContent());
+ mTitleText.setTextColor(mController.getColorItemContent());
+ setSingleLineLayout(getItemTitle(device), true /* bFocused */,
+ true /* showSeekBar */,
+ false /* showProgressBar */, false /* showStatus */);
+ initSeekbar(device, isCurrentSeekbarInvisible);
+ setUpContentDescriptionForView(mContainerLayout, false, device);
+ mCurrentActivePosition = position;
+ }
} else if (isDeviceIncluded(mController.getSelectableMediaDevice(), device)) {
setUpDeviceIcon(device);
mCheckBox.setOnCheckedChangeListener(null);
@@ -269,6 +291,11 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
notifyDataSetChanged();
}
+ private void cancelMuteAwaitConnection() {
+ mController.cancelMuteAwaitConnection();
+ notifyDataSetChanged();
+ }
+
private void setUpContentDescriptionForView(View view, boolean clickable,
MediaDevice device) {
view.setClickable(clickable);
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
index b407e76f1b11..ccc0a3db0611 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
@@ -309,6 +309,17 @@ public abstract class MediaOutputBaseAdapter extends
});
}
+ void initMutingExpectedDevice() {
+ disableSeekBar();
+ final Drawable backgroundDrawable = mContext.getDrawable(
+ R.drawable.media_output_item_background_active)
+ .mutate();
+ backgroundDrawable.setColorFilter(
+ new PorterDuffColorFilter(mController.getColorConnectedItemBackground(),
+ PorterDuff.Mode.SRC_IN));
+ mItemLayout.setBackground(backgroundDrawable);
+ }
+
void initSessionSeekbar() {
disableSeekBar();
mSeekBar.setMax(mController.getSessionVolumeMax());
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt
index 31266b6dc8ec..38005db28cf6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt
@@ -17,6 +17,7 @@
package com.android.systemui.media.dialog
import android.content.Context
+import android.media.AudioManager
import android.media.session.MediaSessionManager
import android.view.View
import com.android.internal.logging.UiEventLogger
@@ -41,7 +42,8 @@ class MediaOutputBroadcastDialogFactory @Inject constructor(
private val notifCollection: CommonNotifCollection,
private val uiEventLogger: UiEventLogger,
private val dialogLaunchAnimator: DialogLaunchAnimator,
- private val nearbyMediaDevicesManagerOptional: Optional<NearbyMediaDevicesManager>
+ private val nearbyMediaDevicesManagerOptional: Optional<NearbyMediaDevicesManager>,
+ private val audioManager: AudioManager
) {
var mediaOutputBroadcastDialog: MediaOutputBroadcastDialog? = null
@@ -52,7 +54,7 @@ class MediaOutputBroadcastDialogFactory @Inject constructor(
val controller = MediaOutputController(context, packageName,
mediaSessionManager, lbm, starter, notifCollection,
- dialogLaunchAnimator, nearbyMediaDevicesManagerOptional)
+ dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager)
val dialog =
MediaOutputBroadcastDialog(context, aboveStatusBar, broadcastSender, controller)
mediaOutputBroadcastDialog = dialog
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index 9329b1bfc2a3..42e9af846322 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -34,6 +34,7 @@ import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
+import android.media.AudioManager;
import android.media.INearbyMediaDevicesUpdateCallback;
import android.media.MediaMetadata;
import android.media.MediaRoute2Info;
@@ -112,6 +113,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
@VisibleForTesting
final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
final List<MediaDevice> mCachedMediaDevices = new CopyOnWriteArrayList<>();
+ private final AudioManager mAudioManager;
private final NearbyMediaDevicesManager mNearbyMediaDevicesManager;
private final Map<String, Integer> mNearbyDeviceInfoMap = new ConcurrentHashMap<>();
@@ -122,7 +124,6 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
Callback mCallback;
@VisibleForTesting
LocalMediaManager mLocalMediaManager;
-
private MediaOutputMetricLogger mMetricLogger;
private int mColorItemContent;
@@ -145,13 +146,15 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
lbm, ActivityStarter starter,
CommonNotifCollection notifCollection,
DialogLaunchAnimator dialogLaunchAnimator,
- Optional<NearbyMediaDevicesManager> nearbyMediaDevicesManagerOptional) {
+ Optional<NearbyMediaDevicesManager> nearbyMediaDevicesManagerOptional,
+ AudioManager audioManager) {
mContext = context;
mPackageName = packageName;
mMediaSessionManager = mediaSessionManager;
mLocalBluetoothManager = lbm;
mActivityStarter = starter;
mNotifCollection = notifCollection;
+ mAudioManager = audioManager;
InfoMediaManager imm = new InfoMediaManager(mContext, packageName, null, lbm);
mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName);
mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName);
@@ -217,14 +220,14 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
return false;
}
- void setRefreshing(boolean refreshing) {
- mIsRefreshing = refreshing;
- }
-
boolean isRefreshing() {
return mIsRefreshing;
}
+ void setRefreshing(boolean refreshing) {
+ mIsRefreshing = refreshing;
+ }
+
void stop() {
if (mMediaController != null) {
mMediaController.unregisterCallback(mCb);
@@ -275,6 +278,27 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
mMetricLogger.logOutputFailure(new ArrayList<>(mMediaDevices), reason);
}
+ /**
+ * Checks if there's any muting expected device exist
+ */
+ public boolean hasMutingExpectedDevice() {
+ return mAudioManager.getMutingExpectedDevice() != null;
+ }
+
+ /**
+ * Cancels mute await connection action in follow up request
+ */
+ public void cancelMuteAwaitConnection() {
+ if (mAudioManager.getMutingExpectedDevice() == null) {
+ return;
+ }
+ try {
+ mAudioManager.cancelMuteAwaitConnection(mAudioManager.getMutingExpectedDevice());
+ } catch (Exception e) {
+ Log.d(TAG, "Unable to cancel mute await connection");
+ }
+ }
+
Drawable getAppSourceIcon() {
if (mPackageName.isEmpty()) {
return null;
@@ -471,12 +495,26 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
// For the first time building list, to make sure the top device is the connected
// device.
if (mMediaDevices.isEmpty()) {
- final MediaDevice connectedMediaDevice = getCurrentConnectedMediaDevice();
+ boolean needToHandleMutingExpectedDevice =
+ hasMutingExpectedDevice() && !isCurrentConnectedDeviceRemote();
+ final MediaDevice connectedMediaDevice =
+ needToHandleMutingExpectedDevice ? null
+ : getCurrentConnectedMediaDevice();
if (connectedMediaDevice == null) {
if (DEBUG) {
- Log.d(TAG, "No connected media device.");
+ Log.d(TAG, "No connected media device or muting expected device exist.");
+ }
+ if (needToHandleMutingExpectedDevice) {
+ for (MediaDevice device : devices) {
+ if (device.isMutingExpectedDevice()) {
+ mMediaDevices.add(0, device);
+ } else {
+ mMediaDevices.add(device);
+ }
+ }
+ } else {
+ mMediaDevices.addAll(devices);
}
- mMediaDevices.addAll(devices);
return;
}
for (MediaDevice device : devices) {
@@ -516,6 +554,12 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
}
+ boolean isCurrentConnectedDeviceRemote() {
+ MediaDevice currentConnectedMediaDevice = getCurrentConnectedMediaDevice();
+ return currentConnectedMediaDevice != null && isActiveRemoteDevice(
+ currentConnectedMediaDevice);
+ }
+
List<MediaDevice> getGroupMediaDevices() {
final List<MediaDevice> selectedDevices = getSelectedMediaDevice();
final List<MediaDevice> selectableDevices = getSelectableMediaDevice();
@@ -731,7 +775,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
void launchMediaOutputBroadcastDialog(View mediaOutputDialog, BroadcastSender broadcastSender) {
MediaOutputController controller = new MediaOutputController(mContext, mPackageName,
mMediaSessionManager, mLocalBluetoothManager, mActivityStarter,
- mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager));
+ mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager),
+ mAudioManager);
MediaOutputBroadcastDialog dialog = new MediaOutputBroadcastDialog(mContext, true,
broadcastSender, controller);
mDialogLaunchAnimator.showFromView(dialog, mediaOutputDialog);
@@ -887,8 +932,9 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
}
boolean isVolumeControlEnabled(@NonNull MediaDevice device) {
- return isPlayBackInfoLocal()
- || device.getDeviceType() != MediaDevice.MediaDeviceType.TYPE_CAST_GROUP_DEVICE;
+ return (isPlayBackInfoLocal()
+ || device.getDeviceType() != MediaDevice.MediaDeviceType.TYPE_CAST_GROUP_DEVICE)
+ && !device.isVolumeFixed();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
index 0d7d60ac5923..36a46f067fb0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
@@ -17,6 +17,7 @@
package com.android.systemui.media.dialog
import android.content.Context
+import android.media.AudioManager
import android.media.session.MediaSessionManager
import android.view.View
import com.android.internal.logging.UiEventLogger
@@ -41,7 +42,8 @@ class MediaOutputDialogFactory @Inject constructor(
private val notifCollection: CommonNotifCollection,
private val uiEventLogger: UiEventLogger,
private val dialogLaunchAnimator: DialogLaunchAnimator,
- private val nearbyMediaDevicesManagerOptional: Optional<NearbyMediaDevicesManager>
+ private val nearbyMediaDevicesManagerOptional: Optional<NearbyMediaDevicesManager>,
+ private val audioManager: AudioManager
) {
companion object {
var mediaOutputDialog: MediaOutputDialog? = null
@@ -54,7 +56,7 @@ class MediaOutputDialogFactory @Inject constructor(
val controller = MediaOutputController(context, packageName,
mediaSessionManager, lbm, starter, notifCollection,
- dialogLaunchAnimator, nearbyMediaDevicesManagerOptional)
+ dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager)
val dialog =
MediaOutputDialog(context, aboveStatusBar, broadcastSender, controller, uiEventLogger)
mediaOutputDialog = dialog
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 9de132f64d0b..41724ef62683 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -151,15 +151,17 @@ public class QSPanel extends LinearLayout implements Tunable {
mHorizontalContentContainer.setClipChildren(true);
mHorizontalContentContainer.setClipToPadding(false);
// Don't clip on the top, that way, secondary pages tiles can animate up
+ // Clipping coordinates should be relative to this view, not absolute (parent coordinates)
mHorizontalContentContainer.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
- if (left != oldLeft || right != oldRight || bottom != oldBottom) {
- mClippingRect.left = left;
- mClippingRect.right = right;
- mClippingRect.bottom = bottom;
+ if ((right - left) != (oldRight - oldLeft)
+ || ((bottom - top) != (oldBottom - oldTop))) {
+ mClippingRect.right = right - left;
+ mClippingRect.bottom = bottom - top;
mHorizontalContentContainer.setClipBounds(mClippingRect);
}
});
+ mClippingRect.left = 0;
mClippingRect.top = -1000;
mHorizontalContentContainer.setClipBounds(mClippingRect);
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 8ce422ac93f8..5b6e5ce95b14 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -83,6 +83,8 @@ import android.view.accessibility.AccessibilityManager;
import android.widget.Toast;
import android.window.WindowContext;
+import androidx.concurrent.futures.CallbackToFutureAdapter;
+
import com.android.internal.app.ChooserActivity;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.policy.PhoneWindow;
@@ -254,7 +256,7 @@ public class ScreenshotController {
private final WindowManager mWindowManager;
private final WindowManager.LayoutParams mWindowLayoutParams;
private final AccessibilityManager mAccessibilityManager;
- private final MediaPlayer mCameraSound;
+ private final ListenableFuture<MediaPlayer> mCameraSound;
private final ScrollCaptureClient mScrollCaptureClient;
private final PhoneWindow mWindow;
private final DisplayManager mDisplayManager;
@@ -338,13 +340,7 @@ public class ScreenshotController {
reloadAssets();
// Setup the Camera shutter sound
- mCameraSound = MediaPlayer.create(mContext,
- Uri.fromFile(new File(mContext.getResources().getString(
- com.android.internal.R.string.config_cameraShutterSound))), null,
- new AudioAttributes.Builder()
- .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
- .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
- .build(), AudioSystem.newAudioSessionId());
+ mCameraSound = loadCameraSound();
mCopyBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -442,16 +438,32 @@ public class ScreenshotController {
return mScreenshotView.isPendingSharedTransition();
}
+ // Any cleanup needed when the service is being destroyed.
+ void onDestroy() {
+ removeWindow();
+ releaseMediaPlayer();
+ releaseContext();
+ mBgExecutor.shutdownNow();
+ }
+
/**
* Release the constructed window context.
*/
- void releaseContext() {
+ private void releaseContext() {
mContext.unregisterReceiver(mCopyBroadcastReceiver);
mContext.release();
- if (mCameraSound != null) {
- mCameraSound.release();
+ }
+
+ private void releaseMediaPlayer() {
+ // Note that this may block if the sound is still being loaded (very unlikely) but we can't
+ // reliably release in the background because the service is being destroyed.
+ try {
+ MediaPlayer player = mCameraSound.get();
+ if (player != null) {
+ player.release();
+ }
+ } catch (InterruptedException | ExecutionException e) {
}
- mBgExecutor.shutdownNow();
}
/**
@@ -822,15 +834,42 @@ public class ScreenshotController {
}
}
+ private ListenableFuture<MediaPlayer> loadCameraSound() {
+ // The media player creation is slow and needs on the background thread.
+ return CallbackToFutureAdapter.getFuture((completer) -> {
+ mBgExecutor.execute(() -> {
+ MediaPlayer player = MediaPlayer.create(mContext,
+ Uri.fromFile(new File(mContext.getResources().getString(
+ com.android.internal.R.string.config_cameraShutterSound))), null,
+ new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+ .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ .build(), AudioSystem.newAudioSessionId());
+ completer.set(player);
+ });
+ return "ScreenshotController#loadCameraSound";
+ });
+ }
+
+ private void playCameraSound() {
+ mCameraSound.addListener(() -> {
+ try {
+ MediaPlayer player = mCameraSound.get();
+ if (player != null) {
+ player.start();
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ }
+ }, mBgExecutor);
+ }
+
/**
* Save the bitmap but don't show the normal screenshot UI.. just a toast (or notification on
* failure).
*/
private void saveScreenshotAndToast(Consumer<Uri> finisher) {
// Play the shutter sound to notify that we've taken a screenshot
- if (mCameraSound != null) {
- mCameraSound.start();
- }
+ playCameraSound();
saveScreenshotInWorkerThread(
/* onComplete */ finisher,
@@ -864,9 +903,7 @@ public class ScreenshotController {
mScreenshotView.createScreenshotDropInAnimation(screenRect, showFlash);
// Play the shutter sound to notify that we've taken a screenshot
- if (mCameraSound != null) {
- mCameraSound.start();
- }
+ playCameraSound();
if (DEBUG_ANIM) {
Log.d(TAG, "starting post-screenshot animation");
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
index 90e7631b4b03..32d82037efb9 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -153,8 +153,7 @@ public class TakeScreenshotService extends Service {
public void onDestroy() {
super.onDestroy();
if (mScreenshot != null) {
- mScreenshot.removeWindow();
- mScreenshot.releaseContext();
+ mScreenshot.onDestroy();
mScreenshot = null;
}
if (DEBUG_SERVICE) {
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
index c7a8fa22d1af..5e908d9cd29f 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
@@ -46,6 +46,8 @@ interface UserTracker : UserContentResolverProvider, UserContextProvider {
/**
* List of profiles associated with the current user.
+ *
+ * Quiet work profiles will still appear here, but will have the `QUIET_MODE` flag.
*/
val userProfiles: List<UserInfo>
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
index 80d5f1681a79..47bed461e371 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -108,8 +108,12 @@ class UserTrackerImpl internal constructor(
val filter = IntentFilter().apply {
addAction(Intent.ACTION_USER_SWITCHED)
+ // These get called when a managed profile goes in or out of quiet mode.
addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE)
+ addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)
+
addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED)
+ addAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED)
}
context.registerReceiverForAllUsers(this, filter, null /* permission */, backgroundHandler)
@@ -121,7 +125,10 @@ class UserTrackerImpl internal constructor(
Intent.ACTION_USER_SWITCHED -> {
handleSwitchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL))
}
- Intent.ACTION_MANAGED_PROFILE_AVAILABLE, Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE -> {
+ Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
+ Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
+ Intent.ACTION_MANAGED_PROFILE_REMOVED,
+ Intent.ACTION_MANAGED_PROFILE_UNLOCKED -> {
handleProfilesChanged()
}
}
@@ -208,7 +215,7 @@ class UserTrackerImpl internal constructor(
pw.println("Initialized: $initialized")
if (initialized) {
pw.println("userId: $userId")
- val ids = userProfiles.map { it.id }
+ val ids = userProfiles.map { it.toFullString() }
pw.println("userProfiles: $ids")
}
val list = synchronized(callbacks) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index a8d685229b32..126a986ee5f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -265,12 +265,12 @@ class NotificationWakeUpCoordinator @Inject constructor(
}
override fun onStateChanged(newState: Int) {
- if (screenOffAnimationController.overrideNotificationsFullyDozingOnKeyguard() &&
- state == StatusBarState.KEYGUARD &&
- newState == StatusBarState.SHADE) {
- // If we're animating the screen off and going from KEYGUARD back to SHADE, the
- // animation was cancelled and we are unlocking. Override the doze amount to 0f (not
- // dozing) so that the notifications are no longer hidden.
+ if (state == StatusBarState.SHADE && newState == StatusBarState.SHADE) {
+ // The SHADE -> SHADE transition is only possible as part of cancelling the screen-off
+ // animation (e.g. by fingerprint unlock). This is done because the system is in an
+ // undefined state, so it's an indication that we should do state cleanup. We override
+ // the doze amount to 0f (not dozing) so that the notifications are no longer hidden.
+ // See: UnlockedScreenOffAnimationController.onFinishedWakingUp()
setDozeAmount(0f, 0f)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 4fc347a09292..aedbd1b56622 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -158,13 +158,6 @@ public final class NotificationEntry extends ListEntry {
private long initializationTime = -1;
/**
- * Whether or not this row represents a system notification. Note that if this is
- * {@code null}, that means we were either unable to retrieve the info or have yet to
- * retrieve the info.
- */
- public Boolean mIsSystemNotification;
-
- /**
* Has the user sent a reply through this Notification.
*/
private boolean hasSentReply;
@@ -777,12 +770,28 @@ public final class NotificationEntry extends ListEntry {
if (mSbn.getNotification().isMediaNotification()) {
return true;
}
- if (mIsSystemNotification != null && mIsSystemNotification) {
+ if (!isBlockable()) {
return true;
}
return false;
}
+ /**
+ * Returns whether this row is considered blockable (i.e. it's not a system notif
+ * or is not in an allowList).
+ */
+ public boolean isBlockable() {
+ if (getChannel() == null) {
+ return false;
+ }
+ if (getChannel().isImportanceLockedByCriticalDeviceFunction()
+ && !getChannel().isBlockable()) {
+ return false;
+ }
+
+ return true;
+ }
+
private boolean shouldSuppressVisualEffect(int effect) {
if (isExemptFromDndVisualSuppression()) {
return false;
@@ -858,15 +867,6 @@ public final class NotificationEntry extends ListEntry {
}
/**
- * Whether or not this row represents a system notification. Note that if this is
- * {@code null}, that means we were either unable to retrieve the info or have yet to
- * retrieve the info.
- */
- public Boolean isSystemNotification() {
- return mIsSystemNotification;
- }
-
- /**
* Set this notification to be sensitive.
*
* @param sensitive true if the content of this notification is sensitive right now
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
index aac5b8d6b2eb..ff1c70ca740b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
@@ -41,6 +41,7 @@ public class KeyguardCoordinator implements Coordinator {
private final HighPriorityProvider mHighPriorityProvider;
private final SectionHeaderVisibilityProvider mSectionHeaderVisibilityProvider;
private final KeyguardNotificationVisibilityProvider mKeyguardNotificationVisibilityProvider;
+ private final SharedCoordinatorLogger mLogger;
@Inject
public KeyguardCoordinator(
@@ -48,12 +49,14 @@ public class KeyguardCoordinator implements Coordinator {
KeyguardUpdateMonitor keyguardUpdateMonitor,
HighPriorityProvider highPriorityProvider,
SectionHeaderVisibilityProvider sectionHeaderVisibilityProvider,
- KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider) {
+ KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider,
+ SharedCoordinatorLogger logger) {
mStatusBarStateController = statusBarStateController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mHighPriorityProvider = highPriorityProvider;
mSectionHeaderVisibilityProvider = sectionHeaderVisibilityProvider;
mKeyguardNotificationVisibilityProvider = keyguardNotificationVisibilityProvider;
+ mLogger = logger;
}
@Override
@@ -81,6 +84,7 @@ public class KeyguardCoordinator implements Coordinator {
}
private void invalidateListFromFilter(String reason) {
+ mLogger.logKeyguardCoordinatorInvalidated(reason);
updateSectionHeadersVisibility();
mNotifFilter.invalidateList();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SharedCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SharedCoordinatorLogger.kt
index c85fc1efee95..25bc641f0a84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SharedCoordinatorLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SharedCoordinatorLogger.kt
@@ -35,4 +35,12 @@ class SharedCoordinatorLogger @Inject constructor(
"Current user or profiles changed. Current user is $int1; profiles are $str1"
})
}
+
+ fun logKeyguardCoordinatorInvalidated(reason: String) {
+ buffer.log("KeyguardCoordinator", LogLevel.DEBUG, {
+ str1 = reason
+ }, {
+ "KeyguardCoordinator invalidated: $str1"
+ })
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt
index a0c39c6daab4..fd5bae151550 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt
@@ -16,15 +16,13 @@
package com.android.systemui.statusbar.notification.collection.provider
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.content.IntentFilter
import android.os.Build
import android.util.Log
import com.android.systemui.Dumpable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.commandline.Command
+import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.util.Assert
import com.android.systemui.util.ListenerSet
@@ -39,20 +37,19 @@ import javax.inject.Inject
* The only configuration is a list of allowed packages. When this list is empty, the feature is
* disabled. When SystemUI starts up, this feature is disabled.
*
- * To enabled filtering, provide the list of packages in a comma-separated list using the command:
+ * To enabled filtering, provide the space-separated list of packages using the command:
*
- * `$ adb shell am broadcast -a com.android.systemui.action.SET_NOTIF_DEBUG_MODE
- * --esal allowed_packages <comma-separated-packages>`
+ * `$ adb shell cmd statusbar notif-filter allowed-pkgs <package> ...`
*
- * To disable filtering, send the action without a list:
+ * To disable filtering, send the command without any packages, or explicitly reset:
*
- * `$ adb shell am broadcast -a com.android.systemui.action.SET_NOTIF_DEBUG_MODE`
+ * `$ adb shell cmd statusbar notif-filter reset`
*
* NOTE: this feature only works on debug builds, and when the broadcaster is root.
*/
@SysUISingleton
class DebugModeFilterProvider @Inject constructor(
- private val context: Context,
+ private val commandRegistry: CommandRegistry,
dumpManager: DumpManager
) : Dumpable {
private var allowedPackages: List<String> = emptyList()
@@ -74,10 +71,8 @@ class DebugModeFilterProvider @Inject constructor(
val needsInitialization = listeners.isEmpty()
listeners.addIfAbsent(listener)
if (needsInitialization) {
- val filter = IntentFilter().apply { addAction(ACTION_SET_NOTIF_DEBUG_MODE) }
- val permission = NOTIF_DEBUG_MODE_PERMISSION
- context.registerReceiver(mReceiver, filter, permission, null, Context.RECEIVER_EXPORTED)
- Log.d(TAG, "Registered: $mReceiver")
+ commandRegistry.registerCommand("notif-filter") { NotifFilterCommand() }
+ Log.d(TAG, "Registered notif-filter command")
}
}
@@ -100,30 +95,49 @@ class DebugModeFilterProvider @Inject constructor(
}
}
- private val mReceiver: BroadcastReceiver = object : BroadcastReceiver() {
- override fun onReceive(context: Context, intent: Intent?) {
- val action = intent?.action
- if (ACTION_SET_NOTIF_DEBUG_MODE == action) {
- // TODO(b/235268992) remove
- Log.d(TAG, "ACTION_SET_NOTIF_DEBUG_MODE enter")
- allowedPackages = intent.extras?.getStringArrayList(EXTRA_ALLOWED_PACKAGES)
- ?: emptyList()
- Log.d(TAG, "Updated allowedPackages: $allowedPackages")
- listeners.forEach(Runnable::run)
- // TODO(b/235268992) remove
- Log.d(TAG, "ACTION_SET_NOTIF_DEBUG_MODE leave")
+ companion object {
+ private const val TAG = "DebugModeFilterProvider"
+ }
+
+ inner class NotifFilterCommand : Command {
+ override fun execute(pw: PrintWriter, args: List<String>) {
+ when (args.firstOrNull()) {
+ "reset" -> {
+ if (args.size > 1) {
+ return invalidCommand(pw, "Unexpected arguments for 'reset' command")
+ }
+ allowedPackages = emptyList()
+ }
+ "allowed-pkgs" -> {
+ allowedPackages = args.drop(1)
+ }
+ null -> return invalidCommand(pw, "Missing command")
+ else -> return invalidCommand(pw, "Unknown command: ${args.firstOrNull()}")
+ }
+ Log.d(TAG, "Updated allowedPackages: $allowedPackages")
+ if (allowedPackages.isEmpty()) {
+ pw.print("Resetting allowedPackages ... ")
} else {
- Log.d(TAG, "Malformed intent: $intent")
+ pw.print("Updating allowedPackages: $allowedPackages ... ")
}
+ listeners.forEach(Runnable::run)
+ pw.println("DONE")
}
- }
- companion object {
- private const val TAG = "DebugModeFilterProvider"
- private const val ACTION_SET_NOTIF_DEBUG_MODE =
- "com.android.systemui.action.SET_NOTIF_DEBUG_MODE"
- private const val NOTIF_DEBUG_MODE_PERMISSION =
- "com.android.systemui.permission.NOTIF_DEBUG_MODE"
- private const val EXTRA_ALLOWED_PACKAGES = "allowed_packages"
+ private fun invalidCommand(pw: PrintWriter, reason: String) {
+ pw.println("Error: $reason")
+ pw.println()
+ help(pw)
+ }
+
+ override fun help(pw: PrintWriter) {
+ pw.println("Usage: adb shell cmd statusbar notif-filter <command>")
+ pw.println("Available commands:")
+ pw.println(" reset")
+ pw.println(" Restore the default system behavior.")
+ pw.println(" allowed-pkgs <package> ...")
+ pw.println(" Hide all notification except from packages listed here.")
+ pw.println(" Providing no packages is treated as a reset.")
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
index 6cd3a6a72865..0b6b929cd93c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
@@ -25,12 +25,15 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.ListenerSet
+import com.android.systemui.util.asIndenting
import com.android.systemui.util.settings.GlobalSettings
import com.android.systemui.util.settings.SecureSettings
+import com.android.systemui.util.withIncreasedIndent
import dagger.Binds
import dagger.Module
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap
+import java.io.PrintWriter
import java.util.function.Consumer
import javax.inject.Inject
@@ -209,6 +212,16 @@ private class KeyguardNotificationVisibilityProviderImpl @Inject constructor(
}
}
+ override fun dump(pw: PrintWriter, args: Array<out String>) = pw.asIndenting().run {
+ println("isLockedOrLocking=$isLockedOrLocking")
+ withIncreasedIndent {
+ println("keyguardStateController.isShowing=${keyguardStateController.isShowing}")
+ println("statusBarStateController.currentOrUpcomingState=" +
+ "${statusBarStateController.currentOrUpcomingState}")
+ }
+ println("hideSilentNotificationsOnLockscreen=$hideSilentNotificationsOnLockscreen")
+ }
+
private val isLockedOrLocking get() =
keyguardStateController.isShowing ||
statusBarStateController.currentOrUpcomingState == StatusBarState.KEYGUARD
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 7c206eb8a54e..eb496abad460 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -513,16 +513,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
* or is in an allowList).
*/
public boolean getIsNonblockable() {
- if (mEntry == null || mEntry.getChannel() == null) {
- Log.w(TAG, "missing entry or channel");
+ if (mEntry == null) {
return true;
}
- if (mEntry.getChannel().isImportanceLockedByCriticalDeviceFunction()
- && !mEntry.getChannel().isBlockable()) {
- return true;
- }
-
- return false;
+ return !mEntry.isBlockable();
}
private boolean isConversation() {
@@ -1669,6 +1663,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
}
+ @VisibleForTesting
+ protected void setEntry(NotificationEntry entry) {
+ mEntry = entry;
+ }
+
private final Runnable mExpireRecentlyAlertedFlag = () -> applyAudiblyAlertedRecently(false);
private void applyAudiblyAlertedRecently(boolean audiblyAlertedRecently) {
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 367684faa621..705de9b43ed0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -1596,7 +1596,7 @@ public class CentralSurfacesImpl extends CoreStartable implements
}
}
});
- mStatusBarKeyguardViewManager.registerCentralSurfaces(
+ mKeyguardViewMediator.registerCentralSurfaces(
/* statusBar= */ this,
mNotificationPanelViewController,
mPanelExpansionStateManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index ba1088fba6ed..557c995586df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -958,14 +958,16 @@ public class NotificationPanelViewController extends PanelViewController {
});
}
- private void onFinishInflate() {
+ @VisibleForTesting
+ void onFinishInflate() {
loadDimens();
mKeyguardStatusBar = mView.findViewById(R.id.keyguard_header);
FrameLayout userAvatarContainer = null;
KeyguardUserSwitcherView keyguardUserSwitcherView = null;
- if (mKeyguardUserSwitcherEnabled && mUserManager.isUserSwitcherEnabled()) {
+ if (mKeyguardUserSwitcherEnabled && mUserManager.isUserSwitcherEnabled(
+ mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))) {
if (mKeyguardQsUserSwitchEnabled) {
ViewStub stub = mView.findViewById(R.id.keyguard_qs_user_switch_stub);
userAvatarContainer = (FrameLayout) stub.inflate();
@@ -1191,7 +1193,8 @@ public class NotificationPanelViewController extends PanelViewController {
return view;
}
- private void reInflateViews() {
+ @VisibleForTesting
+ void reInflateViews() {
if (DEBUG_LOGCAT) Log.d(TAG, "reInflateViews");
// Re-inflate the status view group.
KeyguardStatusView keyguardStatusView =
@@ -1212,7 +1215,8 @@ public class NotificationPanelViewController extends PanelViewController {
// Re-inflate the keyguard user switcher group.
updateUserSwitcherFlags();
- boolean isUserSwitcherEnabled = mUserManager.isUserSwitcherEnabled();
+ boolean isUserSwitcherEnabled = mUserManager.isUserSwitcherEnabled(
+ mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user));
boolean showQsUserSwitch = mKeyguardQsUserSwitchEnabled && isUserSwitcherEnabled;
boolean showKeyguardUserSwitcher =
!mKeyguardQsUserSwitchEnabled
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt
index 1206d0540fd2..ebedbf987aa2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt
@@ -200,6 +200,7 @@ class NotificationsQSContainerController @Inject constructor(
containerPadding = bottomStableInsets
} else {
containerPadding = 0
+ stackScrollMargin = bottomStableInsets + notificationsBottomMargin
}
}
val qsContainerPadding = if (!(isQSCustomizing || isQSDetailShowing)) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
index 2341928b2565..52b5857a2106 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
@@ -106,6 +106,23 @@ class AuthContainerViewTest : SysuiTestCase() {
}
@Test
+ fun testDismissesOnFocusLoss() {
+ val container = initializeContainer()
+ waitForIdleSync()
+
+ verify(callback).onDialogAnimatedIn()
+
+ container.onWindowFocusChanged(false)
+ waitForIdleSync()
+
+ verify(callback).onDismissed(
+ eq(AuthDialogCallback.DISMISSED_USER_CANCELED),
+ eq<ByteArray?>(null) /* credentialAttestation */
+ )
+ assertThat(container.parent).isNull()
+ }
+
+ @Test
fun testActionAuthenticated_sendsDismissedAuthenticated() {
val container = initializeContainer()
container.mBiometricCallback.onAction(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsBpViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsBpViewControllerTest.kt
deleted file mode 100644
index a52c4a3978b4..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsBpViewControllerTest.kt
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.biometrics
-
-import android.app.Instrumentation
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import android.testing.ViewUtils
-import androidx.test.filters.SmallTest
-import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
-import com.android.internal.jank.InteractionJankMonitor
-import com.android.internal.logging.testing.UiEventLoggerFake
-import com.android.systemui.R
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.broadcast.BroadcastSender
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.statusbar.StatusBarStateControllerImpl
-import com.android.systemui.statusbar.phone.SystemUIDialogManager
-import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager
-import com.android.systemui.util.mockito.any
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.spy
-import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
-import org.mockito.junit.MockitoJUnit
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@TestableLooper.RunWithLooper
-class UdfpsBpViewControllerTest : SysuiTestCase() {
-
- @JvmField @Rule var rule = MockitoJUnit.rule()
-
- @Mock lateinit var dumpManager: DumpManager
- @Mock lateinit var systemUIDialogManager: SystemUIDialogManager
- @Mock lateinit var broadcastSender: BroadcastSender
- @Mock lateinit var interactionJankMonitor: InteractionJankMonitor
- @Mock lateinit var panelExpansionStateManager: PanelExpansionStateManager
-
- private lateinit var instrumentation: Instrumentation
- private lateinit var uiEventLogger: UiEventLoggerFake
- private lateinit var udfpsBpView: UdfpsBpView
- private lateinit var statusBarStateController: StatusBarStateControllerImpl
- private lateinit var udfpsBpViewController: UdfpsBpViewController
-
- @Before
- fun setup() {
- instrumentation = getInstrumentation()
- instrumentation.runOnMainSync { createUdfpsView() }
- instrumentation.waitForIdleSync()
-
- uiEventLogger = UiEventLoggerFake()
- statusBarStateController =
- StatusBarStateControllerImpl(uiEventLogger, dumpManager, interactionJankMonitor)
- udfpsBpViewController = UdfpsBpViewController(
- udfpsBpView,
- statusBarStateController,
- panelExpansionStateManager,
- systemUIDialogManager,
- broadcastSender,
- dumpManager)
- udfpsBpViewController.init()
- }
-
- @After
- fun tearDown() {
- if (udfpsBpViewController.isAttachedToWindow) {
- instrumentation.runOnMainSync { ViewUtils.detachView(udfpsBpView) }
- instrumentation.waitForIdleSync()
- }
- }
-
- private fun createUdfpsView() {
- context.setTheme(R.style.Theme_AppCompat)
- context.orCreateTestableResources.addOverride(
- com.android.internal.R.integer.config_udfps_illumination_transition_ms, 0)
- udfpsBpView = UdfpsBpView(context, null)
- }
-
- @Test
- fun addExpansionListener() {
- instrumentation.runOnMainSync { ViewUtils.attachView(udfpsBpView) }
- instrumentation.waitForIdleSync()
-
- // Both UdfpsBpViewController & UdfpsAnimationViewController add listener
- verify(panelExpansionStateManager, times(2)).addExpansionListener(any())
- }
-
- @Test
- fun removeExpansionListener() {
- instrumentation.runOnMainSync { ViewUtils.attachView(udfpsBpView) }
- instrumentation.waitForIdleSync()
- instrumentation.runOnMainSync { ViewUtils.detachView(udfpsBpView) }
- instrumentation.waitForIdleSync()
-
- // Both UdfpsBpViewController & UdfpsAnimationViewController remove listener
- verify(panelExpansionStateManager, times(2)).removeExpansionListener(any())
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
index 431739b6187a..cb8358dd22cc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
@@ -40,7 +40,6 @@ import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ActivityLaunchAnimator
-import com.android.systemui.broadcast.BroadcastSender
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.LockscreenShadeTransitionController
@@ -103,7 +102,6 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
@Mock private lateinit var udfpsView: UdfpsView
@Mock private lateinit var udfpsEnrollView: UdfpsEnrollView
@Mock private lateinit var activityLaunchAnimator: ActivityLaunchAnimator
- @Mock private lateinit var broadcastSender: BroadcastSender
@Captor private lateinit var layoutParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams>
private val onTouch = { _: View, _: MotionEvent, _: Boolean -> true }
@@ -133,8 +131,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
keyguardUpdateMonitor, dialogManager, dumpManager, transitionController,
configurationController, systemClock, keyguardStateController,
unlockedScreenOffAnimationController, HAL_CONTROLS_ILLUMINATION, hbmProvider,
- REQUEST_ID, reason, controllerCallback, onTouch, activityLaunchAnimator,
- broadcastSender)
+ REQUEST_ID, reason, controllerCallback, onTouch, activityLaunchAnimator)
block()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index e7e8e73c3bc1..946c52e8ee5b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -66,7 +66,6 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.ActivityLaunchAnimator;
-import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.plugins.FalsingManager;
@@ -188,8 +187,6 @@ public class UdfpsControllerTest extends SysuiTestCase {
private ActivityLaunchAnimator mActivityLaunchAnimator;
@Mock
private AlternateUdfpsTouchProvider mAlternateTouchProvider;
- @Mock
- private BroadcastSender mBroadcastSender;
// Capture listeners so that they can be used to send events
@Captor private ArgumentCaptor<IUdfpsOverlayController> mOverlayCaptor;
@@ -270,7 +267,6 @@ public class UdfpsControllerTest extends SysuiTestCase {
mLatencyTracker,
mActivityLaunchAnimator,
Optional.of(mAlternateTouchProvider),
- mBroadcastSender,
mBiometricsExecutor);
verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
mOverlayController = mOverlayCaptor.getValue();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
index 18ee79138b52..187210a40b6d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
@@ -47,7 +47,9 @@ import org.mockito.Mockito.any
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
+import org.mockito.Mockito.times
import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.junit.MockitoJUnit
import org.mockito.Mockito.`when` as whenever
@@ -55,6 +57,7 @@ private const val KEY = "TEST_KEY"
private const val KEY_OLD = "TEST_KEY_OLD"
private const val PACKAGE = "PKG"
private const val SESSION_KEY = "SESSION_KEY"
+private const val DEVICE_ID = "DEVICE_ID"
private const val DEVICE_NAME = "DEVICE_NAME"
private const val REMOTE_DEVICE_NAME = "REMOTE_DEVICE_NAME"
@@ -457,6 +460,89 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
}
@Test
+ fun deviceIdChanged_informListener() {
+ // GIVEN a notification is added, with a particular device connected
+ whenever(device.id).thenReturn(DEVICE_ID)
+ manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+
+ // and later the manager gets a new device ID
+ val deviceCallback = captureCallback()
+ val updatedId = DEVICE_ID + "_new"
+ whenever(device.id).thenReturn(updatedId)
+ deviceCallback.onDeviceListUpdate(mutableListOf(device))
+
+ // THEN the listener gets the updated info
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+
+ val dataCaptor = ArgumentCaptor.forClass(MediaDeviceData::class.java)
+ verify(listener, times(2)).onMediaDeviceChanged(eq(KEY), any(), dataCaptor.capture())
+
+ val firstDevice = dataCaptor.allValues.get(0)
+ assertThat(firstDevice.id).isEqualTo(DEVICE_ID)
+
+ val secondDevice = dataCaptor.allValues.get(1)
+ assertThat(secondDevice.id).isEqualTo(updatedId)
+ }
+
+ @Test
+ fun deviceNameChanged_informListener() {
+ // GIVEN a notification is added, with a particular device connected
+ whenever(device.id).thenReturn(DEVICE_ID)
+ whenever(device.name).thenReturn(DEVICE_NAME)
+ manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+
+ // and later the manager gets a new device name
+ val deviceCallback = captureCallback()
+ val updatedName = DEVICE_NAME + "_new"
+ whenever(device.name).thenReturn(updatedName)
+ deviceCallback.onDeviceListUpdate(mutableListOf(device))
+
+ // THEN the listener gets the updated info
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+
+ val dataCaptor = ArgumentCaptor.forClass(MediaDeviceData::class.java)
+ verify(listener, times(2)).onMediaDeviceChanged(eq(KEY), any(), dataCaptor.capture())
+
+ val firstDevice = dataCaptor.allValues.get(0)
+ assertThat(firstDevice.name).isEqualTo(DEVICE_NAME)
+
+ val secondDevice = dataCaptor.allValues.get(1)
+ assertThat(secondDevice.name).isEqualTo(updatedName)
+ }
+
+ @Test
+ fun deviceIconChanged_doesNotCallListener() {
+ // GIVEN a notification is added, with a particular device connected
+ whenever(device.id).thenReturn(DEVICE_ID)
+ whenever(device.name).thenReturn(DEVICE_NAME)
+ val firstIcon = mock(Drawable::class.java)
+ whenever(device.icon).thenReturn(firstIcon)
+ manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+
+ val dataCaptor = ArgumentCaptor.forClass(MediaDeviceData::class.java)
+ verify(listener).onMediaDeviceChanged(eq(KEY), any(), dataCaptor.capture())
+
+ // and later the manager gets a callback with only the icon changed
+ val deviceCallback = captureCallback()
+ val secondIcon = mock(Drawable::class.java)
+ whenever(device.icon).thenReturn(secondIcon)
+ deviceCallback.onDeviceListUpdate(mutableListOf(device))
+
+ // THEN the listener is not called again
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+ verifyNoMoreInteractions(listener)
+ }
+
+ @Test
fun testRemotePlaybackDeviceOverride() {
whenever(route.name).thenReturn(DEVICE_NAME)
val deviceData = MediaDeviceData(false, null, REMOTE_DEVICE_NAME, null)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
index 7c53388c81aa..e3b5059131fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
@@ -27,6 +27,7 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
+import android.media.AudioManager;
import android.media.session.MediaController;
import android.media.session.MediaSessionManager;
import android.media.session.PlaybackState;
@@ -84,6 +85,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase {
private NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock(
NearbyMediaDevicesManager.class);
private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
+ private final AudioManager mAudioManager = mock(AudioManager.class);
private List<MediaController> mMediaControllers = new ArrayList<>();
private MediaOutputBaseDialogImpl mMediaOutputBaseDialogImpl;
@@ -108,7 +110,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase {
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE,
mMediaSessionManager, mLocalBluetoothManager, mStarter,
mNotificationEntryManager, mDialogLaunchAnimator,
- Optional.of(mNearbyMediaDevicesManager));
+ Optional.of(mNearbyMediaDevicesManager), mAudioManager);
mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext, mBroadcastSender,
mMediaOutputController);
mMediaOutputBaseDialogImpl.onCreate(new Bundle());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
index d2dae745bcdc..feed3347f3e2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
@@ -31,6 +31,7 @@ import static org.mockito.Mockito.when;
import android.app.Notification;
import android.content.Context;
import android.graphics.drawable.Icon;
+import android.media.AudioManager;
import android.media.MediaDescription;
import android.media.MediaMetadata;
import android.media.NearbyDevice;
@@ -95,6 +96,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
private MediaMetadata mMediaMetadata = mock(MediaMetadata.class);
private RoutingSessionInfo mRemoteSessionInfo = mock(RoutingSessionInfo.class);
private ActivityStarter mStarter = mock(ActivityStarter.class);
+ private AudioManager mAudioManager = mock(AudioManager.class);
private CommonNotifCollection mNotifCollection = mock(CommonNotifCollection.class);
private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
private final NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock(
@@ -123,7 +125,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME,
mMediaSessionManager, mLocalBluetoothManager, mStarter,
mNotifCollection, mDialogLaunchAnimator,
- Optional.of(mNearbyMediaDevicesManager));
+ Optional.of(mNearbyMediaDevicesManager), mAudioManager);
mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager);
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
MediaDescription.Builder builder = new MediaDescription.Builder();
@@ -175,7 +177,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
mMediaOutputController = new MediaOutputController(mSpyContext, null,
mMediaSessionManager, mLocalBluetoothManager, mStarter,
mNotifCollection, mDialogLaunchAnimator,
- Optional.of(mNearbyMediaDevicesManager));
+ Optional.of(mNearbyMediaDevicesManager), mAudioManager);
mMediaOutputController.start(mCb);
@@ -204,7 +206,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
mMediaOutputController = new MediaOutputController(mSpyContext, null,
mMediaSessionManager, mLocalBluetoothManager, mStarter,
mNotifCollection, mDialogLaunchAnimator,
- Optional.of(mNearbyMediaDevicesManager));
+ Optional.of(mNearbyMediaDevicesManager), mAudioManager);
mMediaOutputController.start(mCb);
@@ -509,7 +511,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
mMediaOutputController = new MediaOutputController(mSpyContext, null,
mMediaSessionManager, mLocalBluetoothManager, mStarter,
mNotifCollection, mDialogLaunchAnimator,
- Optional.of(mNearbyMediaDevicesManager));
+ Optional.of(mNearbyMediaDevicesManager), mAudioManager);
assertThat(mMediaOutputController.getNotificationIcon()).isNull();
}
@@ -569,4 +571,24 @@ public class MediaOutputControllerTest extends SysuiTestCase {
assertThat(mMediaOutputController.getNotificationIcon()).isNull();
}
+
+ @Test
+ public void isVolumeControlEnabled_isCastWithVolumeFixed_returnsFalse() {
+ when(mMediaDevice1.getDeviceType()).thenReturn(
+ MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE);
+
+ when(mMediaDevice1.isVolumeFixed()).thenReturn(true);
+
+ assertThat(mMediaOutputController.isVolumeControlEnabled(mMediaDevice1)).isFalse();
+ }
+
+ @Test
+ public void isVolumeControlEnabled_isCastWithVolumeNotFixed_returnsTrue() {
+ when(mMediaDevice1.getDeviceType()).thenReturn(
+ MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE);
+
+ when(mMediaDevice1.isVolumeFixed()).thenReturn(false);
+
+ assertThat(mMediaOutputController.isVolumeControlEnabled(mMediaDevice1)).isTrue();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
index e6ad6edcec45..6786ad0116ea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
@@ -24,6 +24,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.media.AudioManager;
import android.media.MediaRoute2Info;
import android.media.session.MediaController;
import android.media.session.MediaSessionManager;
@@ -82,6 +83,7 @@ public class MediaOutputDialogTest extends SysuiTestCase {
private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
private final NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock(
NearbyMediaDevicesManager.class);
+ private final AudioManager mAudioManager = mock(AudioManager.class);
private List<MediaController> mMediaControllers = new ArrayList<>();
private MediaOutputDialog mMediaOutputDialog;
@@ -101,7 +103,7 @@ public class MediaOutputDialogTest extends SysuiTestCase {
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE,
mMediaSessionManager, mLocalBluetoothManager, mStarter,
mNotificationEntryManager, mDialogLaunchAnimator,
- Optional.of(mNearbyMediaDevicesManager));
+ Optional.of(mNearbyMediaDevicesManager), mAudioManager);
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
mMediaOutputDialog = new MediaOutputDialog(mContext, false, mBroadcastSender,
mMediaOutputController, mUiEventLogger);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
index 0cdde0775b2d..379bb4fd6336 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
@@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.media.AudioManager;
import android.media.session.MediaSessionManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -68,6 +69,7 @@ public class MediaOutputGroupDialogTest extends SysuiTestCase {
private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
private NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock(
NearbyMediaDevicesManager.class);
+ private final AudioManager mAudioManager = mock(AudioManager.class);
private MediaOutputGroupDialog mMediaOutputGroupDialog;
private MediaOutputController mMediaOutputController;
@@ -78,7 +80,7 @@ public class MediaOutputGroupDialogTest extends SysuiTestCase {
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE,
mMediaSessionManager, mLocalBluetoothManager, mStarter,
mNotificationEntryManager, mDialogLaunchAnimator,
- Optional.of(mNearbyMediaDevicesManager));
+ Optional.of(mNearbyMediaDevicesManager), mAudioManager);
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
mMediaOutputGroupDialog = new MediaOutputGroupDialog(mContext, false, mBroadcastSender,
mMediaOutputController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java
index 63dca3bafc5b..0badd861787d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java
@@ -146,6 +146,20 @@ public class ColorSchemeTest extends SysuiTestCase {
Assert.assertTrue(cam.getChroma() <= 8.0);
}
+ @Test
+ @SuppressWarnings("ResultOfMethodCallIgnored")
+ public void testToString() {
+ new ColorScheme(Color.TRANSPARENT, false /* darkTheme */).toString();
+ new ColorScheme(Color.argb(0, 0, 0, 0xf), false /* darkTheme */).toString();
+ new ColorScheme(Color.argb(0xff, 0xff, 0, 0), false /* darkTheme */).toString();
+ new ColorScheme(0xFFFFFFFF, false /* darkTheme */).toString();
+
+ new ColorScheme(Color.TRANSPARENT, true /* darkTheme */).toString();
+ new ColorScheme(Color.argb(0, 0, 0, 0xf), true /* darkTheme */).toString();
+ new ColorScheme(0xFFFF0000, true /* darkTheme */).toString();
+ new ColorScheme(0xFFFFFFFF, true /* darkTheme */).toString();
+ }
+
/**
* Generate xml for SystemPaletteTest#testThemeStyles().
*/
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
index e237a5ce03fe..60cfd7249919 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
@@ -13,18 +13,24 @@
*/
package com.android.systemui.qs
+import android.graphics.Rect
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
+import android.testing.ViewUtils
import android.view.View
-import android.view.ViewGroup
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.accessibility.AccessibilityNodeInfo
import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.qs.tileimpl.QSIconViewImpl
+import com.android.systemui.qs.tileimpl.QSTileViewImpl
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -36,37 +42,40 @@ import org.mockito.MockitoAnnotations
@RunWithLooper
@SmallTest
class QSPanelTest : SysuiTestCase() {
- private lateinit var mTestableLooper: TestableLooper
- private lateinit var mQsPanel: QSPanel
+ private lateinit var testableLooper: TestableLooper
+ private lateinit var qsPanel: QSPanel
- private lateinit var mParentView: ViewGroup
-
- private lateinit var mFooter: View
+ private lateinit var footer: View
@Before
@Throws(Exception::class)
fun setup() {
MockitoAnnotations.initMocks(this)
- mTestableLooper = TestableLooper.get(this)
+ testableLooper = TestableLooper.get(this)
+
+ testableLooper.runWithLooper {
+ qsPanel = QSPanel(context, null)
+ qsPanel.mUsingMediaPlayer = true
- mTestableLooper.runWithLooper {
- mQsPanel = QSPanel(mContext, null)
- mQsPanel.initialize()
+ qsPanel.initialize()
// QSPanel inflates a footer inside of it, mocking it here
- mFooter = LinearLayout(mContext).apply { id = R.id.qs_footer }
- mQsPanel.addView(mFooter)
- mQsPanel.onFinishInflate()
+ footer = LinearLayout(context).apply { id = R.id.qs_footer }
+ qsPanel.addView(footer, MATCH_PARENT, 100)
+ qsPanel.onFinishInflate()
// Provides a parent with non-zero size for QSPanel
- mParentView = FrameLayout(mContext).apply {
- addView(mQsPanel)
- }
+ ViewUtils.attachView(qsPanel)
}
}
+ @After
+ fun tearDown() {
+ ViewUtils.detachView(qsPanel)
+ }
+
@Test
fun testHasCollapseAccessibilityAction() {
- val info = AccessibilityNodeInfo(mQsPanel)
- mQsPanel.onInitializeAccessibilityNodeInfo(info)
+ val info = AccessibilityNodeInfo(qsPanel)
+ qsPanel.onInitializeAccessibilityNodeInfo(info)
assertThat(info.actions and AccessibilityNodeInfo.ACTION_COLLAPSE).isNotEqualTo(0)
assertThat(info.actions and AccessibilityNodeInfo.ACTION_EXPAND).isEqualTo(0)
@@ -75,9 +84,79 @@ class QSPanelTest : SysuiTestCase() {
@Test
fun testCollapseActionCallsRunnable() {
val mockRunnable = mock(Runnable::class.java)
- mQsPanel.setCollapseExpandAction(mockRunnable)
+ qsPanel.setCollapseExpandAction(mockRunnable)
- mQsPanel.performAccessibilityAction(AccessibilityNodeInfo.ACTION_COLLAPSE, null)
+ qsPanel.performAccessibilityAction(AccessibilityNodeInfo.ACTION_COLLAPSE, null)
verify(mockRunnable).run()
}
+
+ @Test
+ fun testTilesFooterVisibleRTLLandscapeMedia() {
+ qsPanel.layoutDirection = View.LAYOUT_DIRECTION_RTL
+ // We need at least a tile so the layout has a height
+ qsPanel.tileLayout?.addTile(
+ QSPanelControllerBase.TileRecord(
+ mock(QSTile::class.java),
+ QSTileViewImpl(context, QSIconViewImpl(context))
+ )
+ )
+
+ val mediaView = FrameLayout(context)
+ mediaView.addView(View(context), MATCH_PARENT, 800)
+
+ qsPanel.setUsingHorizontalLayout(/* horizontal */ true, mediaView, /* force */ true)
+ qsPanel.measure(
+ /* width */ View.MeasureSpec.makeMeasureSpec(3000, View.MeasureSpec.EXACTLY),
+ /* height */ View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY)
+ )
+ qsPanel.layout(0, 0, qsPanel.measuredWidth, qsPanel.measuredHeight)
+
+ val tiles = qsPanel.tileLayout as View
+ // Tiles are effectively to the right of media
+ assertThat(mediaView isLeftOf tiles)
+ assertThat(tiles.isVisibleToUser).isTrue()
+
+ assertThat(mediaView isLeftOf footer)
+ assertThat(footer.isVisibleToUser).isTrue()
+ }
+
+ @Test
+ fun testTilesFooterVisibleLandscapeMedia() {
+ qsPanel.layoutDirection = View.LAYOUT_DIRECTION_LTR
+ // We need at least a tile so the layout has a height
+ qsPanel.tileLayout?.addTile(
+ QSPanelControllerBase.TileRecord(
+ mock(QSTile::class.java),
+ QSTileViewImpl(context, QSIconViewImpl(context))
+ )
+ )
+
+ val mediaView = FrameLayout(context)
+ mediaView.addView(View(context), MATCH_PARENT, 800)
+
+ qsPanel.setUsingHorizontalLayout(/* horizontal */ true, mediaView, /* force */ true)
+ qsPanel.measure(
+ /* width */ View.MeasureSpec.makeMeasureSpec(3000, View.MeasureSpec.EXACTLY),
+ /* height */ View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY)
+ )
+ qsPanel.layout(0, 0, qsPanel.measuredWidth, qsPanel.measuredHeight)
+
+ val tiles = qsPanel.tileLayout as View
+ // Tiles are effectively to the left of media
+ assertThat(tiles isLeftOf mediaView)
+ assertThat(tiles.isVisibleToUser).isTrue()
+
+ assertThat(footer isLeftOf mediaView)
+ assertThat(footer.isVisibleToUser).isTrue()
+ }
+
+ private infix fun View.isLeftOf(other: View): Boolean {
+ val rect = Rect()
+ getBoundsOnScreen(rect)
+ val thisRight = rect.right
+
+ other.getBoundsOnScreen(rect)
+
+ return thisRight <= rect.left
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
index f76b50a173c3..bd4b94eef2dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
@@ -189,6 +189,67 @@ class UserTrackerImplTest : SysuiTestCase() {
assertThat(tracker.userProfiles.map { it.id }).containsExactly(tracker.userId, profileID)
}
+ fun testManagedProfileUnavailable() {
+ tracker.initialize(0)
+ val profileID = tracker.userId + 10
+
+ `when`(userManager.getProfiles(anyInt())).thenAnswer { invocation ->
+ val id = invocation.getArgument<Int>(0)
+ val info = UserInfo(id, "", UserInfo.FLAG_FULL)
+ val infoProfile = UserInfo(
+ id + 10,
+ "",
+ "",
+ UserInfo.FLAG_MANAGED_PROFILE or UserInfo.FLAG_QUIET_MODE,
+ UserManager.USER_TYPE_PROFILE_MANAGED
+ )
+ infoProfile.profileGroupId = id
+ listOf(info, infoProfile)
+ }
+
+ val intent = Intent(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)
+ .putExtra(Intent.EXTRA_USER, UserHandle.of(profileID))
+ tracker.onReceive(context, intent)
+
+ assertThat(tracker.userProfiles.map { it.id }).containsExactly(tracker.userId, profileID)
+ }
+
+ fun testManagedProfileStartedAndRemoved() {
+ tracker.initialize(0)
+ val profileID = tracker.userId + 10
+
+ `when`(userManager.getProfiles(anyInt())).thenAnswer { invocation ->
+ val id = invocation.getArgument<Int>(0)
+ val info = UserInfo(id, "", UserInfo.FLAG_FULL)
+ val infoProfile = UserInfo(
+ id + 10,
+ "",
+ "",
+ UserInfo.FLAG_MANAGED_PROFILE,
+ UserManager.USER_TYPE_PROFILE_MANAGED
+ )
+ infoProfile.profileGroupId = id
+ listOf(info, infoProfile)
+ }
+
+ // Managed profile started
+ val intent = Intent(Intent.ACTION_MANAGED_PROFILE_UNLOCKED)
+ .putExtra(Intent.EXTRA_USER, UserHandle.of(profileID))
+ tracker.onReceive(context, intent)
+
+ assertThat(tracker.userProfiles.map { it.id }).containsExactly(tracker.userId, profileID)
+
+ `when`(userManager.getProfiles(anyInt())).thenAnswer { invocation ->
+ listOf(UserInfo(invocation.getArgument(0), "", UserInfo.FLAG_FULL))
+ }
+
+ val intent2 = Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED)
+ .putExtra(Intent.EXTRA_USER, UserHandle.of(profileID))
+ tracker.onReceive(context, intent2)
+
+ assertThat(tracker.userProfiles.map { it.id }).containsExactly(tracker.userId)
+ }
+
@Test
fun testCallbackNotCalledOnAdd() {
tracker.initialize(0)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
index 5804ad425267..769143ddbc0d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
@@ -29,6 +29,7 @@ import static com.android.systemui.statusbar.NotificationEntryHelper.modifySbn;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import android.app.ActivityManager;
@@ -57,6 +58,7 @@ import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
import java.util.ArrayList;
@@ -72,6 +74,7 @@ public class NotificationEntryTest extends SysuiTestCase {
private int mId;
private NotificationEntry mEntry;
+ private NotificationChannel mChannel = Mockito.mock(NotificationChannel.class);
private final FakeSystemClock mClock = new FakeSystemClock();
@Before
@@ -85,10 +88,13 @@ public class NotificationEntryTest extends SysuiTestCase {
.setPkg(TEST_PACKAGE_NAME)
.setOpPkg(TEST_PACKAGE_NAME)
.setUid(TEST_UID)
+ .setChannel(mChannel)
.setId(mId++)
.setNotification(n.build())
.setUser(new UserHandle(ActivityManager.getCurrentUser()))
.build();
+
+ doReturn(false).when(mChannel).isBlockable();
}
@Test
@@ -100,6 +106,44 @@ public class NotificationEntryTest extends SysuiTestCase {
}
@Test
+ public void testBlockableEntryWhenCritical() {
+ doReturn(true).when(mChannel).isBlockable();
+
+ assertTrue(mEntry.isBlockable());
+ }
+
+
+ @Test
+ public void testBlockableEntryWhenCriticalAndChannelNotBlockable() {
+ doReturn(true).when(mChannel).isBlockable();
+ doReturn(true).when(mChannel).isImportanceLockedByCriticalDeviceFunction();
+
+ assertTrue(mEntry.isBlockable());
+ }
+
+ @Test
+ public void testNonBlockableEntryWhenCriticalAndChannelNotBlockable() {
+ doReturn(false).when(mChannel).isBlockable();
+ doReturn(true).when(mChannel).isImportanceLockedByCriticalDeviceFunction();
+
+ assertFalse(mEntry.isBlockable());
+ }
+
+ @Test
+ public void testBlockableWhenEntryHasNoChannel() {
+ StatusBarNotification sbn = new SbnBuilder().build();
+ Ranking ranking = new RankingBuilder()
+ .setChannel(null)
+ .setKey(sbn.getKey())
+ .build();
+
+ NotificationEntry entry =
+ new NotificationEntry(sbn, ranking, mClock.uptimeMillis());
+
+ assertFalse(entry.isBlockable());
+ }
+
+ @Test
public void testIsExemptFromDndVisualSuppression_media() {
Notification.Builder n = new Notification.Builder(mContext, "")
.setStyle(new Notification.MediaStyle()
@@ -117,7 +161,8 @@ public class NotificationEntryTest extends SysuiTestCase {
@Test
public void testIsExemptFromDndVisualSuppression_system() {
- mEntry.mIsSystemNotification = true;
+ doReturn(true).when(mChannel).isImportanceLockedByCriticalDeviceFunction();
+ doReturn(false).when(mChannel).isBlockable();
assertTrue(mEntry.isExemptFromDndVisualSuppression());
assertFalse(mEntry.shouldSuppressAmbient());
@@ -128,7 +173,7 @@ public class NotificationEntryTest extends SysuiTestCase {
NotificationEntry entry = new NotificationEntryBuilder()
.setUid(UID_NORMAL)
.build();
- entry.mIsSystemNotification = true;
+ doReturn(true).when(mChannel).isImportanceLockedByCriticalDeviceFunction();
modifyRanking(entry).setSuppressedVisualEffects(SUPPRESSED_EFFECT_AMBIENT).build();
modifySbn(entry)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
index 52bacd2360b3..d082d74078db 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.collection.coordinator;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -74,7 +75,7 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
KeyguardCoordinator keyguardCoordinator = new KeyguardCoordinator(
mStatusBarStateController,
mKeyguardUpdateMonitor, mHighPriorityProvider, mSectionHeaderVisibilityProvider,
- mKeyguardNotificationVisibilityProvider);
+ mKeyguardNotificationVisibilityProvider, mock(SharedCoordinatorLogger.class));
mEntry = new NotificationEntryBuilder()
.setUser(new UserHandle(NOTIF_USER_ID))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
index f4d8405a796e..15c1cb7b123a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.collection.coordinator;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
@@ -30,6 +31,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Notification;
+import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.testing.AndroidTestingRunner;
@@ -185,7 +187,7 @@ public class RankingCoordinatorTest extends SysuiTestCase {
// WHEN it's not dozing (showing the notification list)
when(mStatusBarStateController.isDozing()).thenReturn(false);
-
+
// THEN filter out the notification
assertTrue(mCapturedDozingFilter.shouldFilterOut(mEntry, 0));
}
@@ -277,6 +279,7 @@ public class RankingCoordinatorTest extends SysuiTestCase {
private RankingBuilder getRankingForUnfilteredNotif() {
return new RankingBuilder(mEntry.getRanking())
+ .setChannel(new NotificationChannel("id", null, IMPORTANCE_DEFAULT))
.setSuppressedVisualEffects(0)
.setSuspended(false);
}
@@ -292,7 +295,7 @@ public class RankingCoordinatorTest extends SysuiTestCase {
mEntry.setRanking(new RankingBuilder(mEntry.getRanking())
.setImportance(ambient
? NotificationManager.IMPORTANCE_MIN
- : NotificationManager.IMPORTANCE_DEFAULT)
+ : IMPORTANCE_DEFAULT)
.build());
assertEquals(ambient, mEntry.getRanking().isAmbient());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
index 8a2dc263cf36..90627cb0fa78 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
@@ -36,6 +36,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Notification;
+import android.app.NotificationChannel;
import android.app.PendingIntent;
import android.content.Intent;
import android.graphics.drawable.Icon;
@@ -529,6 +530,7 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
.setPkg("a")
.setOpPkg("a")
.setTag("a")
+ .setChannel(new NotificationChannel("a", null, importance))
.setNotification(n)
.setImportance(importance)
.build();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index c36737c6724e..b1bf971c52fc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -58,6 +58,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
import com.android.systemui.statusbar.notification.FeedbackIcon;
import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
import org.junit.Assert;
@@ -65,6 +66,7 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@@ -412,27 +414,15 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
public void testGetIsNonblockable() throws Exception {
ExpandableNotificationRow row =
mNotificationTestHelper.createRow(mNotificationTestHelper.createNotification());
-
- assertFalse(row.getIsNonblockable());
- }
-
- @Test
- public void testGetIsNonblockable_criticalDeviceFunction() throws Exception {
- ExpandableNotificationRow row =
- mNotificationTestHelper.createRow(mNotificationTestHelper.createNotification());
- row.getEntry().getChannel().setImportanceLockedByCriticalDeviceFunction(true);
- row.getEntry().getChannel().setBlockable(false);
+ row.setEntry(null);
assertTrue(row.getIsNonblockable());
- }
- @Test
- public void testGetIsNonblockable_criticalDeviceFunction_butBlockable() throws Exception {
- ExpandableNotificationRow row =
- mNotificationTestHelper.createRow(mNotificationTestHelper.createNotification());
- row.getEntry().getChannel().setImportanceLockedByCriticalDeviceFunction(true);
- row.getEntry().getChannel().setBlockable(true);
+ NotificationEntry entry = mock(NotificationEntry.class);
+ Mockito.doReturn(false, true).when(entry).isBlockable();
+ row.setEntry(entry);
+ assertTrue(row.getIsNonblockable());
assertFalse(row.getIsNonblockable());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index 16f934b5af59..2faff0ced70a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -39,6 +39,7 @@ import static org.mockito.Mockito.when;
import android.app.IWallpaperManager;
import android.app.Notification;
+import android.app.NotificationChannel;
import android.app.WallpaperManager;
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
@@ -718,6 +719,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
.setPkg("a")
.setOpPkg("a")
.setTag("a")
+ .setChannel(new NotificationChannel("id", null, IMPORTANCE_HIGH))
.setNotification(n)
.setImportance(IMPORTANCE_HIGH)
.setSuppressedVisualEffects(SUPPRESSED_EFFECT_PEEK)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
index 018c4531b382..d47644f047a2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
@@ -889,7 +889,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
updateSmallestScreenWidth(300);
when(mResources.getBoolean(
com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
- when(mUserManager.isUserSwitcherEnabled()).thenReturn(true);
+ when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
+ when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(true);
updateSmallestScreenWidth(800);
@@ -897,6 +898,34 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
}
@Test
+ public void testFinishInflate_userSwitcherDisabled_doNotInflateUserSwitchView() {
+ givenViewAttached();
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
+ when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
+ when(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
+ .thenReturn(false);
+
+ mNotificationPanelViewController.onFinishInflate();
+
+ verify(mUserSwitcherStubView, never()).inflate();
+ }
+
+ @Test
+ public void testReInflateViews_userSwitcherDisabled_doNotInflateUserSwitchView() {
+ givenViewAttached();
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
+ when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
+ when(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
+ .thenReturn(false);
+
+ mNotificationPanelViewController.reInflateViews();
+
+ verify(mUserSwitcherStubView, never()).inflate();
+ }
+
+ @Test
public void testCanCollapsePanelOnTouch_trueForKeyGuard() {
mStatusBarStateController.setState(KEYGUARD);
@@ -1298,7 +1327,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
}
private void updateMultiUserSetting(boolean enabled) {
- when(mUserManager.isUserSwitcherEnabled()).thenReturn(enabled);
+ when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
+ when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(enabled);
final ArgumentCaptor<ContentObserver> observerCaptor =
ArgumentCaptor.forClass(ContentObserver.class);
verify(mContentResolver)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt
index 003245298fa9..de40b7fd0a13 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt
@@ -206,7 +206,9 @@ class NotificationQSContainerControllerTest : SysuiTestCase() {
given(taskbarVisible = false,
navigationMode = BUTTONS_NAVIGATION,
insets = windowInsets().withStableBottom())
- then(expectedContainerPadding = 0, expectedQsPadding = STABLE_INSET_BOTTOM)
+ then(expectedContainerPadding = 0,
+ expectedNotificationsMargin = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN,
+ expectedQsPadding = STABLE_INSET_BOTTOM)
}
@Test
diff --git a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
index 09a05bb6b40e..3d24588c9763 100644
--- a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
+++ b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
@@ -124,15 +124,21 @@ public class CameraExtensionsProxyService extends Service {
private static final String CAMERA_EXTENSION_VERSION_NAME =
"androidx.camera.extensions.impl.ExtensionVersionImpl";
- private static final String LATEST_VERSION = "1.2.0";
+ private static final String LATEST_VERSION = "1.3.0";
+ // No support for the init sequence
private static final String NON_INIT_VERSION_PREFIX = "1.0";
+ // Support advanced API and latency queries
private static final String ADVANCED_VERSION_PREFIX = "1.2";
+ // Support for the capture request & result APIs
private static final String RESULTS_VERSION_PREFIX = "1.3";
+ private static final String[] ADVANCED_VERSION_PREFIXES = {ADVANCED_VERSION_PREFIX,
+ RESULTS_VERSION_PREFIX};
private static final String[] SUPPORTED_VERSION_PREFIXES = {RESULTS_VERSION_PREFIX,
ADVANCED_VERSION_PREFIX, "1.1", NON_INIT_VERSION_PREFIX};
private static final boolean EXTENSIONS_PRESENT = checkForExtensions();
private static final String EXTENSIONS_VERSION = EXTENSIONS_PRESENT ?
(new ExtensionVersionImpl()).checkApiVersion(LATEST_VERSION) : null;
+ private static final boolean LATENCY_API_SUPPORTED = checkForLatencyAPI();
private static final boolean ADVANCED_API_SUPPORTED = checkForAdvancedAPI();
private static final boolean INIT_API_SUPPORTED = EXTENSIONS_PRESENT &&
(!EXTENSIONS_VERSION.startsWith(NON_INIT_VERSION_PREFIX));
@@ -143,19 +149,35 @@ public class CameraExtensionsProxyService extends Service {
private HashMap<String, Long> mMetadataVendorIdMap = new HashMap<>();
private CameraManager mCameraManager;
- private static boolean checkForAdvancedAPI() {
- if (EXTENSIONS_PRESENT && EXTENSIONS_VERSION.startsWith(ADVANCED_VERSION_PREFIX)) {
- try {
- return (new ExtensionVersionImpl()).isAdvancedExtenderImplemented();
- } catch (NoSuchMethodError e) {
- // This could happen in case device specific extension implementations are using an
- // older extension API but incorrectly set the extension version.
+ private static boolean checkForLatencyAPI() {
+ if (!EXTENSIONS_PRESENT) {
+ return false;
+ }
+
+ for (String advancedVersions : ADVANCED_VERSION_PREFIXES) {
+ if (EXTENSIONS_VERSION.startsWith(advancedVersions)) {
+ return true;
}
}
return false;
}
+ private static boolean checkForAdvancedAPI() {
+ if (!checkForLatencyAPI()) {
+ return false;
+ }
+
+ try {
+ return (new ExtensionVersionImpl()).isAdvancedExtenderImplemented();
+ } catch (NoSuchMethodError e) {
+ // This could happen in case device specific extension implementations are using
+ // an older extension API but incorrectly set the extension version.
+ }
+
+ return false;
+ }
+
private static boolean checkForExtensions() {
try {
Class.forName(CAMERA_EXTENSION_VERSION_NAME);
@@ -292,7 +314,7 @@ public class CameraExtensionsProxyService extends Service {
if (INIT_API_SUPPORTED) {
if (mActiveClients.isEmpty()) {
InitializerFuture status = new InitializerFuture();
- InitializerImpl.init(EXTENSIONS_VERSION, ctx, new InitializeHandler(status),
+ InitializerImpl.init(LATEST_VERSION, ctx, new InitializeHandler(status),
new HandlerExecutor(mHandler));
boolean initSuccess;
try {
@@ -1447,7 +1469,7 @@ public class CameraExtensionsProxyService extends Service {
@Override
public LatencyRange getEstimatedCaptureLatencyRange(
android.hardware.camera2.extension.Size outputSize) {
- if (EXTENSIONS_VERSION.startsWith(ADVANCED_VERSION_PREFIX)) {
+ if (LATENCY_API_SUPPORTED) {
Size sz = new Size(outputSize.width, outputSize.height);
Range<Long> latencyRange = mImageExtender.getEstimatedCaptureLatencyRange(sz);
if (latencyRange != null) {
diff --git a/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java b/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java
index c6e595b1d785..01cee33fd81a 100644
--- a/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java
+++ b/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java
@@ -174,7 +174,7 @@ public final class PresentationStatsEventLogger {
public void logAndEndEvent() {
if (!mEventInternal.isPresent()) {
- Slog.wtf(null, "Shouldn't be logging AutofillPresentationEventReported again for same "
+ Slog.w(TAG, "Shouldn't be logging AutofillPresentationEventReported again for same "
+ "event");
return;
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index a4eaef98235d..8368b4dfe070 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -63,6 +63,12 @@ import static android.os.Process.SYSTEM_UID;
import static android.os.Process.ZYGOTE_POLICY_FLAG_EMPTY;
import static com.android.internal.messages.nano.SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICE_BG_LAUNCH;
+import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED;
+import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD;
+import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_HOT;
+import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM;
+import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED__REQUEST_TYPE__BIND;
+import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED__REQUEST_TYPE__START;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKGROUND_CHECK;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOREGROUND_SERVICE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
@@ -522,8 +528,9 @@ public final class ActiveServices {
+ " delayedStop=" + r.delayedStop);
} else {
try {
- startServiceInnerLocked(this, r.pendingStarts.get(0).intent, r, false,
- true);
+ final ServiceRecord.StartItem si = r.pendingStarts.get(0);
+ startServiceInnerLocked(this, si.intent, r, false, true, si.callingId,
+ r.startRequested);
} catch (TransactionTooLargeException e) {
// Ignore, nobody upstack cares.
}
@@ -865,6 +872,7 @@ public final class ActiveServices {
if (unscheduleServiceRestartLocked(r, callingUid, false)) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "START SERVICE WHILE RESTART PENDING: " + r);
}
+ final boolean wasStartRequested = r.startRequested;
r.lastActivity = SystemClock.uptimeMillis();
r.startRequested = true;
r.delayedStop = false;
@@ -954,7 +962,8 @@ public final class ActiveServices {
if (allowBackgroundActivityStarts) {
r.allowBgActivityStartsOnServiceStart(backgroundActivityStartsToken);
}
- ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
+ ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting,
+ callingUid, wasStartRequested);
return cmp;
}
@@ -1150,7 +1159,8 @@ public final class ActiveServices {
}
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
- boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
+ boolean callerFg, boolean addToStarting, int callingUid, boolean wasStartRequested)
+ throws TransactionTooLargeException {
synchronized (mAm.mProcessStats.mLock) {
final ServiceState stracker = r.getTracker();
if (stracker != null) {
@@ -1177,6 +1187,15 @@ public final class ActiveServices {
return new ComponentName("!!", error);
}
+ FrameworkStatsLog.write(SERVICE_REQUEST_EVENT_REPORTED, uid, callingUid,
+ ActivityManagerService.getShortAction(service.getAction()),
+ SERVICE_REQUEST_EVENT_REPORTED__REQUEST_TYPE__START, false,
+ r.app == null || r.app.getThread() == null
+ ? SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD
+ : (wasStartRequested || !r.getConnections().isEmpty()
+ ? SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_HOT
+ : SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM));
+
if (r.startRequested && addToStarting) {
boolean first = smap.mStartingBackground.size() == 0;
smap.mStartingBackground.add(r);
@@ -2876,6 +2895,8 @@ public final class ActiveServices {
mAm.requireAllowedAssociationsLocked(s.appInfo.packageName);
}
+ final boolean wasStartRequested = s.startRequested;
+ final boolean hadConnections = !s.getConnections().isEmpty();
mAm.startAssociationLocked(callerApp.uid, callerApp.processName,
callerApp.mState.getCurProcState(), s.appInfo.uid, s.appInfo.longVersionCode,
s.instanceName, s.processName);
@@ -2962,6 +2983,15 @@ public final class ActiveServices {
mAm.updateOomAdjPendingTargetsLocked(OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);
}
+ FrameworkStatsLog.write(SERVICE_REQUEST_EVENT_REPORTED, s.appInfo.uid, callingUid,
+ ActivityManagerService.getShortAction(service.getAction()),
+ SERVICE_REQUEST_EVENT_REPORTED__REQUEST_TYPE__BIND, false,
+ s.app == null || s.app.getThread() == null
+ ? SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD
+ : (wasStartRequested || hadConnections
+ ? SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_HOT
+ : SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM));
+
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b
+ ": received=" + b.intent.received
+ " apps=" + b.intent.apps.size()
@@ -6917,7 +6947,8 @@ public final class ActiveServices {
durationMs,
r.mStartForegroundCount,
ActivityManagerUtils.hashComponentNameForAtom(r.shortInstanceName),
- r.mFgsHasNotificationPermission);
+ r.mFgsHasNotificationPermission,
+ r.foregroundServiceType);
int event = 0;
if (state == FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 71a28487a763..a78c64b6538d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5003,15 +5003,7 @@ public class ActivityManagerService extends IActivityManager.Stub
final HostingRecord hostingRecord = app.getHostingRecord();
- final String action = hostingRecord.getAction();
- String shortAction = action;
- if (action != null) {
- // only log the last part of the action string to save stats data.
- int index = action.lastIndexOf(".");
- if (index != -1 && index != action.length() - 1) {
- shortAction = action.substring(index + 1);
- }
- }
+ String shortAction = getShortAction(hostingRecord.getAction());
FrameworkStatsLog.write(
FrameworkStatsLog.PROCESS_START_TIME,
app.info.uid,
@@ -5042,6 +5034,20 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ /**
+ * @return The last part of the string of an intent's action.
+ */
+ static @Nullable String getShortAction(@Nullable String action) {
+ String shortAction = action;
+ if (action != null) {
+ int index = action.lastIndexOf('.');
+ if (index != -1 && index != action.length() - 1) {
+ shortAction = action.substring(index + 1);
+ }
+ }
+ return shortAction;
+ }
+
void checkTime(long startTime, String where) {
long now = SystemClock.uptimeMillis();
if ((now - startTime) > 50) {
@@ -14262,7 +14268,7 @@ public class ActivityManagerService extends IActivityManager.Stub
oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
oldRecord.intent,
Activity.RESULT_CANCELED, null, null,
- false, false, oldRecord.userId);
+ false, false, oldRecord.userId, oldRecord.callingUid, callingUid);
} catch (RemoteException e) {
Slog.w(TAG, "Failure ["
+ queue.mQueueName + "] sending broadcast result of "
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index f7aa7c155719..43d0de9855fe 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -24,6 +24,11 @@ import static android.text.TextUtils.formatSimple;
import static com.android.internal.util.FrameworkStatsLog.BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED;
import static com.android.internal.util.FrameworkStatsLog.BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED__EVENT__BOOT_COMPLETED;
import static com.android.internal.util.FrameworkStatsLog.BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED__EVENT__LOCKED_BOOT_COMPLETED;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__MANIFEST;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__RUNTIME;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_DEFERRAL;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_LIGHT;
@@ -316,7 +321,7 @@ public final class BroadcastQueue {
}
private final void processCurBroadcastLocked(BroadcastRecord r,
- ProcessRecord app) throws RemoteException {
+ ProcessRecord app, int receiverType, int processTemperature) throws RemoteException {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r + " for app " + app);
final IApplicationThread thread = app.getThread();
@@ -362,6 +367,10 @@ public final class BroadcastQueue {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r + " DELIVERED for app " + app);
started = true;
+ FrameworkStatsLog.write(BROADCAST_DELIVERY_EVENT_REPORTED, app.uid,
+ r.callingUid == -1 ? Process.SYSTEM_UID : r.callingUid,
+ ActivityManagerService.getShortAction(r.intent.getAction()),
+ receiverType, processTemperature);
} finally {
if (!started) {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
@@ -398,7 +407,9 @@ public final class BroadcastQueue {
}
try {
mPendingBroadcast = null;
- processCurBroadcastLocked(br, app);
+ processCurBroadcastLocked(br, app,
+ BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__MANIFEST,
+ BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD);
didSomething = true;
} catch (Exception e) {
Slog.w(TAG, "Exception in new application when starting receiver "
@@ -628,8 +639,8 @@ public final class BroadcastQueue {
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
- boolean ordered, boolean sticky, int sendingUser)
- throws RemoteException {
+ boolean ordered, boolean sticky, int sendingUser,
+ int receiverUid, int callingUid) throws RemoteException {
// Send the intent to the receiver asynchronously using one-way binder calls.
if (app != null) {
final IApplicationThread thread = app.getThread();
@@ -663,6 +674,12 @@ public final class BroadcastQueue {
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
+ FrameworkStatsLog.write(BROADCAST_DELIVERY_EVENT_REPORTED,
+ receiverUid == -1 ? Process.SYSTEM_UID : receiverUid,
+ callingUid == -1 ? Process.SYSTEM_UID : callingUid,
+ ActivityManagerService.getShortAction(intent.getAction()),
+ BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__RUNTIME,
+ BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM);
}
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
@@ -965,7 +982,8 @@ public final class BroadcastQueue {
maybeReportBroadcastDispatchedEventLocked(r, filter.owningUid);
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
- r.resultExtras, r.ordered, r.initialSticky, r.userId);
+ r.resultExtras, r.ordered, r.initialSticky, r.userId,
+ filter.receiverList.uid, r.callingUid);
// parallel broadcasts are fire-and-forget, not bookended by a call to
// finishReceiverLocked(), so we manage their activity-start token here
if (filter.receiverList.app != null
@@ -1317,7 +1335,8 @@ public final class BroadcastQueue {
}
performReceiveLocked(r.callerApp, r.resultTo,
new Intent(r.intent), r.resultCode,
- r.resultData, r.resultExtras, false, false, r.userId);
+ r.resultData, r.resultExtras, false, false, r.userId,
+ r.callingUid, r.callingUid);
logBootCompletedBroadcastCompletionLatencyIfPossible(r);
// Set this to null so that the reference
// (local and remote) isn't kept in the mBroadcastHistory.
@@ -1837,7 +1856,9 @@ public final class BroadcastQueue {
app.addPackage(info.activityInfo.packageName,
info.activityInfo.applicationInfo.longVersionCode, mService.mProcessStats);
maybeAddAllowBackgroundActivityStartsToken(app, r);
- processCurBroadcastLocked(r, app);
+ processCurBroadcastLocked(r, app,
+ BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__MANIFEST,
+ BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when sending broadcast to "
diff --git a/services/core/java/com/android/server/audio/RotationHelper.java b/services/core/java/com/android/server/audio/RotationHelper.java
index d4f4245f19c5..eb8387fe85e5 100644
--- a/services/core/java/com/android/server/audio/RotationHelper.java
+++ b/services/core/java/com/android/server/audio/RotationHelper.java
@@ -20,12 +20,13 @@ import android.content.Context;
import android.hardware.devicestate.DeviceStateManager;
import android.hardware.devicestate.DeviceStateManager.FoldStateListener;
import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerGlobal;
import android.media.AudioSystem;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.util.Log;
+import android.view.Display;
import android.view.Surface;
-import android.view.WindowManager;
/**
* Class to handle device rotation events for AudioService, and forward device rotation
@@ -48,6 +49,8 @@ class RotationHelper {
private static final String TAG = "AudioService.RotationHelper";
+ private static final boolean DEBUG_ROTATION = false;
+
private static AudioDisplayListener sDisplayListener;
private static FoldStateListener sFoldStateListener;
@@ -98,8 +101,8 @@ class RotationHelper {
// Even though we're responding to device orientation events,
// use display rotation so audio stays in sync with video/dialogs
// TODO(b/148458001): Support multi-display
- int newRotation = ((WindowManager) sContext.getSystemService(
- Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
+ int newRotation = DisplayManagerGlobal.getInstance()
+ .getDisplayInfo(Display.DEFAULT_DISPLAY).rotation;
synchronized(sRotationLock) {
if (newRotation != sDeviceRotation) {
sDeviceRotation = newRotation;
@@ -109,7 +112,9 @@ class RotationHelper {
}
private static void publishRotation(int rotation) {
- Log.v(TAG, "publishing device rotation =" + rotation + " (x90deg)");
+ if (DEBUG_ROTATION) {
+ Log.i(TAG, "publishing device rotation =" + rotation + " (x90deg)");
+ }
switch (rotation) {
case Surface.ROTATION_0:
AudioSystem.setParameters("rotation=0");
@@ -159,6 +164,9 @@ class RotationHelper {
@Override
public void onDisplayChanged(int displayId) {
+ if (DEBUG_ROTATION) {
+ Log.i(TAG, "onDisplayChanged diplayId:" + displayId);
+ }
updateOrientation();
}
}
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index cf63b69254f8..6fd88411593f 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -1057,7 +1057,17 @@ class AutomaticBrightnessController {
public void recalculateSplines(boolean applyAdjustment, float[] adjustment) {
mCurrentBrightnessMapper.recalculateSplines(applyAdjustment, adjustment);
- updateAutoBrightness(true /*sendUpdate*/, false /*isManuallySet*/);
+
+ // If rbc is turned on, off or there is a change in strength, we want to reset the short
+ // term model. Since the nits range at which brightness now operates has changed due to
+ // RBC/strength change, any short term model based on the previous range should be
+ // invalidated.
+ resetShortTermModel();
+
+ // When rbc is turned on, we want to accommodate this change in the short term model.
+ if (applyAdjustment) {
+ setScreenBrightnessByUser(getAutomaticScreenBrightness());
+ }
}
private final class AutomaticBrightnessHandler extends Handler {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 6285ef1fdabd..d3e2966c6df0 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -485,7 +485,7 @@ public final class DisplayManagerService extends SystemService {
mUiHandler = UiThread.getHandler();
mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);
mLogicalDisplayMapper = new LogicalDisplayMapper(mContext, mDisplayDeviceRepo,
- new LogicalDisplayListener(), mSyncRoot, mHandler);
+ new LogicalDisplayListener(), mSyncRoot, mHandler, new DeviceStateToLayoutMap());
mDisplayModeDirector = new DisplayModeDirector(context, mHandler);
mBrightnessSynchronizer = new BrightnessSynchronizer(mContext);
Resources resources = mContext.getResources();
@@ -945,7 +945,8 @@ public final class DisplayManagerService extends SystemService {
private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) {
synchronized (mSyncRoot) {
- final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
+ final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId,
+ /* includeDisabledDisplays= */ true);
if (display != null) {
final DisplayInfo info =
getDisplayInfoForFrameRateOverride(display.getFrameRateOverrides(),
@@ -2128,16 +2129,18 @@ public final class DisplayManagerService extends SystemService {
}
void resetBrightnessConfigurations() {
- mPersistentDataStore.setBrightnessConfigurationForUser(null, mContext.getUserId(),
- mContext.getPackageName());
- mLogicalDisplayMapper.forEachLocked((logicalDisplay -> {
- if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) {
- return;
- }
- final String uniqueId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
- setBrightnessConfigurationForDisplayInternal(null, uniqueId, mContext.getUserId(),
+ synchronized (mSyncRoot) {
+ mPersistentDataStore.setBrightnessConfigurationForUser(null, mContext.getUserId(),
mContext.getPackageName());
- }));
+ mLogicalDisplayMapper.forEachLocked((logicalDisplay -> {
+ if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) {
+ return;
+ }
+ String uniqueId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
+ setBrightnessConfigurationForDisplayInternal(null, uniqueId, mContext.getUserId(),
+ mContext.getPackageName());
+ }));
+ }
}
void setAutoBrightnessLoggingEnabled(boolean enabled) {
@@ -2814,15 +2817,16 @@ public final class DisplayManagerService extends SystemService {
}
/**
- * Returns the list of all display ids.
+ * Returns the list of all enabled display ids, and disabled ones if specified.
*/
@Override // Binder call
- public int[] getDisplayIds() {
+ public int[] getDisplayIds(boolean includeDisabledDisplays) {
final int callingUid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
- return mLogicalDisplayMapper.getDisplayIdsLocked(callingUid);
+ return mLogicalDisplayMapper.getDisplayIdsLocked(callingUid,
+ includeDisabledDisplays);
}
} finally {
Binder.restoreCallingIdentity(token);
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index a5bb716e67b7..d05a902c6593 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -657,12 +657,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
mIsRbcActive = mCdsi.isReduceBrightColorsActivated();
mAutomaticBrightnessController.recalculateSplines(mIsRbcActive, adjustedNits);
-
- // If rbc is turned on, off or there is a change in strength, we want to reset the short
- // term model. Since the nits range at which brightness now operates has changed due to
- // RBC/strength change, any short term model based on the previous range should be
- // invalidated.
- mAutomaticBrightnessController.resetShortTermModel();
}
/**
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index 70c9e23c6af8..34e8e75314ce 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -79,8 +79,12 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
private static final int MSG_TRANSITION_TO_PENDING_DEVICE_STATE = 1;
private static final int UPDATE_STATE_NEW = 0;
- private static final int UPDATE_STATE_TRANSITION = 1;
- private static final int UPDATE_STATE_UPDATED = 2;
+ private static final int UPDATE_STATE_UPDATED = 1;
+ private static final int UPDATE_STATE_DISABLED = 2;
+
+ private static final int UPDATE_STATE_MASK = 0x3;
+
+ private static final int UPDATE_STATE_FLAG_TRANSITION = 0x100;
/**
* Temporary display info, used for comparing display configurations.
@@ -166,7 +170,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo,
@NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
- @NonNull Handler handler) {
+ @NonNull Handler handler, @NonNull DeviceStateToLayoutMap deviceStateToLayoutMap) {
mSyncRoot = syncRoot;
mPowerManager = context.getSystemService(PowerManager.class);
mInteractive = mPowerManager.isInteractive();
@@ -181,7 +185,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
mDeviceStatesOnWhichToSleep = toSparseBooleanArray(context.getResources().getIntArray(
com.android.internal.R.array.config_deviceStatesOnWhichToSleep));
mDisplayDeviceRepo.addListener(this);
- mDeviceStateToLayoutMap = new DeviceStateToLayoutMap();
+ mDeviceStateToLayoutMap = deviceStateToLayoutMap;
}
@Override
@@ -218,10 +222,29 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
}
public LogicalDisplay getDisplayLocked(int displayId) {
- return mLogicalDisplays.get(displayId);
+ return getDisplayLocked(displayId, /* includeDisabled= */ false);
+ }
+
+ LogicalDisplay getDisplayLocked(int displayId, boolean includeDisabled) {
+ LogicalDisplay display = mLogicalDisplays.get(displayId);
+ if (display != null && (display.isEnabled() || includeDisabled)) {
+ return display;
+ }
+ return null;
}
public LogicalDisplay getDisplayLocked(DisplayDevice device) {
+ return getDisplayLocked(device, /* includeDisabled= */ false);
+ }
+
+ /**
+ * Loops through the existing list of displays and returns one that is associated with the
+ * specified display device.
+ *
+ * @param device The display device that should be associated with the LogicalDisplay.
+ * @param includeDisabled True if this method should return disabled displays as well.
+ */
+ private LogicalDisplay getDisplayLocked(DisplayDevice device, boolean includeDisabled) {
if (device == null) {
return null;
}
@@ -229,18 +252,32 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
for (int i = 0; i < count; i++) {
final LogicalDisplay display = mLogicalDisplays.valueAt(i);
if (display.getPrimaryDisplayDeviceLocked() == device) {
- return display;
+ if (display.isEnabled() || includeDisabled) {
+ return display;
+ } else {
+ return null;
+ }
}
}
return null;
}
+ // Returns display Ids, defaults to enabled only.
public int[] getDisplayIdsLocked(int callingUid) {
+ return getDisplayIdsLocked(callingUid, /* includeDisabledDisplays= */ false);
+ }
+
+ // Returns display Ids, specified whether enabled only, or all displays.
+ public int[] getDisplayIdsLocked(int callingUid, boolean includeDisabledDisplays) {
final int count = mLogicalDisplays.size();
int[] displayIds = new int[count];
int n = 0;
for (int i = 0; i < count; i++) {
LogicalDisplay display = mLogicalDisplays.valueAt(i);
+ if (!includeDisabledDisplays && !display.isEnabled()) {
+ continue; // Ignore disabled displays.
+ }
+
DisplayInfo info = display.getDisplayInfoLocked();
if (info.hasAccess(callingUid)) {
displayIds[n++] = mLogicalDisplays.keyAt(i);
@@ -255,7 +292,10 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
public void forEachLocked(Consumer<LogicalDisplay> consumer) {
final int count = mLogicalDisplays.size();
for (int i = 0; i < count; i++) {
- consumer.accept(mLogicalDisplays.valueAt(i));
+ LogicalDisplay display = mLogicalDisplays.valueAt(i);
+ if (display.isEnabled()) {
+ consumer.accept(display);
+ }
}
}
@@ -316,7 +356,8 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
// Find or create the LogicalDisplay to map the DisplayDevice to.
final int logicalDisplayId = displayLayout.getLogicalDisplayId();
- final LogicalDisplay logicalDisplay = getDisplayLocked(logicalDisplayId);
+ final LogicalDisplay logicalDisplay =
+ getDisplayLocked(logicalDisplayId, /* includeDisabled= */ true);
if (logicalDisplay == null) {
Slog.w(TAG, "The logical display (" + address + "), is not available"
+ " for the display state " + deviceState);
@@ -452,7 +493,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
}
/**
- * Returns if the device should be put to sleep or not.
+ * Returns true if the device should be put to sleep or not.
*
* Includes a check to verify that the device state that we are moving to, {@code pendingState},
* is the same as the physical state of the device, {@code baseState}. Different values for
@@ -598,9 +639,12 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
display.getNonOverrideDisplayInfoLocked(mTempNonOverrideDisplayInfo);
display.updateLocked(mDisplayDeviceRepo);
- final DisplayInfo newDisplayInfo = display.getDisplayInfoLocked();
- final int updateState = mUpdatedLogicalDisplays.get(displayId, UPDATE_STATE_NEW);
- final boolean wasPreviouslyUpdated = updateState != UPDATE_STATE_NEW;
+ DisplayInfo newDisplayInfo = display.getDisplayInfoLocked();
+
+ final int storedState = mUpdatedLogicalDisplays.get(displayId, UPDATE_STATE_NEW);
+ final int updateState = storedState & UPDATE_STATE_MASK;
+ final boolean isTransitioning = (storedState & UPDATE_STATE_FLAG_TRANSITION) != 0;
+ final boolean wasPreviouslyUpdated = updateState == UPDATE_STATE_UPDATED;
// The display is no longer valid and needs to be removed.
if (!display.isValidLocked()) {
@@ -624,6 +668,35 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
}
continue;
+ // The display has been newly disabled, we report this as a removed display but
+ // don't actually remove it from our internal list in LogicalDisplayMapper. The reason
+ // is that LogicalDisplayMapper assumes and relies on the fact that every DisplayDevice
+ // has a LogicalDisplay wrapper, but certain displays that are unusable (like the inner
+ // display on a folded foldable device) are not available for use by the system and
+ // we keep them hidden. To do this, we mark those LogicalDisplays as "disabled".
+ // Also, if the display is in TRANSITION but was previously reported as disabled
+ // then keep it unreported.
+ } else if (!display.isEnabled()
+ || (display.getPhase() == LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION
+ && updateState == UPDATE_STATE_DISABLED)) {
+ mUpdatedLogicalDisplays.put(displayId, UPDATE_STATE_DISABLED);
+
+ // If we never told anyone about this display, nothing to do
+ if (!wasPreviouslyUpdated) {
+ continue;
+ }
+
+ // Remove from group
+ final DisplayGroup displayGroup = getDisplayGroupLocked(
+ getDisplayGroupIdFromDisplayIdLocked(displayId));
+ if (displayGroup != null) {
+ displayGroup.removeDisplayLocked(display);
+ }
+
+ Slog.i(TAG, "Removing (disabled) display: " + displayId);
+ mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_REMOVED);
+ continue;
+
// The display is new.
} else if (!wasPreviouslyUpdated) {
Slog.i(TAG, "Adding new display: " + displayId + ": " + newDisplayInfo);
@@ -643,7 +716,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_CHANGED);
// The display is involved in a display layout transition
- } else if (updateState == UPDATE_STATE_TRANSITION) {
+ } else if (isTransitioning) {
mLogicalDisplaysToUpdate.put(displayId,
LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION);
@@ -717,7 +790,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
}
final int id = mLogicalDisplaysToUpdate.keyAt(i);
- final LogicalDisplay display = getDisplayLocked(id);
+ final LogicalDisplay display = getDisplayLocked(id, /* includeDisabled= */ true);
if (DEBUG) {
final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
final String uniqueId = device == null ? "null" : device.getUniqueId();
@@ -725,7 +798,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
+ " with device=" + uniqueId);
}
mListener.onLogicalDisplayEventLocked(display, msg);
- if (msg == LOGICAL_DISPLAY_EVENT_REMOVED) {
+ if (msg == LOGICAL_DISPLAY_EVENT_REMOVED && !display.isValidLocked()) {
// We wait until we sent the EVENT_REMOVED event before actually removing the
// display.
mLogicalDisplays.delete(id);
@@ -845,7 +918,8 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
if (isTransitioning) {
setDisplayPhase(logicalDisplay, phase);
if (phase == LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION) {
- mUpdatedLogicalDisplays.put(displayId, UPDATE_STATE_TRANSITION);
+ int oldState = mUpdatedLogicalDisplays.get(displayId, UPDATE_STATE_NEW);
+ mUpdatedLogicalDisplays.put(displayId, oldState | UPDATE_STATE_FLAG_TRANSITION);
}
}
}
@@ -879,14 +953,15 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
// Now that we have a display-device, we need a LogicalDisplay to map it to. Find the
// right one, if it doesn't exist, create a new one.
final int logicalDisplayId = displayLayout.getLogicalDisplayId();
- LogicalDisplay newDisplay = getDisplayLocked(logicalDisplayId);
+ LogicalDisplay newDisplay =
+ getDisplayLocked(logicalDisplayId, /* includeDisabled= */ true);
if (newDisplay == null) {
newDisplay = createNewLogicalDisplayLocked(
- null /*displayDevice*/, logicalDisplayId);
+ /* displayDevice= */ null, logicalDisplayId);
}
// Now swap the underlying display devices between the old display and the new display
- final LogicalDisplay oldDisplay = getDisplayLocked(device);
+ final LogicalDisplay oldDisplay = getDisplayLocked(device, /* includeDisabled= */ true);
if (newDisplay != oldDisplay) {
newDisplay.swapDisplaysLocked(oldDisplay);
}
@@ -903,13 +978,14 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
* Creates a new logical display for the specified device and display Id and adds it to the list
* of logical displays.
*
- * @param device The device to associate with the LogicalDisplay.
+ * @param displayDevice The displayDevice to associate with the LogicalDisplay.
* @param displayId The display ID to give the new display. If invalid, a new ID is assigned.
* @return The new logical display if created, null otherwise.
*/
- private LogicalDisplay createNewLogicalDisplayLocked(DisplayDevice device, int displayId) {
+ private LogicalDisplay createNewLogicalDisplayLocked(DisplayDevice displayDevice,
+ int displayId) {
final int layerStack = assignLayerStackLocked(displayId);
- final LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
+ final LogicalDisplay display = new LogicalDisplay(displayId, layerStack, displayDevice);
display.updateLocked(mDisplayDeviceRepo);
mLogicalDisplays.put(displayId, display);
setDisplayPhase(display, LogicalDisplay.DISPLAY_PHASE_ENABLED);
diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java
index 59daee9ea2ff..b9a0738d15c4 100644
--- a/services/core/java/com/android/server/display/PersistentDataStore.java
+++ b/services/core/java/com/android/server/display/PersistentDataStore.java
@@ -153,7 +153,7 @@ final class PersistentDataStore {
@VisibleForTesting
PersistentDataStore(Injector injector) {
- this(injector, BackgroundThread.getHandler());
+ this(injector, new Handler(BackgroundThread.getHandler().getLooper()));
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index d536a463f7b4..b89147ea181a 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -563,14 +563,16 @@ public class MediaSessionService extends SystemService implements Monitor {
try {
enforcePackageName(callingPackage, callingUid);
if (targetUid != callingUid) {
- Log.d(TAG, "tempAllowlistTargetPkgIfPossible callingPackage:"
- + callingPackage + " targetPackage:" + targetPackage
- + " reason:" + reason);
boolean canAllowWhileInUse = mActivityManagerLocal
.canAllowWhileInUsePermissionInFgs(callingPid, callingUid, callingPackage);
boolean canStartFgs = canAllowWhileInUse
|| mActivityManagerLocal.canStartForegroundService(callingPid, callingUid,
callingPackage);
+ Log.i(TAG, "tempAllowlistTargetPkgIfPossible callingPackage:"
+ + callingPackage + " targetPackage:" + targetPackage
+ + " reason:" + reason
+ + (canAllowWhileInUse ? " [WIU]" : "")
+ + (canStartFgs ? " [FGS]" : ""));
if (canAllowWhileInUse) {
mActivityManagerLocal.tempAllowWhileInUsePermissionInFgs(targetUid,
MediaSessionDeviceConfig
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
index 67aed4506b27..3cd7795005a7 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
@@ -317,7 +317,7 @@ public class DomainVerificationService extends SystemService
mEnforcer.assertApprovedVerifier(callingUid, mProxy);
final Computer snapshot = mConnection.snapshot();
synchronized (mLock) {
- List<String> verifiedDomains = new ArrayList<>();
+ List<String> newlyVerifiedDomains = new ArrayList<>();
GetAttachedResult result = getAndValidateAttachedLocked(domainSetId, domains,
true /* forAutoVerify */, callingUid, null /* userId */, snapshot);
@@ -329,21 +329,28 @@ public class DomainVerificationService extends SystemService
ArrayMap<String, Integer> stateMap = pkgState.getStateMap();
for (String domain : domains) {
Integer previousState = stateMap.get(domain);
- if (previousState != null
- && !DomainVerificationState.isModifiable(previousState)) {
- continue;
+ // Skip if the state hasn't changed or can't be changed
+ if (previousState != null) {
+ if (previousState == state
+ || !DomainVerificationState.isModifiable(previousState)) {
+ continue;
+ }
}
if (DomainVerificationState.isVerified(state)) {
- verifiedDomains.add(domain);
+ if (previousState == null
+ || !DomainVerificationState.isVerified(previousState)) {
+ newlyVerifiedDomains.add(domain);
+ }
}
stateMap.put(domain, state);
}
- int size = verifiedDomains.size();
+ // For newly verified domains, revoke their user states across other packages
+ int size = newlyVerifiedDomains.size();
for (int index = 0; index < size; index++) {
- removeUserStatesForDomain(verifiedDomains.get(index));
+ removeUserStatesForDomain(pkgState, newlyVerifiedDomains.get(index));
}
}
@@ -367,7 +374,6 @@ public class DomainVerificationService extends SystemService
"State must be one of NO_RESPONSE, SUCCESS, APPROVED, or DENIED");
}
- ArraySet<String> verifiedDomains = new ArraySet<>();
if (packageName == null) {
final Computer snapshot = mConnection.snapshot();
synchronized (mLock) {
@@ -395,10 +401,6 @@ public class DomainVerificationService extends SystemService
validDomains.retainAll(autoVerifyDomains);
}
- if (DomainVerificationState.isVerified(state)) {
- verifiedDomains.addAll(validDomains);
- }
-
setDomainVerificationStatusInternal(pkgState, state, validDomains);
}
}
@@ -424,19 +426,33 @@ public class DomainVerificationService extends SystemService
validDomains.retainAll(mCollector.collectValidAutoVerifyDomains(pkg));
}
+ ArraySet<String> newlyVerifiedDomains = null;
if (DomainVerificationState.isVerified(state)) {
- verifiedDomains.addAll(validDomains);
+ newlyVerifiedDomains = new ArraySet<>();
+ ArrayMap<String, Integer> stateMap = pkgState.getStateMap();
+ int domainsSize = validDomains.size();
+ for (int domainIndex = 0; domainIndex < domainsSize; domainIndex++) {
+ String domain = validDomains.valueAt(domainIndex);
+ Integer oldState = stateMap.get(domain);
+ // Only remove if not previously verified
+ if (oldState == null || !DomainVerificationState.isVerified(oldState)) {
+ newlyVerifiedDomains.add(domain);
+ }
+ }
}
setDomainVerificationStatusInternal(pkgState, state, validDomains);
- }
- }
- // Mirror SystemApi behavior of revoking user selection for approved domains.
- if (DomainVerificationState.isVerified(state)) {
- final int size = verifiedDomains.size();
- for (int index = 0; index < size; index++) {
- removeUserStatesForDomain(verifiedDomains.valueAt(index));
+ // Mirror SystemApi behavior of revoking user selection for approved domains.
+ // This is done in a second pass so that the previous state can be compared before
+ // the previous method overwrites it with the new state.
+ if (newlyVerifiedDomains != null) {
+ int domainsSize = newlyVerifiedDomains.size();
+ for (int domainIndex = 0; domainIndex < domainsSize; domainIndex++) {
+ String domain = newlyVerifiedDomains.valueAt(domainIndex);
+ removeUserStatesForDomain(pkgState, domain);
+ }
+ }
}
}
@@ -452,7 +468,10 @@ public class DomainVerificationService extends SystemService
}
}
- private void removeUserStatesForDomain(@NonNull String domain) {
+ private void removeUserStatesForDomain(@NonNull DomainVerificationPkgState owningPkgState,
+ @NonNull String domain) {
+ SparseArray<DomainVerificationInternalUserState> owningUserStates =
+ owningPkgState.getUserStates();
synchronized (mLock) {
final int size = mAttachedPkgStates.size();
for (int index = 0; index < size; index++) {
@@ -460,6 +479,15 @@ public class DomainVerificationService extends SystemService
SparseArray<DomainVerificationInternalUserState> array = pkgState.getUserStates();
int arraySize = array.size();
for (int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) {
+ int userId = array.keyAt(arrayIndex);
+ DomainVerificationInternalUserState owningUserState =
+ owningUserStates.get(userId);
+ if (owningUserState != null && !owningUserState.isLinkHandlingAllowed()) {
+ // Skip users where the owning package has their link handling disabled,
+ // since revoking those users would lead to no apps being able to handle
+ // the domain.
+ continue;
+ }
array.valueAt(arrayIndex).removeHost(domain);
}
}
@@ -527,6 +555,8 @@ public class DomainVerificationService extends SystemService
mConnection.scheduleWriteSettings();
}
+ @CheckResult
+ @DomainVerificationManager.Error
public int setDomainVerificationUserSelection(@NonNull UUID domainSetId,
@NonNull Set<String> domains, boolean enabled, @UserIdInt int userId)
throws NameNotFoundException {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 859b4df3baa6..5c473d8c67f5 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -432,6 +432,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
private static final int DESTROY_TIMEOUT = 10 * 1000;
final ActivityTaskManagerService mAtmService;
+ @NonNull
final ActivityInfo info; // activity info provided by developer in AndroidManifest
// Which user is this running for?
final int mUserId;
@@ -4299,9 +4300,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mTransitionController.collect(tStartingWindow);
tStartingWindow.reparent(this, POSITION_TOP);
- // Propagate other interesting state between the tokens. If the old token is displayed,
- // we should immediately force the new one to be displayed. If it is animating, we need
- // to move that animation to the new one.
+ // Clear the frozen insets state when transferring the existing starting window to
+ // the next target activity. In case the frozen state from a trampoline activity
+ // affecting the starting window frame computation to see the window being
+ // clipped if the rotation change during the transition animation.
+ tStartingWindow.clearFrozenInsetsState();
+
+ // Propagate other interesting state between the tokens. If the old token is
+ // displayed, we should immediately force the new one to be displayed. If it is
+ // animating, we need to move that animation to the new one.
if (fromActivity.allDrawn) {
allDrawn = true;
}
@@ -9707,6 +9714,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return true;
}
+ @Nullable
+ Point getMinDimensions() {
+ final ActivityInfo.WindowLayout windowLayout = info.windowLayout;
+ if (windowLayout == null) {
+ return null;
+ }
+ return new Point(windowLayout.minWidth, windowLayout.minHeight);
+ }
+
static class Builder {
private final ActivityTaskManagerService mAtmService;
private WindowProcessController mCallerApp;
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index d60981fcf504..32ed4725b3b4 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -508,7 +508,8 @@ public class ActivityStartController {
*/
int startActivityInTaskFragment(@NonNull TaskFragment taskFragment,
@NonNull Intent activityIntent, @Nullable Bundle activityOptions,
- @Nullable IBinder resultTo, int callingUid, int callingPid) {
+ @Nullable IBinder resultTo, int callingUid, int callingPid,
+ @Nullable IBinder errorCallbackToken) {
final ActivityRecord caller =
resultTo != null ? ActivityRecord.forTokenLocked(resultTo) : null;
return obtainStarter(activityIntent, "startActivityInTaskFragment")
@@ -521,6 +522,7 @@ public class ActivityStartController {
.setRealCallingUid(callingUid)
.setRealCallingPid(callingPid)
.setUserId(caller != null ? caller.mUserId : mService.getCurrentUserId())
+ .setErrorCallbackToken(errorCallbackToken)
.execute();
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index fb87576ba809..84cd63424cd1 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -89,7 +89,6 @@ import android.app.PendingIntent;
import android.app.ProfilerInfo;
import android.app.WaitResult;
import android.app.WindowConfiguration;
-import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.content.ComponentName;
@@ -369,6 +368,13 @@ class ActivityStarter {
int filterCallingUid;
PendingIntentRecord originatingPendingIntent;
boolean allowBackgroundActivityStart;
+ /**
+ * The error callback token passed in {@link android.window.WindowContainerTransaction}
+ * for TaskFragment operation error handling via
+ * {@link android.window.TaskFragmentOrganizer#onTaskFragmentError(IBinder, Throwable)}.
+ */
+ @Nullable
+ IBinder errorCallbackToken;
/**
* If set to {@code true}, allows this activity start to look into
@@ -422,6 +428,7 @@ class ActivityStarter {
filterCallingUid = UserHandle.USER_NULL;
originatingPendingIntent = null;
allowBackgroundActivityStart = false;
+ errorCallbackToken = null;
}
/**
@@ -464,6 +471,7 @@ class ActivityStarter {
filterCallingUid = request.filterCallingUid;
originatingPendingIntent = request.originatingPendingIntent;
allowBackgroundActivityStart = request.allowBackgroundActivityStart;
+ errorCallbackToken = request.errorCallbackToken;
}
/**
@@ -2889,6 +2897,7 @@ class ActivityStarter {
private void addOrReparentStartingActivity(@NonNull Task task, String reason) {
TaskFragment newParent = task;
if (mInTaskFragment != null) {
+ // TODO(b/234351413): remove remaining embedded Task logic.
// mInTaskFragment is created and added to the leaf task by task fragment organizer's
// request. If the task was resolved and different than mInTaskFragment, reparent the
// task to mInTaskFragment for embedding.
@@ -2915,7 +2924,14 @@ class ActivityStarter {
newParent = candidateTf;
}
}
-
+ // Start Activity to the Task if mStartActivity's min dimensions are not satisfied.
+ if (newParent.isEmbedded() && newParent.smallerThanMinDimension(mStartActivity)) {
+ reason += " - MinimumDimensionViolation";
+ mService.mWindowOrganizerController.sendMinimumDimensionViolation(
+ newParent, mStartActivity.getMinDimensions(), mRequest.errorCallbackToken,
+ reason);
+ newParent = task;
+ }
if (mStartActivity.getTaskFragment() == null
|| mStartActivity.getTaskFragment() == newParent) {
newParent.addChild(mStartActivity, POSITION_TOP);
@@ -3200,6 +3216,11 @@ class ActivityStarter {
return this;
}
+ ActivityStarter setErrorCallbackToken(@Nullable IBinder errorCallbackToken) {
+ mRequest.errorCallbackToken = errorCallbackToken;
+ return this;
+ }
+
void dump(PrintWriter pw, String prefix) {
pw.print(prefix);
pw.print("mCurrentUser=");
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index eca0fd77fcb9..1d328671876f 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -152,6 +152,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
final RootWindowContainer mRootWindowContainer;
private final TaskFragmentOrganizerController mTaskFragmentOrganizerController;
+ // TODO(b/233177466): Move mMinWidth and mMinHeight to Task and remove usages in TaskFragment
/**
* Minimal width of this task fragment when it's resizeable. {@link #INVALID_MIN_SIZE} means it
* should use the default minimal width.
@@ -535,6 +536,25 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|| isAllowedToEmbedActivityInTrustedMode(a, uid);
}
+ boolean smallerThanMinDimension(@NonNull ActivityRecord activity) {
+ final Rect taskFragBounds = getBounds();
+ final Task task = getTask();
+ // Don't need to check if the bounds match parent Task bounds because the fallback mechanism
+ // is to reparent the Activity to parent if minimum dimensions are not satisfied.
+ if (task == null || taskFragBounds.equals(task.getBounds())) {
+ return false;
+ }
+ final Point minDimensions = activity.getMinDimensions();
+ if (minDimensions == null) {
+ return false;
+ }
+ final int minWidth = minDimensions.x;
+ final int minHeight = minDimensions.y;
+ final boolean smaller = taskFragBounds.width() < minWidth
+ || taskFragBounds.height() < minHeight;
+ return smaller;
+ }
+
/**
* Checks if the organized task fragment is allowed to embed activity in untrusted mode.
*/
@@ -1755,7 +1775,8 @@ class TaskFragment extends WindowContainer<WindowContainer> {
mClearedTaskForReuse = false;
mClearedTaskFragmentForPip = false;
- boolean isAddingActivity = child.asActivityRecord() != null;
+ final ActivityRecord addingActivity = child.asActivityRecord();
+ final boolean isAddingActivity = addingActivity != null;
final Task task = isAddingActivity ? getTask() : null;
// If this task had any activity before we added this one.
@@ -1780,7 +1801,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
mBackScreenshots.put(r.mActivityComponent.flattenToString(), backBuffer);
}
child.asActivityRecord().inHistory = true;
- task.onDescendantActivityAdded(taskHadActivity, activityType, child.asActivityRecord());
+ task.onDescendantActivityAdded(taskHadActivity, activityType, addingActivity);
}
}
@@ -2294,7 +2315,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
TaskFragmentInfo getTaskFragmentInfo() {
List<IBinder> childActivities = new ArrayList<>();
for (int i = 0; i < getChildCount(); i++) {
- final WindowContainer wc = getChildAt(i);
+ final WindowContainer<?> wc = getChildAt(i);
final ActivityRecord ar = wc.asActivityRecord();
if (mTaskFragmentOrganizerUid != INVALID_UID && ar != null
&& ar.info.processName.equals(mTaskFragmentOrganizerProcessName)
@@ -2314,7 +2335,31 @@ class TaskFragment extends WindowContainer<WindowContainer> {
childActivities,
positionInParent,
mClearedTaskForReuse,
- mClearedTaskFragmentForPip);
+ mClearedTaskFragmentForPip,
+ calculateMinDimension());
+ }
+
+ /**
+ * Calculates the minimum dimensions that this TaskFragment can be resized.
+ * @see TaskFragmentInfo#getMinimumWidth()
+ * @see TaskFragmentInfo#getMinimumHeight()
+ */
+ Point calculateMinDimension() {
+ final int[] maxMinWidth = new int[1];
+ final int[] maxMinHeight = new int[1];
+
+ forAllActivities(a -> {
+ if (a.finishing) {
+ return;
+ }
+ final Point minDimensions = a.getMinDimensions();
+ if (minDimensions == null) {
+ return;
+ }
+ maxMinWidth[0] = Math.max(maxMinWidth[0], minDimensions.x);
+ maxMinHeight[0] = Math.max(maxMinHeight[0], minDimensions.y);
+ });
+ return new Point(maxMinWidth[0], maxMinHeight[0]);
}
@Nullable
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index ff3b4a5bb44f..22d6237411f3 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -18,6 +18,7 @@ package com.android.server.wm;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.ActivityManager.isStartResultSuccessful;
+import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_ADD_RECT_INSETS_PROVIDER;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT;
@@ -56,6 +57,7 @@ import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
+import android.graphics.Point;
import android.graphics.Rect;
import android.os.Binder;
import android.os.Bundle;
@@ -115,7 +117,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
static final int CONTROLLABLE_CONFIGS = ActivityInfo.CONFIG_WINDOW_CONFIGURATION
| ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE | ActivityInfo.CONFIG_SCREEN_SIZE
| ActivityInfo.CONFIG_LAYOUT_DIRECTION;
- static final int CONTROLLABLE_WINDOW_CONFIGS = WindowConfiguration.WINDOW_CONFIG_BOUNDS
+ static final int CONTROLLABLE_WINDOW_CONFIGS = WINDOW_CONFIG_BOUNDS
| WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS;
private final ActivityTaskManagerService mService;
@@ -421,7 +423,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
}
}
- int containerEffect = applyWindowContainerChange(wc, entry.getValue());
+ int containerEffect = applyWindowContainerChange(wc, entry.getValue(),
+ t.getErrorCallbackToken());
effects |= containerEffect;
// Lifecycle changes will trigger ensureConfig for everything.
@@ -503,7 +506,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
}
}
- private int applyChanges(WindowContainer container, WindowContainerTransaction.Change change) {
+ private int applyChanges(WindowContainer<?> container,
+ WindowContainerTransaction.Change change, @Nullable IBinder errorCallbackToken) {
// The "client"-facing API should prevent bad changes; however, just in case, sanitize
// masks here.
final int configMask = change.getConfigSetMask() & CONTROLLABLE_CONFIGS;
@@ -511,6 +515,9 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
int effects = 0;
final int windowingMode = change.getWindowingMode();
if (configMask != 0) {
+
+ adjustBoundsForMinDimensionsIfNeeded(container, change, errorCallbackToken);
+
if (windowingMode > -1 && windowingMode != container.getWindowingMode()) {
// Special handling for when we are setting a windowingMode in the same transaction.
// Setting the windowingMode is going to call onConfigurationChanged so we don't
@@ -556,6 +563,26 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
return effects;
}
+ private void adjustBoundsForMinDimensionsIfNeeded(WindowContainer<?> container,
+ WindowContainerTransaction.Change change, @Nullable IBinder errorCallbackToken) {
+ final TaskFragment taskFragment = container.asTaskFragment();
+ if (taskFragment == null || !taskFragment.isEmbedded()) {
+ return;
+ }
+ if ((change.getWindowSetMask() & WINDOW_CONFIG_BOUNDS) == 0) {
+ return;
+ }
+ final WindowConfiguration winConfig = change.getConfiguration().windowConfiguration;
+ final Rect bounds = winConfig.getBounds();
+ final Point minDimensions = taskFragment.calculateMinDimension();
+ if (bounds.width() < minDimensions.x || bounds.height() < minDimensions.y) {
+ sendMinimumDimensionViolation(taskFragment, minDimensions, errorCallbackToken,
+ "setBounds:" + bounds);
+ // Sets the bounds to match parent bounds.
+ winConfig.setBounds(new Rect());
+ }
+ }
+
private int applyTaskChanges(Task tr, WindowContainerTransaction.Change c) {
int effects = 0;
final SurfaceControl.Transaction t = c.getBoundsChangeTransaction();
@@ -696,7 +723,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
final Bundle activityOptions = hop.getLaunchOptions();
final int result = mService.getActivityStartController()
.startActivityInTaskFragment(tf, activityIntent, activityOptions,
- hop.getCallingActivity(), caller.mUid, caller.mPid);
+ hop.getCallingActivity(), caller.mUid, caller.mPid,
+ errorCallbackToken);
if (!isStartResultSuccessful(result)) {
sendTaskFragmentOperationFailure(organizer, errorCallbackToken,
convertStartFailureToThrowable(result, activityIntent));
@@ -740,6 +768,12 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception);
break;
}
+ if (parent.smallerThanMinDimension(activity)) {
+ sendMinimumDimensionViolation(parent, activity.getMinDimensions(),
+ errorCallbackToken, "reparentActivityToTask");
+ break;
+ }
+
activity.reparent(parent, POSITION_TOP);
effects |= TRANSACT_EFFECTS_LIFECYCLE;
break;
@@ -953,6 +987,19 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
return effects;
}
+ /** A helper method to send minimum dimension violation error to the client. */
+ void sendMinimumDimensionViolation(TaskFragment taskFragment, Point minDimensions,
+ IBinder errorCallbackToken, String reason) {
+ if (taskFragment == null || taskFragment.getTaskFragmentOrganizer() == null) {
+ return;
+ }
+ final Throwable exception = new SecurityException("The task fragment's bounds:"
+ + taskFragment.getBounds() + " does not satisfy minimum dimensions:"
+ + minDimensions + " " + reason);
+ sendTaskFragmentOperationFailure(taskFragment.getTaskFragmentOrganizer(),
+ errorCallbackToken, exception);
+ }
+
/**
* Post and wait for the result of the activity start to prevent potential deadlock against
* {@link WindowManagerGlobalLock}.
@@ -1164,14 +1211,14 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
}
private int applyWindowContainerChange(WindowContainer wc,
- WindowContainerTransaction.Change c) {
+ WindowContainerTransaction.Change c, @Nullable IBinder errorCallbackToken) {
sanitizeWindowContainer(wc);
if (wc.asTaskFragment() != null && wc.asTaskFragment().isEmbeddedTaskFragmentInPip()) {
// No override from organizer for embedded TaskFragment in a PIP Task.
return 0;
}
- int effects = applyChanges(wc, c);
+ int effects = applyChanges(wc, c, errorCallbackToken);
if (wc instanceof DisplayArea) {
effects |= applyDisplayAreaChanges(wc.asDisplayArea(), c);
@@ -1515,8 +1562,9 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
mLaunchTaskFragments.put(creationParams.getFragmentToken(), taskFragment);
}
- void reparentTaskFragment(@NonNull TaskFragment oldParent, @Nullable WindowContainer newParent,
- @Nullable ITaskFragmentOrganizer organizer, @Nullable IBinder errorCallbackToken) {
+ void reparentTaskFragment(@NonNull TaskFragment oldParent,
+ @Nullable WindowContainer<?> newParent, @Nullable ITaskFragmentOrganizer organizer,
+ @Nullable IBinder errorCallbackToken) {
final TaskFragment newParentTF;
if (newParent == null) {
// Use the old parent's parent if the caller doesn't specify the new parent.
@@ -1554,6 +1602,14 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception);
return;
}
+ final Point minDimensions = oldParent.calculateMinDimension();
+ final Rect newParentBounds = newParentTF.getBounds();
+ if (newParentBounds.width() < minDimensions.x
+ || newParentBounds.height() < minDimensions.y) {
+ sendMinimumDimensionViolation(newParentTF, minDimensions, errorCallbackToken,
+ "reparentTaskFragment");
+ return;
+ }
while (oldParent.hasChild()) {
oldParent.getChildAt(0).reparent(newParentTF, POSITION_TOP);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index cb78ad834541..590de7b5e119 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -9292,11 +9292,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
// Check profile owner first as that is what most likely is set.
- if (isSupervisionComponent(poComponent)) {
+ if (isSupervisionComponentLocked(poComponent)) {
return poComponent;
}
- if (isSupervisionComponent(doComponent)) {
+ if (isSupervisionComponentLocked(doComponent)) {
return doComponent;
}
@@ -9304,7 +9304,26 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
- private boolean isSupervisionComponent(@Nullable ComponentName who) {
+ /**
+ * Returns if the specified component is the supervision component.
+ */
+ @Override
+ public boolean isSupervisionComponent(@NonNull ComponentName who) {
+ if (!mHasFeature) {
+ return false;
+ }
+ synchronized (getLockObject()) {
+ if (mConstants.USE_TEST_ADMIN_AS_SUPERVISION_COMPONENT) {
+ final CallerIdentity caller = getCallerIdentity();
+ if (isAdminTestOnlyLocked(who, caller.getUserId())) {
+ return true;
+ }
+ }
+ return isSupervisionComponentLocked(who);
+ }
+ }
+
+ private boolean isSupervisionComponentLocked(@Nullable ComponentName who) {
if (who == null) {
return false;
}
@@ -9508,7 +9527,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
"Cannot set the profile owner on a user which is already set-up");
if (!mIsWatch) {
- if (!isSupervisionComponent(owner)) {
+ if (!isSupervisionComponentLocked(owner)) {
throw new IllegalStateException("Unable to set non-default profile owner"
+ " post-setup " + owner);
}
@@ -12102,8 +12121,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
synchronized (getLockObject()) {
// Allow testOnly admins to bypass supervision config requirement.
Preconditions.checkCallAuthorization(isAdminTestOnlyLocked(who, caller.getUserId())
- || isSupervisionComponent(caller.getComponentName()), "Admin %s is not the "
- + "default supervision component", caller.getComponentName());
+ || isSupervisionComponentLocked(caller.getComponentName()), "Admin %s is not "
+ + "the default supervision component", caller.getComponentName());
DevicePolicyData policy = getUserData(caller.getUserId());
policy.mSecondaryLockscreenEnabled = enabled;
saveSettingsLocked(caller.getUserId());
@@ -13004,7 +13023,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
- return isSupervisionComponent(admin.info.getComponent());
+ return isSupervisionComponentLocked(admin.info.getComponent());
}
}
diff --git a/services/proguard.flags b/services/proguard.flags
index bad02b47031c..c648f7d3ac45 100644
--- a/services/proguard.flags
+++ b/services/proguard.flags
@@ -68,6 +68,9 @@
# TODO(b/210510433): Revisit and consider generating from frameworks/base/core/res/res/values/config.xml.
-keep,allowoptimization,allowaccessmodification public class com.android.server.notification.** implements com.android.server.notification.NotificationSignalExtractor
+# OEM provided DisplayAreaPolicy.Provider defined in frameworks/base/core/res/res/values/config.xml.
+-keep,allowoptimization,allowaccessmodification class com.android.server.wm.** implements com.android.server.wm.DisplayAreaPolicy$Provider
+
# JNI keep rules
# TODO(b/210510433): Revisit and fix with @Keep, or consider auto-generating from
# frameworks/base/services/core/jni/onload.cpp.
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt
index 40f37a7ee1f7..ed60c5064eb1 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt
@@ -78,6 +78,8 @@ class DomainVerificationPackageTest {
private val DOMAIN_4 = "four.$DOMAIN_BASE"
private const val USER_ID = 0
+ private const val USER_ID_SECONDARY = 10
+ private val USER_IDS = listOf(USER_ID, USER_ID_SECONDARY)
}
private val pkg1 = mockPkgState(PKG_ONE, UUID_ONE, SIGNATURE_ONE)
@@ -813,6 +815,173 @@ class DomainVerificationPackageTest {
assertExpectedState(serviceAfter)
}
+ @Test
+ fun verifiedUnapproved_unverifiedSelected_approvalCausesUnselect_systemApi() {
+ verifiedUnapproved_unverifiedSelected_approvalCausesUnselect {
+ setDomainVerificationStatus(it.domainSetId, setOf(DOMAIN_1, DOMAIN_2), STATE_SUCCESS)
+ }
+ }
+
+ @Test
+ fun verifiedUnapproved_unverifiedSelected_approvalCausesUnselect_internalApi() {
+ verifiedUnapproved_unverifiedSelected_approvalCausesUnselect {
+ setDomainVerificationStatusInternal(it.packageName, STATE_SUCCESS,
+ ArraySet(setOf(DOMAIN_1, DOMAIN_2)))
+ }
+ }
+
+ private fun verifiedUnapproved_unverifiedSelected_approvalCausesUnselect(
+ setStatusBlock: DomainVerificationService.(PackageStateInternal) -> Unit
+ ) {
+ /*
+ Domains tested:
+ 1: Becomes verified in package 1, but package 1 disabled in secondary user, only
+ disables selection for package 2 in main user
+ 2: Becomes verified in package 1, unselected by package 2, remains unselected
+ 3: Is autoVerify, but unverified, selected by package 2, remains selected
+ 4: Non-autoVerify, selected by package 2, remains selected
+ */
+
+ val pkg1 = mockPkgState(
+ PKG_ONE,
+ UUID_ONE,
+ SIGNATURE_ONE,
+ autoVerifyDomains = listOf(DOMAIN_1, DOMAIN_2, DOMAIN_3),
+ otherDomains = listOf(DOMAIN_4)
+ )
+ val pkg2 = mockPkgState(
+ PKG_TWO,
+ UUID_TWO,
+ SIGNATURE_TWO,
+ autoVerifyDomains = emptyList(),
+ otherDomains = listOf(DOMAIN_1, DOMAIN_2, DOMAIN_3, DOMAIN_4)
+ )
+
+ val service = makeService(pkg1, pkg2)
+ service.addPackage(pkg1)
+ service.addPackage(pkg2)
+
+ // Approve domain 1, 3, and 4 for package 2 for both users
+ USER_IDS.forEach {
+ assertThat(
+ service.setDomainVerificationUserSelection(
+ UUID_TWO,
+ setOf(DOMAIN_1, DOMAIN_3, DOMAIN_4),
+ true,
+ it
+ )
+ ).isEqualTo(DomainVerificationManager.STATUS_OK)
+ }
+
+ // But disable the owner package link handling in the secondary user
+ service.setDomainVerificationLinkHandlingAllowed(pkg1.packageName, false,
+ USER_ID_SECONDARY
+ )
+
+ service.assertState(
+ pkg1,
+ verifyState = listOf(
+ DOMAIN_1 to STATE_NO_RESPONSE,
+ DOMAIN_2 to STATE_NO_RESPONSE,
+ DOMAIN_3 to STATE_NO_RESPONSE,
+ ),
+ userState2LinkHandlingAllowed = false
+ )
+
+ service.assertState(
+ pkg2,
+ verifyState = null,
+ userState1DomainState1 = DOMAIN_STATE_SELECTED,
+ userState1DomainState3 = DOMAIN_STATE_SELECTED,
+ userState1DomainState4 = DOMAIN_STATE_SELECTED,
+ userState2DomainState1 = DOMAIN_STATE_SELECTED,
+ userState2DomainState3 = DOMAIN_STATE_SELECTED,
+ userState2DomainState4 = DOMAIN_STATE_SELECTED,
+ )
+
+ // Verify the owner package
+ service.setStatusBlock(pkg1)
+
+ // Assert that package 1 is now verified, but link handling disabled in secondary user
+ service.assertState(
+ pkg1,
+ verifyState = listOf(
+ DOMAIN_1 to STATE_SUCCESS,
+ DOMAIN_2 to STATE_SUCCESS,
+ DOMAIN_3 to STATE_NO_RESPONSE,
+ ),
+ userState1DomainState1 = DOMAIN_STATE_VERIFIED,
+ userState1DomainState2 = DOMAIN_STATE_VERIFIED,
+ userState1DomainState3 = DOMAIN_STATE_NONE,
+ userState1DomainState4 = DOMAIN_STATE_NONE,
+ userState2LinkHandlingAllowed = false,
+ userState2DomainState1 = DOMAIN_STATE_VERIFIED,
+ userState2DomainState2 = DOMAIN_STATE_VERIFIED,
+ userState2DomainState3 = DOMAIN_STATE_NONE,
+ userState2DomainState4 = DOMAIN_STATE_NONE,
+ )
+
+ // Assert package 2 maintains selected in user where package 1 had link handling disabled
+ service.assertState(
+ pkg2,
+ verifyState = null,
+ userState1DomainState1 = DOMAIN_STATE_NONE,
+ userState1DomainState3 = DOMAIN_STATE_SELECTED,
+ userState1DomainState4 = DOMAIN_STATE_SELECTED,
+ userState2DomainState1 = DOMAIN_STATE_SELECTED,
+ userState2DomainState3 = DOMAIN_STATE_SELECTED,
+ userState2DomainState4 = DOMAIN_STATE_SELECTED,
+ )
+ }
+
+ fun DomainVerificationService.assertState(
+ pkg: PackageStateInternal,
+ verifyState: List<Pair<String, Int>>?,
+ userState1LinkHandlingAllowed: Boolean = true,
+ userState1DomainState1: Int = DOMAIN_STATE_NONE,
+ userState1DomainState2: Int = DOMAIN_STATE_NONE,
+ userState1DomainState3: Int = DOMAIN_STATE_NONE,
+ userState1DomainState4: Int = DOMAIN_STATE_NONE,
+ userState2LinkHandlingAllowed: Boolean = true,
+ userState2DomainState1: Int = DOMAIN_STATE_NONE,
+ userState2DomainState2: Int = DOMAIN_STATE_NONE,
+ userState2DomainState3: Int = DOMAIN_STATE_NONE,
+ userState2DomainState4: Int = DOMAIN_STATE_NONE,
+ ) {
+ if (verifyState == null) {
+ // If no auto verify domains, the info itself will be null
+ assertThat(getDomainVerificationInfo(pkg.packageName)).isNull()
+ } else {
+ getInfo(pkg.packageName).run {
+ assertThat(hostToStateMap).containsExactlyEntriesIn(verifyState.associate { it })
+ }
+ }
+
+ getUserState(pkg.packageName, USER_ID).run {
+ assertThat(isLinkHandlingAllowed).isEqualTo(userState1LinkHandlingAllowed)
+ assertThat(hostToStateMap).containsExactlyEntriesIn(
+ mapOf(
+ DOMAIN_1 to userState1DomainState1,
+ DOMAIN_2 to userState1DomainState2,
+ DOMAIN_3 to userState1DomainState3,
+ DOMAIN_4 to userState1DomainState4,
+ )
+ )
+ }
+
+ getUserState(pkg.packageName, USER_ID_SECONDARY).run {
+ assertThat(isLinkHandlingAllowed).isEqualTo(userState2LinkHandlingAllowed)
+ assertThat(hostToStateMap).containsExactlyEntriesIn(
+ mapOf(
+ DOMAIN_1 to userState2DomainState1,
+ DOMAIN_2 to userState2DomainState2,
+ DOMAIN_3 to userState2DomainState3,
+ DOMAIN_4 to userState2DomainState4,
+ )
+ )
+ }
+ }
+
private fun DomainVerificationService.getInfo(pkgName: String) =
getDomainVerificationInfo(pkgName)
.also { assertThat(it).isNotNull() }!!
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 8014d2502f48..388170bd24cb 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -3360,9 +3360,11 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertThat(dpmi.isActiveSupervisionApp(uid)).isTrue();
assertThat(dpm.getProfileOwnerOrDeviceOwnerSupervisionComponent(user))
.isEqualTo(admin1);
+ assertThat(dpm.isSupervisionComponent(admin1)).isTrue();
} else {
assertThat(dpmi.isActiveSupervisionApp(uid)).isFalse();
assertThat(dpm.getProfileOwnerOrDeviceOwnerSupervisionComponent(user)).isNull();
+ assertThat(dpm.isSupervisionComponent(admin1)).isFalse();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index b0c52f1fdbb8..9d82f1a90c77 100644
--- a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -24,6 +24,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyFloat;
import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -258,29 +259,36 @@ public class AutomaticBrightnessControllerTest {
@Test
public void testRecalculateSplines() throws Exception {
// Enabling the light sensor, and setting the ambient lux to 1000
+ int currentLux = 1000;
ArgumentCaptor<SensorEventListener> listenerCaptor =
ArgumentCaptor.forClass(SensorEventListener.class);
verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor),
eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class));
SensorEventListener listener = listenerCaptor.getValue();
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1000));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, currentLux));
- //Setting the brightnessFloat to 0.5f
- float currentBrightnessFloat = 0.5f;
- when(mBrightnessMappingStrategy.getBrightness(1000,
- null, ApplicationInfo.CATEGORY_UNDEFINED)).thenReturn(currentBrightnessFloat);
+ // User sets brightness to 0.5f
+ when(mBrightnessMappingStrategy.getBrightness(currentLux,
+ null, ApplicationInfo.CATEGORY_UNDEFINED)).thenReturn(0.5f);
mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration */,
- currentBrightnessFloat /* brightness */, false /* userChangedBrightness */,
- 0 /* adjustment */, false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT);
+ 0.5f /* brightness */, true /* userChangedBrightness */, 0 /* adjustment */,
+ false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT);
- // Adjusting spline, and accordingly remapping the current 0.5f brightnessFloat to 0.3f
- float updatedBrightnessFloat = 0.3f;
- when(mBrightnessMappingStrategy.getBrightness(1000,
- null, ApplicationInfo.CATEGORY_UNDEFINED)).thenReturn(updatedBrightnessFloat);
- float[] adjustments = new float[]{0.2f, 0.5f};
+ //Recalculating the spline with RBC enabled, verifying that the short term model is reset,
+ //and the interaction is learnt in short term model
+ float[] adjustments = new float[]{0.2f, 0.6f};
mController.recalculateSplines(true, adjustments);
+ verify(mBrightnessMappingStrategy).clearUserDataPoints();
verify(mBrightnessMappingStrategy).recalculateSplines(true, adjustments);
- assertEquals(mController.getAutomaticScreenBrightness(), updatedBrightnessFloat, EPSILON);
+ verify(mBrightnessMappingStrategy, times(2)).addUserDataPoint(currentLux, 0.5f);
+
+ clearInvocations(mBrightnessMappingStrategy);
+
+ // Verify short term model is not learnt when RBC is disabled
+ mController.recalculateSplines(false, adjustments);
+ verify(mBrightnessMappingStrategy).clearUserDataPoints();
+ verify(mBrightnessMappingStrategy).recalculateSplines(false, adjustments);
+ verifyNoMoreInteractions(mBrightnessMappingStrategy);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index 1e97c1c5c5bc..5f1ff6be49be 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -287,7 +287,7 @@ public class DisplayManagerServiceTest {
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
- final int displayIds[] = bs.getDisplayIds();
+ final int[] displayIds = bs.getDisplayIds(/* includeDisabled= */ false);
final int size = displayIds.length;
assertTrue(size > 0);
@@ -297,7 +297,9 @@ public class DisplayManagerServiceTest {
);
for (int i = 0; i < size; i++) {
DisplayInfo info = bs.getDisplayInfo(displayIds[i]);
- assertTrue(expectedDisplayTypeToViewPortTypeMapping.keySet().contains(info.type));
+ if (info != null) {
+ assertTrue(expectedDisplayTypeToViewPortTypeMapping.keySet().contains(info.type));
+ }
}
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
@@ -1174,7 +1176,8 @@ public class DisplayManagerServiceTest {
DisplayManagerService.BinderService displayManagerBinderService,
FakeDisplayDevice displayDevice) {
- final int[] displayIds = displayManagerBinderService.getDisplayIds();
+ final int[] displayIds = displayManagerBinderService.getDisplayIds(
+ /* includeDisabled= */ false);
assertTrue(displayIds.length > 0);
int displayId = Display.INVALID_DISPLAY;
for (int i = 0; i < displayIds.length; i++) {
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
index cc68ba88f76e..5b131454e4db 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -33,6 +33,7 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -53,6 +54,8 @@ import android.view.DisplayInfo;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.display.layout.Layout;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -79,6 +82,7 @@ public class LogicalDisplayMapperTest {
private TestLooper mLooper;
private Handler mHandler;
private PowerManager mPowerManager;
+ private DeviceStateToLayoutMap mDeviceStateToLayoutMapSpy;
@Mock LogicalDisplayMapper.Listener mListenerMock;
@Mock Context mContextMock;
@@ -133,8 +137,11 @@ public class LogicalDisplayMapperTest {
mLooper = new TestLooper();
mHandler = new Handler(mLooper.getLooper());
+
+ mDeviceStateToLayoutMapSpy = spy(new DeviceStateToLayoutMap());
mLogicalDisplayMapper = new LogicalDisplayMapper(mContextMock, mDisplayDeviceRepo,
- mListenerMock, new DisplayManagerService.SyncRoot(), mHandler);
+ mListenerMock, new DisplayManagerService.SyncRoot(), mHandler,
+ mDeviceStateToLayoutMapSpy);
}
@@ -413,6 +420,86 @@ public class LogicalDisplayMapperTest {
/* isBootCompleted= */true));
}
+ @Test public void testEnabledAndDisabledDisplays() {
+ DisplayAddress displayAddressOne = new TestUtils.TestDisplayAddress();
+ DisplayAddress displayAddressTwo = new TestUtils.TestDisplayAddress();
+ DisplayAddress displayAddressThree = new TestUtils.TestDisplayAddress();
+
+ TestDisplayDevice device1 = createDisplayDevice(displayAddressOne, Display.TYPE_INTERNAL,
+ 600, 800,
+ DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
+ TestDisplayDevice device2 = createDisplayDevice(displayAddressTwo, Display.TYPE_INTERNAL,
+ 200, 800,
+ DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP);
+ TestDisplayDevice device3 = createDisplayDevice(displayAddressThree, Display.TYPE_INTERNAL,
+ 600, 900, DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP);
+
+ Layout threeDevicesEnabledLayout = new Layout();
+ threeDevicesEnabledLayout.createDisplayLocked(
+ displayAddressOne,
+ /* isDefault= */ true,
+ /* isEnabled= */ true);
+
+ threeDevicesEnabledLayout.createDisplayLocked(
+ displayAddressTwo,
+ /* isDefault= */ false,
+ /* isEnabled= */ true);
+ threeDevicesEnabledLayout.createDisplayLocked(
+ displayAddressThree,
+ /* isDefault= */ false,
+ /* isEnabled= */ true);
+
+ when(mDeviceStateToLayoutMapSpy.get(DeviceStateToLayoutMap.STATE_DEFAULT))
+ .thenReturn(threeDevicesEnabledLayout);
+
+ LogicalDisplay display1 = add(device1);
+ LogicalDisplay display2 = add(device2);
+ LogicalDisplay display3 = add(device3);
+
+ // ensure 3 displays are returned
+ int [] ids = mLogicalDisplayMapper.getDisplayIdsLocked(Process.SYSTEM_UID);
+ assertEquals(3, ids.length);
+ Arrays.sort(ids);
+ assertEquals(DEFAULT_DISPLAY, ids[0]);
+
+ Layout oneDeviceEnabledLayout = new Layout();
+ oneDeviceEnabledLayout.createDisplayLocked(
+ display1.getDisplayInfoLocked().address,
+ /* isDefault= */ true,
+ /* isEnabled= */ true);
+ oneDeviceEnabledLayout.createDisplayLocked(
+ display2.getDisplayInfoLocked().address,
+ /* isDefault= */ false,
+ /* isEnabled= */ false);
+ oneDeviceEnabledLayout.createDisplayLocked(
+ display3.getDisplayInfoLocked().address,
+ /* isDefault= */ false,
+ /* isEnabled= */ false);
+
+ when(mDeviceStateToLayoutMapSpy.get(0)).thenReturn(oneDeviceEnabledLayout);
+ when(mDeviceStateToLayoutMapSpy.get(1)).thenReturn(threeDevicesEnabledLayout);
+
+ mLogicalDisplayMapper
+ .setDeviceStateLocked(0, false);
+ mDisplayDeviceRepo.onDisplayDeviceEvent(device3, DISPLAY_DEVICE_EVENT_CHANGED);
+ final int[] allDisplayIds = mLogicalDisplayMapper.getDisplayIdsLocked(
+ Process.SYSTEM_UID, false);
+ mLooper.dispatchAll();
+
+ // ensure only one display is returned
+ assertEquals(1, allDisplayIds.length);
+
+ mLogicalDisplayMapper
+ .setDeviceStateLocked(1, false);
+ mDisplayDeviceRepo.onDisplayDeviceEvent(device3, DISPLAY_DEVICE_EVENT_CHANGED);
+ final int[] threeDisplaysEnabled = mLogicalDisplayMapper.getDisplayIdsLocked(
+ Process.SYSTEM_UID, false);
+ mLooper.dispatchAll();
+
+ // ensure all three displays are returned
+ assertEquals(3, threeDisplaysEnabled.length);
+ }
+
/////////////////
// Helper Methods
/////////////////
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index 758a56f3d2ad..e9171c0c3514 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -393,14 +393,14 @@ public class SystemConfigTest {
+ " <library \n"
+ " name=\"foo\"\n"
+ " file=\"" + mFooJar + "\"\n"
- + " on-bootclasspath-before=\"A\"\n"
+ + " on-bootclasspath-before=\"Q\"\n"
+ " on-bootclasspath-since=\"W\"\n"
+ " />\n\n"
+ " </permissions>";
parseSharedLibraries(contents);
assertFooIsOnlySharedLibrary();
SystemConfig.SharedLibraryEntry entry = mSysConfig.getSharedLibraries().get("foo");
- assertThat(entry.onBootclasspathBefore).isEqualTo("A");
+ assertThat(entry.onBootclasspathBefore).isEqualTo("Q");
assertThat(entry.onBootclasspathSince).isEqualTo("W");
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 8c4a4c9ea284..03d87749072d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -2811,12 +2811,18 @@ public class ActivityRecordTests extends WindowTestsBase {
true, false, false, false);
waitUntilHandlersIdle();
+ final WindowState startingWindow = activityTop.mStartingWindow;
+ assertNotNull(startingWindow);
+
// Make the top one invisible, and try transferring the starting window from the top to the
// bottom one.
activityTop.setVisibility(false, false);
activityBottom.transferStartingWindowFromHiddenAboveTokenIfNeeded();
waitUntilHandlersIdle();
+ // Expect getFrozenInsetsState will be null when transferring the starting window.
+ assertNull(startingWindow.getFrozenInsetsState());
+
// Assert that the bottom window now has the starting window.
assertNoStartingWindow(activityTop);
assertHasStartingWindow(activityBottom);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncerTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncerTest.java
index cc28ea6f55d2..87382952314b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncerTest.java
@@ -48,11 +48,11 @@ public class SurfaceSyncerTest {
public void testSyncOne() throws InterruptedException {
final CountDownLatch finishedLatch = new CountDownLatch(1);
int startSyncId = mSurfaceSyncer.setupSync(transaction -> finishedLatch.countDown());
- Syncable syncable = new Syncable();
- mSurfaceSyncer.addToSync(startSyncId, syncable);
+ SyncTarget syncTarget = new SyncTarget();
+ mSurfaceSyncer.addToSync(startSyncId, syncTarget);
mSurfaceSyncer.markSyncReady(startSyncId);
- syncable.onBufferReady();
+ syncTarget.onBufferReady();
finishedLatch.await(5, TimeUnit.SECONDS);
assertEquals(0, finishedLatch.getCount());
@@ -62,22 +62,22 @@ public class SurfaceSyncerTest {
public void testSyncMultiple() throws InterruptedException {
final CountDownLatch finishedLatch = new CountDownLatch(1);
int startSyncId = mSurfaceSyncer.setupSync(transaction -> finishedLatch.countDown());
- Syncable syncable1 = new Syncable();
- Syncable syncable2 = new Syncable();
- Syncable syncable3 = new Syncable();
+ SyncTarget syncTarget1 = new SyncTarget();
+ SyncTarget syncTarget2 = new SyncTarget();
+ SyncTarget syncTarget3 = new SyncTarget();
- mSurfaceSyncer.addToSync(startSyncId, syncable1);
- mSurfaceSyncer.addToSync(startSyncId, syncable2);
- mSurfaceSyncer.addToSync(startSyncId, syncable3);
+ mSurfaceSyncer.addToSync(startSyncId, syncTarget1);
+ mSurfaceSyncer.addToSync(startSyncId, syncTarget2);
+ mSurfaceSyncer.addToSync(startSyncId, syncTarget3);
mSurfaceSyncer.markSyncReady(startSyncId);
- syncable1.onBufferReady();
+ syncTarget1.onBufferReady();
assertNotEquals(0, finishedLatch.getCount());
- syncable3.onBufferReady();
+ syncTarget3.onBufferReady();
assertNotEquals(0, finishedLatch.getCount());
- syncable2.onBufferReady();
+ syncTarget2.onBufferReady();
finishedLatch.await(5, TimeUnit.SECONDS);
assertEquals(0, finishedLatch.getCount());
@@ -85,7 +85,7 @@ public class SurfaceSyncerTest {
@Test
public void testInvalidSyncId() {
- assertFalse(mSurfaceSyncer.addToSync(0, new Syncable()));
+ assertFalse(mSurfaceSyncer.addToSync(0, new SyncTarget()));
}
@Test
@@ -93,14 +93,14 @@ public class SurfaceSyncerTest {
final CountDownLatch finishedLatch = new CountDownLatch(1);
int startSyncId = mSurfaceSyncer.setupSync(transaction -> finishedLatch.countDown());
- Syncable syncable1 = new Syncable();
- Syncable syncable2 = new Syncable();
+ SyncTarget syncTarget1 = new SyncTarget();
+ SyncTarget syncTarget2 = new SyncTarget();
- assertTrue(mSurfaceSyncer.addToSync(startSyncId, syncable1));
+ assertTrue(mSurfaceSyncer.addToSync(startSyncId, syncTarget1));
mSurfaceSyncer.markSyncReady(startSyncId);
// Adding to a sync that has been completed is also invalid since the sync id has been
// cleared.
- assertFalse(mSurfaceSyncer.addToSync(startSyncId, syncable2));
+ assertFalse(mSurfaceSyncer.addToSync(startSyncId, syncTarget2));
}
@Test
@@ -110,27 +110,89 @@ public class SurfaceSyncerTest {
int startSyncId1 = mSurfaceSyncer.setupSync(transaction -> finishedLatch1.countDown());
int startSyncId2 = mSurfaceSyncer.setupSync(transaction -> finishedLatch2.countDown());
- Syncable syncable1 = new Syncable();
- Syncable syncable2 = new Syncable();
+ SyncTarget syncTarget1 = new SyncTarget();
+ SyncTarget syncTarget2 = new SyncTarget();
- assertTrue(mSurfaceSyncer.addToSync(startSyncId1, syncable1));
- assertTrue(mSurfaceSyncer.addToSync(startSyncId2, syncable2));
+ assertTrue(mSurfaceSyncer.addToSync(startSyncId1, syncTarget1));
+ assertTrue(mSurfaceSyncer.addToSync(startSyncId2, syncTarget2));
mSurfaceSyncer.markSyncReady(startSyncId1);
mSurfaceSyncer.markSyncReady(startSyncId2);
- syncable1.onBufferReady();
+ syncTarget1.onBufferReady();
finishedLatch1.await(5, TimeUnit.SECONDS);
assertEquals(0, finishedLatch1.getCount());
assertNotEquals(0, finishedLatch2.getCount());
- syncable2.onBufferReady();
+ syncTarget2.onBufferReady();
finishedLatch2.await(5, TimeUnit.SECONDS);
assertEquals(0, finishedLatch2.getCount());
}
- private static class Syncable implements SurfaceSyncer.SyncTarget {
+ @Test
+ public void testMergeSync() throws InterruptedException {
+ final CountDownLatch finishedLatch1 = new CountDownLatch(1);
+ final CountDownLatch finishedLatch2 = new CountDownLatch(1);
+ int startSyncId1 = mSurfaceSyncer.setupSync(transaction -> finishedLatch1.countDown());
+ int startSyncId2 = mSurfaceSyncer.setupSync(transaction -> finishedLatch2.countDown());
+
+ SyncTarget syncTarget1 = new SyncTarget();
+ SyncTarget syncTarget2 = new SyncTarget();
+
+ assertTrue(mSurfaceSyncer.addToSync(startSyncId1, syncTarget1));
+ assertTrue(mSurfaceSyncer.addToSync(startSyncId2, syncTarget2));
+ mSurfaceSyncer.markSyncReady(startSyncId1);
+ mSurfaceSyncer.merge(startSyncId2, startSyncId1, mSurfaceSyncer);
+ mSurfaceSyncer.markSyncReady(startSyncId2);
+
+ // Finish syncTarget2 first to test that the syncSet is not complete until the merged sync
+ // is also done.
+ syncTarget2.onBufferReady();
+ finishedLatch2.await(1, TimeUnit.SECONDS);
+ // Sync did not complete yet
+ assertNotEquals(0, finishedLatch2.getCount());
+
+ syncTarget1.onBufferReady();
+
+ // The first sync will still get a callback when it's sync requirements are done.
+ finishedLatch1.await(5, TimeUnit.SECONDS);
+ assertEquals(0, finishedLatch1.getCount());
+
+ finishedLatch2.await(5, TimeUnit.SECONDS);
+ assertEquals(0, finishedLatch2.getCount());
+ }
+
+ @Test
+ public void testMergeSyncAlreadyComplete() throws InterruptedException {
+ final CountDownLatch finishedLatch1 = new CountDownLatch(1);
+ final CountDownLatch finishedLatch2 = new CountDownLatch(1);
+ int startSyncId1 = mSurfaceSyncer.setupSync(transaction -> finishedLatch1.countDown());
+ int startSyncId2 = mSurfaceSyncer.setupSync(transaction -> finishedLatch2.countDown());
+
+ SyncTarget syncTarget1 = new SyncTarget();
+ SyncTarget syncTarget2 = new SyncTarget();
+
+ assertTrue(mSurfaceSyncer.addToSync(startSyncId1, syncTarget1));
+ assertTrue(mSurfaceSyncer.addToSync(startSyncId2, syncTarget2));
+ mSurfaceSyncer.markSyncReady(startSyncId1);
+ syncTarget1.onBufferReady();
+
+ // The first sync will still get a callback when it's sync requirements are done.
+ finishedLatch1.await(5, TimeUnit.SECONDS);
+ assertEquals(0, finishedLatch1.getCount());
+
+ mSurfaceSyncer.merge(startSyncId2, startSyncId1, mSurfaceSyncer);
+ mSurfaceSyncer.markSyncReady(startSyncId2);
+ syncTarget2.onBufferReady();
+
+ // Verify that the second sync will receive complete since the merged sync was already
+ // completed before the merge.
+ finishedLatch2.await(5, TimeUnit.SECONDS);
+ assertEquals(0, finishedLatch2.getCount());
+ }
+
+ private static class SyncTarget implements SurfaceSyncer.SyncTarget {
private SurfaceSyncer.SyncBufferCallback mSyncBufferCallback;
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index 5340a79f4b94..8202cd915527 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -24,6 +24,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.android.server.wm.testing.Assert.assertThrows;
+import static com.google.common.truth.Truth.assertWithMessage;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -43,6 +45,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Binder;
@@ -78,6 +81,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
private static final int TASK_ID = 10;
private TaskFragmentOrganizerController mController;
+ private WindowOrganizerController mWindowOrganizerController;
private TaskFragmentOrganizer mOrganizer;
private TaskFragmentOrganizerToken mOrganizerToken;
private ITaskFragmentOrganizer mIOrganizer;
@@ -87,10 +91,13 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
private WindowContainerTransaction mTransaction;
private WindowContainerToken mFragmentWindowToken;
private RemoteAnimationDefinition mDefinition;
+ private IBinder mErrorToken;
+ private Rect mTaskFragBounds;
@Before
public void setup() {
- mController = mAtm.mWindowOrganizerController.mTaskFragmentOrganizerController;
+ mWindowOrganizerController = mAtm.mWindowOrganizerController;
+ mController = mWindowOrganizerController.mTaskFragmentOrganizerController;
mOrganizer = new TaskFragmentOrganizer(Runnable::run);
mOrganizerToken = mOrganizer.getOrganizerToken();
mIOrganizer = ITaskFragmentOrganizer.Stub.asInterface(mOrganizerToken.asBinder());
@@ -101,6 +108,10 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
mTransaction = new WindowContainerTransaction();
mFragmentWindowToken = mTaskFragment.mRemoteToken.toWindowContainerToken();
mDefinition = new RemoteAnimationDefinition();
+ mErrorToken = new Binder();
+ final Rect displayBounds = mDisplayContent.getBounds();
+ mTaskFragBounds = new Rect(displayBounds.left, displayBounds.top, displayBounds.centerX(),
+ displayBounds.centerY());
spyOn(mController);
spyOn(mOrganizer);
@@ -221,16 +232,15 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
}
@Test
- public void testOnTaskFragmentError() throws RemoteException {
- final IBinder errorCallbackToken = new Binder();
+ public void testOnTaskFragmentError() {
final Throwable exception = new IllegalArgumentException("Test exception");
mController.registerOrganizer(mIOrganizer);
mController.onTaskFragmentError(mTaskFragment.getTaskFragmentOrganizer(),
- errorCallbackToken, exception);
+ mErrorToken, exception);
mController.dispatchPendingEvents();
- verify(mOrganizer).onTaskFragmentError(eq(errorCallbackToken), eq(exception));
+ verify(mOrganizer).onTaskFragmentError(eq(mErrorToken), eq(exception));
}
@Test
@@ -280,7 +290,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
final int uid = Binder.getCallingUid();
mTaskFragment.setTaskFragmentOrganizer(mOrganizer.getOrganizerToken(), uid,
DEFAULT_TASK_FRAGMENT_ORGANIZER_PROCESS_NAME);
- mAtm.mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
mController.registerOrganizer(mIOrganizer);
mOrganizer.applyTransaction(mTransaction);
final Task task = createTask(mDisplayContent);
@@ -305,7 +315,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
final IBinder temporaryToken = token.getValue();
assertNotEquals(activity.token, temporaryToken);
mTransaction.reparentActivityToTaskFragment(mFragmentToken, temporaryToken);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ mWindowOrganizerController.applyTransaction(mTransaction);
assertEquals(mTaskFragment, activity.getTaskFragment());
// The temporary token can only be used once.
@@ -395,8 +405,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
// No lifecycle update when the TaskFragment is not recorded.
verify(mAtm.mRootWindowContainer, never()).resumeFocusedTasksTopActivities();
- mAtm.mWindowOrganizerController.mLaunchTaskFragments
- .put(mFragmentToken, mTaskFragment);
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
assertApplyTransactionAllowed(mTransaction);
verify(mAtm.mRootWindowContainer).resumeFocusedTasksTopActivities();
@@ -466,23 +475,23 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
// Fail to create TaskFragment when the task uid is different from caller.
activity.info.applicationInfo.uid = uid;
activity.getTask().effectiveUid = uid + 1;
- mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
+ mWindowOrganizerController.applyTransaction(mTransaction);
- assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
+ assertNull(mWindowOrganizerController.getTaskFragment(fragmentToken));
// Fail to create TaskFragment when the task uid is different from owner activity.
activity.info.applicationInfo.uid = uid + 1;
activity.getTask().effectiveUid = uid;
- mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
+ mWindowOrganizerController.applyTransaction(mTransaction);
- assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
+ assertNull(mWindowOrganizerController.getTaskFragment(fragmentToken));
// Successfully created a TaskFragment for same uid.
activity.info.applicationInfo.uid = uid;
activity.getTask().effectiveUid = uid;
- mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
+ mWindowOrganizerController.applyTransaction(mTransaction);
- assertNotNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
+ assertNotNull(mWindowOrganizerController.getTaskFragment(fragmentToken));
}
@Test
@@ -519,7 +528,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
.setParentTask(task)
.setFragmentToken(mFragmentToken)
.build();
- mAtm.mWindowOrganizerController.mLaunchTaskFragments
+ mWindowOrganizerController.mLaunchTaskFragments
.put(mFragmentToken, mTaskFragment);
mTransaction.reparentActivityToTaskFragment(mFragmentToken, activity.token);
doReturn(true).when(mTaskFragment).isAllowedToEmbedActivity(activity);
@@ -549,8 +558,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
.setOrganizer(mOrganizer)
.createActivityCount(1)
.build();
- mAtm.mWindowOrganizerController.mLaunchTaskFragments.put(token0, tf0);
- mAtm.mWindowOrganizerController.mLaunchTaskFragments.put(token1, tf1);
+ mWindowOrganizerController.mLaunchTaskFragments.put(token0, tf0);
+ mWindowOrganizerController.mLaunchTaskFragments.put(token1, tf1);
final ActivityRecord activity0 = tf0.getTopMostActivity();
final ActivityRecord activity1 = tf1.getTopMostActivity();
@@ -558,7 +567,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
final ActivityRecord activityInOtherTask = createActivityRecord(mDefaultDisplay);
mDisplayContent.setFocusedApp(activityInOtherTask);
mTransaction.requestFocusOnTaskFragment(token0);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ mWindowOrganizerController.applyTransaction(mTransaction);
assertEquals(activityInOtherTask, mDisplayContent.mFocusedApp);
@@ -566,7 +575,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
activity0.setState(ActivityRecord.State.PAUSED, "test");
activity1.setState(ActivityRecord.State.RESUMED, "test");
mDisplayContent.setFocusedApp(activity1);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ mWindowOrganizerController.applyTransaction(mTransaction);
assertEquals(activity1, mDisplayContent.mFocusedApp);
@@ -574,7 +583,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
// has a resumed activity.
activity0.setState(ActivityRecord.State.RESUMED, "test");
mDisplayContent.setFocusedApp(activity1);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ mWindowOrganizerController.applyTransaction(mTransaction);
assertEquals(activity0, mDisplayContent.mFocusedApp);
}
@@ -583,53 +592,50 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
public void testTaskFragmentInPip_startActivityInTaskFragment() {
setupTaskFragmentInPip();
final ActivityRecord activity = mTaskFragment.getTopMostActivity();
- final IBinder errorToken = new Binder();
spyOn(mAtm.getActivityStartController());
- spyOn(mAtm.mWindowOrganizerController);
+ spyOn(mWindowOrganizerController);
// Not allow to start activity in a TaskFragment that is in a PIP Task.
mTransaction.startActivityInTaskFragment(
mFragmentToken, activity.token, new Intent(), null /* activityOptions */)
- .setErrorCallbackToken(errorToken);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ .setErrorCallbackToken(mErrorToken);
+ mWindowOrganizerController.applyTransaction(mTransaction);
verify(mAtm.getActivityStartController(), never()).startActivityInTaskFragment(any(), any(),
- any(), any(), anyInt(), anyInt());
+ any(), any(), anyInt(), anyInt(), any());
verify(mAtm.mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
- eq(errorToken), any(IllegalArgumentException.class));
+ eq(mErrorToken), any(IllegalArgumentException.class));
}
@Test
public void testTaskFragmentInPip_reparentActivityToTaskFragment() {
setupTaskFragmentInPip();
final ActivityRecord activity = createActivityRecord(mDisplayContent);
- final IBinder errorToken = new Binder();
- spyOn(mAtm.mWindowOrganizerController);
+ spyOn(mWindowOrganizerController);
// Not allow to reparent activity to a TaskFragment that is in a PIP Task.
mTransaction.reparentActivityToTaskFragment(mFragmentToken, activity.token)
- .setErrorCallbackToken(errorToken);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ .setErrorCallbackToken(mErrorToken);
+ mWindowOrganizerController.applyTransaction(mTransaction);
- verify(mAtm.mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
- eq(errorToken), any(IllegalArgumentException.class));
+ verify(mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
+ eq(mErrorToken), any(IllegalArgumentException.class));
assertNull(activity.getOrganizedTaskFragment());
}
@Test
public void testTaskFragmentInPip_setAdjacentTaskFragment() {
setupTaskFragmentInPip();
- final IBinder errorToken = new Binder();
- spyOn(mAtm.mWindowOrganizerController);
+ spyOn(mWindowOrganizerController);
// Not allow to set adjacent on a TaskFragment that is in a PIP Task.
mTransaction.setAdjacentTaskFragments(mFragmentToken, null /* fragmentToken2 */,
null /* options */)
- .setErrorCallbackToken(errorToken);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ .setErrorCallbackToken(mErrorToken);
+ mWindowOrganizerController.applyTransaction(mTransaction);
- verify(mAtm.mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
- eq(errorToken), any(IllegalArgumentException.class));
+ verify(mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
+ eq(mErrorToken), any(IllegalArgumentException.class));
verify(mTaskFragment, never()).setAdjacentTaskFragment(any(), anyBoolean());
}
@@ -640,47 +646,45 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
ACTIVITY_TYPE_STANDARD);
final ActivityRecord activity = createActivityRecord(pipTask);
final IBinder fragmentToken = new Binder();
- final IBinder errorToken = new Binder();
- spyOn(mAtm.mWindowOrganizerController);
+ spyOn(mWindowOrganizerController);
// Not allow to create TaskFragment in a PIP Task.
createTaskFragmentFromOrganizer(mTransaction, activity, fragmentToken);
- mTransaction.setErrorCallbackToken(errorToken);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ mTransaction.setErrorCallbackToken(mErrorToken);
+ mWindowOrganizerController.applyTransaction(mTransaction);
- verify(mAtm.mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
- eq(errorToken), any(IllegalArgumentException.class));
- assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
+ verify(mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
+ eq(mErrorToken), any(IllegalArgumentException.class));
+ assertNull(mWindowOrganizerController.getTaskFragment(fragmentToken));
}
@Test
public void testTaskFragmentInPip_deleteTaskFragment() {
setupTaskFragmentInPip();
- final IBinder errorToken = new Binder();
- spyOn(mAtm.mWindowOrganizerController);
+ spyOn(mWindowOrganizerController);
// Not allow to delete a TaskFragment that is in a PIP Task.
mTransaction.deleteTaskFragment(mFragmentWindowToken)
- .setErrorCallbackToken(errorToken);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ .setErrorCallbackToken(mErrorToken);
+ mWindowOrganizerController.applyTransaction(mTransaction);
- verify(mAtm.mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
- eq(errorToken), any(IllegalArgumentException.class));
- assertNotNull(mAtm.mWindowOrganizerController.getTaskFragment(mFragmentToken));
+ verify(mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
+ eq(mErrorToken), any(IllegalArgumentException.class));
+ assertNotNull(mWindowOrganizerController.getTaskFragment(mFragmentToken));
// Allow organizer to delete empty TaskFragment for cleanup.
final Task task = mTaskFragment.getTask();
mTaskFragment.removeChild(mTaskFragment.getTopMostActivity());
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ mWindowOrganizerController.applyTransaction(mTransaction);
- assertNull(mAtm.mWindowOrganizerController.getTaskFragment(mFragmentToken));
+ assertNull(mWindowOrganizerController.getTaskFragment(mFragmentToken));
assertNull(task.getTopChild());
}
@Test
public void testTaskFragmentInPip_setConfig() {
setupTaskFragmentInPip();
- spyOn(mAtm.mWindowOrganizerController);
+ spyOn(mWindowOrganizerController);
// Set bounds is ignored on a TaskFragment that is in a PIP Task.
mTransaction.setBounds(mFragmentWindowToken, new Rect(0, 0, 100, 100));
@@ -832,14 +836,13 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
final IBinder fragmentToken = new Binder();
createTaskFragmentFromOrganizer(mTransaction, ownerActivity, fragmentToken);
mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
- final TaskFragment taskFragment = mAtm.mWindowOrganizerController
- .getTaskFragment(fragmentToken);
+ final TaskFragment taskFragment = mWindowOrganizerController.getTaskFragment(fragmentToken);
assertNotNull(taskFragment);
taskFragment.removeImmediately();
- assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
+ assertNull(mWindowOrganizerController.getTaskFragment(fragmentToken));
}
/**
@@ -902,6 +905,101 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
assertApplyTransactionDisallowed(mTransaction);
}
+ // TODO(b/232871351): add test for minimum dimension violation in startActivityInTaskFragment
+ @Test
+ public void testMinDimensionViolation_ReparentActivityToTaskFragment() {
+ final Task task = createTask(mDisplayContent);
+ final ActivityRecord activity = createActivityRecord(task);
+ // Make minWidth/minHeight exceeds the TaskFragment bounds.
+ activity.info.windowLayout = new ActivityInfo.WindowLayout(
+ 0, 0, 0, 0, 0, mTaskFragBounds.width() + 10, mTaskFragBounds.height() + 10);
+ mOrganizer.applyTransaction(mTransaction);
+ mController.registerOrganizer(mIOrganizer);
+ mTaskFragment = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .setFragmentToken(mFragmentToken)
+ .setOrganizer(mOrganizer)
+ .setBounds(mTaskFragBounds)
+ .build();
+ doReturn(true).when(mTaskFragment).isAllowedToEmbedActivity(activity);
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
+ clearInvocations(mAtm.mRootWindowContainer);
+
+ // Reparent activity to mTaskFragment, which is smaller than activity's
+ // minimum dimensions.
+ mTransaction.reparentActivityToTaskFragment(mFragmentToken, activity.token)
+ .setErrorCallbackToken(mErrorToken);
+ mWindowOrganizerController.applyTransaction(mTransaction);
+
+ verify(mOrganizer).onTaskFragmentError(eq(mErrorToken), any(SecurityException.class));
+ }
+
+ @Test
+ public void testMinDimensionViolation_ReparentChildren() {
+ final Task task = createTask(mDisplayContent);
+ mOrganizer.applyTransaction(mTransaction);
+ mController.registerOrganizer(mIOrganizer);
+ final IBinder oldFragToken = new Binder();
+ final TaskFragment oldTaskFrag = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .createActivityCount(1)
+ .setFragmentToken(oldFragToken)
+ .setOrganizer(mOrganizer)
+ .build();
+ final ActivityRecord activity = oldTaskFrag.getTopMostActivity();
+ // Make minWidth/minHeight exceeds mTaskFragment bounds.
+ activity.info.windowLayout = new ActivityInfo.WindowLayout(
+ 0, 0, 0, 0, 0, mTaskFragBounds.width() + 10, mTaskFragBounds.height() + 10);
+ mTaskFragment = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .setFragmentToken(mFragmentToken)
+ .setOrganizer(mOrganizer)
+ .setBounds(mTaskFragBounds)
+ .build();
+ doReturn(true).when(mTaskFragment).isAllowedToEmbedActivity(activity);
+ mWindowOrganizerController.mLaunchTaskFragments.put(oldFragToken, oldTaskFrag);
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
+ clearInvocations(mAtm.mRootWindowContainer);
+
+ // Reparent oldTaskFrag's children to mTaskFragment, which is smaller than activity's
+ // minimum dimensions.
+ mTransaction.reparentChildren(oldTaskFrag.mRemoteToken.toWindowContainerToken(),
+ mTaskFragment.mRemoteToken.toWindowContainerToken())
+ .setErrorCallbackToken(mErrorToken);
+ mWindowOrganizerController.applyTransaction(mTransaction);
+
+ verify(mOrganizer).onTaskFragmentError(eq(mErrorToken), any(SecurityException.class));
+ }
+
+ @Test
+ public void testMinDimensionViolation_SetBounds() {
+ final Task task = createTask(mDisplayContent);
+ mOrganizer.applyTransaction(mTransaction);
+ mController.registerOrganizer(mIOrganizer);
+ mTaskFragment = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .createActivityCount(1)
+ .setFragmentToken(mFragmentToken)
+ .setOrganizer(mOrganizer)
+ .setBounds(new Rect(0, 0, mTaskFragBounds.right * 2, mTaskFragBounds.bottom * 2))
+ .build();
+ final ActivityRecord activity = mTaskFragment.getTopMostActivity();
+ // Make minWidth/minHeight exceeds the TaskFragment bounds.
+ activity.info.windowLayout = new ActivityInfo.WindowLayout(
+ 0, 0, 0, 0, 0, mTaskFragBounds.width() + 10, mTaskFragBounds.height() + 10);
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
+ clearInvocations(mAtm.mRootWindowContainer);
+
+ // Shrink the TaskFragment to mTaskFragBounds to make its bounds smaller than activity's
+ // minimum dimensions.
+ mTransaction.setBounds(mTaskFragment.mRemoteToken.toWindowContainerToken(), mTaskFragBounds)
+ .setErrorCallbackToken(mErrorToken);
+ mWindowOrganizerController.applyTransaction(mTransaction);
+
+ assertWithMessage("setBounds must not be performed.")
+ .that(mTaskFragment.getBounds()).isEqualTo(task.getBounds());
+ }
+
/**
* Creates a {@link TaskFragment} with the {@link WindowContainerTransaction}. Calls
* {@link WindowOrganizerController#applyTransaction} to apply the transaction,
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 9957d05d0a52..20fbda428381 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -1199,6 +1199,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
@Nullable
private TaskFragmentOrganizer mOrganizer;
private IBinder mFragmentToken;
+ private Rect mBounds;
TaskFragmentBuilder(ActivityTaskManagerService service) {
mAtm = service;
@@ -1235,6 +1236,11 @@ class WindowTestsBase extends SystemServiceTestsBase {
return this;
}
+ TaskFragmentBuilder setBounds(@Nullable Rect bounds) {
+ mBounds = bounds;
+ return this;
+ }
+
TaskFragment build() {
SystemServicesTestRule.checkHoldsLock(mAtm.mGlobalLock);
@@ -1262,6 +1268,9 @@ class WindowTestsBase extends SystemServiceTestsBase {
mOrganizer.getOrganizerToken(), DEFAULT_TASK_FRAGMENT_ORGANIZER_UID,
DEFAULT_TASK_FRAGMENT_ORGANIZER_PROCESS_NAME);
}
+ if (mBounds != null && !mBounds.isEmpty()) {
+ taskFragment.setBounds(mBounds);
+ }
spyOn(taskFragment);
return taskFragment;
}